Enable bssl client/s_client and server/s_server on Windows.

Change-Id: Iea9bd25176724b56ebb21bded6925f5d30176548
Reviewed-on: https://boringssl-review.googlesource.com/3071
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/tool/client.cc b/tool/client.cc
index d73d408..59c5fe3 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -14,16 +14,12 @@
 
 #include <openssl/base.h>
 
-// TODO(davidben): bssl client does not work on Windows.
-#if !defined(OPENSSL_WINDOWS)
-
 #include <string>
 #include <vector>
 
 #include <errno.h>
 #include <stdlib.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 
 #include <openssl/err.h>
 #include <openssl/ssl.h>
@@ -47,6 +43,10 @@
 };
 
 bool Client(const std::vector<std::string> &args) {
+  if (!InitSocketLibrary()) {
+    return false;
+  }
+
   std::map<std::string, std::string> args_map;
 
   if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
@@ -98,6 +98,3 @@
   SSL_CTX_free(ctx);
   return ok;
 }
-
-
-#endif  // !OPENSSL_WINDOWS
diff --git a/tool/digest.cc b/tool/digest.cc
index 9c75d2d..086d3a4 100644
--- a/tool/digest.cc
+++ b/tool/digest.cc
@@ -37,6 +37,7 @@
 #include <io.h>
 #define PATH_MAX MAX_PATH
 #define read _read
+typedef int ssize_t;
 #endif
 
 #include <openssl/digest.h>
diff --git a/tool/server.cc b/tool/server.cc
index bc3739f..120e450 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -14,9 +14,6 @@
 
 #include <openssl/base.h>
 
-// TODO(davidben): bssl client does not work on Windows.
-#if !defined(OPENSSL_WINDOWS)
-
 #include <string>
 #include <vector>
 
@@ -50,6 +47,10 @@
 };
 
 bool Server(const std::vector<std::string> &args) {
+  if (!InitSocketLibrary()) {
+    return false;
+  }
+
   std::map<std::string, std::string> args_map;
 
   if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
@@ -106,6 +107,3 @@
   SSL_CTX_free(ctx);
   return ok;
 }
-
-
-#endif  // !OPENSSL_WINDOWS
diff --git a/tool/tool.cc b/tool/tool.cc
index 3b24be5..36e3de9 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -26,10 +26,8 @@
 #endif
 
 
-#if !defined(OPENSSL_WINDOWS)
 bool Client(const std::vector<std::string> &args);
 bool Server(const std::vector<std::string> &args);
-#endif
 bool MD5Sum(const std::vector<std::string> &args);
 bool SHA1Sum(const std::vector<std::string> &args);
 bool SHA224Sum(const std::vector<std::string> &args);
@@ -49,12 +47,10 @@
 static const Tool kTools[] = {
   { "speed", Speed },
   { "pkcs12", DoPKCS12 },
-#if !defined(OPENSSL_WINDOWS)
   { "client", Client },
   { "s_client", Client },
   { "server", Server },
   { "s_server", Server },
-#endif
   { "md5sum", MD5Sum },
   { "sha1sum", SHA1Sum },
   { "sha224sum", SHA224Sum },
diff --git a/tool/transport_common.cc b/tool/transport_common.cc
index 528dd3e..c2b3e0c 100644
--- a/tool/transport_common.cc
+++ b/tool/transport_common.cc
@@ -14,17 +14,12 @@
 
 #include <openssl/base.h>
 
-// TODO(davidben): bssl client does not work on Windows.
-#if !defined(OPENSSL_WINDOWS)
-
 #include <string>
 #include <vector>
 
 #include <errno.h>
 #include <stdlib.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 
 #if !defined(OPENSSL_WINDOWS)
 #include <arpa/inet.h>
@@ -32,11 +27,19 @@
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/select.h>
+#include <sys/socket.h>
 #include <unistd.h>
 #else
+#define WIN32_LEAN_AND_MEAN // prevent conflicting defines of X509_* names
+#define NOMINMAX
+#include <io.h>
 #include <WinSock2.h>
 #include <WS2tcpip.h>
 typedef int socklen_t;
+typedef int ssize_t;
+#define read _read
+#define write _write
+#pragma comment(lib, "Ws2_32.lib")
 #endif
 
 #include <openssl/err.h>
@@ -45,6 +48,24 @@
 #include "internal.h"
 
 
+#if !defined(OPENSSL_WINDOWS)
+static int closesocket(int sock) {
+  return close(sock);
+}
+#endif
+
+bool InitSocketLibrary() {
+#if defined(OPENSSL_WINDOWS)
+  WSADATA wsaData;
+  int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
+  if (err != 0) {
+    fprintf(stderr, "WSAStartup failed with error %d\n", err);
+    return false;
+  }
+#endif
+  return true;
+}
+
 // Connect sets |*out_sock| to be a socket connected to the destination given
 // in |hostname_and_port|, which should be of the form "www.example.com:123".
 // It returns true on success and false otherwise.
@@ -140,7 +161,7 @@
   ok = true;
 
 out:
-  close(server_sock);
+  closesocket(server_sock);
   return ok;
 }
 
@@ -158,7 +179,7 @@
 
 #if defined(OPENSSL_WINDOWS)
   u_long arg = is_non_blocking;
-  ok = 0 == ioctlsocket(sock, FIOBIO, &arg);
+  ok = 0 == ioctlsocket(sock, FIONBIO, &arg);
 #else
   int flags = fcntl(sock, F_GETFL, 0);
   if (flags < 0) {
@@ -217,7 +238,11 @@
       if (n == 0) {
         FD_CLR(0, &read_fds);
         stdin_open = false;
+#if !defined(OPENSSL_WINDOWS)
         shutdown(sock, SHUT_WR);
+#else
+        shutdown(sock, SD_SEND);
+#endif
         continue;
       } else if (n < 0) {
         perror("read from stdin");
@@ -271,6 +296,3 @@
     }
   }
 }
-
-
-#endif  // !OPENSSL_WINDOWS
diff --git a/tool/transport_common.h b/tool/transport_common.h
index 6b96659..b701015 100644
--- a/tool/transport_common.h
+++ b/tool/transport_common.h
@@ -18,6 +18,8 @@
 #include <openssl/ssl.h>
 #include <string.h>
 
+// InitSocketLibrary calls the Windows socket init functions, if needed.
+bool InitSocketLibrary();
 
 // Connect sets |*out_sock| to be a socket connected to the destination given
 // in |hostname_and_port|, which should be of the form "www.example.com:123".