summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-31 22:23:55 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-31 22:23:55 -0700
commitf13493edb2aae228ddbe70cc2f0609c541faf2d7 (patch)
treecb1a6845ec82e2ea361ce15e88440a249992091c /node
parent595b386afcd4e4eca0cf379cd14689c1db8ee647 (diff)
downloadinfinitytier-f13493edb2aae228ddbe70cc2f0609c541faf2d7.tar.gz
infinitytier-f13493edb2aae228ddbe70cc2f0609c541faf2d7.zip
Oops... turns out we need to differentiate incoming from outgoing TCP and indeed learn incoming TCP paths. Otherwise the recipient of a TCP connection does not know to reply via TCP! Heh.
Diffstat (limited to 'node')
-rw-r--r--node/PacketDecoder.cpp18
-rw-r--r--node/Path.hpp81
-rw-r--r--node/Peer.cpp80
-rw-r--r--node/Socket.hpp12
-rw-r--r--node/SocketManager.cpp11
-rw-r--r--node/SocketManager.hpp17
-rw-r--r--node/Switch.cpp10
-rw-r--r--node/Switch.hpp12
-rw-r--r--node/TcpSocket.cpp8
-rw-r--r--node/TcpSocket.hpp6
-rw-r--r--node/Topology.cpp2
11 files changed, 147 insertions, 110 deletions
diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp
index 329aab78..2b8cba51 100644
--- a/node/PacketDecoder.cpp
+++ b/node/PacketDecoder.cpp
@@ -579,7 +579,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
source().toString().c_str(),
frameLen,
startingFifoItems);
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct));
#endif
// At this point the frame is basically valid, so we can call it a receive
@@ -602,7 +602,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct));
#endif
TRACE("dropped MULTICAST_FRAME from %s(%s): duplicate",source().toString().c_str(),_remoteAddress.toString().c_str());
return true;
@@ -648,7 +648,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -664,7 +664,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -681,7 +681,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -702,7 +702,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -717,7 +717,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -776,7 +776,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
mctdepth,
(_r->topology->amSupernode() ? 'S' : '-'),
_r->identity.address().toString().c_str());
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,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;
@@ -797,7 +797,7 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
origin.toString().c_str(),
nextHop.toString().c_str(),
numAdded);
- _r->sm->send(ZT_DEFAULTS.multicastTraceWatcher,false,mct,strlen(mct));
+ _r->sm->sendUdp(ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct));
#endif
// Send to next hop, reusing this packet as scratch space
diff --git a/node/Path.hpp b/node/Path.hpp
index b227811a..8cd0776c 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -39,7 +39,7 @@
#include "Utils.hpp"
#include "Buffer.hpp"
-#define ZT_PATH_SERIALIZATION_VERSION 1
+#define ZT_PATH_SERIALIZATION_VERSION 2
namespace ZeroTier {
@@ -49,13 +49,21 @@ namespace ZeroTier {
class Path
{
public:
+ enum Type
+ {
+ PATH_TYPE_NULL = 0,
+ PATH_TYPE_UDP = 1,
+ PATH_TYPE_TCP_OUT = 2,
+ PATH_TYPE_TCP_IN = 3
+ };
+
Path() :
_lastSend(0),
_lastReceived(0),
_lastFirewallOpener(0),
_lastPing(0),
_addr(),
- _tcp(false),
+ _type(PATH_TYPE_NULL),
_fixed(false) {}
Path(const Path &p)
@@ -64,13 +72,13 @@ public:
memcpy(this,&p,sizeof(Path));
}
- Path(const InetAddress &addr,bool tcp,bool fixed = false) :
+ Path(const InetAddress &addr,Type t,bool fixed = false) :
_lastSend(0),
_lastReceived(0),
_lastFirewallOpener(0),
_lastPing(0),
_addr(addr),
- _tcp(tcp),
+ _type(t),
_fixed(fixed) {}
inline Path &operator=(const Path &p)
@@ -81,13 +89,16 @@ public:
}
inline const InetAddress &address() const throw() { return _addr; }
- inline bool tcp() const throw() { return _tcp; }
+
+ inline Type type() const throw() { return _type; }
+ inline bool tcp() const throw() { return ((_type == PATH_TYPE_TCP_IN)||(_type == PATH_TYPE_TCP_OUT)); }
+
inline uint64_t lastSend() const throw() { return _lastSend; }
inline uint64_t lastReceived() const throw() { return _lastReceived; }
inline uint64_t lastFirewallOpener() const throw() { return _lastFirewallOpener; }
inline uint64_t lastPing() const throw() { return _lastPing; }
- inline bool fixed() const throw() { return _fixed; }
+ inline bool fixed() const throw() { return _fixed; }
inline void setFixed(bool f) throw() { _fixed = f; }
inline void sent(uint64_t t) throw() { _lastSend = t; }
@@ -111,40 +122,34 @@ public:
inline std::string toString() const
{
uint64_t now = Utils::now();
- char lsago[32],lrago[32],lfoago[32],lpago[32];
- Utils::snprintf(lsago,sizeof(lsago),"%lld",(long long)((_lastSend != 0) ? (now - _lastSend) : -1));
- Utils::snprintf(lrago,sizeof(lrago),"%lld",(long long)((_lastReceived != 0) ? (now - _lastReceived) : -1));
- Utils::snprintf(lfoago,sizeof(lfoago),"%lld",(long long)((_lastFirewallOpener != 0) ? (now - _lastFirewallOpener) : -1));
- Utils::snprintf(lpago,sizeof(lfoago),"%lld",(long long)((_lastPing != 0) ? (now - _lastPing) : -1));
- return ( _addr.toString() +
- "[" +
- (_tcp ? "tcp" : "udp") +
- ";" +
- lsago +
- ";" +
- lrago +
- ";" +
- lpago +
- ";" +
- lfoago +
- ";" +
- (active(now) ? "active" : "inactive") +
- ";" +
- (_fixed ? "fixed" : "learned") +
- "]"
- );
+ char tmp[1024];
+ const char *t = "";
+ switch(_type) {
+ case PATH_TYPE_NULL: t = "null"; break;
+ case PATH_TYPE_UDP: t = "udp"; break;
+ case PATH_TYPE_TCP_OUT: t = "tcp_out"; break;
+ case PATH_TYPE_TCP_IN: t = "tcp_in"; break;
+ }
+ Utils::snprintf(tmp,sizeof(tmp),"%s:%s:%lld;%lld;%lld;%lld;%s",
+ t,
+ _addr.toString().c_str(),
+ (long long)((_lastSend != 0) ? (now - _lastSend) : -1),
+ (long long)((_lastReceived != 0) ? (now - _lastReceived) : -1),
+ (long long)((_lastFirewallOpener != 0) ? (now - _lastFirewallOpener) : -1),
+ (long long)((_lastPing != 0) ? (now - _lastPing) : -1),
+ ((_fixed) ? "fixed" : (active(now) ? "active" : "inactive"))
+ );
+ return std::string(tmp);
}
- inline bool operator==(const Path &p) const throw() { return ((_addr == p._addr)&&(_tcp == p._tcp)); }
- inline bool operator!=(const Path &p) const throw() { return ((_addr != p._addr)||(_tcp != p._tcp)); }
+ inline bool operator==(const Path &p) const throw() { return ((_addr == p._addr)&&(_type == p._type)); }
+ inline bool operator!=(const Path &p) const throw() { return ((_addr != p._addr)||(_type != p._type)); }
inline bool operator<(const Path &p) const
throw()
{
- if (_addr == p._addr) {
- if (!_tcp) // UDP < TCP
- return p._tcp;
- return false;
- } else return (_addr < p._addr);
+ if (_addr == p._addr)
+ return ((int)_type < (int)p._type);
+ else return (_addr < p._addr);
}
inline bool operator>(const Path &p) const throw() { return (p < *this); }
inline bool operator<=(const Path &p) const throw() { return !(p < *this); }
@@ -171,7 +176,7 @@ public:
b.append((uint16_t)_addr.port());
break;
}
- b.append(_tcp ? (unsigned char)1 : (unsigned char)0);
+ b.append((unsigned char)_type);
b.append(_fixed ? (unsigned char)1 : (unsigned char)0);
}
template<unsigned int C>
@@ -199,7 +204,7 @@ public:
_addr.zero();
break;
}
- _tcp = (b[p++] != 0);
+ _type = (Type)b[p++];
_fixed = (b[p++] != 0);
return (p - startAt);
@@ -211,7 +216,7 @@ private:
volatile uint64_t _lastFirewallOpener;
volatile uint64_t _lastPing;
InetAddress _addr;
- bool _tcp;
+ Type _type;
bool _fixed;
};
diff --git a/node/Peer.cpp b/node/Peer.cpp
index f7d24fee..6e8ecc01 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -69,25 +69,36 @@ void Peer::receive(
Packet::Verb inReVerb,
uint64_t now)
{
+ // Update system-wide last packet receive time
*((const_cast<uint64_t *>(&(_r->timeOfLastPacketReceived)))) = now;
- if (!hops) { // direct packet
+ // Learn paths from direct packets (hops == 0)
+ if (!hops) {
{
Mutex::Lock _l(_lock);
- // Update receive time on known paths
bool havePath = false;
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- if ((p->address() == remoteAddr)&&(p->tcp() == (fromSock->type() == Socket::ZT_SOCKET_TYPE_TCP))) {
+ if ((p->address() == remoteAddr)&&(p->tcp() == fromSock->tcp())) {
p->received(now);
havePath = true;
break;
}
}
- // Learn new UDP paths (learning TCP would require an explicit mechanism)
- if ((!havePath)&&(fromSock->type() != Socket::ZT_SOCKET_TYPE_TCP)) {
- _paths.push_back(Path(remoteAddr,false,false));
+ if (!havePath) {
+ Path::Type pt = Path::PATH_TYPE_UDP;
+ switch(fromSock->type()) {
+ case Socket::ZT_SOCKET_TYPE_TCP_IN:
+ pt = Path::PATH_TYPE_TCP_IN;
+ break;
+ case Socket::ZT_SOCKET_TYPE_TCP_OUT:
+ pt = Path::PATH_TYPE_TCP_OUT;
+ break;
+ default:
+ break;
+ }
+ _paths.push_back(Path(remoteAddr,pt,false));
_paths.back().received(now);
}
}
@@ -110,26 +121,30 @@ bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,u
{
Mutex::Lock _l(_lock);
- std::vector<Path>::iterator p(_paths.begin());
- if (p == _paths.end()) {
- //TRACE("send to %s failed: no paths available",_id.address().toString().c_str());
- return false;
- }
- uint64_t bestPathLastReceived = p->lastReceived();
- std::vector<Path>::iterator bestPath = p;
- while (++p != _paths.end()) {
- uint64_t lr = p->lastReceived();
- if (lr > bestPathLastReceived) {
- bestPathLastReceived = lr;
- bestPath = p;
+ for(;;) {
+ std::vector<Path>::iterator p(_paths.begin());
+ if (p == _paths.end())
+ return false;
+
+ uint64_t bestPathLastReceived = p->lastReceived();
+ std::vector<Path>::iterator bestPath = p;
+ while (++p != _paths.end()) {
+ uint64_t lr = p->lastReceived();
+ if (lr > bestPathLastReceived) {
+ bestPathLastReceived = lr;
+ bestPath = p;
+ }
}
- }
- //TRACE("send to %s: using path: %s",_id.address().toString().c_str(),bestPath->toString().c_str());
-
- if (_r->sm->send(bestPath->address(),bestPath->tcp(),data,len)) {
- bestPath->sent(now);
- return true;
+ if (_r->sm->send(bestPath->address(),bestPath->tcp(),bestPath->type() == Path::PATH_TYPE_TCP_OUT,data,len)) {
+ bestPath->sent(now);
+ return true;
+ } else {
+ if (bestPath->fixed())
+ return false;
+ _paths.erase(bestPath);
+ // ... try again and pick a different path
+ }
}
return false;
@@ -160,23 +175,24 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now,bool firstSinceRes
bool pingTcp;
if (!firstSinceReset) {
- // Do not use TCP if one of our UDP endpoints has answered recently.
+ uint64_t lastUdp = 0;
+ uint64_t lastTcp = 0;
uint64_t lastPing = 0;
- uint64_t lastDirectReceive = 0;
-
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- lastPing = std::max(lastPing,p->lastPing());
- lastDirectReceive = std::max(lastDirectReceive,p->lastReceived());
+ if (p->tcp())
+ lastTcp = std::max(p->lastReceived(),lastTcp);
+ else lastUdp = std::max(p->lastReceived(),lastUdp);
+ lastPing = std::max(p->lastPing(),lastPing);
}
-
- pingTcp = ( (lastDirectReceive < lastPing) && ((lastPing - lastDirectReceive) >= ZT_PING_UNANSWERED_AFTER) );
+ uint64_t lastAny = std::max(lastUdp,lastTcp);
+ pingTcp = ( ( (lastAny < lastPing) && ((lastPing - lastAny) >= ZT_PING_UNANSWERED_AFTER) ) || (lastTcp > lastUdp) );
} else pingTcp = false;
TRACE("PING %s (pingTcp==%d)",_id.address().toString().c_str(),(int)pingTcp);
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
if ((pingTcp)||(!p->tcp())) {
- if (_r->sw->sendHELLO(self,p->address(),p->tcp())) {
+ if (_r->sw->sendHELLO(self,*p)) {
p->sent(now);
p->pinged(now);
sent = true;
diff --git a/node/Socket.hpp b/node/Socket.hpp
index ff185e6f..3cfedb1a 100644
--- a/node/Socket.hpp
+++ b/node/Socket.hpp
@@ -65,7 +65,8 @@ public:
{
ZT_SOCKET_TYPE_UDP_V4,
ZT_SOCKET_TYPE_UDP_V6,
- ZT_SOCKET_TYPE_TCP
+ ZT_SOCKET_TYPE_TCP_IN, // incoming connection, not listen
+ ZT_SOCKET_TYPE_TCP_OUT
};
virtual ~Socket() {}
@@ -80,6 +81,15 @@ public:
}
/**
+ * @return True if this is a TCP socket
+ */
+ inline bool tcp() const
+ throw()
+ {
+ return ((_type == ZT_SOCKET_TYPE_TCP_IN)||(_type == ZT_SOCKET_TYPE_TCP_OUT));
+ }
+
+ /**
* Send a ZeroTier message packet
*
* @param to Destination address (ignored in connected TCP sockets)
diff --git a/node/SocketManager.cpp b/node/SocketManager.cpp
index 722db5b1..85bf9dc3 100644
--- a/node/SocketManager.cpp
+++ b/node/SocketManager.cpp
@@ -347,7 +347,7 @@ SocketManager::~SocketManager()
_closeSockets();
}
-bool SocketManager::send(const InetAddress &to,bool tcp,const void *msg,unsigned int msglen)
+bool SocketManager::send(const InetAddress &to,bool tcp,bool autoConnectTcp,const void *msg,unsigned int msglen)
{
if (tcp) {
SharedPtr<Socket> ts;
@@ -360,6 +360,9 @@ bool SocketManager::send(const InetAddress &to,bool tcp,const void *msg,unsigned
if (ts)
return ts->send(to,msg,msglen);
+ if (!autoConnectTcp)
+ return false;
+
#ifdef __WINDOWS__
SOCKET s = ::socket(to.isV4() ? AF_INET : AF_INET6,SOCK_STREAM,0);
if (s == INVALID_SOCKET)
@@ -394,7 +397,7 @@ bool SocketManager::send(const InetAddress &to,bool tcp,const void *msg,unsigned
} else connecting = true;
}
- ts = SharedPtr<Socket>(new TcpSocket(this,s,connecting,to));
+ ts = SharedPtr<Socket>(new TcpSocket(this,s,Socket::ZT_SOCKET_TYPE_TCP_OUT,connecting,to));
if (!ts->send(to,msg,msglen)) {
_fdSetLock.lock();
FD_CLR(s,&_readfds);
@@ -496,7 +499,7 @@ void SocketManager::poll(unsigned long timeout)
InetAddress fromia((const struct sockaddr *)&from);
Mutex::Lock _l2(_tcpSockets_m);
try {
- _tcpSockets[fromia] = SharedPtr<Socket>(new TcpSocket(this,sockfd,false,fromia));
+ _tcpSockets[fromia] = SharedPtr<Socket>(new TcpSocket(this,sockfd,Socket::ZT_SOCKET_TYPE_TCP_IN,false,fromia));
#ifdef __WINDOWS__
{ u_long iMode=1; ioctlsocket(sockfd,FIONBIO,&iMode); }
#ifdef ZT_TCP_NODELAY
@@ -536,7 +539,7 @@ void SocketManager::poll(unsigned long timeout)
InetAddress fromia((const struct sockaddr *)&from);
Mutex::Lock _l2(_tcpSockets_m);
try {
- _tcpSockets[fromia] = SharedPtr<Socket>(new TcpSocket(this,sockfd,false,fromia));
+ _tcpSockets[fromia] = SharedPtr<Socket>(new TcpSocket(this,sockfd,Socket::ZT_SOCKET_TYPE_TCP_IN,false,fromia));
#ifdef __WINDOWS__
{ u_long iMode=1; ioctlsocket(sockfd,FIONBIO,&iMode); }
#ifdef ZT_TCP_NODELAY
diff --git a/node/SocketManager.hpp b/node/SocketManager.hpp
index 003c35eb..40a0c1df 100644
--- a/node/SocketManager.hpp
+++ b/node/SocketManager.hpp
@@ -85,17 +85,22 @@ public:
/**
* Send a message to a remote peer
*
- * If 'tcp' is true an existing TCP socket will be used or an attempt will
- * be made to connect if one is not available. The message will be placed
- * in the connecting TCP socket's outgoing queue, so if the connection
- * succeeds the message will be sent. Otherwise it will be dropped.
- *
* @param to Destination address
* @param tcp Use TCP?
+ * @param autoConnectTcp If true, automatically initiate TCP connection if there is none
+ * @param msg Message to send
+ * @param msglen Length of message
+ */
+ bool send(const InetAddress &to,bool tcp,bool autoConnectTcp,const void *msg,unsigned int msglen);
+
+ /**
+ * Send a message to a remote peer via UDP (shortcut for setting both TCP params to false in send)
+ *
+ * @param to Destination address
* @param msg Message to send
* @param msglen Length of message
*/
- bool send(const InetAddress &to,bool tcp,const void *msg,unsigned int msglen);
+ inline bool sendUdp(const InetAddress &to,const void *msg,unsigned int msglen) { return send(to,false,false,msg,msglen); }
/**
* Send a UDP packet with a limited IP TTL
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 0e58c744..2ee3a4a0 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -214,7 +214,7 @@ void Switch::sendHELLO(const Address &dest)
send(outp,false);
}
-bool Switch::sendHELLO(const SharedPtr<Socket> &fromSock,const SharedPtr<Peer> &dest,const InetAddress &remoteAddr)
+bool Switch::sendHELLO(const SharedPtr<Peer> &dest,const Path &path)
{
uint64_t now = Utils::now();
Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO);
@@ -225,10 +225,10 @@ bool Switch::sendHELLO(const SharedPtr<Socket> &fromSock,const SharedPtr<Peer> &
outp.append(now);
_r->identity.serialize(outp,false);
outp.armor(dest->key(),false);
- return fromSock->send(remoteAddr,outp.data(),outp.size());
+ return _r->sm->send(path.address(),path.tcp(),path.type() == Path::PATH_TYPE_TCP_OUT,outp.data(),outp.size());
}
-bool Switch::sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &remoteAddr,bool tcp)
+bool Switch::sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &destUdp)
{
uint64_t now = Utils::now();
Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO);
@@ -239,7 +239,7 @@ bool Switch::sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &remoteAddr
outp.append(now);
_r->identity.serialize(outp,false);
outp.armor(dest->key(),false);
- return _r->sm->send(remoteAddr,tcp,outp.data(),outp.size());
+ return _r->sm->send(deskUdp,false,false,outp.data(),outp.size());
}
bool Switch::unite(const Address &p1,const Address &p2,bool force)
@@ -354,7 +354,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->inaddr,false);
+ sendHELLO(qi->peer,qi->inaddr);
_contactQueue.erase(qi++);
} else {
nextDelay = std::min(nextDelay,(unsigned long)(qi->fireAtTime - now));
diff --git a/node/Switch.hpp b/node/Switch.hpp
index fd5837b7..ee78d9fd 100644
--- a/node/Switch.hpp
+++ b/node/Switch.hpp
@@ -122,22 +122,20 @@ public:
/**
* Send a HELLO announcement immediately to the indicated address
*
- * @param fromSock Send from this local socket
* @param dest Destination peer
- * @param remoteAddr Remote address
+ * @param path Network path to peer
* @return True if send appears successful
*/
- bool sendHELLO(const SharedPtr<Socket> &fromSock,const SharedPtr<Peer> &dest,const InetAddress &remoteAddr);
+ bool sendHELLO(const SharedPtr<Peer> &dest,const Path &path);
/**
- * Send a HELLO announcement immediately to the indicated address
+ * Send a HELLO announcement immediately to the indicated address via UDP
*
* @param dest Destination peer
- * @param remoteAddr Remote address
- * @param tcp Attempt to use TCP?
+ * @param destUdp UDP inet address
* @return True if send appears successful
*/
- bool sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &remoteAddr,bool tcp);
+ bool sendHELLO(const SharedPtr<Peer> &dest,const InetAddress &destUdp);
/**
* Send RENDEZVOUS to two peers to permit them to directly connect
diff --git a/node/TcpSocket.cpp b/node/TcpSocket.cpp
index 7dbcc4e1..b21cbd5e 100644
--- a/node/TcpSocket.cpp
+++ b/node/TcpSocket.cpp
@@ -72,7 +72,6 @@ bool TcpSocket::send(const InetAddress &to,const void *msg,unsigned int msglen)
return true; // sanity check
Mutex::Lock _l(_writeLock);
-
bool writeInProgress = ((_outptr != 0)||(_connecting));
// Ensure that _outbuf is large enough
@@ -144,9 +143,10 @@ bool TcpSocket::notifyAvailableForRead(const SharedPtr<Socket> &self,SocketManag
if ((pl)&&(p >= pl)) {
Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> data(_inbuf + 5,pl - 5);
- sm->handleReceivedPacket(self,_remote,data);
- memmove(_inbuf,_inbuf + pl,p - pl);
- p -= pl;
+ memmove(_inbuf,_inbuf + pl,p -= pl);
+ try {
+ sm->handleReceivedPacket(self,_remote,data);
+ } catch ( ... ) {} // handlers should not throw
pl = 0;
}
}
diff --git a/node/TcpSocket.hpp b/node/TcpSocket.hpp
index ea2b0ddf..8a9a7095 100644
--- a/node/TcpSocket.hpp
+++ b/node/TcpSocket.hpp
@@ -71,11 +71,11 @@ public:
protected:
#ifdef __WINDOWS__
- TcpSocket(SocketManager *sm,SOCKET s,bool c,const InetAddress &r) :
+ TcpSocket(SocketManager *sm,SOCKET s,Socket::Type t,bool c,const InetAddress &r) :
#else
- TcpSocket(SocketManager *sm,int s,bool c,const InetAddress &r) :
+ TcpSocket(SocketManager *sm,int s,Socket::Type t,bool c,const InetAddress &r) :
#endif
- Socket(Socket::ZT_SOCKET_TYPE_TCP,s),
+ Socket(t,s),
_lastActivity(Utils::now()),
_sm(sm),
_outbuf((unsigned char *)0),
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 6390a338..d4df3ce6 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -65,7 +65,7 @@ void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<Ine
if (!p)
p = addPeer(SharedPtr<Peer>(new Peer(_r->identity,i->first)));
for(std::vector< std::pair<InetAddress,bool> >::const_iterator j(i->second.begin());j!=i->second.end();++j)
- p->addPath(Path(j->first,j->second,true));
+ p->addPath(Path(j->first,(j->second) ? Path::PATH_TYPE_TCP_OUT : Path::PATH_TYPE_UDP,true));
p->use(now);
_supernodePeers.push_back(p);
}