summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclIOCmd.c40
-rw-r--r--generic/tclIOSock.c27
-rw-r--r--unix/tclUnixSock.c276
-rw-r--r--win/tclWinSock.c578
4 files changed, 573 insertions, 348 deletions
diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c
index 1bd3fe7..e52200d 100644
--- a/generic/tclIOCmd.c
+++ b/generic/tclIOCmd.c
@@ -1618,19 +1618,34 @@ Tcl_SocketObjCmd(
return TCL_ERROR;
}
- // Set the options to their default value if the user didn't override their
- // value.
- if (reusep == -1) reusep = 0;
- if (reusea == -1) reusea = 1;
+ /*
+ * Set the options to their default value if the user didn't override
+ * their value.
+ */
- // Build the bitset with the flags values.
- if (reusea)
+ if (reusep == -1) {
+ reusep = 0;
+ }
+ if (reusea == -1) {
+ reusea = 1;
+ }
+
+ /*
+ * Build the bitset with the flags values.
+ */
+
+ if (reusea) {
flags |= TCL_TCPSERVER_REUSEADDR;
- if (reusep)
+ }
+ if (reusep) {
flags |= TCL_TCPSERVER_REUSEPORT;
+ }
+
+ /*
+ * All the arguments should have been parsed by now, 'a' points to the
+ * last one, the port number.
+ */
- // All the arguments should have been parsed by now, 'a' points to the last
- // one, the port number.
if (a != objc-1) {
goto wrongNumArgs;
}
@@ -1638,15 +1653,14 @@ Tcl_SocketObjCmd(
port = TclGetString(objv[a]);
if (server) {
- AcceptCallback *acceptCallbackPtr =
- ckalloc(sizeof(AcceptCallback));
+ AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback));
Tcl_IncrRefCount(script);
acceptCallbackPtr->script = script;
acceptCallbackPtr->interp = interp;
- chan = Tcl_OpenTcpServerEx(interp, port, host, flags, AcceptCallbackProc,
- acceptCallbackPtr);
+ chan = Tcl_OpenTcpServerEx(interp, port, host, flags,
+ AcceptCallbackProc, acceptCallbackPtr);
if (chan == NULL) {
Tcl_DecrRefCount(script);
ckfree(acceptCallbackPtr);
diff --git a/generic/tclIOSock.c b/generic/tclIOSock.c
index 8ad268a..82d2fc1 100644
--- a/generic/tclIOSock.c
+++ b/generic/tclIOSock.c
@@ -12,7 +12,9 @@
#include "tclInt.h"
#if defined(_WIN32) && defined(UNICODE)
-/* On Windows, we need to do proper Unicode->UTF-8 conversion. */
+/*
+ * On Windows, we need to do proper Unicode->UTF-8 conversion.
+ */
typedef struct ThreadSpecificData {
int initialized;
@@ -21,7 +23,10 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
#undef gai_strerror
-static const char *gai_strerror(int code) {
+static const char *
+gai_strerror(
+ int code)
+{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->initialized) {
@@ -126,7 +131,7 @@ TclSockMinimumBuffers(
}
len = sizeof(int);
getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
- (char *) &current, &len);
+ (char *) &current, &len);
if (current < size) {
len = sizeof(int);
setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF,
@@ -215,7 +220,7 @@ TclCreateSocketAddress(
* We found some problems when using AI_ADDRCONFIG, e.g. on systems that
* have no networking besides the loopback interface and want to resolve
* localhost. See [Bugs 3385024, 3382419, 3382431]. As the advantage of
- * using AI_ADDRCONFIG in situations where it works, is probably low,
+ * using AI_ADDRCONFIG is probably low even in situations where it works,
* we'll leave it out for now. After all, it is just an optimisation.
*
* Missing on: OpenBSD, NetBSD.
@@ -300,16 +305,20 @@ TclCreateSocketAddress(
*
*----------------------------------------------------------------------
*/
-Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port,
- const char *host, Tcl_TcpAcceptProc *acceptProc,
- ClientData callbackData)
+
+Tcl_Channel
+Tcl_OpenTcpServer(
+ Tcl_Interp *interp,
+ int port,
+ const char *host,
+ Tcl_TcpAcceptProc *acceptProc,
+ ClientData callbackData)
{
char portbuf[TCL_INTEGER_SPACE];
TclFormatInt(portbuf, port);
-
return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR,
- acceptProc, callbackData);
+ acceptProc, callbackData);
}
/*
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 9387d05..a64157e 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -117,8 +117,7 @@ struct TcpState {
* Static routines for this file:
*/
-static int TcpConnect(Tcl_Interp *interp,
- TcpState *state);
+static int TcpConnect(Tcl_Interp *interp, TcpState *state);
static void TcpAccept(ClientData data, int mask);
static int TcpBlockModeProc(ClientData data, int mode);
static int TcpCloseProc(ClientData instanceData,
@@ -173,21 +172,24 @@ static ProcessGlobalValue hostName =
#if 0
/* printf debugging */
-void printaddrinfo(struct addrinfo *addrlist, char *prefix)
+void
+printaddrinfo(
+ struct addrinfo *addrlist,
+ char *prefix)
{
char host[NI_MAXHOST], port[NI_MAXSERV];
struct addrinfo *ai;
+
for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
getnameinfo(ai->ai_addr, ai->ai_addrlen,
- host, sizeof(host),
- port, sizeof(port),
- NI_NUMERICHOST|NI_NUMERICSERV);
+ host, sizeof(host), port, sizeof(port),
+ NI_NUMERICHOST|NI_NUMERICSERV);
fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
}
}
#endif
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* InitializeHostName --
*
@@ -197,7 +199,7 @@ void printaddrinfo(struct addrinfo *addrlist, char *prefix)
* Results:
* None.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
static void
@@ -276,7 +278,7 @@ InitializeHostName(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* Tcl_GetHostName --
*
@@ -290,7 +292,7 @@ InitializeHostName(
* Side effects:
* Caches the name to return for future calls.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
const char *
@@ -300,7 +302,7 @@ Tcl_GetHostName(void)
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TclpHasSockets --
*
@@ -312,7 +314,7 @@ Tcl_GetHostName(void)
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
int
@@ -323,7 +325,7 @@ TclpHasSockets(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TclpFinalizeSockets --
*
@@ -335,7 +337,7 @@ TclpHasSockets(
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
void
@@ -345,7 +347,7 @@ TclpFinalizeSockets(void)
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TcpBlockModeProc --
*
@@ -358,7 +360,7 @@ TclpFinalizeSockets(void)
* Side effects:
* Sets the device into blocking or nonblocking mode.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -387,33 +389,32 @@ TcpBlockModeProc(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* WaitForConnect --
*
- * Check the state of an async connect process. If a connection
- * attempt terminated, process it, which may finalize it or may
- * start the next attempt. If a connect error occures, it is saved
- * in statePtr->connectError to be reported by 'fconfigure -error'.
+ * Check the state of an async connect process. If a connection attempt
+ * terminated, process it, which may finalize it or may start the next
+ * attempt. If a connect error occures, it is saved in
+ * statePtr->connectError to be reported by 'fconfigure -error'.
*
* There are two modes of operation, defined by errorCodePtr:
- * * non-NULL: Called by explicite read/write command. block if
+ * * non-NULL: Called by explicite read/write command. Blocks if the
* socket is blocking.
* May return two error codes:
* * EWOULDBLOCK: if connect is still in progress
- * * ENOTCONN: if connect failed. This would be the error
- * message of a rect or sendto syscall so this is
- * emulated here.
- * * NULL: Called by a backround operation. Do not block and
- * don't return any error code.
+ * * ENOTCONN: if connect failed. This would be the error message
+ * of a rect or sendto syscall so this is emulated here.
+ * * NULL: Called by a backround operation. Do not block and do not
+ * return any error code.
*
* Results:
- * 0 if the connection has completed, -1 if still in progress
- * or there is an error.
+ * 0 if the connection has completed, -1 if still in progress or there is
+ * an error.
*
* Side effects:
- * Processes socket events off the system queue.
- * May process asynchroneous connect.
+ * Processes socket events off the system queue. May process
+ * asynchroneous connects.
*
*----------------------------------------------------------------------
*/
@@ -426,8 +427,8 @@ WaitForConnect(
int timeout;
/*
- * Check if an async connect failed already and error reporting is demanded,
- * return the error ENOTCONN
+ * Check if an async connect failed already and error reporting is
+ * demanded, return the error ENOTCONN
*/
if (errorCodePtr != NULL && (statePtr->flags & TCP_ASYNC_FAILED)) {
@@ -450,11 +451,14 @@ WaitForConnect(
}
do {
if (TclUnixWaitForFile(statePtr->fds.fd,
- TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
+ TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
TcpConnect(NULL, statePtr);
}
- /* Do this only once in the nonblocking case and repeat it until the
- * socket is final when blocking */
+
+ /*
+ * Do this only once in the nonblocking case and repeat it until the
+ * socket is final when blocking.
+ */
} while (timeout == -1 && statePtr->flags & TCP_ASYNC_CONNECT);
if (errorCodePtr != NULL) {
@@ -615,6 +619,7 @@ TcpCloseProc(
fds = statePtr->fds.next;
while (fds != NULL) {
TcpFdList *next = fds->next;
+
ckfree(fds);
fds = next;
}
@@ -685,10 +690,9 @@ TcpClose2Proc(
*
* TcpHostPortList --
*
- * This function is called by the -gethostname and -getpeername
- * switches of TcpGetOptionProc() to add three list elements
- * with the textual representation of the given address to the
- * given DString.
+ * This function is called by the -gethostname and -getpeername switches
+ * of TcpGetOptionProc() to add three list elements with the textual
+ * representation of the given address to the given DString.
*
* Results:
* None.
@@ -709,22 +713,22 @@ TcpHostPortList(
char host[NI_MAXHOST], nhost[NI_MAXHOST], nport[NI_MAXSERV];
int flags = 0;
- getnameinfo(&addr.sa, salen,
- nhost, sizeof(nhost), nport, sizeof(nport),
- NI_NUMERICHOST | NI_NUMERICSERV);
+ getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport),
+ NI_NUMERICHOST | NI_NUMERICSERV);
Tcl_DStringAppendElement(dsPtr, nhost);
+
/*
- * We don't want to resolve INADDR_ANY and sin6addr_any; they
- * can sometimes cause problems (and never have a name).
+ * We don't want to resolve INADDR_ANY and sin6addr_any; they can
+ * sometimes cause problems (and never have a name).
*/
+
if (addr.sa.sa_family == AF_INET) {
if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
flags |= NI_NUMERICHOST;
}
#ifndef NEED_FAKE_RFC2553
} else if (addr.sa.sa_family == AF_INET6) {
- if ((IN6_ARE_ADDR_EQUAL(&addr.sa6.sin6_addr,
- &in6addr_any))
+ if ((IN6_ARE_ADDR_EQUAL(&addr.sa6.sin6_addr, &in6addr_any))
|| (IN6_IS_ADDR_V4MAPPED(&addr.sa6.sin6_addr) &&
addr.sa6.sin6_addr.s6_addr[12] == 0 &&
addr.sa6.sin6_addr.s6_addr[13] == 0 &&
@@ -734,15 +738,27 @@ TcpHostPortList(
}
#endif /* NEED_FAKE_RFC2553 */
}
- /* Check if reverse DNS has been switched off globally */
- if (interp != NULL && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
+
+ /*
+ * Check if reverse DNS has been switched off globally.
+ */
+
+ if (interp != NULL &&
+ Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
flags |= NI_NUMERICHOST;
}
- if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0, flags) == 0) {
- /* Reverse mapping worked */
+ if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0,
+ flags) == 0) {
+ /*
+ * Reverse mapping worked.
+ */
+
Tcl_DStringAppendElement(dsPtr, host);
} else {
- /* Reverse mappong failed - use the numeric rep once more */
+ /*
+ * Reverse mapping failed - use the numeric rep once more.
+ */
+
Tcl_DStringAppendElement(dsPtr, nhost);
}
Tcl_DStringAppendElement(dsPtr, nport);
@@ -793,15 +809,19 @@ TcpGetOptionProc(
socklen_t optlen = sizeof(int);
if (statePtr->flags & TCP_ASYNC_CONNECT) {
- /* Suppress errors as long as we are not done */
+ /*
+ * Suppress errors as long as we are not done.
+ */
+
errno = 0;
} else if (statePtr->connectError != 0) {
errno = statePtr->connectError;
statePtr->connectError = 0;
} else {
int err;
- getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &optlen);
+
+ getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
+ &optlen);
errno = err;
}
if (errno != 0) {
@@ -814,7 +834,7 @@ TcpGetOptionProc(
(strncmp(optionName, "-connecting", len) == 0)) {
Tcl_DStringAppend(dsPtr,
- (statePtr->flags & TCP_ASYNC_CONNECT) ? "1" : "0", -1);
+ (statePtr->flags & TCP_ASYNC_CONNECT) ? "1" : "0", -1);
return TCL_OK;
}
@@ -823,10 +843,11 @@ TcpGetOptionProc(
address peername;
socklen_t size = sizeof(peername);
- if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
+ if (statePtr->flags & TCP_ASYNC_CONNECT) {
/*
* In async connect output an empty string
*/
+
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringAppendElement(dsPtr, "");
@@ -837,6 +858,7 @@ TcpGetOptionProc(
/*
* Peername fetch succeeded - output list
*/
+
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringStartSublist(dsPtr);
@@ -876,11 +898,12 @@ TcpGetOptionProc(
Tcl_DStringAppendElement(dsPtr, "-sockname");
Tcl_DStringStartSublist(dsPtr);
}
- if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
+ if (statePtr->flags & TCP_ASYNC_CONNECT) {
/*
* In async connect output an empty string
*/
- found = 1;
+
+ found = 1;
} else {
for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
size = sizeof(sockname);
@@ -905,14 +928,15 @@ TcpGetOptionProc(
}
if (len > 0) {
- return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname");
+ return Tcl_BadChannelOption(interp, optionName,
+ "connecting peername sockname");
}
return TCL_OK;
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TcpWatchProc --
*
@@ -925,7 +949,7 @@ TcpGetOptionProc(
* Sets up the notifier so that a future event on the channel will be
* seen by Tcl.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
static void
@@ -938,17 +962,17 @@ WrapNotify(
if (newmask == 0) {
/*
- * There was no overlap between the states the channel is
- * interested in notifications for, and the states that are
- * reported present on the file descriptor by select(). The
- * only way that can happen is when the channel is interested
- * in a writable condition, and only a readable state is reported
- * present (see TcpWatchProc() below). In that case, signal back
- * to the caller the writable state, which is really an error
- * condition. As an extra check on that assumption, check for
- * a non-zero value of errno before reporting an artificial
+ * There was no overlap between the states the channel is interested
+ * in notifications for, and the states that are reported present on
+ * the file descriptor by select(). The only way that can happen is
+ * when the channel is interested in a writable condition, and only a
+ * readable state is reported present (see TcpWatchProc() below). In
+ * that case, signal back to the caller the writable state, which is
+ * really an error condition. As an extra check on that assumption,
+ * check for a non-zero value of errno before reporting an artificial
* writable state.
*/
+
if (errno == 0) {
return;
}
@@ -972,33 +996,36 @@ TcpWatchProc(
* be readable or writable at the Tcl level. This keeps Tcl scripts
* from interfering with the -accept behavior (bug #3394732).
*/
+
return;
}
if (statePtr->flags & TCP_ASYNC_PENDING) {
- /* Async sockets use a FileHandler internally while connecting, so we
- * need to cache this request until the connection has succeeded. */
+ /*
+ * Async sockets use a FileHandler internally while connecting, so we
+ * need to cache this request until the connection has succeeded.
+ */
+
statePtr->filehandlers = mask;
} else if (mask) {
/*
- * Whether it is a bug or feature or otherwise, it is a fact
- * of life that on at least some Linux kernels select() fails
- * to report that a socket file descriptor is writable when
- * the other end of the socket is closed. This is in contrast
- * to the guarantees Tcl makes that its channels become
- * writable and fire writable events on an error conditon.
- * This has caused a leak of file descriptors in a state of
+ * Whether it is a bug or feature or otherwise, it is a fact of life
+ * that on at least some Linux kernels select() fails to report that a
+ * socket file descriptor is writable when the other end of the socket
+ * is closed. This is in contrast to the guarantees Tcl makes that
+ * its channels become writable and fire writable events on an error
+ * conditon. This has caused a leak of file descriptors in a state of
* background flushing. See Tcl ticket 1758a0b603.
*
- * As a workaround, when our caller indicates an interest in
- * writable notifications, we must tell the notifier built
- * around select() that we are interested in the readable state
- * of the file descriptor as well, as that is the only reliable
- * means to get notified of error conditions. Then it is the
- * task of WrapNotify() above to untangle the meaning of these
- * channel states and report the chan events as best it can.
- * We save a copy of the mask passed in to assist with that.
+ * As a workaround, when our caller indicates an interest in writable
+ * notifications, we must tell the notifier built around select() that
+ * we are interested in the readable state of the file descriptor as
+ * well, as that is the only reliable means to get notified of error
+ * conditions. Then it is the task of WrapNotify() above to untangle
+ * the meaning of these channel states and report the chan events as
+ * best it can. We save a copy of the mask passed in to assist with
+ * that.
*/
statePtr->interest = mask;
@@ -1010,7 +1037,7 @@ TcpWatchProc(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TcpGetHandleProc --
*
@@ -1024,7 +1051,7 @@ TcpWatchProc(
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -1041,16 +1068,17 @@ TcpGetHandleProc(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TcpAsyncCallback --
*
- * Called by the event handler that TcpConnect sets up
- * internally for [socket -async] to get notified when the
- * asyncronous connection attempt has succeeded or failed.
+ * Called by the event handler that TcpConnect sets up internally for
+ * [socket -async] to get notified when the asyncronous connection
+ * attempt has succeeded or failed.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
+
static void
TcpAsyncCallback(
ClientData clientData, /* The socket state. */
@@ -1062,7 +1090,7 @@ TcpAsyncCallback(
}
/*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*
* TcpConnect --
*
@@ -1088,7 +1116,7 @@ TcpAsyncCallback(
* return and the loops resume as if they had never been interrupted.
* For syncronously connecting sockets, the loops work the usual way.
*
- *----------------------------------------------------------------------
+ * ----------------------------------------------------------------------
*/
static int
@@ -1108,7 +1136,8 @@ TcpConnect(
for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
statePtr->addr = statePtr->addr->ai_next) {
- for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL;
+ for (statePtr->myaddr = statePtr->myaddrlist;
+ statePtr->myaddr != NULL;
statePtr->myaddr = statePtr->myaddr->ai_next) {
int reuseaddr = 1;
@@ -1132,7 +1161,8 @@ TcpConnect(
errno = 0;
}
- statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM, 0);
+ statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM,
+ 0);
if (statePtr->fds.fd < 0) {
continue;
}
@@ -1151,14 +1181,18 @@ TcpConnect(
TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);
if (async) {
- ret = TclUnixSetBlockingMode(statePtr->fds.fd,TCL_MODE_NONBLOCKING);
+ ret = TclUnixSetBlockingMode(statePtr->fds.fd,
+ TCL_MODE_NONBLOCKING);
if (ret < 0) {
continue;
}
}
- /* Gotta reset the error variable here, before we use it for the
- * first time in this iteration. */
+ /*
+ * Must reset the error variable here, before we use it for the
+ * first time in this iteration.
+ */
+
error = 0;
(void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR,
@@ -1179,10 +1213,13 @@ TcpConnect(
ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
statePtr->addr->ai_addrlen);
- if (ret < 0) error = errno;
+ if (ret < 0) {
+ error = errno;
+ }
if (ret < 0 && errno == EINPROGRESS) {
Tcl_CreateFileHandler(statePtr->fds.fd,
- TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, statePtr);
+ TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
+ statePtr);
errno = EWOULDBLOCK;
SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
return TCL_OK;
@@ -1210,7 +1247,7 @@ TcpConnect(
}
}
-out:
+ out:
statePtr->connectError = error;
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
if (async_callback) {
@@ -1308,6 +1345,7 @@ Tcl_OpenTcpClient(
/*
* Allocate a new TcpState for this socket.
*/
+
statePtr = ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
@@ -1319,6 +1357,7 @@ Tcl_OpenTcpClient(
/*
* Create a new client socket and wrap it in a channel.
*/
+
if (TcpConnect(interp, statePtr) != TCL_OK) {
TcpCloseProc(statePtr, NULL);
return NULL;
@@ -1326,8 +1365,8 @@ Tcl_OpenTcpClient(
sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
- statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr,
- (TCL_READABLE | TCL_WRITABLE));
+ statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
+ statePtr, TCL_READABLE | TCL_WRITABLE);
if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
"auto crlf") == TCL_ERROR) {
Tcl_Close(NULL, statePtr->channel);
@@ -1356,7 +1395,8 @@ Tcl_Channel
Tcl_MakeTcpClientChannel(
ClientData sock) /* The socket to wrap up into a channel. */
{
- return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock, (TCL_READABLE | TCL_WRITABLE));
+ return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
+ TCL_READABLE | TCL_WRITABLE);
}
/*
@@ -1456,6 +1496,7 @@ Tcl_OpenTcpServerEx(
* families. We try this at most MAXRETRY times to avoid an endless loop
* if all ports are taken.
*/
+
int retry = 0;
#define MAXRETRY 10
@@ -1481,7 +1522,8 @@ Tcl_OpenTcpServerEx(
goto error;
}
- if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) {
+ if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
+ &errorMsg)) {
my_errno = errno;
goto error;
}
@@ -1517,21 +1559,22 @@ Tcl_OpenTcpServerEx(
if (flags & TCL_TCPSERVER_REUSEADDR) {
optvalue = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (char *) &optvalue, sizeof(optvalue));
+ (char *) &optvalue, sizeof(optvalue));
}
if (flags & TCL_TCPSERVER_REUSEPORT) {
#ifndef SO_REUSEPORT
/*
- * If the platform doesn't support the SO_REUSEPORT flag we can't do
- * much beside erroring out.
+ * If the platform doesn't support the SO_REUSEPORT flag we can't
+ * do much beside erroring out.
*/
+
errorMsg = "SO_REUSEPORT isn't supported by this platform";
goto error;
#else
optvalue = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
- (char *) &optvalue, sizeof(optvalue));
+ (char *) &optvalue, sizeof(optvalue));
#endif
}
@@ -1549,7 +1592,10 @@ Tcl_OpenTcpServerEx(
}
#ifdef IPV6_V6ONLY
- /* Missing on: Solaris 2.8 */
+ /*
+ * Missing on: Solaris 2.8
+ */
+
if (addrPtr->ai_family == AF_INET6) {
int v6only = 1;
@@ -1701,7 +1747,7 @@ TcpAccept(
sprintf(channelName, SOCK_TEMPLATE, (long) newSockState);
newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- newSockState, (TCL_READABLE | TCL_WRITABLE));
+ newSockState, TCL_READABLE | TCL_WRITABLE);
Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
"auto crlf");
diff --git a/win/tclWinSock.c b/win/tclWinSock.c
index 81a5449..d6aca1b 100644
--- a/win/tclWinSock.c
+++ b/win/tclWinSock.c
@@ -297,17 +297,25 @@ static ProcessGlobalValue hostName =
* Address print debug functions
*/
#if 0
-void printaddrinfo(struct addrinfo *ai, char *prefix)
+void
+printaddrinfo(
+ struct addrinfo *ai,
+ char *prefix)
{
char host[NI_MAXHOST], port[NI_MAXSERV];
+
getnameinfo(ai->ai_addr, ai->ai_addrlen,
- host, sizeof(host),
- port, sizeof(port),
- NI_NUMERICHOST|NI_NUMERICSERV);
+ host, sizeof(host), port, sizeof(port),
+ NI_NUMERICHOST|NI_NUMERICSERV);
}
-void printaddrinfolist(struct addrinfo *addrlist, char *prefix)
+
+void
+printaddrinfolist(
+ struct addrinfo *addrlist,
+ char *prefix)
{
struct addrinfo *ai;
+
for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
printaddrinfo(ai, prefix);
}
@@ -524,9 +532,9 @@ TcpBlockModeProc(
TcpState *statePtr = instanceData;
if (mode == TCL_MODE_NONBLOCKING) {
- statePtr->flags |= TCP_NONBLOCKING;
+ SET_BITS(statePtr->flags, TCP_NONBLOCKING);
} else {
- statePtr->flags &= ~(TCP_NONBLOCKING);
+ CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
}
return 0;
}
@@ -536,29 +544,28 @@ TcpBlockModeProc(
*
* WaitForConnect --
*
- * Check the state of an async connect process. If a connection
- * attempt terminated, process it, which may finalize it or may
- * start the next attempt. If a connect error occures, it is saved
- * in statePtr->connectError to be reported by 'fconfigure -error'.
+ * Check the state of an async connect process. If a connection attempt
+ * terminated, process it, which may finalize it or may start the next
+ * attempt. If a connect error occures, it is saved in
+ * statePtr->connectError to be reported by 'fconfigure -error'.
*
* There are two modes of operation, defined by errorCodePtr:
- * * non-NULL: Called by explicite read/write command. block if
- * socket is blocking.
+ * * non-NULL: Called by explicite read/write command. Block if socket
+ * is blocking.
* May return two error codes:
* * EWOULDBLOCK: if connect is still in progress
- * * ENOTCONN: if connect failed. This would be the error
- * message of a rect or sendto syscall so this is
- * emulated here.
- * * Null: Called by a backround operation. Do not block and
- * don't return any error code.
+ * * ENOTCONN: if connect failed. This would be the error message
+ * of a rect or sendto syscall so this is emulated here.
+ * * Null: Called by a backround operation. Do not block and don't
+ * return any error code.
*
* Results:
- * 0 if the connection has completed, -1 if still in progress
- * or there is an error.
+ * 0 if the connection has completed, -1 if still in progress or there is
+ * an error.
*
* Side effects:
- * Processes socket events off the system queue.
- * May process asynchroneous connect.
+ * Processes socket events off the system queue. May process
+ * asynchroneous connect.
*
*----------------------------------------------------------------------
*/
@@ -566,17 +573,16 @@ TcpBlockModeProc(
static int
WaitForConnect(
TcpState *statePtr, /* State of the socket. */
- int *errorCodePtr) /* Where to store errors?
- * A passed null-pointer activates background mode.
- */
+ int *errorCodePtr) /* Where to store errors? A passed
+ * null-pointer activates background mode. */
{
int result;
int oldMode;
ThreadSpecificData *tsdPtr;
/*
- * Check if an async connect failed already and error reporting is demanded,
- * return the error ENOTCONN
+ * Check if an async connect failed already and error reporting is
+ * demanded, return the error ENOTCONN.
*/
if (errorCodePtr != NULL && (statePtr->flags & TCP_ASYNC_FAILED)) {
@@ -603,36 +609,51 @@ WaitForConnect(
*/
while (1) {
+ /*
+ * Get the statePtr lock.
+ */
- /* get statePtr lock */
tsdPtr = TclThreadDataKeyGet(&dataKey);
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
- /* Check for connect event */
+ /*
+ * Check for connect event.
+ */
+
if (statePtr->readyEvents & FD_CONNECT) {
+ /*
+ * Consume the connect event.
+ */
- /* Consume the connect event */
- statePtr->readyEvents &= ~(FD_CONNECT);
+ CLEAR_BITS(statePtr->readyEvents, FD_CONNECT);
/*
- * For blocking sockets and foreground processing
- * disable async connect as we continue now synchoneously
+ * For blocking sockets and foreground processing, disable async
+ * connect as we continue now synchoneously.
*/
- if ( errorCodePtr != NULL &&
- ! (statePtr->flags & TCP_NONBLOCKING) ) {
+
+ if (errorCodePtr != NULL &&
+ !(statePtr->flags & TCP_NONBLOCKING)) {
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
}
- /* Free list lock */
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
/*
- * Continue connect.
- * If switched to synchroneous connect, the connect is terminated.
+ * Continue connect. If switched to synchroneous connect, the
+ * connect is terminated.
*/
+
result = TcpConnect(NULL, statePtr);
- /* Restore event service mode */
+ /*
+ * Restore event service mode.
+ */
+
(void) Tcl_SetServiceMode(oldMode);
/*
@@ -641,10 +662,11 @@ WaitForConnect(
if (result == TCL_OK) {
/*
- * Check for async connect restart
- * (not possible for foreground blocking operation)
+ * Check for async connect restart (not possible for
+ * foreground blocking operation)
*/
- if ( statePtr->flags & TCP_ASYNC_PENDING ) {
+
+ if (statePtr->flags & TCP_ASYNC_PENDING) {
if (errorCodePtr != NULL) {
*errorCodePtr = EWOULDBLOCK;
}
@@ -654,8 +676,8 @@ WaitForConnect(
}
/*
- * Connect finally failed.
- * For foreground operation return ENOTCONN.
+ * Connect finally failed. For foreground operation return
+ * ENOTCONN.
*/
if (errorCodePtr != NULL) {
@@ -664,7 +686,10 @@ WaitForConnect(
return -1;
}
- /* Free list lock */
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
/*
@@ -672,13 +697,13 @@ WaitForConnect(
* event
*/
- if ( errorCodePtr == NULL ) {
+ if (errorCodePtr == NULL) {
return -1;
}
/*
- * A non blocking socket waiting for an asyncronous connect
- * returns directly the error EWOULDBLOCK
+ * A non blocking socket waiting for an asyncronous connect returns
+ * directly the error EWOULDBLOCK.
*/
if (statePtr->flags & TCP_NONBLOCKING) {
@@ -770,16 +795,20 @@ TcpInputProc(
while (1) {
SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
(WPARAM) UNSELECT, (LPARAM) statePtr);
- /* single fd operation: this proc is only called for a connected socket. */
+ /*
+ * Single fd operation: this proc is only called for a connected
+ * socket.
+ */
+
bytesRead = recv(statePtr->sockets->fd, buf, bufSize, 0);
- statePtr->readyEvents &= ~(FD_READ);
+ CLEAR_BITS(statePtr->readyEvents, FD_READ);
/*
* Check for end-of-file condition or successful read.
*/
if (bytesRead == 0) {
- statePtr->flags |= SOCKET_EOF;
+ SET_BITS(statePtr->flags, SOCKET_EOF);
}
if (bytesRead != SOCKET_ERROR) {
break;
@@ -791,7 +820,7 @@ TcpInputProc(
*/
if (statePtr->readyEvents & FD_CLOSE) {
- statePtr->flags |= SOCKET_EOF;
+ SET_BITS(statePtr->flags, SOCKET_EOF);
bytesRead = 0;
break;
}
@@ -804,7 +833,7 @@ TcpInputProc(
*/
if (error == WSAECONNRESET) {
- statePtr->flags |= SOCKET_EOF;
+ SET_BITS(statePtr->flags, SOCKET_EOF);
bytesRead = 0;
break;
}
@@ -892,7 +921,11 @@ TcpOutputProc(
SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
(WPARAM) UNSELECT, (LPARAM) statePtr);
- /* single fd operation: this proc is only called for a connected socket. */
+ /*
+ * Single fd operation: this proc is only called for a connected
+ * socket.
+ */
+
written = send(statePtr->sockets->fd, buf, toWrite, 0);
if (written != SOCKET_ERROR) {
/*
@@ -917,7 +950,7 @@ TcpOutputProc(
error = WSAGetLastError();
if (error == WSAEWOULDBLOCK) {
- statePtr->readyEvents &= ~(FD_WRITE);
+ CLEAR_BITS(statePtr->readyEvents, FD_WRITE);
if (statePtr->flags & TCP_NONBLOCKING) {
*errorCodePtr = EWOULDBLOCK;
written = -1;
@@ -941,7 +974,8 @@ TcpOutputProc(
}
}
- SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT, (LPARAM)statePtr);
+ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT,
+ (LPARAM)statePtr);
return written;
}
@@ -988,10 +1022,10 @@ TcpCloseProc(
* background.
*/
- while ( statePtr->sockets != NULL ) {
+ while (statePtr->sockets != NULL) {
TcpFdList *thisfd = statePtr->sockets;
- statePtr->sockets = thisfd->next;
+ statePtr->sockets = thisfd->next;
if (closesocket(thisfd->fd) == SOCKET_ERROR) {
TclWinConvertError((DWORD) WSAGetLastError());
errorCode = Tcl_GetErrno();
@@ -1009,18 +1043,25 @@ TcpCloseProc(
/*
* Clear an eventual tsd info list pointer.
+ *
* This may be called, if an async socket connect fails or is closed
* between connect and thread action callback.
*/
+
if (tsdPtr->pendingTcpState != NULL
&& tsdPtr->pendingTcpState == statePtr) {
+ /*
+ * Get infoPtr lock, because this concerns the notifier thread.
+ */
- /* get infoPtr lock, because this concerns the notifier thread */
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
tsdPtr->pendingTcpState = NULL;
- /* Free list lock */
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
}
@@ -1081,8 +1122,11 @@ TcpClose2Proc(
return TCL_ERROR;
}
- /* single fd operation: Tcl_OpenTcpServer() does not set TCL_READABLE or
- * TCL_WRITABLE so this should never be called for a server socket. */
+ /*
+ * Single fd operation: Tcl_OpenTcpServer() does not set TCL_READABLE or
+ * TCL_WRITABLE so this should never be called for a server socket.
+ */
+
if (shutdown(statePtr->sockets->fd, sd) == SOCKET_ERROR) {
TclWinConvertError((DWORD) WSAGetLastError());
errorCode = Tcl_GetErrno();
@@ -1134,7 +1178,7 @@ TcpSetOptionProc(
}
#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
- #error "TCL_FEATURE_KEEPALIVE_NAGLE not reviewed for whether to treat statePtr->sockets as single fd or list"
+#error "TCL_FEATURE_KEEPALIVE_NAGLE not reviewed for whether to treat statePtr->sockets as single fd or list"
sock = statePtr->sockets->fd;
if (!strcasecmp(optionName, "-keepalive")) {
@@ -1243,8 +1287,11 @@ TcpGetOptionProc(
/*
* Go one step in async connect
- * If any error is thrown save it as backround error to report eventually below
+ *
+ * If any error is thrown save it as backround error to report eventually
+ * below.
*/
+
WaitForConnect(statePtr, NULL);
sock = statePtr->sockets->fd;
@@ -1254,31 +1301,26 @@ TcpGetOptionProc(
if ((len > 1) && (optionName[1] == 'e') &&
(strncmp(optionName, "-error", len) == 0)) {
-
/*
- * Do not return any errors if async connect is running
- */
- if ( ! (statePtr->flags & TCP_ASYNC_PENDING) ) {
-
-
- if ( statePtr->flags & TCP_ASYNC_FAILED ) {
+ * Do not return any errors if async connect is running.
+ */
+ if (!(statePtr->flags & TCP_ASYNC_PENDING)) {
+ if (statePtr->flags & TCP_ASYNC_FAILED) {
/*
* In case of a failed async connect, eventually report the
- * connect error only once.
- * Do not report the system error, as this comes again and again.
+ * connect error only once. Do not report the system error,
+ * as this comes again and again.
*/
- if ( statePtr->connectError != 0 ) {
+ if (statePtr->connectError != 0) {
Tcl_DStringAppend(dsPtr,
Tcl_ErrnoMsg(statePtr->connectError), -1);
statePtr->connectError = 0;
}
-
} else {
-
/*
- * Report an eventual last error of the socket system
+ * Report an eventual last error of the socket system.
*/
int optlen;
@@ -1286,24 +1328,30 @@ TcpGetOptionProc(
DWORD err;
/*
- * Populater the err Variable with a possix error
+ * Populate the err variable with a POSIX error
*/
+
optlen = sizeof(int);
ret = getsockopt(sock, SOL_SOCKET, SO_ERROR,
(char *)&err, &optlen);
+
/*
- * The error was not returned directly but should be
- * taken from WSA
+ * The error was not returned directly but should be taken
+ * from WSA.
*/
+
if (ret == SOCKET_ERROR) {
err = WSAGetLastError();
}
+
/*
- * Return error message
+ * Return error message.
*/
+
if (err) {
TclWinConvertError(err);
- Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), -1);
+ Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()),
+ -1);
}
}
}
@@ -1312,14 +1360,14 @@ TcpGetOptionProc(
if ((len > 1) && (optionName[1] == 'c') &&
(strncmp(optionName, "-connecting", len) == 0)) {
-
Tcl_DStringAppend(dsPtr,
(statePtr->flags & TCP_ASYNC_PENDING)
? "1" : "0", -1);
return TCL_OK;
}
- if (interp != NULL && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
+ if (interp != NULL
+ && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
reverseDNS = NI_NUMERICHOST;
}
@@ -1328,20 +1376,23 @@ TcpGetOptionProc(
address peername;
socklen_t size = sizeof(peername);
- if ( (statePtr->flags & TCP_ASYNC_PENDING) ) {
+ if (statePtr->flags & TCP_ASYNC_PENDING) {
/*
* In async connect output an empty string
*/
+
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringAppendElement(dsPtr, "");
} else {
return TCL_OK;
}
- } else if ( getpeername(sock, (LPSOCKADDR) &(peername.sa), &size) == 0) {
+ } else if (getpeername(sock, (LPSOCKADDR) &(peername.sa),
+ &size) == 0) {
/*
* Peername fetch succeeded - output list
*/
+
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringStartSublist(dsPtr);
@@ -1390,11 +1441,12 @@ TcpGetOptionProc(
Tcl_DStringAppendElement(dsPtr, "-sockname");
Tcl_DStringStartSublist(dsPtr);
}
- if ( (statePtr->flags & TCP_ASYNC_PENDING ) ) {
+ if (statePtr->flags & TCP_ASYNC_PENDING) {
/*
* In async connect output an empty string
*/
- found = 1;
+
+ found = 1;
} else {
for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
sock = fds->fd;
@@ -1408,9 +1460,11 @@ TcpGetOptionProc(
Tcl_DStringAppendElement(dsPtr, host);
/*
- * We don't want to resolve INADDR_ANY and sin6addr_any; they
- * can sometimes cause problems (and never have a name).
+ * We don't want to resolve INADDR_ANY and sin6addr_any;
+ * they can sometimes cause problems (and never have a
+ * name).
*/
+
flags |= NI_NUMERICSERV;
if (sockname.sa.sa_family == AF_INET) {
if (sockname.sa4.sin_addr.s_addr == INADDR_ANY) {
@@ -1494,7 +1548,8 @@ TcpGetOptionProc(
return Tcl_BadChannelOption(interp, optionName,
"connecting peername sockname keepalive nagle");
#else
- return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname");
+ return Tcl_BadChannelOption(interp, optionName,
+ "connecting peername sockname");
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/
}
@@ -1536,10 +1591,10 @@ TcpWatchProc(
if (!statePtr->acceptProc) {
statePtr->watchEvents = 0;
if (mask & TCL_READABLE) {
- statePtr->watchEvents |= (FD_READ|FD_CLOSE);
+ SET_BITS(statePtr->watchEvents, FD_READ | FD_CLOSE);
}
if (mask & TCL_WRITABLE) {
- statePtr->watchEvents |= (FD_WRITE|FD_CLOSE);
+ SET_BITS(statePtr->watchEvents, FD_WRITE | FD_CLOSE);
}
/*
@@ -1630,13 +1685,13 @@ TcpConnect(
TcpState *statePtr)
{
DWORD error;
- /*
- * We are started with async connect and the connect notification
- * was not jet received
- */
int async_connect = statePtr->flags & TCP_ASYNC_CONNECT;
- /* We were called by the event procedure and continue our loop */
+ /* We are started with async connect and the
+ * connect notification was not yet
+ * received. */
int async_callback = statePtr->flags & TCP_ASYNC_PENDING;
+ /* We were called by the event procedure and
+ * continue our loop. */
ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
if (async_callback) {
@@ -1644,11 +1699,10 @@ TcpConnect(
}
for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
- statePtr->addr = statePtr->addr->ai_next) {
-
- for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL;
- statePtr->myaddr = statePtr->myaddr->ai_next) {
-
+ statePtr->addr = statePtr->addr->ai_next) {
+ for (statePtr->myaddr = statePtr->myaddrlist;
+ statePtr->myaddr != NULL;
+ statePtr->myaddr = statePtr->myaddr->ai_next) {
/*
* No need to try combinations of local and remote addresses
* of different families.
@@ -1662,25 +1716,37 @@ TcpConnect(
* Close the socket if it is still open from the last unsuccessful
* iteration.
*/
+
if (statePtr->sockets->fd != INVALID_SOCKET) {
closesocket(statePtr->sockets->fd);
}
- /* get statePtr lock */
+ /*
+ * Get statePtr lock.
+ */
+
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/*
* Reset last error from last try
*/
+
statePtr->notifierConnectError = 0;
Tcl_SetErrno(0);
- statePtr->sockets->fd = socket(statePtr->myaddr->ai_family, SOCK_STREAM, 0);
+ statePtr->sockets->fd = socket(statePtr->myaddr->ai_family,
+ SOCK_STREAM, 0);
+
+ /*
+ * Free list lock.
+ */
- /* Free list lock */
SetEvent(tsdPtr->socketListLock);
- /* continue on socket creation error */
+ /*
+ * Continue on socket creation error.
+ */
+
if (statePtr->sockets->fd == INVALID_SOCKET) {
TclWinConvertError((DWORD) WSAGetLastError());
continue;
@@ -1691,31 +1757,39 @@ TcpConnect(
* processes by default. Turn off the inherit bit.
*/
- SetHandleInformation((HANDLE) statePtr->sockets->fd, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation((HANDLE) statePtr->sockets->fd,
+ HANDLE_FLAG_INHERIT, 0);
/*
* Set kernel space buffering
*/
- TclSockMinimumBuffers((void *) statePtr->sockets->fd, TCP_BUFFER_SIZE);
+ TclSockMinimumBuffers((void *) statePtr->sockets->fd,
+ TCP_BUFFER_SIZE);
/*
* Try to bind to a local port.
*/
if (bind(statePtr->sockets->fd, statePtr->myaddr->ai_addr,
- statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) {
+ statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) {
TclWinConvertError((DWORD) WSAGetLastError());
continue;
}
+
/*
* For asyncroneous connect set the socket in nonblocking mode
* and activate connect notification
*/
+
if (async_connect) {
TcpState *statePtr2;
int in_socket_list = 0;
- /* get statePtr lock */
+
+ /*
+ * Get statePtr lock.
+ */
+
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/*
@@ -1725,8 +1799,8 @@ TcpConnect(
* It is set after this call by TcpThreadActionProc and is set
* on a second round.
*
- * If not, we buffer my statePtr in the tsd memory so it is not
- * lost by the event procedure
+ * If not, we buffer my statePtr in the tsd memory so it is
+ * not lost by the event procedure
*/
for (statePtr2 = tsdPtr->socketList; statePtr2 != NULL;
@@ -1739,19 +1813,26 @@ TcpConnect(
if (!in_socket_list) {
tsdPtr->pendingTcpState = statePtr;
}
+
/*
* Set connect mask to connect events
- * This is activated by a SOCKET_SELECT message to the notifier
- * thread.
+ *
+ * This is activated by a SOCKET_SELECT message to the
+ * notifier thread.
*/
- statePtr->selectEvents |= FD_CONNECT;
+
+ SET_BITS(statePtr->selectEvents, FD_CONNECT);
/*
- * Free list lock
+ * Free list lock.
*/
+
SetEvent(tsdPtr->socketListLock);
- /* activate accept notification */
+ /*
+ * Activate accept notification.
+ */
+
SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
(LPARAM) statePtr);
}
@@ -1769,12 +1850,11 @@ TcpConnect(
if (async_connect && error == WSAEWOULDBLOCK) {
/*
* Asynchroneous connect
- */
-
- /*
+ *
* Remember that we jump back behind this next round
*/
- statePtr->flags |= TCP_ASYNC_PENDING;
+
+ SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
return TCL_OK;
reenter:
@@ -1784,21 +1864,39 @@ TcpConnect(
*
* Clear the reenter flag
*/
- statePtr->flags &= ~(TCP_ASYNC_PENDING);
- /* get statePtr lock */
+
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+
+ /*
+ * Get statePtr lock.
+ */
+
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
- /* Get signaled connect error */
+
+ /*
+ * Get signaled connect error.
+ */
+
TclWinConvertError((DWORD) statePtr->notifierConnectError);
- /* Clear eventual connect flag */
- statePtr->selectEvents &= ~(FD_CONNECT);
- /* Free list lock */
+
+ /*
+ * Clear eventual connect flag.
+ */
+
+ CLEAR_BITS(statePtr->selectEvents, FD_CONNECT);
+
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
}
/*
- * Clear the tsd socket list pointer if we did not wait for
- * the FD_CONNECT asyncroneously
+ * Clear the tsd socket list pointer if we did not wait for the
+ * FD_CONNECT asynchronously.
*/
+
tsdPtr->pendingTcpState = NULL;
if (Tcl_GetErrno() == 0) {
@@ -1807,7 +1905,7 @@ TcpConnect(
}
}
-out:
+ out:
/*
* Socket connected or connection failed
*/
@@ -1818,13 +1916,13 @@ out:
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
- if ( Tcl_GetErrno() == 0 ) {
+ if (Tcl_GetErrno() == 0) {
/*
* Succesfully connected
- */
- /*
+ *
* Set up the select mask for read/write events.
*/
+
statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;
/*
@@ -1837,30 +1935,52 @@ out:
} else {
/*
* Connect failed
- */
-
- /*
+ *
* For async connect schedule a writable event to report the fail.
*/
+
if (async_callback) {
/*
* Set up the select mask for read/write events.
*/
+
statePtr->selectEvents = FD_WRITE|FD_READ;
- /* get statePtr lock */
+
+ /*
+ * Get statePtr lock.
+ */
+
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
- /* Signal ready readable and writable events */
- statePtr->readyEvents |= FD_WRITE | FD_READ;
- /* Flag error to event routine */
- statePtr->flags |= TCP_ASYNC_FAILED;
- /* Save connect error to be reported by 'fconfigure -error' */
+
+ /*
+ * Signal ready readable and writable events.
+ */
+
+ SET_BITS(statePtr->readyEvents, FD_WRITE | FD_READ);
+
+ /*
+ * Flag error to event routine.
+ */
+
+ SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
+
+ /*
+ * Save connect error to be reported by 'fconfigure -error'.
+ */
+
statePtr->connectError = Tcl_GetErrno();
- /* Free list lock */
+
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
}
+
/*
* Error message on syncroneous connect
*/
+
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't open socket: %s", Tcl_PosixError(interp)));
@@ -1938,7 +2058,7 @@ Tcl_OpenTcpClient(
statePtr->addrlist = addrlist;
statePtr->myaddrlist = myaddrlist;
if (async) {
- statePtr->flags |= TCP_ASYNC_CONNECT;
+ SET_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
}
/*
@@ -2008,7 +2128,8 @@ Tcl_MakeTcpClientChannel(
*/
statePtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;
- SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT, (LPARAM)statePtr);
+ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT,
+ (LPARAM)statePtr);
sprintf(channelName, SOCK_TEMPLATE, statePtr);
statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
@@ -2078,7 +2199,8 @@ Tcl_OpenTcpServerEx(
goto error;
}
- if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) {
+ if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
+ &errorMsg)) {
goto error;
}
@@ -2117,13 +2239,14 @@ Tcl_OpenTcpServerEx(
}
/*
- * The SO_REUSEADDR option on Windows behaves like SO_REUSEPORT on unix
- * systems.
+ * The SO_REUSEADDR option on Windows behaves like SO_REUSEPORT on
+ * unix systems.
*/
+
if (flags & TCL_TCPSERVER_REUSEPORT) {
optvalue = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (char *) &optvalue, sizeof(optvalue));
+ (char *) &optvalue, sizeof(optvalue));
}
/*
@@ -2134,8 +2257,8 @@ Tcl_OpenTcpServerEx(
* place to look for bugs.
*/
- if (bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen)
- == SOCKET_ERROR) {
+ if (bind(sock, addrPtr->ai_addr,
+ addrPtr->ai_addrlen) == SOCKET_ERROR) {
TclWinConvertError((DWORD) WSAGetLastError());
closesocket(sock);
continue;
@@ -2170,13 +2293,14 @@ Tcl_OpenTcpServerEx(
/*
* Add this socket to the global list of sockets.
*/
+
statePtr = NewSocketInfo(sock);
} else {
- AddSocketInfoFd( statePtr, sock );
+ AddSocketInfoFd(statePtr, sock);
}
}
-error:
+ error:
if (addrlist != NULL) {
freeaddrinfo(addrlist);
}
@@ -2202,7 +2326,7 @@ error:
ioctlsocket(sock, (long) FIONBIO, &flag);
SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
- (LPARAM) statePtr);
+ (LPARAM) statePtr);
if (Tcl_SetChannelOption(interp, statePtr->channel, "-eofchar", "")
== TCL_ERROR) {
Tcl_Close(NULL, statePtr->channel);
@@ -2564,9 +2688,8 @@ SocketCheckProc(
statePtr = statePtr->nextPtr) {
if ((statePtr->readyEvents &
(statePtr->watchEvents | FD_CONNECT | FD_ACCEPT))
- && !(statePtr->flags & SOCKET_PENDING)
- ) {
- statePtr->flags |= SOCKET_PENDING;
+ && !(statePtr->flags & SOCKET_PENDING)) {
+ SET_BITS(statePtr->flags, SOCKET_PENDING);
evPtr = ckalloc(sizeof(SocketEvent));
evPtr->header.proc = SocketEventProc;
evPtr->socket = statePtr->sockets->fd;
@@ -2641,29 +2764,26 @@ SocketEventProc(
* Clear flag that (this) event is pending
*/
- statePtr->flags &= ~SOCKET_PENDING;
+ CLEAR_BITS(statePtr->flags, SOCKET_PENDING);
/*
* Continue async connect if pending and ready
*/
- if ( statePtr->readyEvents & FD_CONNECT ) {
- if ( statePtr->flags & TCP_ASYNC_PENDING ) {
-
+ if (statePtr->readyEvents & FD_CONNECT) {
+ if (statePtr->flags & TCP_ASYNC_PENDING) {
/*
* Do one step and save eventual connect error
*/
SetEvent(tsdPtr->socketListLock);
WaitForConnect(statePtr,NULL);
-
} else {
-
/*
* No async connect reenter pending. Just clear event.
*/
- statePtr->readyEvents &= ~(FD_CONNECT);
+ CLEAR_BITS(statePtr->readyEvents, FD_CONNECT);
SetEvent(tsdPtr->socketListLock);
}
return 1;
@@ -2672,20 +2792,23 @@ SocketEventProc(
/*
* Handle connection requests directly.
*/
+
if (statePtr->readyEvents & FD_ACCEPT) {
for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
-
/*
- * Accept the incoming connection request.
- */
- len = sizeof(address);
+ * Accept the incoming connection request.
+ */
+ len = sizeof(address);
newSocket = accept(fds->fd, &(addr.sa), &len);
- /* On Tcl server sockets with multiple OS fds we loop over the fds trying
- * an accept() on each, so we expect INVALID_SOCKET. There are also other
- * network stack conditions that can result in FD_ACCEPT but a subsequent
- * failure on accept() by the time we get around to it.
+ /*
+ * On Tcl server sockets with multiple OS fds we loop over the fds
+ * trying an accept() on each, so we expect INVALID_SOCKET. There
+ * are also other network stack conditions that can result in
+ * FD_ACCEPT but a subsequent failure on accept() by the time we
+ * get around to it.
+ *
* Access to sockets (acceptEventCount, readyEvents) in socketList
* is still protected by the lock (prevents reintroduction of
* SF Tcl Bug 3056775.
@@ -2697,35 +2820,40 @@ SocketEventProc(
}
/*
- * It is possible that more than one FD_ACCEPT has been sent, so an extra
- * count must be kept. Decrement the count, and reset the readyEvent bit
- * if the count is no longer > 0.
+ * It is possible that more than one FD_ACCEPT has been sent, so
+ * an extra count must be kept. Decrement the count, and reset the
+ * readyEvent bit if the count is no longer > 0.
*/
+
statePtr->acceptEventCount--;
if (statePtr->acceptEventCount <= 0) {
- statePtr->readyEvents &= ~(FD_ACCEPT);
+ CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
}
SetEvent(tsdPtr->socketListLock);
- /* Caution: TcpAccept() has the side-effect of evaluating the server
- * accept script (via AcceptCallbackProc() in tclIOCmd.c), which can
- * close the server socket and invalidate statePtr and fds.
- * If TcpAccept() accepts a socket we must return immediately and let
- * SocketCheckProc queue additional FD_ACCEPT events.
+ /*
+ * Caution: TcpAccept() has the side-effect of evaluating the
+ * server accept script (via AcceptCallbackProc() in tclIOCmd.c),
+ * which can close the server socket and invalidate statePtr and
+ * fds. If TcpAccept() accepts a socket we must return immediately
+ * and let SocketCheckProc queue additional FD_ACCEPT events.
*/
+
TcpAccept(fds, newSocket, addr);
return 1;
}
- /* Loop terminated with no sockets accepted; clear the ready mask so
+ /*
+ * Loop terminated with no sockets accepted; clear the ready mask so
* we can detect the next connection request. Note that connection
* requests are level triggered, so if there is a request already
* pending, a new event will be generated.
*/
+
statePtr->acceptEventCount = 0;
- statePtr->readyEvents &= ~(FD_ACCEPT);
+ CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
SetEvent(tsdPtr->socketListLock);
return 1;
@@ -2754,16 +2882,15 @@ SocketEventProc(
Tcl_Time blockTime = { 0, 0 };
Tcl_SetMaxBlockTime(&blockTime);
- mask |= TCL_READABLE|TCL_WRITABLE;
+ SET_BITS(mask, TCL_READABLE | TCL_WRITABLE);
} else if (events & FD_READ) {
/*
* Throw the readable event if an async connect failed.
*/
- if ( statePtr->flags & TCP_ASYNC_FAILED ) {
-
- mask |= TCL_READABLE;
+ if (statePtr->flags & TCP_ASYNC_FAILED) {
+ SET_BITS(mask, TCL_READABLE);
} else {
fd_set readFds;
@@ -2786,9 +2913,9 @@ SocketEventProc(
timeout.tv_sec = 0;
if (select(0, &readFds, NULL, NULL, &timeout) != 0) {
- mask |= TCL_READABLE;
+ SET_BITS(mask, TCL_READABLE);
} else {
- statePtr->readyEvents &= ~(FD_READ);
+ CLEAR_BITS(statePtr->readyEvents, FD_READ);
SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
(WPARAM) SELECT, (LPARAM) statePtr);
}
@@ -2800,7 +2927,7 @@ SocketEventProc(
*/
if (events & FD_WRITE) {
- mask |= TCL_WRITABLE;
+ SET_BITS(mask, TCL_WRITABLE);
}
/*
@@ -2837,13 +2964,19 @@ AddSocketInfoFd(
{
TcpFdList *fds = statePtr->sockets;
- if ( fds == NULL ) {
- /* Add the first FD */
+ if (fds == NULL) {
+ /*
+ * Add the first FD.
+ */
+
statePtr->sockets = ckalloc(sizeof(TcpFdList));
fds = statePtr->sockets;
} else {
- /* Find end of list and append FD */
- while ( fds->next != NULL ) {
+ /*
+ * Find end of list and append FD.
+ */
+
+ while (fds->next != NULL) {
fds = fds->next;
}
@@ -2851,7 +2984,10 @@ AddSocketInfoFd(
fds = fds->next;
}
- /* Populate new FD */
+ /*
+ * Populate new FD.
+ */
+
fds->fd = socket;
fds->statePtr = statePtr;
fds->next = NULL;
@@ -2921,6 +3057,7 @@ WaitForSocketEvent(
int result = 1;
int oldMode;
ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
+
/*
* Be sure to disable event servicing so we are truly modal.
*/
@@ -2939,21 +3076,36 @@ WaitForSocketEvent(
while (1) {
int event_found;
- /* get statePtr lock */
+ /*
+ * Get statePtr lock.
+ */
+
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
- /* Check if event occured */
+ /*
+ * Check if event occured.
+ */
+
event_found = (statePtr->readyEvents & events);
- /* Free list lock */
+ /*
+ * Free list lock.
+ */
+
SetEvent(tsdPtr->socketListLock);
- /* exit loop if event occured */
+ /*
+ * Exit loop if event occured.
+ */
+
if (event_found) {
break;
}
- /* Exit loop if event did not occur but this is a non-blocking channel */
+ /*
+ * Exit loop if event did not occur but this is a non-blocking channel
+ */
+
if (statePtr->flags & TCP_NONBLOCKING) {
*errorCodePtr = EWOULDBLOCK;
result = 0;
@@ -3110,34 +3262,34 @@ SocketProc(
for (statePtr = tsdPtr->socketList; statePtr != NULL;
statePtr = statePtr->nextPtr) {
- if ( FindFDInList(statePtr,socket) ) {
+ if (FindFDInList(statePtr, socket)) {
info_found = 1;
break;
}
}
+
/*
- * Check if there is a pending info structure not jet in the
- * list
+ * Check if there is a pending info structure not jet in the list.
*/
- if ( !info_found
+
+ if (!info_found
&& tsdPtr->pendingTcpState != NULL
- && FindFDInList(tsdPtr->pendingTcpState,socket) ) {
+ && FindFDInList(tsdPtr->pendingTcpState, socket)) {
statePtr = tsdPtr->pendingTcpState;
info_found = 1;
}
if (info_found) {
-
/*
* Update the socket state.
*
* A count of FD_ACCEPTS is stored, so if an FD_CLOSE event
- * happens, then clear the FD_ACCEPT count. Otherwise,
- * increment the count if the current event is an FD_ACCEPT.
+ * happens, then clear the FD_ACCEPT count. Otherwise, increment
+ * the count if the current event is an FD_ACCEPT.
*/
if (event & FD_CLOSE) {
statePtr->acceptEventCount = 0;
- statePtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT);
+ CLEAR_BITS(statePtr->readyEvents, FD_WRITE | FD_ACCEPT);
} else if (event & FD_ACCEPT) {
statePtr->acceptEventCount++;
}
@@ -3147,18 +3299,22 @@ SocketProc(
* Remember any error that occurred so we can report
* connection failures.
*/
+
if (error != ERROR_SUCCESS) {
statePtr->notifierConnectError = error;
}
}
+
/*
* Inform main thread about signaled events
*/
- statePtr->readyEvents |= event;
+
+ SET_BITS(statePtr->readyEvents, event);
/*
* Wake up the Main Thread.
*/
+
SetEvent(tsdPtr->readyEvent);
Tcl_ThreadAlert(tsdPtr->threadId);
}