Merge refactored dev into master
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
#ifndef ZT_CENTRAL_H
|
||||
#define ZT_CENTRAL_H
|
||||
|
||||
#ifdef CENTRAL_API
|
||||
#ifdef ZTS_ENABLE_CENTRAL_API
|
||||
|
||||
#include <stdio.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
@@ -25,15 +25,16 @@
|
||||
#include "Mutex.hpp"
|
||||
#include "OSUtils.hpp"
|
||||
|
||||
#include "ZeroTierSockets.h"
|
||||
#include "Debug.hpp"
|
||||
#include "NodeService.hpp"
|
||||
#include "VirtualTap.hpp"
|
||||
#include "Events.hpp"
|
||||
#include "ZeroTierSockets.h"
|
||||
#include "Signals.hpp"
|
||||
|
||||
using namespace ZeroTier;
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
@@ -46,13 +47,20 @@ namespace ZeroTier
|
||||
{
|
||||
extern NodeService *service;
|
||||
extern Mutex serviceLock;
|
||||
extern void (*_userEventCallbackFunc)(void *);
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
|
||||
#endif
|
||||
#ifdef ZTS_ENABLE_PINVOKE
|
||||
extern void (*_userEventCallback)(void *);
|
||||
#endif
|
||||
#ifdef ZTS_C_API_ONLY
|
||||
extern void (*_userEventCallback)(void *);
|
||||
#endif
|
||||
extern uint8_t allowNetworkCaching;
|
||||
extern uint8_t allowPeerCaching;
|
||||
extern uint8_t allowLocalConf;
|
||||
extern uint8_t disableLocalStorage; // Off by default
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
// References to JNI objects and VM kept for future callbacks
|
||||
JavaVM *jvm = NULL;
|
||||
jobject objRef = NULL;
|
||||
@@ -110,10 +118,15 @@ int zts_get_node_identity(char *key_pair_str, uint16_t *key_buf_len)
|
||||
}
|
||||
|
||||
// TODO: This logic should be further generalized in the next API redesign
|
||||
#ifdef ZTS_PINVOKE
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
|
||||
PythonDirectorCallbackClass *callback, uint16_t port)
|
||||
#endif
|
||||
#ifdef ZTS_ENABLE_PINVOKE
|
||||
int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
|
||||
CppCallback callback, uint16_t port)
|
||||
#else
|
||||
#endif
|
||||
#ifdef ZTS_C_API_ONLY
|
||||
int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
|
||||
void (*callback)(void *), uint16_t port)
|
||||
#endif
|
||||
@@ -122,6 +135,9 @@ int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
Mutex::Lock _l(serviceLock);
|
||||
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
_install_signal_handlers();
|
||||
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
_lwip_driver_init();
|
||||
if (service || _getState(ZTS_STATE_NODE_RUNNING)) {
|
||||
// Service is already initialized
|
||||
@@ -132,11 +148,7 @@ int zts_start_with_identity(const char *key_pair_str, uint16_t key_buf_len,
|
||||
// an application restart is required now
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
_userEventCallbackFunc = callback;
|
||||
#else
|
||||
_userEventCallbackFunc = callback;
|
||||
#endif
|
||||
_userEventCallback = callback;
|
||||
if (!_isCallbackRegistered()) {
|
||||
// Must have a callback
|
||||
return ZTS_ERR_ARG;
|
||||
@@ -231,13 +243,20 @@ int zts_disable_local_storage(uint8_t disabled)
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
|
||||
#ifdef ZTS_PINVOKE
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
int zts_start(const char *path, PythonDirectorCallbackClass *callback, uint16_t port)
|
||||
#endif
|
||||
#ifdef ZTS_ENABLE_PINVOKE
|
||||
int zts_start(const char *path, CppCallback callback, uint16_t port)
|
||||
#else
|
||||
#endif
|
||||
#ifdef ZTS_C_API_ONLY
|
||||
int zts_start(const char *path, void (*callback)(void *), uint16_t port)
|
||||
#endif
|
||||
{
|
||||
Mutex::Lock _l(serviceLock);
|
||||
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
_install_signal_handlers();
|
||||
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
_lwip_driver_init();
|
||||
if (service || _getState(ZTS_STATE_NODE_RUNNING)) {
|
||||
// Service is already initialized
|
||||
@@ -248,11 +267,7 @@ int zts_start(const char *path, void (*callback)(void *), uint16_t port)
|
||||
// an application restart is required now
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
_userEventCallbackFunc = callback;
|
||||
#else
|
||||
_userEventCallbackFunc = callback;
|
||||
#endif
|
||||
_userEventCallback = callback;
|
||||
if (!_isCallbackRegistered()) {
|
||||
// Must have a callback
|
||||
return ZTS_ERR_ARG;
|
||||
@@ -300,7 +315,7 @@ int zts_start(const char *path, void (*callback)(void *), uint16_t port)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_start(
|
||||
JNIEnv *env, jobject thisObj, jstring path, jobject callback, jint port)
|
||||
{
|
||||
@@ -344,7 +359,7 @@ int zts_stop()
|
||||
}
|
||||
return ZTS_ERR_SERVICE;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop(
|
||||
JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
@@ -357,11 +372,8 @@ int zts_restart()
|
||||
{
|
||||
serviceLock.lock();
|
||||
// Store callback references
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
static jmethodID _tmpUserCallbackMethodRef = _userCallbackMethodRef;
|
||||
#else
|
||||
void (*_tmpUserEventCallbackFunc)(void *);
|
||||
_tmpUserEventCallbackFunc = _userEventCallbackFunc;
|
||||
#endif
|
||||
int userProvidedPort = 0;
|
||||
std::string userProvidedPath;
|
||||
@@ -388,15 +400,14 @@ int zts_restart()
|
||||
}
|
||||
/* Some of the logic in Java_com_zerotier_libzt_ZeroTier_start
|
||||
is replicated here */
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
_userCallbackMethodRef = _tmpUserCallbackMethodRef;
|
||||
return zts_start(userProvidedPath.c_str(), NULL, userProvidedPort);
|
||||
#else
|
||||
return ZTS_ERR_OK;
|
||||
//return zts_start(userProvidedPath.c_str(), _tmpUserEventCallbackFunc, userProvidedPort);
|
||||
return ZTS_ERR_OK;
|
||||
#endif
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_restart(
|
||||
JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
@@ -415,7 +426,7 @@ int zts_free()
|
||||
_lwip_driver_shutdown();
|
||||
return err;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
|
||||
JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
@@ -423,7 +434,7 @@ JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
/*
|
||||
* Called from Java, saves a static reference to the VM so it can be used
|
||||
* later to call a user-specified callback method from C.
|
||||
@@ -431,7 +442,7 @@ JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free(
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_init(
|
||||
JNIEnv *env, jobject thisObj)
|
||||
{
|
||||
jint rs = env->GetJavaVM(&jvm);
|
||||
jint rs = env->GetJavaVM(&jvm);
|
||||
return rs != JNI_OK ? ZTS_ERR_GENERAL : ZTS_ERR_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -447,7 +458,7 @@ int zts_join(const uint64_t networkId)
|
||||
}
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join(
|
||||
JNIEnv *env, jobject thisObj, jlong networkId)
|
||||
{
|
||||
@@ -466,7 +477,7 @@ int zts_leave(const uint64_t networkId)
|
||||
}
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave(
|
||||
JNIEnv *env, jobject thisObj, jlong networkId)
|
||||
{
|
||||
@@ -485,7 +496,7 @@ int zts_orbit(uint64_t moonWorldId, uint64_t moonSeed)
|
||||
}
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
int zts_deorbit(uint64_t moonWorldId)
|
||||
@@ -499,7 +510,7 @@ int zts_deorbit(uint64_t moonWorldId)
|
||||
}
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
int zts_get_6plane_addr(struct zts_sockaddr_storage *addr, const uint64_t networkId, const uint64_t nodeId)
|
||||
@@ -542,14 +553,14 @@ uint64_t zts_generate_adhoc_nwid_from_range(uint16_t startPortOfRange, uint16_t
|
||||
void zts_delay_ms(long milliseconds)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
Sleep(milliseconds);
|
||||
Sleep(milliseconds);
|
||||
#elif _POSIX_C_SOURCE >= 199309L
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
#else
|
||||
usleep(milliseconds * 1000);
|
||||
usleep(milliseconds * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "concurrentqueue.h"
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,15 @@
|
||||
#define ROUTE_EVENT_TYPE(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED
|
||||
#define ADDR_EVENT_TYPE(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
#include "Python.h"
|
||||
PythonDirectorCallbackClass *_userEventCallback = NULL;
|
||||
void PythonDirectorCallbackClass::on_zerotier_event(struct zts_callback_msg *msg) { }
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
extern NodeService *service;
|
||||
@@ -50,7 +59,12 @@ uint8_t _serviceStateFlags;
|
||||
// Lock to guard access to callback function pointers.
|
||||
Mutex _callbackLock;
|
||||
|
||||
void (*_userEventCallbackFunc)(void *);
|
||||
#ifdef ZTS_ENABLE_PINVOKE
|
||||
void (*_userEventCallback)(void *);
|
||||
#endif
|
||||
#ifdef ZTS_C_API_ONLY
|
||||
void (*_userEventCallback)(void *);
|
||||
#endif
|
||||
|
||||
moodycamel::ConcurrentQueue<struct zts_callback_msg*> _callbackMsgQueue;
|
||||
|
||||
@@ -100,7 +114,12 @@ void _freeEvent(struct zts_callback_msg *msg)
|
||||
void _passDequeuedEventToUser(struct zts_callback_msg *msg)
|
||||
{
|
||||
bool bShouldStopCallbackThread = (msg->eventCode == ZTS_EVENT_STACK_DOWN);
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
PyGILState_STATE state = PyGILState_Ensure();
|
||||
_userEventCallback->on_zerotier_event(msg);
|
||||
PyGILState_Release(state);
|
||||
#endif
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
if(_userCallbackMethodRef) {
|
||||
JNIEnv *env;
|
||||
#if defined(__ANDROID__)
|
||||
@@ -121,14 +140,19 @@ void _passDequeuedEventToUser(struct zts_callback_msg *msg)
|
||||
id = msg->peer ? msg->peer->address : 0;
|
||||
}
|
||||
env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->eventCode);
|
||||
_freeEvent(msg);
|
||||
}
|
||||
#else
|
||||
if (_userEventCallbackFunc) {
|
||||
_userEventCallbackFunc(msg);
|
||||
_freeEvent(msg);
|
||||
#endif // ZTS_ENABLE_JAVA
|
||||
#ifdef ZTS_ENABLE_PINVOKE
|
||||
if (_userEventCallback) {
|
||||
_userEventCallback(msg);
|
||||
}
|
||||
#endif
|
||||
#ifdef ZTS_C_API_ONLY
|
||||
if (_userEventCallback) {
|
||||
_userEventCallback(msg);
|
||||
}
|
||||
#endif
|
||||
_freeEvent(msg);
|
||||
if (bShouldStopCallbackThread) {
|
||||
/* Ensure last possible callback ZTS_EVENT_STACK_DOWN is
|
||||
delivered before callback thread is finally stopped. */
|
||||
@@ -140,10 +164,10 @@ bool _isCallbackRegistered()
|
||||
{
|
||||
_callbackLock.lock();
|
||||
bool retval = false;
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
retval = (jvm && objRef && _userCallbackMethodRef);
|
||||
#else
|
||||
retval = _userEventCallbackFunc;
|
||||
retval = _userEventCallback;
|
||||
#endif
|
||||
_callbackLock.unlock();
|
||||
return retval;
|
||||
@@ -152,11 +176,11 @@ bool _isCallbackRegistered()
|
||||
void _clearRegisteredCallback()
|
||||
{
|
||||
_callbackLock.lock();
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
objRef = NULL;
|
||||
_userCallbackMethodRef = NULL;
|
||||
#else
|
||||
_userEventCallbackFunc = NULL;
|
||||
_userEventCallback = NULL;
|
||||
#endif
|
||||
_callbackLock.unlock();
|
||||
}
|
||||
@@ -237,7 +261,7 @@ void *_runCallbacks(void *thread_id)
|
||||
}
|
||||
zts_delay_ms(ZTS_CALLBACK_PROCESSING_INTERVAL);
|
||||
}
|
||||
#if SDK_JNI
|
||||
#if ZTS_ENABLE_JAVA
|
||||
JNIEnv *env;
|
||||
jint rs = jvm->DetachCurrentThread();
|
||||
pthread_exit(0);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <BaseTsd.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#include <jni.h>
|
||||
#endif
|
||||
namespace ZeroTier {
|
||||
@@ -40,7 +40,7 @@ namespace ZeroTier {
|
||||
#define ZTS_STATE_CALLBACKS_RUNNING 0x08
|
||||
#define ZTS_STATE_FREE_CALLED 0x10
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
// References to JNI objects and VM kept for future callbacks
|
||||
extern JavaVM *jvm;
|
||||
extern jobject objRef;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#define stat _stat
|
||||
#endif
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
|
||||
70
src/Signals.cpp
Normal file
70
src/Signals.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c)2013-2021 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2025-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Custom signal handler
|
||||
*/
|
||||
|
||||
#include "ZeroTierSockets.h"
|
||||
#include "Signals.hpp"
|
||||
|
||||
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
|
||||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
#include <cstdlib>
|
||||
|
||||
void _signal_handler(int signal)
|
||||
{
|
||||
/*
|
||||
switch(signal)
|
||||
{
|
||||
case SIGINT:
|
||||
fprintf(stderr, "SIGINT\n");
|
||||
break;
|
||||
case SIGABRT:
|
||||
fprintf(stderr, "SIGABRT\n");
|
||||
break;
|
||||
case SIGILL:
|
||||
fprintf(stderr, "SIGILL\n");
|
||||
break;
|
||||
case SIGSEGV:
|
||||
fprintf(stderr, "SIGSEGV\n");
|
||||
break;
|
||||
case SIGFPE:
|
||||
fprintf(stderr, "SIGFPE\n");
|
||||
break;
|
||||
case SIGTERM:
|
||||
default:
|
||||
fprintf(stderr, "SIGTERM\n");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
exit(signal);
|
||||
}
|
||||
|
||||
void _install_signal_handlers()
|
||||
{
|
||||
signal(SIGINT, &_signal_handler);
|
||||
/*
|
||||
signal(SIGABRT, &_signal_handler);
|
||||
signal(SIGFPE, &_signal_handler);
|
||||
signal(SIGILL, &_signal_handler);
|
||||
signal(SIGSEGV, &_signal_handler);
|
||||
signal(SIGTERM, &_signal_handler);
|
||||
*/
|
||||
}
|
||||
|
||||
#endif
|
||||
37
src/Signals.hpp
Normal file
37
src/Signals.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c)2013-2021 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2025-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Custom signal handler
|
||||
*/
|
||||
|
||||
#ifndef SIGNALS_HPP
|
||||
#define SIGNALS_HPP
|
||||
|
||||
#ifdef ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void _signal_handler(int signal);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void _install_signal_handlers();
|
||||
|
||||
#endif // ZTS_ENABLE_CUSTOM_SIGNAL_HANDLERS
|
||||
|
||||
#endif // _H
|
||||
108
src/Sockets.cpp
108
src/Sockets.cpp
@@ -23,15 +23,14 @@
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "ZeroTierSockets.h"
|
||||
//#include "Events.hpp"
|
||||
|
||||
#define ZTS_STATE_NODE_RUNNING 0x01
|
||||
#define ZTS_STATE_STACK_RUNNING 0x02
|
||||
#define ZTS_STATE_NET_SERVICE_RUNNING 0x04
|
||||
#define ZTS_STATE_CALLBACKS_RUNNING 0x08
|
||||
#define ZTS_STATE_FREE_CALLED 0x10
|
||||
#define ZTS_STATE_NODE_RUNNING 0x01
|
||||
#define ZTS_STATE_STACK_RUNNING 0x02
|
||||
#define ZTS_STATE_NET_SERVICE_RUNNING 0x04
|
||||
#define ZTS_STATE_CALLBACKS_RUNNING 0x08
|
||||
#define ZTS_STATE_FREE_CALLED 0x10
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#include <jni.h>
|
||||
#endif
|
||||
|
||||
@@ -45,7 +44,7 @@ extern uint8_t _serviceStateFlags;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
void ss2zta(JNIEnv *env, struct zts_sockaddr_storage *ss, jobject addr);
|
||||
void zta2ss(JNIEnv *env, struct zts_sockaddr_storage *ss, jobject addr);
|
||||
void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, zts_fd_set *dest_fd_set);
|
||||
@@ -59,7 +58,7 @@ int zts_socket(const int socket_family, const int socket_type, const int protoco
|
||||
}
|
||||
return lwip_socket(socket_family, socket_type, protocol);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_socket(
|
||||
JNIEnv *env, jobject thisObj, jint family, jint type, jint protocol)
|
||||
{
|
||||
@@ -81,7 +80,7 @@ int zts_connect(int fd, const struct zts_sockaddr *addr, zts_socklen_t addrlen)
|
||||
}
|
||||
return lwip_connect(fd, (sockaddr*)addr, addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_connect(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jobject addr)
|
||||
{
|
||||
@@ -106,7 +105,8 @@ int zts_bind(int fd, const struct zts_sockaddr *addr, zts_socklen_t addrlen)
|
||||
}
|
||||
return lwip_bind(fd, (sockaddr*)addr, addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_bind(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jobject addr)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ int zts_listen(int fd, int backlog)
|
||||
}
|
||||
return lwip_listen(fd, backlog);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_listen(
|
||||
JNIEnv *env, jobject thisObj, jint fd, int backlog)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ int zts_accept(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
}
|
||||
return lwip_accept(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port)
|
||||
{
|
||||
@@ -162,7 +162,7 @@ int zts_accept4(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen, int f
|
||||
return ZTS_ERR_SERVICE; // TODO
|
||||
}
|
||||
#endif
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#if defined(__linux__)
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept4(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jobject addr, jint port, jint flags)
|
||||
@@ -183,7 +183,7 @@ int zts_setsockopt(int fd, int level, int optname, const void *optval,zts_sockle
|
||||
}
|
||||
return lwip_setsockopt(fd, level, optname, optval, optlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval)
|
||||
{
|
||||
@@ -236,7 +236,7 @@ int zts_getsockopt(int fd, int level, int optname, void *optval, zts_socklen_t *
|
||||
}
|
||||
return lwip_getsockopt(fd, level, optname, optval, (socklen_t*)optlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jint level, jint optname, jobject optval)
|
||||
{
|
||||
@@ -259,7 +259,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt(
|
||||
else {
|
||||
retval = zts_getsockopt(fd, level, optname, &optval_int, &optlen);
|
||||
}
|
||||
|
||||
|
||||
if (optname == SO_BROADCAST
|
||||
|| optname == SO_KEEPALIVE
|
||||
|| optname == SO_REUSEADDR
|
||||
@@ -300,14 +300,14 @@ int zts_getsockname(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
}
|
||||
return lwip_getsockname(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_getsockname(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject addr)
|
||||
{
|
||||
struct zts_sockaddr_storage ss;
|
||||
zts_socklen_t addrlen = sizeof(struct zts_sockaddr_storage);
|
||||
int retval = zts_getsockname(fd, (struct zts_sockaddr *)&ss, &addrlen);
|
||||
ss2zta(env, &ss, addr);
|
||||
ss2zta(env, &ss, addr);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -325,13 +325,13 @@ int zts_getpeername(int fd, struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
}
|
||||
return lwip_getpeername(fd, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getpeername(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jobject addr)
|
||||
{
|
||||
struct zts_sockaddr_storage ss;
|
||||
int retval = zts_getpeername(fd, (struct zts_sockaddr *)&ss, (zts_socklen_t*)sizeof(struct zts_sockaddr_storage));
|
||||
ss2zta(env, &ss, addr);
|
||||
ss2zta(env, &ss, addr);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -343,7 +343,7 @@ int zts_close(int fd)
|
||||
}
|
||||
return lwip_close(fd);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_close(
|
||||
JNIEnv *env, jobject thisObj, jint fd)
|
||||
{
|
||||
@@ -359,7 +359,7 @@ int zts_select(int nfds, zts_fd_set *readfds, zts_fd_set *writefds, zts_fd_set *
|
||||
}
|
||||
return lwip_select(nfds, (fd_set*)readfds, (fd_set*)writefds, (fd_set*)exceptfds, (timeval*)timeout);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_select(JNIEnv *env, jobject thisObj,
|
||||
jint nfds, jobject readfds, jobject writefds, jobject exceptfds, jint timeout_sec, jint timeout_usec)
|
||||
{
|
||||
@@ -391,7 +391,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_select(JNIEnv *env, jobj
|
||||
}
|
||||
if (exceptfds) {
|
||||
fdset2ztfdset(env, nfds, &_exceptfds, exceptfds);
|
||||
}
|
||||
}
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -403,7 +403,7 @@ int zts_fcntl(int fd, int cmd, int flags)
|
||||
}
|
||||
return lwip_fcntl(fd, cmd, flags);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_fcntl(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jint cmd, jint flags)
|
||||
{
|
||||
@@ -431,14 +431,14 @@ int zts_ioctl(int fd, unsigned long request, void *argp)
|
||||
}
|
||||
return lwip_ioctl(fd, request, argp);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jlong request, jobject argp)
|
||||
{
|
||||
int retval = ZTS_ERR_OK;
|
||||
if (request == FIONREAD) {
|
||||
int bytesRemaining = 0;
|
||||
retval = zts_ioctl(fd, request, &bytesRemaining);
|
||||
retval = zts_ioctl(fd, request, &bytesRemaining);
|
||||
// set value in general object
|
||||
jclass c = env->GetObjectClass(argp);
|
||||
if (!c) {
|
||||
@@ -450,7 +450,7 @@ JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl(
|
||||
if (request == FIONBIO) {
|
||||
// TODO: double check
|
||||
int meaninglessVariable = 0;
|
||||
retval = zts_ioctl(fd, request, &meaninglessVariable);
|
||||
retval = zts_ioctl(fd, request, &meaninglessVariable);
|
||||
}
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
@@ -466,18 +466,18 @@ ssize_t zts_send(int fd, const void *buf, size_t len, int flags)
|
||||
}
|
||||
return lwip_send(fd, buf, len, flags);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_send(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, int flags)
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_send(fd, data, env->GetArrayLength(buf), flags);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags,
|
||||
ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags,
|
||||
const struct zts_sockaddr *addr,zts_socklen_t addrlen)
|
||||
{
|
||||
if (!addr || !buf) {
|
||||
@@ -491,7 +491,7 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags,
|
||||
}
|
||||
return lwip_sendto(fd, buf, len, flags, (sockaddr*)addr, addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_sendto(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint flags, jobject addr)
|
||||
{
|
||||
@@ -500,7 +500,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_sendto(
|
||||
zta2ss(env, &ss, addr);
|
||||
zts_socklen_t addrlen = ss.ss_family == ZTS_AF_INET ? sizeof(struct zts_sockaddr_in) : sizeof(struct zts_sockaddr_in6);
|
||||
int retval = zts_sendto(fd, data, env->GetArrayLength(buf), flags, (struct zts_sockaddr *)&ss, addrlen);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -512,7 +512,7 @@ ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags)
|
||||
}
|
||||
return lwip_sendmsg(fd, msg, flags);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
ssize_t zts_recv(int fd, void *buf, size_t len, int flags)
|
||||
@@ -525,7 +525,7 @@ ssize_t zts_recv(int fd, void *buf, size_t len, int flags)
|
||||
}
|
||||
return lwip_recv(fd, buf, len, flags);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recv(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jbyteArray buf, jint flags)
|
||||
{
|
||||
@@ -536,7 +536,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recv(JNIEnv *env, jobjec
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
struct zts_sockaddr *addr, zts_socklen_t *addrlen)
|
||||
{
|
||||
if (!buf) {
|
||||
@@ -547,7 +547,7 @@ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags,
|
||||
}
|
||||
return lwip_recvfrom(fd, buf, len, flags, (sockaddr*)addr, (socklen_t*)addrlen);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recvfrom(
|
||||
JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint flags, jobject addr)
|
||||
{
|
||||
@@ -556,7 +556,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recvfrom(
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_recvfrom(fd, data, env->GetArrayLength(buf), flags, (struct zts_sockaddr *)&ss, &addrlen);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
ss2zta(env, &ss, addr);
|
||||
ss2zta(env, &ss, addr);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -572,7 +572,7 @@ ssize_t zts_recvmsg(int fd, struct msghdr *msg, int flags)
|
||||
}
|
||||
return lwip_recvmsg(fd, msg, flags);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
ssize_t zts_read(int fd, void *buf, size_t len)
|
||||
@@ -596,13 +596,13 @@ ssize_t zts_read_offset(int fd, void *buf, size_t offset, size_t len)
|
||||
char *cbuf = (char*)buf;
|
||||
return lwip_read(fd, &(cbuf[offset]), len);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jbyteArray buf)
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_read(fd, data, env->GetArrayLength(buf));
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read_1offset(JNIEnv *env, jobject thisObj,
|
||||
@@ -610,7 +610,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read_1offset(JNIEnv *env
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_read_offset(fd, data, offset, len);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read_1length(JNIEnv *env, jobject thisObj,
|
||||
@@ -618,7 +618,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read_1length(JNIEnv *env
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_read(fd, data, len);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
#endif
|
||||
@@ -642,13 +642,13 @@ ssize_t zts_write(int fd, const void *buf, size_t len)
|
||||
}
|
||||
return lwip_write(fd, buf, len);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write__IB(JNIEnv *env, jobject thisObj,
|
||||
jint fd, jbyteArray buf)
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(buf, NULL);
|
||||
int retval = zts_write(fd, data, env->GetArrayLength(buf));
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write_1offset(JNIEnv *env, jobject thisObj,
|
||||
@@ -656,7 +656,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write_1offset(JNIEnv *en
|
||||
{
|
||||
void *data = env->GetPrimitiveArrayCritical(&(buf[offset]), NULL); // PENDING: check?
|
||||
int retval = zts_write(fd, data, len);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
env->ReleasePrimitiveArrayCritical(buf, data, 0);
|
||||
return retval > -1 ? retval : -(zts_errno);
|
||||
}
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write_1byte(JNIEnv *env, jobject thisObj,
|
||||
@@ -683,7 +683,7 @@ int zts_shutdown(int fd, int how)
|
||||
}
|
||||
return lwip_shutdown(fd, how);
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_shutdown(
|
||||
JNIEnv *env, jobject thisObj, int fd, int how)
|
||||
{
|
||||
@@ -698,7 +698,7 @@ int zts_add_dns_nameserver(struct zts_sockaddr *addr)
|
||||
}
|
||||
return ZTS_ERR_SERVICE; // TODO
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
int zts_del_dns_nameserver(struct zts_sockaddr *addr)
|
||||
@@ -708,7 +708,7 @@ int zts_del_dns_nameserver(struct zts_sockaddr *addr)
|
||||
}
|
||||
return ZTS_ERR_SERVICE; // TODO
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
#endif
|
||||
|
||||
uint16_t zts_htons(uint16_t n)
|
||||
@@ -750,6 +750,8 @@ uint32_t zts_inet_addr(const char *cp)
|
||||
// Statistics //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef ZTS_ENABLE_STATS
|
||||
|
||||
extern struct stats_ lwip_stats;
|
||||
|
||||
int zts_get_all_stats(struct zts_stats *statsDest)
|
||||
@@ -785,7 +787,7 @@ int zts_get_all_stats(struct zts_stats *statsDest)
|
||||
return ZTS_ERR_NO_RESULT;
|
||||
#endif
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
// No implementation for JNI
|
||||
#endif
|
||||
|
||||
@@ -836,7 +838,7 @@ int zts_get_protocol_stats(int protocolType, void *protoStatsDest)
|
||||
return ZTS_ERR_NO_RESULT;
|
||||
#endif
|
||||
}
|
||||
#ifdef SDK_JNI
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1protocol_1stats(
|
||||
JNIEnv *env, jobject thisObj, jint protocolType, jobject protoStatsObj)
|
||||
{
|
||||
@@ -876,7 +878,9 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1protocol_1stats(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDK_JNI
|
||||
#endif // ZTS_ENABLE_STATS
|
||||
|
||||
#ifdef ZTS_ENABLE_JAVA
|
||||
void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, zts_fd_set *dest_fd_set)
|
||||
{
|
||||
jclass c = env->GetObjectClass(src_ztfd_set);
|
||||
|
||||
166
src/bindings/python/PythonSockets.cpp
Normal file
166
src/bindings/python/PythonSockets.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c)2013-2021 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2025-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ZeroTier Socket API (Python)
|
||||
*/
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "ZeroTierSockets.h"
|
||||
|
||||
#ifdef ZTS_ENABLE_PYTHON
|
||||
|
||||
int zts_py_setblocking(int fd, int flag)
|
||||
{
|
||||
int flags = ZTS_ERR_OK;
|
||||
if ((flags = zts_fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
return ZTS_ERR_SOCKET;
|
||||
}
|
||||
return zts_fcntl(fd, F_SETFL, flags | ZTS_O_NONBLOCK);
|
||||
}
|
||||
|
||||
int zts_py_getblocking(int fd)
|
||||
{
|
||||
int flags = ZTS_ERR_OK;
|
||||
if ((flags = zts_fcntl(fd, F_GETFL, 0)) < 0) {
|
||||
return ZTS_ERR_SOCKET;
|
||||
}
|
||||
return flags & ZTS_O_NONBLOCK;
|
||||
}
|
||||
|
||||
static int zts_py_tuple_to_sockaddr(int family,
|
||||
PyObject *addr_obj, struct zts_sockaddr *dst_addr, int *addrlen)
|
||||
{
|
||||
if (family == AF_INET) {
|
||||
struct zts_sockaddr_in* addr;
|
||||
char *host_str;
|
||||
int result, port;
|
||||
if (!PyTuple_Check(addr_obj)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (!PyArg_ParseTuple(addr_obj,
|
||||
"eti:zts_py_tuple_to_sockaddr", "idna", &host_str, &port)) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
addr = (struct zts_sockaddr_in*)dst_addr;
|
||||
addr->sin_addr.s_addr = zts_inet_addr(host_str);
|
||||
PyMem_Free(host_str);
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
if (result < 0) {
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = htons((short)port);
|
||||
*addrlen = sizeof *addr;
|
||||
return ZTS_ERR_OK;
|
||||
}
|
||||
if (family == AF_INET6) {
|
||||
// TODO
|
||||
}
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
|
||||
PyObject * zts_py_accept(int fd)
|
||||
{
|
||||
struct zts_sockaddr_in addrbuf;
|
||||
socklen_t addrlen = sizeof(addrbuf);
|
||||
memset(&addrbuf, 0, addrlen);
|
||||
int err = zts_accept(fd, (struct zts_sockaddr*)&addrbuf, &addrlen);
|
||||
char ipstr[ZTS_INET_ADDRSTRLEN];
|
||||
memset(ipstr, 0, sizeof(ipstr));
|
||||
zts_inet_ntop(ZTS_AF_INET, &(addrbuf.sin_addr), ipstr, ZTS_INET_ADDRSTRLEN);
|
||||
PyObject *t;
|
||||
t = PyTuple_New(3);
|
||||
PyTuple_SetItem(t, 0, PyLong_FromLong(err)); // New file descriptor
|
||||
PyTuple_SetItem(t, 1, PyUnicode_FromString(ipstr));
|
||||
PyTuple_SetItem(t, 2, PyLong_FromLong(zts_ntohs(addrbuf.sin_port)));
|
||||
Py_INCREF(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
int zts_py_listen(int fd, int backlog)
|
||||
{
|
||||
return zts_listen(fd, backlog);
|
||||
}
|
||||
|
||||
int zts_py_bind(int fd, int family, int type, PyObject *addr_obj)
|
||||
{
|
||||
struct zts_sockaddr_storage addrbuf;
|
||||
int addrlen;
|
||||
int err;
|
||||
if (zts_py_tuple_to_sockaddr(family, addr_obj,
|
||||
(struct zts_sockaddr *)&addrbuf, &addrlen) != ZTS_ERR_OK)
|
||||
{
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = zts_bind(fd, (struct zts_sockaddr *)&addrbuf, addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
Py_INCREF(Py_None);
|
||||
return err;
|
||||
}
|
||||
|
||||
int zts_py_connect(int fd, int family, int type, PyObject *addr_obj)
|
||||
{
|
||||
struct zts_sockaddr_storage addrbuf;
|
||||
int addrlen;
|
||||
int err;
|
||||
if (zts_py_tuple_to_sockaddr(family, addr_obj,
|
||||
(struct zts_sockaddr *)&addrbuf, &addrlen) != ZTS_ERR_OK)
|
||||
{
|
||||
return ZTS_ERR_ARG;
|
||||
}
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = zts_connect(fd, (struct zts_sockaddr *)&addrbuf, addrlen);
|
||||
Py_END_ALLOW_THREADS
|
||||
Py_INCREF(Py_None);
|
||||
return err;
|
||||
}
|
||||
|
||||
PyObject * zts_py_recv(int fd, int len, int flags)
|
||||
{
|
||||
PyObject *t;
|
||||
char buf[4096];
|
||||
int err = zts_recv(fd, buf, len, flags);
|
||||
if (err < 0) {
|
||||
return NULL;
|
||||
}
|
||||
t = PyTuple_New(2);
|
||||
PyTuple_SetItem(t, 0, PyLong_FromLong(err));
|
||||
PyTuple_SetItem(t, 1, PyUnicode_FromString(buf));
|
||||
Py_INCREF(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
int zts_py_send(int fd, PyObject *buf, int len, int flags)
|
||||
{
|
||||
int err = ZTS_ERR_OK;
|
||||
PyObject *encodedStr = PyUnicode_AsEncodedString(buf, "UTF-8", "strict");
|
||||
if (encodedStr) {
|
||||
char *bytes = PyBytes_AsString(encodedStr);
|
||||
err = zts_send(fd, bytes, len, flags);
|
||||
Py_DECREF(encodedStr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int zts_py_close(int fd)
|
||||
{
|
||||
return zts_close(fd);
|
||||
}
|
||||
|
||||
#endif // ZTS_ENABLE_PYTHON
|
||||
4
src/bindings/python/README.md
Normal file
4
src/bindings/python/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Python Language Bindings
|
||||
|
||||
- Install (via [PyPI package](https://pypi.org/project/libzt/)): `pip install libzt`
|
||||
- Example usage: [examples/python](./../../../examples/python/)
|
||||
408
src/bindings/python/sockets.py
Normal file
408
src/bindings/python/sockets.py
Normal file
@@ -0,0 +1,408 @@
|
||||
"""ZeroTier low-level socket interface"""
|
||||
|
||||
import libzt
|
||||
|
||||
class EventCallbackClass(libzt.PythonDirectorCallbackClass):
|
||||
"""ZeroTier event callback class"""
|
||||
pass
|
||||
|
||||
def handle_error(err):
|
||||
"""Convert libzt error code to exception"""
|
||||
if err == libzt.ZTS_ERR_SOCKET:
|
||||
raise Exception("ZTS_ERR_SOCKET (" + str(err) + ")")
|
||||
if err == libzt.ZTS_ERR_SERVICE:
|
||||
raise Exception("ZTS_ERR_SERVICE (" + str(err) + ")")
|
||||
if err == libzt.ZTS_ERR_ARG:
|
||||
raise Exception("ZTS_ERR_ARG (" + str(err) + ")")
|
||||
# ZTS_ERR_NO_RESULT isn't strictly an error
|
||||
# if (err == libzt.ZTS_ERR_NO_RESULT):
|
||||
# raise Exception('ZTS_ERR_NO_RESULT (' + err + ')')
|
||||
if err == libzt.ZTS_ERR_GENERAL:
|
||||
raise Exception("ZTS_ERR_GENERAL (" + str(err) + ")")
|
||||
|
||||
# This implementation of errno is NOT thread safe
|
||||
# That is, this value is shared among all lower-level socket calls
|
||||
# and may change for any reason at any time if you have multiple
|
||||
# threads making socket calls.
|
||||
def errno():
|
||||
"""Return errno value of low-level socket layer"""
|
||||
return libzt.cvar.zts_errno
|
||||
|
||||
def start(path, callback, port):
|
||||
"""Start the ZeroTier service"""
|
||||
libzt.zts_start(path, callback, port)
|
||||
|
||||
def stop():
|
||||
"""Stop the ZeroTier service"""
|
||||
libzt.zts_stop()
|
||||
|
||||
def restart():
|
||||
"""[debug] Restarts the ZeroTier service and network stack"""
|
||||
libzt.zts_restart()
|
||||
|
||||
def free():
|
||||
"""Permenantly shuts down the network stack"""
|
||||
libzt.zts_free()
|
||||
|
||||
def join(network_id):
|
||||
"""Join a ZeroTier network"""
|
||||
libzt.zts_join(network_id)
|
||||
|
||||
def leave(network_id):
|
||||
"""Leave a ZeroTier network"""
|
||||
libzt.zts_leave(network_id)
|
||||
|
||||
def zts_orbit(moon_world_id, moon_seed):
|
||||
"""Orbit a moon"""
|
||||
return libzt.zts_orbit(moon_world_id, moon_seed)
|
||||
|
||||
def zts_deorbit(moon_world_id):
|
||||
"""De-orbit a moon"""
|
||||
return libzt.zts_deorbit(moon_world_id)
|
||||
|
||||
|
||||
class socket:
|
||||
"""Pythonic class that wraps low-level sockets"""
|
||||
_fd = -1 # native layer file descriptor
|
||||
_family = -1
|
||||
_type = -1
|
||||
_proto = -1
|
||||
_connected = False
|
||||
_closed = True
|
||||
_bound = False
|
||||
|
||||
def __init__(self, sock_family=-1, sock_type=-1, sock_proto=-1, sock_fd=None):
|
||||
self._fd = sock_fd
|
||||
self._family = sock_family
|
||||
self._type = sock_type
|
||||
self._family = sock_family
|
||||
# Only create native socket if no fd was provided. We may have
|
||||
# accepted a connection
|
||||
if sock_fd is None:
|
||||
self._fd = libzt.zts_socket(sock_family, sock_type, sock_proto)
|
||||
|
||||
def has_dualstack_ipv6(self):
|
||||
"""Return whether libzt supports dual stack sockets: yes"""
|
||||
return True
|
||||
|
||||
@property
|
||||
def family(self):
|
||||
"""Return family of socket"""
|
||||
return self._family
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""Return type of socket"""
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def proto(self):
|
||||
"""Return protocol of socket"""
|
||||
return self._proto
|
||||
|
||||
def socketpair(self, sock_family, sock_type, sock_proto):
|
||||
"""Intentionally not supported"""
|
||||
raise NotImplementedError(
|
||||
"socketpair(): libzt does not support AF_UNIX sockets"
|
||||
)
|
||||
|
||||
def create_connection(self, remote_address):
|
||||
"""Convenience function to create a connection to a remote host"""
|
||||
# TODO: implement timeout
|
||||
conn = socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
|
||||
conn.connect(remote_address)
|
||||
return conn
|
||||
|
||||
def create_server(self, local_address, sock_family=libzt.ZTS_AF_INET, backlog=None):
|
||||
"""Convenience function to create a listening socket"""
|
||||
# TODO: implement reuse_port
|
||||
conn = socket(sock_family, libzt.ZTS_SOCK_STREAM, 0)
|
||||
conn.bind(local_address)
|
||||
conn.listen(backlog)
|
||||
return conn
|
||||
|
||||
def fromfd(self, fd, sock_family, sock_type, sock_proto=0):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError(
|
||||
"fromfd(): Not supported. OS File descriptors aren't used in libzt."
|
||||
)
|
||||
|
||||
def fromshare(self, data):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getaddrinfo(self, host, port, sock_family=0, sock_type=0, sock_proto=0, flags=0):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getfqdn(self, name):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def gethostbyname(self, hostname):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def gethostbyname_ex(self, hostname):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def gethostname(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def gethostbyaddr(self, ip_address):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getnameinfo(self, sockaddr, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getprotobyname(self, protocolname):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getservbyname(self, servicename, protocolname):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getservbyport(self, port, protocolname):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def ntohl(x):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def ntohs(x):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def htonl(x):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def htons(x):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def inet_aton(ip_string):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def inet_ntoa(packed_ip):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def inet_pton(address_family, ip_string):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def inet_ntop(address_family, packed_ip):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def CMSG_LEN(length):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def CMSG_SPACE(length):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getdefaulttimeout(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def setdefaulttimeout(self, timeout):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def sethostname(self, name):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def if_nameindex(self):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError("if_nameindex(): libzt does not name interfaces.")
|
||||
|
||||
def if_nametoindex(self, if_name):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError("if_nametoindex(): libzt does not name interfaces.")
|
||||
|
||||
def if_indextoname(self, if_index):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError("if_indextoname(): libzt does not name interfaces.")
|
||||
|
||||
def accept(self):
|
||||
"""Accept connection on the socket"""
|
||||
new_conn_fd, addr, port = libzt.zts_py_accept(self._fd)
|
||||
if new_conn_fd < 0:
|
||||
handle_error(new_conn_fd)
|
||||
return None
|
||||
return socket(self._family, self._type, self._proto, new_conn_fd), addr
|
||||
|
||||
def bind(self, local_address):
|
||||
"""Bind the socket to a local interface address"""
|
||||
err = libzt.zts_py_bind(self._fd, self._family, self._type, local_address)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
|
||||
def close(self):
|
||||
"""Close the socket"""
|
||||
err = libzt.zts_py_close(self._fd)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
|
||||
def connect(self, remote_address):
|
||||
"""Connect the socket to a remote address"""
|
||||
err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
|
||||
def connect_ex(self, remote_address):
|
||||
"""Connect to remote host but return low-level result code, and errno on failure
|
||||
This uses a non-thread-safe implementation of errno
|
||||
"""
|
||||
err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
|
||||
if err < 0:
|
||||
return errno()
|
||||
return err
|
||||
|
||||
def detach(self):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError(
|
||||
"detach(): Not supported. OS File descriptors aren't used in libzt.")
|
||||
|
||||
def dup(self):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def fileno(self):
|
||||
"""libzt does not support this"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def get_inheritable(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getpeername(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getsockname(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getsockopt(self, level, optname, buflen):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def getblocking(self):
|
||||
"""Get whether this socket is in blocking or non-blocking mode"""
|
||||
return libzt.zts_py_getblocking(self._fd)
|
||||
|
||||
def gettimeout(self):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def ioctl(self, control, option):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def listen(self, backlog):
|
||||
"""Put the socket in a listening state (with an optional backlog argument)"""
|
||||
err = libzt.zts_py_listen(self._fd, backlog)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
|
||||
def makefile(mode="r", buffering=None, *, encoding=None, errors=None, newline=None):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recv(self, n_bytes, flags=0):
|
||||
"""Read data from the socket"""
|
||||
err, data = libzt.zts_py_recv(self._fd, n_bytes, flags)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
return None
|
||||
return data
|
||||
|
||||
def recvfrom(self, bufsize, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recvmsg(self, bufsize, ancbufsize, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recvmsg_into(self, buffers, ancbufsize, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recvfrom_into(self, buffer, n_bytes, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recv_into(self, buffer, n_bytes, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def send(self, data, flags=0):
|
||||
"""Write data to the socket"""
|
||||
err = libzt.zts_py_send(self._fd, data, len(data), flags)
|
||||
if err < 0:
|
||||
handle_error(err)
|
||||
return err
|
||||
|
||||
def sendall(self, n_bytes, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def sendto(self, n_bytes, flags, address):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def sendmsg(self, buffers, ancdata, flags, address):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def sendmsg_afalg(self, msg, *, op, iv, assoclen, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("sendmsg_afalg(): libzt does not support AF_ALG")
|
||||
|
||||
def send_fds(self, sock, buffers, fds, flags, address):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def recv_fds(self, sock, bufsize, maxfds, flags):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def sendfile(self, file, offset=0, count=None):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def set_inheritable(self, inheritable):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def setblocking(self, flag):
|
||||
"""Set whether this socket is in blocking or non-blocking mode"""
|
||||
libzt.zts_py_setblocking(self._fd, flag)
|
||||
|
||||
def settimeout(self, value):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
# TODO: value: buffer
|
||||
# TODO: value: int
|
||||
# TODO: value: None -> optlen required
|
||||
def setsockopt(self, level, optname, value):
|
||||
"""libzt does not support this (yet)"""
|
||||
raise NotImplementedError("libzt does not support this (yet?)")
|
||||
|
||||
def shutdown(self, how):
|
||||
"""Shut down one or more aspects (rx/tx) of the socket"""
|
||||
libzt.zts_shutdown(self._fd, how)
|
||||
39
src/bindings/python/zt.i
Normal file
39
src/bindings/python/zt.i
Normal file
@@ -0,0 +1,39 @@
|
||||
/* libzt.i */
|
||||
|
||||
%begin
|
||||
%{
|
||||
#define SWIG_PYTHON_CAST_MODE
|
||||
%}
|
||||
|
||||
%include <stdint.i>
|
||||
|
||||
#define ZTS_ENABLE_PYTHON 1
|
||||
|
||||
%module(directors="1") libzt
|
||||
%module libzt
|
||||
%{
|
||||
#include "ZeroTierSockets.h"
|
||||
%}
|
||||
|
||||
%feature("director") PythonDirectorCallbackClass;
|
||||
|
||||
%ignore zts_in6_addr;
|
||||
%ignore zts_sockaddr;
|
||||
%ignore zts_in_addr;
|
||||
%ignore zts_sockaddr_in;
|
||||
%ignore zts_sockaddr_storage;
|
||||
%ignore zts_sockaddr_in6;
|
||||
|
||||
%ignore zts_linger;
|
||||
%ignore zts_accept4;
|
||||
%ignore zts_ip_mreq;
|
||||
%ignore zts_in_pktinfo;
|
||||
%ignore zts_ipv6_mreq;
|
||||
|
||||
%ignore zts_fd_set;
|
||||
%ignore zts_pollfd;
|
||||
%ignore zts_nfds_t;
|
||||
%ignore zts_msghdr;
|
||||
%ignore zts_inet_addr;
|
||||
|
||||
%include "ZeroTierSockets.h"
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2013-2020 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2024-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import java.net.*;
|
||||
|
||||
public class ZeroTier
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control API error codes //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Everything is ok
|
||||
public static int ZTS_ERR_OK = 0;
|
||||
// Error
|
||||
public static int ZTS_ERR = -1;
|
||||
// A argument provided by the user application is invalid (e.g. out of range, NULL, etc)
|
||||
public static int ZTS_ERR_INVALID_ARG = -2;
|
||||
// The service isn't initialized or is for some reason currently unavailable. Try again.
|
||||
public static int ZTS_ERR_SERVICE = -3;
|
||||
// For some reason this API operation is not permitted or doesn't make sense at this time.
|
||||
public static int ZTS_ERR_INVALID_OP = -4;
|
||||
// The call succeeded, but no object or relevant result was available
|
||||
public static int ZTS_ERR_NO_RESULT = -5;
|
||||
// General internal failure
|
||||
public static int ZTS_ERR_GENERAL = -6;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Static initialization //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static
|
||||
{
|
||||
// loads libzt.so or libzt.dylib
|
||||
System.loadLibrary("zt");
|
||||
// Give the native code a reference to this VM (for callbacks)
|
||||
if (init() != ZTS_ERR_OK) {
|
||||
throw new ExceptionInInitializerError("JNI init() failed (see GetJavaVM())");
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control API event codes //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static int EVENT_NONE = -1;
|
||||
// Node-specific events
|
||||
public static int EVENT_NODE_UP = 0;
|
||||
public static int EVENT_NODE_OFFLINE = 1;
|
||||
public static int EVENT_NODE_ONLINE = 2;
|
||||
public static int EVENT_NODE_DOWN = 3;
|
||||
public static int EVENT_NODE_IDENTITY_COLLISION = 4;
|
||||
// libzt node events
|
||||
public static int EVENT_NODE_UNRECOVERABLE_ERROR = 16;
|
||||
public static int EVENT_NODE_NORMAL_TERMINATION = 17;
|
||||
// Network-specific events
|
||||
public static int EVENT_NETWORK_NOT_FOUND = 32;
|
||||
public static int EVENT_NETWORK_CLIENT_TOO_OLD = 33;
|
||||
public static int EVENT_NETWORK_REQUESTING_CONFIG = 34;
|
||||
public static int EVENT_NETWORK_OK = 35;
|
||||
public static int EVENT_NETWORK_ACCESS_DENIED = 36;
|
||||
public static int EVENT_NETWORK_READY_IP4 = 37;
|
||||
public static int EVENT_NETWORK_READY_IP6 = 38;
|
||||
public static int EVENT_NETWORK_READY_IP4_IP6 = 39;
|
||||
public static int EVENT_NETWORK_DOWN = 40;
|
||||
// lwIP netif events
|
||||
public static int EVENT_NETIF_UP_IP4 = 64;
|
||||
public static int EVENT_NETIF_UP_IP6 = 65;
|
||||
public static int EVENT_NETIF_DOWN_IP4 = 66;
|
||||
public static int EVENT_NETIF_DOWN_IP6 = 67;
|
||||
public static int EVENT_NETIF_REMOVED = 68;
|
||||
public static int EVENT_NETIF_LINK_UP = 69;
|
||||
public static int EVENT_NETIF_LINK_DOWN = 70;
|
||||
public static int EVENT_NETIF_NEW_ADDRESS = 71;
|
||||
// Peer events
|
||||
public static int EVENT_PEER_P2P = 96;
|
||||
public static int EVENT_PEER_RELAY = 97;
|
||||
public static int EVENT_PEER_UNREACHABLE = 98;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZeroTier Constants //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static int ZT_MAX_PEER_NETWORK_PATHS = 16;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Socket API Constants //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Socket protocol types
|
||||
public static int SOCK_STREAM = 0x00000001;
|
||||
public static int SOCK_DGRAM = 0x00000002;
|
||||
public static int SOCK_RAW = 0x00000003;
|
||||
// Socket family types
|
||||
public static int AF_INET = 0x00000002;
|
||||
public static int AF_INET6 = 0x0000000a;
|
||||
public static int PF_INET = AF_INET;
|
||||
public static int PF_INET6 = AF_INET6;
|
||||
// Used as level numbers for setsockopt() and getsockopt()
|
||||
public static int IPPROTO_IP = 0x00000000;
|
||||
public static int IPPROTO_ICMP = 0x00000001;
|
||||
public static int IPPROTO_TCP = 0x00000006;
|
||||
public static int IPPROTO_UDP = 0x00000011;
|
||||
public static int IPPROTO_IPV6 = 0x00000029;
|
||||
public static int IPPROTO_ICMPV6 = 0x0000003a;
|
||||
public static int IPPROTO_UDPLITE = 0x00000088;
|
||||
public static int IPPROTO_RAW = 0x000000ff;
|
||||
// send() and recv() flags
|
||||
public static int MSG_PEEK = 0x00000001;
|
||||
public static int MSG_WAITALL = 0x00000002;
|
||||
public static int MSG_OOB = 0x00000004;
|
||||
public static int MSG_DONTWAIT = 0x00000008;
|
||||
public static int MSG_MORE = 0x00000010;
|
||||
// fnctl() commands
|
||||
public static int F_GETFL = 0x00000003;
|
||||
public static int F_SETFL = 0x00000004;
|
||||
// fnctl() flags
|
||||
public static int O_NONBLOCK = 0x00000001;
|
||||
public static int O_NDELAY = 0x00000001;
|
||||
// Shutdown commands
|
||||
public static int SHUT_RD = 0x00000000;
|
||||
public static int SHUT_WR = 0x00000001;
|
||||
public static int SHUT_RDWR = 0x00000002;
|
||||
// ioctl() commands
|
||||
public static int FIONREAD = 0x4008667F;
|
||||
public static int FIONBIO = 0x8008667E;
|
||||
// Socket level option number
|
||||
public static int SOL_SOCKET = 0x00000FFF;
|
||||
// Socket options
|
||||
public static int SO_REUSEADDR = 0x00000004;
|
||||
public static int SO_KEEPALIVE = 0x00000008;
|
||||
public static int SO_BROADCAST = 0x00000020;
|
||||
// Socket options
|
||||
public static int SO_DEBUG = 0x00000001; // NOT YET SUPPORTED
|
||||
public static int SO_ACCEPTCONN = 0x00000002;
|
||||
public static int SO_DONTROUTE = 0x00000010; // NOT YET SUPPORTED
|
||||
public static int SO_USELOOPBACK = 0x00000040; // NOT YET SUPPORTED
|
||||
public static int SO_LINGER = 0x00000080;
|
||||
public static int SO_DONTLINGER = ((int)(~SO_LINGER));
|
||||
public static int SO_OOBINLINE = 0x00000100; // NOT YET SUPPORTED
|
||||
public static int SO_REUSEPORT = 0x00000200; // NOT YET SUPPORTED
|
||||
public static int SO_SNDBUF = 0x00001001; // NOT YET SUPPORTED
|
||||
public static int SO_RCVBUF = 0x00001002;
|
||||
public static int SO_SNDLOWAT = 0x00001003; // NOT YET SUPPORTED
|
||||
public static int SO_RCVLOWAT = 0x00001004; // NOT YET SUPPORTED
|
||||
public static int SO_SNDTIMEO = 0x00001005;
|
||||
public static int SO_RCVTIMEO = 0x00001006;
|
||||
public static int SO_ERROR = 0x00001007;
|
||||
public static int SO_TYPE = 0x00001008;
|
||||
public static int SO_CONTIMEO = 0x00001009; // NOT YET SUPPORTED
|
||||
public static int SO_NO_CHECK = 0x0000100a;
|
||||
// IPPROTO_IP options
|
||||
public static int IP_TOS = 0x00000001;
|
||||
public static int IP_TTL = 0x00000002;
|
||||
// IPPROTO_TCP options
|
||||
public static int TCP_NODELAY = 0x00000001;
|
||||
public static int TCP_KEEPALIVE = 0x00000002;
|
||||
public static int TCP_KEEPIDLE = 0x00000003;
|
||||
public static int TCP_KEEPINTVL = 0x00000004;
|
||||
public static int TCP_KEEPCNT = 0x00000005;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Statistics //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static int STATS_PROTOCOL_LINK = 0;
|
||||
public static int STATS_PROTOCOL_ETHARP = 1;
|
||||
public static int STATS_PROTOCOL_IP = 2;
|
||||
public static int STATS_PROTOCOL_UDP = 3;
|
||||
public static int STATS_PROTOCOL_TCP = 4;
|
||||
public static int STATS_PROTOCOL_ICMP = 5;
|
||||
public static int STATS_PROTOCOL_IP_FRAG = 6;
|
||||
public static int STATS_PROTOCOL_IP6 = 7;
|
||||
public static int STATS_PROTOCOL_ICMP6 = 8;
|
||||
public static int STATS_PROTOCOL_IP6_FRAG = 9;
|
||||
|
||||
public static native int get_protocol_stats(int protocolNum, ZeroTierProtoStats stats);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ZeroTier Service Controls //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static native int start(String path, ZeroTierEventListener callbackClass, int port);
|
||||
public static native int stop();
|
||||
public static native int restart();
|
||||
public static native int join(long nwid);
|
||||
public static native int leave(long nwid);
|
||||
public static native long get_node_id();
|
||||
public static native int get_num_assigned_addresses(long nwid);
|
||||
public static native void get_6plane_addr(long nwid, long nodeId, ZeroTierSocketAddress addr);
|
||||
public static native void get_rfc4193_addr(long nwid, long nodeId, ZeroTierSocketAddress addr);
|
||||
public static native int get_node_status();
|
||||
public static native int get_network_status(long networkId);
|
||||
public static native int get_peer_status(long peerId);
|
||||
public static native int get_peer(long peerId, ZeroTierPeerDetails details);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Socket API //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static native int socket(int family, int type, int protocol);
|
||||
public static native int connect(int fd, ZeroTierSocketAddress addr);
|
||||
public static native int bind(int fd, ZeroTierSocketAddress addr);
|
||||
public static native int listen(int fd, int backlog);
|
||||
public static native int accept(int fd, ZeroTierSocketAddress addr);
|
||||
public static native int accept4(int fd, String addr, int port);
|
||||
|
||||
public static native int setsockopt(int fd, int level, int optname, ZeroTierSocketOptionValue optval);
|
||||
public static native int getsockopt(int fd, int level, int optname, ZeroTierSocketOptionValue optval);
|
||||
|
||||
public static native int read(int fd, byte[] buf);
|
||||
public static native int read_offset(int fd, byte[] buf, int offset, int len);
|
||||
public static native int read_length(int fd, byte[] buf, int len);
|
||||
public static native int recv(int fd, byte[] buf, int flags);
|
||||
public static native int recvfrom(int fd, byte[] buf, int flags, ZeroTierSocketAddress addr);
|
||||
|
||||
public static native int write(int fd, byte[] buf);
|
||||
public static native int write_byte(int fd, byte b);
|
||||
public static native int write_offset(int fd, byte[] buf, int offset, int len);
|
||||
public static native int sendto(int fd, byte[] buf, int flags, ZeroTierSocketAddress addr);
|
||||
public static native int send(int fd, byte[] buf, int flags);
|
||||
|
||||
public static native int shutdown(int fd, int how);
|
||||
public static native int close(int fd);
|
||||
|
||||
public static native boolean getsockname(int fd, ZeroTierSocketAddress addr);
|
||||
public static native int getpeername(int fd, ZeroTierSocketAddress addr);
|
||||
public static native int fcntl(int sock, int cmd, int flag);
|
||||
public static native int ioctl(int fd, long request, ZeroTierIoctlArg arg);
|
||||
public static native int select(int nfds, ZeroTierFileDescriptorSet readfds, ZeroTierFileDescriptorSet writefds, ZeroTierFileDescriptorSet exceptfds, int timeout_sec, int timeout_usec);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Internal - Do not call //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static native int init(); // Only to be called by static initializer of this class
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
public interface ZeroTierEventListener {
|
||||
|
||||
/*
|
||||
* Called when an even occurs in the native section of the ZeroTier library service
|
||||
*/
|
||||
public void onZeroTierEvent(long nwid, int eventCode);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
public class ZeroTierFileDescriptorSet
|
||||
{
|
||||
byte[] fds_bits = new byte[1024];
|
||||
|
||||
public void CLR(int fd)
|
||||
{
|
||||
fds_bits[fd] = 0x00;
|
||||
}
|
||||
|
||||
public boolean ISSET(int fd)
|
||||
{
|
||||
return fds_bits[fd] == 0x01;
|
||||
}
|
||||
|
||||
public void SET(int fd)
|
||||
{
|
||||
fds_bits[fd] = 0x01;
|
||||
}
|
||||
|
||||
public void ZERO()
|
||||
{
|
||||
for (int i=0; i<1024; i++) {
|
||||
fds_bits[i] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ZeroTierInputStream extends InputStream
|
||||
{
|
||||
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
/*
|
||||
* File descriptor used by lower native layer
|
||||
*/
|
||||
int zfd;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public int available()
|
||||
throws IOException
|
||||
{
|
||||
return 0; // NOT YET SUPPORTED
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
/* Note: this operation currently only stops RX on a socket that is shared
|
||||
between both I/OStreams. This means that closing this stream will only shutdown
|
||||
that aspect of the socket but not actually close it and free resources. Resources
|
||||
will be properly freed when the socket implementation's close() is called or if
|
||||
both I/OStreams are closed separately */
|
||||
ZeroTier.shutdown(zfd, ZeroTier.SHUT_RD);
|
||||
zfd = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void mark(int readlimit)
|
||||
{
|
||||
System.err.println("mark: ZeroTierInputStream does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void reset()
|
||||
throws IOException
|
||||
{
|
||||
System.err.println("reset: ZeroTierInputStream does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public boolean markSupported()
|
||||
{
|
||||
return false; // mark() is not supported
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public long transferTo(OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull(out, "out must not be null");
|
||||
int bytesTransferred = 0, bytesRead;
|
||||
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
|
||||
while (((bytesRead = ZeroTier.read(zfd, buf)) >= 0)) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
bytesTransferred += bytesRead;
|
||||
}
|
||||
return bytesTransferred;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public int read()
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[1];
|
||||
// Unlike a native read(), if nothing is read we should return -1
|
||||
int retval = ZeroTier.read(zfd, buf);
|
||||
if ((retval == 0) | (retval == -104) /* EINTR, from SO_RCVTIMEO */) {
|
||||
return -1;
|
||||
}
|
||||
if (retval < 0) {
|
||||
throw new IOException("read(), errno="+retval);
|
||||
}
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public int read(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull(b, "input byte array must not be null");
|
||||
// Unlike a native read(), if nothing is read we should return -1
|
||||
int retval = ZeroTier.read(zfd, b);
|
||||
if ((retval == 0) | (retval == -104) /* EINTR, from SO_RCVTIMEO */) {
|
||||
return -1;
|
||||
}
|
||||
if (retval < 0) {
|
||||
throw new IOException("read(b), errno="+retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public int read(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull(b, "input byte array must not be null");
|
||||
if ((off < 0) | (len < 0) | (len > b.length - off)) {
|
||||
throw new IndexOutOfBoundsException("invalid argument");
|
||||
}
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
// Unlike a native read(), if nothing is read we should return -1
|
||||
int retval = ZeroTier.read_offset(zfd, b, off, len);
|
||||
if ((retval == 0) | (retval == -104) /* EINTR, from SO_RCVTIMEO */) {
|
||||
return -1;
|
||||
}
|
||||
if (retval < 0) {
|
||||
throw new IOException("read(b,off,len), errno="+retval);
|
||||
}
|
||||
//System.out.println("readNBytes(byte[] b, int off="+off+", int len="+len+")="+retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public byte[] readAllBytes()
|
||||
throws IOException
|
||||
{
|
||||
//System.out.println("readAllBytes()");
|
||||
ZeroTierIoctlArg ztarg = new ZeroTierIoctlArg();
|
||||
int err = ZeroTier.ioctl(zfd, ZeroTier.FIONREAD, ztarg);
|
||||
byte[] buf = new byte[ztarg.integer];
|
||||
int retval = ZeroTier.read(zfd, buf);
|
||||
if ((retval == 0) | (retval == -104) /* EINTR, from SO_RCVTIMEO */) {
|
||||
// No action needed
|
||||
}
|
||||
if (retval < 0) {
|
||||
throw new IOException("readAllBytes(b,off,len), errno="+retval);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public int readNBytes(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull(b, "input byte array must not be null");
|
||||
if ((off < 0) | (len < 0) | (len > b.length - off)) {
|
||||
throw new IndexOutOfBoundsException("invalid argument");
|
||||
}
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
int retval = ZeroTier.read_offset(zfd, b, off, len);
|
||||
if ((retval == 0) | (retval == -104) /* EINTR, from SO_RCVTIMEO */) {
|
||||
// No action needed
|
||||
}
|
||||
if (retval < 0) {
|
||||
throw new IOException("readNBytes(b,off,len), errno="+retval);
|
||||
}
|
||||
//System.out.println("readNBytes(byte[] b, int off="+off+", int len="+len+")="+retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public long skip(long n)
|
||||
throws IOException
|
||||
{
|
||||
//System.out.println("skip()");
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
long bytesRemaining = n, bytesRead;
|
||||
int bufSize = (int)Math.min(MAX_SKIP_BUFFER_SIZE, bytesRemaining);
|
||||
byte[] buf = new byte[bufSize];
|
||||
while (bytesRemaining > 0) {
|
||||
if ((bytesRead = ZeroTier.read_length(zfd, buf, (int)Math.min(bufSize, bytesRemaining))) < 0) {
|
||||
break;
|
||||
}
|
||||
bytesRemaining -= bytesRead;
|
||||
}
|
||||
return n - bytesRemaining; // skipped
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
public class ZeroTierIoctlArg
|
||||
{
|
||||
int integer; // General integer to be used or updated by the zts_ioctl() call
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
class ZeroTierOutputStream extends OutputStream
|
||||
{
|
||||
/*
|
||||
* File descriptor used by lower native layer
|
||||
*/
|
||||
int zfd;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void flush()
|
||||
throws IOException
|
||||
{
|
||||
// System.err.println("flush: ZeroTierOutputStream does not currently support this feature");
|
||||
// Not fully supported since we don't maintain a buffer
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
/* Note: this operation currently only stops RX on a socket that is shared
|
||||
between both I/OStreams. This means that closing this stream will only shutdown
|
||||
that aspect of the socket but not actually close it and free resources. Resources
|
||||
will be properly freed when the socket implementation's close() is called or if
|
||||
both I/OStreams are closed separately */
|
||||
ZeroTier.shutdown(zfd, ZeroTier.SHUT_WR);
|
||||
zfd = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void write(byte[] b)
|
||||
throws IOException
|
||||
{
|
||||
int err = ZeroTier.write(zfd, b);
|
||||
if (err < 0) {
|
||||
throw new IOException("write(b[]), errno="+err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull(b, "input byte array must not be null");
|
||||
if ((off < 0) | (len < 0) | (off+len > b.length)) {
|
||||
throw new IndexOutOfBoundsException("write(b,off,len)");
|
||||
}
|
||||
int err = ZeroTier.write_offset(zfd, b, off, len);
|
||||
if (err < 0) {
|
||||
throw new IOException("write(b[],off,len), errno="+err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void write(int b)
|
||||
throws IOException
|
||||
{
|
||||
byte lowByte = (byte)(b & 0xFF);
|
||||
int err = ZeroTier.write_byte(zfd, lowByte);
|
||||
if (err < 0) {
|
||||
throw new IOException("write(b), errno="+err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
import com.zerotier.libzt.ZeroTierSocketAddress;
|
||||
|
||||
public class ZeroTierPeerDetails
|
||||
{
|
||||
/**
|
||||
* ZeroTier address (40 bits)
|
||||
*/
|
||||
public long address;
|
||||
|
||||
/**
|
||||
* Remote major version or -1 if not known
|
||||
*/
|
||||
public int versionMajor;
|
||||
|
||||
/**
|
||||
* Remote minor version or -1 if not known
|
||||
*/
|
||||
public int versionMinor;
|
||||
|
||||
/**
|
||||
* Remote revision or -1 if not known
|
||||
*/
|
||||
public int versionRev;
|
||||
|
||||
/**
|
||||
* Last measured latency in milliseconds or -1 if unknown
|
||||
*/
|
||||
public int latency;
|
||||
|
||||
/**
|
||||
* What trust hierarchy role does this device have?
|
||||
*/
|
||||
public int role;
|
||||
|
||||
/**
|
||||
* Number of paths (size of paths[])
|
||||
*/
|
||||
public int pathCount;
|
||||
|
||||
/**
|
||||
* Known network paths to peer
|
||||
*/
|
||||
public ZeroTierSocketAddress[] paths = new ZeroTierSocketAddress[ZeroTier.ZT_MAX_PEER_NETWORK_PATHS];
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
|
||||
public class ZeroTierProtoStats
|
||||
{
|
||||
public int xmit; /* Transmitted packets. */
|
||||
public int recv; /* Received packets. */
|
||||
public int fw; /* Forwarded packets. */
|
||||
public int drop; /* Dropped packets. */
|
||||
public int chkerr; /* Checksum error. */
|
||||
public int lenerr; /* Invalid length error. */
|
||||
public int memerr; /* Out of memory error. */
|
||||
public int rterr; /* Routing error. */
|
||||
public int proterr; /* Protocol error. */
|
||||
public int opterr; /* Error in options. */
|
||||
public int err; /* Misc error. */
|
||||
public int cachehit;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTierSocket;
|
||||
|
||||
import java.net.*;
|
||||
import javax.net.SocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.*;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
public class ZeroTierSSLSocketFactory extends SSLSocketFactory
|
||||
{
|
||||
private final SSLSocketFactory delegate;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public ZeroTierSSLSocketFactory(SSLSocketFactory delegate)
|
||||
{
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
|
||||
throws IOException
|
||||
{
|
||||
ZeroTierSocket zs = new ZeroTierSocket();
|
||||
zs.connect((SocketAddress)new InetSocketAddress(host, port), 10);
|
||||
return delegate.createSocket(zs, host, port, autoClose);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(Socket s, InputStream consumed, boolean autoClose)
|
||||
throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(InetAddress a,int b,InetAddress c,int d)
|
||||
throws IOException
|
||||
{
|
||||
ZeroTierSocket s = new ZeroTierSocket();
|
||||
return delegate.createSocket(a, b, c, d);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(InetAddress a,int b)
|
||||
throws IOException
|
||||
{
|
||||
ZeroTierSocket s = new ZeroTierSocket();
|
||||
return delegate.createSocket(a, b);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(String a,int b,InetAddress c,int d)
|
||||
throws IOException
|
||||
{
|
||||
ZeroTierSocket s = new ZeroTierSocket();
|
||||
return delegate.createSocket(a, b, c, d);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public Socket createSocket(String a,int b)
|
||||
throws IOException
|
||||
{
|
||||
ZeroTierSocket s = new ZeroTierSocket();
|
||||
return delegate.createSocket(a, b);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String [] getSupportedCipherSuites()
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public String [] getDefaultCipherSuites()
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
@@ -1,748 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
import com.zerotier.libzt.ZeroTierSocketAddress;
|
||||
import com.zerotier.libzt.ZeroTierSocketImpl;
|
||||
import com.zerotier.libzt.ZeroTierSocketImplFactory;
|
||||
import com.zerotier.libzt.ZeroTierInputStream;
|
||||
import com.zerotier.libzt.ZeroTierOutputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.Objects;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class ZeroTierSocket extends Socket
|
||||
{
|
||||
/*
|
||||
* Factory designated to create the underlying ZeroTierSocket implementation
|
||||
*/
|
||||
static ZeroTierSocketImplFactory factory = new ZeroTierSocketImplFactory();
|
||||
|
||||
/*
|
||||
* Underlying implementation of this ZeroTierSocket
|
||||
*/
|
||||
ZeroTierSocketImpl impl;
|
||||
|
||||
/*
|
||||
* Misc. state flags
|
||||
*/
|
||||
private boolean created = false;
|
||||
private boolean closed = false;
|
||||
private boolean connected = false;
|
||||
private boolean bound = false;
|
||||
private boolean inputShutdown = false;
|
||||
private boolean outputShutdown = false;
|
||||
|
||||
/*
|
||||
* Creates and sets the implementation
|
||||
*/
|
||||
void setImpl()
|
||||
{
|
||||
if (factory != null) {
|
||||
impl = factory.createSocketImpl();
|
||||
}
|
||||
if (impl != null) {
|
||||
impl.setSocket(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the underlying socket implementation
|
||||
*/
|
||||
private ZeroTierSocketImpl getImpl()
|
||||
throws SocketException
|
||||
{
|
||||
if (!created) {
|
||||
try {
|
||||
impl.create(true);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw (SocketException) new SocketException().initCause(ex);
|
||||
}
|
||||
created = true;
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the underlying socket implementation
|
||||
*/
|
||||
void createImpl(boolean stream)
|
||||
throws SocketException
|
||||
{
|
||||
if (impl == null) {
|
||||
setImpl();
|
||||
}
|
||||
try {
|
||||
impl.create(stream);
|
||||
created = true;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new SocketException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for ZeroTierSocket
|
||||
*/
|
||||
public ZeroTierSocket()
|
||||
throws IOException
|
||||
{
|
||||
this((InetAddress)null, 0, null, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates an unconnected socket
|
||||
*/
|
||||
protected ZeroTierSocket(ZeroTierSocketImpl impl)
|
||||
throws SocketException
|
||||
{
|
||||
this.impl = impl;
|
||||
if (impl != null) {
|
||||
this.impl.setSocket(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for ZeroTierSocket
|
||||
*/
|
||||
public ZeroTierSocket(InetAddress raddr, int rport, InetAddress laddr, int lport)
|
||||
throws IOException
|
||||
{
|
||||
setImpl();
|
||||
|
||||
try {
|
||||
if (laddr != null) {
|
||||
bind(new InetSocketAddress(laddr, lport));
|
||||
}
|
||||
if (raddr != null) {
|
||||
connect(new InetSocketAddress(raddr, rport));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try {
|
||||
close();
|
||||
}
|
||||
catch (IOException _ex) {
|
||||
ex.addSuppressed(_ex);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for ZeroTierSocket
|
||||
*/
|
||||
public ZeroTierSocket(InetAddress address, int port)
|
||||
throws IOException
|
||||
{
|
||||
this(address, port, null, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for ZeroTierSocket
|
||||
*/
|
||||
public ZeroTierSocket(String address, int port)
|
||||
throws IOException
|
||||
{
|
||||
this(InetAddress.getByName(address), port, null, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for ZeroTierSocket
|
||||
*/
|
||||
public ZeroTierSocket(String address, int port, InetAddress localHost, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
this(InetAddress.getByName(address), port, localHost, localPort);
|
||||
}
|
||||
|
||||
/*
|
||||
* Binds the socket to a local address
|
||||
*/
|
||||
public void bind(SocketAddress localAddr)
|
||||
throws IOException
|
||||
{
|
||||
if (isSocketBound()) {
|
||||
throw new SocketException("bind: ZeroTierSocket is already bound");
|
||||
}
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("bind: ZeroTierSocket is closed");
|
||||
}
|
||||
if (localAddr != null && (!(localAddr instanceof InetSocketAddress))) {
|
||||
throw new IllegalArgumentException("bind: Unsupported address type");
|
||||
}
|
||||
InetSocketAddress addr = (InetSocketAddress)localAddr;
|
||||
if (addr != null && addr.isUnresolved()) {
|
||||
throw new SocketException("bind: Unresolved address");
|
||||
}
|
||||
if (addr == null) {
|
||||
addr = new InetSocketAddress(0);
|
||||
}
|
||||
getImpl().bind(addr.getAddress(), addr.getPort());
|
||||
bound = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the socket
|
||||
*/
|
||||
public synchronized void close()
|
||||
throws IOException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
return;
|
||||
}
|
||||
getOutputStream().flush();
|
||||
impl.close();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects the socket to a remote address
|
||||
*/
|
||||
public void connect(SocketAddress remoteAddr)
|
||||
throws IOException
|
||||
{
|
||||
connect(remoteAddr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects the socket to a remote address
|
||||
*/
|
||||
public void connect(SocketAddress remoteAddr, int timeout)
|
||||
throws IOException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("connect: ZeroTierSocket is closed");
|
||||
}
|
||||
if (isSocketConnected()) {
|
||||
throw new SocketException("connect: already connected");
|
||||
}
|
||||
if (remoteAddr == null) {
|
||||
throw new IllegalArgumentException("connect: The address can't be null");
|
||||
}
|
||||
if (!(remoteAddr instanceof InetSocketAddress)) {
|
||||
throw new IllegalArgumentException("connect: Unsupported address type");
|
||||
}
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("connect: timeout cannot be negative");
|
||||
}
|
||||
if (!created) {
|
||||
createImpl(true);
|
||||
}
|
||||
getImpl().connect(remoteAddr, 0);
|
||||
bound = true;
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the associated Channel
|
||||
*/
|
||||
public SocketChannel getChannel()
|
||||
{
|
||||
System.err.println("getChannel: ZeroTierSocket does not currently support this feature");
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address to which the socket is connected
|
||||
*/
|
||||
public InetAddress getInetAddress()
|
||||
{
|
||||
if (!isSocketConnected()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return getImpl().getInetAddress();
|
||||
}
|
||||
catch (SocketException ex) {
|
||||
// Not Reachable
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the input stream
|
||||
*/
|
||||
public ZeroTierInputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!isSocketConnected()) {
|
||||
throw new SocketException("ZeroTierSocket is not connected");
|
||||
}
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (isInputStreamShutdown()) {
|
||||
throw new SocketException("ZeroTierSocket input is shutdown");
|
||||
}
|
||||
return getImpl().getInputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether SO_KEEPALIVE is enabled
|
||||
*/
|
||||
public boolean getKeepAlive()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
return ((Boolean) getImpl().getOption(ZeroTier.SO_KEEPALIVE)).booleanValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the local address to which the socket is bound
|
||||
*/
|
||||
public InetAddress getLocalAddress()
|
||||
{
|
||||
System.err.println("getLocalAddress: ZeroTierSocket does not currently support this feature");
|
||||
/*
|
||||
// This is for backward compatibility
|
||||
if (!isSocketBound()) {
|
||||
return InetAddress.anyLocalAddress();
|
||||
}
|
||||
InetAddress inAddr = null;
|
||||
try {
|
||||
inAddr = (InetAddress) getImpl().getOption(ZeroTier.SO_BINDADDR);
|
||||
if (inAddr.isAnyLocalAddress()) {
|
||||
inAddr = InetAddress.anyLocalAddress();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// "0.0.0.0"
|
||||
inAddr = InetAddress.anyLocalAddress();
|
||||
}
|
||||
return inAddr;
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the local port to which the socket is bound
|
||||
*/
|
||||
public int getLocalPort()
|
||||
{
|
||||
if (!isSocketBound()) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return getImpl().getLocalPort();
|
||||
}
|
||||
catch(SocketException ex) {
|
||||
// Unreachable
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the address of the endpoint that the socket is bound to.
|
||||
*/
|
||||
public SocketAddress getLocalSocketAddress()
|
||||
{
|
||||
if (!isSocketBound()) {
|
||||
return null;
|
||||
}
|
||||
return new InetSocketAddress(getLocalAddress(), getLocalPort());
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether SO_OOBINLINE is enabled.
|
||||
*/
|
||||
public boolean getOOBInline()
|
||||
throws SocketException
|
||||
{
|
||||
System.err.println("getOOBInline: ZeroTierSocket does not currently support this feature");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the output stream.
|
||||
*/
|
||||
public ZeroTierOutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (!isSocketConnected()) {
|
||||
throw new SocketException("ZeroTierSocket is not connected");
|
||||
}
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (isOutputStreamShutdown()) {
|
||||
throw new SocketException("ZeroTierSocket output is shutdown");
|
||||
}
|
||||
return getImpl().getOutputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the remote port to which the socket is connected
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
if (!isSocketConnected()) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return getImpl().getPort();
|
||||
}
|
||||
catch (SocketException ex) {
|
||||
// Not reachable
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns SO_RCVBUF
|
||||
*/
|
||||
public synchronized int getReceiveBufferSize()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
Object opt = getImpl().getOption(ZeroTier.SO_RCVBUF);
|
||||
int sz = 0;
|
||||
if (opt instanceof Integer) {
|
||||
sz = ((Integer)opt).intValue();
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the remote address to which this socket is connected
|
||||
*/
|
||||
public SocketAddress getRemoteSocketAddress()
|
||||
{
|
||||
if (!isSocketConnected()) {
|
||||
return null;
|
||||
}
|
||||
return new InetSocketAddress(getInetAddress(), getPort());
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether SO_REUSEADDR is enabled.
|
||||
*/
|
||||
public boolean getReuseAddress()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
return ((Boolean)(getImpl().getOption(ZeroTier.SO_REUSEADDR))).booleanValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns SO_SNDBUF.
|
||||
*/
|
||||
public synchronized int getSendBufferSize()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
int sz = 0;
|
||||
Object opt = getImpl().getOption(ZeroTier.SO_SNDBUF);
|
||||
if (opt instanceof Integer) {
|
||||
sz = ((Integer)opt).intValue();
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns SO_LINGER.
|
||||
*/
|
||||
public int getSoLinger()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
Object opt = getImpl().getOption(ZeroTier.SO_LINGER);
|
||||
if (opt instanceof Integer) {
|
||||
return ((Integer)opt).intValue();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns SO_TIMEOUT.
|
||||
*/
|
||||
public synchronized int getSoTimeout()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
Object opt = getImpl().getOption(ZeroTier.SO_RCVTIMEO);
|
||||
if (opt instanceof Integer) {
|
||||
return ((Integer)opt).intValue();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether TCP_NODELAY is enabled.
|
||||
*/
|
||||
public boolean getTcpNoDelay()
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
return ((Boolean)getImpl().getOption(ZeroTier.TCP_NODELAY)).booleanValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets traffic class or type-of-service in the IP header for packets sent from this Socket
|
||||
*/
|
||||
public int getTrafficClass()
|
||||
throws SocketException
|
||||
{
|
||||
System.err.println("getTrafficClass: ZeroTierSocket does not currently support this feature");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether or not the socket is bound to a local interface.
|
||||
*/
|
||||
public boolean isSocketBound()
|
||||
{
|
||||
return bound;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether or not the socket has been closed.
|
||||
*/
|
||||
public boolean isSocketClosed()
|
||||
{
|
||||
return closed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether or not the socket is connected to a remote host.
|
||||
*/
|
||||
public boolean isSocketConnected()
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the input aspect of the socket has been disabled.
|
||||
*/
|
||||
public boolean isInputStreamShutdown()
|
||||
{
|
||||
return inputShutdown;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the output aspect of the socket has been disabled.
|
||||
*/
|
||||
public boolean isOutputStreamShutdown()
|
||||
{
|
||||
return outputShutdown;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a byte of urgent data on the socket.
|
||||
*/
|
||||
public void sendUrgentData(int data)
|
||||
throws IOException
|
||||
{
|
||||
System.err.println("sendUrgentData: ZeroTierSocket does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable SO_KEEPALIVE.
|
||||
*/
|
||||
public void setKeepAlive(boolean on)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_KEEPALIVE, Boolean.valueOf(on));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable SO_OOBINLINE.
|
||||
*/
|
||||
public void setOOBInline(boolean on)
|
||||
throws SocketException
|
||||
{
|
||||
System.err.println("setOOBInline: ZeroTierSocket does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set performance preferences.
|
||||
*/
|
||||
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
|
||||
{
|
||||
System.err.println("setPerformancePreferences: ZeroTierSocket does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set SO_RCVBUF.
|
||||
*/
|
||||
public synchronized void setReceiveBufferSize(int size)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (size <= 0) {
|
||||
throw new IllegalArgumentException("invalid receive buffer size argument");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_RCVBUF, new Integer(size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable SO_REUSEADDR.
|
||||
*/
|
||||
public void setReuseAddress(boolean on)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_REUSEADDR, Boolean.valueOf(on));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set SO_SNDBUF.
|
||||
*/
|
||||
public synchronized void setSendBufferSize(int size)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException("size argument cannot be negative");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_SNDBUF, new Integer(size));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set Socket implementation factory for all clients.
|
||||
*/
|
||||
public static void setSocketImplFactory(ZeroTierSocketImplFactory fact)
|
||||
throws IOException
|
||||
{
|
||||
if (factory != null) {
|
||||
throw new SocketException("ZeroTierSocket factory is already defined");
|
||||
}
|
||||
factory = fact;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable SO_LINGER time (seconds).
|
||||
*/
|
||||
public void setSoLinger(boolean on, int linger)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (!on) {
|
||||
getImpl().setOption(ZeroTier.SO_LINGER, new Boolean(on));
|
||||
}
|
||||
else {
|
||||
if (linger < 0) {
|
||||
throw new IllegalArgumentException("linger argument is invalid");
|
||||
}
|
||||
if (linger > 0xFFFF) {
|
||||
linger = 0xFFFF;
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_LINGER, new Integer(linger));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable SO_TIMEOUT with the specified timeout, in milliseconds.
|
||||
*/
|
||||
public void setSoTimeout(int timeout)
|
||||
throws SocketException
|
||||
{
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("timeout argument cannot be negative");
|
||||
}
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.SO_RCVTIMEO, new Integer(timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable TCP_NODELAY (Nagle's algorithm).
|
||||
*/
|
||||
public void setTcpNoDelay(boolean on)
|
||||
throws SocketException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
getImpl().setOption(ZeroTier.TCP_NODELAY, Boolean.valueOf(on));
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets traffic class or ToS.
|
||||
*/
|
||||
public void setTrafficClass(int tc)
|
||||
throws SocketException
|
||||
{
|
||||
System.err.println("setTrafficClass: ZeroTierSocket does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the input stream for this socket.
|
||||
*/
|
||||
public void shutdownInput()
|
||||
throws IOException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (isInputStreamShutdown()) {
|
||||
throw new SocketException("ZeroTierSocket input is already shutdown");
|
||||
}
|
||||
if (!isSocketConnected()) {
|
||||
throw new SocketException("ZeroTierSocket is not connected");
|
||||
}
|
||||
getImpl().shutdownInput();
|
||||
inputShutdown = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the output stream for this socket.
|
||||
*/
|
||||
public void shutdownOutput()
|
||||
throws IOException
|
||||
{
|
||||
if (isSocketClosed()) {
|
||||
throw new SocketException("ZeroTierSocket is closed");
|
||||
}
|
||||
if (isOutputStreamShutdown()) {
|
||||
throw new SocketException("ZeroTierSocket output is already shutdown");
|
||||
}
|
||||
if (!isSocketConnected()) {
|
||||
throw new SocketException("ZeroTierSocket is not connected");
|
||||
}
|
||||
getImpl().shutdownOutput();
|
||||
outputShutdown = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the underlying implementation's file descriptor.
|
||||
*/
|
||||
/*
|
||||
public FileDescriptor getFileDescriptor()
|
||||
{
|
||||
return impl.getFileDescriptor();
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
// Designed to transport address information across the JNI boundary
|
||||
public class ZeroTierSocketAddress
|
||||
{
|
||||
public byte[] _ip6 = new byte[16];
|
||||
public byte[] _ip4 = new byte[4];
|
||||
|
||||
public int _family;
|
||||
public int _port; // Also reused for netmask or prefix
|
||||
|
||||
public ZeroTierSocketAddress() {}
|
||||
|
||||
public ZeroTierSocketAddress(String ipStr, int port)
|
||||
{
|
||||
if(ipStr.contains(":")) {
|
||||
_family = ZeroTier.AF_INET6;
|
||||
try {
|
||||
InetAddress ip = InetAddress.getByName(ipStr);
|
||||
_ip6 = ip.getAddress();
|
||||
}
|
||||
catch (Exception e) { }
|
||||
}
|
||||
else if(ipStr.contains(".")) {
|
||||
_family = ZeroTier.AF_INET;
|
||||
try {
|
||||
InetAddress ip = InetAddress.getByName(ipStr);
|
||||
_ip4 = ip.getAddress();
|
||||
}
|
||||
catch (Exception e) { }
|
||||
}
|
||||
_port = port;
|
||||
}
|
||||
|
||||
public int getPort() { return _port; }
|
||||
public int getNetmask() { return _port; }
|
||||
public int getPrefix() { return _port; }
|
||||
|
||||
public String ipString()
|
||||
{
|
||||
if (_family == ZeroTier.AF_INET) {
|
||||
try {
|
||||
InetAddress inet = InetAddress.getByAddress(_ip4);
|
||||
return "" + inet.getHostAddress();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
if (_family == ZeroTier.AF_INET6) {
|
||||
try {
|
||||
InetAddress inet = InetAddress.getByAddress(_ip6);
|
||||
return "" + inet.getHostAddress();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public String toString() { return ipString() + ":" + _port; }
|
||||
public String toCIDR() { return ipString() + "/" + _port; }
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
import com.zerotier.libzt.ZeroTierSocket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ZeroTierSocketFactory extends SocketFactory
|
||||
{
|
||||
public ZeroTierSocketFactory() { }
|
||||
|
||||
public static SocketFactory getDefault()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Socket createSocket()
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return new ZeroTierSocket();
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return new ZeroTierSocket(host, port);
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return new ZeroTierSocket(host, port, localHost, localPort);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
return new ZeroTierSocket(host, port);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return new ZeroTierSocket(address, port, localAddress, localPort);
|
||||
}
|
||||
}
|
||||
@@ -1,771 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
import com.zerotier.libzt.ZeroTierSocketAddress;
|
||||
import com.zerotier.libzt.ZeroTierInputStream;
|
||||
import com.zerotier.libzt.ZeroTierOutputStream;
|
||||
import com.zerotier.libzt.ZeroTierSocketOptionValue;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.Objects;
|
||||
import java.lang.Object;
|
||||
import java.net.SocketImpl;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Set;
|
||||
import java.lang.Boolean;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
|
||||
public class ZeroTierSocketImpl extends SocketImpl
|
||||
{
|
||||
private int defaultProtocol = 0;
|
||||
|
||||
/*
|
||||
* File descriptor from lower native layer
|
||||
*/
|
||||
private int zfd = -1;
|
||||
private int zfd4 = -1;
|
||||
private int zfd6 = -1;
|
||||
|
||||
/*
|
||||
* Input and Output streams
|
||||
*/
|
||||
private ZeroTierInputStream in = new ZeroTierInputStream();
|
||||
private ZeroTierOutputStream out = new ZeroTierOutputStream();
|
||||
|
||||
Socket socket = null;
|
||||
ServerSocket serverSocket = null;
|
||||
|
||||
/*
|
||||
* The remote address the socket is connected to
|
||||
*/
|
||||
protected InetAddress address;
|
||||
|
||||
/*
|
||||
* Sets the underlying file descriptor valud for the SocketImpl as well as the Input/OutputStream
|
||||
*/
|
||||
private void setNativeFileDescriptor(int fd)
|
||||
{
|
||||
zfd = fd;
|
||||
in.zfd = fd;
|
||||
out.zfd = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Various socket options that are cached from calls to setOption() before
|
||||
* the socket exists.
|
||||
*/
|
||||
private int _so_rcvtimeo;
|
||||
private boolean _so_keepalive;
|
||||
private int _so_sndbuf;
|
||||
private int _so_rcvbuf;
|
||||
private boolean _so_reuseaddr;
|
||||
private int _so_linger;
|
||||
private int _so_tos;
|
||||
private boolean _so_nodelay;
|
||||
|
||||
private void setCachedSocketOptions(int fd)
|
||||
{
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we previously received a setSoTimeout() call but were unable to process it due
|
||||
// to the fact that the underlying socket didn't even exist yet, do so now.
|
||||
int err = 0;
|
||||
ZeroTierSocketOptionValue optval = new ZeroTierSocketOptionValue();
|
||||
|
||||
try {
|
||||
// SO_TIMEOUT
|
||||
if (_so_rcvtimeo > 0) {
|
||||
optval.isInteger = true;
|
||||
optval.isBoolean = false;
|
||||
optval.integerValue = ((Integer)_so_rcvtimeo).intValue();
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_RCVTIMEO, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_RCVTIMEO");
|
||||
}
|
||||
}
|
||||
// SO_KEEPALIVE
|
||||
if (_so_keepalive == true) {
|
||||
optval.isInteger = false;
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)_so_keepalive).booleanValue() ? true : false;
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_KEEPALIVE, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_KEEPALIVE");
|
||||
}
|
||||
}
|
||||
// SO_SNDBUF
|
||||
if (_so_sndbuf > 0) {
|
||||
optval.isInteger = true;
|
||||
optval.isBoolean = false;
|
||||
optval.integerValue = ((Integer)_so_sndbuf).intValue();
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_SNDBUF, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_SNDBUF");
|
||||
}
|
||||
}
|
||||
// SO_RCVBUF
|
||||
if (_so_rcvbuf > 0) {
|
||||
optval.isInteger = true;
|
||||
optval.isBoolean = false;
|
||||
optval.integerValue = ((Integer)_so_rcvbuf).intValue();
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_RCVBUF, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_RCVBUF");
|
||||
}
|
||||
}
|
||||
// SO_REUSEADDR
|
||||
if (_so_reuseaddr == true) {
|
||||
optval.isInteger = false;
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)_so_reuseaddr).booleanValue() ? true : false;
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_REUSEADDR, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_REUSEADDR");
|
||||
}
|
||||
}
|
||||
// SO_LINGER
|
||||
if (_so_linger > 0) {
|
||||
optval.isInteger = true;
|
||||
optval.isBoolean = false;
|
||||
optval.integerValue = ((Integer)_so_linger).intValue();
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.SO_LINGER, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached SO_LINGER");
|
||||
}
|
||||
}
|
||||
// IP_TOS
|
||||
if (_so_tos > 0) {
|
||||
optval.isInteger = true;
|
||||
optval.isBoolean = false;
|
||||
optval.integerValue = ((Integer)_so_tos).intValue();
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.IP_TOS, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached IP_TOS");
|
||||
}
|
||||
}
|
||||
// TCP_NODELAY
|
||||
if (_so_nodelay == true) {
|
||||
optval.isInteger = false;
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)_so_nodelay).booleanValue() ? true : false;
|
||||
if ((err = ZeroTier.setsockopt(fd, ZeroTier.SOL_SOCKET, ZeroTier.TCP_NODELAY, optval)) < 0) {
|
||||
throw new IOException("socket("+fd+"), errno="+err+", unable to set previously cached TCP_NODELAY");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor which creates a new ZeroTierSocketImpl
|
||||
*/
|
||||
public ZeroTierSocketImpl()
|
||||
{
|
||||
if ((zfd > -1) | (zfd4 > -1) | (zfd6 > -1)) { return; }
|
||||
try {
|
||||
create(true);
|
||||
} catch (Exception x) {
|
||||
System.err.println("error creating ZeroTierSocketImpl instance: " + x);
|
||||
}
|
||||
in.zfd = zfd;
|
||||
out.zfd = zfd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor to be called when an underlying ZeroTier socket already exists (does not create a new ZeroTierSocketImpl)
|
||||
*/
|
||||
public ZeroTierSocketImpl(int fd) {
|
||||
setNativeFileDescriptor(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new ZeroTier socket in the native layer
|
||||
*/
|
||||
protected void create(boolean stream)
|
||||
throws IOException
|
||||
{
|
||||
/*
|
||||
* The native-layer socket is only created once a connect/bind call is made, this is due to the fact
|
||||
* that beforehand we have no way to determine whether we should create an AF_INET or AF_INET6 socket,
|
||||
* as a result, this method intentionally does nothing.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates the underlying libzt socket.
|
||||
*
|
||||
* This does the real work that can't be done in the constructor. This is because the socket address type
|
||||
* isn't known until a connect() or bind() request is given. Additionally we cache the value provided by any
|
||||
* setSoTimeout() calls and implement it immediately after creation.
|
||||
*/
|
||||
private void createAppropriateSocketImpl(InetAddress addr)
|
||||
throws IOException
|
||||
{
|
||||
if ((zfd > -1) | (zfd4 > -1) | (zfd6 > -1)) {
|
||||
return; // Socket already created
|
||||
}
|
||||
if(addr instanceof Inet4Address) {
|
||||
if ((zfd4 = ZeroTier.socket(ZeroTier.AF_INET, ZeroTier.SOCK_STREAM, defaultProtocol)) < 0) {
|
||||
throw new IOException("socket(), errno="+zfd4+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setCachedSocketOptions(zfd4);
|
||||
}
|
||||
/*
|
||||
* Since Java creates sockets capable of handling IPV4 and IPV6, we must simulate this. We do this by
|
||||
* creating two sockets (one of each type)
|
||||
*/
|
||||
if(addr instanceof Inet6Address) {
|
||||
if ((zfd4 = ZeroTier.socket(ZeroTier.AF_INET, ZeroTier.SOCK_STREAM, defaultProtocol)) < 0) {
|
||||
throw new IOException("socket(), errno="+zfd4+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
if ((zfd6 = ZeroTier.socket(ZeroTier.AF_INET6, ZeroTier.SOCK_STREAM, defaultProtocol)) < 0) {
|
||||
throw new IOException("socket(), errno="+zfd6+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setCachedSocketOptions(zfd4);
|
||||
setCachedSocketOptions(zfd6);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the remote address the socket is connected to
|
||||
*/
|
||||
protected InetAddress getInetAddress()
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects the socket to a remote address
|
||||
*/
|
||||
protected void connect(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
// TODO: Refactor and consolidate the connect() logic for all three methods
|
||||
createAppropriateSocketImpl(InetAddress.getByName(host));
|
||||
if ((zfd4 < 0) & (zfd6 < 0)) {
|
||||
throw new IOException("invalid fd");
|
||||
}
|
||||
int err;
|
||||
InetAddress address = InetAddress.getByName(host);
|
||||
ZeroTierSocketAddress zt_addr = new ZeroTierSocketAddress(host, port);
|
||||
if (address instanceof Inet4Address) {
|
||||
if ((err = ZeroTier.connect(zfd4, zt_addr)) < 0) {
|
||||
throw new IOException("connect(), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd4);
|
||||
}
|
||||
if (address instanceof Inet6Address) {
|
||||
if ((err = ZeroTier.connect(zfd6, zt_addr)) < 0) {
|
||||
throw new IOException("connect(), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd6);
|
||||
}
|
||||
super.port = port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects the socket to a remote address
|
||||
*/
|
||||
protected void connect(InetAddress address, int port)
|
||||
throws IOException
|
||||
{
|
||||
// TODO: Refactor and consolidate the connect() logic for all three methods
|
||||
createAppropriateSocketImpl(address);
|
||||
if ((zfd4 < 0) & (zfd6 < 0)) {
|
||||
throw new IOException("invalid fd");
|
||||
}
|
||||
int err;
|
||||
ZeroTierSocketAddress zt_addr = new ZeroTierSocketAddress(address.getHostAddress(), port);
|
||||
if (address instanceof Inet4Address) {
|
||||
if ((err = ZeroTier.connect(zfd4, zt_addr)) < 0) {
|
||||
throw new IOException("connect(), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd4);
|
||||
}
|
||||
if (address instanceof Inet6Address) {
|
||||
if ((err = ZeroTier.connect(zfd6, zt_addr)) < 0) {
|
||||
throw new IOException("connect(), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd6);
|
||||
}
|
||||
super.port = port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects the socket to a remote address
|
||||
*/
|
||||
protected void connect(SocketAddress address, int timeout)
|
||||
throws IOException
|
||||
{
|
||||
// TODO: Refactor and consolidate the connect() logic for all three methods
|
||||
//System.out.println("host="+((InetSocketAddress)address).getHostString()+", port="+((InetSocketAddress)address).getPort() + ", timeout="+timeout);
|
||||
createAppropriateSocketImpl(((InetSocketAddress)address).getAddress());
|
||||
if ((zfd4 < 0) & (zfd6 < 0)) {
|
||||
throw new IOException("invalid fd");
|
||||
}
|
||||
ZeroTierSocketAddress zt_addr = null;
|
||||
int err;
|
||||
int port = ((InetSocketAddress)address).getPort();
|
||||
if (((InetSocketAddress)address).getAddress() instanceof Inet4Address) {
|
||||
zt_addr = new ZeroTierSocketAddress(((InetSocketAddress)address).getHostString(), ((InetSocketAddress)address).getPort());
|
||||
if ((err = ZeroTier.connect(zfd4, zt_addr)) < 0) {
|
||||
throw new IOException("connect("+zfd4+"), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd4);
|
||||
}
|
||||
if (((InetSocketAddress)address).getAddress() instanceof Inet6Address) {
|
||||
zt_addr = new ZeroTierSocketAddress(((InetSocketAddress)address).getHostString(), ((InetSocketAddress)address).getPort());
|
||||
if ((err = ZeroTier.connect(zfd6, zt_addr)) < 0) {
|
||||
throw new IOException("connect("+zfd6+"), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
setNativeFileDescriptor(zfd6);
|
||||
}
|
||||
super.port = port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Binds the socket to a local address.
|
||||
*
|
||||
* If this gets a bind() request on [::] it will create a both an IPv4 and an IPv6
|
||||
* socket. This is because we might receive a subsequent listen() and accept() request
|
||||
* and want to accept an IPv6 connection. (or) we may get a connect() request with
|
||||
* an IPv4 address. In the latter case we must abandon the IPv6 socket and use the IPv4
|
||||
* socket exclusively.
|
||||
*/
|
||||
protected void bind(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
createAppropriateSocketImpl(host);
|
||||
/*
|
||||
After this point we may have either a) created a single IPv4 socket, or b) created
|
||||
an IPv4 and IPv6 socket in anticipation of either verion being used
|
||||
*/
|
||||
//System.out.println("host="+host.toString()+", port="+port);
|
||||
int err;
|
||||
if ((zfd < 0) & (zfd4 < 0) & (zfd6 < 0)) {
|
||||
throw new IOException("invalid fd");
|
||||
}
|
||||
ZeroTierSocketAddress zt_addr = new ZeroTierSocketAddress(host.getHostAddress(), port);
|
||||
|
||||
if (zfd6 > -1) {
|
||||
// Since an IPv6 socket and accept IPv4 connections we will only bind to this address
|
||||
if ((err = ZeroTier.bind(zfd6, zt_addr)) < 0) {
|
||||
throw new IOException("bind("+zfd6+"), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
super.localport = port;
|
||||
return;
|
||||
}
|
||||
if (zfd4 > -1) {
|
||||
// Otherwise, just bind to the regular IPv4 address
|
||||
if ((err = ZeroTier.bind(zfd4, zt_addr)) < 0) {
|
||||
throw new IOException("bind("+zfd4+"), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
super.localport = port;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Puts the socket into a listening state.
|
||||
*
|
||||
* We listen on the IPv6 socket since it can listen for IPv4 connections
|
||||
*/
|
||||
protected void listen(int backlog)
|
||||
throws IOException
|
||||
{
|
||||
int err;
|
||||
if ((zfd6 < 0) | (backlog < 0)) {
|
||||
throw new IOException("invalid fd and/or backlog");
|
||||
}
|
||||
if ((err = ZeroTier.listen(zfd6, backlog)) < 0) {
|
||||
throw new IOException("listen("+zfd6+"), errno="+err+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Accepts an incoming connection.
|
||||
*
|
||||
* We accept on the IPv6 socket since it can accept IPv4 connections
|
||||
*/
|
||||
protected void accept(SocketImpl si)
|
||||
throws IOException
|
||||
{
|
||||
if (zfd6 < 0) {
|
||||
throw new IOException("invalid fd");
|
||||
}
|
||||
int accetpedFd = -1;
|
||||
ZeroTierSocketAddress addr = new ZeroTierSocketAddress();
|
||||
if ((accetpedFd = ZeroTier.accept(zfd6, addr)) < 0) {
|
||||
throw new IOException("accept("+zfd6+"), errno="+accetpedFd+", see: libzt/ext/lwip/src/include/errno.h");
|
||||
}
|
||||
// Give the new socket fd from the native layer to the new unconnected ZeroTierSocketImpl
|
||||
((ZeroTierSocketImpl)si).setFileDescriptor(accetpedFd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the input stream for this socket
|
||||
*/
|
||||
protected ZeroTierInputStream getInputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (in == null) {
|
||||
throw new IOException();
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the output stream for this socket
|
||||
*/
|
||||
protected ZeroTierOutputStream getOutputStream()
|
||||
throws IOException
|
||||
{
|
||||
if (out == null) {
|
||||
throw new IOException();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the remote port to which this socket is connected
|
||||
*/
|
||||
protected int getPort()
|
||||
{
|
||||
return super.port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the local port to which this socket is bound
|
||||
*/
|
||||
protected int getLocalPort()
|
||||
{
|
||||
return super.localport;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether this socket implementation supports urgent data (hint: it doesn't)
|
||||
*/
|
||||
protected boolean supportsUrgentData()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void setSocket(ZeroTierSocket soc)
|
||||
{
|
||||
this.socket = soc;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
Socket getSocket()
|
||||
{
|
||||
return socket;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
/*
|
||||
void setServerSocket(ZeroTierServerSocket soc)
|
||||
{
|
||||
this.serverSocket = soc;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
ServerSocket getServerSocket()
|
||||
{
|
||||
return serverSocket;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of bytes that can be read from the socket without blocking
|
||||
*/
|
||||
protected int available()
|
||||
throws IOException
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the socket
|
||||
*/
|
||||
protected void close()
|
||||
throws IOException
|
||||
{
|
||||
if (zfd > -1) {
|
||||
ZeroTier.close(zfd);
|
||||
}
|
||||
if (zfd4 > -1) {
|
||||
ZeroTier.close(zfd4);
|
||||
}
|
||||
if (zfd6 > -1) {
|
||||
ZeroTier.close(zfd6);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send one byte of urgent data on the socket
|
||||
*/
|
||||
protected void sendUrgentData(int data)
|
||||
throws IOException
|
||||
{
|
||||
System.err.println("sendUrgentData: ZeroTierSocketImpl does not currently support this feature");
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets some specified socket option
|
||||
*/
|
||||
public Object getOption(int optID)
|
||||
throws SocketException
|
||||
{
|
||||
// Call native layer
|
||||
ZeroTierSocketOptionValue optval = new ZeroTierSocketOptionValue();
|
||||
int option = -1;
|
||||
int level = -1;
|
||||
|
||||
if (zfd < 0) { // If we haven't committed to a socket version yet, cache the value
|
||||
if (optID == SocketOptions.SO_TIMEOUT || optID == ZeroTier.SO_RCVTIMEO) {
|
||||
return Integer.valueOf(_so_rcvtimeo);
|
||||
}
|
||||
if (optID == SocketOptions.SO_KEEPALIVE || optID == ZeroTier.SO_KEEPALIVE) {
|
||||
return Boolean.valueOf(_so_keepalive);
|
||||
}
|
||||
if (optID == SocketOptions.SO_SNDBUF || optID == ZeroTier.SO_SNDBUF) {
|
||||
return Integer.valueOf(_so_sndbuf);
|
||||
}
|
||||
if (optID == SocketOptions.SO_RCVBUF || optID == ZeroTier.SO_RCVBUF) {
|
||||
return Integer.valueOf(_so_rcvbuf);
|
||||
}
|
||||
if (optID == SocketOptions.SO_REUSEADDR || optID == ZeroTier.SO_REUSEADDR) {
|
||||
return Boolean.valueOf(_so_reuseaddr);
|
||||
}
|
||||
if (optID == SocketOptions.SO_LINGER || optID == ZeroTier.SO_LINGER) {
|
||||
return Integer.valueOf(_so_linger);
|
||||
}
|
||||
if (optID == SocketOptions.IP_TOS || optID == ZeroTier.IP_TOS) {
|
||||
return Integer.valueOf(_so_tos);
|
||||
}
|
||||
if (optID == SocketOptions.TCP_NODELAY || optID == ZeroTier.TCP_NODELAY) {
|
||||
return Boolean.valueOf(_so_nodelay);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (optID == SocketOptions.SO_TIMEOUT || optID == ZeroTier.SO_RCVTIMEO) {
|
||||
option = ZeroTier.SO_RCVTIMEO;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
if (optID == SocketOptions.SO_KEEPALIVE || optID == ZeroTier.SO_KEEPALIVE) {
|
||||
option = ZeroTier.SO_KEEPALIVE;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
if (optID == SocketOptions.SO_SNDBUF || optID == ZeroTier.SO_SNDBUF) {
|
||||
option = ZeroTier.SO_SNDBUF;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
if (optID == SocketOptions.SO_RCVBUF || optID == ZeroTier.SO_RCVBUF) {
|
||||
option = ZeroTier.SO_RCVBUF;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
if (optID == SocketOptions.SO_REUSEADDR || optID == ZeroTier.SO_REUSEADDR) {
|
||||
option = ZeroTier.SO_REUSEADDR;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
if (optID == SocketOptions.SO_LINGER || optID == ZeroTier.SO_LINGER) {
|
||||
option = ZeroTier.SO_LINGER;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
}
|
||||
// IP
|
||||
if (optID == SocketOptions.IP_TOS || optID == ZeroTier.IP_TOS) {
|
||||
option = ZeroTier.IP_TOS;
|
||||
level = ZeroTier.IPPROTO_IP;
|
||||
}
|
||||
// TCP
|
||||
if (optID == SocketOptions.TCP_NODELAY || optID == ZeroTier.TCP_NODELAY) {
|
||||
option = ZeroTier.TCP_NODELAY;
|
||||
level = ZeroTier.IPPROTO_TCP;
|
||||
}
|
||||
ZeroTier.getsockopt(zfd, level, option, optval);
|
||||
// Convert native layer's response into Java object of some sort
|
||||
if (optval.isBoolean) {
|
||||
return Boolean.valueOf(optval.booleanValue);
|
||||
}
|
||||
if (optval.isInteger) {
|
||||
return Integer.valueOf(optval.integerValue);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets a socket option to a specified value. This method should be able to handle SocketOptions values
|
||||
* as well as native ZeroTier.* options
|
||||
*/
|
||||
public void setOption(int optID, Object value)
|
||||
throws SocketException
|
||||
{
|
||||
if (value == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
int option = -1;
|
||||
int level = -1;
|
||||
|
||||
ZeroTierSocketOptionValue optval = new ZeroTierSocketOptionValue();
|
||||
|
||||
if (zfd < 0) { // If we haven't committed to a socket version yet, cache the value
|
||||
if (optID == SocketOptions.SO_TIMEOUT || optID == ZeroTier.SO_RCVTIMEO) {
|
||||
_so_rcvtimeo = ((Integer)value).intValue(); return;
|
||||
}
|
||||
if (optID == SocketOptions.SO_KEEPALIVE || optID == ZeroTier.SO_KEEPALIVE) {
|
||||
_so_keepalive = ((Boolean)value).booleanValue() ? true : false; return;
|
||||
}
|
||||
if (optID == SocketOptions.SO_SNDBUF || optID == ZeroTier.SO_SNDBUF) {
|
||||
_so_sndbuf = ((Integer)value).intValue(); return;
|
||||
}
|
||||
if (optID == SocketOptions.SO_RCVBUF || optID == ZeroTier.SO_RCVBUF) {
|
||||
_so_rcvbuf = ((Integer)value).intValue(); return;
|
||||
}
|
||||
if (optID == SocketOptions.SO_REUSEADDR || optID == ZeroTier.SO_REUSEADDR) {
|
||||
_so_reuseaddr = ((Boolean)value).booleanValue() ? true : false; return;
|
||||
}
|
||||
if (optID == SocketOptions.SO_LINGER || optID == ZeroTier.SO_LINGER) {
|
||||
_so_linger = ((Integer)value).intValue(); return;
|
||||
}
|
||||
if (optID == SocketOptions.IP_TOS || optID == ZeroTier.IP_TOS) {
|
||||
_so_tos = ((Integer)value).intValue(); return;
|
||||
}
|
||||
if (optID == SocketOptions.TCP_NODELAY || optID == ZeroTier.TCP_NODELAY) {
|
||||
_so_nodelay = ((Boolean)value).booleanValue() ? true : false; return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// SOL
|
||||
if (optID == SocketOptions.SO_TIMEOUT || optID == ZeroTier.SO_RCVTIMEO) {
|
||||
option = ZeroTier.SO_RCVTIMEO;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isInteger = true;
|
||||
optval.integerValue = ((Integer)value).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (optID == SocketOptions.SO_KEEPALIVE || optID == ZeroTier.SO_KEEPALIVE) {
|
||||
option = ZeroTier.SO_KEEPALIVE;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)value).booleanValue() ? true : false;
|
||||
}
|
||||
}
|
||||
if (optID == SocketOptions.SO_SNDBUF || optID == ZeroTier.SO_SNDBUF) {
|
||||
option = ZeroTier.SO_SNDBUF;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isInteger = true;
|
||||
optval.integerValue = ((Integer)value).intValue();
|
||||
}
|
||||
}
|
||||
if (optID == SocketOptions.SO_RCVBUF || optID == ZeroTier.SO_RCVBUF) {
|
||||
option = ZeroTier.SO_RCVBUF;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isInteger = true;
|
||||
optval.integerValue = ((Integer)value).intValue();
|
||||
}
|
||||
}
|
||||
if (optID == SocketOptions.SO_REUSEADDR || optID == ZeroTier.SO_REUSEADDR) {
|
||||
option = ZeroTier.SO_REUSEADDR;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)value).booleanValue() ? true : false;
|
||||
}
|
||||
}
|
||||
if (optID == SocketOptions.SO_LINGER || optID == ZeroTier.SO_LINGER) {
|
||||
option = ZeroTier.SO_LINGER;
|
||||
level = ZeroTier.SOL_SOCKET;
|
||||
if (value instanceof Integer) {
|
||||
optval.isInteger = true;
|
||||
optval.integerValue = ((Integer)value).intValue();
|
||||
}
|
||||
}
|
||||
// IP
|
||||
if (optID == SocketOptions.IP_TOS || optID == ZeroTier.IP_TOS) {
|
||||
option = ZeroTier.IP_TOS;
|
||||
level = ZeroTier.IPPROTO_IP;
|
||||
if (value instanceof Integer) {
|
||||
optval.isInteger = true;
|
||||
optval.integerValue = ((Integer)value).intValue();
|
||||
}
|
||||
}
|
||||
// TCP
|
||||
if (optID == SocketOptions.TCP_NODELAY || optID == ZeroTier.TCP_NODELAY) {
|
||||
option = ZeroTier.TCP_NODELAY;
|
||||
level = ZeroTier.IPPROTO_TCP;
|
||||
if (value instanceof Integer) {
|
||||
optval.isBoolean = true;
|
||||
optval.booleanValue = ((Boolean)value).booleanValue() ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
if (option < 0) { // No option was properly set
|
||||
//throw new UnsupportedOperationException();
|
||||
}
|
||||
ZeroTier.setsockopt(zfd, level, option, optval);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables the input aspect of the socket
|
||||
*/
|
||||
public void shutdownInput()
|
||||
{
|
||||
ZeroTier.shutdown(zfd, ZeroTier.SHUT_RD);
|
||||
// Alternatively: getInputStream().close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables the output aspect of the socket
|
||||
*/
|
||||
public void shutdownOutput()
|
||||
{
|
||||
ZeroTier.shutdown(zfd, ZeroTier.SHUT_WR);
|
||||
// Alternatively: getOutputStream().close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the file descriptor
|
||||
*/
|
||||
public void setFileDescriptor(int fd)
|
||||
{
|
||||
zfd = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets the socket
|
||||
*/
|
||||
void reset()
|
||||
throws IOException
|
||||
{
|
||||
localport = 0;
|
||||
address = null;
|
||||
port = 0;
|
||||
}
|
||||
/*
|
||||
public FileDescriptor getFileDescriptor()
|
||||
{
|
||||
// TODO: Should probably remove this for production
|
||||
System.out.println("getFileDescriptor(), zfd="+zfd);
|
||||
ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(zfd);
|
||||
return pfd.getFileDescriptor();
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
import com.zerotier.libzt.ZeroTier;
|
||||
import com.zerotier.libzt.ZeroTierSocketImpl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
import java.net.SocketImplFactory;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class ZeroTierSocketImplFactory implements SocketImplFactory
|
||||
{
|
||||
/*
|
||||
* Does nothing
|
||||
*/
|
||||
public ZeroTierSocketImplFactory() { }
|
||||
|
||||
/*
|
||||
* Produces a ZeroTierSocketImpl
|
||||
*/
|
||||
public ZeroTierSocketImpl createSocketImpl()
|
||||
{
|
||||
return new ZeroTierSocketImpl();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.zerotier.libzt;
|
||||
|
||||
public class ZeroTierSocketOptionValue
|
||||
{
|
||||
public boolean isBoolean = false;
|
||||
public boolean booleanValue;
|
||||
|
||||
public boolean isInteger = false;
|
||||
public int integerValue;
|
||||
|
||||
public boolean isTimeval = false;
|
||||
public int tv_sec; // seconds
|
||||
public int tv_usec; // microseconds
|
||||
}
|
||||
Reference in New Issue
Block a user