|
|
|
@ -31,10 +31,16 @@ |
|
|
|
* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME |
|
|
|
* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SDK_JNI |
|
|
|
|
|
|
|
|
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
|
|
|
|
#include <netinet/in.h> |
|
|
|
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
|
|
|
|
|
|
|
#include "libzt.h" |
|
|
|
#include "libzt.h" |
|
|
|
#include "ZT1Service.h" |
|
|
|
#include "libztDefs.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <jni.h> |
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
#ifdef __cplusplus |
|
|
|
extern "C" { |
|
|
|
extern "C" { |
|
|
|
@ -42,281 +48,285 @@ extern "C" { |
|
|
|
|
|
|
|
|
|
|
|
namespace ZeroTier { |
|
|
|
namespace ZeroTier { |
|
|
|
|
|
|
|
|
|
|
|
#include <jni.h> |
|
|
|
// prototype
|
|
|
|
|
|
|
|
jobject ss2inet(JNIEnv *env, struct sockaddr_storage *src_ss); |
|
|
|
|
|
|
|
int sockinet2ss(JNIEnv *env, jobject src_inet, struct sockaddr_storage *dest_ss); |
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/ |
|
|
|
/****************************************************************************/ |
|
|
|
/* ZeroTier Socket API (for JNI wrapper) */ |
|
|
|
/* ZeroTier service controls */ |
|
|
|
/****************************************************************************/ |
|
|
|
/****************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_socket(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_start( |
|
|
|
jint family, jint type, jint protocol) |
|
|
|
JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return zts_socket(family, type, protocol); |
|
|
|
if (path) { |
|
|
|
|
|
|
|
zts_start(env->GetStringUTFChars(path, NULL), blocking); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_connect(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_startjoin( |
|
|
|
jint fd, jstring addrstr, jint port) |
|
|
|
JNIEnv *env, jobject thisObj, jstring path, jlong nwid) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_storage ss; |
|
|
|
if (path && nwid) { |
|
|
|
socklen_t namelen = sizeof(ss); |
|
|
|
zts_startjoin(env->GetStringUTFChars(path, NULL), (uint64_t)nwid); |
|
|
|
int err = 0; |
|
|
|
|
|
|
|
if ((err = zts_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { |
|
|
|
|
|
|
|
DEBUG_ERROR("error while determining socket family"); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const char *str; |
|
|
|
|
|
|
|
#if defined(LIBZT_IPV4) |
|
|
|
|
|
|
|
if (ss.ss_family == AF_INET) { |
|
|
|
|
|
|
|
struct sockaddr_in in_addr; |
|
|
|
|
|
|
|
str = (*env).GetStringUTFChars(addrstr, 0); |
|
|
|
|
|
|
|
in_addr.sin_addr.s_addr = inet_addr(str); |
|
|
|
|
|
|
|
in_addr.sin_family = AF_INET; |
|
|
|
|
|
|
|
in_addr.sin_port = htons(port); |
|
|
|
|
|
|
|
(*env).ReleaseStringUTFChars(addrstr, str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // LIBZT_IPV4
|
|
|
|
|
|
|
|
#if defined(LIBZT_IPV6) |
|
|
|
|
|
|
|
if (ss.ss_family == AF_INET6) { |
|
|
|
|
|
|
|
struct sockaddr_in6 in_addr; |
|
|
|
|
|
|
|
str = (*env).GetStringUTFChars(addrstr, 0); |
|
|
|
|
|
|
|
//in_addr.sin_addr.s_addr = inet_addr(str);
|
|
|
|
|
|
|
|
in_addr.sin6_family = AF_INET6; |
|
|
|
|
|
|
|
in_addr.sin6_port = htons(port); |
|
|
|
|
|
|
|
(*env).ReleaseStringUTFChars(addrstr, str); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
#endif // LIBZT_IPV6
|
|
|
|
|
|
|
|
DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); |
|
|
|
|
|
|
|
return zts_connect(fd, (struct sockaddr *)&ss, sizeof(in_addr)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
zts_stop(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_address( |
|
|
|
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_core_1running( |
|
|
|
JNIEnv *env, jobject thisObj, jstring nwid) |
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// get address
|
|
|
|
return zts_core_running(); |
|
|
|
const char *nwid_str = env->GetStringUTFChars(nwid, NULL); |
|
|
|
} |
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
zts_get_address(nwid_str, &ss, INET_ADDRSTRLEN); |
|
|
|
|
|
|
|
// map sockaddr_storage contents to java InetAddress
|
|
|
|
|
|
|
|
jclass c = (*env).FindClass("java/net/InetSocketAddress"); |
|
|
|
|
|
|
|
if (c) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "<init>", "()V")); |
|
|
|
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_stack_1running( |
|
|
|
env->CallBooleanMethod(addresses, env->GetMethodID(c, "getPort", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_stack_running(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DEBUG_INFO("port from JNI layer = %d", port); |
|
|
|
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ready( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
fid = (*env).GetFieldID(c, "port", "I"); |
|
|
|
{ |
|
|
|
(*env).SetIntField(ztaddr, fid, addr.sin_port); |
|
|
|
return zts_ready(); |
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
|
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
|
|
|
|
//jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "<init>", "()V"));
|
|
|
|
|
|
|
|
//env->CallBooleanMethod(addresses, env->GetMethodID(c, "add", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
|
|
|
|
//return addresses;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_join( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_join((uint64_t)nwid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_leave( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_leave((uint64_t)nwid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_get_1path( |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
jint fd, jstring addrstr, jint port) |
|
|
|
{ |
|
|
|
|
|
|
|
char pathBuf[ZT_HOME_PATH_MAX_LEN]; |
|
|
|
|
|
|
|
zts_get_path(pathBuf, ZT_HOME_PATH_MAX_LEN); |
|
|
|
|
|
|
|
return (*env).NewStringUTF(pathBuf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jlong JNICALL Java_zerotier_ZeroTier_get_1node_1id( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_get_node_id(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id_from_file(const char *filepath);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_get_1num_1assigned_1addresses( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_get_num_assigned_addresses(nwid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_1address_1at_1index( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid, jint index) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_storage ss; |
|
|
|
struct sockaddr_storage ss; |
|
|
|
socklen_t namelen = sizeof(ss); |
|
|
|
int err; |
|
|
|
int err = 0; |
|
|
|
if((err = zts_get_address_at_index(nwid, index, &ss)) < 0) { |
|
|
|
if ((err = zts_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { |
|
|
|
return NULL; |
|
|
|
DEBUG_ERROR("error while determining socket family"); |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
const char *str; |
|
|
|
return ss2inet(env, &ss); |
|
|
|
#if defined(LIBZT_IPV4) |
|
|
|
} |
|
|
|
if (ss.ss_family == AF_INET) { |
|
|
|
|
|
|
|
struct sockaddr_in in_addr; |
|
|
|
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_has_1address( |
|
|
|
str = (*env).GetStringUTFChars(addrstr, 0); |
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid) |
|
|
|
in_addr.sin_addr.s_addr = inet_addr(str); |
|
|
|
{ |
|
|
|
in_addr.sin_family = AF_INET; |
|
|
|
return zts_has_address(nwid); |
|
|
|
in_addr.sin_port = htons(port); |
|
|
|
} |
|
|
|
(*env).ReleaseStringUTFChars(addrstr, str); |
|
|
|
|
|
|
|
} |
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_1address( |
|
|
|
#endif // LIBZT_IPV4
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid, jint address_family) |
|
|
|
#if defined(LIBZT_IPV6) |
|
|
|
{ |
|
|
|
if (ss.ss_family == AF_INET6) { |
|
|
|
struct sockaddr_storage ss; |
|
|
|
struct sockaddr_in6 in_addr; |
|
|
|
int err; |
|
|
|
str = (*env).GetStringUTFChars(addrstr, 0); |
|
|
|
if ((err = zts_get_address((uint64_t)nwid, &ss, address_family)) < 0) { |
|
|
|
//in_addr.sin_addr.s_addr = inet_addr(str);
|
|
|
|
return NULL; |
|
|
|
in_addr.sin6_family = AF_INET6; |
|
|
|
|
|
|
|
in_addr.sin6_port = htons(port); |
|
|
|
|
|
|
|
(*env).ReleaseStringUTFChars(addrstr, str); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
#endif // LIBZT_IPV6
|
|
|
|
return ss2inet(env, &ss); |
|
|
|
DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); |
|
|
|
|
|
|
|
return zts_bind(fd, (struct sockaddr *)&ss, sizeof(in_addr)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_6plane_addr( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
zts_get_6plane_addr(&ss, nwid, nodeId); |
|
|
|
|
|
|
|
return ss2inet(env, &ss); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_rfc4193_addr( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jlong nwid, jlong nodeId) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
zts_get_rfc4193_addr(&ss, nwid, nodeId); |
|
|
|
|
|
|
|
return ss2inet(env, &ss); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jlong JNICALL Java_zerotier_ZeroTier_get_peer_count( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_get_peer_count(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
// TODO: ZT_SOCKET_API int ZTCALL zts_get_peer_address(char *peer, const uint64_t nodeId);
|
|
|
|
jfieldID IPv4 = (*env).GetFieldID(inetClass, "IPv4", "I"); |
|
|
|
// TODO: ZT_SOCKET_API void ZTCALL zts_allow_http_control(bool allowed);
|
|
|
|
if (IPv4) { |
|
|
|
|
|
|
|
ipv4 = (*env).GetIntField(inetClass, IPv4); |
|
|
|
/****************************************************************************/ |
|
|
|
} |
|
|
|
/* ZeroTier Socket API */ |
|
|
|
else { |
|
|
|
/****************************************************************************/ |
|
|
|
DEBUG_ERROR("No field IPv4"); |
|
|
|
|
|
|
|
} |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_socket( |
|
|
|
jfieldID IPv6 = (*env).GetFieldID(inetClass, "IPv6", "I"); |
|
|
|
JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) |
|
|
|
if (IPv6) { |
|
|
|
{ |
|
|
|
ipv6 = (*env).GetIntField(inetClass, IPv6); |
|
|
|
return zts_socket(family, type, protocol); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
DEBUG_ERROR("No field IPv6"); |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_connect( |
|
|
|
} |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jobject addr) |
|
|
|
ipv6 = (*env).GetIntField(inetClass, IPv6); |
|
|
|
{ |
|
|
|
*/
|
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
if(sockinet2ss(env, addr, &ss) < 0) { |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind(JNIEnv *env, jobject thisObj, jint fd, jobject addr) |
|
|
|
return -1; // possibly invalid address format
|
|
|
|
|
|
|
|
// TODO: set errno
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return zts_connect(fd, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_bind( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jobject addr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_storage ss; |
|
|
|
struct sockaddr_storage ss; |
|
|
|
memset(&ss, 0, sizeof(ss)); |
|
|
|
|
|
|
|
struct sockaddr_in *in4 = (struct sockaddr_in*)&ss; |
|
|
|
struct sockaddr_in *in4 = (struct sockaddr_in*)&ss; |
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss; |
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss; |
|
|
|
int err = -1; |
|
|
|
int err; |
|
|
|
int port = 0; |
|
|
|
if(sockinet2ss(env, addr, &ss) < 0) { |
|
|
|
int socket_family = 0; |
|
|
|
return -1; // possibly invalid address format
|
|
|
|
socklen_t addrlen; |
|
|
|
// TODO: set errno
|
|
|
|
|
|
|
|
|
|
|
|
jclass c = (*env).GetObjectClass(addr); |
|
|
|
|
|
|
|
if (!c) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// get port
|
|
|
|
|
|
|
|
jmethodID getPort = (*env).GetMethodID(c, "getPort", "()I"); |
|
|
|
|
|
|
|
if (!getPort) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
port = (*env).CallIntMethod(addr, getPort);
|
|
|
|
|
|
|
|
// get internal InetAddress
|
|
|
|
|
|
|
|
jobject inetaddr; |
|
|
|
|
|
|
|
int family = 0; |
|
|
|
|
|
|
|
jmethodID getAddress = (*env).GetMethodID(c, "getAddress", "()Ljava/net/InetAddress;"); |
|
|
|
|
|
|
|
if (!getAddress) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
inetaddr = (*env).CallObjectMethod(addr, getAddress);
|
|
|
|
//DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port));
|
|
|
|
if (!inetaddr) { |
|
|
|
socklen_t addrlen = ss.ss_family == AF_INET ? 4 : 16; |
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
jclass inetClass = (*env).GetObjectClass(inetaddr); |
|
|
|
|
|
|
|
if (!inetClass) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// string representation of IP address
|
|
|
|
|
|
|
|
jmethodID getHostAddress = (*env).GetMethodID(inetClass, "getHostAddress", "()Ljava/lang/String;"); |
|
|
|
|
|
|
|
jstring addrstr = (jstring)(*env).CallObjectMethod(inetaddr, getHostAddress);
|
|
|
|
|
|
|
|
const char *addr_str = (*env).GetStringUTFChars(addrstr, NULL); |
|
|
|
|
|
|
|
DEBUG_INFO("addr_str=%s", addr_str); |
|
|
|
|
|
|
|
for (int i=0; i<strlen(addr_str); i++) { |
|
|
|
|
|
|
|
if (addr_str[i]=='.') { |
|
|
|
|
|
|
|
DEBUG_INFO("ipv4, inet_addr"); |
|
|
|
|
|
|
|
socket_family = AF_INET; |
|
|
|
|
|
|
|
in4->sin_family = AF_INET; |
|
|
|
|
|
|
|
in4->sin_port = htons(port); |
|
|
|
|
|
|
|
in4->sin_addr.s_addr = inet_addr(addr_str); |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
if (!inet_pton(AF_INET, addr_str, &(in4->sin_addr))) { |
|
|
|
|
|
|
|
DEBUG_ERROR("error converting address %s", addr_str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
addrlen = sizeof(struct sockaddr_in); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (addr_str[i]==':') { |
|
|
|
|
|
|
|
DEBUG_INFO("ipv6"); |
|
|
|
|
|
|
|
socket_family = AF_INET6; |
|
|
|
|
|
|
|
if (!inet_pton(AF_INET6, addr_str, &(in6->sin6_addr))) {
|
|
|
|
|
|
|
|
DEBUG_ERROR("error converting address %s", addr_str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
addrlen = sizeof(struct sockaddr_in6); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
(*env).ReleaseStringUTFChars(addrstr, addr_str); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
jmethodID getRawAddress = (*env).GetMethodID(inetClass, "getAddress", "()[B"); // get raw IP bytes
|
|
|
|
|
|
|
|
if (getRawAddress)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
jbyte rawIPbuf = (*env).CallByteMethod(inetaddr, getRawAddress); |
|
|
|
|
|
|
|
if (socket_family == AF_INET)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
DEBUG_INFO("copying buffer as AF_INET"); |
|
|
|
|
|
|
|
in4->sin_family = socket_family; |
|
|
|
|
|
|
|
in4->sin_port = port; |
|
|
|
|
|
|
|
memcpy(in4->sin_addr, &rawIPbuf, sizeof(in4->sin_addr)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (socket_family == AF_INET6) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
DEBUG_INFO("copying buffer as AF_INET"); |
|
|
|
|
|
|
|
in6->sin6_family = socket_family; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
DEBUG_ERROR("!getRawAddress"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//DEBUG_INFO("port = %d", port);
|
|
|
|
|
|
|
|
//DEBUG_INFO("inetaddr = %p", inetaddr);
|
|
|
|
|
|
|
|
err = zts_bind(fd, (struct sockaddr*)&ss, addrlen); |
|
|
|
err = zts_bind(fd, (struct sockaddr*)&ss, addrlen); |
|
|
|
return err; |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_listen( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jint fd, int backlog) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_listen(fd, backlog); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
int err; |
|
|
|
|
|
|
|
socklen_t addrlen = sizeof(struct sockaddr_storage); |
|
|
|
|
|
|
|
if ((err = zts_accept(fd, (struct sockaddr *)&ss, &addrlen)) < 0) { |
|
|
|
|
|
|
|
return err; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
addr = ss2inet(env, &ss); |
|
|
|
|
|
|
|
return err; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if defined(__linux__) |
|
|
|
#if defined(__linux__) |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept4(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept4( |
|
|
|
jint fd, jstring addrstr, jint port, jint flags) |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port, jint flags) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_in addr; |
|
|
|
struct sockaddr_storage ss; |
|
|
|
char *str; |
|
|
|
int err; |
|
|
|
// = env->GetStringUTFChars(addrstr, NULL);
|
|
|
|
socklen_t addrlen = sizeof(struct sockaddr_storage); |
|
|
|
(*env).ReleaseStringUTFChars(addrstr, str); |
|
|
|
if ((err = zts_accept(fd, (struct sockaddr *)&ss, &addrlen, flags)) < 0) { |
|
|
|
addr.sin_addr.s_addr = inet_addr(str); |
|
|
|
return err; |
|
|
|
addr.sin_family = AF_INET; |
|
|
|
} |
|
|
|
addr.sin_port = htons(port); |
|
|
|
addr = ss2inet(env, &ss); |
|
|
|
return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); |
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_accept(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_setsockopt( |
|
|
|
jint fd, jstring addrstr, jint port) |
|
|
|
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_getsockopt( |
|
|
|
|
|
|
|
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_getsockname(JNIEnv *env, jobject thisObj, |
|
|
|
|
|
|
|
jint fd, jobject ztaddr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_in addr; |
|
|
|
struct sockaddr_in addr; |
|
|
|
// TODO: Send addr info back to Javaland
|
|
|
|
int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); |
|
|
|
addr.sin_addr.s_addr = inet_addr(""); |
|
|
|
jfieldID fid; |
|
|
|
addr.sin_family = AF_INET; |
|
|
|
jclass c = (*env).GetObjectClass(ztaddr); |
|
|
|
addr.sin_port = htons(port); |
|
|
|
if (c) { |
|
|
|
return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); |
|
|
|
fid = (*env).GetFieldID(c, "port", "I"); |
|
|
|
|
|
|
|
(*env).SetIntField(ztaddr, fid, addr.sin_port); |
|
|
|
|
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
|
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_listen(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getpeername(JNIEnv *env, jobject thisObj, |
|
|
|
jint fd, int backlog) |
|
|
|
jint fd, jobject ztaddr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return zts_listen(fd, backlog); |
|
|
|
struct sockaddr_in addr; |
|
|
|
|
|
|
|
int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); |
|
|
|
|
|
|
|
jfieldID fid; |
|
|
|
|
|
|
|
jclass c = (*env).GetObjectClass( ztaddr); |
|
|
|
|
|
|
|
if (c) { |
|
|
|
|
|
|
|
fid = (*env).GetFieldID(c, "port", "I"); |
|
|
|
|
|
|
|
(*env).SetIntField(ztaddr, fid, addr.sin_port); |
|
|
|
|
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
|
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return err; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_close(JNIEnv *env, jobject thisObj, |
|
|
|
// TODO: ZT_SOCKET_API struct hostent *zts_gethostbyname(const char *name);
|
|
|
|
jint fd) |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_close( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jint fd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return zts_close(fd); |
|
|
|
return zts_close(fd); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: ZT_SOCKET_API int ZTCALL zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl( |
|
|
|
|
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_fcntl(fd, cmd, flags); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: ZT_SOCKET_API int ZTCALL zts_ioctl(int fd, unsigned long request, void *argp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_send(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_sendto( |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_sendto( |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -341,9 +351,13 @@ namespace ZeroTier { |
|
|
|
return sent_bytes; |
|
|
|
return sent_bytes; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: ZT_SOCKET_API ssize_t ZTCALL zts_sendmsg(int fd, const struct msghdr *msg, int flags);
|
|
|
|
|
|
|
|
// TODO: ZT_SOCKET_API ssize_t ZTCALL zts_recv(int fd, void *buf, size_t len, int flags);
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_recvfrom( |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_recvfrom( |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) |
|
|
|
JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
/*
|
|
|
|
struct sockaddr_in addr; |
|
|
|
struct sockaddr_in addr; |
|
|
|
jbyte *body = (*env).GetByteArrayElements( buf, 0); |
|
|
|
jbyte *body = (*env).GetByteArrayElements( buf, 0); |
|
|
|
unsigned char buffer[ZT_SDK_MTU]; |
|
|
|
unsigned char buffer[ZT_SDK_MTU]; |
|
|
|
@ -362,17 +376,19 @@ namespace ZeroTier { |
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
} |
|
|
|
} |
|
|
|
return rxbytes; |
|
|
|
*/ |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) |
|
|
|
// TODO: ZT_SOCKET_API ssize_t ZTCALL zts_recvmsg(int fd, struct msghdr *msg,int flags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj, |
|
|
|
|
|
|
|
jint fd, jarray buf, jint len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); |
|
|
|
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); |
|
|
|
char * bufp = (char *)malloc(sizeof(char)*len); |
|
|
|
int read_bytes = read(fd, body, len); |
|
|
|
memcpy(bufp, body, len); |
|
|
|
|
|
|
|
(*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); |
|
|
|
(*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); |
|
|
|
int written_bytes = zts_write(fd, body, len); |
|
|
|
return read_bytes; |
|
|
|
return written_bytes; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_write(JNIEnv *env, jobject thisObj, |
|
|
|
@ -386,141 +402,124 @@ namespace ZeroTier { |
|
|
|
return written_bytes; |
|
|
|
return written_bytes; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_read(JNIEnv *env, jobject thisObj, |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_shutdown( |
|
|
|
jint fd, jarray buf, jint len) |
|
|
|
JNIEnv *env, jobject thisObj, int fd, int how) |
|
|
|
{ |
|
|
|
{ |
|
|
|
jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); |
|
|
|
return zts_shutdown(fd, how); |
|
|
|
int read_bytes = read(fd, body, len); |
|
|
|
|
|
|
|
(*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); |
|
|
|
|
|
|
|
return read_bytes; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_setsockopt( |
|
|
|
// TODO: ZT_SOCKET_API int ZTCALL zts_add_dns_nameserver(struct sockaddr *addr);
|
|
|
|
JNIEnv *env, jobject thisObj, |
|
|
|
// TODO: ZT_SOCKET_API int ZTCALL zts_del_dns_nameserver(struct sockaddr *addr);
|
|
|
|
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_getsockopt(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_getsockname(JNIEnv *env, jobject thisObj, |
|
|
|
// convenience function
|
|
|
|
jint fd, jobject ztaddr) |
|
|
|
jobject ss2inet(JNIEnv *env, struct sockaddr_storage *src_ss) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
jobject dest_inet; |
|
|
|
|
|
|
|
if(src_ss->ss_family == AF_INET) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_in addr; |
|
|
|
DEBUG_ERROR("converting from INET"); |
|
|
|
int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); |
|
|
|
struct sockaddr_in *in4 = (struct sockaddr_in*)src_ss; |
|
|
|
jfieldID fid; |
|
|
|
int arrlen = 4; |
|
|
|
jclass c = (*env).GetObjectClass(ztaddr); |
|
|
|
jbyteArray bytes = (*env).NewByteArray(arrlen); |
|
|
|
if (c) { |
|
|
|
jbyte *java_address_bytes; |
|
|
|
fid = (*env).GetFieldID(c, "port", "I"); |
|
|
|
java_address_bytes = (*env).GetByteArrayElements(bytes, NULL); |
|
|
|
(*env).SetIntField(ztaddr, fid, addr.sin_port); |
|
|
|
memcpy(java_address_bytes, &(in4->sin_addr.s_addr), arrlen); |
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
(*env).ReleaseByteArrayElements(bytes, java_address_bytes, 0); |
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
jclass cls = (*env).FindClass("java/net/InetAddress"); |
|
|
|
} |
|
|
|
jmethodID mid = (*env).GetStaticMethodID(cls, "getByAddress", "([B)Ljava/net/InetAddress;"); |
|
|
|
return err; |
|
|
|
dest_inet = (*env).CallStaticObjectMethod(cls, mid, bytes); |
|
|
|
|
|
|
|
(*env).DeleteLocalRef(bytes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(src_ss->ss_family == AF_INET6) |
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_getpeername(JNIEnv *env, jobject thisObj, |
|
|
|
|
|
|
|
jint fd, jobject ztaddr) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
struct sockaddr_in addr; |
|
|
|
DEBUG_ERROR("converting from INET6"); |
|
|
|
int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); |
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)src_ss; |
|
|
|
jfieldID fid; |
|
|
|
int arrlen = 16; |
|
|
|
jclass c = (*env).GetObjectClass( ztaddr); |
|
|
|
jbyteArray bytes = (*env).NewByteArray(arrlen); |
|
|
|
if (c) { |
|
|
|
(*env).SetByteArrayRegion(bytes, 0, 16, (const jbyte *)&(in6->sin6_addr)); |
|
|
|
fid = (*env).GetFieldID(c, "port", "I"); |
|
|
|
jclass cls = (*env).FindClass("java/net/InetAddress"); |
|
|
|
(*env).SetIntField(ztaddr, fid, addr.sin_port); |
|
|
|
jmethodID mid = (*env).GetStaticMethodID(cls, "getByAddress", "([B)Ljava/net/InetAddress;"); |
|
|
|
fid = (*env).GetFieldID(c,"_rawAddr", "J"); |
|
|
|
dest_inet = (*env).CallStaticObjectMethod(cls, mid, bytes); |
|
|
|
(*env).SetLongField(ztaddr, fid,addr.sin_addr.s_addr); |
|
|
|
(*env).DeleteLocalRef(bytes); |
|
|
|
} |
|
|
|
|
|
|
|
return err; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return dest_inet; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_fcntl(JNIEnv *env, jobject thisObj, |
|
|
|
|
|
|
|
jint fd, jint cmd, jint flags) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return zts_fcntl(fd,cmd,flags); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/ |
|
|
|
|
|
|
|
/* ZeroTier service controls (for JNI wrapper) */ |
|
|
|
|
|
|
|
/****************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_start(JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (path) { |
|
|
|
|
|
|
|
zts_start(env->GetStringUTFChars(path, NULL), blocking); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_startjoin(JNIEnv *env, jobject thisObj, jstring path, jstring nwid) |
|
|
|
int sockinet2ss(JNIEnv *env, jobject src_inet, struct sockaddr_storage *dest_ss) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (path && nwid) { |
|
|
|
struct sockaddr_in *in4 = (struct sockaddr_in*)dest_ss; |
|
|
|
zts_startjoin(env->GetStringUTFChars(path, NULL), env->GetStringUTFChars(nwid, NULL)); |
|
|
|
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)dest_ss; |
|
|
|
} |
|
|
|
int err = -1; |
|
|
|
} |
|
|
|
int port = 0; |
|
|
|
|
|
|
|
int socket_family = 0; |
|
|
|
|
|
|
|
socklen_t addrlen; |
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_stop(JNIEnv *env, jobject thisObj) |
|
|
|
// ---
|
|
|
|
{ |
|
|
|
|
|
|
|
zts_stop(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_running( |
|
|
|
jclass c = (*env).GetObjectClass(src_inet); |
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
if (!c) { |
|
|
|
{ |
|
|
|
return -1; |
|
|
|
return zts_running(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// get port
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_join(JNIEnv *env, jobject thisObj, jstring nwid) |
|
|
|
jmethodID getPort = (*env).GetMethodID(c, "getPort", "()I"); |
|
|
|
{ |
|
|
|
if (!getPort) { |
|
|
|
if (nwid) { |
|
|
|
return -1; |
|
|
|
zts_join(env->GetStringUTFChars(nwid, NULL)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
port = (*env).CallIntMethod(src_inet, getPort);
|
|
|
|
JNIEXPORT void JNICALL Java_zerotier_ZeroTier_leave(JNIEnv *env, jobject thisObj, jstring nwid) |
|
|
|
// get internal InetAddress
|
|
|
|
{ |
|
|
|
jobject inetaddr; |
|
|
|
if (nwid) { |
|
|
|
int family = 0; |
|
|
|
zts_leave(env->GetStringUTFChars(nwid, NULL)); |
|
|
|
jmethodID getAddress = (*env).GetMethodID(c, "getAddress", "()Ljava/net/InetAddress;"); |
|
|
|
} |
|
|
|
if (!getAddress) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
inetaddr = (*env).CallObjectMethod(src_inet, getAddress);
|
|
|
|
JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_homepath( |
|
|
|
if (!inetaddr) { |
|
|
|
JNIEnv *env, jobject thisObj) |
|
|
|
return -1; |
|
|
|
{ |
|
|
|
|
|
|
|
// TODO: fix, should copy into given arg
|
|
|
|
|
|
|
|
// return (*env).NewStringUTF(zts_get_homepath());
|
|
|
|
|
|
|
|
return (*env).NewStringUTF(""); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
jclass inetClass = (*env).GetObjectClass(inetaddr); |
|
|
|
JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_get_address( |
|
|
|
if (!inetClass) { |
|
|
|
JNIEnv *env, jobject thisObj, jstring nwid) |
|
|
|
return -1; |
|
|
|
{ |
|
|
|
|
|
|
|
// get address
|
|
|
|
|
|
|
|
const char *nwid_str = env->GetStringUTFChars(nwid, NULL); |
|
|
|
|
|
|
|
struct sockaddr_storage ss; |
|
|
|
|
|
|
|
zts_get_address(nwid_str, &ss, INET_ADDRSTRLEN); |
|
|
|
|
|
|
|
// map sockaddr_storage contents to java InetAddress
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
jclass c = (*env).FindClass("java/net/InetAddress"); |
|
|
|
|
|
|
|
if (c) { |
|
|
|
|
|
|
|
jobject addresses = (*env).NewObject(c, (*env).GetMethodID(c, "<init>", "()V")); |
|
|
|
|
|
|
|
env->CallBooleanMethod(addresses, env->GetMethodID(c, "add", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
|
|
|
|
return addresses; |
|
|
|
|
|
|
|
}*/ |
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// string representation of IP address
|
|
|
|
JNIEXPORT jint Java_zerotier_ZeroTier_get_id() |
|
|
|
jmethodID getHostAddress = (*env).GetMethodID(inetClass, "getHostAddress", "()Ljava/lang/String;"); |
|
|
|
{ |
|
|
|
jstring addrstr = (jstring)(*env).CallObjectMethod(inetaddr, getHostAddress);
|
|
|
|
return zts_get_id(NULL); // TODO
|
|
|
|
const char *addr_str = (*env).GetStringUTFChars(addrstr, NULL); |
|
|
|
|
|
|
|
for (int i=0; i<strlen(addr_str); i++) { |
|
|
|
|
|
|
|
if (addr_str[i]=='.') { |
|
|
|
|
|
|
|
DEBUG_INFO("ipv4, inet_addr"); |
|
|
|
|
|
|
|
socket_family = AF_INET; |
|
|
|
|
|
|
|
in4->sin_family = AF_INET; |
|
|
|
|
|
|
|
in4->sin_port = htons(port); |
|
|
|
|
|
|
|
in4->sin_addr.s_addr = inet_addr(addr_str); |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
if (!inet_pton(AF_INET, addr_str, &(in4->sin_addr))) { |
|
|
|
|
|
|
|
DEBUG_ERROR("error converting address %s", addr_str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
addrlen = sizeof(struct sockaddr_in); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (addr_str[i]==':') { |
|
|
|
|
|
|
|
DEBUG_INFO("ipv6"); |
|
|
|
|
|
|
|
socket_family = AF_INET6; |
|
|
|
|
|
|
|
if (!inet_pton(AF_INET6, addr_str, &(in6->sin6_addr))) {
|
|
|
|
|
|
|
|
DEBUG_ERROR("error converting address %s", addr_str); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
addrlen = sizeof(struct sockaddr_in6); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
(*env).ReleaseStringUTFChars(addrstr, addr_str); |
|
|
|
|
|
|
|
DEBUG_TEST("RESULT => %s : %d", inet_ntoa(in4->sin_addr), ntohs(in4->sin_port)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
#ifdef __cplusplus |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // SDK_JNI
|