Added ZTS_ERR_GENERAL, also minor updates to JNI layer

This commit is contained in:
Joseph Henry
2019-03-18 14:23:34 -07:00
parent c91eba4fc6
commit 3cbc1017eb
3 changed files with 77 additions and 73 deletions

View File

@@ -44,6 +44,8 @@
#define ZTS_ERR_INVALID_OP -3 #define ZTS_ERR_INVALID_OP -3
// The call succeeded, but no object or relevant result was available // The call succeeded, but no object or relevant result was available
#define ZTS_ERR_NO_RESULT -4 #define ZTS_ERR_NO_RESULT -4
// General internal failure
#define ZTS_ERR_GENERAL -5
/** /**
* The system port upon which ZT traffic is sent and received * The system port upon which ZT traffic is sent and received

View File

@@ -75,21 +75,15 @@ int _port;
std::string _path; std::string _path;
/* /*
* A lock used to protect any call which relies on the presence of a valid pointer * A lock used to protect any call which relies on the presence of a valid
* to the ZeroTier service. * pointer to the ZeroTier service.
*/ */
Mutex _service_lock; Mutex _service_lock;
/* /*
* A lock which protects flags and state variables used during the startup and * A lock used to protect callback method pointers. With a coarser-grained
* shutdown phase. * lock it would be possible for one thread to alter the callback method
*/ * pointer causing undefined behaviour.
Mutex _startup_lock;
/*
* A lock used to protect callback method pointers. With a coarser-grained lock it
* would be possible for one thread to alter the callback method pointer causing
* undefined behaviour.
*/ */
Mutex _callback_lock; Mutex _callback_lock;
@@ -425,13 +419,14 @@ extern "C" {
#ifdef SDK_JNI #ifdef SDK_JNI
/* /*
* Called from Java, saves a static reference to the VM so it can be used later to call * Called from Java, saves a static reference to the VM so it can be used
* a user-specified callback method from C. * later to call a user-specified callback method from C.
*/ */
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_init(JNIEnv *env, jobject thisObj) JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_init(
JNIEnv *env, jobject thisObj)
{ {
jint rs = env->GetJavaVM(&jvm); jint rs = env->GetJavaVM(&jvm);
assert (rs == JNI_OK); return rs != JNI_OK ? ZTS_ERR_GENERAL : ZTS_ERR_OK;
} }
#endif #endif
@@ -515,7 +510,8 @@ int zts_deorbit(uint64_t moonWorldId)
#ifdef SDK_JNI #ifdef SDK_JNI
#endif #endif
int zts_start(const char *path, void (*callback)(struct zts_callback_msg*), int port) int zts_start(
const char *path, void (*callback)(struct zts_callback_msg*), int port)
{ {
Mutex::Lock _l(_service_lock); Mutex::Lock _l(_service_lock);
lwip_driver_init(); lwip_driver_init();
@@ -524,7 +520,8 @@ int zts_start(const char *path, void (*callback)(struct zts_callback_msg*), int
return ZTS_ERR_INVALID_OP; return ZTS_ERR_INVALID_OP;
} }
if (_freeHasBeenCalled) { if (_freeHasBeenCalled) {
// Stack (presumably lwIP) has been dismantled, an application restart is required now // Stack (presumably lwIP) has been dismantled,
// an application restart is required now
return ZTS_ERR_INVALID_OP; return ZTS_ERR_INVALID_OP;
} }
#ifdef SDK_JNI #ifdef SDK_JNI
@@ -607,10 +604,15 @@ JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_start(
DEBUG_ERROR("Couldn't find onZeroTierEvent method"); DEBUG_ERROR("Couldn't find onZeroTierEvent method");
return ZTS_ERR_INVALID_ARG; return ZTS_ERR_INVALID_ARG;
} }
objRef = env->NewGlobalRef(callback); // Reference used for later calls // Reference used for later calls
objRef = env->NewGlobalRef(callback);
_userCallbackMethodRef = eventListenerCallbackMethod; _userCallbackMethodRef = eventListenerCallbackMethod;
const char* utf_string = env->GetStringUTFChars(path, NULL); const char* utf_string = env->GetStringUTFChars(path, NULL);
int retval = zts_start(utf_string, NULL, port); // using _userCallbackMethodRef if (!utf_string) {
return ZTS_ERR_GENERAL;
}
// using _userCallbackMethodRef
int retval = zts_start(utf_string, NULL, port);
env->ReleaseStringUTFChars(path, utf_string); env->ReleaseStringUTFChars(path, utf_string);
return retval; return retval;
} }

