summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixSock.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixSock.c')
-rw-r--r--unix/tclUnixSock.c650
1 files changed, 325 insertions, 325 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 78ed008..14be638 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -23,8 +23,8 @@
#define GOT_BITS(var, bits) (((var) & (bits)) != 0)
/* "sock" + a pointer in hex + \0 */
-#define SOCK_CHAN_LENGTH (4 + sizeof(void *) * 2 + 1)
-#define SOCK_TEMPLATE "sock%" TCL_Z_MODIFIER "x"
+#define SOCK_CHAN_LENGTH (4 + sizeof(void *) * 2 + 1)
+#define SOCK_TEMPLATE "sock%" TCL_Z_MODIFIER "x"
#undef SOCKET /* Possible conflict with win32 SOCKET */
@@ -64,8 +64,8 @@ struct TcpState {
*/
Tcl_TcpAcceptProc *acceptProc;
- /* Proc to call on accept. */
- void *acceptProcData; /* The data for the accept proc. */
+ /* Proc to call on accept. */
+ void *acceptProcData; /* The data for the accept proc. */
/*
* Only needed for client sockets
@@ -75,10 +75,10 @@ struct TcpState {
struct addrinfo *addr; /* Iterator over addrlist. */
struct addrinfo *myaddrlist;/* Local address. */
struct addrinfo *myaddr; /* Iterator over myaddrlist. */
- int filehandlers; /* Caches FileHandlers that get set up while
- * an async socket is not yet connected. */
- int connectError; /* Cache SO_ERROR of async socket. */
- int cachedBlocking; /* Cache blocking mode of async socket. */
+ int filehandlers; /* Caches FileHandlers that get set up while
+ * an async socket is not yet connected. */
+ int connectError; /* Cache SO_ERROR of async socket. */
+ int cachedBlocking; /* Cache blocking mode of async socket. */
};
/*
@@ -156,7 +156,7 @@ static Tcl_FileProc WrapNotify;
static const Tcl_ChannelType tcpChannelType = {
"tcp", /* Type name. */
TCL_CHANNEL_VERSION_5, /* v5 channel */
- NULL, /* Close proc. */
+ NULL, /* Close proc. */
TcpInputProc, /* Input proc. */
TcpOutputProc, /* Output proc. */
NULL, /* Seek proc. */
@@ -195,7 +195,7 @@ printaddrinfo(
getnameinfo(ai->ai_addr, ai->ai_addrlen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV);
- fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
+ fprintf(stderr, "%s: %s:%s\n", prefix, host, port);
}
}
#endif
@@ -227,7 +227,7 @@ InitializeHostName(
memset(&u, (int) 0, sizeof(struct utsname));
if (uname(&u) >= 0) { /* INTL: Native. */
- hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
+ hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
if (hp == NULL) {
/*
* Sometimes the nodename is fully qualified, but gets truncated
@@ -246,11 +246,11 @@ InitializeHostName(
Tcl_Free(node);
}
}
- if (hp != NULL) {
+ if (hp != NULL) {
native = hp->h_name;
- } else {
+ } else {
native = u.nodename;
- }
+ }
}
#else /* !NO_UNAME */
/*
@@ -357,7 +357,7 @@ TclpFinalizeSockets(void)
static int
TcpBlockModeProc(
- void *instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
int mode) /* The mode to set. Can be one of
* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
@@ -370,8 +370,8 @@ TcpBlockModeProc(
SET_BITS(statePtr->flags, TCP_NONBLOCKING);
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
- statePtr->cachedBlocking = mode;
- return 0;
+ statePtr->cachedBlocking = mode;
+ return 0;
}
if (TclUnixSetBlockingMode(statePtr->fds.fd, mode) < 0) {
return errno;
@@ -443,37 +443,37 @@ WaitForConnect(
*/
if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)
- && !(errorCodePtr != NULL
- && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
+ && !(errorCodePtr != NULL
+ && !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
*errorCodePtr = EWOULDBLOCK;
return -1;
}
if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
- timeout = 0;
+ timeout = 0;
} else {
- timeout = -1;
+ timeout = -1;
}
do {
- if (TclUnixWaitForFile(statePtr->fds.fd,
- 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.
- */
+ if (TclUnixWaitForFile(statePtr->fds.fd,
+ 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.
+ */
} while (timeout == -1 && GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT));
if (errorCodePtr != NULL) {
- if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
- *errorCodePtr = EAGAIN;
- return -1;
- } else if (statePtr->connectError != 0) {
- *errorCodePtr = ENOTCONN;
- return -1;
- }
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
+ *errorCodePtr = EAGAIN;
+ return -1;
+ } else if (statePtr->connectError != 0) {
+ *errorCodePtr = ENOTCONN;
+ return -1;
+ }
}
return 0;
}
@@ -502,7 +502,7 @@ WaitForConnect(
static int
TcpInputProc(
- void *instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
char *buf, /* Where to store data read. */
int bufSize, /* How much space is available in the
* buffer? */
@@ -553,7 +553,7 @@ TcpInputProc(
static int
TcpOutputProc(
- void *instanceData, /* Socket state. */
+ void *instanceData, /* Socket state. */
const char *buf, /* The data buffer. */
int toWrite, /* How many bytes to write? */
int *errorCodePtr) /* Where to store error code. */
@@ -594,7 +594,7 @@ TcpOutputProc(
static int
TcpCloseProc(
- void *instanceData, /* The socket to close. */
+ void *instanceData, /* The socket to close. */
TCL_UNUSED(Tcl_Interp *))
{
TcpState *statePtr = (TcpState *)instanceData;
@@ -627,10 +627,10 @@ TcpCloseProc(
fds = next;
}
if (statePtr->addrlist != NULL) {
- freeaddrinfo(statePtr->addrlist);
+ freeaddrinfo(statePtr->addrlist);
}
if (statePtr->myaddrlist != NULL) {
- freeaddrinfo(statePtr->myaddrlist);
+ freeaddrinfo(statePtr->myaddrlist);
}
Tcl_Free(statePtr);
return errorCode;
@@ -655,7 +655,7 @@ TcpCloseProc(
static int
TcpClose2Proc(
- void *instanceData, /* The socket to close. */
+ void *instanceData, /* The socket to close. */
TCL_UNUSED(Tcl_Interp *),
int flags) /* Flags that indicate which side to close. */
{
@@ -706,7 +706,7 @@ IPv6AddressNeedsNumericRendering(
struct in6_addr addr)
{
if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) {
- return 1;
+ return 1;
}
/*
@@ -715,11 +715,11 @@ IPv6AddressNeedsNumericRendering(
*/
if (!IN6_IS_ADDR_V4MAPPED(&addr)) {
- return 0;
+ return 0;
}
return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0
- && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
+ && addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
}
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
@@ -738,7 +738,7 @@ TcpHostPortList(
int flags = 0;
getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport),
- NI_NUMERICHOST | NI_NUMERICSERV);
+ NI_NUMERICHOST | NI_NUMERICSERV);
Tcl_DStringAppendElement(dsPtr, nhost);
/*
@@ -747,14 +747,14 @@ TcpHostPortList(
*/
if (addr.sa.sa_family == AF_INET) {
- if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
- flags |= NI_NUMERICHOST;
- }
+ 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 (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
- flags |= NI_NUMERICHOST;
- }
+ if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
+ flags |= NI_NUMERICHOST;
+ }
#endif /* NEED_FAKE_RFC2553 */
}
@@ -763,22 +763,22 @@ TcpHostPortList(
*/
if (interp != NULL &&
- Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
- flags |= NI_NUMERICHOST;
+ 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.
- */
+ flags) == 0) {
+ /*
+ * Reverse mapping worked.
+ */
- Tcl_DStringAppendElement(dsPtr, host);
+ Tcl_DStringAppendElement(dsPtr, host);
} else {
- /*
- * Reverse mapping failed - use the numeric rep once more.
- */
+ /*
+ * Reverse mapping failed - use the numeric rep once more.
+ */
- Tcl_DStringAppendElement(dsPtr, nhost);
+ Tcl_DStringAppendElement(dsPtr, nhost);
}
Tcl_DStringAppendElement(dsPtr, nport);
}
@@ -907,25 +907,25 @@ TcpGetOptionProc(
socklen_t optlen = sizeof(int);
WaitForConnect(statePtr, NULL);
- if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
- /*
- * 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);
- errno = err;
- }
- if (errno != 0) {
+ if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
+ /*
+ * 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);
+ errno = err;
+ }
+ if (errno != 0) {
Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), TCL_INDEX_NONE);
- }
+ }
return TCL_OK;
}
@@ -934,13 +934,13 @@ TcpGetOptionProc(
WaitForConnect(statePtr, NULL);
Tcl_DStringAppend(dsPtr,
GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", TCL_INDEX_NONE);
- return TCL_OK;
+ return TCL_OK;
}
if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
(strncmp(optionName, "-peername", len) == 0))) {
- address peername;
- socklen_t size = sizeof(peername);
+ address peername;
+ socklen_t size = sizeof(peername);
WaitForConnect(statePtr, NULL);
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
@@ -963,11 +963,11 @@ TcpGetOptionProc(
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringStartSublist(dsPtr);
}
- TcpHostPortList(interp, dsPtr, peername, size);
+ TcpHostPortList(interp, dsPtr, peername, size);
if (len) {
- return TCL_OK;
- }
- Tcl_DStringEndSublist(dsPtr);
+ return TCL_OK;
+ }
+ Tcl_DStringEndSublist(dsPtr);
} else {
/*
* getpeername failed - but if we were asked for all the options
@@ -979,7 +979,7 @@ TcpGetOptionProc(
if (len) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't get peername: %s",
+ "can't get peername: %s",
Tcl_PosixError(interp)));
}
return TCL_ERROR;
@@ -1004,7 +1004,7 @@ TcpGetOptionProc(
* In async connect output an empty string
*/
- found = 1;
+ found = 1;
} else {
for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
size = sizeof(sockname);
@@ -1014,16 +1014,16 @@ TcpGetOptionProc(
}
}
}
- if (found) {
- if (len) {
- return TCL_OK;
- }
- Tcl_DStringEndSublist(dsPtr);
- } else {
- if (interp) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't get sockname: %s", Tcl_PosixError(interp)));
- }
+ if (found) {
+ if (len) {
+ return TCL_OK;
+ }
+ Tcl_DStringEndSublist(dsPtr);
+ } else {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "can't get sockname: %s", Tcl_PosixError(interp)));
+ }
return TCL_ERROR;
}
}
@@ -1070,7 +1070,7 @@ TcpGetOptionProc(
if (len > 0) {
return Tcl_BadChannelOption(interp, optionName,
- "connecting keepalive nodelay peername sockname");
+ "connecting keepalive nodelay peername sockname");
}
return TCL_OK;
@@ -1169,7 +1169,7 @@ WrapNotify(
static void
TcpWatchProc(
- void *instanceData, /* The socket state. */
+ void *instanceData, /* The socket state. */
int mask) /* Events of interest; an OR-ed combination of
* TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
@@ -1177,24 +1177,23 @@ TcpWatchProc(
TcpState *statePtr = (TcpState *)instanceData;
if (statePtr->acceptProc != NULL) {
- /*
- * Make sure we don't mess with server sockets since they will never
- * be readable or writable at the Tcl level. This keeps Tcl scripts
- * from interfering with the -accept behavior (bug #3394732).
- */
+ /*
+ * Make sure we don't mess with server sockets since they will never
+ * be readable or writable at the Tcl level. This keeps Tcl scripts
+ * from interfering with the -accept behavior (bug #3394732).
+ */
return;
}
if (GOT_BITS(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;
+ 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
@@ -1242,9 +1241,9 @@ TcpWatchProc(
static int
TcpGetHandleProc(
- void *instanceData, /* The socket state. */
+ void *instanceData, /* The socket state. */
TCL_UNUSED(int) /*direction*/,
- void **handlePtr) /* Where to store the handle. */
+ void **handlePtr) /* Where to store the handle. */
{
TcpState *statePtr = (TcpState *)instanceData;
@@ -1266,7 +1265,7 @@ TcpGetHandleProc(
static void
TcpAsyncCallback(
- void *clientData, /* The socket state. */
+ void *clientData, /* The socket state. */
TCL_UNUSED(int) /*mask*/)
{
TcpConnect(NULL, (TcpState *)clientData);
@@ -1280,9 +1279,9 @@ TcpAsyncCallback(
* This function opens a new socket in client mode.
*
* Results:
- * TCL_OK, if the socket was successfully connected or an asynchronous
- * connection is in progress. If an error occurs, TCL_ERROR is returned
- * and an error message is left in interp.
+ * TCL_OK, if the socket was successfully connected or an asynchronous
+ * connection is in progress. If an error occurs, TCL_ERROR is returned
+ * and an error message is left in interp.
*
* Side effects:
* Opens a socket.
@@ -1314,14 +1313,14 @@ TcpConnect(
static const int reuseaddr = 1;
if (async_callback) {
- goto reenter;
+ goto reenter;
}
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.
@@ -1331,19 +1330,19 @@ TcpConnect(
continue;
}
- /*
- * Close the socket if it is still open from the last unsuccessful
- * iteration.
- */
+ /*
+ * Close the socket if it is still open from the last unsuccessful
+ * iteration.
+ */
- if (statePtr->fds.fd >= 0) {
+ if (statePtr->fds.fd >= 0) {
close(statePtr->fds.fd);
statePtr->fds.fd = -1;
- errno = 0;
+ errno = 0;
}
statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM,
- 0);
+ 0);
if (statePtr->fds.fd < 0) {
continue;
}
@@ -1362,28 +1361,28 @@ TcpConnect(
TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);
if (async) {
- ret = TclUnixSetBlockingMode(statePtr->fds.fd,
- TCL_MODE_NONBLOCKING);
- if (ret < 0) {
- continue;
- }
- }
-
- /*
- * 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,
- (char *) &reuseaddr, sizeof(reuseaddr));
- ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
- statePtr->myaddr->ai_addrlen);
- if (ret < 0) {
- error = errno;
- continue;
- }
+ ret = TclUnixSetBlockingMode(statePtr->fds.fd,
+ TCL_MODE_NONBLOCKING);
+ if (ret < 0) {
+ continue;
+ }
+ }
+
+ /*
+ * 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,
+ (char *) &reuseaddr, sizeof(reuseaddr));
+ ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
+ statePtr->myaddr->ai_addrlen);
+ if (ret < 0) {
+ error = errno;
+ continue;
+ }
/*
* Attempt to connect. The connect may fail at present with an
@@ -1393,35 +1392,35 @@ TcpConnect(
*/
ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
- statePtr->addr->ai_addrlen);
- if (ret < 0) {
- error = errno;
- }
+ statePtr->addr->ai_addrlen);
+ if (ret < 0) {
+ error = errno;
+ }
if (ret < 0 && errno == EINPROGRESS) {
- Tcl_CreateFileHandler(statePtr->fds.fd,
- TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
- statePtr);
- errno = EWOULDBLOCK;
- SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
- return TCL_OK;
-
- reenter:
- CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
- Tcl_DeleteFileHandler(statePtr->fds.fd);
-
- /*
- * Read the error state from the socket to see if the async
- * connection has succeeded or failed. As this clears the
- * error condition, we cache the status in the socket state
- * struct for later retrieval by [fconfigure -error].
- */
-
- optlen = sizeof(int);
-
- getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
- (char *) &error, &optlen);
- errno = error;
- }
+ Tcl_CreateFileHandler(statePtr->fds.fd,
+ TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
+ statePtr);
+ errno = EWOULDBLOCK;
+ SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ return TCL_OK;
+
+ reenter:
+ CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
+ Tcl_DeleteFileHandler(statePtr->fds.fd);
+
+ /*
+ * Read the error state from the socket to see if the async
+ * connection has succeeded or failed. As this clears the
+ * error condition, we cache the status in the socket state
+ * struct for later retrieval by [fconfigure -error].
+ */
+
+ optlen = sizeof(int);
+
+ getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
+ (char *) &error, &optlen);
+ errno = error;
+ }
if (error == 0) {
goto out;
}
@@ -1432,43 +1431,43 @@ TcpConnect(
statePtr->connectError = error;
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
if (async_callback) {
- /*
- * An asynchonous connection has finally succeeded or failed.
- */
-
- TcpWatchProc(statePtr, statePtr->filehandlers);
- TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);
-
- if (error != 0) {
- SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
- }
-
- /*
- * We need to forward the writable event that brought us here, because
- * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
- * writable state from the socket, and so a subsequent select() on
- * behalf of a script level [fileevent] would not fire. It doesn't
- * hurt that this is also called in the successful case and will save
- * the event mechanism one roundtrip through select().
- */
+ /*
+ * An asynchonous connection has finally succeeded or failed.
+ */
+
+ TcpWatchProc(statePtr, statePtr->filehandlers);
+ TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);
+
+ if (error != 0) {
+ SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
+ }
+
+ /*
+ * We need to forward the writable event that brought us here, because
+ * upon reading of getsockopt(SO_ERROR), at least some OSes clear the
+ * writable state from the socket, and so a subsequent select() on
+ * behalf of a script level [fileevent] would not fire. It doesn't
+ * hurt that this is also called in the successful case and will save
+ * the event mechanism one roundtrip through select().
+ */
if (statePtr->cachedBlocking == TCL_MODE_NONBLOCKING) {
Tcl_NotifyChannel(statePtr->channel, TCL_WRITABLE);
}
}
if (error != 0) {
- /*
- * Failure for either a synchronous connection, or an async one that
- * failed before it could enter background mode, e.g. because an
- * invalid -myaddr was given.
- */
-
- if (interp != NULL) {
- errno = error;
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "couldn't open socket: %s", Tcl_PosixError(interp)));
- }
- return TCL_ERROR;
+ /*
+ * Failure for either a synchronous connection, or an async one that
+ * failed before it could enter background mode, e.g. because an
+ * invalid -myaddr was given.
+ */
+
+ if (interp != NULL) {
+ errno = error;
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't open socket: %s", Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
}
return TCL_OK;
}
@@ -1511,16 +1510,16 @@ Tcl_OpenTcpClient(
*/
if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
- || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
- &errorMsg)) {
- if (addrlist != NULL) {
- freeaddrinfo(addrlist);
- }
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "couldn't open socket: %s", errorMsg));
- }
- return NULL;
+ || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
+ &errorMsg)) {
+ if (addrlist != NULL) {
+ freeaddrinfo(addrlist);
+ }
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't open socket: %s", errorMsg));
+ }
+ return NULL;
}
/*
@@ -1540,14 +1539,14 @@ Tcl_OpenTcpClient(
*/
if (TcpConnect(interp, statePtr) != TCL_OK) {
- TcpCloseProc(statePtr, NULL);
- return NULL;
+ TcpCloseProc(statePtr, NULL);
+ return NULL;
}
snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));
statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
- statePtr, TCL_READABLE | TCL_WRITABLE);
+ statePtr, TCL_READABLE | TCL_WRITABLE);
if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
"auto crlf") == TCL_ERROR) {
Tcl_CloseEx(NULL, statePtr->channel, 0);
@@ -1574,10 +1573,10 @@ Tcl_OpenTcpClient(
Tcl_Channel
Tcl_MakeTcpClientChannel(
- void *sock) /* The socket to wrap up into a channel. */
+ void *sock) /* The socket to wrap up into a channel. */
{
return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
- TCL_READABLE | TCL_WRITABLE);
+ TCL_READABLE | TCL_WRITABLE);
}
/*
@@ -1599,7 +1598,7 @@ Tcl_MakeTcpClientChannel(
void *
TclpMakeTcpClientChannelMode(
- void *sock, /* The socket to wrap up into a channel. */
+ void *sock, /* The socket to wrap up into a channel. */
int mode) /* OR'ed combination of TCL_READABLE and
* TCL_WRITABLE to indicate file mode. */
{
@@ -1646,7 +1645,7 @@ Tcl_OpenTcpServerEx(
const char *service, /* Port number to open. */
const char *myHost, /* Name of local host. */
unsigned int flags, /* Flags. */
- int backlog, /* Length of OS listen backlog queue. */
+ int backlog, /* Length of OS listen backlog queue. */
Tcl_TcpAcceptProc *acceptProc,
/* Callback for accepting connections from new
* clients. */
@@ -1684,17 +1683,17 @@ Tcl_OpenTcpServerEx(
repeat:
if (retry > 0) {
- if (statePtr != NULL) {
- TcpCloseProc(statePtr, NULL);
- statePtr = NULL;
- }
- if (addrlist != NULL) {
- freeaddrinfo(addrlist);
- addrlist = NULL;
- }
- if (retry >= MAXRETRY) {
- goto error;
- }
+ if (statePtr != NULL) {
+ TcpCloseProc(statePtr, NULL);
+ statePtr = NULL;
+ }
+ if (addrlist != NULL) {
+ freeaddrinfo(addrlist);
+ addrlist = NULL;
+ }
+ if (retry >= MAXRETRY) {
+ goto error;
+ }
}
retry++;
chosenport = 0;
@@ -1705,14 +1704,14 @@ Tcl_OpenTcpServerEx(
}
if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
- &errorMsg)) {
+ &errorMsg)) {
my_errno = errno;
goto error;
}
for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
- addrPtr->ai_protocol);
+ addrPtr->ai_protocol);
if (sock == -1) {
if (howfar < SOCKET) {
howfar = SOCKET;
@@ -1760,100 +1759,101 @@ Tcl_OpenTcpServerEx(
#endif
}
- /*
- * Make sure we use the same port number when opening two server
- * sockets for IPv4 and IPv6 on a random port.
- *
- * As sockaddr_in6 uses the same offset and size for the port member
- * as sockaddr_in, we can handle both through the IPv4 API.
- */
+ /*
+ * Make sure we use the same port number when opening two server
+ * sockets for IPv4 and IPv6 on a random port.
+ *
+ * As sockaddr_in6 uses the same offset and size for the port member
+ * as sockaddr_in, we can handle both through the IPv4 API.
+ */
if (port == 0 && chosenport != 0) {
((struct sockaddr_in *) addrPtr->ai_addr)->sin_port =
- htons(chosenport);
+ htons(chosenport);
}
#ifdef IPV6_V6ONLY
/*
- * Missing on: Solaris 2.8
- */
+ * Missing on: Solaris 2.8
+ */
- if (addrPtr->ai_family == AF_INET6) {
- int v6only = 1;
+ if (addrPtr->ai_family == AF_INET6) {
+ int v6only = 1;
- (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
- &v6only, sizeof(v6only));
- }
+ (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &v6only, sizeof(v6only));
+ }
#endif /* IPV6_V6ONLY */
status = bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen);
- if (status == -1) {
+ if (status == -1) {
if (howfar < BIND) {
howfar = BIND;
my_errno = errno;
}
- close(sock);
- sock = -1;
- if (port == 0 && errno == EADDRINUSE) {
- goto repeat;
- }
- continue;
- }
- if (port == 0 && chosenport == 0) {
- address sockname;
- socklen_t namelen = sizeof(sockname);
-
- /*
- * Synchronize port numbers when binding to port 0 of multiple
- * addresses.
- */
-
- if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
- chosenport = ntohs(sockname.sa4.sin_port);
- }
- }
- if (backlog < 0) {
- backlog = SOMAXCONN;
- }
- status = listen(sock, backlog);
- if (status < 0) {
+ close(sock);
+ sock = -1;
+ if (port == 0 && errno == EADDRINUSE) {
+ goto repeat;
+ }
+ continue;
+ }
+ if (port == 0 && chosenport == 0) {
+ address sockname;
+ socklen_t namelen = sizeof(sockname);
+
+ /*
+ * Synchronize port numbers when binding to port 0 of multiple
+ * addresses.
+ */
+
+ if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
+ chosenport = ntohs(sockname.sa4.sin_port);
+ }
+ }
+ if (backlog < 0) {
+ backlog = SOMAXCONN;
+ }
+ status = listen(sock, backlog);
+ if (status < 0) {
if (howfar < LISTEN) {
howfar = LISTEN;
my_errno = errno;
}
- close(sock);
- sock = -1;
- if (port == 0 && errno == EADDRINUSE) {
- goto repeat;
- }
- continue;
- }
- if (statePtr == NULL) {
- /*
- * Allocate a new TcpState for this socket.
- */
-
- statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
- memset(statePtr, 0, sizeof(TcpState));
- statePtr->acceptProc = acceptProc;
- statePtr->acceptProcData = acceptProcData;
- snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));
- newfds = &statePtr->fds;
- } else {
- newfds = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
- memset(newfds, (int) 0, sizeof(TcpFdList));
- fds->next = newfds;
- }
- newfds->fd = sock;
- newfds->statePtr = statePtr;
- fds = newfds;
-
- /*
- * Set up the callback mechanism for accepting connections from new
- * clients.
- */
-
- Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
+ close(sock);
+ sock = -1;
+ if (port == 0 && errno == EADDRINUSE) {
+ goto repeat;
+ }
+ continue;
+ }
+ if (statePtr == NULL) {
+ /*
+ * Allocate a new TcpState for this socket.
+ */
+
+ statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
+ memset(statePtr, 0, sizeof(TcpState));
+ statePtr->acceptProc = acceptProc;
+ statePtr->acceptProcData = acceptProcData;
+ snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE,
+ PTR2INT(statePtr));
+ newfds = &statePtr->fds;
+ } else {
+ newfds = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
+ memset(newfds, (int) 0, sizeof(TcpFdList));
+ fds->next = newfds;
+ }
+ newfds->fd = sock;
+ newfds->statePtr = statePtr;
+ fds = newfds;
+
+ /*
+ * Set up the callback mechanism for accepting connections from new
+ * clients.
+ */
+
+ Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
}
error:
@@ -1866,15 +1866,15 @@ Tcl_OpenTcpServerEx(
return statePtr->channel;
}
if (interp != NULL) {
- Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", TCL_INDEX_NONE);
+ Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", TCL_INDEX_NONE);
if (errorMsg == NULL) {
- errno = my_errno;
- Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), TCL_INDEX_NONE);
- } else {
+ errno = my_errno;
+ Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), TCL_INDEX_NONE);
+ } else {
Tcl_AppendToObj(errorObj, errorMsg, TCL_INDEX_NONE);
}
- Tcl_SetObjResult(interp, errorObj);
+ Tcl_SetObjResult(interp, errorObj);
}
if (sock != -1) {
close(sock);
@@ -1900,7 +1900,7 @@ Tcl_OpenTcpServerEx(
static void
TcpAccept(
- void *data, /* Callback token. */
+ void *data, /* Callback token. */
TCL_UNUSED(int) /*mask*/)
{
TcpFdList *fds = (TcpFdList *)data; /* Client data of server socket. */
@@ -1938,9 +1938,9 @@ TcpAccept(
if (fds->statePtr->acceptProc != NULL) {
getnameinfo(&addr.sa, len, host, sizeof(host), port, sizeof(port),
- NI_NUMERICHOST|NI_NUMERICSERV);
+ NI_NUMERICHOST|NI_NUMERICSERV);
fds->statePtr->acceptProc(fds->statePtr->acceptProcData,
- newSockState->channel, host, atoi(port));
+ newSockState->channel, host, atoi(port));
}
}