THRIFT-1031 Patch to compile Thrift for vc++ 9.0 and 10.0
Patch: James Dickson and Alexandre Parenteau

git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1171777 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/transport/TServerSocket.cpp b/lib/cpp/src/transport/TServerSocket.cpp
index efe08fe..dfa55b4 100644
--- a/lib/cpp/src/transport/TServerSocket.cpp
+++ b/lib/cpp/src/transport/TServerSocket.cpp
@@ -52,6 +52,24 @@
 #define AF_LOCAL AF_UNIX
 #endif
 
+#ifndef SOCKOPT_CAST_T
+#   ifndef _WIN32
+#       define SOCKOPT_CAST_T void
+#   else
+#       define SOCKOPT_CAST_T char
+#   endif // _WIN32
+#endif
+
+template<class T>
+inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) {
+    return reinterpret_cast<const SOCKOPT_CAST_T*>(v);
+}
+
+template<class T>
+inline SOCKOPT_CAST_T* cast_sockopt(T* v) {
+    return reinterpret_cast<SOCKOPT_CAST_T*>(v);
+}
+
 namespace apache { namespace thrift { namespace transport {
 
 using namespace std;
@@ -182,7 +200,7 @@
   // Set reusaddress to prevent 2MSL delay on accept
   int one = 1;
   if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR,
-                       &one, sizeof(one))) {
+                       cast_sockopt(&one), sizeof(one))) {
     int errno_copy = errno;
     GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_REUSEADDR ", errno_copy);
     close();
@@ -192,7 +210,7 @@
   // Set TCP buffer sizes
   if (tcpSendBuffer_ > 0) {
     if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF,
-                         &tcpSendBuffer_, sizeof(tcpSendBuffer_))) {
+                         cast_sockopt(&tcpSendBuffer_), sizeof(tcpSendBuffer_))) {
       int errno_copy = errno;
       GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy);
       close();
@@ -202,7 +220,7 @@
 
   if (tcpRecvBuffer_ > 0) {
     if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF,
-                         &tcpRecvBuffer_, sizeof(tcpRecvBuffer_))) {
+                         cast_sockopt(&tcpRecvBuffer_), sizeof(tcpRecvBuffer_))) {
       int errno_copy = errno;
       GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy);
       close();
@@ -225,7 +243,7 @@
   if (res->ai_family == AF_INET6 && path_.empty()) {
     int zero = 0;
     if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY, 
-          &zero, sizeof(zero))) {
+          cast_sockopt(&zero), sizeof(zero))) {
       GlobalOutput.perror("TServerSocket::listen() IPV6_V6ONLY ", errno);
     }
   }
@@ -234,7 +252,7 @@
   // Turn linger off, don't want to block on calls to close
   struct linger ling = {0, 0};
   if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER,
-                       &ling, sizeof(ling))) {
+                       cast_sockopt(&ling), sizeof(ling))) {
     int errno_copy = errno;
     GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy);
     close();
@@ -245,7 +263,7 @@
   if (path_.empty()) {
     // TCP Nodelay, speed over bandwidth
     if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY,
-                         &one, sizeof(one))) {
+                         cast_sockopt(&one), sizeof(one))) {
       int errno_copy = errno;
       GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy);
       close();
@@ -273,6 +291,9 @@
   int retries = 0;
 
   if (! path_.empty()) {
+
+#ifndef _WIN32
+
     // Unix Domain Socket
     struct sockaddr_un address;
     socklen_t len;
@@ -303,6 +324,12 @@
 
     // free addrinfo
     freeaddrinfo(res0);
+
+#else
+      GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
+      throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported");
+#endif
+
   }
 
   // throw an error if we failed to bind properly
