⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclwinsock.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (tsdPtr->hwnd == NULL) {	    goto unloadLibrary;	}		Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);	Tcl_CreateThreadExitHandler(SocketThreadExitHandler, NULL);    }    return;unloadLibrary:    if (tsdPtr != NULL) {	if (tsdPtr->hwnd != NULL) {	    DestroyWindow(tsdPtr->hwnd);	}	if (tsdPtr->socketThread != NULL) {	    TerminateThread(tsdPtr->socketThread, 0);	    tsdPtr->socketThread = NULL;	}	CloseHandle(tsdPtr->readyEvent);	CloseHandle(tsdPtr->socketListLock);    }    FreeLibrary(winSock.hInstance);    winSock.hInstance = NULL;    return;}/* *---------------------------------------------------------------------- * * SocketsEnabled -- * *	Check that the WinSock DLL is loaded and ready. * * Results: *	1 if it is. * * Side effects: *	None. * *---------------------------------------------------------------------- */    /* ARGSUSED */static intSocketsEnabled(){    int enabled;    Tcl_MutexLock(&socketMutex);    enabled = (winSock.hInstance != NULL);    Tcl_MutexUnlock(&socketMutex);    return enabled;}/* *---------------------------------------------------------------------- * * SocketExitHandler -- * *	Callback invoked during exit clean up to delete the socket *	communication window and to release the WinSock DLL. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */    /* ARGSUSED */static voidSocketExitHandler(clientData)    ClientData clientData;              /* Not used. */{    Tcl_MutexLock(&socketMutex);    if (winSock.hInstance) {	UnregisterClassA("TclSocket", TclWinGetTclInstance());	(*winSock.WSACleanup)();	FreeLibrary(winSock.hInstance);	winSock.hInstance = NULL;    }    initialized = 0;    hostnameInitialized = 0;    Tcl_MutexUnlock(&socketMutex);}/* *---------------------------------------------------------------------- * * SocketThreadExitHandler -- * *	Callback invoked during thread clean up to delete the socket *	event source. * * Results: *	None. * * Side effects: *	Delete the event source. * *---------------------------------------------------------------------- */    /* ARGSUSED */static voidSocketThreadExitHandler(clientData)    ClientData clientData;              /* Not used. */{    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (tsdPtr->socketThread != NULL) {	PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);        /*	 * Wait for the thread to terminate.  This ensures that we are	 * completely cleaned up before we leave this function. 	 */	WaitForSingleObject(tsdPtr->socketThread, INFINITE);	CloseHandle(tsdPtr->socketThread);	CloseHandle(tsdPtr->readyEvent);	CloseHandle(tsdPtr->socketListLock);    }    if (tsdPtr->hwnd != NULL) {	DestroyWindow(tsdPtr->hwnd);    }        Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL);}/* *---------------------------------------------------------------------- * * TclpHasSockets -- * *	This function determines whether sockets are available on the *	current system and returns an error in interp if they are not. *	Note that interp may be NULL. * * Results: *	Returns TCL_OK if the system supports sockets, or TCL_ERROR with *	an error in interp. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTclpHasSockets(interp)    Tcl_Interp *interp;{    Tcl_MutexLock(&socketMutex);    InitSockets();    Tcl_MutexUnlock(&socketMutex);    if (SocketsEnabled()) {	return TCL_OK;    }    if (interp != NULL) {	Tcl_AppendResult(interp, "sockets are not available on this system",		NULL);    }    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * SocketSetupProc -- * *	This procedure is invoked before Tcl_DoOneEvent blocks waiting *	for an event. * * Results: *	None. * * Side effects: *	Adjusts the block time if needed. * *---------------------------------------------------------------------- */voidSocketSetupProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    SocketInfo *infoPtr;    Tcl_Time blockTime = { 0, 0 };    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Check to see if there is a ready socket.  If so, poll.     */    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);    for (infoPtr = tsdPtr->socketList; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->readyEvents & infoPtr->watchEvents) {	    Tcl_SetMaxBlockTime(&blockTime);	    break;	}    }    SetEvent(tsdPtr->socketListLock);}/* *---------------------------------------------------------------------- * * SocketCheckProc -- * *	This procedure is called by Tcl_DoOneEvent to check the socket *	event source for events.  * * Results: *	None. * * Side effects: *	May queue an event. * *---------------------------------------------------------------------- */static voidSocketCheckProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    SocketInfo *infoPtr;    SocketEvent *evPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Queue events for any ready sockets that don't already have events     * queued (caused by persistent states that won't generate WinSock     * events).     */    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);    for (infoPtr = tsdPtr->socketList; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if ((infoPtr->readyEvents & infoPtr->watchEvents)		&& !(infoPtr->flags & SOCKET_PENDING)) {	    infoPtr->flags |= SOCKET_PENDING;	    evPtr = (SocketEvent *) ckalloc(sizeof(SocketEvent));	    evPtr->header.proc = SocketEventProc;	    evPtr->socket = infoPtr->socket;	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);	}    }    SetEvent(tsdPtr->socketListLock);}/* *---------------------------------------------------------------------- * * SocketEventProc -- * *	This procedure is called by Tcl_ServiceEvent when a socket event *	reaches the front of the event queue.  This procedure is *	responsible for notifying the generic channel code. * * Results: *	Returns 1 if the event was handled, meaning it should be removed *	from the queue.  Returns 0 if the event was not handled, meaning *	it should stay on the queue.  The only time the event isn't *	handled is if the TCL_FILE_EVENTS flag bit isn't set. * * Side effects: *	Whatever the channel callback procedures do. * *---------------------------------------------------------------------- */static intSocketEventProc(evPtr, flags)    Tcl_Event *evPtr;		/* Event to service. */    int flags;			/* Flags that indicate what events to				 * handle, such as TCL_FILE_EVENTS. */{    SocketInfo *infoPtr;    SocketEvent *eventPtr = (SocketEvent *) evPtr;    int mask = 0;    int events;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return 0;    }    /*     * Find the specified socket on the socket list.     */    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) {	return 1;    }    infoPtr->flags &= ~SOCKET_PENDING;    /*     * Handle connection requests directly.     */    if (infoPtr->readyEvents & FD_ACCEPT) {	TcpAccept(infoPtr);	return 1;    }    /*     * Mask off unwanted events and compute the read/write mask so      * we can notify the channel.     */    events = infoPtr->readyEvents & infoPtr->watchEvents;    if (events & FD_CLOSE) {	/*	 * If the socket was closed and the channel is still interested	 * in read events, then we need to ensure that we keep polling	 * for this event until someone does something with the channel.	 * Note that we do this before calling Tcl_NotifyChannel so we don't	 * have to watch 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 };	Tcl_SetMaxBlockTime(&blockTime);	mask |= TCL_READABLE;    } else if (events & FD_READ) {	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.	 */	SendMessage(tsdPtr->hwnd, SOCKET_SELECT,		(WPARAM) UNSELECT, (LPARAM) infoPtr);	FD_ZERO(&readFds);	FD_SET(infoPtr->socket, &readFds);	timeout.tv_usec = 0;	timeout.tv_sec = 0; 	if ((*winSock.select)(0, &readFds, NULL, NULL, &timeout) != 0) {	    mask |= TCL_READABLE;	} else {	    infoPtr->readyEvents &= ~(FD_READ);	    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,		    (WPARAM) SELECT, (LPARAM) infoPtr);	}    }    if (events & (FD_WRITE | FD_CONNECT)) {	mask |= TCL_WRITABLE;    }    if (mask) {	Tcl_NotifyChannel(infoPtr->channel, mask);    }    return 1;}/* *---------------------------------------------------------------------- * * TcpBlockProc -- * *	Sets a socket into blocking or non-blocking mode. * * Results: *	0 if successful, errno if there was an error. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intTcpBlockProc(instanceData, mode)    ClientData	instanceData;	/* The socket to block/un-block. */    int mode;			/* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    SocketInfo *infoPtr = (SocketInfo *) instanceData;    if (mode == TCL_MODE_NONBLOCKING) {	infoPtr->flags |= SOCKET_ASYNC;    } else {	infoPtr->flags &= ~(SOCKET_ASYNC);    }    return 0;}/* *---------------------------------------------------------------------- * * TcpCloseProc -- * *	This procedure is called by the generic IO level to perform *	channel type specific cleanup on a socket based channel *	when the channel is closed. * * Results: *	0 if successful, the value of errno if failed. * * Side effects: *	Closes the socket. * *---------------------------------------------------------------------- */    /* ARGSUSED */static intTcpCloseProc(instanceData, interp)    ClientData instanceData;	/* The socket to close. */    Tcl_Interp *interp;		/* Unused. */{    SocketInfo *infoPtr = (SocketInfo *) instanceData;    SocketInfo **nextPtrPtr;    int errorCode = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -