refactor: [3/n] Use userdata member in euicc_ctx

This commit is contained in:
Peter Cai 2023-11-18 18:42:59 -05:00
parent 013fe157eb
commit 2707a5f1f8
7 changed files with 45 additions and 74 deletions

View file

@ -2,5 +2,6 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/libs/lpac-jni/src/main/jni/lpac" vcs="Git" />
</component> </component>
</project> </project>

View file

@ -7,5 +7,4 @@ private object LpacJni {
external fun createContext(apduInterface: ApduInterface, httpInterface: HttpInterface): Long external fun createContext(apduInterface: ApduInterface, httpInterface: HttpInterface): Long
external fun destroyContext(handle: Long) external fun destroyContext(handle: Long)
external fun setCurrentContext(handle: Long)
} }

@ -1 +1 @@
Subproject commit 2eaefa6f8d79f68eff6a8c03932b861425767330 Subproject commit c29f1d40f131d955b4867e230da5539ea7cc6149

View file

@ -1,7 +1,6 @@
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include "interface-wrapper.h" #include "interface-wrapper.h"
#include "lpac-jni.h"
jmethodID method_apdu_connect; jmethodID method_apdu_connect;
jmethodID method_apdu_disconnect; jmethodID method_apdu_disconnect;
@ -32,86 +31,73 @@ void interface_wrapper_init() {
field_resp_data = (*env)->GetFieldID(env, resp_class, "data", "[B"); field_resp_data = (*env)->GetFieldID(env, resp_class, "data", "[B");
} }
static int apdu_interface_connect(void) { static int apdu_interface_connect(struct euicc_ctx *ctx) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_connect); (*env)->CallVoidMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface, method_apdu_connect);
LPAC_JNI_END(!((*env)->ExceptionCheck(env) == JNI_FALSE)); return (*env)->ExceptionCheck(env) != JNI_FALSE;
} }
static void apdu_interface_disconnect(void) { static void apdu_interface_disconnect(struct euicc_ctx *ctx) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_disconnect); (*env)->CallVoidMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface, method_apdu_disconnect);
LPAC_JNI_END0;
} }
static int apdu_interface_logical_channel_open(const uint8_t *aid, uint8_t aid_len) { static int apdu_interface_logical_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
jbyteArray jbarr = (*env)->NewByteArray(env, aid_len); jbyteArray jbarr = (*env)->NewByteArray(env, aid_len);
(*env)->SetByteArrayRegion(env, jbarr, 0, aid_len, (const jbyte *) aid); (*env)->SetByteArrayRegion(env, jbarr, 0, aid_len, (const jbyte *) aid);
jint ret = (*env)->CallIntMethod(env, jni_ctx->apdu_interface, method_apdu_logical_channel_open, jbarr); jint ret = (*env)->CallIntMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface, method_apdu_logical_channel_open, jbarr);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) { if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
LPAC_JNI_END(-1); return -1;
} else { } else {
LPAC_JNI_END(ret); return ret;
} }
} }
static void apdu_interface_logical_channel_close(uint8_t channel) { static void apdu_interface_logical_channel_close(struct euicc_ctx *ctx, uint8_t channel) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
(*env)->CallVoidMethod(env, jni_ctx->apdu_interface, method_apdu_logical_channel_close, channel); (*env)->CallVoidMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface, method_apdu_logical_channel_close, channel);
LPAC_JNI_END0;
} }
static int apdu_interface_transmit(uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) { static int apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
jbyteArray txArr = (*env)->NewByteArray(env, tx_len); jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx); (*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
jbyteArray ret = (jbyteArray) (*env)->CallObjectMethod(env, jni_ctx->apdu_interface, method_apdu_transmit, txArr); jbyteArray ret = (jbyteArray) (*env)->CallObjectMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface, method_apdu_transmit, txArr);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) { if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
LPAC_JNI_END(-1); return -1;
} }
*rx_len = (*env)->GetArrayLength(env, ret); *rx_len = (*env)->GetArrayLength(env, ret);
*rx = malloc(*rx_len * sizeof(uint8_t)); *rx = malloc(*rx_len * sizeof(uint8_t));
(*env)->GetByteArrayRegion(env, ret, 0, *rx_len, *rx); (*env)->GetByteArrayRegion(env, ret, 0, *rx_len, *rx);
LPAC_JNI_END(0); return 0;
} }
static int http_interface_transmit(const char *url, uint32_t *rcode, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) { static int http_interface_transmit(struct euicc_ctx *ctx, const char *url, uint32_t *rcode, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) {
LPAC_JNI_BEGIN;
LPAC_JNI_ASSERT_CTX;
LPAC_JNI_SETUP_ENV; LPAC_JNI_SETUP_ENV;
jstring jurl = (*env)->NewString(env, url, strlen(url)); jstring jurl = (*env)->NewString(env, url, strlen(url));
jbyteArray txArr = (*env)->NewByteArray(env, tx_len); jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx); (*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
jobject ret = (*env)->CallObjectMethod(env, jni_ctx->http_interface, method_http_transmit, jurl, txArr); jobject ret = (*env)->CallObjectMethod(env, LPAC_JNI_CTX(ctx)->http_interface, method_http_transmit, jurl, txArr);
if ((*env)->ExceptionCheck(env) == JNI_TRUE) { if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
LPAC_JNI_END(-1); return -1;
} }
*rcode = (*env)->GetIntField(env, ret, field_resp_rcode); *rcode = (*env)->GetIntField(env, ret, field_resp_rcode);
jbyteArray rxArr = (jbyteArray) (*env)->GetObjectField(env, ret, field_resp_data); jbyteArray rxArr = (jbyteArray) (*env)->GetObjectField(env, ret, field_resp_data);
*rx_len = (*env)->GetArrayLength(env, rxArr); *rx_len = (*env)->GetArrayLength(env, rxArr);
*rx = malloc(*rx_len * sizeof(uint8_t)); *rx = malloc(*rx_len * sizeof(uint8_t));
(*env)->GetByteArrayRegion(env, rxArr, 0, *rx_len, *rx); (*env)->GetByteArrayRegion(env, rxArr, 0, *rx_len, *rx);
LPAC_JNI_END(0); return 0;
} }
struct euicc_apdu_interface apdu_interface_wrapper = { struct euicc_apdu_interface lpac_jni_apdu_interface = {
.connect = apdu_interface_connect, .connect = &apdu_interface_connect,
.disconnect = apdu_interface_disconnect, .disconnect = &apdu_interface_disconnect,
.logic_channel_open = apdu_interface_logical_channel_open, .logic_channel_open = &apdu_interface_logical_channel_open,
.logic_channel_close = apdu_interface_logical_channel_close, .logic_channel_close = &apdu_interface_logical_channel_close,
.transmit = apdu_interface_transmit .transmit = &apdu_interface_transmit
}; };
struct euicc_http_interface http_interface_wrapper = {
.transmit = http_interface_transmit struct euicc_http_interface lpac_jni_http_interface = {
.transmit = &http_interface_transmit
}; };

