From e8b613e625d18a03d14073e4634cdfb64e120d38 Mon Sep 17 00:00:00 2001
From: Adam Ierymenko <adam.ierymenko@zerotier.com>
Date: Fri, 28 Mar 2014 12:26:33 -0700
Subject: [PATCH] TCP connections work on Windows now.

---
 node/SocketManager.cpp | 18 +++++++++++-------
 node/TcpSocket.cpp     | 11 +++++++++++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/node/SocketManager.cpp b/node/SocketManager.cpp
index 8bbf94d2e..41facdc04 100644
--- a/node/SocketManager.cpp
+++ b/node/SocketManager.cpp
@@ -364,10 +364,6 @@ bool SocketManager::send(const InetAddress &to,bool tcp,const void *msg,unsigned
 		SOCKET s = ::socket(to.isV4() ? AF_INET : AF_INET6,SOCK_STREAM,0);
 		if (s == INVALID_SOCKET)
 			return false;
-		if (s >= FD_SETSIZE) {
-			::closesocket(s);
-			return false;
-		}
 		{ u_long iMode=1; ioctlsocket(s,FIONBIO,&iMode); }
 #ifdef ZT_TCP_NODELAY
 		{ BOOL f = TRUE; setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&f,sizeof(f)); }
@@ -387,8 +383,12 @@ bool SocketManager::send(const InetAddress &to,bool tcp,const void *msg,unsigned
 #endif
 
 		bool connecting = false;
-		if (connect(s,to.saddr(),to.saddrLen())) {
+		if (::connect(s,to.saddr(),to.saddrLen())) {
+#ifdef __WINDOWS__
+			if (WSAGetLastError() != WSAEWOULDBLOCK) {
+#else
 			if (errno != EINPROGRESS) {
+#endif
 				CLOSE_SOCKET(s);
 				return false;
 			} else connecting = true;
@@ -480,8 +480,8 @@ void SocketManager::poll(unsigned long timeout)
 		if (sockfd != INVALID_SOCKET) {
 #else
 		if (sockfd > 0) {
-#endif
 			if (sockfd < FD_SETSIZE) {
+#endif
 				InetAddress fromia((const struct sockaddr *)&from);
 				Mutex::Lock _l2(_tcpSockets_m);
 				try {
@@ -505,9 +505,11 @@ void SocketManager::poll(unsigned long timeout)
 				} catch ( ... ) {
 					CLOSE_SOCKET(sockfd);
 				}
+#ifndef __WINDOWS__
 			} else {
 				CLOSE_SOCKET(sockfd);
 			}
+#endif
 		}
 	}
 	if ((_tcpV6ListenSocket != INVALID_SOCKET)&&(FD_ISSET(_tcpV6ListenSocket,&rfds))) {
@@ -518,8 +520,8 @@ void SocketManager::poll(unsigned long timeout)
 		if (sockfd != INVALID_SOCKET) {
 #else
 		if (sockfd > 0) {
-#endif
 			if (sockfd < FD_SETSIZE) {
+#endif
 				InetAddress fromia((const struct sockaddr *)&from);
 				Mutex::Lock _l2(_tcpSockets_m);
 				try {
@@ -543,9 +545,11 @@ void SocketManager::poll(unsigned long timeout)
 				} catch ( ... ) {
 					CLOSE_SOCKET(sockfd);
 				}
+#ifndef __WINDOWS__
 			} else {
 				CLOSE_SOCKET(sockfd);
 			}
+#endif
 		}
 	}
 
diff --git a/node/TcpSocket.cpp b/node/TcpSocket.cpp
index 5d475c936..fd8e9a949 100644
--- a/node/TcpSocket.cpp
+++ b/node/TcpSocket.cpp
@@ -164,6 +164,16 @@ bool TcpSocket::notifyAvailableForWrite(const SharedPtr<Socket> &self,SocketMana
 
 	if (_outptr) {
 		int n = (int)::send(_sock,(const char *)_outbuf,_outptr,0);
+#ifdef __WINDOWS__
+		if (n == SOCKET_ERROR) {
+			switch(WSAGetLastError()) {
+				case WSAEINTR:
+				case WSAEWOULDBLOCK:
+					break;
+				default:
+					return false;
+			}
+#else
 		if (n <= 0) {
 			switch(errno) {
 #ifdef EAGAIN
@@ -179,6 +189,7 @@ bool TcpSocket::notifyAvailableForWrite(const SharedPtr<Socket> &self,SocketMana
 				default:
 					return false;
 			}
+#endif
 		} else memmove(_outbuf,_outbuf + (unsigned int)n,_outptr -= (unsigned int)n);
 	}