Added ZTS_ERR_GENERAL, also minor updates to JNI layer
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/Sockets.cpp
108
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(
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user