JNI/JSSE: wrap wolfSSL_set_SessionTicket_cb(), add session ticket callback to SSLEngine for detection of ticket received
parent
d245630133
commit
8449b6744e
|
@ -63,6 +63,12 @@ int NativeALPNSelectCb(WOLFSSL *ssl, const unsigned char **out,
|
|||
int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret,
|
||||
int secretSz, void* ctx);
|
||||
|
||||
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
||||
/* Session ticket callback prototype */
|
||||
int NativeSessionTicketCb(WOLFSSL *ssl, const unsigned char* ticket,
|
||||
int ticketLen, void* ctx);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CRL
|
||||
/* global object refs for CRL callback */
|
||||
static jobject g_crlCbIfaceObj;
|
||||
|
@ -5622,6 +5628,30 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTls13SecretCb
|
|||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setSessionTicketCb
|
||||
(JNIEnv* jenv, jobject jcl, jlong sslPtr)
|
||||
{
|
||||
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
||||
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
|
||||
int ret = SSL_SUCCESS;
|
||||
(void)jcl;
|
||||
|
||||
if (jenv == NULL || ssl == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Java layer handles setting and giving back user CTX */
|
||||
ret = wolfSSL_set_SessionTicket_cb(ssl, NativeSessionTicketCb, NULL);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
(void)jenv;
|
||||
(void)jcl;
|
||||
(void)sslPtr;
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_TLS13) && !defined(WOLFCRYPT_ONLY) && \
|
||||
defined(HAVE_SECRET_CALLBACK)
|
||||
|
||||
|
@ -5764,6 +5794,146 @@ int NativeTls13SecretCb(WOLFSSL *ssl, int id, const unsigned char* secret,
|
|||
|
||||
#endif /* WOLFSSL_TLS13 && !WOLFCRYPT_ONLY && HAVE_SECRET_CALLBACK */
|
||||
|
||||
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET)
|
||||
|
||||
int NativeSessionTicketCb(WOLFSSL* ssl, const unsigned char* ticket,
|
||||
int ticketLen, void* ctx)
|
||||
{
|
||||
JNIEnv* jenv; /* JNI environment */
|
||||
jclass excClass; /* WolfSSLJNIException class */
|
||||
int needsDetach = 0; /* Should we explicitly detach? */
|
||||
jint retval = 0;
|
||||
jint vmret = 0;
|
||||
|
||||
jobject* g_cachedSSLObj; /* WolfSSLSession cached object */
|
||||
jclass sslClass; /* WolfSSLSession class */
|
||||
jmethodID sessTicketCbMethodId; /* internalTls13SecretCallback ID */
|
||||
jbyteArray ticketArr = NULL;
|
||||
|
||||
if (g_vm == NULL || ssl == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* get JavaEnv from JavaVM */
|
||||
vmret = (int)((*g_vm)->GetEnv(g_vm, (void**) &jenv, JNI_VERSION_1_6));
|
||||
if (vmret == JNI_EDETACHED) {
|
||||
#ifdef __ANDROID__
|
||||
vmret = (*g_vm)->AttachCurrentThread(g_vm, &jenv, NULL);
|
||||
#else
|
||||
vmret = (*g_vm)->AttachCurrentThread(g_vm, (void**) &jenv, NULL);
|
||||
#endif
|
||||
if (vmret) {
|
||||
return -1;
|
||||
}
|
||||
needsDetach = 1;
|
||||
}
|
||||
else if (vmret != JNI_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find exception class in case we need it */
|
||||
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
|
||||
if ((*jenv)->ExceptionOccurred(jenv)) {
|
||||
(*jenv)->ExceptionDescribe(jenv);
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get stored WolfSSLSession object */
|
||||
g_cachedSSLObj = (jobject*) wolfSSL_get_jobject(ssl);
|
||||
if (!g_cachedSSLObj) {
|
||||
(*jenv)->ThrowNew(jenv, excClass,
|
||||
"Can't get native WolfSSLSession object reference in "
|
||||
"NativeSessionTicketCb");
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Lookup WolfSSLSession class from object */
|
||||
sslClass = (*jenv)->GetObjectClass(jenv, (jobject)(*g_cachedSSLObj));
|
||||
if (sslClass == NULL) {
|
||||
(*jenv)->ThrowNew(jenv, excClass,
|
||||
"Can't get native WolfSSLSession class reference in "
|
||||
"NativeSessionTicketCb");
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Call internal TLS 1.3 secret callback */
|
||||
sessTicketCbMethodId = (*jenv)->GetMethodID(jenv, sslClass,
|
||||
"internalSessionTicketCallback", "(Lcom/wolfssl/WolfSSLSession;[B)I");
|
||||
if (sessTicketCbMethodId == NULL) {
|
||||
if ((*jenv)->ExceptionOccurred(jenv)) {
|
||||
(*jenv)->ExceptionDescribe(jenv);
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
}
|
||||
(*jenv)->ThrowNew(jenv, excClass,
|
||||
"Error getting internalSessionTicketCallback method from JNI");
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ticketLen > 0) {
|
||||
/* Create jbyteArray to hold session ticket */
|
||||
ticketArr = (*jenv)->NewByteArray(jenv, ticketLen);
|
||||
if (ticketArr == NULL) {
|
||||
(*jenv)->ThrowNew(jenv, excClass,
|
||||
"Error creating new jbyteArray in NativeSessionTicketCb");
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*jenv)->SetByteArrayRegion(jenv, ticketArr, 0, ticketLen,
|
||||
(jbyte*)ticket);
|
||||
if ((*jenv)->ExceptionOccurred(jenv)) {
|
||||
(*jenv)->ExceptionDescribe(jenv);
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Call Java session ticket callback, ignore native CTX since Java
|
||||
* handles it */
|
||||
retval = (*jenv)->CallIntMethod(jenv, (jobject)(*g_cachedSSLObj),
|
||||
sessTicketCbMethodId, (jobject)(*g_cachedSSLObj), ticketArr);
|
||||
if ((*jenv)->ExceptionOccurred(jenv)) {
|
||||
(*jenv)->ExceptionDescribe(jenv);
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
(*jenv)->ThrowNew(jenv, excClass,
|
||||
"Exception while calling internalSessionTicketCallback()");
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Delete local refs */
|
||||
(*jenv)->DeleteLocalRef(jenv, ticketArr);
|
||||
}
|
||||
|
||||
/* Detach JNIEnv from thread */
|
||||
if (needsDetach) {
|
||||
(*g_vm)->DetachCurrentThread(g_vm);
|
||||
}
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_TLS13 && !WOLFCRYPT_ONLY && HAVE_SECRET_CALLBACK */
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_useSecureRenegotiation
|
||||
(JNIEnv* jenv, jobject jcl, jlong ssl)
|
||||
{
|
||||
|
|
|
@ -863,6 +863,14 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setALPNSelectCb
|
|||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setTls13SecretCb
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: com_wolfssl_WolfSSLSession
|
||||
* Method: setSessionTicketCb
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLSession_setSessionTicketCb
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: com_wolfssl_WolfSSLSession
|
||||
* Method: keepArrays
|
||||
|
|
|
@ -61,6 +61,7 @@ infer --fail-on-issue run -- javac \
|
|||
src/java/com/wolfssl/WolfSSLRsaSignCallback.java \
|
||||
src/java/com/wolfssl/WolfSSLRsaVerifyCallback.java \
|
||||
src/java/com/wolfssl/WolfSSLSession.java \
|
||||
src/java/com/wolfssl/WolfSSLSessionTicketCallback.java \
|
||||
src/java/com/wolfssl/WolfSSLTls13SecretCallback.java \
|
||||
src/java/com/wolfssl/WolfSSLVerifyCallback.java \
|
||||
src/java/com/wolfssl/WolfSSLVerifyDecryptCallback.java \
|
||||
|
|
|
@ -62,6 +62,7 @@ public class WolfSSLSession {
|
|||
private Object rsaDecCtx;
|
||||
private Object alpnSelectArg;
|
||||
private Object tls13SecretCtx;
|
||||
private Object sessionTicketCtx;
|
||||
|
||||
/* reference to the associated WolfSSLContext */
|
||||
private WolfSSLContext ctx = null;
|
||||
|
@ -80,10 +81,14 @@ public class WolfSSLSession {
|
|||
* ALPN select callback */
|
||||
private WolfSSLALPNSelectCallback internAlpnSelectCb;
|
||||
|
||||
/* user-registered TLS 1.3 secret callbcak, called by internal
|
||||
/* user-registered TLS 1.3 secret callback, called by internal
|
||||
* WolfSSLSession TLS 1.3 secret callback */
|
||||
private WolfSSLTls13SecretCallback internTls13SecretCb;
|
||||
|
||||
/* user-registered session ticket callback, called by internal
|
||||
* WolfSSLSession session ticket callback */
|
||||
private WolfSSLSessionTicketCallback internSessionTicketCb;
|
||||
|
||||
/* have session tickets been enabled for this session? Default to false. */
|
||||
private boolean sessionTicketsEnabled = false;
|
||||
|
||||
|
@ -282,6 +287,13 @@ public class WolfSSLSession {
|
|||
this.tls13SecretCtx);
|
||||
}
|
||||
|
||||
private int internalSessionTicketCallback(WolfSSLSession ssl, byte[] ticket)
|
||||
{
|
||||
/* call user-registered session ticket callback */
|
||||
return internSessionTicketCb.sessionTicketCallback(ssl, ticket,
|
||||
this.sessionTicketCtx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the current WolfSSLSession object is active.
|
||||
*
|
||||
|
@ -415,6 +427,7 @@ public class WolfSSLSession {
|
|||
private native int useALPN(long ssl, String protocols, int options);
|
||||
private native int setALPNSelectCb(long ssl);
|
||||
private native int setTls13SecretCb(long ssl);
|
||||
private native int setSessionTicketCb(long ssl);
|
||||
private native void keepArrays(long ssl);
|
||||
private native byte[] getClientRandom(long ssl);
|
||||
private native int useSecureRenegotiation(long ssl);
|
||||
|
@ -4819,6 +4832,47 @@ public class WolfSSLSession {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register session ticket callback.
|
||||
*
|
||||
* The callback registered by this method is called by native wolfSSL
|
||||
* when a session ticket is received from the peer.
|
||||
*
|
||||
* @param cb callback to be registered with this SSL session
|
||||
* @param ctx Object that will be passed back to user inside callback
|
||||
*
|
||||
* @return <code>SSL_SUCCESS</code> on success. <code>
|
||||
* NOT_COMPILED_IN</code> if wolfSSL was not compiled with
|
||||
* session ticket support, and other negative value on error.
|
||||
*
|
||||
* @throws IllegalStateException WolfSSLSession has been freed
|
||||
* @throws WolfSSLJNIException Internal JNI error
|
||||
*/
|
||||
public int setSessionTicketCb(WolfSSLSessionTicketCallback cb, Object ctx)
|
||||
throws IllegalStateException, WolfSSLJNIException {
|
||||
|
||||
int ret = 0;
|
||||
|
||||
confirmObjectIsActive();
|
||||
|
||||
synchronized (sslLock) {
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
|
||||
WolfSSLDebug.INFO, this.sslPtr, "entered setSessionTicketCb(" +
|
||||
cb + ", ctx: " + ctx + ")");
|
||||
|
||||
ret = setSessionTicketCb(this.sslPtr);
|
||||
if (ret == WolfSSL.SSL_SUCCESS) {
|
||||
/* Set session ticket callback */
|
||||
internSessionTicketCb = cb;
|
||||
|
||||
/* Set session ticket ctx Object, returned to user in cb */
|
||||
this.sessionTicketCtx = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not free temporary arrays at end of handshake.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* WolfSSLSessionTicketCallback.java
|
||||
*
|
||||
* Copyright (C) 2006-2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
package com.wolfssl;
|
||||
|
||||
/**
|
||||
* wolfSSL session ticket callback interface.
|
||||
* This interface specifies how applications should implement the session
|
||||
* ticket callback class, to be used by wolfSSL when receiving a session
|
||||
* ticket message.
|
||||
* <p>
|
||||
* To use this interface, native wolfSSL must be compiled with
|
||||
* HAVE_SESSION_TICKET defined.
|
||||
* </p>
|
||||
* After implementing this interface, it should be passed as a parameter
|
||||
* to the
|
||||
* {@link WolfSSLSession#setSessionTicketCb(WolfSSLSessionTicketCallback, Object)
|
||||
* WolfSSLSession.setSessionTicketCb()} method to be registered with the native
|
||||
* wolfSSL library.
|
||||
*/
|
||||
public interface WolfSSLSessionTicketCallback {
|
||||
|
||||
/**
|
||||
* Callback method which is called when native wolfSSL receives a
|
||||
* session ticket message.
|
||||
*
|
||||
* @param ssl the current SSL session object from which the
|
||||
* callback was initiated
|
||||
* @param ticket Session ticket received as a byte array
|
||||
* @param ctx Optional user context if set when callback was
|
||||
* registered
|
||||
*
|
||||
* @return 0 on success. wolfSSL does not currently do anything with
|
||||
* the return value of this method, but is in place for
|
||||
* future expansion if needed.
|
||||
*/
|
||||
public int sessionTicketCallback(WolfSSLSession ssl, byte[] ticket,
|
||||
Object ctx);
|
||||
}
|
||||
|
||||
|
|
@ -29,6 +29,7 @@ import com.wolfssl.WolfSSLIOSendCallback;
|
|||
import com.wolfssl.WolfSSLJNIException;
|
||||
import com.wolfssl.WolfSSLSession;
|
||||
import com.wolfssl.WolfSSLALPNSelectCallback;
|
||||
import com.wolfssl.WolfSSLSessionTicketCallback;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
|
@ -111,11 +112,16 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
/* TLS 1.3 session ticket received (on client side) */
|
||||
private boolean sessionTicketReceived = false;
|
||||
|
||||
/* Number of session tickets received, incremented in
|
||||
* SessionTicketCB callback */
|
||||
private int sessionTicketCount = 0;
|
||||
|
||||
/* client/server mode has been set */
|
||||
private boolean clientModeSet = false;
|
||||
|
||||
private SendCB sendCb = null;
|
||||
private RecvCB recvCb = null;
|
||||
private SessionTicketCB sessTicketCb = null;
|
||||
|
||||
private ByteBuffer netData = null;
|
||||
private final Object netDataLock = new Object();
|
||||
|
@ -306,6 +312,12 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
ssl.setIOSend(sendCb);
|
||||
ssl.setIOReadCtx(this);
|
||||
ssl.setIOWriteCtx(this);
|
||||
|
||||
/* Session ticket callback */
|
||||
if (sessTicketCb == null) {
|
||||
sessTicketCb = new SessionTicketCB();
|
||||
}
|
||||
ssl.setSessionTicketCb(sessTicketCb, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,6 +350,9 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
if (recvCb == null) {
|
||||
recvCb = new RecvCB();
|
||||
}
|
||||
if (sessTicketCb == null) {
|
||||
sessTicketCb = new SessionTicketCB();
|
||||
}
|
||||
|
||||
/* will throw WolfSSLException if issue creating WOLFSSL */
|
||||
ssl = new WolfSSLSession(ctx, false);
|
||||
|
@ -1022,6 +1037,7 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
int produced = 0;
|
||||
long dtlsPrevDropCount = 0;
|
||||
long dtlsCurrDropCount = 0;
|
||||
int prevSessionTicketCount = 0;
|
||||
byte[] tmp;
|
||||
|
||||
/* Set initial status for SSLEngineResult return */
|
||||
|
@ -1149,11 +1165,13 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
}
|
||||
}
|
||||
else {
|
||||
/* Get previous DTLS drop count, before we process any
|
||||
* incomming data. Allows us to set BUFFER_UNDERFLOW status
|
||||
* (or not if packet decrypt failed and was dropped) */
|
||||
/* Get previous DTLS drop count and session ticket count,
|
||||
* before we process any incomming data. Allows us to set
|
||||
* BUFFER_UNDERFLOW status (or not if packet decrypt failed
|
||||
* and was dropped) */
|
||||
synchronized (ioLock) {
|
||||
dtlsPrevDropCount = ssl.getDtlsMacDropCount();
|
||||
prevSessionTicketCount = this.sessionTicketCount;
|
||||
}
|
||||
|
||||
if (this.handshakeFinished == false) {
|
||||
|
@ -1284,12 +1302,17 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
dtlsCurrDropCount = ssl.getDtlsMacDropCount();
|
||||
}
|
||||
|
||||
/* Detect if we need to set BUFFER_UNDERFLOW */
|
||||
/* Detect if we need to set BUFFER_UNDERFLOW.
|
||||
* If we consume data in unwrap() but it's just a session
|
||||
* ticket, we don't set BUFFER_UNDERFLOW and just continue
|
||||
* on to set status as OK. */
|
||||
synchronized (toSendLock) {
|
||||
synchronized (netDataLock) {
|
||||
if (ret <= 0 && err == WolfSSL.SSL_ERROR_WANT_READ &&
|
||||
in.remaining() == 0 && (this.toSend == null ||
|
||||
(this.toSend != null && this.toSend.length == 0))) {
|
||||
(this.toSend != null && this.toSend.length == 0))
|
||||
&& (prevSessionTicketCount ==
|
||||
this.sessionTicketCount)) {
|
||||
|
||||
if ((this.ssl.dtls() == 0) ||
|
||||
(this.handshakeFinished &&
|
||||
|
@ -2154,6 +2177,32 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal session ticket callback. Called when native wolfSSL
|
||||
* receives a session ticket from peer.
|
||||
*
|
||||
* @param ticket byte array containing session ticket data
|
||||
*
|
||||
* @return 0 on success, negative value on error
|
||||
*/
|
||||
protected synchronized int internalSessionTicketCb(byte[] ticket) {
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"entered internalSessionTicketCb()");
|
||||
|
||||
if (ticket != null) {
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"Session ticket received, length = " + ticket.length);
|
||||
if (ticket.length > 0) {
|
||||
this.sessionTicketCount++;
|
||||
}
|
||||
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
|
||||
"Total session tickets received by this SSLEngine: " +
|
||||
this.sessionTicketCount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private class SendCB implements WolfSSLIOSendCallback {
|
||||
|
||||
protected SendCB() {
|
||||
|
@ -2180,6 +2229,17 @@ public class WolfSSLEngine extends SSLEngine {
|
|||
|
||||
}
|
||||
|
||||
private class SessionTicketCB implements WolfSSLSessionTicketCallback {
|
||||
|
||||
protected SessionTicketCB() {
|
||||
}
|
||||
|
||||
public int sessionTicketCallback(WolfSSLSession ssl, byte[] ticket,
|
||||
Object engine) {
|
||||
return ((WolfSSLEngine)engine).internalSessionTicketCb(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected synchronized void finalize() throws Throwable {
|
||||
|
|
Loading…
Reference in New Issue