| ︙ | | |
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
-
-
-
-
-
-
-
-
|
*
* (Ad 2) The main functions for this are SocketSetupProc() and
* SocketCheckProc().
*/
#include "tclWinInt.h"
//#define DEBUGGING
#ifdef DEBUGGING
#define DEBUG(x) fprintf(stderr, ">>> %p %s(%d): %s<<<\n", \
statePtr, __FUNCTION__, __LINE__, x)
#else
#define DEBUG(x)
#endif
/*
* Which version of the winsock API do we want?
*/
#define WSA_VERSION_MAJOR 1
#define WSA_VERSION_MINOR 1
|
| ︙ | | |
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
|
+
+
+
+
-
-
-
+
|
* The following variable holds the network name of this host.
*/
static TclInitProcessGlobalValueProc InitializeHostName;
static ProcessGlobalValue hostName =
{0, 0, NULL, NULL, InitializeHostName, NULL, NULL};
/*
* Address print debug functions
*/
#if 0
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);
#ifdef DEBUGGING
fprintf(stderr,"%s: [%s]:%s\n", prefix, host, port);
#endif
}
void printaddrinfolist(struct addrinfo *addrlist, char *prefix)
{
struct addrinfo *ai;
for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
printaddrinfo(ai, prefix);
}
}
#endif
/*
*----------------------------------------------------------------------
*
* InitializeHostName --
*
* This routine sets the process global value of the name of the local
|
| ︙ | | |
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
|
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
|
-
-
-
|
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-sockname");
Tcl_DStringStartSublist(dsPtr);
}
for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
sock = fds->fd;
#ifdef DEBUGGING
fprintf(stderr, "sock == %d\n", sock);
#endif
size = sizeof(sockname);
if (getsockname(sock, &(sockname.sa), &size) >= 0) {
int flags = reverseDNS;
found = 1;
getnameinfo(&sockname.sa, size, host, sizeof(host),
NULL, 0, NI_NUMERICHOST);
|
| ︙ | | |
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
|
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
|
-
-
-
|
ClientData instanceData, /* The socket state. */
int mask) /* Events of interest; an OR-ed combination of
* TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
TcpState *statePtr = instanceData;
DEBUG((mask & TCL_READABLE) ? "+r":"-r");
DEBUG((mask & TCL_WRITABLE) ? "+w":"-w");
/*
* Update the watch events mask. Only if the socket is not a server
* socket. [Bug 557878]
*/
if (!statePtr->acceptProc) {
statePtr->watchEvents = 0;
|
| ︙ | | |
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
|
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
|
* was not jet received
*/
int async_connect = statePtr->flags & TCP_ASYNC_CONNECT;
/* We were called by the event procedure and continue our loop */
int async_callback = statePtr->sockets->fd != INVALID_SOCKET;
ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
DEBUG(async_connect ? "async connect" : "sync connect");
if (async_callback) {
DEBUG("subsequent call");
goto reenter;
} else {
DEBUG("first call");
}
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) {
DEBUG("inner loop");
/*
* No need to try combinations of local and remote addresses
* of different families.
*/
if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
DEBUG("family mismatch");
continue;
}
DEBUG(statePtr->myaddr->ai_family == AF_INET ? "IPv4" : "IPv6");
printaddrinfo(statePtr->myaddr, "~~ from");
printaddrinfo(statePtr->addr, "~~ to");
/*
* Close the socket if it is still open from the last unsuccessful
* iteration.
*/
if (statePtr->sockets->fd != INVALID_SOCKET) {
DEBUG("closesocket");
closesocket(statePtr->sockets->fd);
}
/* 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);
/* continue on socket creation error */
if (statePtr->sockets->fd == INVALID_SOCKET) {
DEBUG("socket() failed");
TclWinConvertError((DWORD) WSAGetLastError());
continue;
}
#ifdef DEBUGGING
fprintf(stderr, "Client socket %d created\n", statePtr->sockets->fd);
#endif
/*
* Win-NT has a misfeature that sockets are inherited in child
* processes by default. Turn off the inherit bit.
*/
SetHandleInformation((HANDLE) statePtr->sockets->fd, HANDLE_FLAG_INHERIT, 0);
/*
* Set kernel space buffering
*/
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) {
DEBUG("bind() failed");
TclWinConvertError((DWORD) WSAGetLastError());
continue;
}
/*
* For asyncroneous connect set the socket in nonblocking mode
* and activate connect notification
*/
|
| ︙ | | |
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
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
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
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
|
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
|
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
|
(LPARAM) statePtr);
}
/*
* Attempt to connect to the remote socket.
*/
DEBUG("connect()");
connect(statePtr->sockets->fd, statePtr->addr->ai_addr,
statePtr->addr->ai_addrlen);
error = WSAGetLastError();
TclWinConvertError(error);
if (async_connect && error == WSAEWOULDBLOCK) {
/*
* Asynchroneous connect
*/
DEBUG("WSAEWOULDBLOCK");
/*
* Remember that we jump back behind this next round
*/
statePtr->flags |= TCP_ASYNC_CONNECT_REENTER_PENDING;
return TCL_OK;
reenter:
DEBUG("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);
}
#ifdef DEBUGGING
fprintf(stderr, "connectError: %d\n", Tcl_GetErrno());
#endif
/*
* Clear the tsd socket list pointer if we did not wait for
* the FD_CONNECT asyncroneously
*/
tsdPtr->pendingTcpState = NULL;
if (Tcl_GetErrno() == 0) {
goto out;
}
}
}
out:
/*
* Socket connected or connection failed
*/
DEBUG("connected or finally failed");
/*
* Final connect failure
*/
if ( Tcl_GetErrno() == 0 ) {
/*
* Succesfully connected
*/
/*
* Set up the select mask for read/write events.
*/
DEBUG("selectEvents = FD_READ | FD_WRITE | FD_CLOSE");
statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;
/*
* Register for interest in events in the select mask. Note that this
* automatically places the socket into non-blocking mode.
*/
SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
(LPARAM) statePtr);
} else {
/*
* Connect failed
*/
DEBUG("ERRNO");
/*
* For async connect schedule a writable event to report the fail.
*/
if (async_callback) {
/*
* Set up the select mask for read/write events.
*/
DEBUG("selectEvents = FD_WRITE/FD_READ for connect fail");
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;
|
| ︙ | | |
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
|
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
|
-
-
-
|
}
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't open socket: %s", errorMsg));
}
return NULL;
}
printaddrinfolist(myaddrlist, "local");
printaddrinfolist(addrlist, "remote");
statePtr = NewSocketInfo(INVALID_SOCKET);
statePtr->addrlist = addrlist;
statePtr->myaddrlist = myaddrlist;
if (async) {
statePtr->flags |= TCP_ASYNC_CONNECT;
}
/*
* Create a new client socket and wrap it in a channel.
*/
DEBUG("");
if (CreateClientSocket(interp, statePtr) != TCL_OK) {
TcpCloseProc(statePtr, NULL);
return NULL;
}
sprintf(channelName, SOCK_TEMPLATE, statePtr);
|
| ︙ | | |
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
|
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
|
-
|
*/
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
for (statePtr = tsdPtr->socketList; statePtr != NULL;
statePtr = statePtr->nextPtr) {
if (statePtr->readyEvents &
(statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)
) {
DEBUG("Tcl_SetMaxBlockTime");
Tcl_SetMaxBlockTime(&blockTime);
break;
}
}
SetEvent(tsdPtr->socketListLock);
}
|
| ︙ | | |
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
|
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
|
-
-
|
* queued (caused by persistent states that won't generate WinSock
* events).
*/
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
for (statePtr = tsdPtr->socketList; statePtr != NULL;
statePtr = statePtr->nextPtr) {
DEBUG("Socket loop");
if ((statePtr->readyEvents &
(statePtr->watchEvents | FD_CONNECT | FD_ACCEPT))
&& !(statePtr->flags & SOCKET_PENDING)
) {
DEBUG("Event found");
statePtr->flags |= SOCKET_PENDING;
evPtr = ckalloc(sizeof(SocketEvent));
evPtr->header.proc = SocketEventProc;
evPtr->socket = statePtr->sockets->fd;
Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
}
}
|
| ︙ | | |
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
|
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
|
-
+
-
|
static int
SocketEventProc(
Tcl_Event *evPtr, /* Event to service. */
int flags) /* Flags that indicate what events to handle,
* such as TCL_FILE_EVENTS. */
{
TcpState *statePtr = NULL; /* DEBUG */
TcpState *statePtr;
SocketEvent *eventPtr = (SocketEvent *) evPtr;
int mask = 0, events;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
TcpFdList *fds;
SOCKET newSocket;
address addr;
int len;
DEBUG("");
if (!(flags & TCL_FILE_EVENTS)) {
return 0;
}
/*
* Find the specified socket on the socket list.
*/
|
| ︙ | | |
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
|
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
|
-
|
}
statePtr->flags &= ~SOCKET_PENDING;
/* Continue async connect if pending and ready */
if ( statePtr->readyEvents & FD_CONNECT ) {
statePtr->readyEvents &= ~(FD_CONNECT);
DEBUG("FD_CONNECT");
if ( statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING ) {
SetEvent(tsdPtr->socketListLock);
CreateClientSocket(NULL, statePtr);
return 1;
}
}
|
| ︙ | | |
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
|
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
|
-
-
-
-
+
+
+
-
|
* out for the channel being deleted out from under us. This may cause
* a redundant trip through the event loop, but it's simpler than
* trying to do unwind protection.
*/
Tcl_Time blockTime = { 0, 0 };
DEBUG("FD_CLOSE");
Tcl_SetMaxBlockTime(&blockTime);
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;
/*
* We must check to see if data is really available, since someone
* could have consumed the data in the meantime. Turn off async
* notification so select will work correctly. If the socket is still
* readable, notify the channel driver, otherwise reset the async
* select handler and keep waiting.
* notification so select will work correctly. If the socket is
* still readable, notify the channel driver, otherwise reset the
* async select handler and keep waiting.
*/
DEBUG("FD_READ");
SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
(WPARAM) UNSELECT, (LPARAM) statePtr);
FD_ZERO(&readFds);
FD_SET(statePtr->sockets->fd, &readFds);
timeout.tv_usec = 0;
|
| ︙ | | |
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
|
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
|
-
-
-
|
}
/*
* writable event
*/
if (events & FD_WRITE) {
DEBUG("FD_WRITE");
mask |= TCL_WRITABLE;
}
/*
* Call registered event procedures
*/
if (mask) {
DEBUG("Calling Tcl_NotifyChannel...");
Tcl_NotifyChannel(statePtr->channel, mask);
}
DEBUG("returning...");
return 1;
}
/*
*----------------------------------------------------------------------
*
* AddSocketInfoFd --
|
| ︙ | | |
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
|
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
|
-
|
{
int result = 1;
int oldMode;
ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
/*
* Be sure to disable event servicing so we are truly modal.
*/
DEBUG("=============");
oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
/*
* Reset WSAAsyncSelect so we have a fresh set of events pending.
*/
|
| ︙ | | |
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
|
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
|
-
+
|
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
int event, error;
SOCKET socket;
TcpState *statePtr = NULL; /* DEBUG */
TcpState *statePtr;
int info_found = 0;
TcpFdList *fds = NULL;
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
#ifdef _WIN64
GetWindowLongPtr(hwnd, GWLP_USERDATA);
#else
GetWindowLong(hwnd, GWL_USERDATA);
|
| ︙ | | |
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
|
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
|
break;
case SOCKET_MESSAGE:
event = WSAGETSELECTEVENT(lParam);
error = WSAGETSELECTERROR(lParam);
socket = (SOCKET) wParam;
#ifdef DEBUGGING
fprintf(stderr,"event = %d, error=%d\n",event,error);
#endif
if (event & FD_READ) DEBUG("READ Event");
if (event & FD_WRITE) DEBUG("WRITE Event");
if (event & FD_CLOSE) DEBUG("CLOSE Event");
if (event & FD_CONNECT)
DEBUG("CONNECT Event");
if (event & FD_ACCEPT) DEBUG("ACCEPT Event");
DEBUG("Get list lock");
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
/*
* Find the specified socket on the socket list and update its
* eventState flag.
*/
for (statePtr = tsdPtr->socketList; statePtr != NULL;
statePtr = statePtr->nextPtr) {
DEBUG("Cur InfoPtr");
if ( FindFDInList(statePtr,socket) ) {
info_found = 1;
DEBUG("InfoPtr found");
break;
}
}
/*
* Check if there is a pending info structure not jet in the
* list
*/
if ( !info_found
&& tsdPtr->pendingTcpState != NULL
&& FindFDInList(tsdPtr->pendingTcpState,socket) ) {
statePtr = tsdPtr->pendingTcpState;
DEBUG("Pending InfoPtr found");
info_found = 1;
}
if (info_found) {
if (event & FD_READ)
DEBUG("|->FD_READ");
if (event & FD_WRITE)
DEBUG("|->FD_WRITE");
/*
* 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.
*/
if (event & FD_CLOSE) {
DEBUG("FD_CLOSE");
statePtr->acceptEventCount = 0;
statePtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT);
} else if (event & FD_ACCEPT) {
DEBUG("FD_ACCEPT");
statePtr->acceptEventCount++;
statePtr->acceptEventCount++;
}
if (event & FD_CONNECT) {
DEBUG("FD_CONNECT");
/*
* Remember any error that occurred so we can report
* connection failures.
*/
if (error != ERROR_SUCCESS) {
TclWinConvertError((DWORD) error);
statePtr->connectError = Tcl_GetErrno();
|
| ︙ | | |
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
|
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
|
-
-
-
-
-
-
-
-
-
-
-
-
|
SetEvent(tsdPtr->readyEvent);
Tcl_ThreadAlert(tsdPtr->threadId);
}
SetEvent(tsdPtr->socketListLock);
break;
case SOCKET_SELECT:
DEBUG("SOCKET_SELECT");
statePtr = (TcpState *) lParam;
for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
#ifdef DEBUGGING
fprintf(stderr,"loop over fd = %d\n",fds->fd);
#endif
if (wParam == SELECT) {
DEBUG("SELECT");
if (statePtr->selectEvents & FD_READ) DEBUG(" READ");
if (statePtr->selectEvents & FD_WRITE) DEBUG(" WRITE");
if (statePtr->selectEvents & FD_CLOSE) DEBUG(" CLOSE");
if (statePtr->selectEvents & FD_CONNECT) DEBUG(" CONNECT");
if (statePtr->selectEvents & FD_ACCEPT) DEBUG(" ACCEPT");
WSAAsyncSelect(fds->fd, hwnd,
SOCKET_MESSAGE, statePtr->selectEvents);
} else {
/*
* Clear the selection mask
*/
DEBUG("!SELECT");
WSAAsyncSelect(fds->fd, hwnd, 0, 0);
}
}
break;
case SOCKET_TERMINATE:
DEBUG("SOCKET_TERMINATE");
DestroyWindow(hwnd);
break;
}
return 0;
}
|
| ︙ | | |
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
|
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
|
-
-
-
|
static int
FindFDInList(
TcpState *statePtr,
SOCKET socket)
{
TcpFdList *fds;
for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
#ifdef DEBUGGING
fprintf(stderr,"socket = %d, fd=%d\n",socket,fds);
#endif
if (fds->fd == socket) {
return 1;
}
}
return 0;
}
|
| ︙ | | |
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
|
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
|
-
-
-
|
Tcl_MutexLock(&socketMutex);
InitSockets();
Tcl_MutexUnlock(&socketMutex);
tsdPtr = TCL_TSD_INIT(&dataKey);
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
DEBUG("Inserting pointer to list");
statePtr->nextPtr = tsdPtr->socketList;
tsdPtr->socketList = statePtr;
if (statePtr == tsdPtr->pendingTcpState) {
DEBUG("Clearing temporary info pointer");
tsdPtr->pendingTcpState = NULL;
}
SetEvent(tsdPtr->socketListLock);
notifyCmd = SELECT;
} else {
TcpState **nextPtrPtr;
int removed = 0;
tsdPtr = TCL_TSD_INIT(&dataKey);
/*
* TIP #218, Bugfix: All access to socketList has to be protected by
* the lock.
*/
WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
DEBUG("Removing pointer from list");
for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;
nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
if ((*nextPtrPtr) == statePtr) {
(*nextPtrPtr) = statePtr->nextPtr;
removed = 1;
break;
}
|
| ︙ | | |