2016-06-14 15:48:48 -07:00
|
|
|
/*
|
|
|
|
|
* ZeroTier One - Network Virtualization Everywhere
|
|
|
|
|
* Copyright (C) 2011-2015 ZeroTier, Inc.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*
|
|
|
|
|
* --
|
|
|
|
|
*
|
|
|
|
|
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
|
|
|
|
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
|
|
|
|
*
|
|
|
|
|
* If you would like to embed ZeroTier into a commercial application or
|
|
|
|
|
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
|
|
|
|
* LLC. Start here: http://www.zerotier.com/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if defined(__ANDROID__)
|
|
|
|
|
#include <jni.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
|
2016-07-17 20:56:42 -07:00
|
|
|
#include "OneService.hpp"
|
2016-06-14 15:48:48 -07:00
|
|
|
#include "Utils.hpp"
|
|
|
|
|
#include "OSUtils.hpp"
|
|
|
|
|
|
2016-08-08 12:31:06 -07:00
|
|
|
#include "SDK_EthernetTap.hpp"
|
2016-06-14 15:48:48 -07:00
|
|
|
#include "SDK.h"
|
|
|
|
|
#include "SDK_Debug.h"
|
|
|
|
|
|
|
|
|
|
std::string service_path;
|
|
|
|
|
pthread_t intercept_thread;
|
|
|
|
|
int * intercept_thread_id;
|
|
|
|
|
pthread_key_t thr_id_key;
|
|
|
|
|
static ZeroTier::OneService *volatile zt1Service;
|
2016-07-17 20:56:42 -07:00
|
|
|
|
|
|
|
|
std::string localHomeDir; // Local shortened path
|
|
|
|
|
std::string givenHomeDir; // What the user/application provides as a suggestion
|
|
|
|
|
std::string homeDir; // The resultant platform-specific dir we *must* use internally
|
2016-06-14 15:48:48 -07:00
|
|
|
std::string netDir;
|
2016-07-20 14:20:45 -07:00
|
|
|
std::string rpcNWID;
|
2016-06-14 15:48:48 -07:00
|
|
|
|
2016-07-18 01:42:18 -07:00
|
|
|
bool rpcEnabled;
|
|
|
|
|
|
2016-06-14 15:48:48 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-07-11 19:42:57 -05:00
|
|
|
void zt_init_rpc(const char * path, const char * nwid);
|
2016-08-04 13:10:12 -07:00
|
|
|
void dwr(int level, const char *fmt, ... );
|
2016-07-11 19:42:57 -05:00
|
|
|
|
2016-06-16 14:06:20 -07:00
|
|
|
#if defined(__UNITY_3D__)
|
|
|
|
|
// .NET Interop-friendly debug mechanism
|
|
|
|
|
typedef void (*FuncPtr)( const char * );
|
|
|
|
|
FuncPtr Debug;
|
|
|
|
|
void SetDebugFunction( FuncPtr fp ) { Debug = fp; }
|
|
|
|
|
|
2016-07-18 11:35:40 -07:00
|
|
|
// Starts a ZeroTier service at the given path
|
2016-06-16 14:06:20 -07:00
|
|
|
void unity_start_service(char * path, int len) {
|
2016-07-18 11:35:40 -07:00
|
|
|
std::string dstr = std::string(path);
|
|
|
|
|
dstr = "unity_start_service(): path = " + dstr;
|
|
|
|
|
Debug(dstr.c_str());
|
2016-06-16 14:06:20 -07:00
|
|
|
init_service(INTERCEPT_DISABLED, path);
|
|
|
|
|
}
|
2016-07-18 11:35:40 -07:00
|
|
|
// Starts a ZeroTier service and RPC
|
|
|
|
|
void unity_start_service_and_rpc(char * path, char *nwid, int len) {
|
|
|
|
|
std::string dstr = std::string(path);
|
|
|
|
|
dstr = "unity_start_service_and_rpc(): path = " + dstr;
|
|
|
|
|
Debug(dstr.c_str());
|
|
|
|
|
init_service_and_rpc(INTERCEPT_DISABLED, path, nwid);
|
|
|
|
|
}
|
2016-06-16 14:06:20 -07:00
|
|
|
#endif
|
|
|
|
|
|
2016-07-20 14:20:45 -07:00
|
|
|
|
2016-08-17 12:41:59 -07:00
|
|
|
int zts_start_proxy_server(const char *homepath, const char * nwid, struct sockaddr_storage * addr) {
|
|
|
|
|
LOGV("zts_start_proxy_server\n");
|
|
|
|
|
|
|
|
|
|
dwr(MSG_DEBUG, "zts_start_proxy_server()");
|
|
|
|
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
|
|
|
|
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
|
|
|
|
|
if(tap) {
|
|
|
|
|
if(tap->startProxyServer(homepath, nwid_int, addr) < 0) {
|
|
|
|
|
dwr(MSG_ERROR, "zts_start_proxy_server(%s): Problem while starting server.", nwid);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dwr(MSG_ERROR, "zts_start_proxy_server(%s): Invalid tap. Possibly incorrect NWID", nwid);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int zts_stop_proxy_server(const char *nwid) {
|
|
|
|
|
dwr(MSG_DEBUG, "zts_stop_proxy_server()");
|
|
|
|
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
|
|
|
|
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
|
|
|
|
|
if(tap) {
|
|
|
|
|
if(tap->stopProxyServer() < 0) {
|
|
|
|
|
dwr(MSG_ERROR, "zts_stop_proxy_server(%s): Problem while stopping server.", nwid);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dwr(MSG_ERROR, "zts_stop_proxy_server(%s): Invalid tap. Possibly incorrect NWID", nwid);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * addr) {
|
|
|
|
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
|
|
|
|
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
|
|
|
|
|
if(tap) {
|
|
|
|
|
tap->getProxyServerAddress(addr);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-20 14:20:45 -07:00
|
|
|
// Basic ZT service controls
|
2016-08-17 12:41:59 -07:00
|
|
|
// Will also spin up a SOCKS5 proxy server if USE_SOCKS_PROXY is set
|
2016-07-20 14:20:45 -07:00
|
|
|
void zts_join_network(const char * nwid) {
|
2016-08-17 12:41:59 -07:00
|
|
|
LOGV("zts_join_network\n");
|
2016-07-20 14:20:45 -07:00
|
|
|
std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
|
|
|
|
|
if(!ZeroTier::OSUtils::mkdir(netDir)) {
|
2016-08-04 13:10:12 -07:00
|
|
|
dwr(MSG_ERROR, "unable to create %s\n", netDir.c_str());
|
2016-06-14 15:48:48 -07:00
|
|
|
}
|
2016-07-20 14:20:45 -07:00
|
|
|
if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) {
|
2016-08-04 13:10:12 -07:00
|
|
|
dwr(MSG_ERROR, "unable to write network conf file: %s\n", confFile.c_str());
|
2016-07-20 14:20:45 -07:00
|
|
|
}
|
|
|
|
|
// Provide the API with the RPC information
|
|
|
|
|
zt_init_rpc(homeDir.c_str(), nwid);
|
2016-08-17 12:41:59 -07:00
|
|
|
|
|
|
|
|
// SOCKS5 Proxy server
|
|
|
|
|
// Default is 127.0.0.1:RANDOM_PORT
|
|
|
|
|
#if defined(USE_SOCKS_PROXY)
|
|
|
|
|
zts_start_proxy_server(homeDir.c_str(), nwid, NULL); // NULL addr for default
|
|
|
|
|
#endif
|
2016-07-20 14:20:45 -07:00
|
|
|
}
|
|
|
|
|
void zts_leave_network(const char * nwid) { zt1Service->leave(nwid); }
|
|
|
|
|
bool zts_is_running() { return zt1Service->isRunning(); }
|
2016-08-17 10:22:31 -07:00
|
|
|
void zts_stop_service() { zt1Service->terminate(); }
|
2016-07-12 02:44:17 -05:00
|
|
|
|
2016-08-11 23:34:40 -07:00
|
|
|
// FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations
|
|
|
|
|
// Now only returns first assigned address per network. Shouldn't normally be a problem
|
|
|
|
|
void zts_get_addresses(const char * nwid, char *addrstr)
|
2016-08-08 12:31:06 -07:00
|
|
|
{
|
2016-08-11 23:34:40 -07:00
|
|
|
uint64_t nwid_int = strtoull(nwid, NULL, 16);
|
|
|
|
|
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
|
|
|
|
|
if(tap && tap->_ips.size()){
|
|
|
|
|
std::string addr = tap->_ips[0].toString();
|
|
|
|
|
memcpy(addrstr, addr.c_str(), addr.length());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
memcpy(addrstr, "-1.-1.-1.-1/-1", 14);
|
|
|
|
|
}
|
|
|
|
|
/*
|
2016-08-08 12:31:06 -07:00
|
|
|
uint64_t nwid_int = strtoull(nwid.c_str(), NULL, 16);
|
|
|
|
|
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
|
|
|
|
|
std::vector<std::string> ip_strings;
|
|
|
|
|
if(tap) {
|
|
|
|
|
for(int i=0; i<tap->_ips.size(); i++) {
|
|
|
|
|
ip_strings.push_back(tap->_ips[i].toString());
|
|
|
|
|
}
|
|
|
|
|
return ip_strings;
|
|
|
|
|
}
|
|
|
|
|
return ip_strings;
|
2016-08-11 23:34:40 -07:00
|
|
|
*/
|
|
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
int zts_get_device_id() { /* TODO */ return 0; }
|
2016-08-11 23:34:40 -07:00
|
|
|
|
|
|
|
|
bool zts_is_relayed() {
|
|
|
|
|
// TODO
|
|
|
|
|
// zt1Service->getNode()->peers()
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-24 13:08:19 -07:00
|
|
|
char *zts_get_homepath() {
|
|
|
|
|
return (char*)givenHomeDir.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-18 11:35:40 -07:00
|
|
|
// Android JNI wrapper
|
2016-07-20 14:20:45 -07:00
|
|
|
// JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME
|
2016-07-12 02:44:17 -05:00
|
|
|
#if defined(__ANDROID__)
|
2016-08-15 17:29:02 -07:00
|
|
|
// Join a network
|
2016-07-20 14:20:45 -07:00
|
|
|
JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1join_1network(JNIEnv *env, jobject thisObj, jstring nwid) {
|
2016-07-12 02:44:17 -05:00
|
|
|
const char *nwidstr;
|
|
|
|
|
if(nwid) {
|
|
|
|
|
nwidstr = env->GetStringUTFChars(nwid, NULL);
|
2016-07-20 14:20:45 -07:00
|
|
|
zts_join_network(nwidstr);
|
2016-07-12 02:44:17 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
// Leave a network
|
2016-07-20 14:20:45 -07:00
|
|
|
JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1leave_1network(JNIEnv *env, jobject thisObj, jstring nwid) {
|
2016-07-12 02:44:17 -05:00
|
|
|
const char *nwidstr;
|
|
|
|
|
if(nwid) {
|
|
|
|
|
nwidstr = env->GetStringUTFChars(nwid, NULL);
|
2016-07-20 14:20:45 -07:00
|
|
|
zts_leave_network(nwidstr);
|
2016-07-12 02:44:17 -05:00
|
|
|
}
|
|
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
// Returns whether the ZeroTier service is running
|
2016-07-20 14:20:45 -07:00
|
|
|
JNIEXPORT jboolean JNICALL Java_ZeroTier_SDK_zt_1running(JNIEnv *env, jobject thisObj) {
|
2016-07-12 02:44:17 -05:00
|
|
|
if(zt1Service)
|
2016-07-20 14:20:45 -07:00
|
|
|
return zts_is_running();
|
2016-07-12 02:44:17 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
// Shuts down ZeroTier service and SOCKS5 Proxy server
|
2016-08-17 10:22:31 -07:00
|
|
|
JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1stop_1service(JNIEnv *env, jobject thisObj) {
|
2016-07-14 22:43:37 +02:00
|
|
|
if(zt1Service)
|
2016-08-17 10:22:31 -07:00
|
|
|
zts_stop_service();
|
2016-08-15 17:29:02 -07:00
|
|
|
// TODO: Also terminate SOCKS5 Proxy
|
|
|
|
|
// zts_stop_proxy_server();
|
2016-07-14 22:43:37 +02:00
|
|
|
}
|
2016-08-11 23:34:40 -07:00
|
|
|
// FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations
|
|
|
|
|
// Now only returns first assigned address per network. Shouldn't normally be a problem
|
2016-08-08 12:31:06 -07:00
|
|
|
JNIEXPORT jobject JNICALL Java_ZeroTier_SDK_zt_1get_1addresses(JNIEnv *env, jobject thisObj, jstring nwid) {
|
|
|
|
|
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
|
2016-08-11 23:34:40 -07:00
|
|
|
char address_string[32];
|
|
|
|
|
memset(address_string, 0, 32);
|
|
|
|
|
zts_get_addresses(nwid_str, address_string);
|
|
|
|
|
jclass clazz = (*env).FindClass("java/util/ArrayList");
|
|
|
|
|
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
|
|
|
|
|
jstring _str = (*env).NewStringUTF(address_string);
|
|
|
|
|
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
|
return addresses;
|
|
|
|
|
/*
|
|
|
|
|
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
|
|
|
|
|
std::vector<std::string> address_strings = zts_get_addresses(nwid_str);
|
2016-08-08 12:31:06 -07:00
|
|
|
jclass clazz = (*env).FindClass("java/util/ArrayList");
|
|
|
|
|
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
|
|
|
|
|
if(address_strings.size()) {
|
|
|
|
|
for (int n=0;n<address_strings.size();n++) {
|
|
|
|
|
jstring _str = (*env).NewStringUTF(address_strings[n].c_str());
|
|
|
|
|
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { // Add dummy value
|
|
|
|
|
jstring _str = (*env).NewStringUTF("-1.-1.-1.-1/-1");
|
|
|
|
|
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
|
|
|
|
|
}
|
|
|
|
|
return addresses;
|
2016-08-11 23:34:40 -07:00
|
|
|
*/
|
2016-08-08 12:31:06 -07:00
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
// Returns the device is in integer form
|
|
|
|
|
JNIEXPORT jint Java_ZeroTier_SDK_zt_1get_1device_1id() {
|
|
|
|
|
return zts_get_device_id();
|
|
|
|
|
}
|
|
|
|
|
// Returns whether the path to an endpoint is currently relayed by a root server
|
2016-08-11 23:34:40 -07:00
|
|
|
JNIEXPORT jboolean JNICALL Java_ZeroTier_SDK_zt_1is_1relayed() {
|
|
|
|
|
return zts_is_relayed();
|
|
|
|
|
}
|
2016-08-15 17:29:02 -07:00
|
|
|
// Returns the local address of the SOCKS5 Proxy server
|
|
|
|
|
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1get_1proxy_1server_1address(JNIEnv *env, jobject thisObj, jstring nwid, jobject ztaddr) {
|
2016-08-24 13:08:19 -07:00
|
|
|
struct sockaddr_in addr;
|
|
|
|
|
int err = zts_get_proxy_server_address(env->GetStringUTFChars(nwid, NULL), (struct sockaddr_storage*)&addr);
|
|
|
|
|
// SET ZTAddress fields
|
|
|
|
|
jfieldID fid;
|
|
|
|
|
jclass cls = env->GetObjectClass(ztaddr);
|
|
|
|
|
fid = env->GetFieldID(cls, "port", "I");
|
|
|
|
|
env->SetIntField(ztaddr, fid, addr.sin_port);
|
|
|
|
|
fid = env->GetFieldID(cls,"_rawAddr", "J");
|
|
|
|
|
env->SetLongField(ztaddr, fid,addr.sin_addr.s_addr);
|
|
|
|
|
return err;
|
2016-08-15 17:29:02 -07:00
|
|
|
}
|
|
|
|
|
// Starts a SOCKS5 proxy server for a given ZeroTier network
|
|
|
|
|
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1start_1proxy_1server(JNIEnv *env, jobject thisObj, jstring nwid, jobject ztaddr) {
|
2016-08-24 13:08:19 -07:00
|
|
|
const char *nwidstr = env->GetStringUTFChars(nwid, NULL);
|
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
|
// GET ZTAddress fields
|
|
|
|
|
jclass cls = env->GetObjectClass(ztaddr);
|
|
|
|
|
jfieldID fid = env->GetFieldID(cls, "port", "I");
|
|
|
|
|
addr.sin_port = htons(env->GetIntField(ztaddr, fid));
|
|
|
|
|
fid = env->GetFieldID(cls, "_rawAddr", "J");
|
|
|
|
|
addr.sin_addr.s_addr = env->GetLongField(ztaddr, fid);
|
|
|
|
|
return zts_start_proxy_server((char *)zts_get_homepath, nwidstr, (struct sockaddr_storage *)&addr);
|
2016-08-15 17:29:02 -07:00
|
|
|
}
|
2016-08-24 13:08:19 -07:00
|
|
|
//
|
2016-08-15 17:29:02 -07:00
|
|
|
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1stop_1proxy_1server(JNIEnv *env, jobject thisObj, jstring nwid) {
|
2016-08-24 13:08:19 -07:00
|
|
|
return zts_stop_proxy_server((char*)env->GetStringUTFChars(nwid, NULL));
|
|
|
|
|
}
|
|
|
|
|
JNIEXPORT jstring JNICALL Java_ZeroTier_SDK_zt_1get_1homepath(JNIEnv *env, jobject thisObj) {
|
|
|
|
|
return (*env).NewStringUTF(zts_get_homepath());
|
2016-08-11 23:34:40 -07:00
|
|
|
}
|
2016-07-12 02:44:17 -05:00
|
|
|
#endif
|
|
|
|
|
|
2016-08-08 12:31:06 -07:00
|
|
|
|
2016-07-18 11:35:40 -07:00
|
|
|
// Typically used on iOS/OSX
|
2016-06-14 15:48:48 -07:00
|
|
|
#if !defined(__ANDROID__)
|
|
|
|
|
/*
|
|
|
|
|
* Starts a service thread and performs basic setup tasks
|
|
|
|
|
*/
|
2016-07-17 20:56:42 -07:00
|
|
|
void init_service(int key, const char * path) {
|
|
|
|
|
givenHomeDir = path;
|
2016-06-14 15:48:48 -07:00
|
|
|
pthread_key_create(&thr_id_key, NULL);
|
|
|
|
|
intercept_thread_id = (int*)malloc(sizeof(int));
|
|
|
|
|
*intercept_thread_id = key;
|
2016-07-20 14:20:45 -07:00
|
|
|
pthread_create(&intercept_thread, NULL, zt_start_service, (void *)(intercept_thread_id));
|
2016-06-14 15:48:48 -07:00
|
|
|
}
|
2016-07-18 01:42:18 -07:00
|
|
|
void init_service_and_rpc(int key, const char * path, const char * nwid) {
|
|
|
|
|
rpcEnabled = true;
|
|
|
|
|
rpcNWID = nwid;
|
2016-07-17 20:56:42 -07:00
|
|
|
init_service(key, path);
|
|
|
|
|
}
|
2016-06-14 15:48:48 -07:00
|
|
|
/*
|
|
|
|
|
* Enables or disables intercept for current thread using key in thread-local storage
|
|
|
|
|
*/
|
2016-07-17 20:56:42 -07:00
|
|
|
void set_intercept_status(int mode) {
|
2016-06-14 15:48:48 -07:00
|
|
|
fprintf(stderr, "set_intercept_status(mode=%d): tid = %d\n", mode, pthread_mach_thread_np(pthread_self()));
|
|
|
|
|
pthread_key_create(&thr_id_key, NULL);
|
|
|
|
|
intercept_thread_id = (int*)malloc(sizeof(int));
|
|
|
|
|
*intercept_thread_id = mode;
|
|
|
|
|
pthread_setspecific(thr_id_key, intercept_thread_id);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Starts a new service instance
|
|
|
|
|
*/
|
|
|
|
|
#if defined(__ANDROID__)
|
2016-08-17 12:41:59 -07:00
|
|
|
/* NOTE: Since on Android devices the sdcard is formatted as fat32, we can't use just any
|
|
|
|
|
location to set up the RPC unix domain socket. Rather we must use the application's specific
|
|
|
|
|
data directory given by getApplicationContext().getFilesDir() */
|
2016-07-20 14:20:45 -07:00
|
|
|
JNIEXPORT int JNICALL Java_ZeroTier_SDK_zt_1start_1service(JNIEnv *env, jobject thisObj, jstring path) {
|
|
|
|
|
if(path)
|
2016-07-12 02:44:17 -05:00
|
|
|
homeDir = env->GetStringUTFChars(path, NULL);
|
2016-06-14 15:48:48 -07:00
|
|
|
#else
|
2016-07-20 14:20:45 -07:00
|
|
|
void *zt_start_service(void *thread_id) {
|
2016-06-14 15:48:48 -07:00
|
|
|
#endif
|
|
|
|
|
|
2016-07-15 14:52:02 -07:00
|
|
|
#if defined(SDK_BUNDLED) && !defined(__ANDROID__)
|
2016-07-20 14:20:45 -07:00
|
|
|
set_intercept_status(INTERCEPT_DISABLED); // Ignore network calls from ZT service
|
2016-06-14 15:48:48 -07:00
|
|
|
#endif
|
2016-06-28 19:53:09 -07:00
|
|
|
|
2016-07-17 20:56:42 -07:00
|
|
|
#if defined(__UNITY_3D__)
|
|
|
|
|
int MAX_DIR_SZ = 256;
|
|
|
|
|
char current_dir[MAX_DIR_SZ];
|
|
|
|
|
getcwd(current_dir, MAX_DIR_SZ);
|
|
|
|
|
chdir(service_path.c_str());
|
2016-07-20 14:20:45 -07:00
|
|
|
homeDir = current_dir; // homeDir shall be current_dir
|
2016-07-17 20:56:42 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
|
#include "TargetConditionals.h"
|
|
|
|
|
#if TARGET_IPHONE_SIMULATOR
|
|
|
|
|
// homeDir = "dont/run/this/in/the/simulator/it/wont/work";
|
|
|
|
|
#elif TARGET_OS_IPHONE
|
|
|
|
|
localHomeDir = "ZeroTier/One";
|
|
|
|
|
std::string del = givenHomeDir.length() && givenHomeDir[givenHomeDir.length()-1]!='/' ? "/" : "";
|
|
|
|
|
homeDir = givenHomeDir + del + localHomeDir;
|
2016-06-28 19:53:09 -07:00
|
|
|
#endif
|
2016-07-17 20:56:42 -07:00
|
|
|
#endif
|
2016-06-28 19:53:09 -07:00
|
|
|
|
2016-07-17 20:56:42 -07:00
|
|
|
#if defined(__APPLE__) && !defined(__IOS__)
|
|
|
|
|
homeDir = givenHomeDir;
|
2016-07-18 01:42:18 -07:00
|
|
|
localHomeDir = givenHomeDir; // Used for RPC and *can* differ from homeDir on some platforms
|
2016-07-17 20:56:42 -07:00
|
|
|
#endif
|
|
|
|
|
|
2016-08-04 13:10:12 -07:00
|
|
|
dwr(MSG_DEBUG, "homeDir = %s", givenHomeDir.c_str());
|
2016-06-28 19:53:09 -07:00
|
|
|
// Where network .conf files will be stored
|
2016-06-14 15:48:48 -07:00
|
|
|
netDir = homeDir + "/networks.d";
|
2016-06-28 19:53:09 -07:00
|
|
|
zt1Service = (ZeroTier::OneService *)0;
|
2016-06-14 15:48:48 -07:00
|
|
|
|
2016-07-17 20:56:42 -07:00
|
|
|
// Construct path for network config and supporting service files
|
2016-07-20 14:20:45 -07:00
|
|
|
if (homeDir.length()) {
|
2016-08-04 13:10:12 -07:00
|
|
|
dwr(MSG_DEBUG, "start_service(): constructing path...\n");
|
2016-06-14 15:48:48 -07:00
|
|
|
std::vector<std::string> hpsp(ZeroTier::Utils::split(homeDir.c_str(),ZT_PATH_SEPARATOR_S,"",""));
|
|
|
|
|
std::string ptmp;
|
|
|
|
|
if (homeDir[0] == ZT_PATH_SEPARATOR)
|
|
|
|
|
ptmp.push_back(ZT_PATH_SEPARATOR);
|
|
|
|
|
for(std::vector<std::string>::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) {
|
|
|
|
|
if (ptmp.length() > 0)
|
|
|
|
|
ptmp.push_back(ZT_PATH_SEPARATOR);
|
|
|
|
|
ptmp.append(*pi);
|
|
|
|
|
if ((*pi != ".")&&(*pi != "..")) {
|
|
|
|
|
if (!ZeroTier::OSUtils::mkdir(ptmp)) {
|
2016-08-04 13:10:12 -07:00
|
|
|
dwr(MSG_ERROR, "startOneService(): home path does not exist, and could not create\n");
|
2016-06-14 15:48:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-07-20 14:20:45 -07:00
|
|
|
else {
|
|
|
|
|
fprintf(stderr, "start_service(): homeDir is empty, could not construct path\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2016-06-14 15:48:48 -07:00
|
|
|
|
2016-07-17 20:56:42 -07:00
|
|
|
#if defined(__IOS__)
|
|
|
|
|
// Go to the app's data directory so we can shorten the sun_path we bind to
|
|
|
|
|
int MAX_DIR_SZ = 256;
|
|
|
|
|
char current_dir[MAX_DIR_SZ];
|
|
|
|
|
getcwd(current_dir, MAX_DIR_SZ);
|
|
|
|
|
std::string targetDir = homeDir + "/../../";
|
|
|
|
|
chdir(targetDir.c_str());
|
|
|
|
|
homeDir = localHomeDir;
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-06-24 12:10:47 -07:00
|
|
|
//chdir(current_dir); // Return to previous current working directory (at the request of Unity3D)
|
2016-07-18 14:18:46 -07:00
|
|
|
#if defined(__UNITY_3D__)
|
|
|
|
|
Debug("Starting service...\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-07-18 01:42:18 -07:00
|
|
|
// Initialize RPC
|
|
|
|
|
if(rpcEnabled) {
|
|
|
|
|
zt_init_rpc(localHomeDir.c_str(), rpcNWID.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-14 15:48:48 -07:00
|
|
|
// Generate random port for new service instance
|
|
|
|
|
unsigned int randp = 0;
|
|
|
|
|
ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp));
|
|
|
|
|
int servicePort = 9000 + (randp % 1000);
|
2016-07-20 14:20:45 -07:00
|
|
|
|
2016-06-14 15:48:48 -07:00
|
|
|
for(;;) {
|
|
|
|
|
zt1Service = ZeroTier::OneService::newInstance(homeDir.c_str(),servicePort);
|
|
|
|
|
switch(zt1Service->run()) {
|
|
|
|
|
case ZeroTier::OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
|
|
|
|
case ZeroTier::OneService::ONE_NORMAL_TERMINATION:
|
|
|
|
|
break;
|
|
|
|
|
case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR:
|
2016-07-20 14:20:45 -07:00
|
|
|
fprintf(stderr,"start_service(): fatal error: %s",zt1Service->fatalErrorMessage().c_str());
|
2016-06-14 15:48:48 -07:00
|
|
|
break;
|
|
|
|
|
case ZeroTier::OneService::ONE_IDENTITY_COLLISION: {
|
|
|
|
|
delete zt1Service;
|
|
|
|
|
zt1Service = (ZeroTier::OneService *)0;
|
|
|
|
|
std::string oldid;
|
2016-07-20 14:20:45 -07:00
|
|
|
ZeroTier::OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid);
|
2016-06-14 15:48:48 -07:00
|
|
|
if (oldid.length()) {
|
2016-07-20 14:20:45 -07:00
|
|
|
ZeroTier::OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid);
|
|
|
|
|
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
|
|
|
|
|
ZeroTier::OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
|
2016-06-14 15:48:48 -07:00
|
|
|
}
|
2016-07-20 14:20:45 -07:00
|
|
|
}
|
|
|
|
|
continue; // restart!
|
|
|
|
|
}
|
|
|
|
|
break; // terminate loop -- normally we don't keep restarting
|
|
|
|
|
}
|
|
|
|
|
delete zt1Service;
|
|
|
|
|
zt1Service = (ZeroTier::OneService *)0;
|
|
|
|
|
return NULL;
|
2016-06-14 15:48:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|