diff options
Diffstat (limited to 'win/tclWinSock.c')
-rw-r--r-- | win/tclWinSock.c | 559 |
1 files changed, 330 insertions, 229 deletions
diff --git a/win/tclWinSock.c b/win/tclWinSock.c index bd81d2d..c6e6273 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -8,11 +8,10 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * SCCS: @(#) tclWinSock.c 1.80 97/10/09 18:24:59 + * SCCS: @(#) tclWinSock.c 1.93 98/02/19 15:21:32 */ -#include "tclInt.h" -#include "tclPort.h" +#include "tclWinInt.h" /* * The following variable is used to tell whether this module has been @@ -24,6 +23,7 @@ static int initialized = 0; static int hostnameInitialized = 0; static char hostname[255]; /* This buffer should be big enough for * hostname plus domain name. */ +static Tcl_Mutex socketMutex; /* * The following structure contains pointers to all of the WinSock API entry @@ -139,11 +139,15 @@ typedef struct SocketEvent { #define SOCKET_PENDING (1<<3) /* A message has been sent * for this socket */ -/* - * Every open socket has an entry on the following list. - */ +typedef struct ThreadSpecificData { + /* + * Every open socket has an entry on the following list. + */ + + SocketInfo *socketList; +} ThreadSpecificData; -static SocketInfo *socketList; +static Tcl_ThreadDataKey dataKey; /* * Static functions defined in this file. @@ -166,6 +170,8 @@ static LRESULT CALLBACK SocketProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); static void SocketSetupProc _ANSI_ARGS_((ClientData clientData, int flags)); +static void SocketThreadExitHandler _ANSI_ARGS_((ClientData clientData)); +static int SocketsEnabled _ANSI_ARGS_((void)); static void TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr)); static int TcpBlockProc _ANSI_ARGS_((ClientData instanceData, int mode)); @@ -218,6 +224,8 @@ static Tcl_ChannelType tcpChannelType = { * library and set up the winSock function table. If successful, * registers the event window for the socket notifier code. * + * Assumes Mutex is held. + * * Results: * None. * @@ -234,181 +242,195 @@ InitSockets() { WSADATA wsaData; OSVERSIONINFO info; - WNDCLASS class; - - initialized = 1; - Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL); - - /* - * Find out if we're running on Win32s. - */ - - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&info); - - /* - * Check to see if Sockets are supported on this system. Since - * win32s panics if we call WSAStartup on a system that doesn't - * have winsock.dll, we need to look for it on the system first. - * If we find winsock, then load the library and initialize the - * stub table. - */ - - if ((info.dwPlatformId != VER_PLATFORM_WIN32s) - || (SearchPath(NULL, "WINSOCK", ".DLL", 0, NULL, NULL) != 0)) { - winSock.hInstance = LoadLibrary("wsock32.dll"); - } else { - winSock.hInstance = NULL; - } + WNDCLASSA class; + ThreadSpecificData *tsdPtr = + (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); - /* - * Initialize the function table. - */ - - if (winSock.hInstance == NULL) { - return; - } - - winSock.accept = (SOCKET (PASCAL FAR *)(SOCKET s, - struct sockaddr FAR *addr, int FAR *addrlen)) - GetProcAddress(winSock.hInstance, "accept"); - winSock.bind = (int (PASCAL FAR *)(SOCKET s, - const struct sockaddr FAR *addr, int namelen)) - GetProcAddress(winSock.hInstance, "bind"); - winSock.closesocket = (int (PASCAL FAR *)(SOCKET s)) - GetProcAddress(winSock.hInstance, "closesocket"); - winSock.connect = (int (PASCAL FAR *)(SOCKET s, - const struct sockaddr FAR *name, int namelen)) - GetProcAddress(winSock.hInstance, "connect"); - winSock.ioctlsocket = (int (PASCAL FAR *)(SOCKET s, long cmd, - u_long FAR *argp)) GetProcAddress(winSock.hInstance, "ioctlsocket"); - winSock.getsockopt = (int (PASCAL FAR *)(SOCKET s, - int level, int optname, char FAR * optval, int FAR *optlen)) - GetProcAddress(winSock.hInstance, "getsockopt"); - winSock.htons = (u_short (PASCAL FAR *)(u_short hostshort)) - GetProcAddress(winSock.hInstance, "htons"); - winSock.inet_addr = (unsigned long (PASCAL FAR *)(const char FAR *cp)) - GetProcAddress(winSock.hInstance, "inet_addr"); - winSock.inet_ntoa = (char FAR * (PASCAL FAR *)(struct in_addr in)) - GetProcAddress(winSock.hInstance, "inet_ntoa"); - winSock.listen = (int (PASCAL FAR *)(SOCKET s, int backlog)) - GetProcAddress(winSock.hInstance, "listen"); - winSock.ntohs = (u_short (PASCAL FAR *)(u_short netshort)) - GetProcAddress(winSock.hInstance, "ntohs"); - winSock.recv = (int (PASCAL FAR *)(SOCKET s, char FAR * buf, - int len, int flags)) GetProcAddress(winSock.hInstance, "recv"); - winSock.send = (int (PASCAL FAR *)(SOCKET s, const char FAR * buf, - int len, int flags)) GetProcAddress(winSock.hInstance, "send"); - winSock.setsockopt = (int (PASCAL FAR *)(SOCKET s, int level, - int optname, const char FAR * optval, int optlen)) - GetProcAddress(winSock.hInstance, "setsockopt"); - winSock.shutdown = (int (PASCAL FAR *)(SOCKET s, int how)) - GetProcAddress(winSock.hInstance, "shutdown"); - winSock.socket = (SOCKET (PASCAL FAR *)(int af, int type, - int protocol)) GetProcAddress(winSock.hInstance, "socket"); - winSock.gethostbyaddr = (struct hostent FAR * (PASCAL FAR *) - (const char FAR *addr, int addrlen, int addrtype)) - GetProcAddress(winSock.hInstance, "gethostbyaddr"); - winSock.gethostbyname = (struct hostent FAR * (PASCAL FAR *) - (const char FAR *name)) - GetProcAddress(winSock.hInstance, "gethostbyname"); - winSock.gethostname = (int (PASCAL FAR *)(char FAR * name, - int namelen)) GetProcAddress(winSock.hInstance, "gethostname"); - winSock.getpeername = (int (PASCAL FAR *)(SOCKET sock, - struct sockaddr FAR *name, int FAR *namelen)) - GetProcAddress(winSock.hInstance, "getpeername"); - winSock.getservbyname = (struct servent FAR * (PASCAL FAR *) - (const char FAR * name, const char FAR * proto)) - GetProcAddress(winSock.hInstance, "getservbyname"); - winSock.getsockname = (int (PASCAL FAR *)(SOCKET sock, - struct sockaddr FAR *name, int FAR *namelen)) - GetProcAddress(winSock.hInstance, "getsockname"); - winSock.WSAStartup = (int (PASCAL FAR *)(WORD wVersionRequired, - LPWSADATA lpWSAData)) GetProcAddress(winSock.hInstance, "WSAStartup"); - winSock.WSACleanup = (int (PASCAL FAR *)(void)) - GetProcAddress(winSock.hInstance, "WSACleanup"); - winSock.WSAGetLastError = (int (PASCAL FAR *)(void)) - GetProcAddress(winSock.hInstance, "WSAGetLastError"); - winSock.WSAAsyncSelect = (int (PASCAL FAR *)(SOCKET s, HWND hWnd, - u_int wMsg, long lEvent)) - GetProcAddress(winSock.hInstance, "WSAAsyncSelect"); - - /* - * Now check that all fields are properly initialized. If not, return - * zero to indicate that we failed to initialize properly. - */ - - if ((winSock.hInstance == NULL) || - (winSock.accept == NULL) || - (winSock.bind == NULL) || - (winSock.closesocket == NULL) || - (winSock.connect == NULL) || - (winSock.ioctlsocket == NULL) || - (winSock.getsockopt == NULL) || - (winSock.htons == NULL) || - (winSock.inet_addr == NULL) || - (winSock.inet_ntoa == NULL) || - (winSock.listen == NULL) || - (winSock.ntohs == NULL) || - (winSock.recv == NULL) || - (winSock.send == NULL) || - (winSock.setsockopt == NULL) || - (winSock.socket == NULL) || - (winSock.gethostbyname == NULL) || - (winSock.gethostbyaddr == NULL) || - (winSock.gethostname == NULL) || - (winSock.getpeername == NULL) || - (winSock.getservbyname == NULL) || - (winSock.getsockname == NULL) || - (winSock.WSAStartup == NULL) || - (winSock.WSACleanup == NULL) || - (winSock.WSAGetLastError == NULL) || - (winSock.WSAAsyncSelect == NULL)) { - goto unloadLibrary; - } + if (! initialized) { + initialized = 1; + Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL); - /* - * Initialize the winsock library and check the version number. - */ - - if ((*winSock.WSAStartup)(WSA_VERSION_REQD, &wsaData) != 0) { - goto unloadLibrary; - } - if (wsaData.wVersion != WSA_VERSION_REQD) { - (*winSock.WSACleanup)(); - goto unloadLibrary; + /* + * Find out if we're running on Win32s. + */ + + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&info); + + /* + * Check to see if Sockets are supported on this system. Since + * win32s panics if we call WSAStartup on a system that doesn't + * have winsock.dll, we need to look for it on the system first. + * If we find winsock, then load the library and initialize the + * stub table. + */ + + if ((info.dwPlatformId != VER_PLATFORM_WIN32s) + || (SearchPathA(NULL, "WINSOCK", ".DLL", 0, NULL, NULL) != 0)) { + winSock.hInstance = LoadLibraryA("wsock32.dll"); + } else { + winSock.hInstance = NULL; + } + + /* + * Initialize the function table. + */ + + if (!SocketsEnabled()) { + return; + } + + winSock.accept = (SOCKET (PASCAL FAR *)(SOCKET s, + struct sockaddr FAR *addr, int FAR *addrlen)) + GetProcAddress(winSock.hInstance, "accept"); + winSock.bind = (int (PASCAL FAR *)(SOCKET s, + const struct sockaddr FAR *addr, int namelen)) + GetProcAddress(winSock.hInstance, "bind"); + winSock.closesocket = (int (PASCAL FAR *)(SOCKET s)) + GetProcAddress(winSock.hInstance, "closesocket"); + winSock.connect = (int (PASCAL FAR *)(SOCKET s, + const struct sockaddr FAR *name, int namelen)) + GetProcAddress(winSock.hInstance, "connect"); + winSock.ioctlsocket = (int (PASCAL FAR *)(SOCKET s, long cmd, + u_long FAR *argp)) GetProcAddress(winSock.hInstance, "ioctlsocket"); + winSock.getsockopt = (int (PASCAL FAR *)(SOCKET s, + int level, int optname, char FAR * optval, int FAR *optlen)) + GetProcAddress(winSock.hInstance, "getsockopt"); + winSock.htons = (u_short (PASCAL FAR *)(u_short hostshort)) + GetProcAddress(winSock.hInstance, "htons"); + winSock.inet_addr = (unsigned long (PASCAL FAR *)(const char FAR *cp)) + GetProcAddress(winSock.hInstance, "inet_addr"); + winSock.inet_ntoa = (char FAR * (PASCAL FAR *)(struct in_addr in)) + GetProcAddress(winSock.hInstance, "inet_ntoa"); + winSock.listen = (int (PASCAL FAR *)(SOCKET s, int backlog)) + GetProcAddress(winSock.hInstance, "listen"); + winSock.ntohs = (u_short (PASCAL FAR *)(u_short netshort)) + GetProcAddress(winSock.hInstance, "ntohs"); + winSock.recv = (int (PASCAL FAR *)(SOCKET s, char FAR * buf, + int len, int flags)) GetProcAddress(winSock.hInstance, "recv"); + winSock.send = (int (PASCAL FAR *)(SOCKET s, const char FAR * buf, + int len, int flags)) GetProcAddress(winSock.hInstance, "send"); + winSock.setsockopt = (int (PASCAL FAR *)(SOCKET s, int level, + int optname, const char FAR * optval, int optlen)) + GetProcAddress(winSock.hInstance, "setsockopt"); + winSock.shutdown = (int (PASCAL FAR *)(SOCKET s, int how)) + GetProcAddress(winSock.hInstance, "shutdown"); + winSock.socket = (SOCKET (PASCAL FAR *)(int af, int type, + int protocol)) GetProcAddress(winSock.hInstance, "socket"); + winSock.gethostbyaddr = (struct hostent FAR * (PASCAL FAR *) + (const char FAR *addr, int addrlen, int addrtype)) + GetProcAddress(winSock.hInstance, "gethostbyaddr"); + winSock.gethostbyname = (struct hostent FAR * (PASCAL FAR *) + (const char FAR *name)) + GetProcAddress(winSock.hInstance, "gethostbyname"); + winSock.gethostname = (int (PASCAL FAR *)(char FAR * name, + int namelen)) GetProcAddress(winSock.hInstance, "gethostname"); + winSock.getpeername = (int (PASCAL FAR *)(SOCKET sock, + struct sockaddr FAR *name, int FAR *namelen)) + GetProcAddress(winSock.hInstance, "getpeername"); + winSock.getservbyname = (struct servent FAR * (PASCAL FAR *) + (const char FAR * name, const char FAR * proto)) + GetProcAddress(winSock.hInstance, "getservbyname"); + winSock.getsockname = (int (PASCAL FAR *)(SOCKET sock, + struct sockaddr FAR *name, int FAR *namelen)) + GetProcAddress(winSock.hInstance, "getsockname"); + winSock.WSAStartup = (int (PASCAL FAR *)(WORD wVersionRequired, + LPWSADATA lpWSAData)) GetProcAddress(winSock.hInstance, "WSAStartup"); + winSock.WSACleanup = (int (PASCAL FAR *)(void)) + GetProcAddress(winSock.hInstance, "WSACleanup"); + winSock.WSAGetLastError = (int (PASCAL FAR *)(void)) + GetProcAddress(winSock.hInstance, "WSAGetLastError"); + winSock.WSAAsyncSelect = (int (PASCAL FAR *)(SOCKET s, HWND hWnd, + u_int wMsg, long lEvent)) + GetProcAddress(winSock.hInstance, "WSAAsyncSelect"); + + /* + * Now check that all fields are properly initialized. If not, return + * zero to indicate that we failed to initialize properly. + */ + + if ((winSock.hInstance == NULL) || + (winSock.accept == NULL) || + (winSock.bind == NULL) || + (winSock.closesocket == NULL) || + (winSock.connect == NULL) || + (winSock.ioctlsocket == NULL) || + (winSock.getsockopt == NULL) || + (winSock.htons == NULL) || + (winSock.inet_addr == NULL) || + (winSock.inet_ntoa == NULL) || + (winSock.listen == NULL) || + (winSock.ntohs == NULL) || + (winSock.recv == NULL) || + (winSock.send == NULL) || + (winSock.setsockopt == NULL) || + (winSock.socket == NULL) || + (winSock.gethostbyname == NULL) || + (winSock.gethostbyaddr == NULL) || + (winSock.gethostname == NULL) || + (winSock.getpeername == NULL) || + (winSock.getservbyname == NULL) || + (winSock.getsockname == NULL) || + (winSock.WSAStartup == NULL) || + (winSock.WSACleanup == NULL) || + (winSock.WSAGetLastError == NULL) || + (winSock.WSAAsyncSelect == NULL)) { + goto unloadLibrary; + } + + /* + * Initialize the winsock library and check the version number. + */ + + if ((*winSock.WSAStartup)(WSA_VERSION_REQD, &wsaData) != 0) { + goto unloadLibrary; + } + if (wsaData.wVersion != WSA_VERSION_REQD) { + (*winSock.WSACleanup)(); + goto unloadLibrary; + } + + /* + * Create the async notification window with a new class. We + * must create a new class to avoid a Windows 95 bug that causes + * us to get the wrong message number for socket events if the + * message window is a subclass of a static control. + */ + + class.style = 0; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = TclWinGetTclInstance(); + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = "TclSocket"; + class.lpfnWndProc = SocketProc; + class.hIcon = NULL; + class.hCursor = NULL; + + if (RegisterClassA(&class)) { + winSock.hwnd = CreateWindowA("TclSocket", "TclSocket", + WS_TILED, 0, 0, 0, 0, NULL, NULL, class.hInstance, NULL); + } else { + winSock.hwnd = NULL; + } + if (winSock.hwnd == NULL) { + TclWinConvertError(GetLastError()); + (*winSock.WSACleanup)(); + goto unloadLibrary; + } } /* - * Create the async notification window with a new class. We - * must create a new class to avoid a Windows 95 bug that causes - * us to get the wrong message number for socket events if the - * message window is a subclass of a static control. + * Check for per-thread initialization. */ - class.style = 0; - class.cbClsExtra = 0; - class.cbWndExtra = 0; - class.hInstance = TclWinGetTclInstance(); - class.hbrBackground = NULL; - class.lpszMenuName = NULL; - class.lpszClassName = "TclSocket"; - class.lpfnWndProc = SocketProc; - class.hIcon = NULL; - class.hCursor = NULL; - - if (RegisterClass(&class)) { - winSock.hwnd = CreateWindow("TclSocket", "TclSocket", WS_TILED, 0, 0, - 0, 0, NULL, NULL, class.hInstance, NULL); - } else { - winSock.hwnd = NULL; - } - if (winSock.hwnd == NULL) { - TclWinConvertError(GetLastError()); - (*winSock.WSACleanup)(); - goto unloadLibrary; + if (tsdPtr == NULL) { + tsdPtr = TCL_TSD_INIT(&dataKey); + tsdPtr->socketList = NULL; + Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); + Tcl_CreateThreadExitHandler(SocketThreadExitHandler, NULL); } - Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); return; unloadLibrary: @@ -420,6 +442,34 @@ unloadLibrary: /* *---------------------------------------------------------------------- * + * SocketsEnabled -- + * + * Check that the WinSock DLL is loaded and ready. + * + * Results: + * 1 if it is. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +SocketsEnabled() +{ + int enabled; + Tcl_MutexLock(&socketMutex); + enabled = (winSock.hInstance != NULL); + Tcl_MutexUnlock(&socketMutex); + return enabled; +} + + +/* + *---------------------------------------------------------------------- + * * SocketExitHandler -- * * Callback invoked during exit clean up to delete the socket @@ -439,22 +489,48 @@ static void SocketExitHandler(clientData) ClientData clientData; /* Not used. */ { + Tcl_MutexLock(&socketMutex); if (winSock.hInstance) { DestroyWindow(winSock.hwnd); - UnregisterClass("TclSocket", TclWinGetTclInstance()); + UnregisterClassA("TclSocket", TclWinGetTclInstance()); (*winSock.WSACleanup)(); FreeLibrary(winSock.hInstance); winSock.hInstance = NULL; } - Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL); initialized = 0; hostnameInitialized = 0; + Tcl_MutexUnlock(&socketMutex); +} + +/* + *---------------------------------------------------------------------- + * + * SocketThreadExitHandler -- + * + * Callback invoked during thread clean up to delete the socket + * event source. + * + * Results: + * None. + * + * Side effects: + * Delete the event source. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static void +SocketThreadExitHandler(clientData) + ClientData clientData; /* Not used. */ +{ + Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL); } /* *---------------------------------------------------------------------- * - * TclHasSockets -- + * TclpHasSockets -- * * This function determines whether sockets are available on the * current system and returns an error in interp if they are not. @@ -471,14 +547,14 @@ SocketExitHandler(clientData) */ int -TclHasSockets(interp) +TclpHasSockets(interp) Tcl_Interp *interp; { - if (!initialized) { - InitSockets(); - } - - if (winSock.hInstance != NULL) { + Tcl_MutexLock(&socketMutex); + InitSockets(); + Tcl_MutexUnlock(&socketMutex); + + if (SocketsEnabled()) { return TCL_OK; } if (interp != NULL) { @@ -512,6 +588,7 @@ SocketSetupProc(data, flags) { SocketInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; @@ -521,7 +598,8 @@ SocketSetupProc(data, flags) * Check to see if there is a ready socket. If so, poll. */ - for (infoPtr = socketList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->socketList; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (infoPtr->readyEvents & infoPtr->watchEvents) { Tcl_SetMaxBlockTime(&blockTime); break; @@ -553,6 +631,7 @@ SocketCheckProc(data, flags) { SocketInfo *infoPtr; SocketEvent *evPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; @@ -564,7 +643,8 @@ SocketCheckProc(data, flags) * events). */ - for (infoPtr = socketList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->socketList; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if ((infoPtr->readyEvents & infoPtr->watchEvents) && !(infoPtr->flags & SOCKET_PENDING)) { infoPtr->flags |= SOCKET_PENDING; @@ -608,6 +688,7 @@ SocketEventProc(evPtr, flags) int mask = 0; u_long nBytes; int status, events; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; @@ -617,7 +698,8 @@ SocketEventProc(evPtr, flags) * Find the specified socket on the socket list. */ - for (infoPtr = socketList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->socketList; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (infoPtr->socket == eventPtr->socket) { break; } @@ -670,9 +752,10 @@ SocketEventProc(evPtr, flags) * could have consumed the data in the meantime. */ + nBytes = 0; status = (*winSock.ioctlsocket)(infoPtr->socket, FIONREAD, &nBytes); - if (status != SOCKET_ERROR && nBytes > 0) { + if ((status != SOCKET_ERROR) && (nBytes > 0)) { mask |= TCL_READABLE; } else { /* @@ -762,6 +845,7 @@ TcpCloseProc(instanceData, interp) SocketInfo *infoPtr = (SocketInfo *) instanceData; SocketInfo **nextPtrPtr; int errorCode = 0; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Check that WinSock is initialized; do not call it if not, to @@ -770,7 +854,7 @@ TcpCloseProc(instanceData, interp) * use sockets. */ - if (winSock.hInstance != NULL) { + if (SocketsEnabled()) { /* * Clean up the OS socket handle. The default Windows setting @@ -788,13 +872,14 @@ TcpCloseProc(instanceData, interp) * Remove the socket from socketList. */ - for (nextPtrPtr = &socketList; (*nextPtrPtr) != NULL; + for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == infoPtr) { (*nextPtrPtr) = infoPtr->nextPtr; break; } } + ckfree((char *) infoPtr); return errorCode; } @@ -821,6 +906,7 @@ NewSocketInfo(socket) SOCKET socket; { SocketInfo *infoPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); infoPtr = (SocketInfo *) ckalloc((unsigned) sizeof(SocketInfo)); infoPtr->socket = socket; @@ -830,8 +916,10 @@ NewSocketInfo(socket) infoPtr->selectEvents = 0; infoPtr->acceptProc = NULL; infoPtr->lastError = 0; - infoPtr->nextPtr = socketList; - socketList = infoPtr; + + infoPtr->nextPtr = tsdPtr->socketList; + tsdPtr->socketList = infoPtr; + return infoPtr; } @@ -878,11 +966,11 @@ CreateSocket(interp, port, host, server, myaddr, myport, async) * handler for WinSock ran before other exit handlers that want to * use sockets. */ - - if (winSock.hInstance == NULL) { + + if (!SocketsEnabled()) { return NULL; } - + if (! CreateSocketAddress(&sockaddr, host, port)) { goto error; } @@ -1056,11 +1144,11 @@ CreateSocketAddress(sockaddrPtr, host, port) * use sockets. */ - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { Tcl_SetErrno(EFAULT); return 0; } - + (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); sockaddrPtr->sin_family = AF_INET; sockaddrPtr->sin_port = (*winSock.htons)((short) (port & 0xFFFF)); @@ -1209,9 +1297,9 @@ Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async) * client socket asynchronously. */ { SocketInfo *infoPtr; - char channelName[20]; + char channelName[16 + TCL_INTEGER_SPACE]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } @@ -1224,7 +1312,7 @@ Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async) return NULL; } - sprintf(channelName, "sock%d", infoPtr->socket); + wsprintfA(channelName, "sock%d", infoPtr->socket); infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE)); @@ -1264,9 +1352,9 @@ Tcl_MakeTcpClientChannel(sock) ClientData sock; /* The socket to wrap up into a channel. */ { SocketInfo *infoPtr; - char channelName[20]; + char channelName[16 + TCL_INTEGER_SPACE]; - if (TclHasSockets(NULL) != TCL_OK) { + if (TclpHasSockets(NULL) != TCL_OK) { return NULL; } @@ -1286,7 +1374,7 @@ Tcl_MakeTcpClientChannel(sock) (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd, SOCKET_MESSAGE, infoPtr->selectEvents); - sprintf(channelName, "sock%d", infoPtr->socket); + wsprintfA(channelName, "sock%d", infoPtr->socket); infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE)); Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto crlf"); @@ -1321,9 +1409,9 @@ Tcl_OpenTcpServer(interp, port, host, acceptProc, acceptProcData) ClientData acceptProcData; /* Data for the callback. */ { SocketInfo *infoPtr; - char channelName[20]; + char channelName[16 + TCL_INTEGER_SPACE]; - if (TclHasSockets(interp) != TCL_OK) { + if (TclpHasSockets(interp) != TCL_OK) { return NULL; } @@ -1339,7 +1427,7 @@ Tcl_OpenTcpServer(interp, port, host, acceptProc, acceptProcData) infoPtr->acceptProc = acceptProc; infoPtr->acceptProcData = acceptProcData; - sprintf(channelName, "sock%d", infoPtr->socket); + wsprintfA(channelName, "sock%d", infoPtr->socket); infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, (ClientData) infoPtr, 0); @@ -1377,7 +1465,7 @@ TcpAccept(infoPtr) SocketInfo *newInfoPtr; struct sockaddr_in addr; int len; - char channelName[20]; + char channelName[16 + TCL_INTEGER_SPACE]; /* * Accept the incoming connection request. @@ -1413,7 +1501,7 @@ TcpAccept(infoPtr) (void) (*winSock.WSAAsyncSelect)(newInfoPtr->socket, winSock.hwnd, SOCKET_MESSAGE, newInfoPtr->selectEvents); - sprintf(channelName, "sock%d", newInfoPtr->socket); + wsprintfA(channelName, "sock%d", newInfoPtr->socket); newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, (ClientData) newInfoPtr, (TCL_READABLE | TCL_WRITABLE)); if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation", @@ -1475,7 +1563,7 @@ TcpInputProc(instanceData, buf, toRead, errorCodePtr) * use sockets. */ - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } @@ -1596,11 +1684,11 @@ TcpOutputProc(instanceData, buf, toWrite, errorCodePtr) * use sockets. */ - if (winSock.hInstance == NULL) { + if (! SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } - + /* * Check to see if the socket is connected before trying to write. */ @@ -1698,7 +1786,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr) SOCKET sock; int size = sizeof(struct sockaddr_in); size_t len = 0; - char buf[128]; + char buf[TCL_INTEGER_SPACE]; /* * Check that WinSock is initialized; do not call it if not, to @@ -1707,7 +1795,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr) * use sockets. */ - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { if (interp) { Tcl_AppendResult(interp, "winsock is not initialized", NULL); } @@ -1740,7 +1828,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr) Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(peername.sin_addr)); } - sprintf(buf, "%d", (*winSock.ntohs)(peername.sin_port)); + TclFormatInt(buf, (*winSock.ntohs)(peername.sin_port)); Tcl_DStringAppendElement(dsPtr, buf); if (len == 0) { Tcl_DStringEndSublist(dsPtr); @@ -1786,7 +1874,7 @@ TcpGetOptionProc(instanceData, interp, optionName, dsPtr) Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(sockname.sin_addr)); } - sprintf(buf, "%d", (*winSock.ntohs)(sockname.sin_port)); + TclFormatInt(buf, (*winSock.ntohs)(sockname.sin_port)); Tcl_DStringAppendElement(dsPtr, buf); if (len == 0) { Tcl_DStringEndSublist(dsPtr); @@ -1919,6 +2007,7 @@ SocketProc(hwnd, message, wParam, lParam) int event, error; SOCKET socket; SocketInfo *infoPtr; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (message != SOCKET_MESSAGE) { return DefWindowProc(hwnd, message, wParam, lParam); @@ -1933,7 +2022,8 @@ SocketProc(hwnd, message, wParam, lParam) * eventState flag. */ - for (infoPtr = socketList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + for (infoPtr = tsdPtr->socketList; infoPtr != NULL; + infoPtr = infoPtr->nextPtr) { if (infoPtr->socket == socket) { /* * Update the socket state. @@ -1997,29 +2087,42 @@ char * Tcl_GetHostName() { DWORD length; - char *p; + WCHAR wbuf[MAX_COMPUTERNAME_LENGTH + 1]; + Tcl_MutexLock(&socketMutex); if (hostnameInitialized) { + Tcl_MutexUnlock(&socketMutex); return hostname; } - if (TclHasSockets(NULL) == TCL_OK) { + if (TclpHasSockets(NULL) == TCL_OK) { + /* + * INTL: bug + */ + if ((*winSock.gethostname)(hostname, sizeof(hostname)) == 0) { hostnameInitialized = 1; + Tcl_MutexUnlock(&socketMutex); return hostname; } } length = sizeof(hostname); - if (GetComputerName(hostname, &length) != 0) { - for (p = hostname; *p != '\0'; p++) { - if (isupper(*((unsigned char *) p))) { - *p = (char) tolower(*((unsigned char *) p)); - } - } + if ((*tclWinProcs->getComputerNameProc)(wbuf, &length) != 0) { + /* + * Convert string from native to UTF then change to lowercase. + */ + + Tcl_DString ds; + + lstrcpynA(hostname, Tcl_WinTCharToUtf((TCHAR *) wbuf, -1, &ds), + sizeof(hostname)); + Tcl_DStringFree(&ds); + Tcl_UtfToLower(hostname); } else { hostname[0] = '\0'; } hostnameInitialized = 1; + Tcl_MutexUnlock(&socketMutex); return hostname; } @@ -2053,7 +2156,7 @@ TclWinGetSockOpt(SOCKET s, int level, int optname, char FAR * optval, * use sockets. */ - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { return SOCKET_ERROR; } @@ -2070,8 +2173,7 @@ TclWinSetSockOpt(SOCKET s, int level, int optname, const char FAR * optval, * handler for WinSock ran before other exit handlers that want to * use sockets. */ - - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { return SOCKET_ERROR; } @@ -2088,7 +2190,7 @@ TclWinNToHS(u_short netshort) * use sockets. */ - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { return (u_short) -1; } @@ -2104,8 +2206,7 @@ TclWinGetServByName(const char FAR * name, const char FAR * proto) * handler for WinSock ran before other exit handlers that want to * use sockets. */ - - if (winSock.hInstance == NULL) { + if (!SocketsEnabled()) { return (struct servent FAR *) NULL; } |