diff --git a/Makefile b/Makefile index e9bbfd8..84f8308 100644 --- a/Makefile +++ b/Makefile @@ -295,13 +295,16 @@ libzt_socket_layer: $(CXX) $(CXXFLAGS) -c src/libzt.cpp \ $(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) +jni_socket_wrapper: + $(CXX) $(CXXFLAGS) -DSDK_JNI -c src/libztJNI.cpp \ + $(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) + utilities: $(CXX) $(CXXFLAGS) -c src/Platform.cpp \ $(LIBZT_INCLUDES) $(CXX) $(CXXFLAGS) -c src/Utilities.cpp \ $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) - win_dll: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS) # First we use mingw to build our DLL @mkdir -p $(BUILD) obj @@ -313,6 +316,16 @@ win_dll: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS) # lib /machine:x64 /def:libzt.def # or just execute: makelib +shared_lib: lwip lwip_driver libzt_socket_layer utilities $(ZTO_OBJS) + @mkdir -p $(BUILD) obj + mv *.o obj + $(CXX) $(CXXFLAGS) -shared -o $(BUILD)/libzt.so obj/*.o + +shared_jni_lib: lwip lwip_driver libzt_socket_layer jni_socket_wrapper utilities $(ZTO_OBJS) + @mkdir -p $(BUILD) obj + mv *.o obj + $(CXX) $(CXXFLAGS) -shared -o $(BUILD)/libzt.so obj/*.o + ifeq ($(STACK_PICO),1) static_lib: picotcp picotcp_driver libzt_socket_layer utilities $(ZTO_OBJS) @mkdir -p $(BUILD) obj @@ -354,14 +367,6 @@ macos_app_framework: cd examples/apple/ZeroTierSDK_Apple; xcodebuild -configuration Debug \ -scheme ZeroTierSDK_OSX build SYMROOT="../../../$(BUILD)/macos_app_framework" -############################################################################## -## Java JNI ## -############################################################################## - -shared_jni_lib: picotcp $(ZTO_OBJS) - $(CXX) $(CXXFLAGS) $(TAP_FILES) $(STACK_DRIVER_FILES) $(ZTO_OBJS) $(INCLUDES) \ - $(PICO_LIB) -dynamiclib -o $(SHARED_JNI_LIB) - ############################################################################## ## Python module ## ############################################################################## diff --git a/src/ZT1Service.cpp b/src/ZT1Service.cpp index 5fbb920..a5f5457 100644 --- a/src/ZT1Service.cpp +++ b/src/ZT1Service.cpp @@ -263,7 +263,7 @@ void disableTaps() void zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen) { - DEBUG_EXTRA(); + // DEBUG_EXTRA(); if (ZeroTier::zt1Service) { uint64_t nwid_int = strtoull(nwid, NULL, 16); ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); @@ -286,7 +286,7 @@ void zts_get_ipv4_address(const char *nwid, char *addrstr, const size_t addrlen) void zts_get_ipv6_address(const char *nwid, char *addrstr, size_t addrlen) { - DEBUG_EXTRA(); + // DEBUG_EXTRA(); if (ZeroTier::zt1Service) { uint64_t nwid_int = strtoull(nwid, NULL, 16); ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); @@ -309,7 +309,7 @@ void zts_get_ipv6_address(const char *nwid, char *addrstr, size_t addrlen) int zts_has_ipv4_address(const char *nwid) { - DEBUG_EXTRA(); + // DEBUG_EXTRA(); char ipv4_addr[INET_ADDRSTRLEN]; memset(ipv4_addr, 0, INET_ADDRSTRLEN); zts_get_ipv4_address(nwid, ipv4_addr, INET_ADDRSTRLEN); @@ -318,7 +318,7 @@ int zts_has_ipv4_address(const char *nwid) int zts_has_ipv6_address(const char *nwid) { - DEBUG_EXTRA(); + // DEBUG_EXTRA(); char ipv6_addr[INET6_ADDRSTRLEN]; memset(ipv6_addr, 0, INET6_ADDRSTRLEN); zts_get_ipv6_address(nwid, ipv6_addr, INET6_ADDRSTRLEN); @@ -327,11 +327,10 @@ int zts_has_ipv6_address(const char *nwid) int zts_has_address(const char *nwid) { - DEBUG_EXTRA(); + // DEBUG_EXTRA(); return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); } - void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) { DEBUG_EXTRA(); @@ -537,99 +536,6 @@ void zts_allow_http_control(bool allowed) // TODO } - -#if defined(SDK_JNI) - -namespace ZeroTier { - - #include - - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1start(JNIEnv *env, jobject thisObj, jstring path) { - if (path) { - homeDir = env->GetStringUTFChars(path, NULL); - zts_start(homeDir.c_str()); - } - } - // Shuts down ZeroTier service and SOCKS5 Proxy server - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) { - if (ZeroTier::zt1Service) { - zts_stop(); - } - } - - // Returns whether the ZeroTier service is running - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ztjni_1running( - JNIEnv *env, jobject thisObj) - { - return zts_running(); - } - // Returns path for ZT config/data files - JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_ztjni_1homepath( - JNIEnv *env, jobject thisObj) - { - // TODO: fix, should copy into given arg - // return (*env).NewStringUTF(zts_get_homepath()); - return (*env).NewStringUTF(""); - } - // Join a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1join( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if (nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_join(nwidstr); - } - } - // Leave a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1leave( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if (nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_leave(nwidstr); - } - } - // FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations - // Now only returns first assigned address per network. Shouldn't normally be a problem - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv4_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[INET_ADDRSTRLEN]; - memset(address_string, 0, INET_ADDRSTRLEN); - zts_get_ipv4_address(nwid_str, address_string, INET_ADDRSTRLEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } - - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[INET6_ADDRSTRLEN]; - memset(address_string, 0, INET6_ADDRSTRLEN); - zts_get_ipv6_address(nwid_str, address_string, INET6_ADDRSTRLEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } - - // Returns the device is in integer form - JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id() - { - return zts_get_device_id(NULL); // TODO - } -} - -#endif // SDK_JNI - #ifdef __cplusplus } #endif diff --git a/src/libzt.cpp b/src/libzt.cpp index c9e9a7d..a41e3d5 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -534,196 +534,6 @@ int zts_del_dns_nameserver(struct sockaddr *addr) return err; } - -/****************************************************************************/ -/* SDK Socket API (Java Native Interface JNI) */ -/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */ -/****************************************************************************/ - -#if defined(SDK_JNI) - -namespace ZeroTier { - - #include - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1sendto( - JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jclass cls = (*env).GetObjectClass( ztaddr); - jfieldID f = (*env).GetFieldID( cls, "port", "I"); - addr.sin_port = htons((*env).GetIntField( ztaddr, f)); - f = (*env).GetFieldID( cls, "_rawAddr", "J"); - addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); - addr.sin_family = AF_INET; - //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - // TODO: Optimize this - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - // "connect" and send buffer contents - int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); - return sent_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1recvfrom( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jbyte *body = (*env).GetByteArrayElements( buf, 0); - unsigned char buffer[ZT_SDK_MTU]; - int payload_offset = sizeof(int32_t) + sizeof(struct sockaddr_storage); - int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); - if (rxbytes > 0) - memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); - (*env).ReleaseByteArrayElements( buf, body, 0); - // Update fields of Java ZTAddress object - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return rxbytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - int read_bytes = read(fd, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - return read_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt( - JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, - jint family, jint type, jint protocol) { - return zts_socket(family, type, protocol); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_bind(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - -#if defined(__linux__) - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port, jint flags) { - struct sockaddr_in addr; - char *str; - // = env->GetStringUTFChars(addrstr, NULL); - (*env).ReleaseStringUTFChars( addrstr, str); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); - } -#endif - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - // TODO: Send addr info back to Javaland - addr.sin_addr.s_addr = inet_addr(""); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, - jint fd, int backlog) { - return zts_listen(fd, backlog); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, - jint fd) { - return zts_close(fd); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, - jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass(ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, - jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, - jint fd, jint cmd, jint flags) { - return zts_fcntl(fd,cmd,flags); - } -} -#endif // SDK_JNI - #ifdef __cplusplus } #endif diff --git a/src/libztJNI.cpp b/src/libztJNI.cpp new file mode 100644 index 0000000..53d3d81 --- /dev/null +++ b/src/libztJNI.cpp @@ -0,0 +1,321 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Javs JNI wrapper for partially-POSIX-compliant socket API + * JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME + */ + +#if defined(SDK_JNI) + +#include + +#include "libzt.h" +#include "ZT1Service.h" + +#ifdef __cplusplus +extern "C" { +#endif + +namespace ZeroTier { + + #include + + /****************************************************************************/ + /* Java JNI Wrapper for ZeroTier Socket API */ + /****************************************************************************/ + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1sendto( + JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) + { + struct sockaddr_in addr; + jclass cls = (*env).GetObjectClass( ztaddr); + jfieldID f = (*env).GetFieldID( cls, "port", "I"); + addr.sin_port = htons((*env).GetIntField( ztaddr, f)); + f = (*env).GetFieldID( cls, "_rawAddr", "J"); + addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); + addr.sin_family = AF_INET; + //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + // TODO: Optimize this + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + // "connect" and send buffer contents + int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); + return sent_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1recvfrom( + JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) + { + struct sockaddr_in addr; + jbyte *body = (*env).GetByteArrayElements( buf, 0); + unsigned char buffer[ZT_SDK_MTU]; + int payload_offset = sizeof(int32_t) + sizeof(struct sockaddr_storage); + int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); + if (rxbytes > 0) + memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); + (*env).ReleaseByteArrayElements( buf, body, 0); + // Update fields of Java ZTAddress object + jfieldID fid; + jclass cls = (*env).GetObjectClass( ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return rxbytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, + jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + char * bufp = (char *)malloc(sizeof(char)*len); + memcpy(bufp, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + int written_bytes = zts_write(fd, body, len); + return written_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, + jint fd, jarray buf, jint len) + { + jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); + int read_bytes = read(fd, body, len); + (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); + return read_bytes; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt( + JNIEnv *env, jobject thisObj, + jint fd, jint level, jint optname, jint optval, jint optlen) { + return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, + jint fd, jint level, jint optname, jint optval, jint optlen) { + return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, + jint family, jint type, jint protocol) { + return zts_socket(family, type, protocol); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, + jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + const char *str = (*env).GetStringUTFChars( addrstr, 0); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + (*env).ReleaseStringUTFChars( addrstr, str); + return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, + jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + const char *str = (*env).GetStringUTFChars( addrstr, 0); + DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + (*env).ReleaseStringUTFChars( addrstr, str); + return zts_bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + } + +#if defined(__linux__) + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, + jint fd, jstring addrstr, jint port, jint flags) { + struct sockaddr_in addr; + char *str; + // = env->GetStringUTFChars(addrstr, NULL); + (*env).ReleaseStringUTFChars( addrstr, str); + addr.sin_addr.s_addr = inet_addr(str); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); + } +#endif + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, + jint fd, jstring addrstr, jint port) { + struct sockaddr_in addr; + // TODO: Send addr info back to Javaland + addr.sin_addr.s_addr = inet_addr(""); + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, + jint fd, int backlog) { + return zts_listen(fd, backlog); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, + jint fd) { + return zts_close(fd); + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, + jint fd, jobject ztaddr) { + struct sockaddr_in addr; + int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); + jfieldID fid; + jclass cls = (*env).GetObjectClass(ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return err; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, + jint fd, jobject ztaddr) { + struct sockaddr_in addr; + int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); + jfieldID fid; + jclass cls = (*env).GetObjectClass( ztaddr); + fid = (*env).GetFieldID( cls, "port", "I"); + (*env).SetIntField( ztaddr, fid, addr.sin_port); + fid = (*env).GetFieldID( cls,"_rawAddr", "J"); + (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); + return err; + } + + JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, + jint fd, jint cmd, jint flags) { + return zts_fcntl(fd,cmd,flags); + } + + /****************************************************************************/ + /* Java JNI Wrapper for ZeroTier service controls */ + /****************************************************************************/ + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1start(JNIEnv *env, jobject thisObj, jstring path) { + if (path) { + zts_start(env->GetStringUTFChars(path, NULL)); + } + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1startjoin(JNIEnv *env, jobject thisObj, jstring path, jstring nwid) { + if (path) { + zts_startjoin(env->GetStringUTFChars(path, NULL), env->GetStringUTFChars(nwid, NULL)); + } + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) { + zts_stop(); + } + + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ztjni_1running( + JNIEnv *env, jobject thisObj) + { + return zts_running(); + } + + JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_ztjni_1homepath( + JNIEnv *env, jobject thisObj) + { + // TODO: fix, should copy into given arg + // return (*env).NewStringUTF(zts_get_homepath()); + return (*env).NewStringUTF(""); + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1join( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if (nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_join(nwidstr); + } + } + + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1leave( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if (nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_leave(nwidstr); + } + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv4_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[INET_ADDRSTRLEN]; + memset(address_string, 0, INET_ADDRSTRLEN); + zts_get_ipv4_address(nwid_str, address_string, INET_ADDRSTRLEN); + jclass clazz = (*env).FindClass("java/util/ArrayList"); + jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); + jstring _str = (*env).NewStringUTF(address_string); + env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); + return addresses; + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[INET6_ADDRSTRLEN]; + memset(address_string, 0, INET6_ADDRSTRLEN); + zts_get_ipv6_address(nwid_str, address_string, INET6_ADDRSTRLEN); + jclass clazz = (*env).FindClass("java/util/ArrayList"); + jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); + jstring _str = (*env).NewStringUTF(address_string); + env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); + return addresses; + } + + JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id() + { + return zts_get_device_id(NULL); // TODO + } +} + +#endif // SDK_JNI + +#ifdef __cplusplus +} +#endif \ No newline at end of file