IPC changes and SocketManager changes all build!

This commit is contained in:
Adam Ierymenko 2014-03-19 13:56:48 -07:00
parent acf7d70d24
commit abc82d6a52
15 changed files with 288 additions and 341 deletions

View File

@ -114,14 +114,9 @@ error_no_byte_order_defined;
#define ZT_ADDRESS_RESERVED_PREFIX 0xff
/**
* Default local UDP port
* Default local port for ZeroTier traffic
*/
#define ZT_DEFAULT_UDP_PORT 9993
/**
* Local control port, also used for multiple invocation check
*/
#define ZT_DEFAULT_CONTROL_UDP_PORT 39393
#define ZT_DEFAULT_PORT 9993
/**
* Default payload MTU for UDP packets

View File

@ -56,35 +56,35 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
addrs.clear();
if (!id.fromString("8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("162.243.77.111",ZT_DEFAULT_UDP_PORT));
addrs.push_back(InetAddress("162.243.77.111",ZT_DEFAULT_PORT));
sn[id] = addrs;
// nyarlathotep.zerotier.com - San Francisco, California, USA
addrs.clear();
if (!id.fromString("7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("198.199.97.220",ZT_DEFAULT_UDP_PORT));
addrs.push_back(InetAddress("198.199.97.220",ZT_DEFAULT_PORT));
sn[id] = addrs;
// shub-niggurath.zerotier.com - Amsterdam, Netherlands
addrs.clear();
if (!id.fromString("36f63d6574:0:67a776487a1a99b32f413329f2b67c43fbf6152e42c6b66e89043e69d93e48314c7d709b58a83016bd2612dd89400b856e18c553da94892f7d3ca16bf2c92c24"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_UDP_PORT));
addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_PORT));
sn[id] = addrs;
// mi-go.zerotier.com - Singapore
addrs.clear();
if (!id.fromString("abbb7f4622:0:89d2c6b2062b10f4ce314dfcb914c082566247090a6f74c8ba1c15c63b205f540758f0abae85287397152c9d8cf463cfe51e7a480946cd6a31495b24ca13253c"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_UDP_PORT));
addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_PORT));
sn[id] = addrs;
// shoggoth.zerotier.com - Tokyo, Japan
addrs.clear();
if (!id.fromString("48e8f875cb:0:5ca54f55e1094f65589f3e6d74158b6964d418ddac3570757128f1c6a2498322d92fcdcd47de459f4d1f9b38df2afd0c7b3fc247ba3d773c38ba35288f24988e"))
throw std::runtime_error("invalid identity in Defaults");
addrs.push_back(InetAddress("108.61.200.101",ZT_DEFAULT_UDP_PORT));
addrs.push_back(InetAddress("108.61.200.101",ZT_DEFAULT_PORT));
sn[id] = addrs;
return sn;

View File

@ -156,7 +156,7 @@ void IpcConnection::threadMain()
_writeLock.unlock();
}
_handler(_arg,this,IPC_EVENT_CONNECTION_CLOSING,(const char *)0);
_handler(_arg,this,IPC_EVENT_CONNECTION_CLOSED,(const char *)0);
#endif
}

View File

@ -124,7 +124,7 @@ void IpcListener::threadMain()
break;
}
try {
_handler(_arg,new IpcConnection(s,_handler,_arg),Ipcconnection::IPC_EVENT_NEW_CONNECTION,(const char *)0);
_handler(_arg,new IpcConnection(s,_handler,_arg),IpcConnection::IPC_EVENT_NEW_CONNECTION,(const char *)0);
} catch ( ... ) {} // handlers should not throw
}
#endif

View File

@ -37,9 +37,9 @@
#include <stdexcept>
#ifdef __WINDOWS__
#define ZT_IPC_ENDPOINT "\\\\.\\pipe\\ZeroTierOne-control"
#define ZT_IPC_ENDPOINT_BASE "\\\\.\\pipe\\ZeroTierOne-"
#else
#define ZT_IPC_ENDPOINT "/tmp/.ZeroTierOne-control"
#define ZT_IPC_ENDPOINT_BASE "/tmp/.ZeroTierOne-"
#endif
namespace ZeroTier {
@ -78,7 +78,7 @@ public:
private:
std::string _endpoint;
void (*_handler)(void *,IpcConnection *,const char *);
void (*_handler)(void *,IpcConnection *,IpcConnection::EventType,const char *);
void *_arg;
volatile int _sock;
Thread _thread;

View File

@ -45,9 +45,7 @@
#include <WinSock2.h>
#include <Windows.h>
#include <ShlObj.h>
#endif
#ifdef __UNIX_LIKE__
#else
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
@ -55,176 +53,151 @@
#endif
#include "Node.hpp"
#include "RuntimeEnvironment.hpp"
#include "Logger.hpp"
#include "Utils.hpp"
#include "Defaults.hpp"
#include "Identity.hpp"
#include "Topology.hpp"
#include "SocketManager.hpp"
#include "Packet.hpp"
#include "Switch.hpp"
#include "Utils.hpp"
#include "EthernetTap.hpp"
#include "Logger.hpp"
#include "InetAddress.hpp"
#include "Salsa20.hpp"
#include "RuntimeEnvironment.hpp"
#include "CMWC4096.hpp"
#include "NodeConfig.hpp"
#include "Defaults.hpp"
#include "SysEnv.hpp"
#include "Network.hpp"
#include "MulticastGroup.hpp"
#include "Mutex.hpp"
#include "Multicaster.hpp"
#include "CMWC4096.hpp"
#include "SHA512.hpp"
#include "Service.hpp"
#include "SoftwareUpdater.hpp"
#include "Buffer.hpp"
#include "IpcConnection.hpp"
#include "../version.h"
namespace ZeroTier {
struct _LocalClientImpl
{
unsigned char key[32];
int sock;
void (*resultHandler)(void *,unsigned long,const char *);
void *arg;
unsigned int controlPort;
InetAddress localDestAddr;
Mutex inUseLock;
// ---------------------------------------------------------------------------
void threadMain()
throw()
{
}
struct _NodeControlClientImpl
{
void (*resultHandler)(void *,const char *);
void *arg;
IpcConnection *ipcc;
std::string err;
};
static void _CBlocalClientHandler(const SharedPtr<Socket> &sock,void *arg,const InetAddress &from,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
static void _CBipcResultHandler(void *arg,IpcConnection *ipcc,IpcConnection::EventType event,const char *result)
{
if ((event == IpcConnection::IPC_EVENT_COMMAND)&&(result))
((_NodeControlClientImpl *)arg)->resultHandler(((_NodeControlClientImpl *)arg)->arg,result);
}
Node::NodeControlClient::NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken)
throw() :
_impl((void *)new _NodeControlClientImpl)
{
_NodeControlClientImpl *impl = (_NodeControlClientImpl *)_impl;
std::string at;
if (authToken)
at = authToken;
else if (!Utils::readFile((std::string(hp) + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(),at))
impl->err = "no authentication token specified and authtoken.secret not readable";
else {
std::string myid;
if (Utils::readFile((std::string(hp) + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),myid)) {
std::string myaddr(myid.substr(0,myid.find(':')));
if (myaddr.length() != 10)
impl->err = "invalid address extracted from identity.public";
else {
try {
impl->resultHandler = resultHandler;
impl->arg = arg;
impl->ipcc = new IpcConnection((std::string(ZT_IPC_ENDPOINT_BASE) + myaddr).c_str(),&_CBipcResultHandler,_impl);
impl->ipcc->printf("auth %s"ZT_EOL_S,at.c_str());
} catch ( ... ) {
impl->err = "failure connecting to running ZeroTier One service";
}
}
} else impl->err = "unable to read identity.public";
}
}
Node::NodeControlClient::~NodeControlClient()
{
if (_impl) {
delete ((_NodeControlClientImpl *)_impl)->ipcc;
delete (_NodeControlClientImpl *)_impl;
}
}
void Node::NodeControlClient::send(const char *command)
throw()
{
_LocalClientImpl *impl = (_LocalClientImpl *)arg;
if (!impl)
return;
if (!impl->resultHandler)
return; // sanity check
Mutex::Lock _l(impl->inUseLock);
try {
unsigned long convId = 0;
std::vector<std::string> results;
if (!NodeConfig::decodeControlMessagePacket(impl->key,data.data(),data.size(),convId,results))
return;
for(std::vector<std::string>::iterator r(results.begin());r!=results.end();++r)
impl->resultHandler(impl->arg,convId,r->c_str());
((_NodeControlClientImpl *)_impl)->ipcc->printf("%s"ZT_EOL_S,command);
} catch ( ... ) {}
}
Node::LocalClient::LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
throw() :
_impl((void *)0)
{
_LocalClientImpl *impl = new _LocalClientImpl;
impl->sock =
SocketManager *sm = (SocketManager *)0;
for(unsigned int i=0;i<5000;++i) {
try {
sm = new SocketManager(0,32768 + (rand() % 20000),&_CBlocalClientHandler,impl);
break;
} catch ( ... ) {
sm = (SocketManager *)0;
}
}
if (sm) {
{
unsigned int csk[64];
SHA512::hash(csk,authToken,(unsigned int)strlen(authToken));
memcpy(impl->key,csk,32);
}
impl->sock = sock;
impl->resultHandler = resultHandler;
impl->arg = arg;
impl->controlPort = (controlPort) ? controlPort : (unsigned int)ZT_DEFAULT_CONTROL_UDP_PORT;
impl->localDestAddr = InetAddress::LO4;
impl->localDestAddr.setPort(impl->controlPort);
_impl = impl;
} else delete impl; // big problem, no ports?
}
Node::LocalClient::~LocalClient()
{
if (_impl) {
((_LocalClientImpl *)_impl)->inUseLock.lock();
delete ((_LocalClientImpl *)_impl)->sock;
((_LocalClientImpl *)_impl)->inUseLock.unlock();
delete ((_LocalClientImpl *)_impl);
}
}
unsigned long Node::LocalClient::send(const char *command)
throw()
{
if (!_impl)
return 0;
_LocalClientImpl *impl = (_LocalClientImpl *)_impl;
Mutex::Lock _l(impl->inUseLock);
try {
uint32_t convId = (uint32_t)rand();
if (!convId)
convId = 1;
std::vector<std::string> tmp;
tmp.push_back(std::string(command));
std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets(NodeConfig::encodeControlMessage(impl->key,convId,tmp));
for(std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> >::iterator p(packets.begin());p!=packets.end();++p)
impl->sock->send(impl->localDestAddr,p->data(),p->size(),-1);
return convId;
} catch ( ... ) {
return 0;
}
}
std::vector<std::string> Node::LocalClient::splitLine(const char *line)
std::vector<std::string> Node::NodeControlClient::splitLine(const char *line)
{
return Utils::split(line," ","\\","\"");
}
std::string Node::LocalClient::authTokenDefaultUserPath()
const char *Node::NodeControlClient::authTokenDefaultUserPath()
{
static std::string dlp;
static Mutex dlp_m;
Mutex::Lock _l(dlp_m);
#ifdef __WINDOWS__
char buf[16384];
if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,0,buf)))
return (std::string(buf) + "\\ZeroTier\\One\\authtoken.secret");
else return std::string();
if (!dlp.length()) {
char buf[16384];
if (SUCCEEDED(SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,0,buf)))
dlp = (std::string(buf) + "\\ZeroTier\\One\\authtoken.secret");
}
#else // not __WINDOWS__
const char *home = getenv("HOME");
if (home) {
if (!dlp.length()) {
const char *home = getenv("HOME");
if (home) {
#ifdef __APPLE__
return (std::string(home) + "/Library/Application Support/ZeroTier/One/authtoken.secret");
dlp = (std::string(home) + "/Library/Application Support/ZeroTier/One/authtoken.secret");
#else
return (std::string(home) + "/.zeroTierOneAuthToken");
dlp = (std::string(home) + "/.zeroTierOneAuthToken");
#endif
} else return std::string();
}
}
#endif // __WINDOWS__ or not __WINDOWS__
return dlp.c_str();
}
std::string Node::LocalClient::authTokenDefaultSystemPath()
const char *Node::NodeControlClient::authTokenDefaultSystemPath()
{
return (ZT_DEFAULTS.defaultHomePath + ZT_PATH_SEPARATOR_S"authtoken.secret");
static std::string dsp;
static Mutex dsp_m;
Mutex::Lock _l(dsp_m);
if (!dsp.length())
dsp = (ZT_DEFAULTS.defaultHomePath + ZT_PATH_SEPARATOR_S"authtoken.secret");
return dsp.c_str();
}
// ---------------------------------------------------------------------------
struct _NodeImpl
{
RuntimeEnvironment renv;
unsigned int port;
unsigned int controlPort;
unsigned int udpPort,tcpPort;
std::string reasonForTerminationStr;
volatile Node::ReasonForTermination reasonForTermination;
volatile bool started;
@ -352,16 +325,35 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
}
#endif // !__WINDOWS__
Node::Node(const char *hp,unsigned int port,unsigned int controlPort)
Node::Node(const char *hp,unsigned int udpPort,unsigned int tcpPort,bool resetIdentity)
throw() :
_impl(new _NodeImpl)
{
_NodeImpl *impl = (_NodeImpl *)_impl;
if ((hp)&&(strlen(hp) > 0))
if ((hp)&&(hp[0]))
impl->renv.homePath = hp;
else impl->renv.homePath = ZT_DEFAULTS.defaultHomePath;
impl->port = (port) ? port : (unsigned int)ZT_DEFAULT_UDP_PORT;
impl->controlPort = (controlPort) ? controlPort : (unsigned int)ZT_DEFAULT_CONTROL_UDP_PORT;
if (resetIdentity) {
// Forget identity and peer database, peer keys, etc.
Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "identity.public").c_str());
Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "identity.secret").c_str());
Utils::rm((impl->renv.homePath + ZT_PATH_SEPARATOR_S + "peers.persist").c_str());
// Truncate network config information in networks.d but leave the files since we
// still want to remember any networks we have joined. This will force re-config.
std::string networksDotD(impl->renv.homePath + ZT_PATH_SEPARATOR_S + "networks.d");
std::map< std::string,bool > nwfiles(Utils::listDirectory(networksDotD.c_str()));
for(std::map<std::string,bool>::iterator nwf(nwfiles.begin());nwf!=nwfiles.end();++nwf) {
FILE *foo = fopen((networksDotD + ZT_PATH_SEPARATOR_S + nwf->first).c_str(),"w");
if (foo)
fclose(foo);
}
}
impl->udpPort = ((udpPort > 0)&&(udpPort <= 0xffff)) ? udpPort : (unsigned int)ZT_DEFAULT_PORT;
impl->tcpPort = ((tcpPort > 0)&&(tcpPort <= 0xffff)) ? tcpPort : (unsigned int)ZT_DEFAULT_PORT;
impl->reasonForTermination = Node::NODE_RUNNING;
impl->started = false;
impl->running = false;
@ -373,6 +365,13 @@ Node::~Node()
delete (_NodeImpl *)_impl;
}
static void _CBztTraffic(const SharedPtr<Socket> &fromSock,void *arg,const InetAddress &from,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
{
const RuntimeEnvironment *_r = (const RuntimeEnvironment *)arg;
if ((_r->sw)&&(!_r->shutdownInProgress))
_r->sw->onRemotePacket(fromSock,from,data);
}
Node::ReasonForTermination Node::run()
throw()
{
@ -452,15 +451,13 @@ Node::ReasonForTermination Node::run()
// Create the objects that make up runtime state.
_r->mc = new Multicaster();
_r->sw = new Switch(_r);
_r->demarc = new Demarc(_r);
_r->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,_r);
_r->topology = new Topology(_r,Utils::fileExists((_r->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
_r->sysEnv = new SysEnv();
try {
_r->nc = new NodeConfig(_r,configAuthToken.c_str(),impl->controlPort);
_r->nc = new NodeConfig(_r,configAuthToken.c_str());
} catch (std::exception &exc) {
char foo[1024];
Utils::snprintf(foo,sizeof(foo),"unable to bind to local control port %u: is another instance of ZeroTier One already running?",impl->controlPort);
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,foo);
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"unable to initialize IPC socket: is ZeroTier One already running?");
}
_r->node = this;
#ifdef ZT_AUTO_UPDATE
@ -472,13 +469,6 @@ Node::ReasonForTermination Node::run()
}
#endif
// Bind local port for core I/O
if (!_r->demarc->bindLocalUdp(impl->port)) {
char foo[1024];
Utils::snprintf(foo,sizeof(foo),"unable to bind to global I/O port %u: is another instance of ZeroTier One already running?",impl->controlPort);
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,foo);
}
// Set initial supernode list
_r->topology->setSupernodes(ZT_DEFAULTS.supernodes);
} catch (std::bad_alloc &exc) {
@ -669,14 +659,14 @@ void Node::terminate(ReasonForTermination reason,const char *reasonText)
{
((_NodeImpl *)_impl)->reasonForTermination = reason;
((_NodeImpl *)_impl)->reasonForTerminationStr = ((reasonText) ? reasonText : "");
((_NodeImpl *)_impl)->renv.sw->whack();
((_NodeImpl *)_impl)->renv.sm->whack();
}
void Node::resync()
throw()
{
((_NodeImpl *)_impl)->resynchronize = true;
((_NodeImpl *)_impl)->renv.sw->whack();
((_NodeImpl *)_impl)->renv.sm->whack();
}
class _VersionStringMaker
@ -698,27 +688,3 @@ unsigned int Node::versionMinor() throw() { return ZEROTIER_ONE_VERSION_MINOR; }
unsigned int Node::versionRevision() throw() { return ZEROTIER_ONE_VERSION_REVISION; }
} // namespace ZeroTier
extern "C" {
ZeroTier::Node *zeroTierCreateNode(const char *hp,unsigned int port,unsigned int controlPort)
{
return new ZeroTier::Node(hp,port,controlPort);
}
void zeroTierDeleteNode(ZeroTier::Node *n)
{
delete n;
}
ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
{
return new ZeroTier::Node::LocalClient(authToken,controlPort,resultHandler,arg);
}
void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc)
{
delete lc;
}
} // extern "C"

View File

@ -50,20 +50,28 @@ public:
* otherwise it will be unable to open a local UDP socket to
* communicate with the service.
*/
class LocalClient
class NodeControlClient
{
public:
/**
* Create a new node config client
*
* @param authToken Authentication token
* @param controlPort Control port or 0 for 39393 (default)
* Initialization may fail. Call error() to check.
*
* @param hp Home path of ZeroTier One instance
* @param resultHandler Function to call when commands provide results
* @param arg First argument to result handler
* @param authToken Authentication token or NULL (default) to read from authtoken.secret in home path
*/
LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken = (const char *)0)
throw();
~LocalClient();
~NodeControlClient();
/**
* @return Initialization error or NULL if none
*/
const char *error() const;
/**
* Send a command to the local node
@ -75,12 +83,13 @@ public:
* @param command
* @return Conversation ID that will be provided to result handler when/if results are sent back
*/
unsigned long send(const char *command)
void send(const char *command)
throw();
inline unsigned long send(const std::string &command) throw() { return send(command.c_str()); }
inline void send(const std::string &command)
throw() { return send(command.c_str()); }
/**
* Split a line of results by space
* Split a line of results
*
* @param line Line to split
* @return Vector of fields
@ -89,19 +98,19 @@ public:
static inline std::vector<std::string> splitLine(const std::string &line) { return splitLine(line.c_str()); }
/**
* @return Default path for user-local authorization token for the current user or empty string if cannot be determined
* @return Default path for current user's authtoken.secret
*/
static std::string authTokenDefaultUserPath();
static const char *authTokenDefaultUserPath();
/**
* @return Default system path for auth token on this platform
* @return Default path to system authtoken.secret
*/
static std::string authTokenDefaultSystemPath();
static const char *authTokenDefaultSystemPath();
private:
// LocalClient is not copyable
LocalClient(const LocalClient&);
const LocalClient& operator=(const LocalClient&);
// NodeControlClient is not copyable
NodeControlClient(const NodeControlClient&);
const NodeControlClient& operator=(const NodeControlClient&);
void *_impl;
};
@ -129,7 +138,12 @@ public:
/**
* A serious unrecoverable error has occurred.
*/
NODE_UNRECOVERABLE_ERROR = 3
NODE_UNRECOVERABLE_ERROR = 3,
/**
* An address collision occurred (typically this should cause re-invocation with resetIdentity set to true)
*/
NODE_ADDRESS_COLLISION = 4
};
/**
@ -137,11 +151,12 @@ public:
*
* The node is not executed until run() is called.
*
* @param hp Home directory path
* @param port Port to bind for talking to the ZT1 network or 0 for 9993 (default)
* @param controlPort Port to bind locally for control packets or 0 for 39393 (default)
* @param hp Home directory path or NULL for system-wide default for this platform (default: NULL)
* @param udpPort UDP port or 0 for default (9993) (default: 0)
* @param tcpPort TCP port or 0 for default (9993) (default: 0)
* @param resetIdentity If true, delete identity before starting and regenerate (default: false)
*/
Node(const char *hp,unsigned int port,unsigned int controlPort)
Node(const char *hp = (const char *)0,unsigned int udpPort = 0,unsigned int tcpPort = 0,bool resetIdentity = false)
throw();
~Node();
@ -181,19 +196,12 @@ public:
throw();
/**
* Forget p2p links and resynchronize with peers
* Forget p2p links now and resynchronize with peers
*/
void resync()
throw();
/**
* Get the ZeroTier version in major.minor.revision string format
*
* @return Version in string form
*/
static const char *versionString()
throw();
static const char *versionString() throw();
static unsigned int versionMajor() throw();
static unsigned int versionMinor() throw();
static unsigned int versionRevision() throw();
@ -208,17 +216,4 @@ private:
} // namespace ZeroTier
extern "C" {
// Functions with C-style linkage for easy DLL symbol table
// lookup. These just create instances of Node and LocalClient.
ZeroTier::Node *zeroTierCreateNode(const char *hp,unsigned int port,unsigned int controlPort);
void zeroTierDeleteNode(ZeroTier::Node *n);
ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg);
void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc);
} // extern "C"
#endif

