int ssl_callback_ServerNameIndication()

in native/src/sslcontext.c [90:132]


int ssl_callback_ServerNameIndication(SSL *ssl, int *al, tcn_ssl_ctxt_t *c)
{
    /* TODO: Is it better to cache the JNIEnv* during the call to handshake? */

    /* Get the JNI environment for this callback */
    JavaVM *javavm = tcn_get_java_vm();
    JNIEnv *env;
    const char *servername;
    jstring hostname;
    jlong original_ssl_context, new_ssl_context;
    tcn_ssl_ctxt_t *new_c;

    // Continue only if the static method exists
    if (sni_java_callback == NULL) {
        return SSL_TLSEXT_ERR_OK;
    }

    (*javavm)->AttachCurrentThread(javavm, (void **)&env, NULL);

    // Get the host name presented by the client
    servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);

    // Convert to Java compatible parameters ready for the method call
    hostname = (*env)->NewStringUTF(env, servername);
    original_ssl_context = P2J(c);

    new_ssl_context = (*env)->CallStaticLongMethod(env,
                                                   ssl_context_class,
                                                   sni_java_callback,
                                                   original_ssl_context,
                                                   hostname);

    // Delete the local reference as this method is called via callback.
    // Otherwise local references are only freed once jni method returns.
    (*env)->DeleteLocalRef(env, hostname);

    if (new_ssl_context != 0 && new_ssl_context != original_ssl_context) {
        new_c = J2P(new_ssl_context, tcn_ssl_ctxt_t *);
        SSL_set_SSL_CTX(ssl, new_c->ctx);
    }

    return SSL_TLSEXT_ERR_OK;
}