Diff
Not logged in

Differences From Artifact [d0e9b72ac1]:

To Artifact [c35e3bf5e3]:


1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18










-
+







/* 
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclWinSock.c,v 1.30 2002/11/27 02:22:23 davygrvy Exp $
 * RCS: @(#) $Id: tclWinSock.c,v 1.31 2002/11/27 05:29:46 davygrvy Exp $
 */

#include "tclWinInt.h"

/*
 * Make sure to remove the redirection defines set in tclWinPort.h
 * that is in use in other sections of the core, except for us.
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
82
83
84
85
86
87
88











89
90
91
92
93
94
95







-
-
-
-
-
-
-
-
-
-
-








#define SOCKET_MESSAGE	    WM_USER+1
#define SOCKET_SELECT	    WM_USER+2
#define SOCKET_TERMINATE    WM_USER+3
#define SELECT		    TRUE
#define UNSELECT	    FALSE

/*
 * Accepted sockets done in the message handling thread are stored here
 * and appended to the listen sockets SocketInfo struct until they are
 * processed.
 */

typedef struct SocketAcceptInfo {
    SOCKET newSock;
    SOCKADDR_IN newAddr;
} SocketAcceptInfo;

/*
 * The following structure is used to store the data associated with
 * each socket.
 */

typedef struct SocketInfo {
    Tcl_Channel channel;	   /* Channel associated with this
760
761
762
763
764
765
766

767

768
769
770
771
772
773
774
775
776
777
778
779
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
749
750
751
752
753
754
755
756

757
758
759
760
761
762

763
764
765
766
767
768

769
770
771
772
773
774
775
776






777
778
779
780
781
782
783







+
-
+





-






-
+







-
-
-
-
-
-







    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
    for (infoPtr = tsdPtr->socketList; infoPtr != NULL; 
	    infoPtr = infoPtr->nextPtr) {
	if (infoPtr->socket == eventPtr->socket) {
	    break;
	}
    }
    SetEvent(tsdPtr->socketListLock);
    

    /*
     * Discard events that have gone stale.
     */

    if (!infoPtr) {
	SetEvent(tsdPtr->socketListLock);
	return 1;
    }

    infoPtr->flags &= ~SOCKET_PENDING;

    /*
     * Handle all accepted connections directly.
     * Handle connection requests directly.
     */

    if (infoPtr->readyEvents & FD_ACCEPT) {
	TcpAccept(infoPtr);
	return 1;
    }

    /*
     * Release the lock here as FD_ACCEPTs are a special case.
     */

    SetEvent(tsdPtr->socketListLock);

    /*
     * Mask off unwanted events and compute the read/write mask so 
     * we can notify the channel.
     */

    events = infoPtr->readyEvents & infoPtr->watchEvents;

1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
1012







-
+







    int port;			/* Port number to open. */
    CONST char *host;		/* Name of host on which to open port. */
    int server;			/* 1 if socket should be a server socket,
				 * else 0 for a client socket. */
    CONST char *myaddr;		/* Optional client-side address */
    int myport;			/* Optional client-side port */
    int async;			/* If nonzero, connect client socket
                                 * asynchronously. */
				 * asynchronously. */
{
    u_long flag = 1;		/* Indicates nonblocking mode. */
    int asyncConnect = 0;	/* Will be 1 if async connect is
				 * in progress. */
    SOCKADDR_IN sockaddr;	/* Socket address */
    SOCKADDR_IN mysockaddr;	/* Socket address for client */
    SOCKET sock;
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
1355
1356
1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367
1368
1369







-
+







     */

    infoPtr = CreateSocket(interp, port, host, 0, myaddr, myport, async);
    if (infoPtr == NULL) {
	return NULL;
    }

    wsprintf(channelName, "sock%d", infoPtr->socket);
    wsprintfA(channelName, "sock%d", infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
        Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
        return (Tcl_Channel) NULL;
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
1434







-
+







     * Start watching for read/write events on the socket.
     */

    infoPtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,
	    (WPARAM) SELECT, (LPARAM) infoPtr);

    wsprintf(channelName, "sock%d", infoPtr->socket);
    wsprintfA(channelName, "sock%d", infoPtr->socket);
    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto crlf");
    return infoPtr->channel;
}

/*
1490
1491
1492
1493
1494
1495
1496
1497

1498
1499
1500
1501
1502
1503
1504
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1487







-
+







    if (infoPtr == NULL) {
	return NULL;
    }

    infoPtr->acceptProc = acceptProc;
    infoPtr->acceptProcData = acceptProcData;

    wsprintf(channelName, "sock%d", infoPtr->socket);
    wsprintfA(channelName, "sock%d", infoPtr->socket);

    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    (ClientData) infoPtr, 0);
    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-eofchar", "")
	    == TCL_ERROR) {
        Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);
        return (Tcl_Channel) NULL;
1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1520
1521
1522
1523
1524
1525
1526

1527
1528
1529
1530
1531
1532
1533
1534







-
+







	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    /*
     * Accept the incoming connection request.
     */

    len = sizeof(SOCKADDR_IN);
  

    newSocket = winSock.accept(infoPtr->socket, (SOCKADDR *)&addr,
	    &len);

    /*
     * Clear the ready mask so we can detect the next connection request.
     * Note that connection requests are level triggered, so if there is
     * a request already pending, a new event will be generated.
1858
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868

1869
1870
1871
1872
1873
1874
1875
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850

1851
1852
1853
1854
1855
1856
1857
1858







-
+


-
+







 *----------------------------------------------------------------------
 *
 * TcpSetOptionProc --
 *
 *	Sets Tcp channel specific options.
 *
 * Results:
 *	...
 *	None, unless an error happens.
 *
 * Side effects:
 *	...
 *	Changes attributes of the socket at the system level.
 *
 *----------------------------------------------------------------------
 */

static int
TcpSetOptionProc (
    ClientData instanceData,	/* Socket state. */
2273
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
2256
2257
2258
2259
2260
2261
2262

2263
2264
2265
2266
2267
2268
2269
2270







-
+







    SetEvent(tsdPtr->readyEvent);
    
    if (tsdPtr->hwnd == NULL) {
	return 1;
    }

    /*
     * Process all messages on the socket window.
     * Process all messages on the socket window until WM_QUIT.
     */

    while (GetMessage(&msg, NULL, 0, 0) > 0) {
	DispatchMessage(&msg);
    }

    return msg.wParam;
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374




2375
2376
2377
2378
2379
2380
2381
2347
2348
2349
2350
2351
2352
2353




2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364







-
-
-
-
+
+
+
+







		 infoPtr = infoPtr->nextPtr) {
		if (infoPtr->socket == socket) {
		    /*
		     * 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 and
		     * FD_ACCEPT.
		     * 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) {
			infoPtr->acceptEventCount = 0;
			infoPtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT);
		    } else if (event & FD_ACCEPT) {
			infoPtr->acceptEventCount++;