diff options
| author | Joseph Henry <[email protected]> | 2017-04-14 17:23:28 -0700 |
|---|---|---|
| committer | Joseph Henry <[email protected]> | 2017-04-14 17:23:28 -0700 |
| commit | c65b609fb467c018c61cae0dc78bc0324e6a4236 (patch) | |
| tree | fb1cc907f650a7348a871304735940540eed3bcc /src/ZeroTierSDK.cpp | |
| parent | 3052f55d1253b894f90b0f4e4e3a844b785690dc (diff) | |
spring cleaning
Diffstat (limited to 'src/ZeroTierSDK.cpp')
| -rw-r--r-- | src/ZeroTierSDK.cpp | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/src/ZeroTierSDK.cpp b/src/ZeroTierSDK.cpp new file mode 100644 index 0000000..6625f0d --- /dev/null +++ b/src/ZeroTierSDK.cpp @@ -0,0 +1,707 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/ + * + * 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/>. + */ + +#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> + +#include "OneService.hpp" +#include "Utils.hpp" +#include "OSUtils.hpp" +#include "InetAddress.hpp" +#include "ZeroTierOne.h" + +#include "SocketTap.hpp" +#include "ZeroTierSDK.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static ZeroTier::OneService *zt1Service; + +namespace ZeroTier { + std::string homeDir; // The resultant platform-specific dir we *must* use internally + std::string netDir; // Where network .conf files are to be written + + picoTCP *picostack = NULL; + std::map<int, Connection*> UnassignedConnections; + std::map<int, std::pair<Connection*,SocketTap*>*> AssignedFileDescriptors; + Mutex _multiplexer_lock; + Mutex _accepted_connection_lock; +} + +/****************************************************************************/ +/* SDK Socket API - Language Bindings are written in terms of these */ +/****************************************************************************/ + +void zts_start(const char *path) +{ + if(zt1Service) + return; + if(ZeroTier::picostack) + return; + + ZeroTier::picostack = new ZeroTier::picoTCP(); + pico_stack_init(); + + DEBUG_INFO("path=%s", path); + if(path) + ZeroTier::homeDir = path; + pthread_t service_thread; + pthread_create(&service_thread, NULL, _start_service, (void *)(path)); +} + +void zts_stop() { + if(zt1Service) { + zt1Service->terminate(); + zt1Service->removeNets(); + } +} + +void zts_join_network(const char * nwid) { + if(zt1Service) { + std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; + if(!ZeroTier::OSUtils::mkdir(ZeroTier::netDir)) + DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str()); + if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + zt1Service->join(nwid); + } +} + +void zts_join_network_soft(const char * filepath, const char * nwid) { + std::string net_dir = std::string(filepath) + "/networks.d/"; + std::string confFile = net_dir + std::string(nwid) + ".conf"; + if(!ZeroTier::OSUtils::mkdir(net_dir)) { + DEBUG_ERROR("unable to create: %s", net_dir.c_str()); + } + if(!ZeroTier::OSUtils::fileExists(confFile.c_str(),false)) { + if(!ZeroTier::OSUtils::writeFile(confFile.c_str(), "")) { + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + } + } +} + +void zts_leave_network(const char * nwid) { + if(zt1Service) + zt1Service->leave(nwid); +} + +void zts_leave_network_soft(const char * filepath, const char * nwid) { + std::string net_dir = std::string(filepath) + "/networks.d/"; + ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); +} + +void zts_get_homepath(char *homePath, int len) { + if(ZeroTier::homeDir.length()) { + memset(homePath, 0, len); + memcpy(homePath, ZeroTier::homeDir.c_str(), len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length()); + } +} + +void zts_core_version(char *ver) { + int major, minor, revision; + ZT_version(&major, &minor, &revision); + sprintf(ver, "%d.%d.%d", major, minor, revision); +} + +void zts_sdk_version(char *ver) { + sprintf(ver, "%d.%d.%d", ZT_SDK_VERSION_MAJOR, ZT_SDK_VERSION_MINOR, ZT_SDK_VERSION_REVISION); +} + +int zts_get_device_id(char *devID) { + if(zt1Service) { + char id[ZT_ID_LEN+1]; + sprintf(id, "%lx",zt1Service->getNode()->address()); + memcpy(devID, id, ZT_ID_LEN+1); + return 0; + } + else // Service isn't online, try to read ID from file + { + std::string fname("identity.public"); + std::string fpath(ZeroTier::homeDir); + + if(ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { + std::string oldid; + ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); + memcpy(devID, oldid.c_str(), ZT_ID_LEN); // first 10 bytes of file + return 0; + } + } + return -1; +} + +int zts_service_running() { + return !zt1Service ? false : zt1Service->isRunning(); +} + +int zts_has_ipv4_address(const char *nwid) +{ + char ipv4_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv4_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv4_address(nwid, ipv4_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv4_addr, "\0"); +} + +int zts_has_ipv6_address(const char *nwid) +{ + char ipv6_addr[ZT_MAX_IPADDR_LEN]; + memset(ipv6_addr, 0, ZT_MAX_IPADDR_LEN); + zts_get_ipv6_address(nwid, ipv6_addr, ZT_MAX_IPADDR_LEN); + return strcmp(ipv6_addr, "\0"); +} + +int zts_has_address(const char *nwid) +{ + return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); +} + +void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen) +{ + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i<tap->_ips.size(); i++) { + if(tap->_ips[i].isV4()) { + std::string addr = tap->_ips[i].toString(); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen) +{ + if(zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::SocketTap *tap = zt1Service->getTap(nwid_int); + if(tap && tap->_ips.size()){ + for(int i=0; i<tap->_ips.size(); i++) { + if(tap->_ips[i].isV6()) { + std::string addr = tap->_ips[i].toString(); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + memcpy(addr, _6planeAddr.toIpString().c_str(), 40); +} + +void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + memcpy(addr, _6planeAddr.toIpString().c_str(), 40); +} + +unsigned long zts_get_peer_count() { + if(zt1Service) + return zt1Service->getNode()->peers()->peerCount; + else + return 0; +} + +int zts_get_peer_address(char *peer, const char *devID) { + if(zt1Service) { + ZT_PeerList *pl = zt1Service->getNode()->peers(); + // uint64_t addr; + for(int i=0; i<pl->peerCount; i++) { + // ZT_Peer *p = &(pl->peers[i]); + // DEBUG_INFO("peer[%d] = %lx", i, p->address); + } + return pl->peerCount; + } + else + return -1; +} + +void zts_enable_http_control_plane() +{ + +} + +void zts_disable_http_control_plane() +{ + +} + +/****************************************************************************/ +/* SocketTap Multiplexer Functionality */ +/* - This section of the API is used to implement the general socket */ +/* controls. Basically this is designed to handle socket provisioning */ +/* requests when no SocketTap is yet initialized, and as a way to */ +/* determine which SocketTap is to be used for a particular connect() or */ +/* bind() call. This enables multi-network support */ +/****************************************************************************/ + +int zts_socket(ZT_SOCKET_SIG) { + DEBUG_INFO(); + ZeroTier::_multiplexer_lock.lock(); + ZeroTier::Connection *conn = new ZeroTier::Connection(); + int err, protocol_version; + // set up pico_socket + struct pico_socket * psock; + #if defined(SDK_IPV4) + protocol_version = PICO_PROTO_IPV4; + #elif defined(SDK_IPV6) + protocol_version = PICO_PROTO_IPV6; + #endif + if(socket_type == SOCK_DGRAM) { + psock = pico_socket_open( + protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_activity); + } + if(socket_type == SOCK_STREAM) { + psock = pico_socket_open( + protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_activity); + } + // set up Unix Domain socketpair (used for data later on) + if(psock) { + conn->socket_family = socket_family; + conn->socket_type = socket_type; + conn->picosock = psock; + memset(conn->rxbuf, 0, ZT_UDP_RX_BUF_SZ); + ZeroTier::UnassignedConnections[conn->app_fd] = conn; + err = conn->app_fd; // return one end of the socketpair + } + else { + DEBUG_ERROR("failed to create pico_socket"); + err = -1; + } + ZeroTier::_multiplexer_lock.unlock(); + return err; +} + +int zts_connect(ZT_CONNECT_SIG) { + if(!zt1Service) { + DEBUG_ERROR("zt1Service = NULL"); + // errno = ? + return -1; + } + ZeroTier::_multiplexer_lock.lock(); + int err; + ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd]; + ZeroTier::SocketTap *tap; + + if(conn) { + char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + ZeroTier::InetAddress iaddr; + + if(conn->socket_family == AF_INET) { + // FIXME: Fix this typecast mess + inet_ntop(AF_INET, + (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); + } + if(conn->socket_family == AF_INET6) { + // FIXME: Fix this typecast mess + inet_ntop(AF_INET6, + (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); + } + iaddr.fromString(ipstr); + + DEBUG_INFO("ipstr= %s", ipstr); + DEBUG_INFO("iaddr= %s", iaddr.toString().c_str()); + + tap = zt1Service->getTap(iaddr); + + if(!tap) { + // TODO: More canonical error? + DEBUG_ERROR("no route to host"); + // errno = ? + err = -1; + } + else { + conn->sock = tap->_phy.wrapSocket(conn->sdk_fd, conn); // wrap the socketpair we created earlier + conn->picosock->priv = new ZeroTier::Larg(tap, conn); // pointer to tap we use in callbacks from the stack + DEBUG_INFO("found appropriate SocketTap"); + // TODO: Perhaps move this connect call outside of the lock + tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on + err = tap->Connect(conn, fd, addr, addrlen); // Semantically: tap->stack->connect + conn->tap = tap; + } + } + else { + DEBUG_ERROR("unable to locate connection"); + // errno = ? + err = -1; + } + ZeroTier::AssignedFileDescriptors[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap); + ZeroTier::_multiplexer_lock.unlock(); + return err; +} + +int zts_bind(ZT_BIND_SIG) { + if(!zt1Service) { + DEBUG_ERROR("zt1Service = NULL"); + // errno = ? + return -1; + } + ZeroTier::_multiplexer_lock.lock(); + int err; + ZeroTier::Connection *conn = ZeroTier::UnassignedConnections[fd]; + ZeroTier::SocketTap *tap; + + if(conn) { + char ipstr[INET6_ADDRSTRLEN];//, nm_str[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + ZeroTier::InetAddress iaddr; + + if(conn->socket_family == AF_INET) { + // FIXME: Fix this typecast mess + inet_ntop(AF_INET, + (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); + } + if(conn->socket_family == AF_INET6) { + // FIXME: Fix this typecast mess + inet_ntop(AF_INET6, + (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); + } + iaddr.fromString(ipstr); + + DEBUG_INFO("ipstr= %s", ipstr); + DEBUG_INFO("iaddr= %s", iaddr.toString().c_str()); + + tap = zt1Service->getTap(iaddr); + + if(!tap) { + // TODO: More canonical error? + DEBUG_ERROR("no appropriate interface to bind to"); + // errno = ? + err = -1; + } + else { + DEBUG_INFO("found appropriate SocketTap"); + DEBUG_INFO("conn->picosock = %p", conn->picosock); + conn->picosock->priv = new ZeroTier::Larg(tap, conn); + // TODO: Perhaps move this connect call outside of the lock + tap->_Connections.push_back(conn); // Give this Connection to the tap we decided on + err = tap->Bind(conn, fd, addr, addrlen); // Semantically: tap->stack->connect + conn->tap = tap; + } + } + else { + DEBUG_ERROR("unable to locate connection"); + // errno = ? + err = -1; + } + ZeroTier::AssignedFileDescriptors[fd] = new std::pair<ZeroTier::Connection*,ZeroTier::SocketTap*>(conn, tap); + ZeroTier::_multiplexer_lock.unlock(); + return err; +} + +int zts_listen(ZT_LISTEN_SIG) { + if(!zt1Service) { + DEBUG_ERROR("zt1Service = NULL"); + // errno = ? + return -1; + } + int err; + ZeroTier::_multiplexer_lock.lock(); + ZeroTier::Connection *conn = ZeroTier::AssignedFileDescriptors[fd]->first; + ZeroTier::SocketTap *tap = ZeroTier::AssignedFileDescriptors[fd]->second; + + if(!tap || !conn) { + DEBUG_ERROR("unable to locate tap interface for file descriptor"); + err = -1; + } + tap->Listen(conn, fd, backlog); + err = 0; + DEBUG_INFO("put %p into LISTENING state", conn); + ZeroTier::_multiplexer_lock.unlock(); + return err; +} + +int zts_accept(ZT_ACCEPT_SIG) { + int err; + ZeroTier::Connection *conn = ZeroTier::AssignedFileDescriptors[fd]->first; + ZeroTier::SocketTap *tap = ZeroTier::AssignedFileDescriptors[fd]->second; + // BLOCKING: loop and keep checking until we find a newly accepted connection + if(true) { + while(true) { + usleep(ZT_ACCEPT_RECHECK_DELAY * 1000); + err = tap->Accept(conn); + if(err >= 0) + return err; + } + } + // NON-BLOCKING: only check for a new connection once + else + err = tap->Accept(conn); + return err; +} + +#if defined(__linux__) + int zts_accept4(ZT_ACCEPT4_SIG) + { + return 0; + } +#endif + +int zts_setsockopt(ZT_SETSOCKOPT_SIG) +{ + return 0; +} + +int zts_getsockopt(ZT_GETSOCKOPT_SIG) +{ + return 0; +} + +int zts_getsockname(ZT_GETSOCKNAME_SIG) +{ + return 0; +} + +int zts_getpeername(ZT_GETPEERNAME_SIG) +{ + return 0; +} + +int zts_close(ZT_CLOSE_SIG) +{ + return 0; +} + +int zts_fcntl(ZT_FCNTL_SIG) +{ + return 0; +} + +ssize_t zts_sendto(ZT_SENDTO_SIG) +{ + return 0; +} + +ssize_t zts_sendmsg(ZT_SENDMSG_SIG) +{ + return 0; +} + +ssize_t zts_recvfrom(ZT_RECVFROM_SIG) +{ + return 0; +} + +ssize_t zts_recvmsg(ZT_RECVMSG_SIG) +{ + return 0; +} + +int zts_read(ZT_READ_SIG) { + return read(fd, buf, len); +} + +int zts_write(ZT_WRITE_SIG) { + return write(fd, buf, len); +} + + + +/****************************************************************************/ +/* SDK Socket API (Java Native Interface JNI) */ +/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */ +/****************************************************************************/ + +#if defined(__ANDROID__) || defined(__JNI_LIB__) + // Returns whether the ZeroTier service is running + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1service_1is_1running( + JNIEnv *env, jobject thisObj) + { + return zts_service_is_running(); + } + // Returns path for ZT config/data files + JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_zt_1get_1homepath( + JNIEnv *env, jobject thisObj) + { + return (*env).NewStringUTF(zts_get_homepath()); + } + // Join a network + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1join_1network( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if(nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_join_network(nwidstr); + } + } + // Leave a network + JNIEXPORT void JNICALL Java_zerotier_ZeroTier_zt_1leave_1network( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwidstr; + if(nwid) { + nwidstr = env->GetStringUTFChars(nwid, NULL); + zts_leave_network(nwidstr); + } + } + // 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 + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv4_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[32]; + memset(address_string, 0, 32); + zts_get_ipv4_address(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; + } + + JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_zt_1get_1ipv6_1address( + JNIEnv *env, jobject thisObj, jstring nwid) + { + const char *nwid_str = env->GetStringUTFChars(nwid, NULL); + char address_string[32]; + memset(address_string, 0, 32); + zts_get_ipv6_address(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; + } + + // Returns the device is in integer form + JNIEXPORT jint Java_zerotier_ZeroTier_zt_1get_1device_1id() + { + return zts_get_device_id(NULL); // TODO + } + // Returns whether the path to an endpoint is currently relayed by a root server + JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_zt_1is_1relayed() + { + return 0; + // TODO + // zts_is_relayed(); + } +#endif + +/****************************************************************************/ +/* SDK Socket API Helper functions --- DONT CALL THESE DIRECTLY */ +/****************************************************************************/ + +// Starts a ZeroTier service in the background +void *_start_service(void *thread_id) { + + DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str()); + // Where network .conf files will be stored + ZeroTier::netDir = ZeroTier::homeDir + "/networks.d"; + zt1Service = (ZeroTier::OneService *)0; + + // Construct path for network config and supporting service files + if (ZeroTier::homeDir.length()) { + std::vector<std::string> hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), + ZT_PATH_SEPARATOR_S,"","")); + std::string ptmp; + if (ZeroTier::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)) { + DEBUG_ERROR("home path does not exist, and could not create"); + perror("error\n"); + } + } + } + } + else { + DEBUG_ERROR("homeDir is empty, could not construct path"); + return NULL; + } + // rpc dir + if(!ZeroTier::OSUtils::mkdir(ZeroTier::homeDir + "/" + ZT_SDK_RPC_DIR_PREFIX)) { + DEBUG_ERROR("unable to create dir: " ZT_SDK_RPC_DIR_PREFIX); + return NULL; + } + + // Generate random port for new service instance + unsigned int randp = 0; + ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); + int servicePort = 9000 + (randp % 10000); + DEBUG_ERROR("servicePort = %d", servicePort); + + for(;;) { + zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort); + switch(zt1Service->run()) { + case ZeroTier::OneService::ONE_STILL_RUNNING: + case ZeroTier::OneService::ONE_NORMAL_TERMINATION: + break; + case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: + DEBUG_ERROR("fatal error: %s",zt1Service->fatalErrorMessage().c_str()); + break; + case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { + delete zt1Service; + zt1Service = (ZeroTier::OneService *)0; + std::string oldid; + ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str(),oldid); + if (oldid.length()) { + ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret.saved_after_collision").c_str(),oldid); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str()); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.public").c_str()); + } + } + continue; // restart! + } + break; // terminate loop -- normally we don't keep restarting + } + delete zt1Service; + zt1Service = (ZeroTier::OneService *)0; + return NULL; +} + +#ifdef __cplusplus +} +#endif |
