From dc04b7cf09342e7676467ea2d5a79f8762dbe02e Mon Sep 17 00:00:00 2001
From: mpc <mpc>
Date: Sun, 27 Jun 2004 09:12:05 +0000
Subject: [PATCH] Some winsock improvements

---
 apps/sam/c/Makefile.cygwin |   2 +-
 apps/sam/c/inc/platform.h  |   6 +-
 apps/sam/c/inc/sam.h       |   2 +-
 apps/sam/c/src/sam.c       | 200 +++++++++++++++++++++++++++++++++----
 4 files changed, 189 insertions(+), 21 deletions(-)

diff --git a/apps/sam/c/Makefile.cygwin b/apps/sam/c/Makefile.cygwin
index 46930684e3..df439bf291 100644
--- a/apps/sam/c/Makefile.cygwin
+++ b/apps/sam/c/Makefile.cygwin
@@ -3,7 +3,7 @@
 #
 
 #
-# Your operating system
+# Your operating environment
 #
 
 OS = CYGWIN
diff --git a/apps/sam/c/inc/platform.h b/apps/sam/c/inc/platform.h
index 7fe4d63309..1d79c2668b 100644
--- a/apps/sam/c/inc/platform.h
+++ b/apps/sam/c/inc/platform.h
@@ -44,6 +44,7 @@
 	#define NO_GETHOSTBYNAME2
 	#define NO_INET_ATON  /* implies NO_INET_PTON */
 	#define NO_INET_NTOP
+	#define NO_SSIZE_T
 	#define NO_STRL
 	#define NO_Z_FORMAT
 	#define WINSOCK
@@ -103,6 +104,7 @@
 #endif
 #ifdef WINSOCK
 	#include <windows.h>
+	#include <winsock2.h>
 #else
 	#include <unistd.h>
 #endif
@@ -112,10 +114,12 @@
  */
 #ifdef WINSOCK
 	typedef SOCKET socket_t;
-	typedef signed long ssize_t;
 #else
 	typedef int socket_t;
 #endif
+#ifdef NO_SSIZE_T
+	typedef signed long ssize_t;
+#endif
 
 /*
  * Prints out the file name, line number, and function name before log message
diff --git a/apps/sam/c/inc/sam.h b/apps/sam/c/inc/sam.h
index 3b1e0e5879..258696f96c 100644
--- a/apps/sam/c/inc/sam.h
+++ b/apps/sam/c/inc/sam.h
@@ -86,7 +86,7 @@ extern samerr_t	sam_connect(const char *samhost, uint16_t samport,
 					const char *destname, sam_conn_t style, uint_t tunneldepth);
 extern void		sam_naming_lookup(const char *name);
 extern bool		sam_read_buffer(void);
-extern char		*sam_strerror(samerr_t code);
+extern const char *sam_strerror(samerr_t code);
 /* SAM controls - callbacks */
 extern void		(*sam_diedback)(void);
 extern void		(*sam_logback)(char *str);
diff --git a/apps/sam/c/src/sam.c b/apps/sam/c/src/sam.c
index 473f017674..2b97fd19e1 100644
--- a/apps/sam/c/src/sam.c
+++ b/apps/sam/c/src/sam.c
@@ -41,6 +41,11 @@ static samerr_t		sam_session_create(const char *destname, sam_conn_t style,
 						uint_t tunneldepth);
 static bool			sam_socket_connect(const char *host, uint16_t port);
 static bool			sam_socket_resolve(const char *hostname, char *ipaddr);
