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