Browse Source

Windows build work: condition, mutex, thread, udp socket...

Adam Ierymenko 12 years ago
parent
commit
36af3d92ec
5 changed files with 151 additions and 24 deletions
  1. 50 16
      node/Condition.hpp
  2. 3 5
      node/Mutex.hpp
  3. 51 1
      node/Thread.hpp
  4. 45 2
      node/UdpSocket.cpp
  5. 2 0
      node/UdpSocket.hpp

+ 50 - 16
node/Condition.hpp

@@ -28,9 +28,57 @@
 #ifndef _ZT_CONDITION_HPP
 #ifndef _ZT_CONDITION_HPP
 #define _ZT_CONDITION_HPP
 #define _ZT_CONDITION_HPP
 
 
+#include "Constants.hpp"
 #include "NonCopyable.hpp"
 #include "NonCopyable.hpp"
 
 
-#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
+#ifdef __WINDOWS__
+
+#include <Windows.h>
+#include <stdlib.h>
+
+#include "Utils.hpp"
+
+namespace ZeroTier {
+
+class Condition : NonCopyable
+{
+public:
+	Condition()
+		throw()
+	{
+		_sem = CreateSemaphore(NULL,0,1,NULL);
+	}
+
+	~Condition()
+	{
+		CloseHandle(_sem);
+	}
+
+	inline void wait() const
+		throw()
+	{
+		WaitForSingleObject(_sem,INFINITE);
+	}
+
+	inline void wait(unsigned long ms) const
+		throw()
+	{
+		WaitForSingleObject(_sem,(DWORD)ms);
+	}
+
+	inline void signal() const
+		throw()
+	{
+		ReleaseSemaphore(_sem,1,NULL);
+	}
+
+private:
+	HANDLE _sem;
+};
+
+} // namespace ZeroTier
+
+#else // !__WINDOWS__
 
 
 #include <time.h>
 #include <time.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -88,20 +136,6 @@ private:
 
 
 } // namespace ZeroTier
 } // namespace ZeroTier
 
 
-#endif // Apple / Linux
-
-#ifdef _WIN32
-
-#include <stdlib.h>
-#include <Windows.h>
-
-namespace ZeroTier {
-
-error need windoze;
-// On Windows this will probably be implemented via Semaphores
-
-} // namespace ZeroTier
-
-#endif // _WIN32
+#endif // !__WINDOWS__
 
 
 #endif
 #endif

+ 3 - 5
node/Mutex.hpp

@@ -28,9 +28,10 @@
 #ifndef _ZT_MUTEX_HPP
 #ifndef _ZT_MUTEX_HPP
 #define _ZT_MUTEX_HPP
 #define _ZT_MUTEX_HPP
 
 
+#include "Constants.hpp"
 #include "NonCopyable.hpp"
 #include "NonCopyable.hpp"
 
 
-#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
+#ifdef __UNIX_LIKE__
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <pthread.h>
@@ -112,7 +113,7 @@ private:
 
 
 #endif // Apple / Linux
 #endif // Apple / Linux
 
 
-#ifdef _WIN32
+#ifdef __WINDOWS__
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <Windows.h>
 #include <Windows.h>
@@ -157,9 +158,6 @@ public:
 		(const_cast <Mutex *> (this))->unlock();
 		(const_cast <Mutex *> (this))->unlock();
 	}
 	}
 
 
