summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2020-08-10 16:16:36 (GMT)
committersebres <sebres@users.sourceforge.net>2020-08-10 16:16:36 (GMT)
commit3cd49200d7d04605090a8dbaba57a127b785ceb5 (patch)
treeb3c58fe0531ddd88a34f301d03a7ddda4f67c753 /win
parenta15ea81906fdac4ed3868e9866d07a8ca4c2354c (diff)
downloadtcl-3cd49200d7d04605090a8dbaba57a127b785ceb5.zip
tcl-3cd49200d7d04605090a8dbaba57a127b785ceb5.tar.gz
tcl-3cd49200d7d04605090a8dbaba57a127b785ceb5.tar.bz2
windows: replace gethostbyname with getaddrinfo (gethostbyname can hang sporadically, closes [7cf7cce423]);
corresponding to MS (https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-gethostbyname): Developers creating Windows Sockets 2 applications are urged to use the getaddrinfo function instead of gethostbyname
Diffstat (limited to 'win')
-rw-r--r--win/tclWinSock.c102
1 files changed, 58 insertions, 44 deletions
diff --git a/win/tclWinSock.c b/win/tclWinSock.c
index 882aa4a..11632c4 100644
--- a/win/tclWinSock.c
+++ b/win/tclWinSock.c
@@ -45,6 +45,8 @@
* SocketCheckProc().
*/
+#include <winsock2.h>
+#include <ws2tcpip.h>
#include "tclWinInt.h"
#ifdef _MSC_VER
@@ -187,8 +189,8 @@ static WNDCLASS windowClass;
static SocketInfo * CreateSocket(Tcl_Interp *interp, int port,
const char *host, int server, const char *myaddr,
int myport, int async);
-static int CreateSocketAddress(LPSOCKADDR_IN sockaddrPtr,
- const char *host, int port);
+static int CreateSocketAddress(struct sockaddr_in *sockaddrPtr,
+ const char *host, int port, int willBind);
static void InitSockets(void);
static SocketInfo * NewSocketInfo(SOCKET socket);
static void SocketExitHandler(ClientData clientData);
@@ -917,8 +919,8 @@ CreateSocket(
* asynchronously. */
{
u_long flag = 1; /* Indicates nonblocking mode. */
- SOCKADDR_IN sockaddr; /* Socket address */
- SOCKADDR_IN mysockaddr; /* Socket address for client */
+ struct sockaddr_in sockaddr; /* Socket address */
+ struct sockaddr_in mysockaddr; /* Socket address for client */
SOCKET sock = INVALID_SOCKET;
SocketInfo *infoPtr=NULL; /* The returned value. */
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
@@ -934,11 +936,11 @@ CreateSocket(
return NULL;
}
- if (!CreateSocketAddress(&sockaddr, host, port)) {
+ if (!CreateSocketAddress(&sockaddr, host, port, server)) {
goto error;
}
if ((myaddr != NULL || myport != 0) &&
- !CreateSocketAddress(&mysockaddr, myaddr, myport)) {
+ !CreateSocketAddress(&mysockaddr, myaddr, myport, 1)) {
goto error;
}
@@ -1149,55 +1151,67 @@ static int
CreateSocketAddress(
LPSOCKADDR_IN sockaddrPtr, /* Socket address */
const char *host, /* Host. NULL implies INADDR_ANY */
- int port) /* Port number */
+ int port, /* Port number */
+ int willBind) /* Is this an address to bind() to or
+ * to connect() to? */
{
- struct hostent *hostent; /* Host database entry */
- struct in_addr addr; /* For 64/32 bit madness */
+ struct addrinfo hints, *resPtr = NULL;
+ char *native;
+ Tcl_DString ds;
+ int result;
+
+ if (host == NULL) {
+ sockaddrPtr->sin_family = AF_INET;
+ sockaddrPtr->sin_addr.s_addr = INADDR_ANY;
+ addPort:
+ sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
+ return 1;
+ }
+
+ (void) memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ if (willBind) {
+ hints.ai_flags |= AI_PASSIVE;
+ }
/*
- * Check that WinSock is initialized; do not call it if not, to prevent
- * system crashes. This can happen at exit time if the exit handler for
- * WinSock ran before other exit handlers that want to use sockets.
+ * Note that getaddrinfo() *is* thread-safe. If a platform doesn't get
+ * that right, it shouldn't use this part of the code.
*/
- if (!SocketsEnabled()) {
- Tcl_SetErrno(EFAULT);
- return 0;
+ native = Tcl_UtfToExternalDString(NULL, host, -1, &ds);
+ result = getaddrinfo(native, NULL, &hints, &resPtr);
+ Tcl_DStringFree(&ds);
+ if (result == 0) {
+ memcpy(sockaddrPtr, resPtr->ai_addr, sizeof(struct sockaddr_in));
+ freeaddrinfo(resPtr);
+ goto addPort;
}
- ZeroMemory(sockaddrPtr, sizeof(SOCKADDR_IN));
- sockaddrPtr->sin_family = AF_INET;
- sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
- if (host == NULL) {
- addr.s_addr = INADDR_ANY;
- } else {
- addr.s_addr = inet_addr(host);
- if (addr.s_addr == INADDR_NONE) {
- hostent = gethostbyname(host);
- if (hostent != NULL) {
- memcpy(&addr, hostent->h_addr, (size_t) hostent->h_length);
- } else {
+ /*
+ * errno corresponding result ...
+ */
+
+ switch (result) {
+ case EAI_NONAME:
+ case EAI_SERVICE:
+#if defined(EAI_ADDRFAMILY) && EAI_ADDRFAMILY != EAI_NONAME
+ case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+ case EAI_NODATA:
+#endif
#ifdef EHOSTUNREACH
- Tcl_SetErrno(EHOSTUNREACH);
-#else
-#ifdef ENXIO
- Tcl_SetErrno(ENXIO);
+ Tcl_SetErrno(EHOSTUNREACH);
+ return 0;
#endif
+ default:
+#ifdef ENXIO
+ Tcl_SetErrno(ENXIO);
#endif
- return 0; /* Error. */
- }
- }
+ return 0;
}
-
- /*
- * NOTE: On 64 bit machines the assignment below is rumored to not do the
- * right thing. Please report errors related to this if you observe
- * incorrect behavior on 64 bit machines such as DEC Alphas. Should we
- * modify this code to do an explicit memcpy?
- */
-
- sockaddrPtr->sin_addr.s_addr = addr.s_addr;
- return 1; /* Success. */
}
/*