mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-07 11:17:29 +00:00
Remove old launcher code, fix build error in idtool, add terminate command to control bus.
This commit is contained in:
parent
11774f7d5f
commit
4875eb49f8
126
idtool.cpp
126
idtool.cpp
@ -45,8 +45,6 @@ static void printHelp(char *pn)
|
||||
std::cout << "\tgetpublic <identity.secret>" << std::endl;
|
||||
std::cout << "\tsign <identity.secret> <file>" << std::endl;
|
||||
std::cout << "\tverify <identity.secret/public> <file> <signature>" << std::endl;
|
||||
std::cout << "\tencrypt <identity.secret> <identity.public (recipient)> [<file>] [<outfile>]" << std::endl;
|
||||
std::cout << "\tdecrypt <identity.secret> <identity.public (sender)> [<file>] [<outfile>]" << std::endl;
|
||||
}
|
||||
|
||||
static Identity getIdFromArg(char *arg)
|
||||
@ -165,130 +163,6 @@ int main(int argc,char **argv)
|
||||
std::cerr << argv[3] << " signature check FAILED" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcmp(argv[1],"encrypt")) {
|
||||
if (argc < 4) {
|
||||
printHelp(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Identity from = getIdFromArg(argv[2]);
|
||||
if (!from) {
|
||||
std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (!from.hasPrivate()) {
|
||||
std::cerr << argv[2] << " must contain a secret key" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Identity to = getIdFromArg(argv[3]);
|
||||
if (!to) {
|
||||
std::cerr << "Identity argument invalid or file unreadable: " << argv[3] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *inf;
|
||||
if (argc > 4) {
|
||||
inf = fopen(argv[4],"r");
|
||||
if (!inf) {
|
||||
std::cerr << "Could not open input file " << argv[4] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
} else inf = stdin;
|
||||
int inbuflen = 131072;
|
||||
char *inbuf = (char *)malloc(inbuflen);
|
||||
if (!inbuf) {
|
||||
std::cerr << "Could not malloc()" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
int inlen = 0;
|
||||
int n;
|
||||
while ((n = (int)fread(inbuf + inlen,1,inbuflen - inlen,inf)) > 0) {
|
||||
inlen += n;
|
||||
if ((inbuflen - inlen) < 1024) {
|
||||
inbuf = (char *)realloc(inbuf,inbuflen += 131072);
|
||||
if (!inbuf) {
|
||||
std::cerr << "Could not malloc()" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inf != stdin)
|
||||
fclose(inf);
|
||||
|
||||
std::string crypted(from.encrypt(to,inbuf,inlen));
|
||||
if (!crypted.length()) {
|
||||
std::cerr << "Failure encrypting data, check from/to identities" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 5)
|
||||
Utils::writeFile(argv[5],crypted.data(),crypted.length());
|
||||
else fwrite(crypted.data(),1,crypted.length(),stdout);
|
||||
|
||||
free(inbuf);
|
||||
} else if (!strcmp(argv[1],"decrypt")) {
|
||||
if (argc < 4) {
|
||||
printHelp(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Identity to = getIdFromArg(argv[2]);
|
||||
if (!to) {
|
||||
std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!to.hasPrivate()) {
|
||||
std::cerr << argv[2] << " must contain a secret key" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Identity from = getIdFromArg(argv[3]);
|
||||
if (!from) {
|
||||
std::cerr << "Identity argument invalid or file unreadable: " << argv[3] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *inf;
|
||||
if (argc > 4) {
|
||||
inf = fopen(argv[4],"r");
|
||||
if (!inf) {
|
||||
std::cerr << "Could not open input file " << argv[4] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
} else inf = stdin;
|
||||
int inbuflen = 131072;
|
||||
char *inbuf = (char *)malloc(inbuflen);
|
||||
if (!inbuf) {
|
||||
std::cerr << "Could not malloc()" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
int inlen = 0;
|
||||
int n;
|
||||
while ((n = (int)fread(inbuf + inlen,1,inbuflen - inlen,inf)) > 0) {
|
||||
inlen += n;
|
||||
if ((inbuflen - inlen) < 1024) {
|
||||
inbuf = (char *)realloc(inbuf,inbuflen += 131072);
|
||||
if (!inbuf) {
|
||||
std::cerr << "Could not malloc()" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inf != stdin)
|
||||
fclose(inf);
|
||||
|
||||
std::string dec(to.decrypt(from,inbuf,inlen));
|
||||
free(inbuf);
|
||||
if (!dec.length()) {
|
||||
std::cerr << "Failure decrypting data, check from/to identities" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 5)
|
||||
Utils::writeFile(argv[5],dec.data(),dec.length());
|
||||
else fwrite(dec.data(),1,dec.length(),stdout);
|
||||
} else {
|
||||
printHelp(argv[0]);
|
||||
return -1;
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* Fake zerotier-one binary to test launcher upgrade procedure */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "launcher.h"
|
||||
|
||||
const unsigned char EMBEDDED_VERSION_STAMP[20] = {
|
||||
0x6d,0xfe,0xff,0x01,0x90,0xfa,0x89,0x57,0x88,0xa1,0xaa,0xdc,0xdd,0xde,0xb0,0x33,
|
||||
ZEROTIER_FAKE_VERSION_MAJOR,
|
||||
ZEROTIER_FAKE_VERSION_MINOR,
|
||||
(unsigned char)(((unsigned int)ZEROTIER_FAKE_VERSION_REVISION) & 0xff), /* little-endian */
|
||||
(unsigned char)((((unsigned int)ZEROTIER_FAKE_VERSION_REVISION) >> 8) & 0xff)
|
||||
};
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
fprintf(stderr,"Fake ZeroTier binary version %d.%d.%d\n",ZEROTIER_FAKE_VERSION_MAJOR,ZEROTIER_FAKE_VERSION_MINOR,ZEROTIER_FAKE_VERSION_REVISION);
|
||||
sleep(5);
|
||||
fprintf(stderr," (exiting)\n");
|
||||
return ZEROTIER_EXEC_RETURN_VALUE_TERMINATED_FOR_UPGRADE;
|
||||
}
|
279
launcher.c
279
launcher.c
@ -1,279 +0,0 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet
|
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC
|
||||
*
|
||||
* 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/
|
||||
*/
|
||||
|
||||
/* Launcher for Linux/Unix/Mac */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "launcher.h"
|
||||
|
||||
/* Must match first 16 bytes of EMBEDDED_VERSION_STAMP in Node.cpp */
|
||||
static const unsigned char EMBEDDED_VERSION_STAMP_KEY[16] = { 0x6d,0xfe,0xff,0x01,0x90,0xfa,0x89,0x57,0x88,0xa1,0xaa,0xdc,0xdd,0xde,0xb0,0x33 };
|
||||
|
||||
const unsigned char EMBEDDED_LAUNCHER_VERSION_STAMP[20] = {
|
||||
0x96,0xf0,0x00,0x08,0x18,0xff,0xc9,0xde,0xad,0xf0,0x0f,0xbe,0xef,0x30,0xce,0xa1, /* key */
|
||||
ZT_LAUNCHER_VERSION_MAJOR,
|
||||
ZT_LAUNCHER_VERSION_MINOR,
|
||||
(unsigned char)(((unsigned int)ZT_LAUNCHER_VERSION_REVISION) & 0xff), /* little-endian */
|
||||
(unsigned char)((((unsigned int)ZT_LAUNCHER_VERSION_REVISION) >> 8) & 0xff)
|
||||
};
|
||||
|
||||
#define ZT_BINARY_NAME "zerotier-one"
|
||||
#define ZT_BINARY_UPDATE_PREFIX "zerotier-one_update."
|
||||
|
||||
#define ZT_LAUNCHER_PIDFILE "zerotier-launcher.pid"
|
||||
#define ZT_ONE_PIDFILE "zerotier-one.pid"
|
||||
|
||||
/* Load a file into newly malloc()'ed memory, len set to size */
|
||||
static unsigned char *loadFile(const char *path,unsigned long *len)
|
||||
{
|
||||
unsigned char *fbuf = (unsigned char *)0;
|
||||
FILE *f = fopen(path,"rb");
|
||||
if (f) {
|
||||
if (!fseek(f,0,SEEK_END)) {
|
||||
long l = ftell(f);
|
||||
if (l > 0) {
|
||||
fseek(f,0,SEEK_SET);
|
||||
fbuf = malloc(l);
|
||||
if (fbuf) {
|
||||
if (fread(fbuf,l,1,f) != 1) {
|
||||
free(fbuf);
|
||||
fbuf = (unsigned char *)0;
|
||||
} else *len = (unsigned long)l;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return fbuf;
|
||||
}
|
||||
|
||||
/* Scans a ZeroTier binary and determines its version from its embedded version code */
|
||||
static int findVersion(const unsigned char *bin,unsigned long len,unsigned int *major,unsigned int *minor,unsigned int *revision)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
if (len > 20) {
|
||||
for(i=0;i<(len - 20);++i) {
|
||||
if ((bin[i] == EMBEDDED_VERSION_STAMP_KEY[0])&&(!memcmp(bin + i,EMBEDDED_VERSION_STAMP_KEY,16))) {
|
||||
*major = bin[i + 16];
|
||||
*minor = bin[i + 17];
|
||||
*revision = ((unsigned int)bin[i + 18] & 0xff) | (((unsigned int)bin[i + 19] << 8) & 0xff00);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scan for updates and, if found, replace the main binary if possible */
|
||||
static int doUpdateBinaryIfNewer()
|
||||
{
|
||||
long pfxLen = strlen(ZT_BINARY_UPDATE_PREFIX);
|
||||
struct dirent dbuf,*d;
|
||||
int needUpdate;
|
||||
unsigned int major = 0,minor = 0,revision = 0;
|
||||
unsigned int existingMajor = 0,existingMinor = 0,existingRevision = 0;
|
||||
unsigned long binLen;
|
||||
unsigned char *bin;
|
||||
char oldname[1024];
|
||||
DIR *dir;
|
||||
|
||||
binLen = 0;
|
||||
bin = loadFile(ZT_BINARY_NAME,&binLen);
|
||||
if (!((bin)&&(binLen)&&(findVersion(bin,binLen,&existingMajor,&existingMinor,&existingRevision)))) {
|
||||
if (bin)
|
||||
free(bin);
|
||||
return 0;
|
||||
}
|
||||
free(bin);
|
||||
|
||||
dir = opendir(".");
|
||||
if (!dir)
|
||||
return 0;
|
||||
while (!readdir_r(dir,&dbuf,&d)) {
|
||||
if (!d) break;
|
||||
if (!strncasecmp(d->d_name,ZT_BINARY_UPDATE_PREFIX,pfxLen)) {
|
||||
binLen = 0;
|
||||
unsigned char *bin = loadFile(d->d_name,&binLen);
|
||||
if ((bin)&&(binLen)&&(findVersion(bin,binLen,&major,&minor,&revision))) {
|
||||
needUpdate = 0;
|
||||
if (major > existingMajor)
|
||||
needUpdate = 1;
|
||||
else if (major == existingMajor) {
|
||||
if (minor > existingMinor)
|
||||
needUpdate = 1;
|
||||
else if (minor == existingMinor) {
|
||||
if (revision > existingRevision)
|
||||
needUpdate = 1;
|
||||
}
|
||||
}
|
||||
free(bin);
|
||||
if (needUpdate) {
|
||||
/* fprintf(stderr,"zerotier-launcher: replacing %s with %s\n",ZT_BINARY_NAME,d->d_name); */
|
||||
sprintf(oldname,"%s.OLD",ZT_BINARY_NAME);
|
||||
if (!rename(ZT_BINARY_NAME,oldname)) {
|
||||
/* fprintf(stderr,"zerotier-launcher: %s -> %s\n",ZT_BINARY_NAME,oldname); */
|
||||
if (!rename(d->d_name,ZT_BINARY_NAME)) {
|
||||
/* fprintf(stderr,"zerotier-launcher: %s -> %s\nzerotier-launcher: delete %s\n",d->d_name,ZT_BINARY_NAME,oldname); */
|
||||
chmod(ZT_BINARY_NAME,0755);
|
||||
unlink(oldname);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bin)
|
||||
free(bin);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static volatile long childPid = 0;
|
||||
|
||||
static void sigRepeater(int sig)
|
||||
{
|
||||
if (childPid > 0)
|
||||
kill(childPid,sig);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
const char *zerotierHome = ZT_DEFAULT_HOME;
|
||||
FILE *pidf;
|
||||
int status,exitCode;
|
||||
unsigned long timeStart;
|
||||
unsigned int numSubTwoSecondRuns;
|
||||
|
||||
/* Pass on certain signals transparently to the subprogram to do with as it will */
|
||||
signal(SIGHUP,&sigRepeater);
|
||||
signal(SIGPIPE,SIG_IGN);
|
||||
signal(SIGUSR1,&sigRepeater);
|
||||
signal(SIGUSR2,&sigRepeater);
|
||||
signal(SIGALRM,SIG_IGN);
|
||||
signal(SIGURG,SIG_IGN);
|
||||
signal(SIGTERM,&sigRepeater);
|
||||
signal(SIGQUIT,&sigRepeater);
|
||||
|
||||
if (argc == 2)
|
||||
zerotierHome = argv[1];
|
||||
|
||||
if (chdir(zerotierHome)) {
|
||||
fprintf(stderr,"%s: fatal error: could not chdir to %s\n",argv[0],zerotierHome);
|
||||
return ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
|
||||
pidf = fopen(ZT_LAUNCHER_PIDFILE,"w");
|
||||
if (pidf) {
|
||||
fprintf(pidf,"%d",(int)getpid());
|
||||
fclose(pidf);
|
||||
}
|
||||
|
||||
numSubTwoSecondRuns = 0;
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
|
||||
|
||||
restart_subprogram:
|
||||
/* We actually do this on every loop, which is fine. It picks up any
|
||||
* newer versions that are waiting and swaps them out for the current
|
||||
* running binary. */
|
||||
doUpdateBinaryIfNewer();
|
||||
|
||||
timeStart = time(0);
|
||||
childPid = fork();
|
||||
if (childPid < 0) {
|
||||
fprintf(stderr,"%s: fatal error: could not fork(): %s\n",argv[0],strerror(errno));
|
||||
return ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
} else if (childPid) {
|
||||
pidf = fopen(ZT_ONE_PIDFILE,"w");
|
||||
if (pidf) {
|
||||
fprintf(pidf,"%d",(int)childPid);
|
||||
fclose(pidf);
|
||||
}
|
||||
|
||||
status = ZT_EXEC_RETURN_VALUE_NO_BINARY;
|
||||
wait_for_subprogram_exit:
|
||||
if ((long)waitpid(childPid,&status,0) >= 0) {
|
||||
if (WIFEXITED(status)) {
|
||||
unlink(ZT_ONE_PIDFILE);
|
||||
|
||||
if ((time(0) - timeStart) < 2) {
|
||||
/* Terminate abnormally if we appear to be looping in a tight loop
|
||||
* to avoid fork bombing if one exits abnormally without an abnormal
|
||||
* exit code. */
|
||||
if (++numSubTwoSecondRuns >= 16) {
|
||||
fprintf(stderr,"%s: fatal error: program exiting immediately in infinite loop\n",argv[0]);
|
||||
return ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
switch(WEXITSTATUS(status)) {
|
||||
case ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION:
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
|
||||
goto exit_launcher;
|
||||
case ZT_EXEC_RETURN_VALUE_NO_BINARY:
|
||||
fprintf(stderr,"%s: fatal error: binary zerotier-one not found at %s\n",argv[0],zerotierHome);
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
goto exit_launcher;
|
||||
case ZT_EXEC_RETURN_VALUE_TERMINATED_FOR_UPGRADE:
|
||||
case ZT_EXEC_RETURN_VALUE_PLEASE_RESTART:
|
||||
goto restart_subprogram;
|
||||
default:
|
||||
exitCode = status;
|
||||
goto exit_launcher;
|
||||
}
|
||||
}
|
||||
} else if (errno != EINTR) {
|
||||
fprintf(stderr,"%s: fatal error: waitpid() failed: %s\n",argv[0],strerror(errno));
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
goto exit_launcher;
|
||||
} else {
|
||||
goto wait_for_subprogram_exit;
|
||||
}
|
||||
} else {
|
||||
execl(ZT_BINARY_NAME,ZT_BINARY_NAME,zerotierHome,(char *)0);
|
||||
exit(ZT_EXEC_RETURN_VALUE_NO_BINARY); /* only reached if execl succeeds */
|
||||
}
|
||||
|
||||
exit_launcher:
|
||||
unlink(ZT_LAUNCHER_PIDFILE);
|
||||
return exitCode;
|
||||
}
|
71
launcher.h
71
launcher.h
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet
|
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC
|
||||
*
|
||||
* 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/
|
||||
*/
|
||||
|
||||
#ifndef _ZT_LAUNCHER_H
|
||||
#define _ZT_LAUNCHER_H
|
||||
|
||||
#define ZT_LAUNCHER_VERSION_MAJOR 0
|
||||
#define ZT_LAUNCHER_VERSION_MINOR 0
|
||||
#define ZT_LAUNCHER_VERSION_REVISION 1
|
||||
|
||||
/**
|
||||
* Normal termination
|
||||
*
|
||||
* This causes the launcher too to exit normally.
|
||||
*/
|
||||
#define ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION 0
|
||||
|
||||
/**
|
||||
* Terminated for upgrade
|
||||
*
|
||||
* This tells the launcher that an upgrade may be available, so a scan for
|
||||
* newer executables should be performed followed by a restart.
|
||||
*/
|
||||
#define ZT_EXEC_RETURN_VALUE_TERMINATED_FOR_UPGRADE 1
|
||||
|
||||
/**
|
||||
* Terminated but should be restarted
|
||||
*
|
||||
* This simply tells the launcher to restart the executable. Possible
|
||||
* reasons include the need to change a config parameter that requires restart.
|
||||
*/
|
||||
#define ZT_EXEC_RETURN_VALUE_PLEASE_RESTART 2
|
||||
|
||||
/**
|
||||
* Unrecoverable error
|
||||
*
|
||||
* This tells the launcher to exit after possibly sending an error report to
|
||||
* ZeroTier if the user has this option enabled.
|
||||
*/
|
||||
#define ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR 3
|
||||
|
||||
/**
|
||||
* Used on Unix systems to return from forked sub-process if exec fails
|
||||
*/
|
||||
#define ZT_EXEC_RETURN_VALUE_NO_BINARY 4
|
||||
|
||||
#endif
|
20
main.cpp
20
main.cpp
@ -56,8 +56,6 @@
|
||||
#include "node/Utils.hpp"
|
||||
#include "node/Node.hpp"
|
||||
|
||||
#include "launcher.h"
|
||||
|
||||
using namespace ZeroTier;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -102,7 +100,7 @@ static void sighandlerQuit(int sig)
|
||||
{
|
||||
Node *n = node;
|
||||
if (n)
|
||||
n->terminate();
|
||||
n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
|
||||
else exit(0);
|
||||
}
|
||||
#endif
|
||||
@ -117,7 +115,7 @@ static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
Node *n = node;
|
||||
if (n)
|
||||
n->terminate();
|
||||
n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -157,12 +155,12 @@ int main(int argc,char **argv)
|
||||
case '?':
|
||||
default:
|
||||
printHelp(argv[0],stderr);
|
||||
return ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (homeDir) {
|
||||
printHelp(argv[0],stderr);
|
||||
return ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
|
||||
return 0;
|
||||
}
|
||||
homeDir = argv[i];
|
||||
break;
|
||||
@ -176,22 +174,16 @@ int main(int argc,char **argv)
|
||||
mkdir(homeDir,0755); // will fail if it already exists
|
||||
#endif
|
||||
|
||||
int exitCode = ZT_EXEC_RETURN_VALUE_NORMAL_TERMINATION;
|
||||
int exitCode = 0;
|
||||
|
||||
node = new Node(homeDir);
|
||||
const char *termReason = (char *)0;
|
||||
switch(node->run()) {
|
||||
case Node::NODE_RESTART_FOR_RECONFIGURATION:
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_PLEASE_RESTART;
|
||||
break;
|
||||
case Node::NODE_UNRECOVERABLE_ERROR:
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_UNRECOVERABLE_ERROR;
|
||||
exitCode = -1;
|
||||
termReason = node->reasonForTermination();
|
||||
fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
|
||||
break;
|
||||
case Node::NODE_NEW_VERSION_AVAILABLE:
|
||||
exitCode = ZT_EXEC_RETURN_VALUE_TERMINATED_FOR_UPGRADE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -183,20 +183,20 @@ struct _NodeImpl
|
||||
{
|
||||
RuntimeEnvironment renv;
|
||||
std::string reasonForTerminationStr;
|
||||
Node::ReasonForTermination reasonForTermination;
|
||||
volatile Node::ReasonForTermination reasonForTermination;
|
||||
volatile bool started;
|
||||
volatile bool running;
|
||||
volatile bool terminateNow;
|
||||
|
||||
// run() calls this on all return paths
|
||||
inline Node::ReasonForTermination terminateBecause(Node::ReasonForTermination r,const char *rstr)
|
||||
inline Node::ReasonForTermination terminate()
|
||||
{
|
||||
RuntimeEnvironment *_r = &renv;
|
||||
LOG("terminating: %s",rstr);
|
||||
LOG("terminating: %s",reasonForTerminationStr.c_str());
|
||||
|
||||
renv.shutdownInProgress = true;
|
||||
Thread::sleep(500);
|
||||
|
||||
running = false;
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
delete renv.netconfService;
|
||||
#endif
|
||||
@ -209,11 +209,14 @@ struct _NodeImpl
|
||||
delete renv.prng;
|
||||
delete renv.log;
|
||||
|
||||
return reasonForTermination;
|
||||
}
|
||||
|
||||
inline Node::ReasonForTermination terminateBecause(Node::ReasonForTermination r,const char *rstr)
|
||||
{
|
||||
reasonForTerminationStr = rstr;
|
||||
reasonForTermination = r;
|
||||
running = false;
|
||||
|
||||
return r;
|
||||
return terminate();
|
||||
}
|
||||
};
|
||||
|
||||
@ -279,7 +282,6 @@ Node::Node(const char *hp)
|
||||
impl->reasonForTermination = Node::NODE_RUNNING;
|
||||
impl->started = false;
|
||||
impl->running = false;
|
||||
impl->terminateNow = false;
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
@ -377,6 +379,7 @@ Node::ReasonForTermination Node::run()
|
||||
// One is running.
|
||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,(std::string("another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound: ") + exc.what()).c_str());
|
||||
}
|
||||
_r->node = this;
|
||||
|
||||
// TODO: make configurable
|
||||
bool boundPort = false;
|
||||
@ -424,7 +427,7 @@ Node::ReasonForTermination Node::run()
|
||||
|
||||
LOG("%s starting version %s",_r->identity.address().toString().c_str(),versionString());
|
||||
|
||||
while (!impl->terminateNow) {
|
||||
while (impl->reasonForTermination == NODE_RUNNING) {
|
||||
uint64_t now = Utils::now();
|
||||
bool resynchronize = false;
|
||||
|
||||
@ -562,7 +565,7 @@ Node::ReasonForTermination Node::run()
|
||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"unexpected exception during outer main I/O loop");
|
||||
}
|
||||
|
||||
return impl->terminateBecause(Node::NODE_NORMAL_TERMINATION,"normal termination");
|
||||
return impl->terminate();
|
||||
}
|
||||
|
||||
const char *Node::reasonForTermination() const
|
||||
@ -573,10 +576,11 @@ const char *Node::reasonForTermination() const
|
||||
return ((_NodeImpl *)_impl)->reasonForTerminationStr.c_str();
|
||||
}
|
||||
|
||||
void Node::terminate()
|
||||
void Node::terminate(ReasonForTermination reason,const char *reasonText)
|
||||
throw()
|
||||
{
|
||||
((_NodeImpl *)_impl)->terminateNow = true;
|
||||
((_NodeImpl *)_impl)->reasonForTermination = reason;
|
||||
((_NodeImpl *)_impl)->reasonForTerminationStr = ((reasonText) ? reasonText : "");
|
||||
((_NodeImpl *)_impl)->renv.mainLoopWaitCondition.signal();
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,7 @@ public:
|
||||
NODE_RUNNING = 0,
|
||||
NODE_NORMAL_TERMINATION = 1,
|
||||
NODE_RESTART_FOR_RECONFIGURATION = 2,
|
||||
NODE_UNRECOVERABLE_ERROR = 3,
|
||||
NODE_NEW_VERSION_AVAILABLE = 4
|
||||
NODE_UNRECOVERABLE_ERROR = 3
|
||||
};
|
||||
|
||||
/**
|
||||
@ -124,13 +123,16 @@ public:
|
||||
throw();
|
||||
|
||||
/**
|
||||
* Cause run() to return with NODE_NORMAL_TERMINATION
|
||||
* Cause run() to return
|
||||
*
|
||||
* This can be called from a signal handler or another thread to signal a
|
||||
* running node to shut down. Shutdown may take a few seconds, so run()
|
||||
* may not return instantly. Multiple calls are ignored.
|
||||
*
|
||||
* @param reason Reason for termination
|
||||
* @param reasonText Text to be returned by reasonForTermination()
|
||||
*/
|
||||
void terminate()
|
||||
void terminate(ReasonForTermination reason,const char *reasonText)
|
||||
throw();
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "Peer.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "HMAC.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define strtoull _strtoui64
|
||||
@ -170,6 +171,7 @@ std::vector<std::string> NodeConfig::execute(const char *command)
|
||||
_P("200 help listnetworks");
|
||||
_P("200 help join <network ID>");
|
||||
_P("200 help leave <network ID>");
|
||||
_P("200 help terminate [<reason>]");
|
||||
} else if (cmd[0] == "listpeers") {
|
||||
_P("200 listpeers <ztaddr> <ipv4> <ipv6> <latency> <version>");
|
||||
_r->topology->eachPeer(_DumpPeerStatistics(r));
|
||||
@ -231,6 +233,10 @@ std::vector<std::string> NodeConfig::execute(const char *command)
|
||||
} else {
|
||||
_P("400 leave requires a network ID (>0) in hexadecimal format");
|
||||
}
|
||||
} else if (cmd[0] == "terminate") {
|
||||
if (cmd.size() > 1)
|
||||
_r->node->terminate(Node::NODE_NORMAL_TERMINATION,cmd[1].c_str());
|
||||
else _r->node->terminate(Node::NODE_NORMAL_TERMINATION,(const char *)0);
|
||||
} else {
|
||||
_P("404 %s No such command. Use 'help' for help.",cmd[0].c_str());
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ class SysEnv;
|
||||
class Multicaster;
|
||||
class CMWC4096;
|
||||
class Service;
|
||||
class Node;
|
||||
|
||||
/**
|
||||
* Holds global state for an instance of ZeroTier::Node
|
||||
@ -96,7 +97,7 @@ public:
|
||||
Topology *topology;
|
||||
SysEnv *sysEnv;
|
||||
NodeConfig *nc;
|
||||
|
||||
Node *node;
|
||||
#ifndef __WINDOWS__
|
||||
Service *netconfService; // may be null
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user