+#ifdef WINSOCK
+static samerr_t		sam_winsock_cleanup(void);
+static samerr_t		sam_winsock_startup(void);
+static const char	*sam_winsock_strerror(int code);
+#endif
 static ssize_t		sam_write(const void *buf, size_t n);
 
 /*
@@ -83,6 +88,8 @@ bool sam_close(void)
 	if (closesocket(samd) == 0) {
 		samd_connected = false;
 		return true;
+	if (sam_winsock_cleanup() != SAM_OK)
+		return false;
 #else
 	if (close(samd) == 0) {
 		samd_connected = false;
@@ -132,23 +139,9 @@ samerr_t sam_connect(const char *samhost, uint16_t samport,
 	}
 
 #ifdef WINSOCK
-	/*
-	 * Is Windows retarded or what?
-	 */
-	WORD wVersionRequested;
-	WSADATA wsaData;
-	int err;
-
-	wVersionRequested = MAKEWORD(1, 1);
-	err = WSAStartup(wVersionRequested, &wsaData);
-	if (err != 0) {
-		SAMLOGS("WSAStartup() failed");
-    	return SAM_SOCKET_ERROR;
-	}
-	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1 ) {
-		SAMLOGS("Bad WinSock version");
-    	return SAM_SOCKET_ERROR;
-	}
+	rc = sam_winsock_startup();
+	if (rc != SAM_OK)
+		return rc;
 #endif
 
 	if (!sam_socket_connect(samhost, samport)) {
@@ -953,7 +946,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
  *
  * Returns: error string
  */
-char *sam_strerror(samerr_t code)
+const char *sam_strerror(samerr_t code)
 {
 	switch (code) {
 		case SAM_OK:				/* Operation completed succesfully */
@@ -994,6 +987,177 @@ char *sam_strerror(samerr_t code)
 	}
 }
 
+#ifdef WINSOCK
+/*
+ * Unloads the Winsock network subsystem
+ *
+ * Returns: SAM error code
+ */
+samerr_t sam_winsock_cleanup(void)
+{
+	if (WSACleanup() == SOCKET_ERROR) {
+		SAMLOG("WSACleanup() failed (%s)",
+			sam_winsock_strerror(WSAGetLastError()));
+    	return SAM_SOCKET_ERROR;		
+	}
+
+	return SAM_OK;
+}
+
+/*
+ * Loads the Winsock network sucksystem
+ *
+ * Returns: SAM error code
+ */
+samerr_t sam_winsock_startup(void)
+{
+	/*
+	 * Is Windows retarded or what?
+	 */
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int rc;
+
+	wVersionRequested = MAKEWORD(2, 2);
+	rc = WSAStartup(wVersionRequested, &wsaData);
+	if (rc != 0) {
+		SAMLOG("WSAStartup() failed (%s)", sam_winsock_strerror(rc));
+    	return SAM_SOCKET_ERROR;
+	}
+	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
+		SAMLOGS("Bad Winsock version");
+		sam_winsock_cleanup();
+    	return SAM_SOCKET_ERROR;
+	}
+
+	return SAM_OK;
+}
+
+/*
+ * Apparently Winsock does not have a strerror() equivalent for its functions
+ *
+ * code - code from WSAGetLastError()
+ *
+ * Returns: error string (from http://msdn.microsoft.com/library/default.asp?
+ *		url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp)
+ */
+const char *sam_winsock_strerror(int code)
+{
+	switch (code) {
+		case WSAEINTR:
+			return "Interrupted function call";
+		case WSAEACCES:  // yes, that is the correct spelling
+			return "Permission denied";
+		case WSAEFAULT:
+			return "Bad address";
+		case WSAEINVAL:
+			return "Invalid argument";
+		case WSAEMFILE:
+			return "Too many open files";
+		case WSAEWOULDBLOCK:
+			return "Resource temporarily unavailable";
+		case WSAEINPROGRESS:
+			return "Operation now in progress";
+		case WSAEALREADY:
+			return "Operation already in progress";
+		case WSAENOTSOCK:
+			return "Socket operations on nonsocket";
+		case WSAEDESTADDRREQ:
+			return "Destination address required";
+		case WSAEMSGSIZE:
+			return "Message too long";
+		case WSAEPROTOTYPE:
+			return "Protocol wrong type for socket";
+		case WSAENOPROTOOPT:
+			return "Bad protocol option";
+		case WSAEPROTONOSUPPORT:
+			return "Protocol not supported";
+		case WSAESOCKTNOSUPPORT:
+			return "Socket type not supported";
+		case WSAEOPNOTSUPP:
+			return "Operation not supported";
+		case WSAEPFNOSUPPORT:
+			return "Protocol family not supported";
+		case WSAEAFNOSUPPORT:
+			return "Address family not supported by protocol family";
+		case WSAEADDRINUSE:
+			return "Address already in use";
+		case WSAEADDRNOTAVAIL:
+			return "Cannot assign requested address";
+		case WSAENETDOWN:
+			return "Network is down";
+		case WSAENETUNREACH:
+			return "Network is unreachable";
+		case WSAENETRESET:
+			return "Network dropped connection on reset";
+		case WSAECONNABORTED:
+			return "Software caused connection abort";
+		case WSAECONNRESET:
+			return "Connection reset by peer";
+		case WSAENOBUFS:
+			return "No buffer space available";
+		case WSAEISCONN:
+			return "Socket is already connected";
+		case WSAENOTCONN:
+			return "Socket is not connected";
+		case WSAESHUTDOWN:
+			return "Cannot send after socket shutdown";
+		case WSAETIMEDOUT:
+			return "Connection timed out";
+		case WSAECONNREFUSED:
+			return "Connection refused";
+		case WSAEHOSTDOWN:
+			return "Host is down";
+		case WSAEHOSTUNREACH:
+			return "No route to host";
+		case WSAEPROCLIM:
+			return "Too many processes";
+		case WSASYSNOTREADY:
+			return "Network subsystem is unavailable";
+		case WSAVERNOTSUPPORTED:
+			return "Winsock.dll version out of range";
+		case WSANOTINITIALISED:
+			return "Successful WSAStartup not yet performed";
+		case WSAEDISCON:
+			return "Graceful shutdown in progress";
+		case WSATYPE_NOT_FOUND:
+			return "Class type not found";
+		case WSAHOST_NOT_FOUND:
+			return "Host not found";
+		case WSATRY_AGAIN:
+			return "Nonauthoritative host not found";
+		case WSANO_RECOVERY:
+			return "This is a nonrecoverable error";
+		case WSANO_DATA:
+			return "Valid name, no data record of requested type";
+/* None of this shit compiles under Mingw - who knows why...
+		case WSA_INVALID_HANDLE:
+			return "Specified event object handle is invalid";
+		case WSA_INVALID_PARAMETER:
+			return "One or more parameters are invalid";
+		case WSA_IO_INCOMPLETE:
+			return "Overlapped I/O event object not in signaled state";
+		case WSA_IO_PENDING:
+			return "Overlapped operations will complete later";
+		case WSA_NOT_ENOUGH_MEMORY:
+			return "Insufficient memory available";
+		case WSA_OPERATION_ABORTED:
+			return "Overlapped operation aborted";
+		case WSAINVALIDPROCTABLE:
+			return "Invalid procedure table from service provider";
+		case WSAINVALIDPROVIDER:
+			return "Invalid service provider version number";
+		case WSAPROVIDERFAILEDINIT:
+			return "Unable to initialize a service provider";
+*/
+		case WSASYSCALLFAILURE:
+			return "System call failure";
+		default:
+			return "Unknown error";
+	}
+}
+#endif
+
 /*
  * Sends `n' bytes to the SAM host
  *
-- 
GitLab