-	/**
-	 * Uses C++ contexts and constructor/destructor to lock/unlock automatically
-	 */
 	class Lock : NonCopyable
 	class Lock : NonCopyable
 	{
 	{
 	public:
 	public:

+ 51 - 1
node/Thread.hpp

@@ -35,7 +35,57 @@
 
 
 #ifdef __WINDOWS__
 #ifdef __WINDOWS__
 
 
-todo need windows;
+#include <Windows.h>
+#include <string.h>
+
+namespace ZeroTier {
+
+template<typename C>
+static DWORD WINAPI ___zt_threadMain(LPVOID lpParam)
+{
+	try {
+		((C *)lpParam)->threadMain();
+	} catch ( ... ) {}
+	return 0;
+}
+
+class Thread
+{
+public:
+	Thread()
+		throw()
+	{
+		_th = NULL;
+	}
+
+	template<typename C>
+	static inline Thread start(C *instance)
+		throw(std::runtime_error)
+	{
+		Thread t;
+		t._th = CreateThread(NULL,0,&___zt_threadMain<C>,(LPVOID)instance,0,&t._tid);
+		if (t._th == NULL)
+			throw std::runtime_error("CreateThread() failed");
+		return t;
+	}
+
+	static inline void join(const Thread &t)
+	{
+		if (t._th != NULL)
+			WaitForSingleObject(t._th,INFINITE);
+	}
+
+	static inline void sleep(unsigned long ms)
+	{
+		Sleep((DWORD)ms);
+	}
+
+private:
+	HANDLE _th;
+	DWORD _tid;
+};
+
+} // namespace ZeroTier
 
 
 #else
 #else
 
 

+ 45 - 2
node/UdpSocket.cpp

@@ -30,13 +30,16 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <errno.h>
-#include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/types.h>
-#include <arpa/inet.h>
+#include <sys/stat.h>
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 #include <Windows.h>
 #include <Windows.h>
+#include <WinSock2.h>
+#include <WS2tcpip.h>
 #else
 #else
+#include <sys/socket.h>
+#include <arpa/inet.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <signal.h>
 #include <signal.h>
 #endif
 #endif
@@ -61,7 +64,11 @@ UdpSocket::UdpSocket(
 	_sock(0),
 	_sock(0),
 	_v6(ipv6)
 	_v6(ipv6)
 {
 {
+#ifdef __WINDOWS__
+	BOOL yes,no;
+#else
 	int yes,no;
 	int yes,no;
+#endif
 
 
 	if ((localPort <= 0)||(localPort > 0xffff))
 	if ((localPort <= 0)||(localPort > 0xffff))
 		throw std::runtime_error("port is out of range");
 		throw std::runtime_error("port is out of range");
@@ -71,6 +78,11 @@ UdpSocket::UdpSocket(
 		if (_sock <= 0)
 		if (_sock <= 0)
 			throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
 			throw std::runtime_error("unable to create IPv6 SOCK_DGRAM socket");
 
 
+#ifdef __WINDOWS__
+		yes = TRUE; setsockopt(_sock,IPPROTO_IPV6,IPV6_V6ONLY,(const char *)&yes,sizeof(yes));
+		no = FALSE; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(const char *)&no,sizeof(no));
+		no = FALSE; setsockopt(_sock,IPPROTO_IPV6,IPV6_DONTFRAG,(const char *)&no,sizeof(no));
+#else
 		yes = 1; setsockopt(_sock,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&yes,sizeof(yes));
 		yes = 1; setsockopt(_sock,IPPROTO_IPV6,IPV6_V6ONLY,(void *)&yes,sizeof(yes));
 		no = 0; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(void *)&no,sizeof(no));
 		no = 0; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(void *)&no,sizeof(no));
 #ifdef IP_DONTFRAG
 #ifdef IP_DONTFRAG
@@ -81,6 +93,7 @@ UdpSocket::UdpSocket(
 #endif
 #endif
 #ifdef IPV6_MTU_DISCOVER
 #ifdef IPV6_MTU_DISCOVER
 		no = 0; setsockopt(_sock,IPPROTO_IPV6,IPV6_MTU_DISCOVER,&no,sizeof(no));
 		no = 0; setsockopt(_sock,IPPROTO_IPV6,IPV6_MTU_DISCOVER,&no,sizeof(no));
+#endif
 #endif
 #endif
 
 
 		struct sockaddr_in6 sin6;
 		struct sockaddr_in6 sin6;
@@ -91,7 +104,11 @@ UdpSocket::UdpSocket(
 			memcpy(&(sin6.sin6_addr.s6_addr),InetAddress::LO6.rawIpData(),16);
 			memcpy(&(sin6.sin6_addr.s6_addr),InetAddress::LO6.rawIpData(),16);
 		else memcpy(&(sin6.sin6_addr),&in6addr_any,sizeof(struct in6_addr));
 		else memcpy(&(sin6.sin6_addr),&in6addr_any,sizeof(struct in6_addr));
 		if (::bind(_sock,(const struct sockaddr *)&sin6,sizeof(sin6))) {
 		if (::bind(_sock,(const struct sockaddr *)&sin6,sizeof(sin6))) {
+#ifdef __WINDOWS__
+			::closesocket(_sock);
+#else
 			::close(_sock);
 			::close(_sock);
+#endif
 			throw std::runtime_error("unable to bind to port");
 			throw std::runtime_error("unable to bind to port");
 		}
 		}
 	} else {
 	} else {
@@ -99,12 +116,17 @@ UdpSocket::UdpSocket(
 		if (_sock <= 0)
 		if (_sock <= 0)
 			throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
 			throw std::runtime_error("unable to create IPv4 SOCK_DGRAM socket");
 
 
+#ifdef __WINDOWS__
+		no = FALSE; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(const char *)&no,sizeof(no));
+		no = FALSE; setsockopt(_sock,IPPROTO_IP,IP_DONTFRAGMENT,(const char *)&no,sizeof(no));
+#else
 		no = 0; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(void *)&no,sizeof(no));
 		no = 0; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(void *)&no,sizeof(no));
 #ifdef IP_DONTFRAG
 #ifdef IP_DONTFRAG
 		no = 0; setsockopt(_sock,IPPROTO_IP,IP_DONTFRAG,&no,sizeof(no));
 		no = 0; setsockopt(_sock,IPPROTO_IP,IP_DONTFRAG,&no,sizeof(no));
 #endif
 #endif
 #ifdef IP_MTU_DISCOVER
 #ifdef IP_MTU_DISCOVER
 		no = 0; setsockopt(_sock,IPPROTO_IP,IP_MTU_DISCOVER,&no,sizeof(no));
 		no = 0; setsockopt(_sock,IPPROTO_IP,IP_MTU_DISCOVER,&no,sizeof(no));
+#endif
 #endif
 #endif
 
 
 		struct sockaddr_in sin;
 		struct sockaddr_in sin;
@@ -115,7 +137,11 @@ UdpSocket::UdpSocket(
 			memcpy(&(sin.sin_addr.s_addr),InetAddress::LO4.rawIpData(),4);
 			memcpy(&(sin.sin_addr.s_addr),InetAddress::LO4.rawIpData(),4);
 		else sin.sin_addr.s_addr = INADDR_ANY;
 		else sin.sin_addr.s_addr = INADDR_ANY;
 		if (::bind(_sock,(const struct sockaddr *)&sin,sizeof(sin))) {
 		if (::bind(_sock,(const struct sockaddr *)&sin,sizeof(sin))) {
+#ifdef __WINDOWS__
+			::closesocket(_sock);
+#else
 			::close(_sock);
 			::close(_sock);
+#endif
 			throw std::runtime_error("unable to bind to port");
 			throw std::runtime_error("unable to bind to port");
 		}
 		}
 	}
 	}
@@ -128,8 +154,13 @@ UdpSocket::~UdpSocket()
 	int s = _sock;
 	int s = _sock;
 	_sock = 0;
 	_sock = 0;
 	if (s > 0) {
 	if (s > 0) {
+#ifdef __WINDOWS__
+		::shutdown(s,SD_BOTH);
+		::closesocket(s);
+#else
 		::shutdown(s,SHUT_RDWR);
 		::shutdown(s,SHUT_RDWR);
 		::close(s);
 		::close(s);
+#endif
 	}
 	}
 	Thread::join(_thread);
 	Thread::join(_thread);
 }
 }
