ZeroTierOne for Windows binary project, builds and runs and mostly works but still some issues with tap.
This commit is contained in:
parent
9f16707b0b
commit
487eb17ec0
25 changed files with 832 additions and 59 deletions
|
@ -284,7 +284,7 @@ public:
|
|||
inline void append(const std::string &s)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
append(s.data(),s.length());
|
||||
append(s.data(),(unsigned int)s.length());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,9 +114,9 @@ public:
|
|||
std::string s;
|
||||
|
||||
for(const_iterator kv(begin());kv!=end();++kv) {
|
||||
_appendEsc(kv->first.data(),kv->first.length(),s);
|
||||
_appendEsc(kv->first.data(),(unsigned int)kv->first.length(),s);
|
||||
s.push_back('=');
|
||||
_appendEsc(kv->second.data(),kv->second.length(),s);
|
||||
_appendEsc(kv->second.data(),(unsigned int)kv->second.length(),s);
|
||||
s.append(ZT_EOL_S);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
EllipticCurveKey(const std::string &data)
|
||||
throw(std::out_of_range)
|
||||
{
|
||||
set(data.data(),data.length());
|
||||
set(data.data(),(unsigned int)data.length());
|
||||
}
|
||||
|
||||
inline void set(const void *data,unsigned int len)
|
||||
|
|
|
@ -153,7 +153,7 @@ bool EllipticCurveKeyPair::generate()
|
|||
}
|
||||
|
||||
memset(_priv._key,0,sizeof(_priv._key));
|
||||
len = BN_num_bytes(EC_KEY_get0_private_key(key));
|
||||
len = (int)BN_num_bytes(EC_KEY_get0_private_key(key));
|
||||
if ((len > ZT_EC_PRIME_BYTES)||(len < 0)) {
|
||||
EC_KEY_free(key);
|
||||
return false;
|
||||
|
@ -162,7 +162,7 @@ bool EllipticCurveKeyPair::generate()
|
|||
_priv._bytes = ZT_EC_PRIME_BYTES;
|
||||
|
||||
memset(_pub._key,0,sizeof(_pub._key));
|
||||
len = EC_POINT_point2oct(ZT_EC_GROUP.g,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,_pub._key,sizeof(_pub._key),0);
|
||||
len = (int)EC_POINT_point2oct(ZT_EC_GROUP.g,EC_KEY_get0_public_key(key),POINT_CONVERSION_COMPRESSED,_pub._key,sizeof(_pub._key),0);
|
||||
if (len != ZT_EC_PUBLIC_KEY_BYTES) {
|
||||
EC_KEY_free(key);
|
||||
return false;
|
||||
|
|
|
@ -693,11 +693,37 @@ void EthernetTap::threadMain()
|
|||
#include <tchar.h>
|
||||
#include <winreg.h>
|
||||
#include <wchar.h>
|
||||
#include <nldef.h>
|
||||
#include <netioapi.h>
|
||||
|
||||
#include "..\vsprojects\TapDriver\tap-windows.h"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
// Helper function to get an adapter's LUID and index from its GUID. The LUID is
|
||||
// constant but the index can change, so go ahead and just look them both up by
|
||||
// the GUID which is constant. (The GUID is the instance ID in the registry.)
|
||||
static inline std::pair<NET_LUID,NET_IFINDEX> _findAdapterByGuid(const GUID &guid)
|
||||
throw(std::runtime_error)
|
||||
{
|
||||
MIB_IF_TABLE2 *ift = (MIB_IF_TABLE2 *)0;
|
||||
|
||||
if (GetIfTable2Ex(MibIfTableRaw,&ift) != NO_ERROR)
|
||||
throw std::runtime_error("GetIfTable2Ex() failed");
|
||||
|
||||
for(ULONG i=0;i<ift->NumEntries;++i) {
|
||||
if (ift->Table[i].InterfaceGuid == guid) {
|
||||
std::pair<NET_LUID,NET_IFINDEX> tmp(ift->Table[i].InterfaceLuid,ift->Table[i].InterfaceIndex);
|
||||
FreeMibTable(&ift);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
FreeMibTable(&ift);
|
||||
|
||||
throw std::runtime_error("interface not found");
|
||||
}
|
||||
|
||||
static Mutex _systemTapInitLock;
|
||||
|
||||
EthernetTap::EthernetTap(
|
||||
|
@ -721,6 +747,9 @@ EthernetTap::EthernetTap(
|
|||
char subkeyClass[4096];
|
||||
char data[4096];
|
||||
|
||||
if (mtu > ZT_IF_MTU)
|
||||
throw std::runtime_error("MTU too large for Windows tap");
|
||||
|
||||
Mutex::Lock _l(_systemTapInitLock); // only init one tap at a time, process-wide
|
||||
|
||||
HKEY nwAdapters;
|
||||
|
@ -813,7 +842,7 @@ EthernetTap::EthernetTap(
|
|||
dataLen = sizeof(data);
|
||||
if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
|
||||
if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
|
||||
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,strlen(tag)+1);
|
||||
RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
|
||||
_myDeviceInstanceId.assign(data,dataLen);
|
||||
mySubkeyName = subkeyName;
|
||||
subkeyIndex = -1; // break outer loop
|
||||
|
@ -842,8 +871,27 @@ EthernetTap::EthernetTap(
|
|||
if (_myDeviceInstanceId.length() == 0)
|
||||
throw std::runtime_error("unable to create new tap adapter");
|
||||
|
||||
{
|
||||
char nobraces[128];
|
||||
const char *nbtmp1 = _myDeviceInstanceId.c_str();
|
||||
char *nbtmp2 = nobraces;
|
||||
while (*nbtmp1) {
|
||||
if ((*nbtmp1 != '{')&&(*nbtmp1 != '}'))
|
||||
*nbtmp2++ = *nbtmp1;
|
||||
++nbtmp1;
|
||||
}
|
||||
*nbtmp2 = (char)0;
|
||||
if (UuidFromStringA((RPC_CSTR)nobraces,&_deviceGuid) != RPC_S_OK)
|
||||
throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
wchar_t tapPath[4096];
|
||||
swprintf_s(tapPath,L"\\\\.\\Global\\%S.tap",_myDeviceInstanceId.c_str());
|
||||
#else
|
||||
char tapPath[4096];
|
||||
sprintf_s(tapPath,"\\\\.\\Global\\%s.tap",_myDeviceInstanceId.c_str());
|
||||
#endif
|
||||
_tap = CreateFile(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
|
||||
if (_tap == INVALID_HANDLE_VALUE)
|
||||
throw std::runtime_error("unable to open tap in \\\\.\\Global\\ namespace");
|
||||
|
@ -878,14 +926,104 @@ void EthernetTap::whack()
|
|||
|
||||
bool EthernetTap::addIP(const InetAddress &ip)
|
||||
{
|
||||
Mutex::Lock _l(_ips_m);
|
||||
|
||||
if (_ips.count(ip))
|
||||
return true;
|
||||
|
||||
if (!ip.port())
|
||||
return false;
|
||||
|
||||
try {
|
||||
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
||||
MIB_UNICASTIPADDRESS_ROW ipr;
|
||||
|
||||
InitializeUnicastIpAddressEntry(&ipr);
|
||||
if (ip.isV4()) {
|
||||
ipr.Address.Ipv4.sin_family = AF_INET;
|
||||
ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
|
||||
ipr.OnLinkPrefixLength = ip.port();
|
||||
} else if (ip.isV6()) {
|
||||
} else return false;
|
||||
|
||||
ipr.PrefixOrigin = IpPrefixOriginManual;
|
||||
ipr.SuffixOrigin = IpSuffixOriginManual;
|
||||
ipr.ValidLifetime = 0xffffffff;
|
||||
ipr.PreferredLifetime = 0xffffffff;
|
||||
|
||||
ipr.InterfaceLuid = ifidx.first;
|
||||
ipr.InterfaceIndex = ifidx.second;
|
||||
|
||||
if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
|
||||
_ips.insert(ip);
|
||||
return true;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EthernetTap::removeIP(const InetAddress &ip)
|
||||
{
|
||||
try {
|
||||
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
|
||||
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
||||
|
||||
if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
|
||||
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
||||
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
||||
InetAddress addr;
|
||||
switch(ipt->Table[i].Address.si_family) {
|
||||
case AF_INET:
|
||||
addr.set(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
|
||||
break;
|
||||
}
|
||||
if (addr == ip) {
|
||||
DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
|
||||
FreeMibTable(&ipt);
|
||||
Mutex::Lock _l(_ips_m);
|
||||
_ips.erase(ip);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeMibTable(&ipt);
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<InetAddress> EthernetTap::allIps() const
|
||||
{
|
||||
std::set<InetAddress> addrs;
|
||||
|
||||
try {
|
||||
MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
|
||||
std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
|
||||
|
||||
if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
|
||||
for(DWORD i=0;i<ipt->NumEntries;++i) {
|
||||
if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
|
||||
switch(ipt->Table[i].Address.si_family) {
|
||||
case AF_INET:
|
||||
addrs.insert(InetAddress(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength));
|
||||
break;
|
||||
case AF_INET6:
|
||||
addrs.insert(InetAddress(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeMibTable(&ipt);
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
|
||||
return addrs;
|
||||
}
|
||||
|
||||
void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||
{
|
||||
if (len > (ZT_IF_MTU))
|
||||
|
@ -939,8 +1077,8 @@ void EthernetTap::threadMain()
|
|||
MAC from(_tapReadBuf + 6);
|
||||
unsigned int etherType = Utils::ntoh(*((const uint16_t *)(_tapReadBuf + 12)));
|
||||
Buffer<4096> tmp(_tapReadBuf + 14,bytesRead - 14);
|
||||
printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
|
||||
//_handler(_arg,from,to,etherType,tmp);
|
||||
//printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
|
||||
_handler(_arg,from,to,etherType,tmp);
|
||||
}
|
||||
}
|
||||
ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
|
||||
|
|
|
@ -134,6 +134,11 @@ public:
|
|||
return _ips;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set of IP addresses / netmasks included any we did not assign, link-local, etc.
|
||||
*/
|
||||
std::set<InetAddress> allIps() const;
|
||||
|
||||
/**
|
||||
* Set this tap's IP addresses to exactly this set of IPs
|
||||
*
|
||||
|
@ -213,6 +218,7 @@ private:
|
|||
OVERLAPPED _tapOvlRead,_tapOvlWrite;
|
||||
char _tapReadBuf[ZT_IF_MTU + 32];
|
||||
HANDLE _injectSemaphore;
|
||||
GUID _deviceGuid;
|
||||
std::string _myDeviceInstanceId;
|
||||
std::queue< std::pair< Array<char,ZT_IF_MTU + 32>,unsigned int > > _injectPending;
|
||||
Mutex _injectPending_m;
|
||||
|
|
|
@ -298,7 +298,7 @@ public:
|
|||
throw()
|
||||
{
|
||||
Mutex::Lock _l(_chain_m);
|
||||
return _chain.size();
|
||||
return (unsigned int)_chain.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -88,7 +88,7 @@ bool Identity::locallyValidate(bool doAddressDerivationCheck) const
|
|||
SHA256_Update(&sha,&zero,1);
|
||||
SHA256_Final(dig,&sha);
|
||||
|
||||
return ((EllipticCurveKeyPair::verify(dig,_publicKey,_signature.data(),_signature.length()))&&((!doAddressDerivationCheck)||(deriveAddress(_publicKey.data(),_publicKey.size()) == _address)));
|
||||
return ((EllipticCurveKeyPair::verify(dig,_publicKey,_signature.data(),(unsigned int)_signature.length()))&&((!doAddressDerivationCheck)||(deriveAddress(_publicKey.data(),_publicKey.size()) == _address)));
|
||||
}
|
||||
|
||||
std::string Identity::toString(bool includePrivate) const
|
||||
|
@ -98,7 +98,7 @@ std::string Identity::toString(bool includePrivate) const
|
|||
r.append(":1:"); // 1 == IDENTITY_TYPE_NIST_P_521
|
||||
r.append(Utils::base64Encode(_publicKey.data(),_publicKey.size()));
|
||||
r.push_back(':');
|
||||
r.append(Utils::base64Encode(_signature.data(),_signature.length()));
|
||||
r.append(Utils::base64Encode(_signature.data(),(unsigned int)_signature.length()));
|
||||
if ((includePrivate)&&(_keyPair)) {
|
||||
r.push_back(':');
|
||||
r.append(Utils::base64Encode(_keyPair->priv().data(),_keyPair->priv().size()));
|
||||
|
@ -127,7 +127,7 @@ bool Identity::fromString(const char *str)
|
|||
b = Utils::base64Decode(fields[2]);
|
||||
if ((!b.length())||(b.length() > ZT_EC_MAX_BYTES))
|
||||
return false;
|
||||
_publicKey.set(b.data(),b.length());
|
||||
_publicKey.set(b.data(),(unsigned int)b.length());
|
||||
|
||||
_signature = Utils::base64Decode(fields[3]);
|
||||
if (!_signature.length())
|
||||
|
@ -137,7 +137,7 @@ bool Identity::fromString(const char *str)
|
|||
b = Utils::base64Decode(fields[4]);
|
||||
if ((!b.length())||(b.length() > ZT_EC_MAX_BYTES))
|
||||
return false;
|
||||
_keyPair = new EllipticCurveKeyPair(_publicKey,EllipticCurveKey(b.data(),b.length()));
|
||||
_keyPair = new EllipticCurveKeyPair(_publicKey,EllipticCurveKey(b.data(),(unsigned int)b.length()));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -107,7 +107,12 @@ void Logger::trace(const char *module,unsigned int line,const char *fmt,...)
|
|||
|
||||
if (_log) {
|
||||
time_t now = time(0);
|
||||
#ifdef __WINDOWS__
|
||||
ctime_s(tmp,sizeof(tmp),&now);
|
||||
char *nowstr = tmp;
|
||||
#else
|
||||
char *nowstr = ctime_r(&now,tmp);
|
||||
#endif
|
||||
for(char *c=nowstr;*c;++c) {
|
||||
if (*c == '\n')
|
||||
*c = '\0';
|
||||
|
|
|
@ -258,7 +258,7 @@ Node::Node(const char *hp)
|
|||
{
|
||||
_NodeImpl *impl = (_NodeImpl *)_impl;
|
||||
|
||||
if (hp)
|
||||
if ((hp)&&(strlen(hp) > 0))
|
||||
impl->renv.homePath = hp;
|
||||
else impl->renv.homePath = ZT_DEFAULTS.defaultHomePath;
|
||||
impl->reasonForTermination = Node::NODE_RUNNING;
|
||||
|
@ -382,10 +382,10 @@ Node::ReasonForTermination Node::run()
|
|||
_r->sysEnv = new SysEnv(_r);
|
||||
try {
|
||||
_r->nc = new NodeConfig(_r,configAuthToken.c_str());
|
||||
} catch ( ... ) {
|
||||
} catch (std::exception &exc) {
|
||||
// An exception here currently means that another instance of ZeroTier
|
||||
// One is running.
|
||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound");
|
||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,(std::string("another instance of ZeroTier One appears to be running, or local control UDP port cannot be bound: ") + exc.what()).c_str());
|
||||
}
|
||||
|
||||
// TODO: make configurable
|
||||
|
@ -618,3 +618,27 @@ const unsigned char EMBEDDED_VERSION_STAMP[20] = {
|
|||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
extern "C" {
|
||||
|
||||
ZeroTier::Node *zeroTierCreateNode(const char *hp)
|
||||
{
|
||||
return new ZeroTier::Node(hp);
|
||||
}
|
||||
|
||||
void zeroTierDeleteNode(ZeroTier::Node *n)
|
||||
{
|
||||
delete n;
|
||||
}
|
||||
|
||||
ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,void (*resultHandler)(void *,unsigned long,const char *),void *arg)
|
||||
{
|
||||
return new ZeroTier::Node::LocalClient(authToken,resultHandler,arg);
|
||||
}
|
||||
|
||||
void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc)
|
||||
{
|
||||
delete lc;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -163,5 +163,17 @@ extern const unsigned char EMBEDDED_VERSION_STAMP[20];
|
|||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
||||
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);
|
||||
void zeroTierDeleteNode(ZeroTier::Node *n);
|
||||
|
||||
ZeroTier::Node::LocalClient *zeroTierCreateLocalClient(const char *authToken,void (*resultHandler)(void *,unsigned long,const char *),void *arg);
|
||||
void zeroTierDeleteLocalClient(ZeroTier::Node::LocalClient *lc);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,7 +142,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
|
|||
outpTmpl.append((uint16_t)data.size());
|
||||
outpTmpl.append((uint16_t)signature.length());
|
||||
outpTmpl.append(data.data(),data.size());
|
||||
outpTmpl.append(signature.data(),signature.length());
|
||||
outpTmpl.append(signature.data(),(unsigned int)signature.length());
|
||||
outpTmpl.compress();
|
||||
send(outpTmpl,true);
|
||||
for(unsigned int i=1;i<np;++i) {
|
||||
|
|
|
@ -232,7 +232,7 @@ void Topology::threadMain()
|
|||
}
|
||||
_PeerDeepVerifyJob job(_peerDeepVerifyJobs.front());
|
||||
_peerDeepVerifyJobs.pop_front();
|
||||
unsigned long queueRemaining = _peerDeepVerifyJobs.size();
|
||||
unsigned long queueRemaining = (unsigned long)_peerDeepVerifyJobs.size();
|
||||
_peerDeepVerifyJobs_m.unlock();
|
||||
|
||||
switch(job.type) {
|
||||
|
|
|
@ -63,7 +63,11 @@ UdpSocket::UdpSocket(
|
|||
_packetHandler(packetHandler),
|
||||
_arg(arg),
|
||||
_localPort(localPort),
|
||||
#ifdef __WINDOWS__
|
||||
_sock(INVALID_SOCKET),
|
||||
#else
|
||||
_sock(0),
|
||||
#endif
|
||||
_v6(ipv6)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -77,8 +81,13 @@ UdpSocket::UdpSocket(
|
|||
|
||||
if (ipv6) {
|
||||
_sock = socket(AF_INET6,SOCK_DGRAM,0);
|
||||
#ifdef __WINDOWS__
|
||||
if (_sock == INVALID_SOCKET)
|
||||
throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
|
||||
#else
|
||||
if (_sock <= 0)
|
||||
throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
yes = TRUE; setsockopt(_sock,IPPROTO_IPV6,IPV6_V6ONLY,(const char *)&yes,sizeof(yes));
|
||||
|
@ -115,8 +124,13 @@ UdpSocket::UdpSocket(
|
|||
}
|
||||
} else {
|
||||
_sock = socket(AF_INET,SOCK_DGRAM,0);
|
||||
#ifdef __WINDOWS__
|
||||
if (_sock == INVALID_SOCKET)
|
||||
throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
|
||||
#else
|
||||
if (_sock <= 0)
|
||||
throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
no = FALSE; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(const char *)&no,sizeof(no));
|
||||
|
@ -154,16 +168,19 @@ UdpSocket::UdpSocket(
|
|||
UdpSocket::~UdpSocket()
|
||||
{
|
||||
int s = _sock;
|
||||
_sock = 0;
|
||||
if (s > 0) {
|
||||
#ifdef __WINDOWS__
|
||||
_sock = INVALID_SOCKET;
|
||||
if (s != INVALID_SOCKET) {
|
||||
::shutdown(s,SD_BOTH);
|
||||
::closesocket(s);
|
||||
}
|
||||
#else
|
||||
_sock = 0;
|
||||
if (s > 0) {
|
||||
::shutdown(s,SHUT_RDWR);
|
||||
::close(s);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Thread::join(_thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include "InetAddress.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
@ -100,7 +104,11 @@ private:
|
|||
void (*_packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int);
|
||||
void *_arg;
|
||||
int _localPort;
|
||||
#ifdef __WINDOWS__
|
||||
volatile SOCKET _sock;
|
||||
#else
|
||||
volatile int _sock;
|
||||
#endif
|
||||
bool _v6;
|
||||
Mutex _sendLock;
|
||||
};
|
||||
|
|
|
@ -501,7 +501,7 @@ uint64_t Utils::fromRfc1123(const char *tstr)
|
|||
struct tm t;
|
||||
char wdays[128],mons[128];
|
||||
|
||||
int l = strlen(tstr);
|
||||
int l = (int)strlen(tstr);
|
||||
if ((l < 29)||(l > 64))
|
||||
return 0;
|
||||
int assigned = sscanf(tstr,"%3s, %02d %3s %4d %02d:%02d:%02d GMT",wdays,&t.tm_mday,mons,&t.tm_year,&t.tm_hour,&t.tm_min,&t.tm_sec);
|
||||
|
@ -620,7 +620,7 @@ std::vector<std::string> Utils::split(const char *s,const char *const sep,const
|
|||
|
||||
std::string Utils::trim(const std::string &s)
|
||||
{
|
||||
unsigned long end = s.length();
|
||||
unsigned long end = (unsigned long)s.length();
|
||||
while (end) {
|
||||
char c = s[end - 1];
|
||||
if ((c == ' ')||(c == '\r')||(c == '\n')||(!c)||(c == '\t'))
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
* @return Hexadecimal string
|
||||
*/
|
||||
static std::string hex(const void *data,unsigned int len);
|
||||
static inline std::string hex(const std::string &data) { return hex(data.data(),data.length()); }
|
||||
static inline std::string hex(const std::string &data) { return hex(data.data(),(unsigned int)data.length()); }
|
||||
|
||||
/**
|
||||
* @param hex Hexadecimal ASCII code (non-hex chars are ignored)
|
||||
|
@ -413,7 +413,7 @@ public:
|
|||
*/
|
||||
static inline bool writeFile(const char *path,const std::string &s)
|
||||
{
|
||||
return writeFile(path,s.data(),s.length());
|
||||
return writeFile(path,s.data(),(unsigned int)s.length());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -422,7 +422,7 @@ public:
|
|||
* @return Base64-encoded string
|
||||
*/
|
||||
static std::string base64Encode(const void *data,unsigned int len);
|
||||
inline static std::string base64Encode(const std::string &data) { return base64Encode(data.data(),data.length()); }
|
||||
inline static std::string base64Encode(const std::string &data) { return base64Encode(data.data(),(unsigned int)data.length()); }
|
||||
|
||||
/**
|
||||
* @param data Base64-encoded string
|
||||
|
@ -430,7 +430,7 @@ public:
|
|||
* @return Decoded binary date
|
||||
*/
|
||||
static std::string base64Decode(const char *data,unsigned int len);
|
||||
inline static std::string base64Decode(const std::string &data) { return base64Decode(data.data(),data.length()); }
|
||||
inline static std::string base64Decode(const std::string &data) { return base64Decode(data.data(),(unsigned int)data.length()); }
|
||||
|
||||
/**
|
||||
* Split a string by delimiter, with optional escape and quote characters
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue