From 3e87aa16c9bfc7b14b71ce85dfb714a573d6235a Mon Sep 17 00:00:00 2001 From: wkgcass Date: Thu, 24 Dec 2020 00:03:43 +0800 Subject: [PATCH] add jni related functions to msquic --- src/bin/linux/exports.txt | 2 +- src/core/library.c | 54 +++++++++++++++++++++++++++++++++++ src/inc/msquic.h | 29 +++++++++++++++++++ src/manifest/clog.sidecar | 36 +++++++++++++++++++++++ src/platform/platform_linux.c | 54 ++++++++++++++++++++++++++++++++++- 5 files changed, 173 insertions(+), 2 deletions(-) diff --git a/src/bin/linux/exports.txt b/src/bin/linux/exports.txt index f81ae03a..d7f7471e 100644 --- a/src/bin/linux/exports.txt +++ b/src/bin/linux/exports.txt @@ -1,5 +1,5 @@ msquic { - global: MsQuicOpen; MsQuicClose; + global: MsQuicOpen; MsQuicClose; MsQuicJavaInit; MsQuicGetJNIEnv; local: *; }; diff --git a/src/core/library.c b/src/core/library.c index 320494b0..cafd1d80 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -1099,6 +1099,60 @@ QuicLibraryGetParam( return Status; } +// actual variables are defined in platform_linux.c +// because the tools will use the platform lib without the core lib +extern pthread_key_t ThreadLocalJNIEnvKey; +extern void* GlobalJvm; // JavaVM* +extern void* (* AttachThreadFunc)(void*); // JavaVM* => JNIEnv* +extern void (* DetachThreadFunc)(void*); // JavaVM* => void + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +QUIC_API +MsQuicJavaInit( + _In_ void* Jvm, // JavaVM* + _In_ ATTACH_THREAD_FUNC AttachThreadFuncLocal, + _In_ DETACH_THREAD_FUNC DetachThreadFuncLocal + ) +{ + int err = pthread_key_create(&ThreadLocalJNIEnvKey, NULL); + if (err < 0) { + QuicTraceEvent( + JavaError, + "[java] Error: %u %s.", + errno, + "create pthread_key failed"); + } + GlobalJvm = Jvm; + AttachThreadFunc = AttachThreadFuncLocal; + DetachThreadFunc = DetachThreadFuncLocal; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +QUIC_STATUS +QUIC_API +MsQuicGetJNIEnv( + _Out_ void** OutEnv // &JNIEnv* + ) +{ + void* env = pthread_getspecific(ThreadLocalJNIEnvKey); + if (env == NULL) { + if (GlobalJvm == NULL) { + QuicTraceEvent( + SimpleJavaError, + "[java] Error: %s.", + "GlobalJvm not set"); + } + QuicTraceEvent( + SimpleJavaError, + "[java] Error: %s.", + "ThreadLocalJNIEnv not set"); + return QUIC_STATUS_INTERNAL_ERROR; + } + *OutEnv = env; + return QUIC_STATUS_SUCCESS; +} + _IRQL_requires_max_(PASSIVE_LEVEL) QUIC_STATUS QUIC_API diff --git a/src/inc/msquic.h b/src/inc/msquic.h index 588dd398..40a4ca91 100644 --- a/src/inc/msquic.h +++ b/src/inc/msquic.h @@ -1154,6 +1154,35 @@ MsQuicClose( _In_ _Pre_defensive_ const QUIC_API_TABLE* QuicApi ); +// +// JVM +// + +typedef void* (* ATTACH_THREAD_FUNC)(void*); // JavaVM* => JNIEnv* +typedef void (* DETACH_THREAD_FUNC)(void*); // JavaVM* => void + +// +// Initiating Java environment +// +_IRQL_requires_max_(PASSIVE_LEVEL) +void +QUIC_API +MsQuicJavaInit( + _In_ void* Jvm, // JavaVM* + _In_ ATTACH_THREAD_FUNC AttachThreadFunc, + _In_ DETACH_THREAD_FUNC DetachThreadFunc + ); + +// +// Retrieving the JNIEnv* for the current thread +// +_IRQL_requires_max_(PASSIVE_LEVEL) +QUIC_STATUS +QUIC_API +MsQuicGetJNIEnv( + _Out_ void** OutEnv // &JNIEnv* + ); + #if defined(__cplusplus) } #endif diff --git a/src/manifest/clog.sidecar b/src/manifest/clog.sidecar index e04a72fc..85d84d89 100644 --- a/src/manifest/clog.sidecar +++ b/src/manifest/clog.sidecar @@ -9525,6 +9525,34 @@ } ], "macroName": "QuicTraceLogInfo" + }, + "JavaError": { + "ModuleProperites": {}, + "TraceString": "[java] Error: %u %s.", + "UniqueId": "JavaError", + "splitArgs": [ + { + "DefinationEncoding": "u", + "MacroVariableName": "arg2" + }, + { + "DefinationEncoding": "s", + "MacroVariableName": "arg3" + } + ], + "macroName": "QuicTraceEvent" + }, + "SimpleJavaError": { + "ModuleProperites": {}, + "TraceString": "[java] Error: %s.", + "UniqueId": "SimpleJavaError", + "splitArgs": [ + { + "DefinationEncoding": "s", + "MacroVariableName": "arg2" + } + ], + "macroName": "QuicTraceEvent" } }, "Version": 1, @@ -12374,6 +12402,14 @@ { "UniquenessHash": "7368812e-a46d-0924-7643-009511288886", "TraceID": "InteropTestStop" + }, + { + "UniquenessHash": "7ca9a627-ea0b-4a7a-76b5-02bd899e607a", + "TraceID": "JavaError" + }, + { + "UniquenessHash": "6f7ab853-c29e-8843-88f2-56a8aff0aeab", + "TraceID": "SimpleJavaError" } ] } diff --git a/src/platform/platform_linux.c b/src/platform/platform_linux.c index b0031c12..68925921 100644 --- a/src/platform/platform_linux.c +++ b/src/platform/platform_linux.c @@ -687,6 +687,55 @@ QuicConvertFromMappedV6( } } +// actual variables here because the tools will use the platform lib without the core lib +pthread_key_t ThreadLocalJNIEnvKey; +void* GlobalJvm = NULL; // JavaVM* +void* (* AttachThreadFunc)(void*); // JavaVM* => JNIEnv* +void (* DetachThreadFunc)(void*); // JavaVM* => void + +typedef struct st_quic_thread_create_ctx { + void* Context; + LPTHREAD_START_ROUTINE Callback; +} quic_thread_create_ctx_t; + +void* quic_thread_runnable(void* data) { + quic_thread_create_ctx_t* ctx = data; + void* Context = ctx->Context; + LPTHREAD_START_ROUTINE Callback = ctx->Callback; + free(ctx); + + if (GlobalJvm == NULL) { + QuicTraceEvent( + SimpleJavaError, + "[java] Error: %s.", + "GlobalJvm not set"); + goto quic_thread_runnable_err; + } + void* env = AttachThreadFunc(GlobalJvm); + if (env == NULL) { + QuicTraceEvent( + SimpleJavaError, + "[java] Error: %s.", + "attaching thread failed"); + goto quic_thread_runnable_err; + } + int err = pthread_setspecific(ThreadLocalJNIEnvKey, env); + if (err < 0) { + QuicTraceEvent( + JavaError, + "[java] Error: %u %s.", + errno, + "setting jni env to thread local failed"); + DetachThreadFunc(GlobalJvm); + goto quic_thread_runnable_err; + } + void* ret = Callback(Context); + DetachThreadFunc(GlobalJvm); + return ret; +quic_thread_runnable_err: + return Callback(Context); +} + QUIC_STATUS QuicThreadCreate( _In_ QUIC_THREAD_CONFIG* Config, @@ -734,7 +783,10 @@ QuicThreadCreate( } } - if (pthread_create(Thread, &Attr, Config->Callback, Config->Context)) { + quic_thread_create_ctx_t* quic_thread_create_ctx = malloc(sizeof(quic_thread_create_ctx_t)); + quic_thread_create_ctx->Callback = Config->Callback; + quic_thread_create_ctx->Context = Config->Context; + if (pthread_create(Thread, &Attr, quic_thread_runnable, quic_thread_create_ctx)) { Status = errno; QuicTraceEvent( LibraryErrorStatus,