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
 *
 *   (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", \
			    infoPtr, __FUNCTION__, __LINE__, x)
#else
#define DEBUG(x)
#endif








|







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
#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
        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) ) {

	DEBUG("FD_CONNECT");

	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) {







<
|
>

>
|
|
|
>







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->readyEvents & FD_CONNECT ) {
	infoPtr->readyEvents &= ~(FD_CONNECT);
	DEBUG("FD_CONNECT");
        if ( infoPtr->flags & SOCKET_REENTER_PENDING ) {
	    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
    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) {







<
<







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");


        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
	    infoPtr->sockets->fd = socket(infoPtr->myaddr->ai_family, SOCK_STREAM, 0);
	    if (infoPtr->sockets->fd == INVALID_SOCKET) {
		DEBUG("socket() failed");
		TclWinConvertError((DWORD) WSAGetLastError());
		continue;
	    }
	    



	    /*
	     * 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);








>
>
>







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
	     */
	    
	    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) {
		DEBUG("WSAEWOULDBLOCK");
		/* Jump out and remember that we want to get back in */



		infoPtr->flags |= SOCKET_REENTER_PENDING;
		return TCL_OK;
	    reenter:
		Tcl_SetErrno(infoPtr->lastError);
		DEBUG("reenter");
		infoPtr->selectEvents &= ~(FD_CONNECT);
	    }





#ifdef DEBUGGING
	    fprintf(stderr, "lastError: %d\n", Tcl_GetErrno());
#endif
	    if (Tcl_GetErrno() == 0) {
		goto out;
	    }
	}
    }

out:
    DEBUG("connected or finally failed");


    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;
    }
    /*







<
<
<
|

<
>
>
>







>
>
>
>
>











>
>


<
<







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);



	    if (async_connect && error == WSAEWOULDBLOCK) {
		DEBUG("WSAEWOULDBLOCK");

		/*
		 * 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");


	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
    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;
	}

    /*
     * 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 * */
    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) {



	    /* continue async connect syncroneously */
	    result = CreateClientSocket(NULL, infoPtr);
	    (void) Tcl_SetServiceMode(oldMode);
	    /* Todo: find adequate error code */
	    *errorCodePtr = EFAULT;
	    return (result == TCL_OK);
	}







|
|
|











|


<
<
<
<
<
<
<
<
<



>
>
>







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;
    }

    /*
     * 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? */
    infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);










    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
		    } 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.
			     */

			    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;
		    }
#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");
	infoPtr = (SocketInfo *) lParam;
	for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
	    infoPtr = (SocketInfo *) lParam;


	    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");







<
<
|
<
<
<
<
<
<
|
|
|
>




<
<
<
<
<
<
<
<
>
|
<
<
>





<










|


|
>
>







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");


			/*






			 * Remember any error that occurred so we can report
			 * connection failures.
			 */
			if (error != ERROR_SUCCESS) {
			    TclWinConvertError((DWORD) error);
			    infoPtr->lastError = Tcl_GetErrno();
			}
		    }








		    /*
		     * Inform main thread about signaled events


		     */
		    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");
	infoPtr = (SocketInfo *) lParam;
	for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
#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");