📄 tclwinsock.c
字号:
SocketInfo *infoPtr; struct sockaddr_in sockname; struct sockaddr_in peername; struct hostent *hostEntPtr; SOCKET sock; int size = sizeof(struct sockaddr_in); size_t len = 0; char buf[128]; /* * Check that WinSock is initialized; do not call it if not, to * prevent system crashes. This can happen at exit time if the exit * handler for WinSock ran before other exit handlers that want to * use sockets. */ if (winSock.hInstance == NULL) { if (interp) { Tcl_AppendResult(interp, "winsock is not initialized", NULL); } return TCL_ERROR; } infoPtr = (SocketInfo *) instanceData; sock = (int) infoPtr->socket; if (optionName != (char *) NULL) { len = strlen(optionName); } if ((len == 0) || ((len > 1) && (optionName[1] == 'p') && (strncmp(optionName, "-peername", len) == 0))) { if ((*winSock.getpeername)(sock, (struct sockaddr *) &peername, &size) == 0) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringStartSublist(dsPtr); } Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(peername.sin_addr)); hostEntPtr = (*winSock.gethostbyaddr)( (char *) &(peername.sin_addr), sizeof(peername.sin_addr), AF_INET); if (hostEntPtr != (struct hostent *) NULL) { Tcl_DStringAppendElement(dsPtr, hostEntPtr->h_name); } else { Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(peername.sin_addr)); } sprintf(buf, "%d", (*winSock.ntohs)(peername.sin_port)); Tcl_DStringAppendElement(dsPtr, buf); if (len == 0) { Tcl_DStringEndSublist(dsPtr); } else { return TCL_OK; } } else { /* * getpeername failed - but if we were asked for all the options * (len==0), don't flag an error at that point because it could * be an fconfigure request on a server socket. (which have * no peer). {copied from unix/tclUnixChan.c} */ if (len) { TclWinConvertWSAError((*winSock.WSAGetLastError)()); if (interp) { Tcl_AppendResult(interp, "can't get peername: ", Tcl_PosixError(interp), (char *) NULL); } return TCL_ERROR; } } } if ((len == 0) || ((len > 1) && (optionName[1] == 's') && (strncmp(optionName, "-sockname", len) == 0))) { if ((*winSock.getsockname)(sock, (struct sockaddr *) &sockname, &size) == 0) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sockname"); Tcl_DStringStartSublist(dsPtr); } Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(sockname.sin_addr)); hostEntPtr = (*winSock.gethostbyaddr)( (char *) &(sockname.sin_addr), sizeof(peername.sin_addr), AF_INET); if (hostEntPtr != (struct hostent *) NULL) { Tcl_DStringAppendElement(dsPtr, hostEntPtr->h_name); } else { Tcl_DStringAppendElement(dsPtr, (*winSock.inet_ntoa)(sockname.sin_addr)); } sprintf(buf, "%d", (*winSock.ntohs)(sockname.sin_port)); Tcl_DStringAppendElement(dsPtr, buf); if (len == 0) { Tcl_DStringEndSublist(dsPtr); } else { return TCL_OK; } } else { if (interp) { TclWinConvertWSAError((*winSock.WSAGetLastError)()); Tcl_AppendResult(interp, "can't get sockname: ", Tcl_PosixError(interp), (char *) NULL); } return TCL_ERROR; } } if (len > 0) { return Tcl_BadChannelOption(interp, optionName, "peername sockname"); } return TCL_OK;}/* *---------------------------------------------------------------------- * * TcpWatchProc -- * * Informs the channel driver of the events that the generic * channel code wishes to receive on this socket. * * Results: * None. * * Side effects: * May cause the notifier to poll if any of the specified * conditions are already true. * *---------------------------------------------------------------------- */static voidTcpWatchProc(instanceData, mask) ClientData instanceData; /* The socket state. */ int mask; /* Events of interest; an OR-ed * combination of TCL_READABLE, * TCL_WRITABLE and TCL_EXCEPTION. */{ SocketInfo *infoPtr = (SocketInfo *) instanceData; /* * Update the watch events mask. */ infoPtr->watchEvents = 0; if (mask & TCL_READABLE) { infoPtr->watchEvents |= (FD_READ|FD_CLOSE|FD_ACCEPT); } if (mask & TCL_WRITABLE) { infoPtr->watchEvents |= (FD_WRITE); } /* * If there are any conditions already set, then tell the notifier to poll * rather than block. */ if (infoPtr->readyEvents & infoPtr->watchEvents) { Tcl_Time blockTime = { 0, 0 }; Tcl_SetMaxBlockTime(&blockTime); } }/* *---------------------------------------------------------------------- * * TcpGetProc -- * * Called from Tcl_GetChannelFile to retrieve an OS handle from inside * a TCP socket based channel. * * Results: * Returns TCL_OK with the socket in handlePtr. * * Side effects: * None. * *---------------------------------------------------------------------- */static intTcpGetHandleProc(instanceData, direction, handlePtr) ClientData instanceData; /* The socket state. */ int direction; /* Not used. */ ClientData *handlePtr; /* Where to store the handle. */{ SocketInfo *statePtr = (SocketInfo *) instanceData; *handlePtr = (ClientData) statePtr->socket; return TCL_OK;}/* *---------------------------------------------------------------------- * * SocketProc -- * * This function is called when WSAAsyncSelect has been used * to register interest in a socket event, and the event has * occurred. * * Results: * 0 on success. * * Side effects: * The flags for the given socket are updated to reflect the * event that occured. * *---------------------------------------------------------------------- */static LRESULT CALLBACKSocketProc(hwnd, message, wParam, lParam) HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam;{ int event, error; SOCKET socket; SocketInfo *infoPtr; if (message != SOCKET_MESSAGE) { return DefWindowProc(hwnd, message, wParam, lParam); } event = WSAGETSELECTEVENT(lParam); error = WSAGETSELECTERROR(lParam); socket = (SOCKET) wParam; /* * Find the specified socket on the socket list and update its * eventState flag. */ for (infoPtr = socketList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->socket == socket) { /* * Update the socket state. */ if (event & FD_CLOSE) { infoPtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT); } if (event & FD_CONNECT) { /* * The socket is now connected, so clear the async connect * flag. */ infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT); /* * Remember any error that occurred so we can report * connection failures. */ if (error != ERROR_SUCCESS) { TclWinConvertWSAError(error); infoPtr->lastError = Tcl_GetErrno(); } } infoPtr->readyEvents |= event; break; } } /* * Flush the Tcl event queue before returning to the event loop. */ Tcl_ServiceAll(); return 0;}/* *---------------------------------------------------------------------- * * Tcl_GetHostName -- * * Returns the name of the local host. * * Results: * A string containing the network name for this machine, or * an empty string if we can't figure out the name. The caller * must not modify or free this string. * * Side effects: * None. * *---------------------------------------------------------------------- */char *Tcl_GetHostName(){ DWORD length; char *p; if (hostnameInitialized) { return hostname; } if (TclHasSockets(NULL) == TCL_OK) { if ((*winSock.gethostname)(hostname, sizeof(hostname)) == 0) { hostnameInitialized = 1; return hostname; } } length = sizeof(hostname); if (GetComputerName(hostname, &length) != 0) { for (p = hostname; *p != '\0'; p++) { if (isupper(*((unsigned char *) p))) { *p = (char) tolower(*((unsigned char *) p)); } } } else { hostname[0] = '\0'; } hostnameInitialized = 1; return hostname;}/* *---------------------------------------------------------------------- * * TclWinGetSockOpt, et al. -- * * These functions are wrappers that let us bind the WinSock * API dynamically so we can run on systems that don't have * the wsock32.dll. We need wrappers for these interfaces * because they are called from the generic Tcl code. * * Results: * As defined for each function. * * Side effects: * As defined for each function. * *---------------------------------------------------------------------- */int PASCAL FARTclWinGetSockOpt(SOCKET s, int level, int optname, char FAR * optval, int FAR *optlen){ /* * Check that WinSock is initialized; do not call it if not, to * prevent system crashes. This can happen at exit time if the exit * handler for WinSock ran before other exit handlers that want to * use sockets. */ if (winSock.hInstance == NULL) { return SOCKET_ERROR; } return (*winSock.getsockopt)(s, level, optname, optval, optlen);}int PASCAL FARTclWinSetSockOpt(SOCKET s, int level, int optname, const char FAR * optval, int optlen){ /* * Check that WinSock is initialized; do not call it if not, to * prevent system crashes. This can happen at exit time if the exit * handler for WinSock ran before other exit handlers that want to * use sockets. */ if (winSock.hInstance == NULL) { return SOCKET_ERROR; } return (*winSock.setsockopt)(s, level, optname, optval, optlen);}u_short PASCAL FARTclWinNToHS(u_short netshort){ /* * Check that WinSock is initialized; do not call it if not, to * prevent system crashes. This can happen at exit time if the exit * handler for WinSock ran before other exit handlers that want to * use sockets. */ if (winSock.hInstance == NULL) { return (u_short) -1; } return (*winSock.ntohs)(netshort);}struct servent FAR * PASCAL FARTclWinGetServByName(const char FAR * name, const char FAR * proto){ /* * Check that WinSock is initialized; do not call it if not, to * prevent system crashes. This can happen at exit time if the exit * handler for WinSock ran before other exit handlers that want to * use sockets. */ if (winSock.hInstance == NULL) { return (struct servent FAR *) NULL; } return (*winSock.getservbyname)(name, proto);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -