summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2013-08-12 16:18:35 -0400
committerAdam Ierymenko <adam.ierymenko@zerotier.com>2013-08-12 16:18:35 -0400
commit36af3d92ecb4148a74c14896f5b6a9dcea0c1700 (patch)
tree0474c2add280ea6a33f25eff9bdf7ada7fe0c70d
parent2ad80063ec6e7d78d0d5b492f6065563792de05c (diff)
downloadinfinitytier-36af3d92ecb4148a74c14896f5b6a9dcea0c1700.tar.gz
infinitytier-36af3d92ecb4148a74c14896f5b6a9dcea0c1700.zip
Windows build work: condition, mutex, thread, udp socket...
-rw-r--r--node/Condition.hpp66
-rw-r--r--node/Mutex.hpp8
-rw-r--r--node/Thread.hpp52
-rw-r--r--node/UdpSocket.cpp47
-rw-r--r--node/UdpSocket.hpp2
5 files changed, 151 insertions, 24 deletions
diff --git a/node/Condition.hpp b/node/Condition.hpp
index 2ce8c98f..4b2d32ca 100644
--- a/node/Condition.hpp
+++ b/node/Condition.hpp
@@ -28,9 +28,57 @@
#ifndef _ZT_CONDITION_HPP
#define _ZT_CONDITION_HPP
+#include "Constants.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 <stdlib.h>
@@ -88,20 +136,6 @@ private:
} // 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
diff --git a/node/Mutex.hpp b/node/Mutex.hpp
index 493cc425..b0130293 100644
--- a/node/Mutex.hpp
+++ b/node/Mutex.hpp
@@ -28,9 +28,10 @@
#ifndef _ZT_MUTEX_HPP
#define _ZT_MUTEX_HPP
+#include "Constants.hpp"
#include "NonCopyable.hpp"
-#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
+#ifdef __UNIX_LIKE__
#include <stdlib.h>
#include <pthread.h>
@@ -112,7 +113,7 @@ private:
#endif // Apple / Linux
-#ifdef _WIN32
+#ifdef __WINDOWS__
#include <stdlib.h>
#include <Windows.h>
@@ -157,9 +158,6 @@ public:
(const_cast <Mutex *> (this))->unlock();
}
- /**
- * Uses C++ contexts and constructor/destructor to lock/unlock automatically
- */
class Lock : NonCopyable
{
public:
diff --git a/node/Thread.hpp b/node/Thread.hpp
index ea75297a..d295fea3 100644
--- a/node/Thread.hpp
+++ b/node/Thread.hpp
@@ -35,7 +35,57 @@
#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
diff --git a/node/UdpSocket.cpp b/node/UdpSocket.cpp
index d1eb87d6..dfe2b11d 100644
--- a/node/UdpSocket.cpp
+++ b/node/UdpSocket.cpp
@@ -30,13 +30,16 @@
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
-#include <sys/socket.h>
#include <sys/types.h>
-#include <arpa/inet.h>
+#include <sys/stat.h>
#ifdef _WIN32
#include <Windows.h>
+#include <WinSock2.h>
+#include <WS2tcpip.h>
#else
+#include <sys/socket.h>
+#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#endif
@@ -61,7 +64,11 @@ UdpSocket::UdpSocket(
_sock(0),
_v6(ipv6)
{
+#ifdef __WINDOWS__
+ BOOL yes,no;
+#else
int yes,no;
+#endif
if ((localPort <= 0)||(localPort > 0xffff))
throw std::runtime_error("port is out of range");
@@ -71,6 +78,11 @@ UdpSocket::UdpSocket(
if (_sock <= 0)
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));
no = 0; setsockopt(_sock,SOL_SOCKET,SO_REUSEADDR,(void *)&no,sizeof(no));
#ifdef IP_DONTFRAG
@@ -82,6 +94,7 @@ UdpSocket::UdpSocket(
#ifdef IPV6_MTU_DISCOVER
no = 0; setsockopt(_sock,IPPROTO_IPV6,IPV6_MTU_DISCOVER,&no,sizeof(no));
#endif
+#endif
struct sockaddr_in6 sin6;
memset(&sin6,0,sizeof(sin6));
@@ -91,7 +104,11 @@ UdpSocket::UdpSocket(
memcpy(&(sin6.sin6_addr.s6_addr),InetAddress::LO6.rawIpData(),16);
else memcpy(&(sin6.sin6_addr),&in6addr_any,sizeof(struct in6_addr));
if (::bind(_sock,(const struct sockaddr *)&sin6,sizeof(sin6))) {
+#ifdef __WINDOWS__
+ ::closesocket(_sock);
+#else
::close(_sock);
+#endif
throw std::runtime_error("unable to bind to port");
}
} else {
@@ -99,6 +116,10 @@ UdpSocket::UdpSocket(
if (_sock <= 0)
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));
#ifdef IP_DONTFRAG
no = 0; setsockopt(_sock,IPPROTO_IP,IP_DONTFRAG,&no,sizeof(no));
@@ -106,6 +127,7 @@ UdpSocket::UdpSocket(
#ifdef IP_MTU_DISCOVER
no = 0; setsockopt(_sock,IPPROTO_IP,IP_MTU_DISCOVER,&no,sizeof(no));
#endif
+#endif
struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
@@ -115,7 +137,11 @@ UdpSocket::UdpSocket(
memcpy(&(sin.sin_addr.s_addr),InetAddress::LO4.rawIpData(),4);
else sin.sin_addr.s_addr = INADDR_ANY;
if (::bind(_sock,(const struct sockaddr *)&sin,sizeof(sin))) {
+#ifdef __WINDOWS__
+ ::closesocket(_sock);
+#else
::close(_sock);
+#endif
throw std::runtime_error("unable to bind to port");
}
}
@@ -128,8 +154,13 @@ UdpSocket::~UdpSocket()
int s = _sock;
_sock = 0;
if (s > 0) {
+#ifdef __WINDOWS__
+ ::shutdown(s,SD_BOTH);
+ ::closesocket(s);
+#else
::shutdown(s,SHUT_RDWR);
::close(s);
+#endif
}
Thread::join(_thread);
}
@@ -141,13 +172,25 @@ bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int
if (to.isV6()) {
if (!_v6)
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));
return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#endif
} else {
if (_v6)
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));
return ((int)sendto(_sock,data,len,0,to.saddr(),to.saddrLen()) == (int)len);
+#endif
}
}
diff --git a/node/UdpSocket.hpp b/node/UdpSocket.hpp
index c6200eac..6b7d488c 100644
--- a/node/UdpSocket.hpp
+++ b/node/UdpSocket.hpp
@@ -29,6 +29,8 @@
#define _ZT_UDPSOCKET_HPP
#include <stdexcept>
+
+#include "Constants.hpp"
#include "Thread.hpp"
#include "InetAddress.hpp"
#include "Mutex.hpp"