SDK_JNI
This commit is contained in:
7
Makefile
7
Makefile
@@ -141,15 +141,14 @@ endif
|
||||
# JNI (Java Native Interface)
|
||||
ifeq ($(SDK_JNI), 1)
|
||||
# jni.h
|
||||
INCLUDES+=-I$(shell /usr/libexec/java_home)/include
|
||||
LIBZT_INCLUDES+=-I$(shell /usr/libexec/java_home)/include
|
||||
# jni_md.h
|
||||
INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(SYSTEM)
|
||||
CXXFLAGS+=-DSDK_JNI
|
||||
LIBZT_INCLUDES+=-I$(shell /usr/libexec/java_home)/include/$(OSTYPE)
|
||||
LIBZT_DEFS+=-DSDK_JNI
|
||||
endif
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -Wno-format -fno-rtti -std=c++11
|
||||
ZT_DEFS+=-DZT_SDK -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
|
||||
LIBZT_DEFS+=
|
||||
LIBZT_FILES:=src/VirtualTap.cpp src/libzt.cpp src/Utilities.cpp
|
||||
STATIC_LIB=$(BUILD)/libzt.a
|
||||
|
||||
|
||||
@@ -485,6 +485,101 @@ void zts_allow_http_control(bool allowed)
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(SDK_JNI)
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
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, "<init>", "()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, "<init>", "()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
|
||||
|
||||
190
src/libzt.cpp
190
src/libzt.cpp
@@ -496,6 +496,196 @@ 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 <jni.h>
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user