|
@@ -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);
|
|
|
|
-#else
|
|
|
|
|
|
+ { // hack copied from StackOverflow, behaves a bit like pipe() on *nix systems
|
|
|
|
+ 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);
|
|
|
|
- else // if ... below
|
|
|
|
|
|
+ this->close((WireSocket *)&(*s),true);
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ for(typename std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
|
|
|
|
+ if (&(*s) == sock) {
|
|
|
|
+ _socks.erase(s);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (oldSock >= _nfds) {
|
|
long nfds = (long)_whackSendSocket;
|
|
long nfds = (long)_whackSendSocket;
|
|
if ((long)_whackReceiveSocket > nfds)
|
|
if ((long)_whackReceiveSocket > nfds)
|
|
nfds = (long)_whackReceiveSocket;
|
|
nfds = (long)_whackReceiveSocket;
|
|
- 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 ((long)s->sock > nfds)
|
|
if ((long)s->sock > nfds)
|
|
nfds = (long)s->sock;
|
|
nfds = (long)s->sock;
|
|
}
|
|
}
|
|
_nfds = nfds;
|
|
_nfds = nfds;
|
|
}
|
|
}
|
|
-
|
|
|
|
- for(std::list<WireSocketImpl>::iterator s(_socks.begin());s!=_socks.end();++s) {
|
|
|
|
- if (&(*s) == sock) {
|
|
|
|
- _socks.erase(s);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
-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
|