@@ -141,13 +172,25 @@ bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int
 	if (to.isV6()) {
 	if (to.isV6()) {
 		if (!_v6)
 		if (!_v6)
 			return false;
 			return false;
+#ifdef __WINDOWS__
+		DWORD hltmp = (DWORD)hopLimit;
+		setsockopt(_sock,IPPROTO_IPV6,IPV6_UNICAST_HOPS,(const char *)&hltmp,sizeof(hltmp));
+		return ((int)sendto(_sock,(const char *)data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#else
 		setsockopt(_sock,IPPROTO_IPV6,IPV6_UNICAST_HOPS,&hopLimit,sizeof(hopLimit));
 		setsockopt(_sock,IPPROTO_IPV6,IPV6_UNICAST_HOPS,&hopLimit,sizeof(hopLimit));
 		return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
 		return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#endif
 	} else {
 	} else {
 		if (_v6)
 		if (_v6)
 			return false;
 			return false;
+#ifdef __WINDOWS__
+		DWORD hltmp = (DWORD)hopLimit;
+		setsockopt(_sock,IPPROTO_IP,IP_TTL,(const char *)&hltmp,sizeof(hltmp));
+		return ((int)sendto(_sock,(const char *)data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#else
 		setsockopt(_sock,IPPROTO_IP,IP_TTL,&hopLimit,sizeof(hopLimit));
 		setsockopt(_sock,IPPROTO_IP,IP_TTL,&hopLimit,sizeof(hopLimit));
 		return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
 		return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#endif
 	}
 	}
 }
 }
 
 

+ 2 - 0
node/UdpSocket.hpp

@@ -29,6 +29,8 @@
 #define _ZT_UDPSOCKET_HPP
 #define _ZT_UDPSOCKET_HPP
 
 
 #include <stdexcept>
 #include <stdexcept>
+
+#include "Constants.hpp"
 #include "Thread.hpp"
 #include "Thread.hpp"
 #include "InetAddress.hpp"
 #include "InetAddress.hpp"
 #include "Mutex.hpp"
 #include "Mutex.hpp"