partial implementation of android direct-call API -- still has path problems
This commit is contained in:
19
src/SDK.h
19
src/SDK.h
@@ -32,6 +32,11 @@
|
||||
#include <stdbool.h>
|
||||
#include "SDK_Signatures.h"
|
||||
|
||||
// For defining the Android direct-call API
|
||||
#if defined(__ANDROID__)
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -80,6 +85,20 @@ ssize_t zt_recvmsg(RECVMSG_SIG);
|
||||
int zt_set_nonblock(int fd);
|
||||
#endif
|
||||
|
||||
// Android JNI Direct-call API
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniSocket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniConnect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniBind(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniAccept(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniAccept4(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port, jint flags);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniListen(JNIEnv *env, jobject thisObj, jint fd, int backlog);
|
||||
//JNIEXPORT void JNICALL Java_ZeroTier_SDK_ztjniSetsockopt(JNIEnv *env, jobject thisObj);
|
||||
//JNIEXPORT void JNICALL Java_ZeroTier_SDK_ztjniGetsockopt(JNIEnv *env, jobject thisObj);
|
||||
//JNIEXPORT void JNICALL Java_ZeroTier_SDK_ztjniGetsockname(JNIEnv *env, jobject thisObj);
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniClose(JNIEnv *env, jobject thisObj, jint fd);
|
||||
#endif
|
||||
|
||||
int zt_socket(SOCKET_SIG);
|
||||
int zt_connect(CONNECT_SIG);
|
||||
int zt_bind(BIND_SIG);
|
||||
|
||||
@@ -54,6 +54,27 @@
|
||||
#define MSG_DEBUG 4 // Information which is only useful to someone debugging
|
||||
#define MSG_DEBUG_EXTRA 5 // If nothing in your world makes sense
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if __ANDROID__
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#define LOG_TAG "ZTSDK"
|
||||
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
#else
|
||||
#define LOGV(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGI(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGD(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGE(...) fprintf(stdout, __VA_ARGS__)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
//char *debug_logfile = (char*)0;
|
||||
void dwr(int level, const char *fmt, ... );
|
||||
|
||||
@@ -94,33 +115,17 @@ void dwr(int level, const char *fmt, ... )
|
||||
va_start(ap, fmt);
|
||||
fprintf(stderr, "%s [tid=%7d] ", timestring, tid);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
|
||||
// Outputs to Android debug console
|
||||
#if defined(__ANDROID__)
|
||||
LOGV(fmt, ap);
|
||||
#endif
|
||||
|
||||
fflush(stderr);
|
||||
errno = saveerr;
|
||||
va_end(ap);
|
||||
#endif // _SDK_DEBUG
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if __ANDROID__
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#define LOG_TAG "ZTSDK"
|
||||
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
#else
|
||||
#define LOGV(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGI(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGD(...) fprintf(stdout, __VA_ARGS__)
|
||||
#define LOGE(...) fprintf(stdout, __VA_ARGS__)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif //
|
||||
#endif //
|
||||
@@ -148,8 +148,9 @@ NetconEthernetTap::NetconEthernetTap(
|
||||
|
||||
_unixListenSocket = _phy.unixListen(sockPath,(void *)this);
|
||||
dwr(MSG_DEBUG, " NetconEthernetTap initialized on: %s\n", sockPath);
|
||||
//if (!_unixListenSocket)
|
||||
// throw std::runtime_error(std::string("unable to bind to ")+sockPath);
|
||||
LOGV(" NetconEthernetTap initialized on: %s\n", sockPath);
|
||||
if (!_unixListenSocket)
|
||||
LOGV("unable to bind to: %s\n", sockPath);
|
||||
_thread = Thread::start(this);
|
||||
}
|
||||
|
||||
|
||||
25
src/SDK_JNI_Java_Wapper.java
Normal file
25
src/SDK_JNI_Java_Wapper.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package ZeroTier;
|
||||
public class SDK {
|
||||
|
||||
// Loads JNI code
|
||||
static { System.loadLibrary("ZeroTierOneJNI"); }
|
||||
|
||||
// ZeroTier service controls
|
||||
public native void startOneService(String homeDir);
|
||||
public native void joinNetwork(String nwid);
|
||||
public native void leaveNetwork(String nwid);
|
||||
public native boolean isRunning();
|
||||
|
||||
// Direct-call API
|
||||
// --- These calls skip the intercept and interface directly via the RPC mechanism ---
|
||||
public native int ztjniSocket(int family, int type, int protocol);
|
||||
public native int ztjniConnect(int fd, SocketAddress addr, int addrlen);
|
||||
public native int ztjniBind(int fd, SocketAddress addr, int addrlen);
|
||||
public native int ztjniAccept4(int fd, SocketAddress addr, int addrlen);
|
||||
public native int ztjniAccept(int fd, SocketAddress addr, int addrlen, int flags);
|
||||
public native int ztjniListen(int fd, int backlog);
|
||||
//public native int ztjniGetsockopt(int fd, int type, int protocol);
|
||||
//public native int ztjniSetsockopt(int fd, int type, int protocol);
|
||||
//public native int ztjniGetsockname(int fd, int type, int protocol);
|
||||
public native int ztjniClose(int fd);
|
||||
}
|
||||
@@ -33,6 +33,11 @@
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
// For defining the Android direct-call API
|
||||
#if defined(__ANDROID__)
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
@@ -42,10 +47,13 @@
|
||||
#include <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
//#include <sys/un.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "SDK.h"
|
||||
#include "SDK_RPC.h"
|
||||
#include "SDK_Debug.h"
|
||||
|
||||
|
||||
// externs common between SDK_Intercept and SDK_Socket from SDK.h
|
||||
int (*realsocket)(SOCKET_SIG);
|
||||
@@ -109,7 +117,7 @@ int load_symbols_rpc()
|
||||
{
|
||||
#if defined(SDK_BUNDLED) || defined(__IOS__) || defined(__UNITY_3D__)
|
||||
realsocket = dlsym(RTLD_NEXT, "socket");
|
||||
realconnect = dlsym(RTLD_NEXT, "connect");
|
||||
realconnect = dlsym(RTLD_NOW, "connect");
|
||||
if(!realconnect || !realsocket)
|
||||
return -1;
|
||||
#endif
|
||||
@@ -118,6 +126,7 @@ int load_symbols_rpc()
|
||||
|
||||
int rpc_join(char * sockname)
|
||||
{
|
||||
LOGV("RPC = %s\n", sockname);
|
||||
if(sockname == NULL) {
|
||||
printf("Warning, rpc netpath is NULL\n");
|
||||
}
|
||||
@@ -129,13 +138,22 @@ int rpc_join(char * sockname)
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)-1);
|
||||
int sock;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
||||
#else
|
||||
if((sock = realsocket(AF_UNIX, SOCK_STREAM, 0)) < 0){
|
||||
fprintf(stderr, "Error while creating RPC socket\n");
|
||||
#endif
|
||||
LOGV(stderr, "Error while creating RPC socket\n");
|
||||
return -1;
|
||||
}
|
||||
while((conn_err != 0) && (attempts < SERVICE_CONNECT_ATTEMPTS)){
|
||||
if((conn_err = realconnect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
||||
fprintf(stderr, "Error while connecting to RPC socket. Re-attempting...\n");
|
||||
#if defined(__ANDROID__)
|
||||
if((conn_err = connect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
||||
#else
|
||||
if((conn_err = realconnect(sock, (struct sockaddr*)&addr, sizeof(addr))) != 0) {
|
||||
#endif
|
||||
LOGV("Error while connecting to RPC socket. Re-attempting...\n");
|
||||
sleep(1);
|
||||
}
|
||||
else
|
||||
@@ -157,9 +175,7 @@ int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
|
||||
memcpy(CANARY+CANARY_SZ, padding, sizeof(padding));
|
||||
uint64_t canary_num;
|
||||
// ephemeral RPC socket used only for this command
|
||||
printf("calling rpc_join");
|
||||
int rpc_sock = rpc_join(path);
|
||||
printf("fin\n");
|
||||
// Generate token
|
||||
int fdrand = open("/dev/urandom", O_RDONLY);
|
||||
if(read(fdrand, &CANARY, CANARY_SZ) < 0) {
|
||||
|
||||
@@ -94,7 +94,8 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
|
||||
//zt1Service->join(nwid);
|
||||
LOGV("started up\n");
|
||||
//zt_init_rpc(homeDir.c_str(), nwid); // This provides the shim API with the RPC information
|
||||
// This provides the shim API with the RPC information
|
||||
zt_init_rpc(homeDir.c_str(), nwid);
|
||||
}
|
||||
|
||||
void leave_network(const char *nwid) { zt1Service->leave(nwid); }
|
||||
@@ -175,7 +176,7 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
void *startOneService(void *thread_id) {
|
||||
#endif
|
||||
|
||||
#if defined(SDK_BUNDLED)
|
||||
#if defined(SDK_BUNDLED) && !defined(__ANDROID__)
|
||||
// Don't intercept network calls originating from ZeroTier service
|
||||
set_intercept_status(INTERCEPT_DISABLED);
|
||||
#endif
|
||||
@@ -196,11 +197,6 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
homeDir = current_dir; // homeDir shall be current dir
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
homeDir = "/sdcard/zerotier";
|
||||
join_network("565799d8f65063e5");
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
@@ -211,6 +207,15 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
/* NOTE: Since on Android devices the sdcard is formatted as fat32, we can't use this
|
||||
location to set up the RPC unix domain socket. Rather we must use the application's
|
||||
specific data directory given by getApplicationContext().getFilesDir() */
|
||||
//rpcDir = homeDir; // Take given homeDir as rpcDir
|
||||
//homeDir = "/sdcard/zerotier"; // Use fat32-formatted sdcard for writing network conf & supporting files
|
||||
//join_network("565799d8f65063e5");
|
||||
#endif
|
||||
|
||||
LOGV("homeDir = %s", homeDir.c_str());
|
||||
// Where network .conf files will be stored
|
||||
netDir = homeDir + "/networks.d";
|
||||
@@ -225,8 +230,7 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
return NULL;
|
||||
#endif
|
||||
} else {
|
||||
LOGV("constructing path...\n");
|
||||
|
||||
LOGV("startOneService(): constructing path...\n");
|
||||
std::vector<std::string> hpsp(ZeroTier::Utils::split(homeDir.c_str(),ZT_PATH_SEPARATOR_S,"",""));
|
||||
std::string ptmp;
|
||||
if (homeDir[0] == ZT_PATH_SEPARATOR)
|
||||
@@ -237,28 +241,22 @@ void zt_init_rpc(const char * path, const char * nwid);
|
||||
ptmp.append(*pi);
|
||||
if ((*pi != ".")&&(*pi != "..")) {
|
||||
if (!ZeroTier::OSUtils::mkdir(ptmp)) {
|
||||
std::string homePathErrStr = "home path does not exist, and could not create";
|
||||
throw std::runtime_error(homePathErrStr);
|
||||
LOGV("startOneService(): home path does not exist, and could not create\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//chdir(current_dir); // Return to previous current working directory (at the request of Unity3D)
|
||||
|
||||
//Debug(homeDir.c_str());
|
||||
|
||||
// Generate random port for new service instance
|
||||
unsigned int randp = 0;
|
||||
ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp));
|
||||
int servicePort = 9000 + (randp % 1000);
|
||||
|
||||
LOGV("generated port\n");
|
||||
|
||||
|
||||
for(;;) {
|
||||
zt1Service = ZeroTier::OneService::newInstance(homeDir.c_str(),servicePort);
|
||||
LOGV("created new instance\n");
|
||||
|
||||
switch(zt1Service->run()) {
|
||||
case ZeroTier::OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
||||
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
// For defining the Android direct-call API
|
||||
#if defined(__ANDROID__)
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -95,11 +100,13 @@ int (*realclose)(CLOSE_SIG);
|
||||
if(!api_netpath) {
|
||||
#if defined(SDK_BUNDLED)
|
||||
// Get the path/nwid from the user application
|
||||
// netpath = [path + "/nc_" + nwid]
|
||||
char *fullpath = malloc(strlen(path)+strlen(nwid)+1);
|
||||
if(fullpath) {
|
||||
strcpy(fullpath, path);
|
||||
strcat(fullpath, nwid);
|
||||
api_netpath = fullpath;
|
||||
//api_netpath = fullpath;
|
||||
api_netpath = "/data/data/com.example.joseph.example_app/files/zerotier/nc_565799d8f65063e5";
|
||||
}
|
||||
#else
|
||||
// Get path/nwid from environment variables
|
||||
@@ -316,6 +323,12 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int socket_family, int socket_type, int protocol
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniSocket(JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol) {
|
||||
return zt_socket(family, type, protocol);
|
||||
}
|
||||
#endif
|
||||
|
||||
int zt_socket(SOCKET_SIG) {
|
||||
get_api_netpath();
|
||||
dwr(MSG_DEBUG, "zt_socket()\n");
|
||||
@@ -355,7 +368,9 @@ int (*realclose)(CLOSE_SIG);
|
||||
#endif
|
||||
/* -1 is passed since we we're generating the new socket in this call */
|
||||
printf("path = %s\n", api_netpath);
|
||||
LOGV("path = %s\n", api_netpath);
|
||||
int err = rpc_send_command(api_netpath, RPC_SOCKET, -1, &rpc_st, sizeof(struct socket_st));
|
||||
LOGV("socket() = %s\n", err);
|
||||
dwr(MSG_DEBUG," socket() = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
@@ -365,6 +380,19 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int __fd, const struct sockaddr * __addr, socklen_t __len
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniConnect(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
char *str;
|
||||
// = env->GetStringUTFChars(addrstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, addrstr, str);
|
||||
addr.sin_addr.s_addr = inet_addr(str);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons( port );
|
||||
return zt_connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
int zt_connect(CONNECT_SIG)
|
||||
{
|
||||
get_api_netpath();
|
||||
@@ -388,6 +416,20 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int sockfd, const struct sockaddr *addr, socklen_t addrlen
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniBind(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
char *str;
|
||||
// = env->GetStringUTFChars(addrstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, addrstr, str);
|
||||
addr.sin_addr.s_addr = inet_addr(str);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons( port );
|
||||
//return zt_bind(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
int zt_bind(BIND_SIG)
|
||||
{
|
||||
@@ -413,6 +455,19 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniAccept4(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port, jint flags) {
|
||||
struct sockaddr_in addr;
|
||||
char *str;
|
||||
// = env->GetStringUTFChars(addrstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, addrstr, str);
|
||||
addr.sin_addr.s_addr = inet_addr(str);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons( port );
|
||||
return zt_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
int zt_accept4(ACCEPT4_SIG)
|
||||
{
|
||||
@@ -433,6 +488,19 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int sockfd struct sockaddr *addr, socklen_t *addrlen
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniAccept(JNIEnv *env, jobject thisObj, jint fd, jstring addrstr, jint port) {
|
||||
struct sockaddr_in addr;
|
||||
char *str;
|
||||
// = env->GetStringUTFChars(addrstr, NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, addrstr, str);
|
||||
addr.sin_addr.s_addr = inet_addr(str);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons( port );
|
||||
return zt_accept(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
int zt_accept(ACCEPT_SIG)
|
||||
{
|
||||
get_api_netpath();
|
||||
@@ -458,6 +526,12 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int sockfd, int backlog
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniListen(JNIEnv *env, jobject thisObj, jint fd, int backlog) {
|
||||
return zt_listen(fd, backlog);
|
||||
}
|
||||
#endif
|
||||
|
||||
int zt_listen(LISTEN_SIG)
|
||||
{
|
||||
get_api_netpath();
|
||||
@@ -480,6 +554,12 @@ int (*realclose)(CLOSE_SIG);
|
||||
// ------------------------------------------------------------------------------
|
||||
// int fd
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_ztjniClose(JNIEnv *env, jobject thisObj, jint fd) {
|
||||
return zt_close(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
int zt_close(CLOSE_SIG) {
|
||||
get_api_netpath();
|
||||
dwr(MSG_DEBUG, "zt_close(%d)\n", fd);
|
||||
|
||||
Reference in New Issue
Block a user