View file

@ -2,13 +2,13 @@
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
#include <euicc/interface.h> #include <euicc/interface.h>
#include "lpac-jni.h"
extern struct euicc_apdu_interface apdu_interface_wrapper;
extern struct euicc_http_interface http_interface_wrapper;
void interface_wrapper_init(); void interface_wrapper_init();
#define LPAC_JNI_ASSERT_CTX assert(jni_ctx != NULL) extern struct euicc_apdu_interface lpac_jni_apdu_interface;
extern struct euicc_http_interface lpac_jni_http_interface;
#define LPAC_JNI_SETUP_ENV \ #define LPAC_JNI_SETUP_ENV \
JNIEnv *env; \ JNIEnv *env; \
(*jvm)->AttachCurrentThread(jvm, &env, NULL) (*jvm)->AttachCurrentThread(jvm, &env, NULL)

View file

@ -4,8 +4,6 @@
#include "lpac-jni.h" #include "lpac-jni.h"
#include "interface-wrapper.h" #include "interface-wrapper.h"
pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
struct lpac_jni_ctx *jni_ctx = NULL;
JavaVM *jvm = NULL; JavaVM *jvm = NULL;
jint JNI_OnLoad(JavaVM *vm, void *reserved) { jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@ -18,32 +16,24 @@ JNIEXPORT jlong JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_createContext(JNIEnv *env, jobject thiz, Java_net_typeblog_lpac_1jni_LpacJni_createContext(JNIEnv *env, jobject thiz,
jobject apdu_interface, jobject apdu_interface,
jobject http_interface) { jobject http_interface) {
LPAC_JNI_BEGIN; struct euicc_ctx *ctx = malloc(sizeof(struct euicc_ctx));
struct lpac_jni_ctx *_ctx = malloc(sizeof(struct lpac_jni_ctx)); struct lpac_jni_ctx *_ctx = malloc(sizeof(struct lpac_jni_ctx));
memset(ctx, 0, sizeof(struct lpac_jni_ctx));
memset(_ctx, 0, sizeof(struct lpac_jni_ctx)); memset(_ctx, 0, sizeof(struct lpac_jni_ctx));
_ctx->ctx.interface.apdu = &apdu_interface_wrapper; ctx->interface.apdu = &lpac_jni_apdu_interface;
_ctx->ctx.interface.http = &http_interface_wrapper; ctx->interface.http = &lpac_jni_apdu_interface;
_ctx->apdu_interface = (*env)->NewGlobalRef(env, apdu_interface); _ctx->apdu_interface = (*env)->NewGlobalRef(env, apdu_interface);
_ctx->http_interface = (*env)->NewGlobalRef(env, http_interface); _ctx->http_interface = (*env)->NewGlobalRef(env, http_interface);
LPAC_JNI_END((jlong) _ctx); ctx->userdata = (void *) _ctx;
return (jlong) ctx;
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_destroyContext(JNIEnv *env, jobject thiz, jlong handle) { Java_net_typeblog_lpac_1jni_LpacJni_destroyContext(JNIEnv *env, jobject thiz, jlong handle) {
LPAC_JNI_BEGIN; struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
struct lpac_jni_ctx *_ctx = (struct lpac_jni_ctx *) handle; struct lpac_jni_ctx *_ctx = LPAC_JNI_CTX(ctx);
(*env)->DeleteGlobalRef(env, _ctx->apdu_interface); (*env)->DeleteGlobalRef(env, _ctx->apdu_interface);
(*env)->DeleteGlobalRef(env, _ctx->http_interface); (*env)->DeleteGlobalRef(env, _ctx->http_interface);
if (jni_ctx == _ctx) {
jni_ctx = NULL;
}
free(_ctx); free(_ctx);
LPAC_JNI_END0; free(ctx);
}
JNIEXPORT void JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_setCurrentContext(JNIEnv *env, jobject thiz, jlong handle) {
LPAC_JNI_BEGIN;
jni_ctx = (struct lpac_jni_ctx *) handle;
LPAC_JNI_END0;
} }

View file

@ -4,15 +4,10 @@
#include <jni.h> #include <jni.h>
struct lpac_jni_ctx { struct lpac_jni_ctx {
struct euicc_ctx ctx;
jobject apdu_interface; jobject apdu_interface;
jobject http_interface; jobject http_interface;
}; };
extern JavaVM *jvm; #define LPAC_JNI_CTX(ctx) ((struct lpac_jni_ctx *) ctx->userdata)
extern pthread_mutex_t global_lock;
extern struct lpac_jni_ctx *jni_ctx;
#define LPAC_JNI_BEGIN pthread_mutex_lock(&global_lock) extern JavaVM *jvm;
#define LPAC_JNI_END0 pthread_mutex_unlock(&global_lock)
#define LPAC_JNI_END(ret) LPAC_JNI_END0; return ret