Build fixes.

This commit is contained in:
Adam Ierymenko 2015-03-30 13:21:35 -07:00
parent 4445bfc869
commit b6241f6cb1
2 changed files with 124 additions and 118 deletions

View file

@ -32,14 +32,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <list>
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#include <WinSock2.h> #include <WinSock2.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
#include <Windows.h> #include <Windows.h>
#else
#define ZT_WIRE_SOCKFD_TYPE SOCKET
#define ZT_WIRE_SOCKFD_NULL (INVALID_SOCKET)
#define ZT_WIRE_SOCKFD_VALID(s) ((s) != INVALID_SOCKET)
#define ZT_WIRE_CLOSE_SOCKET(s) ::closesocket(s)
#define ZT_WIRE_MAX_SOCKETS (FD_SETSIZE)
#define ZT_WIRE_SOCKADDR_STORAGE_TYPE struct sockaddr_storage
#else // not Windows
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/select.h> #include <sys/select.h>
@ -47,25 +60,15 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#endif
#include <list>
#if defined(_WIN32) || defined(_WIN64)
#define ZT_WIRE_SOCKFD_TYPE SOCKET
#define ZT_WIRE_SOCKFD_NULL (INVALID_SOCKET)
#define ZT_WIRE_SOCKFD_VALID(s) ((s) != INVALID_SOCKET)
#define ZT_WIRE_CLOSE_SOCKET(s) ::closesocket(s)
#define ZT_WIRE_MAX_SOCKETS (FD_SETSIZE)
#define ZT_WIRE_SOCKADDR_STORAGE_TYPE struct sockaddr_storage
#else
#define ZT_WIRE_SOCKFD_TYPE int #define ZT_WIRE_SOCKFD_TYPE int
#define ZT_WIRE_SOCKFD_NULL (-1) #define ZT_WIRE_SOCKFD_NULL (-1)
#define ZT_WIRE_SOCKFD_VALID(s) ((s) > -1) #define ZT_WIRE_SOCKFD_VALID(s) ((s) > -1)
#define ZT_WIRE_CLOSE_SOCKET(s) ::close(s) #define ZT_WIRE_CLOSE_SOCKET(s) ::close(s)
#define ZT_WIRE_MAX_SOCKETS (FD_SETSIZE) #define ZT_WIRE_MAX_SOCKETS (FD_SETSIZE)
#define ZT_WIRE_SOCKADDR_STORAGE_TYPE struct sockaddr_storage #define ZT_WIRE_SOCKADDR_STORAGE_TYPE struct sockaddr_storage
#endif
#endif // Windows or not
namespace ZeroTier { namespace ZeroTier {
@ -111,20 +114,57 @@ typedef const void * WireSocket;
* This isn't thread-safe with the exception of whack(), which is safe to * This isn't thread-safe with the exception of whack(), which is safe to
* call from another thread to abort poll(). * call from another thread to abort poll().
*/ */
template template <
<
typename ON_DATAGRAM_FUNCTION, typename ON_DATAGRAM_FUNCTION,
typename ON_TCP_CONNECT_FUNCTION, typename ON_TCP_CONNECT_FUNCTION,
typename ON_TCP_ACCEPT_FUNCTION, typename ON_TCP_ACCEPT_FUNCTION,
typename ON_TCP_CLOSE_FUNCTION, typename ON_TCP_CLOSE_FUNCTION,
typename ON_TCP_DATA_FUNCTION, typename ON_TCP_DATA_FUNCTION,
typename ON_TCP_WRITABLE_FUNCTION typename ON_TCP_WRITABLE_FUNCTION>
>
class Wire class Wire
{ {
private:
ON_DATAGRAM_FUNCTION _datagramHandler;
ON_TCP_CONNECT_FUNCTION _tcpConnectHandler;
ON_TCP_ACCEPT_FUNCTION _tcpAcceptHandler;
ON_TCP_CLOSE_FUNCTION _tcpCloseHandler;
ON_TCP_DATA_FUNCTION _tcpDataHandler;
ON_TCP_WRITABLE_FUNCTION _tcpWritableHandler;
enum WireSocketType
{
ZT_WIRE_SOCKET_TCP_OUT_PENDING = 0x00,
ZT_WIRE_SOCKET_TCP_OUT_CONNECTED = 0x01,
ZT_WIRE_SOCKET_TCP_IN = 0x02,
ZT_WIRE_SOCKET_TCP_LISTEN = 0x03,
ZT_WIRE_SOCKET_RAW = 0x04,
ZT_WIRE_SOCKET_UDP = 0x05
};
struct WireSocketImpl
{
WireSocketType type;
ZT_WIRE_SOCKFD_TYPE sock;
void *uptr; // user-settable pointer
ZT_WIRE_SOCKADDR_STORAGE_TYPE saddr; // remote for TCP_OUT and TCP_IN, local for TCP_LISTEN, RAW, and UDP
};
std::list<WireSocketImpl> _socks;
fd_set _readfds;
fd_set _writefds;
#if defined(_WIN32) || defined(_WIN64)
fd_set _exceptfds;
#endif
long _nfds;
ZT_WIRE_SOCKFD_TYPE _whackReceiveSocket;
ZT_WIRE_SOCKFD_TYPE _whackSendSocket;
bool _noDelay;
public: public:
/** /**
* @param dgHandler Function or function object to handle UDP or RAW datagrams * @param datagramHandler Function or function object to handle UDP or RAW datagrams
* @param tcpConnectHandler Handler for outgoing TCP connection attempts (success or failure) * @param tcpConnectHandler Handler for outgoing TCP connection attempts (success or failure)
* @param tcpAcceptHandler Handler for incoming TCP connections * @param tcpAcceptHandler Handler for incoming TCP connections
* @param tcpDataHandler Handler for incoming TCP data * @param tcpDataHandler Handler for incoming TCP data
@ -132,14 +172,14 @@ public:
* @param noDelay If true, disable Nagle algorithm on new TCP sockets * @param noDelay If true, disable Nagle algorithm on new TCP sockets
*/ */
Wire( Wire(
ON_DATAGRAM_FUNCTION dgHandler, ON_DATAGRAM_FUNCTION datagramHandler,
ON_TCP_CONNECT_FUNCTION tcpConnectHandler, ON_TCP_CONNECT_FUNCTION tcpConnectHandler,
ON_TCP_ACCEPT_FUNCTION tcpAcceptHandler, ON_TCP_ACCEPT_FUNCTION tcpAcceptHandler,
ON_TCP_CLOSE_FUNCTION tcpCloseHandler, ON_TCP_CLOSE_FUNCTION tcpCloseHandler,
ON_TCP_DATA_FUNCTION tcpDataHandler, ON_TCP_DATA_FUNCTION tcpDataHandler,
ON_TCP_WRITABLE_FUNCTION tcpWritableHandler, ON_TCP_WRITABLE_FUNCTION tcpWritableHandler,
bool noDelay) : bool noDelay) :
_dgHandler(dgHandler), _datagramHandler(datagramHandler),
_tcpConnectHandler(tcpConnectHandler), _tcpConnectHandler(tcpConnectHandler),
_tcpAcceptHandler(tcpAcceptHandler), _tcpAcceptHandler(tcpAcceptHandler),
_tcpCloseHandler(tcpCloseHandler), _tcpCloseHandler(tcpCloseHandler),
@ -148,16 +188,40 @@ public:
{ {
FD_ZERO(&_readfds); FD_ZERO(&_readfds);
FD_ZERO(&_writefds); FD_ZERO(&_writefds);
FD_ZERO(&_exceptfds);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
FD_ZERO(&_exceptfds);
SOCKET pipes[2]; SOCKET pipes[2];
this->_winPipeHack(pipes); { // hack copied from StackOverflow, behaves a bit like pipe() on *nix systems
#else struct sockaddr_in inaddr;
struct sockaddr addr;
SOCKET lst=::socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (lst == INVALID_SOCKET)
throw std::runtime_error("unable to create pipes for select() abort");
memset(&inaddr, 0, sizeof(inaddr));
memset(&addr, 0, sizeof(addr));
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
inaddr.sin_port = 0;
int yes=1;
setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr));
listen(lst,1);
int len=sizeof(inaddr);
getsockname(lst, &addr,&len);
pipes[0]=::socket(AF_INET, SOCK_STREAM,0);
if (pipes[0] == INVALID_SOCKET)
throw std::runtime_error("unable to create pipes for select() abort");
connect(pipes[0],&addr,len);
pipes[1]=accept(lst,0,0);
closesocket(lst);
}
#else // not Windows
int pipes[2]; int pipes[2];
if (::pipe(pipes)) if (::pipe(pipes))
throw std::runtime_error("unable to create pipes for select() abort"); throw std::runtime_error("unable to create pipes for select() abort");
#endif #endif // Windows or not
_nfds = (pipes[0] > pipes[1]) ? (long)pipes[0] : (long)pipes[1]; _nfds = (pipes[0] > pipes[1]) ? (long)pipes[0] : (long)pipes[1];
_whackReceiveSocket = pipes[0]; _whackReceiveSocket = pipes[0];
@ -336,7 +400,7 @@ public:
int f; int f;
f = 1; ::setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&f,sizeof(f)); f = 1; ::setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&f,sizeof(f));
f = 1; ::setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(void *)&f,sizeof(f)); f = 1; ::setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(void *)&f,sizeof(f));
f = (_noDelay ? 1 : 0); setsockopt(newSock,IPPROTO_TCP,TCP_NODELAY,(char *)&f,sizeof(f)); f = (_noDelay ? 1 : 0); setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&f,sizeof(f));
fcntl(s,F_SETFL,O_NONBLOCK); fcntl(s,F_SETFL,O_NONBLOCK);
} }
#endif #endif
@ -395,7 +459,7 @@ public:
if (_socks.size() >= ZT_WIRE_MAX_SOCKETS) if (_socks.size() >= ZT_WIRE_MAX_SOCKETS)
return (WireSocket *)0; return (WireSocket *)0;
ZT_WIRE_SOCKFD_TYPE s = ::socket(localAddress->sa_family,SOCK_STREAM,0); ZT_WIRE_SOCKFD_TYPE s = ::socket(remoteAddress->sa_family,SOCK_STREAM,0);
if (!ZT_WIRE_SOCKFD_VALID(s)) if (!ZT_WIRE_SOCKFD_VALID(s))
return (WireSocket *)0; return (WireSocket *)0;
@ -413,13 +477,13 @@ public:
int f; int f;
f = 1; ::setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&f,sizeof(f)); f = 1; ::setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&f,sizeof(f));
f = 1; ::setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(void *)&f,sizeof(f)); f = 1; ::setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(void *)&f,sizeof(f));
f = (_noDelay ? 1 : 0); setsockopt(newSock,IPPROTO_TCP,TCP_NODELAY,(char *)&f,sizeof(f)); f = (_noDelay ? 1 : 0); setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&f,sizeof(f));
fcntl(s,F_SETFL,O_NONBLOCK); fcntl(s,F_SETFL,O_NONBLOCK);
} }
#endif #endif
connected = true; connected = true;
if (::connect(s,localAddress,(localAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))) { if (::connect(s,remoteAddress,(remoteAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))) {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (WSAGetLastError() != WSAEWOULDBLOCK) { if (WSAGetLastError() != WSAEWOULDBLOCK) {
#else #else
@ -453,7 +517,7 @@ public:
sws.sock = s; sws.sock = s;
sws.uptr = uptr; sws.uptr = uptr;
memset(&(sws.saddr),0,sizeof(struct sockaddr_storage)); memset(&(sws.saddr),0,sizeof(struct sockaddr_storage));
memcpy(&(sws.saddr),localAddress,(localAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); memcpy(&(sws.saddr),remoteAddress,(remoteAddress->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
if ((callConnectHandlerOnInstantConnect)&&(connected)) { if ((callConnectHandlerOnInstantConnect)&&(connected)) {
try { try {
@ -560,7 +624,8 @@ public:
tv.tv_sec = (long)(timeout / 1000); tv.tv_sec = (long)(timeout / 1000);
tv.tv_usec = (long)((timeout % 1000) * 1000); tv.tv_usec = (long)((timeout % 1000) * 1000);
::select((int)_nfds + 1,&rfds,&wfds,&efds,(timeout > 0) ? &tv : (struct timeval *)0); if (::select((int)_nfds + 1,&rfds,&wfds,&efds,(timeout > 0) ? &tv : (struct timeval *)0) <= 0)
return;
if (FD_ISSET(_whackReceiveSocket,&rfds)) { if (FD_ISSET(_whackReceiveSocket,&rfds)) {
char tmp[16]; char tmp[16];
@ -571,7 +636,7 @@ public:
#endif #endif
} }
for(std::list<WireSocketImpl>::iterator s(_socks.begin()),nexts;s!=_socks.end();s=nexts) { for(typename std::list<WireSocketImpl>::iterator s(_socks.begin()),nexts;s!=_socks.end();s=nexts) {
nexts = s; ++nexts; // we can delete the linked list item, so traverse now nexts = s; ++nexts; // we can delete the linked list item, so traverse now
switch (s->type) { switch (s->type) {
@ -579,13 +644,13 @@ public:
case ZT_WIRE_SOCKET_TCP_OUT_PENDING: case ZT_WIRE_SOCKET_TCP_OUT_PENDING:
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (FD_ISSET(s->sock,&efds)) if (FD_ISSET(s->sock,&efds))
this->close((WireSocket *)&(_socks[i]),true); this->close((WireSocket *)&(*s),true);
else // if ... below else // ... if
#endif #endif
if (FD_ISSET(s->sock,&wfds)) { if (FD_ISSET(s->sock,&wfds)) {
socklen_t slen = sizeof(ss); socklen_t slen = sizeof(ss);
if (::getpeername(s->sock,(struct sockaddr *)&ss,&slen) != 0) { if (::getpeername(s->sock,(struct sockaddr *)&ss,&slen) != 0) {
this->close((WireSocket *)&(_socks[i]),true); this->close((WireSocket *)&(*s),true);
} else { } else {
s->type = ZT_WIRE_SOCKET_TCP_OUT_CONNECTED; s->type = ZT_WIRE_SOCKET_TCP_OUT_CONNECTED;
FD_SET(s->sock,&_readfds); FD_SET(s->sock,&_readfds);
@ -594,7 +659,7 @@ public:
FD_CLR(s->sock,&_exceptfds); FD_CLR(s->sock,&_exceptfds);
#endif #endif
try { try {
_tcpConnectHandler((WireSocket *)&(_socks[i]),&(s->uptr),true); _tcpConnectHandler((WireSocket *)&(*s),&(s->uptr),true);
} catch ( ... ) {} } catch ( ... ) {}
} }
} }
@ -605,16 +670,16 @@ public:
if (FD_ISSET(s->sock,&rfds)) { if (FD_ISSET(s->sock,&rfds)) {
long n = (long)::recv(s->sock,buf,sizeof(buf),0); long n = (long)::recv(s->sock,buf,sizeof(buf),0);
if (n <= 0) { if (n <= 0) {
this->close((WireSocket *)&(_socks[i]),true); this->close((WireSocket *)&(*s),true);
} else { } else {
try { try {
_tcpDataHandler((WireSocket *)&(_socks[i]),&(s->uptr),(void *)buf,(unsigned long)n); _tcpDataHandler((WireSocket *)&(*s),&(s->uptr),(void *)buf,(unsigned long)n);
} catch ( ... ) {} } catch ( ... ) {}
} }
} }
if ((FD_ISSET(s->sock,&wfds))&&(FD_ISSET(s->sock,&_writefds))) { if ((FD_ISSET(s->sock,&wfds))&&(FD_ISSET(s->sock,&_writefds))) {
try { try {
_tcpWritableHandler((WireSocket *)&(_socks[i]),&(s->uptr)); _tcpWritableHandler((WireSocket *)&(*s),&(s->uptr));
} catch ( ... ) {} } catch ( ... ) {}
} }
break; break;
@ -647,6 +712,7 @@ public:
try { try {
_tcpAcceptHandler((WireSocket *)&(*s),(WireSocket *)&(_socks.back()),&(s->uptr),&(sws.uptr),(const struct sockaddr *)&(sws.saddr)); _tcpAcceptHandler((WireSocket *)&(*s),(WireSocket *)&(_socks.back()),&(s->uptr),&(sws.uptr),(const struct sockaddr *)&(sws.saddr));
} catch ( ... ) {} } catch ( ... ) {}
}
} }
} }
break; break;
@ -658,7 +724,7 @@ public:
long n = (long)::recvfrom(s->sock,buf,sizeof(buf),0,(struct sockaddr *)&ss,&slen); long n = (long)::recvfrom(s->sock,buf,sizeof(buf),0,(struct sockaddr *)&ss,&slen);
if (n > 0) { if (n > 0) {
try { try {
_dgHandler((WireSocket *)&(_socks[i]),&(s->uptr),(const struct sockaddr *)&ss,(void *)buf,(unsigned long)n); _datagramHandler((WireSocket *)&(*s),&(s->uptr),(const struct sockaddr *)&ss,(void *)buf,(unsigned long)n);
} catch ( ... ) {} } catch ( ... ) {}
} }
} }
@ -705,92 +771,26 @@ public:
break; break;
} }
if ((long)sws.sock >= _nfds) { long oldSock = (long)sws.sock;
long nfds = (long)_whackSendSocket;
if ((long)_whackReceiveSocket > nfds)
nfds = (long)_whackReceiveSocket;
for(std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
if ((long)s->sock > nfds)
nfds = (long)s->sock;
}
_nfds = nfds;
}
for(std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) { for(typename std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
if (&(*s) == sock) { if (&(*s) == sock) {
_socks.erase(s); _socks.erase(s);
break; break;
} }
} }
if (oldSock >= _nfds) {
long nfds = (long)_whackSendSocket;
if ((long)_whackReceiveSocket > nfds)
nfds = (long)_whackReceiveSocket;
for(typename std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
if ((long)s->sock > nfds)
nfds = (long)s->sock;
}
_nfds = nfds;
}
} }
private:
#if defined(_WIN32) || defined(_WIN64)
// hack copied from StackOverflow, behaves a bit like pipe() on *nix systems
inline void _winPipeHack(SOCKET fds[2]) const
{
struct sockaddr_in inaddr;
struct sockaddr addr;
SOCKET lst=::socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (lst == INVALID_SOCKET)
throw std::runtime_error("unable to create pipes for select() abort");
memset(&inaddr, 0, sizeof(inaddr));
memset(&addr, 0, sizeof(addr));
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
inaddr.sin_port = 0;
int yes=1;
setsockopt(lst,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
bind(lst,(struct sockaddr *)&inaddr,sizeof(inaddr));
listen(lst,1);
int len=sizeof(inaddr);
getsockname(lst, &addr,&len);
fds[0]=::socket(AF_INET, SOCK_STREAM,0);
if (fds[0] == INVALID_SOCKET)
throw std::runtime_error("unable to create pipes for select() abort");
connect(fds[0],&addr,len);
fds[1]=accept(lst,0,0);
closesocket(lst);
}
#endif
enum WireSocketType
{
ZT_WIRE_SOCKET_TCP_OUT_PENDING = 0x00,
ZT_WIRE_SOCKET_TCP_OUT_CONNECTED = 0x01,
ZT_WIRE_SOCKET_TCP_IN = 0x02,
ZT_WIRE_SOCKET_TCP_LISTEN = 0x03,
ZT_WIRE_SOCKET_RAW = 0x04,
ZT_WIRE_SOCKET_UDP = 0x05
};
struct WireSocketImpl
{
WireSocketType type;
ZT_WIRE_SOCKFD_TYPE sock;
void *uptr; // user-settable pointer
ZT_WIRE_SOCKADDR_STORAGE_TYPE saddr; // remote for TCP_OUT and TCP_IN, local for TCP_LISTEN, RAW, and UDP
};
ON_DATAGRAM_FUNCTION _dgHandler;
ON_TCP_CONNECT_FUNCTION _tcpConnectHandler;
ON_TCP_ACCEPT_FUNCTION _tcpAcceptHandler;
ON_TCP_CLOSE_FUNCTION _tcpCloseHandler;
ON_TCP_DATA_FUNCTION _tcpDataHandler;
ON_TCP_WRITABLE_FUNCTION _tcpWritableHandler;
std::list<WireSocketImpl> _socks;
fd_set _readfds;
fd_set _writefds;
#if defined(_WIN32) || defined(_WIN64)
fd_set _exceptfds;
#endif
long _nfds;
ZT_WIRE_SOCKFD_TYPE _whackReceiveSocket;
ZT_WIRE_SOCKFD_TYPE _whackSendSocket;
bool _noDelay;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -25,6 +25,8 @@
* LLC. Start here: http://www.zerotier.com/ * LLC. Start here: http://www.zerotier.com/
*/ */
#define ZT_TEST_WIRE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -55,6 +57,10 @@
#include "node/Defaults.hpp" #include "node/Defaults.hpp"
#include "node/Node.hpp" #include "node/Node.hpp"
#ifdef ZT_TEST_WIRE
#include "osnet/Wire.hpp"
#endif
#ifdef ZT_ENABLE_NETCONF_MASTER #ifdef ZT_ENABLE_NETCONF_MASTER
#include "netconf/SqliteNetworkConfigMaster.hpp" #include "netconf/SqliteNetworkConfigMaster.hpp"
#endif // ZT_ENABLE_NETCONF_MASTER #endif // ZT_ENABLE_NETCONF_MASTER