View File

@ -53,7 +53,7 @@ namespace ZeroTier {
NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken) :
_r(renv),
_ipcListener(ZT_IPC_ENDPOINT,&_CBcommandHandler,this),
_ipcListener((std::string(ZT_IPC_ENDPOINT_BASE) + renv->identity.address().toString()).c_str(),&_CBcommandHandler,this),
_authToken(authToken)
{
{
@ -177,8 +177,8 @@ public:
void NodeConfig::_doCommand(IpcConnection *ipcc,const char *commandLine)
{
if (!commandLine)
return; // sanity check
if ((!commandLine)||(!commandLine[0]))
return;
std::vector<std::string> r;
std::vector<std::string> cmd(Utils::split(commandLine,"\r\n \t","\\","'"));

View File

@ -40,7 +40,6 @@
#include "Peer.hpp"
#include "NodeConfig.hpp"
#include "Service.hpp"
#include "Demarc.hpp"
#include "SoftwareUpdater.hpp"
namespace ZeroTier {
@ -82,7 +81,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r)
switch(verb()) {
case Packet::VERB_NOP:
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NOP,0,Packet::VERB_NOP,Utils::now());
return true;
case Packet::VERB_HELLO:
return _doHELLO(_r); // legal, but why? :)
@ -156,7 +155,7 @@ bool PacketDecoder::_doERROR(const RuntimeEnvironment *_r,const SharedPtr<Peer>
break;
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,Utils::now());
} catch (std::exception &ex) {
TRACE("dropped ERROR from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) {
@ -200,7 +199,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
outp.append(packetId());
outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
outp.armor(key,true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
} else {
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
}
@ -227,7 +226,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
outp.append(packetId());
outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
outp.armor(key,true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
} else {
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
}
@ -246,7 +245,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
peer = _r->topology->addPeer(newPeer);
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP,Utils::now());
peer->setRemoteVersion(vMajor,vMinor,vRevision);
// If a supernode has a version higher than ours, this causes a software
@ -263,7 +262,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
} catch (std::exception &ex) {
TRACE("dropped HELLO from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) {
@ -324,7 +323,7 @@ bool PacketDecoder::_doOK(const RuntimeEnvironment *_r,const SharedPtr<Peer> &pe
break;
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,Utils::now());
} catch (std::exception &ex) {
TRACE("dropped OK from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) {
@ -343,7 +342,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr<Peer>
outp.append(packetId());
id.serialize(outp,false);
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
//TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
} else {
Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
@ -352,13 +351,13 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr<Peer>
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
outp.append(payload(),ZT_ADDRESS_LENGTH);
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
//TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
}
} else {
TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str());
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now());
return true;
}
@ -387,7 +386,7 @@ bool PacketDecoder::_doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr<P
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",source().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,Utils::now());
_r->sw->contact(withPeer,atAddr);
} else {
TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",source().toString().c_str(),_remoteAddress.toString().c_str());
@ -426,7 +425,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer>
// we receive unicast frames from it. This is called "implicit social
// ordering" in other docs.
_r->mc->bringCloser(network->id(),source());
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now());
} else {
TRACE("dropped FRAME from %s(%s): sender not a member of closed network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
@ -436,7 +435,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer>
outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
outp.append(network->id());
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
return true;
}
@ -569,11 +568,11 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
source().toString().c_str(),
frameLen,
startingFifoItems);
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
// At this point the frame is basically valid, so we can call it a receive
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now());
// This gets updated later in most cases but start with the global limit.
unsigned int maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH;
@ -592,7 +591,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("dropped MULTICAST_FRAME from %s(%s): duplicate",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
@ -619,7 +618,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
outp.append(nwid);
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
// We do not terminate here, since if the member just has an out of
// date cert or hasn't sent us a cert yet we still want to propagate
@ -638,7 +637,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: source mac %s doesn't belong to %s, and bridging is not supported on network",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid,sourceMac.toString().c_str(),origin.toString().c_str());
return true;
@ -654,7 +653,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: ethertype %u is not allowed",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),etherType);
return true;
@ -671,7 +670,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str());
return true;
@ -692,7 +691,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("not forwarding MULTICAST_FRAME from %s(%s): depth == 0xffff (do not forward)",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
@ -707,7 +706,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
TRACE("not forwarding MULTICAST_FRAME from %s(%s): max propagation depth reached",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
@ -766,7 +765,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
//TRACE("not forwarding MULTICAST_FRAME from %s(%s): no next hop",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
@ -787,7 +786,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
origin.toString().c_str(),
nextHop.toString().c_str(),
numAdded);
_r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1);
_r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
#endif
// Send to next hop, reusing this packet as scratch space
@ -824,7 +823,7 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP
}
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,now);
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,now);
} catch (std::exception &ex) {
TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) {
@ -860,7 +859,7 @@ bool PacketDecoder::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *
}
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP,Utils::now());
} catch (std::exception &ex) {
TRACE("dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
} catch ( ... ) {
@ -899,11 +898,11 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
outp.append(nwid);
outp.armor(peer->key(),true);
_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
_fromSock->send(_remoteAddress,outp.data(),outp.size());
#ifndef __WINDOWS__
}
#endif // !__WINDOWS__
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,Utils::now());
} catch (std::exception &exc) {
TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what());
} catch ( ... ) {
@ -924,7 +923,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const
nw->requestConfiguration();
}
}
peer->onReceive(_r,_localPort,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now());
peer->onReceive(_r,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now());
} catch (std::exception &exc) {
TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what());
} catch ( ... ) {

View File

@ -37,6 +37,7 @@
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
#include "Peer.hpp"
#include "Socket.hpp"
/*
* The big picture:
@ -70,16 +71,16 @@ public:
* Create a new packet-in-decode
*
* @param b Source buffer with raw packet data
* @param localPort Local port on which packet was received
* @param fromSock Socket on which packet was received
* @param remoteAddress Address from which packet came
* @throws std::out_of_range Range error processing packet
*/
template<unsigned int C2>
PacketDecoder(const Buffer<C2> &b,Demarc::Port localPort,const InetAddress &remoteAddress)
PacketDecoder(const Buffer<C2> &b,const SharedPtr<Socket> &fromSock,const InetAddress &remoteAddress)
throw(std::out_of_range) :
Packet(b),
_receiveTime(Utils::now()),
_localPort(localPort),
_fromSock(fromSock),
_remoteAddress(remoteAddress),
_step(DECODE_WAITING_FOR_SENDER_LOOKUP),
__refCount()
@ -124,7 +125,7 @@ private:
bool _doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
uint64_t _receiveTime;
Demarc::Port _localPort;
SharedPtr<Socket> _fromSock;
InetAddress _remoteAddress;
enum {

View File

@ -67,7 +67,6 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
void Peer::onReceive(
const RuntimeEnvironment *_r,
Demarc::Port localPort,
const InetAddress &remoteAddr,
unsigned int hops,
uint64_t packetId,
@ -80,7 +79,6 @@ void Peer::onReceive(
// Update last receive info for our direct path
WanPath *const wp = (remoteAddr.isV4() ? &_ipv4p : &_ipv6p);
wp->lastReceive = now;
wp->localPort = ((localPort) ? localPort : Demarc::ANY_PORT);
if (!wp->fixed)
wp->addr = remoteAddr;
@ -101,14 +99,14 @@ void Peer::onReceive(
bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,uint64_t now)
{
if ((_ipv6p.isActive(now))||((!(_ipv4p.addr))&&(_ipv6p.addr))) {
if (_r->demarc->send(_ipv6p.addr,data,len,-1)) {
if (_r->sm->send(_ipv6p.addr,false,data,len)) {
_ipv6p.lastSend = now;
return true;
}
}
if (_ipv4p.addr) {
if (_r->sm->send(_ipv4p.addr,data,len,-1)) {
if (_r->sm->send(_ipv4p.addr,false,data,len)) {
_ipv4p.lastSend = now;
return true;
}
@ -121,14 +119,14 @@ bool Peer::sendFirewallOpener(const RuntimeEnvironment *_r,uint64_t now)
{
bool sent = false;
if (_ipv4p.addr) {
if (_r->demarc->send(_ipv4p.localPort,_ipv4p.addr,"\0",1,ZT_FIREWALL_OPENER_HOPS)) {
if (_r->sm->sendFirewallOpener(_ipv4p.addr,ZT_FIREWALL_OPENER_HOPS)) {
_ipv4p.lastFirewallOpener = now;
sent = true;
}
}
if (_ipv6p.addr) {
if (_r->demarc->send(_ipv6p.localPort,_ipv6p.addr,"\0",1,ZT_FIREWALL_OPENER_HOPS)) {
if (_r->sm->sendFirewallOpener(_ipv6p.addr,ZT_FIREWALL_OPENER_HOPS)) {
_ipv6p.lastFirewallOpener = now;
sent = true;
}
@ -142,7 +140,7 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now)
bool sent = false;
if (_ipv4p.addr) {
TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv4p.addr.toString().c_str());
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv4p.localPort,_ipv4p.addr)) {
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv4p.addr,false)) {
_ipv4p.lastSend = now;
sent = true;
}
@ -150,7 +148,7 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now)
if (_ipv6p.addr) {
TRACE("PING %s(%s)",_id.address().toString().c_str(),_ipv6p.addr.toString().c_str());
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv6p.localPort,_ipv6p.addr)) {
if (_r->sw->sendHELLO(SharedPtr<Peer>(this),_ipv6p.addr,false)) {
_ipv6p.lastSend = now;
sent = true;
}

View File

@ -427,7 +427,7 @@ void SocketManager::poll(unsigned long timeout)
ts.reserve(_tcpSockets.size());
uint64_t now = Utils::now();
for(std::map< InetAddress,SharedPtr<Socket> >::iterator s(_tcpSockets.begin());s!=_tcpSockets.end();) {
if ((now - ((TcpSocket *)s->second.get())->_lastActivity) < ZT_TCP_TUNNEL_ACTIVITY_TIMEOUT) {
if ((now - ((TcpSocket *)s->second.ptr())->_lastActivity) < ZT_TCP_TUNNEL_ACTIVITY_TIMEOUT) {
ts.push_back(s->second);
++s;
} else {

View File

@ -47,7 +47,6 @@
#include "RuntimeEnvironment.hpp"
#include "Peer.hpp"
#include "NodeConfig.hpp"
#include "Demarc.hpp"
#include "CMWC4096.hpp"
#include "../version.h"
@ -64,14 +63,14 @@ Switch::~Switch()
{
}
void Switch::onRemotePacket(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::onRemotePacket(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
{
try {
if (data.size() > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
if (data[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR)
_handleRemotePacketFragment(localPort,fromAddr,data);
_handleRemotePacketFragment(fromSock,fromAddr,data);
else if (data.size() >= ZT_PROTO_MIN_PACKET_LENGTH)
_handleRemotePacketHead(localPort,fromAddr,data);
_handleRemotePacketHead(fromSock,fromAddr,data);
}
} catch (std::exception &ex) {
TRACE("dropped packet from %s: unexpected exception: %s",fromAddr.toString().c_str(),ex.what());
@ -207,7 +206,7 @@ void Switch::sendHELLO(const Address &dest)
send(outp,false);
}
bool Switch::sendHELLO(const SharedPtr<Peer> &dest,Demarc::Port localPort,const InetAddress &remoteAddr)
bool Switch::sendHELLO(const SharedPtr<Socket> &fromSock,const SharedPtr<Peer> &dest,const InetAddress &remoteAddr)
{
uint64_t now = Utils::now();
Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO);
@ -218,7 +217,21 @@ bool Switch::sendHELLO(const SharedPtr<Peer> &dest,Demarc::Port localPort,const
outp.append(now);
_r->identity.serialize(outp,false);
outp.armor(dest->key(),false);
return (_r->demarc->send(localPort,remoteAddr,outp.data(),outp.size(),-1) != Demarc::NULL_PORT);
return fromSock->send(remoteAddr,outp.data(),outp.size());
}
bool Switch::sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &remoteAddr,bool tcp)
{
uint64_t now = Utils::now();
Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO);
outp.append((unsigned char)ZT_PROTO_VERSION);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
outp.append(now);
_r->identity.serialize(outp,false);
outp.armor(dest->key(),false);
return _r->sm->send(remoteAddr,tcp,outp.data(),outp.size());
}
bool Switch::unite(const Address &p1,const Address &p2,bool force)
@ -311,12 +324,11 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
{
Demarc::Port fromPort = _r->demarc->pick(atAddr);
_r->demarc->send(fromPort,atAddr,"\0",1,ZT_FIREWALL_OPENER_HOPS);
_r->sm->sendFirewallOpener(atAddr,ZT_FIREWALL_OPENER_HOPS);
{
Mutex::Lock _l(_contactQueue_m);
_contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_RENDEZVOUS_NAT_T_DELAY,fromPort,atAddr));
_contactQueue.push_back(ContactQueueEntry(peer,Utils::now() + ZT_RENDEZVOUS_NAT_T_DELAY,atAddr));
}
// Kick main loop out of wait so that it can pick up this
@ -334,7 +346,7 @@ unsigned long Switch::doTimerTasks()
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
if (now >= qi->fireAtTime) {
TRACE("sending NAT-T HELLO to %s(%s)",qi->peer->address().toString().c_str(),qi->inaddr.toString().c_str());
sendHELLO(qi->peer,qi->localPort,qi->inaddr);
sendHELLO(qi->peer,qi->inaddr,false);
_contactQueue.erase(qi++);
} else {
nextDelay = std::min(nextDelay,(unsigned long)(qi->fireAtTime - now));
@ -529,7 +541,7 @@ const char *Switch::etherTypeName(const unsigned int etherType)
return "UNKNOWN";
}
void Switch::_handleRemotePacketFragment(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::_handleRemotePacketFragment(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data)
{
Packet::Fragment fragment(data);
Address destination(fragment.destination());
@ -598,9 +610,9 @@ void Switch::_handleRemotePacketFragment(Demarc::Port localPort,const InetAddres
}
}
void Switch::_handleRemotePacketHead(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::_handleRemotePacketHead(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data)
{
SharedPtr<PacketDecoder> packet(new PacketDecoder(data,localPort,fromAddr));
SharedPtr<PacketDecoder> packet(new PacketDecoder(data,fromSock,fromAddr));
Address source(packet->source());
Address destination(packet->destination());
@ -711,8 +723,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
tmp.armor(peer->key(),encrypt);
Demarc::Port localPort;
if ((localPort = via->send(_r,tmp.data(),chunkSize,now))) {
if (via->send(_r,tmp.data(),chunkSize,now)) {
if (chunkSize < tmp.size()) {
// Too big for one bite, fragment the rest
unsigned int fragStart = chunkSize;

View File

@ -44,9 +44,9 @@
#include "Array.hpp"
#include "Network.hpp"
#include "SharedPtr.hpp"
#include "SocketManager.hpp"
#include "Multicaster.hpp"
#include "PacketDecoder.hpp"
#include "Socket.hpp"
/* Ethernet frame types that might be relevant to us */
#define ZT_ETHERTYPE_IPV4 0x0800
@ -78,11 +78,11 @@ public:
/**
* Called when a packet is received from the real network
*
* @param localPort Local port on which packet was received
* @param fromSock Originating socket
* @param fromAddr Internet IP address of origin
* @param data Packet data
*/
void onRemotePacket(Demarc::Port localPort,const InetAddress &fromAddr,const Buffer<4096> &data);
void onRemotePacket(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data);
/**
* Called when a packet comes from a local Ethernet tap
@ -122,12 +122,22 @@ public:
/**
* Send a HELLO announcement immediately to the indicated address
*
* @param localPort Originating local port or ANY_PORT to pick
* @param remoteAddr IP address to send to
* @param fromSock Send from this local socket
* @param dest Destination peer
* @param remoteAddr Remote address
* @return True if send appears successful
*/
bool sendHELLO(const SharedPtr<Peer> &dest,Demarc::Port localPort,const InetAddress &remoteAddr);
bool sendHELLO(const SharedPtr<Socket> &fromSock,const SharedPtr<Peer> &dest,const InetAddress &remoteAddr);
/**
* Send a HELLO announcement immediately to the indicated address
*
* @param dest Destination peer
* @param remoteAddr Remote address
* @param tcp Attempt to use TCP?
* @return True if send appears successful
*/
bool sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &remoteAddr,bool tcp);
/**
* Send RENDEZVOUS to two peers to permit them to directly connect
@ -214,12 +224,12 @@ public:
private:
void _handleRemotePacketFragment(
Demarc::Port localPort,
const SharedPtr<Socket> &fromSock,
const InetAddress &fromAddr,
const Buffer<4096> &data);
void _handleRemotePacketHead(
Demarc::Port localPort,
const SharedPtr<Socket> &fromSock,
const InetAddress &fromAddr,
const Buffer<4096> &data);
@ -279,15 +289,13 @@ private:
struct ContactQueueEntry
{
ContactQueueEntry() {}
ContactQueueEntry(const SharedPtr<Peer> &p,uint64_t ft,Demarc::Port lp,const InetAddress &a) :
ContactQueueEntry(const SharedPtr<Peer> &p,uint64_t ft,const InetAddress &a) :
peer(p),
fireAtTime(ft),
localPort(lp),
inaddr(a) {}
SharedPtr<Peer> peer;
uint64_t fireAtTime;
Demarc::Port localPort;
InetAddress inaddr;
};
std::list<ContactQueueEntry> _contactQueue;

View File

@ -44,7 +44,6 @@
#include "node/Salsa20.hpp"
#include "node/MAC.hpp"
#include "node/Peer.hpp"
#include "node/Condition.hpp"
#include "node/NodeConfig.hpp"
#include "node/Dictionary.hpp"
#include "node/EthernetTap.hpp"
@ -66,7 +65,7 @@ using namespace ZeroTier;
static unsigned char fuzzbuf[1048576];
static Condition webDoneCondition;
static volatile bool webDone = false;
static std::string webSha512ShouldBe;
static void testHttpHandler(void *arg,int code,const std::string &url,bool onDisk,const std::string &body)
{
@ -77,45 +76,52 @@ static void testHttpHandler(void *arg,int code,const std::string &url,bool onDis
std::cout << "got " << body.length() << " bytes, response code " << code << ", SHA-512 OK" << std::endl;
else std::cout << "got " << body.length() << " bytes, response code " << code << ", SHA-512 FAILED!" << std::endl;
} else std::cout << "ERROR " << code << ": " << body << std::endl;
webDoneCondition.signal();
webDone = true;
}
static int testHttp()
{
webSha512ShouldBe = "221b348c8278ad2063c158fb15927c35dc6bb42880daf130d0574025f88ec350811c34fae38a014b576d3ef5c98af32bb540e68204810db87a51fa9b239ea567";
std::cout << "[http] fetching http://download.zerotier.com/dev/1k ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/1k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "342e1a058332aad2d7a5412c1d9cd4ad02b4038178ca0c3ed9d34e3cf0905c118b684e5d2a935a158195d453d7d69e9c6e201e252620fb53f29611794a5d4b0c";
std::cout << "[http] fetching http://download.zerotier.com/dev/2k ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/2k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "439562e1471dd6bdb558cb680f38dd7742e521497e280cb1456a31f74b9216b7d98145b3896c2f68008e6ac0c1662a4cb70562caeac294c5d01f378b22a21292";
std::cout << "[http] fetching http://download.zerotier.com/dev/4k ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/4k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "fbd3901a9956158b9d290efa1af4fff459d8c03187c98b0e630d10a19fab61940e668652257763973f6cde34f2aa81574f9a50b1979b675b45ddd18d69a4ceb8";
std::cout << "[http] fetching http://download.zerotier.com/dev/8k ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/8k",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "098ae593f8c3a962f385f9f008ec2116ad22eea8bc569fc88a06a0193480fdfb27470345c427116d19179fb2a74df21d95fe5f1df575a9f2d10d99595708b765";
std::cout << "[http] fetching http://download.zerotier.com/dev/4m ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/4m",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "";
std::cout << "[http] fetching http://download.zerotier.com/dev/NOEXIST ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://download.zerotier.com/dev/NOEXIST",HttpClient::NO_HEADERS,30,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
webSha512ShouldBe = "";
std::cout << "[http] fetching http://1.1.1.1/SHOULD_TIME_OUT ... "; std::cout.flush();
webDone = false;
HttpClient::GET("http://1.1.1.1/SHOULD_TIME_OUT",HttpClient::NO_HEADERS,4,&testHttpHandler,(void *)0);
webDoneCondition.wait();
while (!webDone) Thread::sleep(500);
return 0;
}
@ -512,38 +518,6 @@ static int testOther()
}
std::cout << "PASS" << std::endl;
std::cout << "[other] Testing command bus encode/decode... "; std::cout.flush();
try {
static char key[32] = { 0 };
for(unsigned int k=0;k<100;++k) {
std::vector<std::string> original;
for(unsigned int i=0,j=rand() % 256,l=(rand() % 1024)+1;i<j;++i)
original.push_back(std::string(l,'x'));
std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets(NodeConfig::encodeControlMessage(key,1,original));
//std::cout << packets.size() << ' '; std::cout.flush();
std::vector<std::string> after;
for(std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> >::iterator i(packets.begin());i!=packets.end();++i) {
unsigned long convId = 9999;
if (!NodeConfig::decodeControlMessagePacket(key,i->data(),i->size(),convId,after)) {
std::cout << "FAIL (decode)" << std::endl;
return -1;
}
if (convId != 1) {
std::cout << "FAIL (conversation ID)" << std::endl;
return -1;
}
}
if (after != original) {
std::cout << "FAIL (compare)" << std::endl;
return -1;
}
}
} catch (std::exception &exc) {
std::cout << "FAIL (" << exc.what() << ")" << std::endl;
return -1;
}
std::cout << "PASS" << std::endl;
std::cout << "[other] Testing Dictionary... "; std::cout.flush();
for(int k=0;k<1000;++k) {
Dictionary a,b;
@ -617,8 +591,8 @@ int main(int argc,char **argv)
std::cout << "[info] sizeof(void *) == " << sizeof(void *) << std::endl;
std::cout << "[info] default home: " << ZT_DEFAULTS.defaultHomePath << std::endl;
std::cout << "[info] system authtoken.secret: " << Node::LocalClient::authTokenDefaultSystemPath() << std::endl;
std::cout << "[info] user authtoken.secret: " << Node::LocalClient::authTokenDefaultUserPath() << std::endl;
std::cout << "[info] system authtoken.secret: " << Node::NodeControlClient::authTokenDefaultSystemPath() << std::endl;
std::cout << "[info] user authtoken.secret: " << Node::NodeControlClient::authTokenDefaultUserPath() << std::endl;
srand((unsigned int)time(0));