diff --git a/include/ZeroTierConstants.h b/include/ZeroTierConstants.h index ad3e3e2..43349de 100644 --- a/include/ZeroTierConstants.h +++ b/include/ZeroTierConstants.h @@ -44,6 +44,8 @@ #define ZTS_ERR_INVALID_OP -3 // The call succeeded, but no object or relevant result was available #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 diff --git a/src/Controls.cpp b/src/Controls.cpp index faa4426..8cd5fef 100644 --- a/src/Controls.cpp +++ b/src/Controls.cpp @@ -75,21 +75,15 @@ int _port; std::string _path; /* - * A lock used to protect any call which relies on the presence of a valid pointer - * to the ZeroTier service. + * A lock used to protect any call which relies on the presence of a valid + * pointer to the ZeroTier service. */ Mutex _service_lock; /* - * A lock which protects flags and state variables used during the startup and - * shutdown phase. - */ -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. + * 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; @@ -425,13 +419,14 @@ extern "C" { #ifdef SDK_JNI /* - * Called from Java, saves a static reference to the VM so it can be used later to call - * a user-specified callback method from C. + * Called from Java, saves a static reference to the VM so it can be used + * 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); - assert (rs == JNI_OK); + return rs != JNI_OK ? ZTS_ERR_GENERAL : ZTS_ERR_OK; } #endif @@ -515,7 +510,8 @@ int zts_deorbit(uint64_t moonWorldId) #ifdef SDK_JNI #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); 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; } 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; } #ifdef SDK_JNI @@ -607,10 +604,15 @@ JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_start( DEBUG_ERROR("Couldn't find onZeroTierEvent method"); 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; 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); return retval; } diff --git a/src/Sockets.cpp b/src/Sockets.cpp index 76c5bad..df65521 100644 --- a/src/Sockets.cpp +++ b/src/Sockets.cpp @@ -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( JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval) { - jclass c = (*env).GetObjectClass(optval); + jclass c = env->GetObjectClass(optval); if (!c) { return ZTS_ERR_INVALID_OP; } @@ -198,8 +198,8 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( || optname == SO_REUSEPORT || optname == TCP_NODELAY) { - jfieldID fid = (*env).GetFieldID(c, "booleanValue", "Z"); - optval_int = (int)(*env).GetBooleanField(optval, fid); + jfieldID fid = env->GetFieldID(c, "booleanValue", "Z"); + optval_int = (int)(env->GetBooleanField(optval, fid)); } if (optname == IP_TTL || optname == SO_RCVTIMEO @@ -208,8 +208,8 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( || optname == SO_RCVBUF || optname == SO_SNDBUF) { - jfieldID fid = (*env).GetFieldID(c, "integerValue", "I"); - optval_int = (*env).GetIntField(optval, fid); + jfieldID fid = env->GetFieldID(c, "integerValue", "I"); + optval_int = env->GetIntField(optval, fid); } 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( JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval) { - jclass c = (*env).GetObjectClass(optval); + jclass c = env->GetObjectClass(optval); if (!c) { return ZTS_ERR_INVALID_OP; } @@ -262,10 +262,10 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt( || optname == SO_REUSEPORT || optname == TCP_NODELAY) { - jfieldID fid = (*env).GetFieldID(c, "isBoolean", "Z"); - (*env).SetBooleanField(optval, fid, true); - fid = (*env).GetFieldID(c, "booleanValue", "Z"); - (*env).SetBooleanField(optval, fid, (bool)optval_int); + jfieldID fid = env->GetFieldID(c, "isBoolean", "Z"); + env->SetBooleanField(optval, fid, true); + fid = env->GetFieldID(c, "booleanValue", "Z"); + env->SetBooleanField(optval, fid, (bool)optval_int); } if (optname == IP_TTL || optname == SO_RCVTIMEO @@ -274,10 +274,10 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt( || optname == SO_RCVBUF || optname == SO_SNDBUF) { - jfieldID fid = (*env).GetFieldID(c, "isInteger", "Z"); - (*env).SetBooleanField(optval, fid, true); - fid = (*env).GetFieldID(c, "integerValue", "I"); - (*env).SetIntField(optval, fid, optval_int); + jfieldID fid = env->GetFieldID(c, "isInteger", "Z"); + env->SetBooleanField(optval, fid, true); + fid = env->GetFieldID(c, "integerValue", "I"); + env->SetIntField(optval, fid, optval_int); } return retval > -1 ? retval : -(zts_errno); } @@ -461,12 +461,12 @@ JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl( int bytesRemaining = 0; retval = zts_ioctl(fd, request, &bytesRemaining); // set value in general object - jclass c = (*env).GetObjectClass(argp); + jclass c = env->GetObjectClass(argp); if (!c) { return ZTS_ERR_INVALID_ARG; } - jfieldID fid = (*env).GetFieldID(c, "integer", "I"); - (*env).SetIntField(argp, fid, bytesRemaining); + jfieldID fid = env->GetFieldID(c, "integer", "I"); + env->SetIntField(argp, fid, bytesRemaining); } if (request == FIONBIO) { // TODO: double check @@ -678,40 +678,40 @@ int zts_del_dns_nameserver(struct sockaddr *addr) #ifdef SDK_JNI 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) { return; } FD_ZERO(dest_fd_set); 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(&fdData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); for (int i=0; iReleaseByteArrayElements(*arr, (jbyte*)data, 0); return; } 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) { return; } 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(&fdData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); for (int i=0; iReleaseByteArrayElements(*arr, (jbyte*)data, 0); 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) { - jclass c = (*env).GetObjectClass(addr); + jclass c = env->GetObjectClass(addr); if (!c) { return; } if(ss->ss_family == AF_INET) { struct sockaddr_in *in4 = (struct sockaddr_in*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, lwip_ntohs(in4->sin_port)); - fid = (*env).GetFieldID(c,"_family", "I"); - (*env).SetIntField(addr, fid, (in4->sin_family)); + jfieldID fid = env->GetFieldID(c, "_port", "I"); + env->SetIntField(addr, fid, lwip_ntohs(in4->sin_port)); + fid = env->GetFieldID(c,"_family", "I"); + env->SetIntField(addr, fid, (in4->sin_family)); fid = env->GetFieldID(c, "_ip4", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); + jobject ipData = env->GetObjectField (addr, fid); jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); memcpy(data, &(in4->sin_addr.s_addr), 4); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); + env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0); return; } if(ss->ss_family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, lwip_ntohs(in6->sin6_port)); - fid = (*env).GetFieldID(c,"_family", "I"); - (*env).SetIntField(addr, fid, (in6->sin6_family)); + jfieldID fid = env->GetFieldID(c, "_port", "I"); + env->SetIntField(addr, fid, lwip_ntohs(in6->sin6_port)); + fid = env->GetFieldID(c,"_family", "I"); + env->SetIntField(addr, fid, (in6->sin6_family)); fid = env->GetFieldID(c, "_ip6", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); + jobject ipData = env->GetObjectField (addr, fid); jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); memcpy(data, &(in6->sin6_addr.s6_addr), 16); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); + env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0); return; } } void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) { - jclass c = (*env).GetObjectClass(addr); + jclass c = env->GetObjectClass(addr); if (!c) { return; } - jfieldID fid = (*env).GetFieldID(c, "_family", "I"); - int family = (*env).GetIntField(addr, fid); + jfieldID fid = env->GetFieldID(c, "_family", "I"); + int family = env->GetIntField(addr, fid); if (family == AF_INET) { struct sockaddr_in *in4 = (struct sockaddr_in*)ss; - fid = (*env).GetFieldID(c, "_port", "I"); - in4->sin_port = lwip_htons((*env).GetIntField(addr, fid)); + fid = env->GetFieldID(c, "_port", "I"); + in4->sin_port = lwip_htons(env->GetIntField(addr, fid)); in4->sin_family = AF_INET; fid = env->GetFieldID(c, "_ip4", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); + jobject ipData = env->GetObjectField (addr, fid); jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); memcpy(&(in4->sin_addr.s_addr), data, 4); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); + env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0); return; } if (family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; - jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - in6->sin6_port = lwip_htons((*env).GetIntField(addr, fid)); - fid = (*env).GetFieldID(c,"_family", "I"); + jfieldID fid = env->GetFieldID(c, "_port", "I"); + in6->sin6_port = lwip_htons(env->GetIntField(addr, fid)); + fid = env->GetFieldID(c,"_family", "I"); in6->sin6_family = AF_INET6; fid = env->GetFieldID(c, "_ip6", "[B"); - jobject ipData = (*env).GetObjectField (addr, fid); + jobject ipData = env->GetObjectField (addr, fid); jbyteArray * arr = reinterpret_cast(&ipData); - char *data = (char*)(*env).GetByteArrayElements(*arr, NULL); + char *data = (char*)env->GetByteArrayElements(*arr, NULL); memcpy(&(in6->sin6_addr.s6_addr), data, 16); - (*env).ReleaseByteArrayElements(*arr, (jbyte*)data, 0); + env->ReleaseByteArrayElements(*arr, (jbyte*)data, 0); return; } }