Diff
Not logged in

Differences From Artifact [06f917f08c]:

To Artifact [a7003fb42f]:


43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+







 *
 *   (Ad 2) The main functions for this are SocketSetupProc() and
 *          SocketCheckProc().
 */

#include "tclWinInt.h"

//#define DEBUGGING
#define DEBUGGING
#ifdef DEBUGGING
#define DEBUG(x) fprintf(stderr, ">>> %p %s(%d): %s<<<\n", \
			    infoPtr, __FUNCTION__, __LINE__, x)
#else
#define DEBUG(x)
#endif

764
765
766
767
768
769
770
771
772


773

774
775
776




777
778
779
780
781
782
783
764
765
766
767
768
769
770


771
772
773
774



775
776
777
778
779
780
781
782
783
784
785







-
-
+
+

+
-
-
-
+
+
+
+







        SetEvent(tsdPtr->socketListLock);
	return 1;
    }

    infoPtr->flags &= ~SOCKET_PENDING;

    /* Continue async connect if pending and ready */
    if ( (infoPtr->flags & SOCKET_REENTER_PENDING)
	    && (infoPtr->readyEvents & FD_CONNECT) ) {
    if ( infoPtr->readyEvents & FD_CONNECT ) {
	infoPtr->readyEvents &= ~(FD_CONNECT);
	DEBUG("FD_CONNECT");
        if ( infoPtr->flags & SOCKET_REENTER_PENDING ) {
	SetEvent(tsdPtr->socketListLock);
	CreateClientSocket(NULL, infoPtr);
	return 1;
	    SetEvent(tsdPtr->socketListLock);
	    CreateClientSocket(NULL, infoPtr);
	    return 1;
	}
    }

    /*
     * Handle connection requests directly.
     */
    if (infoPtr->readyEvents & FD_ACCEPT) {
	for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1190
1191
1192
1193
1194
1195
1196


1197
1198
1199
1200
1201
1202
1203







-
-







    ThreadSpecificData *tsdPtr;
    DWORD error;
    
    DEBUG(async_connect ? "async connect" : "sync connect");

    if (async_callback) {
	DEBUG("subsequent call");
	/* Clear this pending reenter case */
	infoPtr->flags &= ~(SOCKET_REENTER_PENDING);
        goto reenter;
    } else {
	DEBUG("first call");
    }
    
    for (infoPtr->addr = infoPtr->addrlist; infoPtr->addr != NULL;
	 infoPtr->addr = infoPtr->addr->ai_next) {
1238
1239
1240
1241
1242
1243
1244



1245
1246
1247
1248
1249
1250
1251
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254







+
+
+







	    infoPtr->sockets->fd = socket(infoPtr->myaddr->ai_family, SOCK_STREAM, 0);
	    if (infoPtr->sockets->fd == INVALID_SOCKET) {
		DEBUG("socket() failed");
		TclWinConvertError((DWORD) WSAGetLastError());
		continue;
	    }
	    
#ifdef DEBUGGING
	    fprintf(stderr, "Client socket %d created\n", infoPtr->sockets->fd);
#endif
	    /*
	     * Win-NT has a misfeature that sockets are inherited in child
	     * processes by default. Turn off the inherit bit.
	     */

	    SetHandleInformation((HANDLE) infoPtr->sockets->fd, HANDLE_FLAG_INHERIT, 0);

1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293

1294
1295



1296
1297
1298
1299
1300
1301
1302





1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313


1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1286
1287
1288
1289
1290
1291
1292




1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324


1325
1326
1327
1328
1329
1330
1331







-
-
-
-
+

-
+
+
+







+
+
+
+
+











+
+


-
-







	     */
	    
	    DEBUG("connect()");
	    connect(infoPtr->sockets->fd, infoPtr->addr->ai_addr,
		    infoPtr->addr->ai_addrlen);
	    error = WSAGetLastError();
	    TclWinConvertError(error);
#ifdef DEBUGGING
	    // fprintf(stderr,"error = %lu\n", error);
#endif
	    if (error == WSAEWOULDBLOCK) {
	    if (async_connect && error == WSAEWOULDBLOCK) {
		DEBUG("WSAEWOULDBLOCK");
		/* Jump out and remember that we want to get back in */
		/*
		 * Activate FD_CONNECT notification and reenter jump
		 */
		infoPtr->flags |= SOCKET_REENTER_PENDING;
		return TCL_OK;
	    reenter:
		Tcl_SetErrno(infoPtr->lastError);
		DEBUG("reenter");
		infoPtr->selectEvents &= ~(FD_CONNECT);
	    }
	    /*
	     * Clear the reenter flag also for the (hypothetic) case
	     * that connect did succeed emidiately
	     */
	    infoPtr->flags &= ~(SOCKET_REENTER_PENDING);
#ifdef DEBUGGING
	    fprintf(stderr, "lastError: %d\n", Tcl_GetErrno());
#endif
	    if (Tcl_GetErrno() == 0) {
		goto out;
	    }
	}
    }

out:
    DEBUG("connected or finally failed");
    /* Clear async flag (not really necessary, not used any more) */
    infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
    if (Tcl_GetErrno() != 0 && interp != NULL) {
	DEBUG("ERRNO");
        /* Clear async flag so if a read is done it does not block */
        infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
				"couldn't open socket: %s", Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
    }
    /*
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378



1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404



1405
1406
1407
1408
1409
1410
1411
1376
1377
1378
1379
1380
1381
1382



1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399









1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412







-
-
-
+
+
+











-
+


-
-
-
-
-
-
-
-
-



+
+
+







    int oldMode;
    ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
    /*
     * A non blocking socket waiting for an asyncronous connect
     * returns directly an error
     */
    if (infoPtr->flags & SOCKET_ASYNC) {
	    *errorCodePtr = EWOULDBLOCK;
	    return 0;
	}
	*errorCodePtr = EWOULDBLOCK;
	return 0;
    }

    /*
     * Be sure to disable event servicing so we are truly modal.
     */

    oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);

    /*
     * Disable async connect as we continue now synchoneously
     */

    /* ToDo: need thread protection * */
    /* ToDo: need thread protection? */
    infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);

    /*
     * Reset WSAAsyncSelect so we have a fresh set of events pending.
     */

    SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT,
	    (LPARAM) infoPtr);
    SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
	    (LPARAM) infoPtr);

    while (1) {
	/* Check for connect event */
	if (infoPtr->readyEvents & FD_CONNECT) {
	    /* Consume the connect event */
	    /* ToDo: eventual signaling ? */
	    infoPtr->readyEvents &= ~(FD_CONNECT);
	    /* continue async connect syncroneously */
	    result = CreateClientSocket(NULL, infoPtr);
	    (void) Tcl_SetServiceMode(oldMode);
	    /* Todo: find adequate error code */
	    *errorCodePtr = EFAULT;
	    return (result == TCL_OK);
	}
2741
2742
2743
2744
2745
2746
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
2774

2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791

2792
2793
2794



2795
2796
2797
2798
2799
2800
2801
2742
2743
2744
2745
2746
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
2774
2775

2776
2777
2778

2779
2780
2781
2782
2783
2784
2785
2786
2787
2788







-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+




-
-
-
-
-
-
-
-
-
+
+
-
-
+





-










-
+


-
+
+
+







		    } else if (event & FD_ACCEPT) {
			DEBUG("FD_ACCEPT");
			    infoPtr->acceptEventCount++;
		    }

		    if (event & FD_CONNECT) {
			DEBUG("FD_CONNECT");

			if (error == ERROR_SUCCESS) {
			    /*
			/*
			     * The socket is now connected, clear the async connect
			     * flag.
			     */
			    infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
			} else {
			    /*
			     * Remember any error that occurred so we can report
			     * connection failures.
			     */
			 * Remember any error that occurred so we can report
			 * connection failures.
			 */
			if (error != ERROR_SUCCESS) {
			    TclWinConvertError((DWORD) error);
			    infoPtr->lastError = Tcl_GetErrno();
			}
		    }
#if 0
		    if (infoPtr->flags & SOCKET_ASYNC_CONNECT) {
			DEBUG("SOCKET_ASYNC_CONNECT");
			// infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
			if (error != ERROR_SUCCESS) {
			    TclWinConvertError((DWORD) error);
			    infoPtr->lastError = Tcl_GetErrno();
			}
			infoPtr->readyEvents |= FD_WRITE;
		    /*
		     * Inform main thread about signaled events
		    }
#endif
		     */
		    infoPtr->readyEvents |= event;

		    /*
		     * Wake up the Main Thread.
		     */

		    SetEvent(tsdPtr->readyEvent);
		    Tcl_ThreadAlert(tsdPtr->threadId);
		    break;
		}
	    }
	}
	SetEvent(tsdPtr->socketListLock);
	break;

    case SOCKET_SELECT:
	    DEBUG("SOCKET_SELECT");
	DEBUG("SOCKET_SELECT");
	infoPtr = (SocketInfo *) lParam;
	for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
	    infoPtr = (SocketInfo *) lParam;
#ifdef DEBUGGING
	    fprintf(stderr,"loop over fd = %d\n",fds->fd);
#endif
	    if (wParam == SELECT) {
		DEBUG("SELECT");
		if (infoPtr->selectEvents & FD_READ) DEBUG("  READ");
		if (infoPtr->selectEvents & FD_WRITE) DEBUG("  WRITE");
		if (infoPtr->selectEvents & FD_CLOSE) DEBUG("  CLOSE");
		if (infoPtr->selectEvents & FD_CONNECT) DEBUG("  CONNECT");
		if (infoPtr->selectEvents & FD_ACCEPT) DEBUG("  ACCEPT");