| ︙ | | | ︙ | |
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
struct addrinfo *addrlist; /* Addresses to connect to. */
struct addrinfo *addr; /* Iterator over addrlist. */
struct addrinfo *myaddrlist;/* Local address. */
struct addrinfo *myaddr; /* Iterator over myaddrlist. */
int connectError; /* Cache status of async socket. */
int cachedBlocking; /* Cache blocking mode of async socket. */
volatile int connectError; /* Async connect error set by notifier thread.
* Access must be protected by semaphore */
struct TcpState *nextPtr; /* The next socket on the per-thread socket
* list. */
};
/*
* These bits may be ORed together into the "flags" field of a TcpState
* structure.
*/
#define TCP_ASYNC_SOCKET (1<<0) /* Asynchronous socket. */
#define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */
#define SOCKET_EOF (1<<2) /* A zero read happened on the
* socket. */
#define SOCKET_PENDING (1<<3) /* A message has been sent for this
* socket */
#define TCP_ASYNC_CONNECT_REENTER_PENDING (1<<4)
/* TcpConnect was called to
* process an async connect. This
* flag indicates that reentry is
* still pending */
#define TCP_ASYNC_CONNECT_FAILED (1<<5)
/* An async connect finally failed */
/*
* The following structure is what is added to the Tcl event queue when a
* socket event occurs.
*/
typedef struct {
|
>
|
>
|
<
|
<
|
|
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
struct addrinfo *addrlist; /* Addresses to connect to. */
struct addrinfo *addr; /* Iterator over addrlist. */
struct addrinfo *myaddrlist;/* Local address. */
struct addrinfo *myaddr; /* Iterator over myaddrlist. */
int connectError; /* Cache status of async socket. */
int cachedBlocking; /* Cache blocking mode of async socket. */
volatile int notifierConnectError;
/* Async connect error set by notifier thread.
* This error is still a windows error code.
* Access must be protected by semaphore */
struct TcpState *nextPtr; /* The next socket on the per-thread socket
* list. */
};
/*
* 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 SOCKET_EOF (1<<2) /* A zero read happened on the
* socket. */
#define SOCKET_PENDING (1<<3) /* A message has been sent for this
* socket */
#define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to
* process an async connect. This
* flag indicates that reentry is
* still pending */
#define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */
/*
* The following structure is what is added to the Tcl event queue when a
* socket event occurs.
*/
typedef struct {
|
| ︙ | | | ︙ | |
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
|
int mode) /* The mode to set. Can be one of
* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
TcpState *statePtr = instanceData;
if (mode == TCL_MODE_NONBLOCKING) {
statePtr->flags |= TCP_ASYNC_SOCKET;
} else {
statePtr->flags &= ~(TCP_ASYNC_SOCKET);
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* 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.
* There are two modes of operation, defined by errorCodePtr:
* * non-NULL: Called by explicite read/write command. block if
* socket is blocking. Return a possible error and clear it.
* * Null: Called by a backround operation. Never block and
* save eventual error in statePtr->connectError.
*
* Results:
* 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.
*
*----------------------------------------------------------------------
*/
static int
WaitForConnect(
TcpState *statePtr, /* State of the socket. */
int *errorCodePtr) /* Where to store errors?
* A passed null-pointer activates background mode.
* In this case, a possible error is stored in
* statePtr->connectError.
* In addition, we do never block and allow the next
* processing cycle to happen.
*/
{
int result;
int oldMode;
ThreadSpecificData *tsdPtr;
/*
* Check if an async connect error is not jet reported.
* If yes, report it now.
*/
if ( errorCodePtr != NULL && statePtr->connectError != 0 ) {
*errorCodePtr = statePtr->connectError;
statePtr->connectError = 0;
return -1;
}
/*
* Check if an async connect is running. If not return ok
*/
if ( !(statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING) )
return 0;
/*
* Be sure to disable event servicing so we are truly modal.
*/
oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
while (1) {
/* get statePtr lock */
tsdPtr = TclThreadDataKeyGet(&dataKey);
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/* Check for connect event */
if (statePtr->readyEvents & FD_CONNECT) {
/* Consume the connect event */
statePtr->readyEvents &= ~(FD_CONNECT);
/*
* For blocking sockets and foreground processing
* disable async connect as we continue now synchoneously
*/
if ( errorCodePtr != NULL &&
! (statePtr->flags & TCP_ASYNC_SOCKET) ) {
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
}
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
/* continue connect */
result = TcpConnect(NULL, statePtr);
/* Restore event service mode */
(void) Tcl_SetServiceMode(oldMode);
/* Succesfully connected or async connect restarted */
if (result == TCL_OK) {
if ( statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING ) {
if (errorCodePtr != NULL) {
*errorCodePtr = EWOULDBLOCK;
}
return -1;
}
return 0;
}
/* error case */
if (errorCodePtr != NULL) {
*errorCodePtr = Tcl_GetErrno();
} else {
statePtr->connectError = Tcl_GetErrno();
}
return -1;
}
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
/*
* A non blocking socket waiting for an asyncronous connect
* returns directly an error
*/
if ( errorCodePtr == NULL ) {
/* Backround operation */
return -1;
} else if (statePtr->flags & TCP_ASYNC_SOCKET) {
/* foreground operation but non blocking socket */
*errorCodePtr = EWOULDBLOCK;
return -1;
}
/*
* Wait until something happens.
*/
|
|
|
|
>
>
|
>
>
>
>
>
|
|
<
<
<
<
|
|
|
>
|
<
|
|
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
|
|
>
>
>
>
>
|
<
<
|
|
>
<
>
|
>
|
>
>
>
>
|
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
|
int mode) /* The mode to set. Can be one of
* TCL_MODE_BLOCKING or
* TCL_MODE_NONBLOCKING. */
{
TcpState *statePtr = instanceData;
if (mode == TCL_MODE_NONBLOCKING) {
statePtr->flags |= TCP_NONBLOCKING;
} else {
statePtr->flags &= ~(TCP_NONBLOCKING);
}
return 0;
}
/*
*----------------------------------------------------------------------
*
* 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. 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.
*
* Results:
* 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.
*
*----------------------------------------------------------------------
*/
static int
WaitForConnect(
TcpState *statePtr, /* State of the socket. */
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
*/
if ( errorCodePtr != NULL &&
(statePtr->flags & TCP_ASYNC_FAILED) ) {
*errorCodePtr = ENOTCONN;
return -1;
}
/*
* Check if an async connect is running. If not return ok
*/
if ( !(statePtr->flags & TCP_ASYNC_PENDING) )
return 0;
/*
* Be sure to disable event servicing so we are truly modal.
*/
oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
/*
* Loop in the blocking case until the connect signal is present
*/
while (1) {
/* get statePtr lock */
tsdPtr = TclThreadDataKeyGet(&dataKey);
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/* Check for connect event */
if (statePtr->readyEvents & FD_CONNECT) {
/* Consume the connect event */
statePtr->readyEvents &= ~(FD_CONNECT);
/*
* For blocking sockets and foreground processing
* disable async connect as we continue now synchoneously
*/
if ( errorCodePtr != NULL &&
! (statePtr->flags & TCP_NONBLOCKING) ) {
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
}
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
/*
* Continue connect.
* If switched to synchroneous connect, the connect is terminated.
*/
result = TcpConnect(NULL, statePtr);
/* Restore event service mode */
(void) Tcl_SetServiceMode(oldMode);
/*
* Check for Succesfull connect or async connect restart
*/
if (result == TCL_OK) {
/*
* Check for async connect restart
* (not possible for foreground blocking operation)
*/
if ( statePtr->flags & TCP_ASYNC_PENDING ) {
if (errorCodePtr != NULL) {
*errorCodePtr = EWOULDBLOCK;
}
return -1;
}
return 0;
}
/*
* Connect finally failed.
* For foreground operation return ENOTCONN.
*/
if (errorCodePtr != NULL) {
*errorCodePtr = ENOTCONN;
}
return -1;
}
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
/*
* Background operation returns with no action as there was no connect
* event
*/
if ( errorCodePtr == NULL ) {
return -1;
}
/*
* A non blocking socket waiting for an asyncronous connect
* returns directly the error EWOULDBLOCK
*/
if (statePtr->flags & TCP_NONBLOCKING) {
*errorCodePtr = EWOULDBLOCK;
return -1;
}
/*
* Wait until something happens.
*/
|
| ︙ | | | ︙ | |
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
|
break;
}
/*
* Check for error condition or underflow in non-blocking case.
*/
if ((statePtr->flags & TCP_ASYNC_SOCKET) || (error != WSAEWOULDBLOCK)) {
TclWinConvertError(error);
*errorCodePtr = Tcl_GetErrno();
bytesRead = -1;
break;
}
/*
|
|
|
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
|
break;
}
/*
* Check for error condition or underflow in non-blocking case.
*/
if ((statePtr->flags & TCP_NONBLOCKING) || (error != WSAEWOULDBLOCK)) {
TclWinConvertError(error);
*errorCodePtr = Tcl_GetErrno();
bytesRead = -1;
break;
}
/*
|
| ︙ | | | ︙ | |
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
|
* event. Note that Windows only sends a new writable event after a
* send fails with WSAEWOULDBLOCK.
*/
error = WSAGetLastError();
if (error == WSAEWOULDBLOCK) {
statePtr->readyEvents &= ~(FD_WRITE);
if (statePtr->flags & TCP_ASYNC_SOCKET) {
*errorCodePtr = EWOULDBLOCK;
written = -1;
break;
}
} else {
TclWinConvertError(error);
*errorCodePtr = Tcl_GetErrno();
|
|
|
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
|
* event. Note that Windows only sends a new writable event after a
* send fails with WSAEWOULDBLOCK.
*/
error = WSAGetLastError();
if (error == WSAEWOULDBLOCK) {
statePtr->readyEvents &= ~(FD_WRITE);
if (statePtr->flags & TCP_NONBLOCKING) {
*errorCodePtr = EWOULDBLOCK;
written = -1;
break;
}
} else {
TclWinConvertError(error);
*errorCodePtr = Tcl_GetErrno();
|
| ︙ | | | ︙ | |
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
|
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_CONNECT_REENTER_PENDING) ) {
if ( statePtr->flags & TCP_ASYNC_CONNECT_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.
*/
|
|
|
|
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
|
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 ) {
/*
* 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.
*/
|
| ︙ | | | ︙ | |
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
|
int ret;
DWORD err;
/*
* Populater the err Variable with a possix error
*/
optlen = sizeof(int);
ret = TclWinGetSockOpt(sock, SOL_SOCKET, SO_ERROR,
(char *)&err, &optlen);
/*
* The error was not returned directly but should be
* taken from WSA
*/
if (ret == SOCKET_ERROR) {
err = WSAGetLastError();
|
|
|
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
|
int ret;
DWORD err;
/*
* Populater the err Variable with a possix 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
*/
if (ret == SOCKET_ERROR) {
err = WSAGetLastError();
|
| ︙ | | | ︙ | |
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
|
return TCL_OK;
}
if ((len > 1) && (optionName[1] == 'c') &&
(strncmp(optionName, "-connecting", len) == 0)) {
Tcl_DStringAppend(dsPtr,
(statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING)
? "1" : "0", -1);
return TCL_OK;
}
if (interp != NULL && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) {
reverseDNS = NI_NUMERICHOST;
}
|
|
|
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
|
return TCL_OK;
}
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_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) {
reverseDNS = NI_NUMERICHOST;
}
|
| ︙ | | | ︙ | |
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
|
/* get statePtr lock */
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/*
* Reset last error from last try
*/
statePtr->connectError = 0;
Tcl_SetErrno(0);
statePtr->sockets->fd = socket(statePtr->myaddr->ai_family, SOCK_STREAM, 0);
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
|
|
|
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
|
/* 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);
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
|
| ︙ | | | ︙ | |
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
|
/*
* Asynchroneous connect
*/
/*
* Remember that we jump back behind this next round
*/
statePtr->flags |= TCP_ASYNC_CONNECT_REENTER_PENDING;
return TCL_OK;
reenter:
/*
* Re-entry point for async connect after connect event or
* blocking operation
*
* Clear the reenter flag
*/
statePtr->flags &= ~(TCP_ASYNC_CONNECT_REENTER_PENDING);
/* get statePtr lock */
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/* Get signaled connect error */
Tcl_SetErrno(statePtr->connectError);
/* Clear eventual connect flag */
statePtr->selectEvents &= ~(FD_CONNECT);
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
}
/*
|
|
|
|
|
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
|
/*
* Asynchroneous connect
*/
/*
* Remember that we jump back behind this next round
*/
statePtr->flags |= TCP_ASYNC_PENDING;
return TCL_OK;
reenter:
/*
* Re-entry point for async connect after connect event or
* blocking operation
*
* Clear the reenter flag
*/
statePtr->flags &= ~(TCP_ASYNC_PENDING);
/* get statePtr lock */
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/* Get signaled connect error */
TclWinConvertError((DWORD) statePtr->notifierConnectError);
/* Clear eventual connect flag */
statePtr->selectEvents &= ~(FD_CONNECT);
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
}
/*
|
| ︙ | | | ︙ | |
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
|
*/
statePtr->selectEvents = FD_WRITE|FD_READ;
/* 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_CONNECT_FAILED;
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
}
/*
* Error message on syncroneous connect
*/
if (interp != NULL) {
|
|
>
>
|
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
|
*/
statePtr->selectEvents = FD_WRITE|FD_READ;
/* 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' */
statePtr->connectError = Tcl_GetErrno();
/* Free list lock */
SetEvent(tsdPtr->socketListLock);
}
/*
* Error message on syncroneous connect
*/
if (interp != NULL) {
|
| ︙ | | | ︙ | |
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
|
* InitSockets --
*
* Initialize the socket module. If winsock startup is successful,
* registers the event window for the socket notifier code.
*
* Assumes socketMutex is held.
*
* Results:
* None.
*
* Side effects:
* Initializes winsock, registers a new window class and creates a
* window for use in asynchronous socket notification.
*
|
>
>
>
>
>
>
|
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
|
* InitSockets --
*
* Initialize the socket module. If winsock startup is successful,
* registers the event window for the socket notifier code.
*
* Assumes socketMutex is held.
*
* Warning:
* This check was useful in times of Windows98 where WinSock may
* not be available. This is not the case any more.
* This function may be removed with TCL 9.0.
* Any failures may be reported as panics.
*
* Results:
* None.
*
* Side effects:
* Initializes winsock, registers a new window class and creates a
* window for use in asynchronous socket notification.
*
|
| ︙ | | | ︙ | |
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
|
/*
*----------------------------------------------------------------------
*
* SocketsEnabled --
*
* Check that the WinSock was successfully initialized.
*
* Results:
* 1 if it is.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
|
>
>
>
>
>
|
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
|
/*
*----------------------------------------------------------------------
*
* SocketsEnabled --
*
* Check that the WinSock was successfully initialized.
*
* Warning:
* This check was useful in times of Windows98 where WinSock may
* not be available. This is not the case any more.
* This function may be removed with TCL 9.0
*
* Results:
* 1 if it is.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
|
| ︙ | | | ︙ | |
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
|
statePtr->flags &= ~SOCKET_PENDING;
/*
* Continue async connect if pending and ready
*/
if ( statePtr->readyEvents & FD_CONNECT ) {
if ( statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING ) {
/*
* Do one step and save eventual connect error
*/
SetEvent(tsdPtr->socketListLock);
WaitForConnect(statePtr,NULL);
|
|
|
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
|
statePtr->flags &= ~SOCKET_PENDING;
/*
* Continue async connect if pending and ready
*/
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);
|
| ︙ | | | ︙ | |
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
|
mask |= TCL_READABLE|TCL_WRITABLE;
} else if (events & FD_READ) {
/*
* Throw the readable event if an async connect failed.
*/
if ( statePtr->flags & TCP_ASYNC_CONNECT_FAILED ) {
mask |= TCL_READABLE;
} else {
fd_set readFds;
struct timeval timeout;
|
|
|
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
|
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;
} else {
fd_set readFds;
struct timeval timeout;
|
| ︙ | | | ︙ | |
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
|
/* exit loop if event occured */
if (event_found) {
break;
}
/* Exit loop if event did not occur but this is a non-blocking channel */
if (statePtr->flags & TCP_ASYNC_SOCKET) {
*errorCodePtr = EWOULDBLOCK;
result = 0;
break;
}
/*
* Wait until something happens.
|
|
|
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
|
/* exit loop if event occured */
if (event_found) {
break;
}
/* Exit loop if event did not occur but this is a non-blocking channel */
if (statePtr->flags & TCP_NONBLOCKING) {
*errorCodePtr = EWOULDBLOCK;
result = 0;
break;
}
/*
* Wait until something happens.
|
| ︙ | | | ︙ | |
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
|
if (event & FD_CONNECT) {
/*
* Remember any error that occurred so we can report
* connection failures.
*/
if (error != ERROR_SUCCESS) {
TclWinConvertError((DWORD) error);
statePtr->connectError = Tcl_GetErrno();
}
}
/*
* Inform main thread about signaled events
*/
statePtr->readyEvents |= event;
|
<
|
|
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
|
if (event & FD_CONNECT) {
/*
* 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;
|
| ︙ | | | ︙ | |
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
|
*
* TclWinGetSockOpt, et al. --
*
* These functions are wrappers that let us bind the WinSock API
* dynamically so we can run on systems that don't have the wsock32.dll.
* We need wrappers for these interfaces because they are called from the
* generic Tcl code.
*
* Results:
* As defined for each function.
*
* Side effects:
* As defined for each function.
*
|
>
>
>
>
|
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
|
*
* TclWinGetSockOpt, et al. --
*
* These functions are wrappers that let us bind the WinSock API
* dynamically so we can run on systems that don't have the wsock32.dll.
* We need wrappers for these interfaces because they are called from the
* generic Tcl code.
* Those functions are exported by the stubs table.
*
* Warning:
* Those functions are depreciated and will be removed with TCL 9.0.
*
* Results:
* As defined for each function.
*
* Side effects:
* As defined for each function.
*
|
| ︙ | | | ︙ | |