summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-19 13:56:48 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-19 13:56:48 -0700
commitabc82d6a52a75a30040fb4a458751a664a625c0a (patch)
treefe2f1cb05521fcc0da0472a572755829924d49c4 /node
parentacf7d70d241c6afc1f3f13fb7b678882f1ec3ea5 (diff)
downloadinfinitytier-abc82d6a52a75a30040fb4a458751a664a625c0a.tar.gz
infinitytier-abc82d6a52a75a30040fb4a458751a664a625c0a.zip
IPC changes and SocketManager changes all build!
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp9
-rw-r--r--node/Defaults.cpp10
-rw-r--r--node/IpcConnection.cpp2
-rw-r--r--node/IpcListener.cpp2
-rw-r--r--node/IpcListener.hpp6
-rw-r--r--node/Node.cpp270
-rw-r--r--node/Node.hpp79
-rw-r--r--node/NodeConfig.cpp6
-rw-r--r--node/PacketDecoder.cpp59
-rw-r--r--node/PacketDecoder.hpp9
-rw-r--r--node/Peer.cpp14
-rw-r--r--node/SocketManager.cpp2
-rw-r--r--node/Switch.cpp41
-rw-r--r--node/Switch.hpp30
14 files changed, 256 insertions, 283 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index bcefe7f9..58265bcd 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -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
diff --git a/node/Defaults.cpp b/node/Defaults.cpp
index 44f344ea..3e0727da 100644
--- a/node/Defaults.cpp
+++ b/node/Defaults.cpp
@@ -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;
diff --git a/node/IpcConnection.cpp b/node/IpcConnection.cpp
index c6937004..292403c0 100644
--- a/node/IpcConnection.cpp
+++ b/node/IpcConnection.cpp
@@ -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
}
diff --git a/node/IpcListener.cpp b/node/IpcListener.cpp
index dc5ef52a..94cf065f 100644
--- a/node/IpcListener.cpp
+++ b/node/IpcListener.cpp
@@ -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
diff --git a/node/IpcListener.hpp b/node/IpcListener.hpp
index 897c5451..00a29b5d 100644
--- a/node/IpcListener.hpp
+++ b/node/IpcListener.hpp
@@ -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;
diff --git a/node/Node.cpp b/node/Node.cpp
index ffd7568f..a1416896 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -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
+// ---------------------------------------------------------------------------
+
+struct _NodeControlClientImpl
{
- unsigned char key[32];
- int sock;
- void (*resultHandler)(void *,unsigned long,const char *);
+ void (*resultHandler)(void *,const char *);
void *arg;
- unsigned int controlPort;
- InetAddress localDestAddr;
- Mutex inUseLock;
-
- void threadMain()
- throw()
- {
- }
+ 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)
{
- _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());
- } catch ( ... ) {}
+ if ((event == IpcConnection::IPC_EVENT_COMMAND)&&(result))
+ ((_NodeControlClientImpl *)arg)->resultHandler(((_NodeControlClientImpl *)arg)->arg,result);
}
-Node::LocalClient::LocalClient(const char *authToken,unsigned int controlPort,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
+Node::NodeControlClient::NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken)
throw() :
- _impl((void *)0)
+ _impl((void *)new _NodeControlClientImpl)
{
- _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;
- }
+ _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";
}
-
- 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()
+Node::NodeControlClient::~NodeControlClient()
{
if (_impl) {
- ((_LocalClientImpl *)_impl)->inUseLock.lock();
- delete ((_LocalClientImpl *)_impl)->sock;
- ((_LocalClientImpl *)_impl)->inUseLock.unlock();
- delete ((_LocalClientImpl *)_impl);
+ delete ((_NodeControlClientImpl *)_impl)->ipcc;
+ delete (_NodeControlClientImpl *)_impl;
}
}
-unsigned long Node::LocalClient::send(const char *command)
+void Node::NodeControlClient::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;
- }
+ ((_NodeControlClientImpl *)_impl)->ipcc->printf("%s"ZT_EOL_S,command);
+ } catch ( ... ) {}
}
-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"
diff --git a/node/Node.hpp b/node/Node.hpp
index 18abdbb6..a8b13003 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -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
diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp
index 48782efa..07fa8b25 100644
--- a/node/NodeConfig.cpp
+++ b/node/NodeConfig.cpp
@@ -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","\\","'"));
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index 061c20f3..59a4ee56 100644
--- a/node/PacketDecoder.cpp
+++ b/node/PacketDecoder.cpp
@@ -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 ( ... ) {
diff --git a/node/PacketDecoder.hpp b/node/PacketDecoder.hpp
index 26aa85ce..9552c7fe 100644
--- a/node/PacketDecoder.hpp
+++ b/node/PacketDecoder.hpp
@@ -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 {
diff --git a/node/Peer.cpp b/node/Peer.cpp
index bd2e7e43..6bfa5b1d 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -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;
}
diff --git a/node/SocketManager.cpp b/node/SocketManager.cpp
index 5dbbf6d7..2c583f09 100644
--- a/node/SocketManager.cpp
+++ b/node/SocketManager.cpp
@@ -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 {
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 30160110..a59473b7 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -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;
diff --git a/node/Switch.hpp b/node/Switch.hpp
index ca55ae94..fd5837b7 100644
--- a/node/Switch.hpp
+++ b/node/Switch.hpp
@@ -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;