Index: tclWinSock.c =================================================================== RCS file: /cvsroot/tcl/tcl/win/tclWinSock.c,v retrieving revision 1.25 diff -c -r1.25 tclWinSock.c *** tclWinSock.c 24 Jan 2002 01:34:16 -0000 1.25 --- tclWinSock.c 17 May 2002 22:48:09 -0000 *************** *** 194,199 **** --- 194,200 ---- int mode)); static int TcpCloseProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp)); + static Tcl_DriverSetOptionProc TcpSetOptionProc; static int TcpGetOptionProc _ANSI_ARGS_((ClientData instanceData, Tcl_Interp *interp, CONST char *optionName, Tcl_DString *optionValue)); *************** *** 221,227 **** TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ ! NULL, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Set up notifier to watch this channel. */ TcpGetHandleProc, /* Get an OS handle from channel. */ --- 222,228 ---- TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ ! TcpSetOptionProc, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Set up notifier to watch this channel. */ TcpGetHandleProc, /* Get an OS handle from channel. */ *************** *** 1859,1864 **** --- 1860,1929 ---- /* *---------------------------------------------------------------------- * + * TcpSetOptionProc -- + * + * Sets Tcp channel specific options. + * + * Results: + * ... + * + * Side effects: + * ... + * + *---------------------------------------------------------------------- + */ + + static int + TcpSetOptionProc ( + ClientData instanceData, /* Socket state. */ + Tcl_Interp *interp, /* For error reporting - can be NULL. */ + CONST char *optionName, /* Name of the option to set. */ + CONST char *value) /* New value for option. */ + { + SocketInfo *infoPtr; + SOCKET sock; + BOOL val = FALSE; + int boolVar, rtn; + + /* + * 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 (!SocketsEnabled()) { + if (interp) { + Tcl_AppendResult(interp, "winsock is not initialized", NULL); + } + return TCL_ERROR; + } + + infoPtr = (SocketInfo *) instanceData; + sock = infoPtr->socket; + + if (!stricmp(optionName, "-keepalive")) { + if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) { + return TCL_ERROR; + } + if (boolVar) val = TRUE; + rtn = winSock.setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, + (const char *) &val, sizeof(BOOL)); + if (rtn != 0) { + TclWinConvertWSAError(winSock.WSAGetLastError()); + if (interp) { + Tcl_AppendResult(interp, "couldn't set socket option: ", + Tcl_PosixError(interp), NULL); + } + return TCL_ERROR; + } + } + return TCL_OK; + } + + /* + *---------------------------------------------------------------------- + * * TcpGetOptionProc -- * * Computes an option value for a TCP socket based channel, or a *************** *** 2028,2035 **** } } if (len > 0) { ! return Tcl_BadChannelOption(interp, optionName, "peername sockname"); } return TCL_OK; --- 2093,2119 ---- } } + if ((len == 0) || + ((len > 1) && (optionName[1] == 'k') && + (strncmp(optionName, "-keepalive", len) == 0))) { + int optlen; + BOOL ka; + + if (len == 0) { + Tcl_DStringAppendElement(dsPtr, "-keepalive"); + } + optlen = sizeof(BOOL); + winSock.getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&ka, + &optlen); + if (ka) { + Tcl_DStringAppendElement(dsPtr, "1"); + } else { + Tcl_DStringAppendElement(dsPtr, "0"); + } + } + if (len > 0) { ! return Tcl_BadChannelOption(interp, optionName, "peername sockname keepalive"); } return TCL_OK;