View File

@@ -186,7 +186,7 @@ int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt(
JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval) JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval)
{ {
jclass c = (*env).GetObjectClass(optval); jclass c = env->GetObjectClass(optval);
if (!c) { if (!c) {
return ZTS_ERR_INVALID_OP; return ZTS_ERR_INVALID_OP;
} }
@@ -198,8 +198,8 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt(
|| optname == SO_REUSEPORT || optname == SO_REUSEPORT
|| optname == TCP_NODELAY) || optname == TCP_NODELAY)
{ {
jfieldID fid = (*env).GetFieldID(c, "booleanValue", "Z"); jfieldID fid = env->GetFieldID(c, "booleanValue", "Z");
optval_int = (int)(*env).GetBooleanField(optval, fid); optval_int = (int)(env->GetBooleanField(optval, fid));
} }
if (optname == IP_TTL if (optname == IP_TTL
|| optname == SO_RCVTIMEO || optname == SO_RCVTIMEO
@@ -208,8 +208,8 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt(
|| optname == SO_RCVBUF || optname == SO_RCVBUF
|| optname == SO_SNDBUF) || optname == SO_SNDBUF)
{ {
jfieldID fid = (*env).GetFieldID(c, "integerValue", "I"); jfieldID fid = env->GetFieldID(c, "integerValue", "I");
optval_int = (*env).GetIntField(optval, fid); optval_int = env->GetIntField(optval, fid);
} }
int retval = ZTS_ERR_OK; int retval = ZTS_ERR_OK;
@@ -236,7 +236,7 @@ int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optl
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt( JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt(
JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval) JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval)
{ {
jclass c = (*env).GetObjectClass(optval); jclass c = env->GetObjectClass(optval);
if (!c) { if (!c) {
return ZTS_ERR_INVALID_OP; return ZTS_ERR_INVALID_OP;
} }
@@ -262,10 +262,10 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt(
|| optname == SO_REUSEPORT || optname == SO_REUSEPORT
|| optname == TCP_NODELAY) || optname == TCP_NODELAY)
{ {
jfieldID fid = (*env).GetFieldID(c, "isBoolean", "Z"); jfieldID fid = env->GetFieldID(c, "isBoolean", "Z");
(*env).SetBooleanField(optval, fid, true); env->SetBooleanField(optval, fid, true);
fid = (*env).GetFieldID(c, "booleanValue", "Z"); fid = env->GetFieldID(c, "booleanValue", "Z");
(*env).SetBooleanField(optval, fid, (bool)optval_int); env->SetBooleanField(optval, fid, (bool)optval_int);
} }
if (optname == IP_TTL if (optname == IP_TTL
|| optname == SO_RCVTIMEO || optname == SO_RCVTIMEO
@@ -274,10 +274,10 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt(
|| optname == SO_RCVBUF || optname == SO_RCVBUF
|| optname == SO_SNDBUF) || optname == SO_SNDBUF)
{ {
jfieldID fid = (*env).GetFieldID(c, "isInteger", "Z"); jfieldID fid = env->GetFieldID(c, "isInteger", "Z");
(*env).SetBooleanField(optval, fid, true); env->SetBooleanField(optval, fid, true);
fid = (*env).GetFieldID(c, "integerValue", "I"); fid = env->GetFieldID(c, "integerValue", "I");
(*env).SetIntField(optval, fid, optval_int); env->SetIntField(optval, fid, optval_int);
} }
return retval > -1 ? retval : -(zts_errno); return retval > -1 ? retval : -(zts_errno);
} }
@@ -461,12 +461,12 @@ JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl(
int bytesRemaining = 0; int bytesRemaining = 0;
retval = zts_ioctl(fd, request, &bytesRemaining); retval = zts_ioctl(fd, request, &bytesRemaining);
// set value in general object // set value in general object
jclass c = (*env).GetObjectClass(argp); jclass c = env->GetObjectClass(argp);
if (!c) { if (!c) {
return ZTS_ERR_INVALID_ARG; return ZTS_ERR_INVALID_ARG;
} }
jfieldID fid = (*env).GetFieldID(c, "integer", "I"); jfieldID fid = env->GetFieldID(c, "integer", "I");
(*env).SetIntField(argp, fid, bytesRemaining); env->SetIntField(argp, fid, bytesRemaining);
} }
if (request == FIONBIO) { if (request == FIONBIO) {
// TODO: double check // TODO: double check
@@ -678,40 +678,40 @@ int zts_del_dns_nameserver(struct sockaddr *addr)
#ifdef SDK_JNI #ifdef SDK_JNI
void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set) void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set)
{ {
jclass c = (*env).GetObjectClass(src_ztfd_set); jclass c = env->GetObjectClass(src_ztfd_set);
if (!c) { if (!c) {
return; return;
} }
FD_ZERO(dest_fd_set); FD_ZERO(dest_fd_set);
jfieldID fid = env->GetFieldID(c, "fds_bits", "[B"); jfieldID fid = env->GetFieldID(c, "fds_bits", "[B");
jobject fdData = (*env).GetObjectField (src_ztfd_set, fid); jobject fdData = env->GetObjectField (src_ztfd_set, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&fdData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&fdData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
for (int i=0; i<nfds; i++) { for (int i=0; i<nfds; i++) {
if (data[i] == 0x01) { if (data[i] == 0x01) {
FD_SET(i, dest_fd_set); FD_SET(i, dest_fd_set);
} }
} }
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_set) void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_set)
{ {
jclass c = (*env).GetObjectClass(dest_ztfd_set); jclass c = env->GetObjectClass(dest_ztfd_set);
if (!c) { if (!c) {
return; return;
} }
jfieldID fid = env->GetFieldID(c, "fds_bits", "[B"); jfieldID fid = env->GetFieldID(c, "fds_bits", "[B");
jobject fdData = (*env).GetObjectField (dest_ztfd_set, fid); jobject fdData = env->GetObjectField (dest_ztfd_set, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&fdData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&fdData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
for (int i=0; i<nfds; i++) { for (int i=0; i<nfds; i++) {
if (FD_ISSET(i, src_fd_set)) { if (FD_ISSET(i, src_fd_set)) {
data[i] = 0x01; data[i] = 0x01;
} }
} }
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
@@ -721,78 +721,78 @@ void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_
void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr)
{ {
jclass c = (*env).GetObjectClass(addr); jclass c = env->GetObjectClass(addr);
if (!c) { if (!c) {
return; return;
} }
if(ss->ss_family == AF_INET) if(ss->ss_family == AF_INET)
{ {
struct sockaddr_in *in4 = (struct sockaddr_in*)ss; struct sockaddr_in *in4 = (struct sockaddr_in*)ss;
jfieldID fid = (*env).GetFieldID(c, "_port", "I"); jfieldID fid = env->GetFieldID(c, "_port", "I");
(*env).SetIntField(addr, fid, lwip_ntohs(in4->sin_port)); env->SetIntField(addr, fid, lwip_ntohs(in4->sin_port));
fid = (*env).GetFieldID(c,"_family", "I"); fid = env->GetFieldID(c,"_family", "I");
(*env).SetIntField(addr, fid, (in4->sin_family)); env->SetIntField(addr, fid, (in4->sin_family));
fid = env->GetFieldID(c, "_ip4", "[B"); fid = env->GetFieldID(c, "_ip4", "[B");
jobject ipData = (*env).GetObjectField (addr, fid); jobject ipData = env->GetObjectField (addr, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
memcpy(data, &(in4->sin_addr.s_addr), 4); memcpy(data, &(in4->sin_addr.s_addr), 4);
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
if(ss->ss_family == AF_INET6) if(ss->ss_family == AF_INET6)
{ {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss;
jfieldID fid = (*env).GetFieldID(c, "_port", "I"); jfieldID fid = env->GetFieldID(c, "_port", "I");
(*env).SetIntField(addr, fid, lwip_ntohs(in6->sin6_port)); env->SetIntField(addr, fid, lwip_ntohs(in6->sin6_port));
fid = (*env).GetFieldID(c,"_family", "I"); fid = env->GetFieldID(c,"_family", "I");
(*env).SetIntField(addr, fid, (in6->sin6_family)); env->SetIntField(addr, fid, (in6->sin6_family));
fid = env->GetFieldID(c, "_ip6", "[B"); fid = env->GetFieldID(c, "_ip6", "[B");
jobject ipData = (*env).GetObjectField (addr, fid); jobject ipData = env->GetObjectField (addr, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
memcpy(data, &(in6->sin6_addr.s6_addr), 16); memcpy(data, &(in6->sin6_addr.s6_addr), 16);
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
} }
void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr)
{ {
jclass c = (*env).GetObjectClass(addr); jclass c = env->GetObjectClass(addr);
if (!c) { if (!c) {
return; return;
} }
jfieldID fid = (*env).GetFieldID(c, "_family", "I"); jfieldID fid = env->GetFieldID(c, "_family", "I");
int family = (*env).GetIntField(addr, fid); int family = env->GetIntField(addr, fid);
if (family == AF_INET) if (family == AF_INET)
{ {
struct sockaddr_in *in4 = (struct sockaddr_in*)ss; struct sockaddr_in *in4 = (struct sockaddr_in*)ss;
fid = (*env).GetFieldID(c, "_port", "I"); fid = env->GetFieldID(c, "_port", "I");
in4->sin_port = lwip_htons((*env).GetIntField(addr, fid)); in4->sin_port = lwip_htons(env->GetIntField(addr, fid));
in4->sin_family = AF_INET; in4->sin_family = AF_INET;
fid = env->GetFieldID(c, "_ip4", "[B"); fid = env->GetFieldID(c, "_ip4", "[B");
jobject ipData = (*env).GetObjectField (addr, fid); jobject ipData = env->GetObjectField (addr, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
memcpy(&(in4->sin_addr.s_addr), data, 4); memcpy(&(in4->sin_addr.s_addr), data, 4);
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
if (family == AF_INET6) if (family == AF_INET6)
{ {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss;
jfieldID fid = (*env).GetFieldID(c, "_port", "I"); jfieldID fid = env->GetFieldID(c, "_port", "I");
in6->sin6_port = lwip_htons((*env).GetIntField(addr, fid)); in6->sin6_port = lwip_htons(env->GetIntField(addr, fid));
fid = (*env).GetFieldID(c,"_family", "I"); fid = env->GetFieldID(c,"_family", "I");
in6->sin6_family = AF_INET6; in6->sin6_family = AF_INET6;
fid = env->GetFieldID(c, "_ip6", "[B"); fid = env->GetFieldID(c, "_ip6", "[B");
jobject ipData = (*env).GetObjectField (addr, fid); jobject ipData = env->GetObjectField (addr, fid);
jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData); jbyteArray * arr = reinterpret_cast<jbyteArray*>(&ipData);
char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); char *data = (char*)env->GetByteArrayElements(*arr, NULL);
memcpy(&(in6->sin6_addr.s6_addr), data, 16); memcpy(&(in6->sin6_addr.s6_addr), data, 16);
(*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0);
return; return;
} }
} }