Send path simplification.

This commit is contained in:
Adam Ierymenko 2015-04-03 13:14:37 -07:00
parent a69e1876f1
commit ee0f56355b
10 changed files with 99 additions and 122 deletions

View File

@ -408,9 +408,9 @@ typedef struct
* What trust hierarchy role does this peer have?
*/
enum ZT1_PeerRole {
ZT1_PEER_ROLE_NODE = 0 // ordinary node
ZT1_PEER_ROLE_NODE = 0, // ordinary node
ZT1_PEER_ROLE_HUB = 1, // locally federated hub
ZT1_PEER_ROLE_SUPERNODE = 2, // planetary supernode
ZT1_PEER_ROLE_SUPERNODE = 2 // planetary supernode
};
/**
@ -541,18 +541,14 @@ typedef int (*ZT1_DataStorePutFunction)(ZT1_Node *,const char *,const void *,uns
/**
* Function to send a ZeroTier packet out over the wire
*
* Parameters: (1) node, (2) address, (3) desperation, (4) spam? (bool),
* (5) packet data, (6) packet data length.
*
* If spam is nonzero, the implementation should attempt to send the packet
* over all link types or protocols up to and including the stated level of
* desperation. Non-applicable link types can of course be skipped.
* Parameters: (1) node, (2) address, (3) link desperation,
* (4) packet data, (5) packet data length.
*
* The function must return zero on success and may return any error code
* on failure. Note that success does not (of course) guarantee packet
* delivery. It only means that the packet appears to have been sent.
*/
typedef int (*ZT1_WirePacketSendFunction)(ZT1_Node *,const struct sockaddr_storage *,int,int,const void *,unsigned int);
typedef int (*ZT1_WirePacketSendFunction)(ZT1_Node *,const struct sockaddr_storage *,int,const void *,unsigned int);
/**
* Function to send a frame out to a virtual network port
@ -583,12 +579,12 @@ typedef void (*ZT1_VirtualNetworkFrameFunction)(ZT1_Node *,uint64_t,uint64_t,uin
enum ZT1_ResultCode ZT1_Node_new(
ZT1_Node **node,
uint64_t now,
ZT1_DataStoreGetFunction *dataStoreGetFunction,
ZT1_DataStorePutFunction *dataStorePutFunction,
ZT1_WirePacketSendFunction *wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback,
ZT1_StatusCallback *statusCallback);
ZT1_DataStoreGetFunction dataStoreGetFunction,
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_StatusCallback statusCallback);
/**
* Process a packet received from the physical wire

View File

@ -46,12 +46,12 @@ namespace ZeroTier {
Node::Node(
uint64_t now,
ZT1_DataStoreGetFunction *dataStoreGetFunction,
ZT1_DataStorePutFunction *dataStorePutFunction,
ZT1_WirePacketSendFunction *wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback,
ZT1_StatusCallback *statusCallback) :
ZT1_DataStoreGetFunction dataStoreGetFunction,
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_StatusCallback statusCallback) :
RR(new RuntimeEnvironment(this)),
_dataStoreGetFunction(dataStoreGetFunction),
_dataStorePutFunction(dataStorePutFunction),
@ -183,12 +183,12 @@ extern "C" {
enum ZT1_ResultCode ZT1_Node_new(
ZT1_Node **node,
uint64_t now,
ZT1_DataStoreGetFunction *dataStoreGetFunction,
ZT1_DataStorePutFunction *dataStorePutFunction,
ZT1_WirePacketSendFunction *wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback,
ZT1_StatusCallback *statusCallback)
ZT1_DataStoreGetFunction dataStoreGetFunction,
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_StatusCallback statusCallback)
{
*node = (ZT1_Node *)0;
try {

View File

@ -57,12 +57,12 @@ class Node
public:
Node(
uint64_t now,
ZT1_DataStoreGetFunction *dataStoreGetFunction,
ZT1_DataStorePutFunction *dataStorePutFunction,
ZT1_WirePacketSendFunction *wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback,
ZT1_StatusCallback *statusCallback);
ZT1_DataStoreGetFunction dataStoreGetFunction,
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
ZT1_StatusCallback statusCallback);
~Node();
@ -85,7 +85,7 @@ public:
const void *frameData,
unsigned int frameLength,
uint64_t *nextCallDeadline);
ZT1_Resultcode processNothing(uint64_t now,uint64_t *nextCallDeadline);
ZT1_ResultCode processNothing(uint64_t now,uint64_t *nextCallDeadline);
ZT1_ResultCode join(uint64_t nwid);
ZT1_ResultCode leave(uint64_t nwid);
ZT1_ResultCode multicastSubscribe(ZT1_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi = 0);
@ -111,16 +111,14 @@ public:
* @param data Packet data
* @param len Packet length
* @param desperation Link desperation for reaching this address
* @param spam If true, flag this packet to be spammed to lower-desperation links
* @return True if packet appears to have been sent
*/
inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len,int desperation,bool spam)
inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len,int desperation)
{
return (_wirePacketSendFunction(
reinterpret_cast<ZT1_Node *>(this),
reinterpret_cast<const struct sockaddr_storage *>(&addr),
desperation,
(int)spam,
data,
len) == 0);
}
@ -160,28 +158,24 @@ public:
return ((nw == _networks.end()) ? SharedPtr<Network>() : nw->second);
}
inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure)
{
}
inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_dataStorePutFunction(reinterpret_cast<ZT1_Node *>(this),name,data,len,(int)secure) == 0); }
inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); }
inline std::string dataStoreGet(const char *name)
{
}
inline void dataStoreDelete(const char *name)
{
}
inline void dataStoreDelete(const char *name) { _dataStorePutFunction(reinterpret_cast<ZT1_Node *>(this),name,(const void *)0,0,0); }
private:
RuntimeEnvironment *RR;
ZT1_DataStoreGetFunction *_dataStoreGetFunction;
ZT1_DataStorePutFunction *_dataStorePutFunction;
ZT1_WirePacketSendFunction *_wirePacketSendFunction;
ZT1_VirtualNetworkFrameFunction *_virtualNetworkFrameFunction;
ZT1_VirtualNetworkConfigCallback *_virtualNetworkConfigCallback;
ZT1_StatusCallback *_statusCallback;
ZT1_DataStoreGetFunction _dataStoreGetFunction;
ZT1_DataStorePutFunction _dataStorePutFunction;
ZT1_WirePacketSendFunction _wirePacketSendFunction;
ZT1_VirtualNetworkFrameFunction _virtualNetworkFrameFunction;
ZT1_VirtualNetworkConfigCallback _virtualNetworkConfigCallback;
ZT1_StatusCallback _statusCallback;
//Dictionary _localConfig; // persisted as local.conf
//Mutex _localConfig_m;

