| ︙ | | | ︙ | |
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
struct sockaddr sa;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
struct sockaddr_storage sas;
} address;
/*
* This structure describes per-instance state of a tcp based channel.
*/
typedef struct TcpState TcpState;
typedef struct TcpFdList {
TcpState *statePtr;
int fd;
struct TcpFdList *next;
} TcpFdList;
struct TcpState {
Tcl_Channel channel; /* Channel associated with this file. */
int flags; /* ORed combination of the bitfields defined
* below. */
TcpFdList fds; /* The file descriptors of the sockets. */
int interest; /* Event types of interest */
/*
* Only needed for server sockets
*/
|
|
|
|
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
struct sockaddr sa;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
struct sockaddr_storage sas;
} address;
/*
* This structure describes per-instance state of a tcp-based channel.
*/
typedef struct TcpState TcpState;
typedef struct TcpFdList {
TcpState *statePtr;
int fd;
struct TcpFdList *next;
} TcpFdList;
struct TcpState {
Tcl_Channel channel; /* Channel associated with this file. */
int flags; /* OR'ed combination of the bitfields defined
* below. */
TcpFdList fds; /* The file descriptors of the sockets. */
int interest; /* Event types of interest */
/*
* Only needed for server sockets
*/
|
| ︙ | | | ︙ | |
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
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. */
};
/*
* These bits may be ORed together into the "flags" field of a TcpState
* structure.
*/
#define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */
#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */
#define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to
* process an async connect. This
|
|
|
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
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. */
};
/*
* These bits may be OR'ed together into the "flags" field of a TcpState
* structure.
*/
#define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */
#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */
#define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to
* process an async connect. This
|
| ︙ | | | ︙ | |
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
|
/*
* ----------------------------------------------------------------------
*
* 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'.
*
* There are two modes of operation, defined by errorCodePtr:
* * 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 do not
* return any error code.
*
* Results:
* 0 if the connection has completed, -1 if still in progress or there is
* an error.
*
* Side effects:
|
|
|
|
|
|
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
|
/*
* ----------------------------------------------------------------------
*
* 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 occurs, 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 explicit 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 recv or sendto syscall so this is emulated here.
* * NULL: Called by a background 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.
*
* Side effects:
|
| ︙ | | | ︙ | |
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
|
if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
*errorCodePtr = ENOTCONN;
return -1;
}
/*
* Check if an async connect is running. If not return ok
*/
if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
return 0;
}
/*
|
|
|
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
|
if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) {
*errorCodePtr = ENOTCONN;
return -1;
}
/*
* Check if an async connect is running. If not return ok.
*/
if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
return 0;
}
/*
|
| ︙ | | | ︙ | |
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
|
/*
* 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
|
|
|
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
|
/*
* 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
* condition. 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
|
| ︙ | | | ︙ | |
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
|
*
*----------------------------------------------------------------------
*/
void *
TclpMakeTcpClientChannelMode(
void *sock, /* The socket to wrap up into a channel. */
int mode) /* ORed combination of TCL_READABLE and
* TCL_WRITABLE to indicate file mode. */
{
TcpState *statePtr;
char channelName[SOCK_CHAN_LENGTH];
statePtr = (TcpState *)ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
|
|
|
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
|
*
*----------------------------------------------------------------------
*/
void *
TclpMakeTcpClientChannelMode(
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. */
{
TcpState *statePtr;
char channelName[SOCK_CHAN_LENGTH];
statePtr = (TcpState *)ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
|
| ︙ | | | ︙ | |