| ︙ | | |
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
|
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
|
-
+
-
+
|
*errorCodePtr = ENOTCONN;
return -1;
}
/*
* Check if an async connect is running. If not return ok
*/
if (!(statePtr->flags & TCP_ASYNC_PENDING)) {
return 0;
}
if (errorCodePtr == NULL || (statePtr->flags & TCP_NONBLOCKING)) {
timeout = 0;
} else {
timeout = -1;
}
do {
if (TclUnixWaitForFile(statePtr->fds.fd,
|
| ︙ | | |
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
|
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
|
-
+
-
+
|
/*
* Delete a file handler that may be active for this socket if this is a
* server socket - the file handler was created automatically by Tcl as
* part of the mechanism to accept new client connections. Channel
* handlers are already deleted in the generic IO channel closing code
* that called this function, so we do not have to delete them here.
*/
for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
if (fds->fd < 0) {
continue;
}
Tcl_DeleteFileHandler(fds->fd);
if (close(fds->fd) < 0) {
errorCode = errno;
}
}
fds = statePtr->fds.next;
while (fds != NULL) {
TcpFdList *next = fds->next;
ckfree(fds);
fds = next;
}
|
| ︙ | | |
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
|
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
|
-
+
|
/*
* 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 (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. */
statePtr->filehandlers = mask;
} else if (mask) {
/*
|
| ︙ | | |
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
|
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
|
-
+
|
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) {
int reuseaddr = 1;
/*
* No need to try combinations of local and remote addresses of
* different families.
*/
if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
continue;
|
| ︙ | | |
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
|
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
|
-
+
-
+
-
+
-
+
-
+
-
+
|
continue;
}
/*
* Set the close-on-exec flag so that the socket will not get
* inherited by child processes.
*/
fcntl(statePtr->fds.fd, F_SETFD, FD_CLOEXEC);
/*
* Set kernel space buffering
*/
TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);
if (async) {
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. */
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
* EINPROGRESS but at a later time it will complete. The caller
* will set up a file handler on the socket if she is interested
* in being informed when the connect completes.
*/
ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
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;
|
| ︙ | | |
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
|
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
|
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
|
if (sock == -1) {
if (howfar < SOCKET) {
howfar = SOCKET;
my_errno = errno;
}
continue;
}
/*
* Set the close-on-exec flag so that the socket will not get
* inherited by child processes.
*/
fcntl(sock, F_SETFD, FD_CLOEXEC);
/*
* Set kernel space buffering
*/
TclSockMinimumBuffers(INT2PTR(sock), SOCKET_BUFSIZE);
/*
* Set up to reuse server addresses automatically and bind to the
* specified port.
*/
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *) &reuseaddr, sizeof(reuseaddr));
/*
* 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.
*/
|
| ︙ | | |
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
|
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
|
-
+
|
#endif /* IPV6_V6ONLY */
status = bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen);
if (status == -1) {
if (howfar < BIND) {
howfar = BIND;
my_errno = errno;
}
}
close(sock);
sock = -1;
continue;
}
if (port == 0 && chosenport == 0) {
address sockname;
socklen_t namelen = sizeof(sockname);
|
| ︙ | | |
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
|
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
|
-
+
-
+
-
+
|
sock = -1;
continue;
}
if (statePtr == NULL) {
/*
* Allocate a new TcpState for this socket.
*/
statePtr = ckalloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->acceptProc = acceptProc;
statePtr->acceptProcData = acceptProcData;
sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);
newfds = &statePtr->fds;
} else {
newfds = ckalloc(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:
if (addrlist != NULL) {
freeaddrinfo(addrlist);
}
|
| ︙ | | |
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
|
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
|
-
+
|
TcpFdList *fds = data; /* Client data of server socket. */
int newsock; /* The new client socket */
TcpState *newSockState; /* State for new socket. */
address addr; /* The remote address */
socklen_t len; /* For accept interface */
char channelName[SOCK_CHAN_LENGTH];
char host[NI_MAXHOST], port[NI_MAXSERV];
len = sizeof(addr);
newsock = accept(fds->fd, &addr.sa, &len);
if (newsock < 0) {
return;
}
/*
|
| ︙ | | |