View File

@ -36,8 +36,11 @@
#include <algorithm>
#include "Constants.hpp"
#include "Node.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "AntiRecursion.hpp"
#include "RuntimeEnvironment.hpp"
namespace ZeroTier {
@ -91,6 +94,8 @@ public:
/**
* Called when a packet is sent to this path
*
* This is called automatically by Path::send().
*
* @param t Time of send
*/
inline void sent(uint64_t t) throw() { _lastSend = t; }
@ -128,7 +133,7 @@ public:
*/
inline int desperation(uint64_t now) const
{
if ((_lastSend > _lastReceived)&&(_fixed))
if ((_fixed)&&(_lastSend > _lastReceived))
return std::max(_lastReceiveDesperation,(int)((_lastSend - _lastReceived) / ZT_DESPERATION_INCREMENT));
return _lastReceiveDesperation;
}
@ -143,6 +148,25 @@ public:
return ( (_fixed) || ((now - _lastReceived) < ZT_PEER_PATH_ACTIVITY_TIMEOUT) );
}
/**
* Send a packet via this path
*
* @param RR Runtime environment
* @param data Packet data
* @param len Packet length
* @param now Current time
* @return True if transport reported success
*/
inline bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
{
if (RR->node->putPacket(_addr,data,len,desperation(now))) {
sent(now);
RR->antiRec->logOutgoingZT(data,len);
return true;
}
return false;
}
/**
* @param now Current time
* @return Human-readable address and other information about this path

View File

@ -43,7 +43,6 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
_lastUnicastFrame(0),
_lastMulticastFrame(0),
_lastAnnouncedTo(0),
_lastSpammed(0),
_vMajor(0),
_vMinor(0),
_vRevision(0),
@ -147,31 +146,6 @@ void Peer::received(
_lastMulticastFrame = now;
}
bool Peer::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
{
Path *bestPath = (Path *)0;
uint64_t lrMax = 0;
for(unsigned int p=0,np=_numPaths;p<np;++p) {
if ((_paths[p].active(now)&&(_paths[p].lastReceived() >= lrMax)) {
lrMax = _paths[p].lastReceived();
bestPath = &(_paths[p]);
}
}
if (bestPath) {
bool spam = ((now - _lastSpammed) >= ZT_DESPERATION_SPAM_INTERVAL);
if (RR->node->putPacket(bestPath->address(),data,len,bestPath->desperation(),spam)) {
bestPath->sent(now);
RR->antiRec->logOutgoingZT(data,len);
if (spam)
_lastSpammed = now;
return true;
}
}
return false;
}
void Peer::addPath(const Path &newp)
{
unsigned int np = _numPaths;

View File

@ -132,18 +132,23 @@ public:
Packet::Verb inReVerb = Packet::VERB_NOP);
/**
* Send a packet directly to this peer
* Get the best direct path to this peer
*
* This sends only via direct paths if available and does not handle
* finding of relays. That is done in the send logic in Switch.
*
* @param RR Runtime environment
* @param data Data to send
* @param len Length of packet
* @param now Current time
* @return True if packet appears to have been sent via some available path
* @return Best path or NULL if there are no active (or fixed) direct paths
*/
bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now);
Path *getBestPath(uint64_t now)
{
Path *bestPath = (Path *)0;
uint64_t lrMax = 0;
for(unsigned int p=0,np=_numPaths;p<np;++p) {
if ((_paths[p].active(now))&&(_paths[p].lastReceived() >= lrMax)) {
lrMax = _paths[p].lastReceived();
bestPath = &(_paths[p]);
}
}
return bestPath;
}
/**
* @return All known direct paths to this peer
@ -359,25 +364,20 @@ private:
void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now);
unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH];
uint64_t _lastUsed;
uint64_t _lastReceive; // direct or indirect
uint64_t _lastUnicastFrame;
uint64_t _lastMulticastFrame;
uint64_t _lastAnnouncedTo;
uint64_t _lastSpammed;
uint16_t _vProto;
uint16_t _vMajor;
uint16_t _vMinor;
uint16_t _vRevision;
Identity _id;
Path _paths[ZT_PEER_MAX_PATHS];
unsigned int _numPaths;
unsigned int _latency;
unsigned int _spamCounter;
AtomicCounter __refCount;
};

View File

@ -32,13 +32,10 @@
#include <utility>
#include <stdexcept>
#include "../version.h"
#include "../include/ZeroTierOne.h"
#include "Constants.hpp"
#ifdef __WINDOWS__
#include <WinSock2.h>
#include <Windows.h>
#endif
#include "Switch.hpp"
#include "Node.hpp"
#include "EthernetTap.hpp"
@ -50,8 +47,6 @@
#include "CMWC4096.hpp"
#include "AntiRecursion.hpp"
#include "../version.h"
namespace ZeroTier {
Switch::Switch(const RuntimeEnvironment *renv) :
@ -64,16 +59,17 @@ Switch::~Switch()
{
}
void Switch::onRemotePacket(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data)
void Switch::onRemotePacket(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data)
{
try {
if (data.size() == ZT_PROTO_BEACON_LENGTH) {
_handleBeacon(fromSock,fromAddr,data);
_handleBeacon(fromAddr,linkDesperation,data);
} else if (data.size() > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
if (data[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR)
_handleRemotePacketFragment(fromSock,fromAddr,data);
else if (data.size() >= ZT_PROTO_MIN_PACKET_LENGTH)
_handleRemotePacketHead(fromSock,fromAddr,data);
if (data[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) {
_handleRemotePacketFragment(fromAddr,linkDesperation,data);
} else if (data.size() >= ZT_PROTO_MIN_PACKET_LENGTH) {
_handleRemotePacketHead(fromAddr,linkDesperation,data);
}
}
} catch (std::exception &ex) {
TRACE("dropped packet from %s: unexpected exception: %s",fromAddr.toString().c_str(),ex.what());
@ -376,7 +372,7 @@ void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
{
// Send simple packet directly to indicated address -- works for most NATs
sendHELLO(peer,atAddr);
TRACE("sending NAT-t HELLO to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());
TRACE("sending NAT-t message to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());
// If we have not punched through after this timeout, open refreshing can of whupass
{
@ -543,7 +539,7 @@ const char *Switch::etherTypeName(const unsigned int etherType)
return "UNKNOWN";
}
void Switch::_handleRemotePacketFragment(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data)
{
Packet::Fragment fragment(data);
Address destination(fragment.destination());
@ -615,7 +611,7 @@ void Switch::_handleRemotePacketFragment(const SharedPtr<Socket> &fromSock,const
}
}
void Switch::_handleRemotePacketHead(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data)
{
SharedPtr<IncomingPacket> packet(new IncomingPacket(data,fromSock,fromAddr));
@ -690,7 +686,7 @@ void Switch::_handleRemotePacketHead(const SharedPtr<Socket> &fromSock,const Ine
}
}
void Switch::_handleBeacon(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data)
void Switch::_handleBeacon(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data)
{
Address beaconAddr(data.field(ZT_PROTO_BEACON_IDX_ADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
if (beaconAddr == RR->identity.address())

View File

@ -45,7 +45,6 @@
#include "Network.hpp"
#include "SharedPtr.hpp"
#include "IncomingPacket.hpp"
#include "Socket.hpp"
/* Ethernet frame types that might be relevant to us */
#define ZT_ETHERTYPE_IPV4 0x0800
@ -60,9 +59,7 @@
namespace ZeroTier {
class RuntimeEnvironment;
class EthernetTap;
class Logger;
class Node;
class Peer;
/**
@ -82,11 +79,11 @@ public:
/**
* Called when a packet is received from the real network
*
* @param fromSock Originating socket
* @param fromAddr Internet IP address of origin
* @param linkDesperation Link desperation of path over which packet was received
* @param data Packet data
*/
void onRemotePacket(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,Buffer<ZT_SOCKET_MAX_MESSAGE_LEN> &data);
void onRemotePacket(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data);
/**
* Called when a packet comes from a local Ethernet tap
@ -178,9 +175,9 @@ public:
throw();
private:
void _handleRemotePacketFragment(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data);
void _handleRemotePacketHead(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data);
void _handleBeacon(const SharedPtr<Socket> &fromSock,const InetAddress &fromAddr,const Buffer<4096> &data);
void _handleRemotePacketFragment(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data);
void _handleRemotePacketHead(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data);
void _handleBeacon(const InetAddress &fromAddr,int linkDesperation,const Buffer<4096> &data);
Address _sendWhoisRequest(
const Address &addr,

View File

@ -32,8 +32,6 @@
#include "CMWC4096.hpp"
#include "Dictionary.hpp"
#define ZT_PEER_WRITE_BUF_SIZE 131072
namespace ZeroTier {
Topology::Topology(const RuntimeEnvironment *renv) :

View File

@ -44,8 +44,6 @@
#include "Mutex.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "Packet.hpp"
#include "Logger.hpp"
#include "Dictionary.hpp"
#include "ExternalSurface.hpp"