@@ -368,7 +395,7 @@
       // Check for an interrupt signal
       if (intSock2_ >= 0 && (fds[1].revents & POLLIN)) {
         int8_t buf;
-        if (-1 == recv(intSock2_, &buf, sizeof(int8_t), 0)) {
+        if (-1 == recv(intSock2_, cast_sockopt(&buf), sizeof(int8_t), 0)) {
           GlobalOutput.perror("TServerSocket::acceptImpl() recv() interrupt ", errno);
         }
         throw TTransportException(TTransportException::INTERRUPTED);
@@ -429,7 +456,7 @@
 void TServerSocket::interrupt() {
   if (intSock1_ >= 0) {
     int8_t byte = 0;
-    if (-1 == send(intSock1_, &byte, sizeof(int8_t), 0)) {
+    if (-1 == send(intSock1_, cast_sockopt(&byte), sizeof(int8_t), 0)) {
       GlobalOutput.perror("TServerSocket::interrupt() send() ", errno);
     }
   }
@@ -437,11 +464,18 @@
 
 void TServerSocket::close() {
   if (serverSocket_ >= 0) {
-    shutdown(serverSocket_, SHUT_RDWR);
-    ::close(serverSocket_);
+
+#ifdef _WIN32
+      shutdown(serverSocket_, SD_BOTH);
+      ::closesocket(serverSocket_);
+#else
+      shutdown(serverSocket_, SHUT_RDWR);
+      ::close(serverSocket_);
+#endif
+
   }
   if (intSock1_ >= 0) {
-    ::close(intSock1_);
+      ::close(intSock1_);
   }
   if (intSock2_ >= 0) {
     ::close(intSock2_);
diff --git a/lib/cpp/src/transport/TSocket.cpp b/lib/cpp/src/transport/TSocket.cpp
index bee9d80..48d0007 100644
--- a/lib/cpp/src/transport/TSocket.cpp
+++ b/lib/cpp/src/transport/TSocket.cpp
@@ -49,6 +49,24 @@
 #include "TSocket.h"
 #include "TTransportException.h"
 
+#ifndef SOCKOPT_CAST_T
+#   ifndef _WIN32
+#       define SOCKOPT_CAST_T void
+#   else
+#       define SOCKOPT_CAST_T char
+#   endif // _WIN32
+#endif
+
+template<class T>
+inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) {
+    return reinterpret_cast<const SOCKOPT_CAST_T*>(v);
+}
+
+template<class T>
+inline SOCKOPT_CAST_T* cast_sockopt(T* v) {
+    return reinterpret_cast<SOCKOPT_CAST_T*>(v);
+}
+
 namespace apache { namespace thrift { namespace transport {
 
 using namespace std;
@@ -141,7 +159,7 @@
     return false;
   }
   uint8_t buf;
-  int r = recv(socket_, &buf, 1, MSG_PEEK);
+  int r = recv(socket_, cast_sockopt(&buf), 1, MSG_PEEK);
   if (r == -1) {
     int errno_copy = errno;
     #if defined __FreeBSD__ || defined __MACH__
@@ -162,6 +180,11 @@
 }
 
 void TSocket::openConnection(struct addrinfo *res) {
+
+#ifdef _WIN32
+    TWinsockSingleton::create();
+#endif // _WIN32
+
   if (isOpen()) {
     return;
   }
@@ -222,6 +245,9 @@
   // Connect the socket
   int ret;
   if (! path_.empty()) {
+
+#ifndef _WIN32
+
     struct sockaddr_un address;
     socklen_t len;
 
@@ -235,6 +261,12 @@
     snprintf(address.sun_path, sizeof(address.sun_path), "%s", path_.c_str());
     len = sizeof(address);
     ret = connect(socket_, (struct sockaddr *) &address, len);
+
+#else
+      GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
+      throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported");
+#endif
+
   } else {
     ret = connect(socket_, res->ai_addr, res->ai_addrlen);
   }
@@ -262,7 +294,7 @@
     int val;
     socklen_t lon;
     lon = sizeof(int);
-    int ret2 = getsockopt(socket_, SOL_SOCKET, SO_ERROR, (void *)&val, &lon);
+    int ret2 = getsockopt(socket_, SOL_SOCKET, SO_ERROR, cast_sockopt(&val), &lon);
     if (ret2 == -1) {
       int errno_copy = errno;
       GlobalOutput.perror("TSocket::open() getsockopt() " + getSocketInfo(), errno_copy);
@@ -366,8 +398,15 @@
 
 void TSocket::close() {
   if (socket_ >= 0) {
-    shutdown(socket_, SHUT_RDWR);
-    ::close(socket_);
+
+#ifdef _WIN32
+      shutdown(socket_, SD_BOTH);
+      ::closesocket(socket_);
+#else
+      shutdown(socket_, SHUT_RDWR);
+      ::close(socket_);
+#endif
+
   }
   socket_ = -1;
 }
@@ -408,7 +447,7 @@
     // an EAGAIN is due to a timeout or an out-of-resource condition.
     begin.tv_sec = begin.tv_usec = 0;
   }
-  int got = recv(socket_, buf, len, 0);
+  int got = recv(socket_, cast_sockopt(buf), len, 0);
   int errno_copy = errno; //gettimeofday can change errno
   ++g_socket_syscalls;
 
@@ -518,7 +557,7 @@
   flags |= MSG_NOSIGNAL;
 #endif // ifdef MSG_NOSIGNAL
 
-  int b = send(socket_, buf + sent, len - sent, flags);
+  int b = send(socket_, const_cast_sockopt(buf + sent), len - sent, flags);
   ++g_socket_syscalls;
 
   if (b < 0) {
@@ -568,7 +607,7 @@
   }
 
   struct linger l = {(lingerOn_ ? 1 : 0), lingerVal_};
-  int ret = setsockopt(socket_, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
+  int ret = setsockopt(socket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&l), sizeof(l));
   if (ret == -1) {
     int errno_copy = errno;  // Copy errno because we're allocating memory.
     GlobalOutput.perror("TSocket::setLinger() setsockopt() " + getSocketInfo(), errno_copy);
@@ -583,7 +622,7 @@
 
   // Set socket to NODELAY
   int v = noDelay_ ? 1 : 0;
-  int ret = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+  int ret = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&v), sizeof(v));
   if (ret == -1) {
     int errno_copy = errno;  // Copy errno because we're allocating memory.
     GlobalOutput.perror("TSocket::setNoDelay() setsockopt() " + getSocketInfo(), errno_copy);
@@ -612,7 +651,7 @@
 
   // Copy because poll may modify
   struct timeval r = recvTimeval_;
-  int ret = setsockopt(socket_, SOL_SOCKET, SO_RCVTIMEO, &r, sizeof(r));
+  int ret = setsockopt(socket_, SOL_SOCKET, SO_RCVTIMEO, cast_sockopt(&r), sizeof(r));
   if (ret == -1) {
     int errno_copy = errno;  // Copy errno because we're allocating memory.
     GlobalOutput.perror("TSocket::setRecvTimeout() setsockopt() " + getSocketInfo(), errno_copy);
@@ -634,7 +673,7 @@
 
   struct timeval s = {(int)(sendTimeout_/1000),
                       (int)((sendTimeout_%1000)*1000)};
-  int ret = setsockopt(socket_, SOL_SOCKET, SO_SNDTIMEO, &s, sizeof(s));
+  int ret = setsockopt(socket_, SOL_SOCKET, SO_SNDTIMEO, cast_sockopt(&s), sizeof(s));
   if (ret == -1) {
     int errno_copy = errno;  // Copy errno because we're allocating memory.
     GlobalOutput.perror("TSocket::setSendTimeout() setsockopt() " + getSocketInfo(), errno_copy);