From 25235d635f23bc74aa0ad3e304eeeda9506bf348 Mon Sep 17 00:00:00 2001 From: patthoyts Date: Wed, 12 Mar 2003 00:21:15 +0000 Subject: [PATCH] Fixed udpGetHandle to perform as per specs. Added channel Get and SetOption procedure to support fconfigure. General layout changes to group related functions together. Bumped version pathlevel to 1.0.5 --- ChangeLog | 14 + configure | 2 +- configure.in | 2 +- generic/udp_tcl.c | 875 +++++++++++++++++++++++++++++----------------- tests/udp.test | 2 +- win/tcludp.dsp | 234 +++++++------ 6 files changed, 695 insertions(+), 434 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6f08d2..4bc13ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-03-12 Pat Thoyts + + * win/tcludp.dsp: + * configure.in: bumped patchlevel to 1.0.5 + +2003-03-05 Pat Thoyts + + * generic/udp_tcl.c: General layout rearrangement to put tcl + command procs, channel handler procs and utility procs together. + * generic/udp_tcl.c: Added channel option handlers to enable the + use of 'fconfigure' to hopefully replace udp_conf. + * generic/udp_tcl.c (udpGetHandle): Fixed to return the handle + properly. + 2003-03-03 Pat Thoyts * generic/udp_tcl.c: Fix include list to use the autoconfig test diff --git a/configure b/configure index b3d1da9..5787270 100755 --- a/configure +++ b/configure @@ -572,7 +572,7 @@ PACKAGE=udp MAJOR_VERSION=1 MINOR_VERSION=0 -PATCHLEVEL=4 +PATCHLEVEL=5 VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${PATCHLEVEL} NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION} diff --git a/configure.in b/configure.in index e07e4c0..a697d17 100644 --- a/configure.in +++ b/configure.in @@ -37,7 +37,7 @@ PACKAGE=udp MAJOR_VERSION=1 MINOR_VERSION=0 -PATCHLEVEL=4 +PATCHLEVEL=5 VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${PATCHLEVEL} NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION} diff --git a/generic/udp_tcl.c b/generic/udp_tcl.c index 89605b3..5f88749 100644 --- a/generic/udp_tcl.c +++ b/generic/udp_tcl.c @@ -20,9 +20,6 @@ #ifdef WIN32 #include -#include -#include -#include #include #else #if defined(HAVE_SYS_IOCTL_H) @@ -57,176 +54,247 @@ FILE *dbg; static char errBuf[256]; +/* + * Channel handling procedures + */ +static Tcl_DriverOutputProc udpOutput; +static Tcl_DriverInputProc udpInput; +static Tcl_DriverCloseProc udpClose; +static Tcl_DriverWatchProc udpWatch; +static Tcl_DriverGetHandleProc udpGetHandle; +static Tcl_DriverSetOptionProc udpSetOption; +static Tcl_DriverGetOptionProc udpGetOption; + +/* + * Tcl command procedures + */ +int Udp_CmdProc(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []); int udpOpen(ClientData , Tcl_Interp *, int , CONST84 char * []); int udpConf(ClientData , Tcl_Interp *, int , CONST84 char * []); int udpPeek(ClientData , Tcl_Interp *, int , CONST84 char * []); -static int udpGet(ClientData instanceData,int direction,ClientData *handlePtr); -static void udpWatch(ClientData instanceData, int mask); -static int udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCode); -static int udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode); -static int udpClose(ClientData instanceData, Tcl_Interp *interp); +/* + * internal functions + */ static void udpTrace(const char *format, ...); -static int udpGetService(Tcl_Interp *interp, const char *service, - unsigned short *servicePort); +static int udpGetService(Tcl_Interp *interp, const char *service, + unsigned short *servicePort); +/* + * Windows specific functions + */ #ifdef WIN32 + +int UdpEventProc(Tcl_Event *evPtr, int flags); +static void UDP_SetupProc(ClientData data, int flags); +void UDP_CheckProc(ClientData data, int flags); +int Udp_WinHasSockets(Tcl_Interp *interp); + +/* FIX ME - these should be part of a thread/package specific structure */ static HANDLE waitForSock; static HANDLE waitSockRead; static HANDLE sockListLock; static UdpState *sockList; static UdpState *sockTail; -#endif + +#endif /* ! WIN32 */ /* - * udpClose + * ---------------------------------------------------------------------- + * udpInit + * ---------------------------------------------------------------------- */ -int -udpClose(ClientData instanceData, Tcl_Interp *interp) +int +Udp_Init(Tcl_Interp *interp) { - int sock; - int errorCode = 0; - UdpState *statePtr = (UdpState *) instanceData; -#ifdef WIN32 - UdpState *statePre; - - WaitForSingleObject(sockListLock, INFINITE); -#endif /* ! WIN32 */ - - sock = statePtr->sock; - -#ifdef WIN32 - /* remove the statePtr from the list */ - for (statePtr = sockList, statePre = sockList; - statePtr != NULL; - statePre=statePtr, statePtr=statePtr->next) { - if (statePtr->sock == sock) { - UDPTRACE("Remove %d from the list\n", sock); - if (statePtr == sockList) { - sockList = statePtr->next; - } else { - statePre->next = statePtr->next; - if (sockTail == statePtr) - sockTail = statePre; - } - } - } -#endif /* ! WIN32 */ - - ckfree((char *) statePtr); - if (closesocket(sock) < 0) { - errorCode = errno; - } - if (errorCode != 0) { -#ifndef WIN32 - sprintf(errBuf, "udpClose: %d, error: %d\n", sock, errorCode); -#else - sprintf(errBuf, "udpClose: %d, error: %d\n", sock, WSAGetLastError()); + int r = TCL_OK; +#if defined(DEBUG) && !defined(WIN32) + dbg = fopen("udp.dbg", "wt"); #endif - UDPTRACE("UDP error - close %d", sock); - } else { - UDPTRACE("Close socket %d\n", sock); - } - + +#ifdef USE_TCL_STUBS + Tcl_InitStubs(interp, "8.1", 0); +#endif + #ifdef WIN32 - SetEvent(sockListLock); + if (Udp_WinHasSockets(interp) != TCL_OK) { + return TCL_ERROR; + } #endif + + Tcl_CreateCommand(interp, "udp_open", udpOpen , + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "udp_conf", udpConf , + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, "udp_peek", udpPeek , + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - return errorCode; + r = Tcl_PkgProvide(interp, TCLUDP_PACKAGE_NAME, TCLUDP_PACKAGE_VERSION); + return r; } - + /* - * udpWatch + * ---------------------------------------------------------------------- + * Udp_CmdProc -- + * Provide a user interface similar to the Tcl stock 'socket' command. + * + * udp ?options? + * udp ?options? host port + * udp -server command ?options? port + * + * ---------------------------------------------------------------------- */ -static void -udpWatch(ClientData instanceData, int mask) +int +Udp_CmdProc(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) { -#ifndef WIN32 - UdpState *fsPtr = (UdpState *) instanceData; - if (mask) { - UDPTRACE("Tcl_CreateFileHandler\n"); - Tcl_CreateFileHandler(fsPtr->sock, mask, - (Tcl_FileProc *) Tcl_NotifyChannel, - (ClientData) fsPtr->channel); - } else { - UDPTRACE("Tcl_DeleteFileHandler\n"); - Tcl_DeleteFileHandler(fsPtr->sock); - } -#endif + Tcl_SetResult(interp, "E_NOTIMPL", TCL_STATIC); + return TCL_ERROR; } /* - * udpGet + * Probably we should provide an equivalent to the C API for TCP. + * + * Tcl_Channel Tcl_OpenUdpClient(interp, port, host, myaddr, myport, async); + * Tcl_Channel Tcl_OpenUdpServer(interp, port, myaddr, proc, clientData); + * Tcl_Channel Tcl_MakeUdpClientChannel(sock); */ -static int -udpGet(ClientData instanceData,int direction,ClientData *handlePtr) -{ - UdpState *statePtr = (UdpState *) instanceData; - UDPTRACE("UDP_get %d\n", statePtr->sock); - return statePtr->sock; -} /* - * udpPeek - peek some data and set the peer information + * ---------------------------------------------------------------------- + * udpOpen -- + * + * opens a UDP socket and addds the file descriptor to the tcl + * interpreter + * ---------------------------------------------------------------------- */ int -udpPeek(ClientData clientData, Tcl_Interp *interp, - int argc, CONST84 char * argv[]) +udpOpen(ClientData clientData, Tcl_Interp *interp, + int argc, CONST84 char * argv[]) { -#ifndef WIN32 - int buffer_size = 16; - int actual_size, socksize, port; int sock; - char message[17]; - char *remotehost; - struct hostent *name; + char channelName[20]; + UdpState *statePtr; + uint16_t localport = 0; #ifdef SIPC_IPV6 - struct sockaddr_in6 recvaddr; + struct sockaddr_in6 addr, sockaddr; #else - struct sockaddr_in recvaddr; + struct sockaddr_in addr, sockaddr; #endif - Tcl_Channel chan; - UdpState *statePtr; + unsigned long status = 1; + int len; - chan = Tcl_GetChannel(interp, (char *)argv[1], NULL); - if (chan == (Tcl_Channel) NULL) { - return TCL_ERROR; - } - statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan); - sock = Tcl_GetChannelHandle (chan, (TCL_READABLE | TCL_WRITABLE), NULL); + Tcl_ChannelType *Udp_ChannelType; + Udp_ChannelType = (Tcl_ChannelType *) ckalloc((unsigned) sizeof(Tcl_ChannelType)); + memset(Udp_ChannelType, 0, sizeof(Tcl_ChannelType)); +#ifdef SIPC_IPV6 + Udp_ChannelType->typeName = strdup("udp6"); +#else + Udp_ChannelType->typeName = strdup("udp"); +#endif + Udp_ChannelType->blockModeProc = NULL; + Udp_ChannelType->closeProc = udpClose; + Udp_ChannelType->inputProc = udpInput; + Udp_ChannelType->outputProc = udpOutput; + Udp_ChannelType->seekProc = NULL; + Udp_ChannelType->setOptionProc = udpSetOption; + Udp_ChannelType->getOptionProc = udpGetOption; + Udp_ChannelType->watchProc = udpWatch; + Udp_ChannelType->getHandleProc = udpGetHandle; + Udp_ChannelType->close2Proc = NULL; - if (argc > 2) { - buffer_size = atoi(argv[2]); - if (buffer_size > 16) buffer_size = 16; + if (argc >= 2) { + if (udpGetService(interp, argv[1], &localport) != TCL_OK) + return TCL_ERROR; } - actual_size = recvfrom(sock, message, buffer_size, MSG_PEEK, - (struct sockaddr *)&recvaddr, &socksize); - if (actual_size < 0) { - sprintf(errBuf, "udppeek error"); + memset(channelName, 0, sizeof(channelName)); + +#ifdef SIPC_IPV6 + sock = socket(AF_INET6, SOCK_DGRAM, 0); +#else + sock = socket(AF_INET, SOCK_DGRAM, 0); +#endif + if (sock < 0) { + sprintf(errBuf,"%s","udp - socket"); + UDPTRACE("UDP error - socket\n"); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } + memset(&addr, 0, sizeof(addr)); #ifdef SIPC_IPV6 - remotehost = (char *)inet_ntop(AF_INET6, &recvaddr.sin_addr, statePtr->peerhost, sizeof(statePtr->peerhost) ); - statePtr->peerport = ntohs(recvaddr.sin_port); + addr.sin6_family = AF_INET6; + addr.sin6_port = localport; #else - strcpy(statePtr->peerhost, (char *)inet_ntoa(recvaddr.sin_addr)); - statePtr->peerport = ntohs(recvaddr.sin_port); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = 0; + addr.sin_port = localport; #endif - message[16]='\0'; + if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) { + sprintf(errBuf,"%s","udp - bind"); + UDPTRACE("UDP error - bind\n"); + Tcl_AppendResult(interp, errBuf, (char *)NULL); + return TCL_ERROR; + } +#ifdef WIN32 + ioctlsocket(sock, FIONBIO, &status); +#else + ioctl(sock, (int) FIONBIO, &status); +#endif + if (localport == 0) { + len = sizeof(sockaddr); + getsockname(sock, (struct sockaddr *)&sockaddr, &len); +#ifdef SIPC_IPV6 + localport = sockaddr.sin6_port; +#else + localport = sockaddr.sin_port; +#endif + } - Tcl_AppendResult(interp, message, (char *)NULL); + UDPTRACE("Open socket %d. Bind socket to port %d\n", + sock, ntohs(localport)); + + statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState)); + memset(statePtr, 0, sizeof(UdpState)); + statePtr->sock = sock; + sprintf(channelName, "sock%d", statePtr->sock); + statePtr->channel = Tcl_CreateChannel(Udp_ChannelType, channelName, + (ClientData) statePtr, + (TCL_READABLE | TCL_WRITABLE | TCL_MODE_NONBLOCKING)); + statePtr->doread = 1; + statePtr->localport = localport; + Tcl_RegisterChannel(interp, statePtr->channel); +#ifdef WIN32 + statePtr->threadId = Tcl_GetCurrentThread(); + statePtr->packetNum = 0; + statePtr->next = NULL; + statePtr->packets = NULL; + statePtr->packetsTail = NULL; + Tcl_CreateEventSource(UDP_SetupProc, UDP_CheckProc, NULL); +#endif + /* Tcl_SetChannelOption(interp, statePtr->channel, "-blocking", "0"); */ + Tcl_AppendResult(interp, channelName, (char *)NULL); +#ifdef WIN32 + WaitForSingleObject(sockListLock, INFINITE); + if (sockList == NULL) { + sockList = statePtr; + sockTail = statePtr; + } else { + sockTail->next = statePtr; + sockTail = statePtr; + } + + UDPTRACE("Append %d to sockList\n", statePtr->sock); + SetEvent(sockListLock); + SetEvent(waitForSock); +#endif return TCL_OK; -#else /* WIN32 */ - Tcl_SetResult(interp, "udp_peek not implemented for this platform", - TCL_STATIC); - return TCL_ERROR; -#endif /* ! WIN32 */ } /* - * udpConf + * ---------------------------------------------------------------------- + * udpConf -- + * ---------------------------------------------------------------------- */ int udpConf(ClientData clientData, Tcl_Interp *interp, @@ -337,9 +405,77 @@ udpConf(ClientData clientData, Tcl_Interp *interp, } } +/* + * ---------------------------------------------------------------------- + * udpPeek -- + * peek some data and set the peer information + * ---------------------------------------------------------------------- + */ +int +udpPeek(ClientData clientData, Tcl_Interp *interp, + int argc, CONST84 char * argv[]) +{ +#ifndef WIN32 + int buffer_size = 16; + int actual_size, socksize, port; + int sock; + char message[17]; + char *remotehost; + struct hostent *name; +#ifdef SIPC_IPV6 + struct sockaddr_in6 recvaddr; +#else + struct sockaddr_in recvaddr; +#endif + Tcl_Channel chan; + UdpState *statePtr; + + chan = Tcl_GetChannel(interp, (char *)argv[1], NULL); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } + statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan); + sock = Tcl_GetChannelHandle (chan, (TCL_READABLE | TCL_WRITABLE), NULL); + + if (argc > 2) { + buffer_size = atoi(argv[2]); + if (buffer_size > 16) buffer_size = 16; + } + actual_size = recvfrom(sock, message, buffer_size, MSG_PEEK, + (struct sockaddr *)&recvaddr, &socksize); + + if (actual_size < 0) { + sprintf(errBuf, "udppeek error"); + Tcl_AppendResult(interp, errBuf, (char *)NULL); + return TCL_ERROR; + } +#ifdef SIPC_IPV6 + remotehost = (char *)inet_ntop(AF_INET6, &recvaddr.sin_addr, statePtr->peerhost, sizeof(statePtr->peerhost) ); + statePtr->peerport = ntohs(recvaddr.sin_port); +#else + strcpy(statePtr->peerhost, (char *)inet_ntoa(recvaddr.sin_addr)); + statePtr->peerport = ntohs(recvaddr.sin_port); +#endif + message[16]='\0'; + + Tcl_AppendResult(interp, message, (char *)NULL); + return TCL_OK; +#else /* WIN32 */ + Tcl_SetResult(interp, "udp_peek not implemented for this platform", + TCL_STATIC); + return TCL_ERROR; +#endif /* ! WIN32 */ +} + #ifdef WIN32 /* + * ---------------------------------------------------------------------- * UdpEventProc -- + * + * Raise an event from the UDP read thread to notify the Tcl interpreter + * that something has happened. + * + * ---------------------------------------------------------------------- */ int UdpEventProc(Tcl_Event *evPtr, int flags) @@ -354,7 +490,9 @@ UdpEventProc(Tcl_Event *evPtr, int flags) } /* + * ---------------------------------------------------------------------- * UDP_SetupProc - called in Tcl_SetEventSource to do the setup step + * ---------------------------------------------------------------------- */ static void UDP_SetupProc(ClientData data, int flags) @@ -380,7 +518,9 @@ UDP_SetupProc(ClientData data, int flags) } /* + * ---------------------------------------------------------------------- * UDP_CheckProc -- + * ---------------------------------------------------------------------- */ void UDP_CheckProc(ClientData data, int flags) @@ -433,186 +573,56 @@ UDP_CheckProc(ClientData data, int flags) p->message = message; p->actual_size = actual_size; #ifdef SIPC_IPV6 - remotehost = (char *)inet_ntoa(AF_INET6, &recvaddr.sin6_addr, p->r_host, sizeof(p->r_host)); - p->r_port = ntohs(recvaddr.sin6_port); -#else - strcpy(p->r_host, (char *)inet_ntoa(recvaddr.sin_addr)); - p->r_port = ntohs(recvaddr.sin_port); -#endif - p->next = NULL; - -#ifdef SIPC_IPV6 - remotehost = (char *)inet_ntoa(AF_INET6, &recvaddr.sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost) ); - statePtr->peerport = ntohs(recvaddr.sin6_port); -#else - strcpy(statePtr->peerhost, (char *)inet_ntoa(recvaddr.sin_addr)); - statePtr->peerport = ntohs(recvaddr.sin_port); -#endif - - if (statePtr->packets == NULL) { - statePtr->packets = p; - statePtr->packetsTail = p; - } else { - statePtr->packetsTail->next = p; - statePtr->packetsTail = p; - } - - UDPTRACE("Received %d bytes from %s:%d through %d\n", - p->actual_size, p->r_host, p->r_port, statePtr->sock); - UDPTRACE("%s\n", p->message); - } - - statePtr->packetNum--; - statePtr->doread = 1; - UDPTRACE("packetNum is %d\n", statePtr->packetNum); - - if (actual_size >= 0) { - evPtr = (UdpEvent *) ckalloc(sizeof(UdpEvent)); - evPtr->header.proc = UdpEventProc; - evPtr->chan = statePtr->channel; - Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); - UDPTRACE("socket %d has data\n", statePtr->sock); - } - } - } - - SetEvent(sockListLock); -} -#endif /* ! WIN32 */ - -/* - *---------------------------------------------------------------------- - * udpOpen - opens a UDP socket and addds the file descriptor to the - * tcl interpreter - *---------------------------------------------------------------------- - */ -int -udpOpen(ClientData clientData, Tcl_Interp *interp, - int argc, CONST84 char * argv[]) -{ - int sock; - char channelName[20]; - UdpState *statePtr; - uint16_t localport = 0; -#ifdef SIPC_IPV6 - struct sockaddr_in6 addr, sockaddr; -#else - struct sockaddr_in addr, sockaddr; -#endif - unsigned long status = 1; - int len; - - Tcl_ChannelType *Udp_ChannelType; - Udp_ChannelType = (Tcl_ChannelType *) ckalloc((unsigned) sizeof(Tcl_ChannelType)); - memset(Udp_ChannelType, 0, sizeof(Tcl_ChannelType)); -#ifdef SIPC_IPV6 - Udp_ChannelType->typeName = strdup("udp6"); -#else - Udp_ChannelType->typeName = strdup("udp"); -#endif - Udp_ChannelType->blockModeProc = NULL; - Udp_ChannelType->closeProc = udpClose; - Udp_ChannelType->inputProc = udpInput; - Udp_ChannelType->outputProc = udpOutput; - Udp_ChannelType->seekProc = NULL; - Udp_ChannelType->setOptionProc = NULL; - Udp_ChannelType->getOptionProc = NULL; - Udp_ChannelType->watchProc = udpWatch; - Udp_ChannelType->getHandleProc = udpGet; - Udp_ChannelType->close2Proc = NULL; - - if (argc >= 2) { - if (udpGetService(interp, argv[1], &localport) != TCL_OK) - return TCL_ERROR; - } - - memset(channelName, 0, sizeof(channelName)); - -#ifdef SIPC_IPV6 - sock = socket(AF_INET6, SOCK_DGRAM, 0); -#else - sock = socket(AF_INET, SOCK_DGRAM, 0); -#endif - if (sock < 0) { - sprintf(errBuf,"%s","udp - socket"); - UDPTRACE("UDP error - socket\n"); - Tcl_AppendResult(interp, errBuf, (char *)NULL); - return TCL_ERROR; - } - memset(&addr, 0, sizeof(addr)); -#ifdef SIPC_IPV6 - addr.sin6_family = AF_INET6; - addr.sin6_port = localport; -#else - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0; - addr.sin_port = localport; -#endif - if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) { - sprintf(errBuf,"%s","udp - bind"); - UDPTRACE("UDP error - bind\n"); - Tcl_AppendResult(interp, errBuf, (char *)NULL); - return TCL_ERROR; - } -#ifdef WIN32 - ioctlsocket(sock, FIONBIO, &status); + remotehost = (char *)inet_ntoa(AF_INET6, &recvaddr.sin6_addr, p->r_host, sizeof(p->r_host)); + p->r_port = ntohs(recvaddr.sin6_port); #else - ioctl(sock, (int) FIONBIO, &status); + strcpy(p->r_host, (char *)inet_ntoa(recvaddr.sin_addr)); + p->r_port = ntohs(recvaddr.sin_port); #endif - if (localport == 0) { - len = sizeof(sockaddr); - getsockname(sock, (struct sockaddr *)&sockaddr, &len); + p->next = NULL; + #ifdef SIPC_IPV6 - localport = sockaddr.sin6_port; + remotehost = (char *)inet_ntoa(AF_INET6, &recvaddr.sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost) ); + statePtr->peerport = ntohs(recvaddr.sin6_port); #else - localport = sockaddr.sin_port; + strcpy(statePtr->peerhost, (char *)inet_ntoa(recvaddr.sin_addr)); + statePtr->peerport = ntohs(recvaddr.sin_port); #endif + + if (statePtr->packets == NULL) { + statePtr->packets = p; + statePtr->packetsTail = p; + } else { + statePtr->packetsTail->next = p; + statePtr->packetsTail = p; + } + + UDPTRACE("Received %d bytes from %s:%d through %d\n", + p->actual_size, p->r_host, p->r_port, statePtr->sock); + UDPTRACE("%s\n", p->message); + } + + statePtr->packetNum--; + statePtr->doread = 1; + UDPTRACE("packetNum is %d\n", statePtr->packetNum); + + if (actual_size >= 0) { + evPtr = (UdpEvent *) ckalloc(sizeof(UdpEvent)); + evPtr->header.proc = UdpEventProc; + evPtr->chan = statePtr->channel; + Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); + UDPTRACE("socket %d has data\n", statePtr->sock); + } + } } - UDPTRACE("Open socket %d. Bind socket to port %d\n", - sock, ntohs(localport)); - - statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState)); - memset(statePtr, 0, sizeof(UdpState)); - statePtr->sock = sock; - sprintf(channelName, "sock%d", statePtr->sock); - statePtr->channel = Tcl_CreateChannel(Udp_ChannelType, channelName, - (ClientData) statePtr, - (TCL_READABLE | TCL_WRITABLE | TCL_MODE_NONBLOCKING)); - statePtr->doread = 1; - statePtr->localport = localport; - Tcl_RegisterChannel(interp, statePtr->channel); -#ifdef WIN32 - statePtr->threadId = Tcl_GetCurrentThread(); - statePtr->packetNum = 0; - statePtr->next = NULL; - statePtr->packets = NULL; - statePtr->packetsTail = NULL; - Tcl_CreateEventSource(UDP_SetupProc, UDP_CheckProc, NULL); -#endif - /* Tcl_SetChannelOption(interp, statePtr->channel, "-blocking", "0"); */ - Tcl_AppendResult(interp, channelName, (char *)NULL); -#ifdef WIN32 - WaitForSingleObject(sockListLock, INFINITE); - if (sockList == NULL) { - sockList = statePtr; - sockTail = statePtr; - } else { - sockTail->next = statePtr; - sockTail = statePtr; - } - - UDPTRACE("Append %d to sockList\n", statePtr->sock); SetEvent(sockListLock); - SetEvent(waitForSock); -#endif - return TCL_OK; } -#ifdef WIN32 - /* + * ---------------------------------------------------------------------- * InitSockets + * ---------------------------------------------------------------------- */ static int InitSockets() @@ -630,7 +640,9 @@ InitSockets() } /* + * ---------------------------------------------------------------------- * SocketThread + * ---------------------------------------------------------------------- */ static DWORD WINAPI SocketThread(LPVOID arg) @@ -704,7 +716,9 @@ SocketThread(LPVOID arg) } /* + * ---------------------------------------------------------------------- * Udp_WinHasSockets -- + * ---------------------------------------------------------------------- */ int Udp_WinHasSockets(Tcl_Interp *interp) @@ -740,7 +754,7 @@ Udp_WinHasSockets(Tcl_Interp *interp) } /* - * Start the socketThread windows and set the thread priority of the + * Start the socketThread window and set the thread priority of the * socketThread as highest */ @@ -772,39 +786,120 @@ Udp_WinHasSockets(Tcl_Interp *interp) #endif /* ! WIN32 */ /* - * udpInit + * ---------------------------------------------------------------------- + * udpClose -- + * Called from the channel driver code to cleanup and close + * the socket. + * + * Results: + * 0 if successful, the value of errno if failed. + * + * Side effects: + * The socket is closed. + * + * ---------------------------------------------------------------------- */ -int -Udp_Init(Tcl_Interp *interp) +static int +udpClose(ClientData instanceData, Tcl_Interp *interp) { - int r = TCL_OK; -#if defined(DEBUG) && !defined(WIN32) - dbg = fopen("udp.dbg", "wt"); -#endif - -#ifdef USE_TCL_STUBS - Tcl_InitStubs(interp, "8.3", 0); + int sock; + int errorCode = 0; + UdpState *statePtr = (UdpState *) instanceData; +#ifdef WIN32 + UdpState *statePre; + + WaitForSingleObject(sockListLock, INFINITE); +#endif /* ! WIN32 */ + + sock = statePtr->sock; + +#ifdef WIN32 + /* remove the statePtr from the list */ + for (statePtr = sockList, statePre = sockList; + statePtr != NULL; + statePre=statePtr, statePtr=statePtr->next) { + if (statePtr->sock == sock) { + UDPTRACE("Remove %d from the list\n", sock); + if (statePtr == sockList) { + sockList = statePtr->next; + } else { + statePre->next = statePtr->next; + if (sockTail == statePtr) + sockTail = statePre; + } + } + } +#endif /* ! WIN32 */ + + ckfree((char *) statePtr); + if (closesocket(sock) < 0) { + errorCode = errno; + } + if (errorCode != 0) { +#ifndef WIN32 + sprintf(errBuf, "udpClose: %d, error: %d\n", sock, errorCode); +#else + sprintf(errBuf, "udpClose: %d, error: %d\n", sock, WSAGetLastError()); #endif - + UDPTRACE("UDP error - close %d", sock); + } else { + UDPTRACE("Close socket %d\n", sock); + } + #ifdef WIN32 - if (Udp_WinHasSockets(interp) != TCL_OK) { - return TCL_ERROR; + SetEvent(sockListLock); +#endif + + return errorCode; +} + +/* + * ---------------------------------------------------------------------- + * udpWatch -- + * ---------------------------------------------------------------------- + */ +static void +udpWatch(ClientData instanceData, int mask) +{ +#ifndef WIN32 + UdpState *fsPtr = (UdpState *) instanceData; + if (mask) { + UDPTRACE("Tcl_CreateFileHandler\n"); + Tcl_CreateFileHandler(fsPtr->sock, mask, + (Tcl_FileProc *) Tcl_NotifyChannel, + (ClientData) fsPtr->channel); + } else { + UDPTRACE("Tcl_DeleteFileHandler\n"); + Tcl_DeleteFileHandler(fsPtr->sock); } #endif +} - Tcl_CreateCommand(interp, "udp_open", udpOpen , - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "udp_conf", udpConf , - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - Tcl_CreateCommand(interp, "udp_peek", udpPeek , - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - - r = Tcl_PkgProvide(interp, TCLUDP_PACKAGE_NAME, TCLUDP_PACKAGE_VERSION); - return r; +/* + * ---------------------------------------------------------------------- + * udpGetHandle -- + * Called from the channel driver to get a handle to the socket. + * + * Results: + * Puts the socket into handlePtr and returns TCL_OK; + * + * Side Effects: + * None + * ---------------------------------------------------------------------- + */ +static int +udpGetHandle(ClientData instanceData, int direction, ClientData *handlePtr) +{ + UdpState *statePtr = (UdpState *) instanceData; + UDPTRACE("udpGetHandle %ld\n", (long)statePtr->sock); + *handlePtr = (ClientData) statePtr->sock; + return TCL_OK; } /* + * ---------------------------------------------------------------------- * udpOutput-- + * ---------------------------------------------------------------------- */ static int udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCode) @@ -869,7 +964,9 @@ udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCod } /* + * ---------------------------------------------------------------------- * udpInput + * ---------------------------------------------------------------------- */ static int udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode) @@ -983,6 +1080,139 @@ udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode) return -1; } +/* + * ---------------------------------------------------------------------- + * udpGetOption -- + * ---------------------------------------------------------------------- + */ +static int +udpGetOption(ClientData instanceData, Tcl_Interp *interp, + CONST84 char *optionName, Tcl_DString *optionValue) +{ + UdpState *statePtr = (UdpState *)instanceData; + const char * options = "myport remote peer mcastadd mcastdrop"; + int r = TCL_OK; + + if (optionName == NULL) { + + Tcl_DStringAppend(optionValue, " -myport ", -1); + udpGetOption(instanceData, interp, "-myport", optionValue); + Tcl_DStringAppend(optionValue, " -remote ", -1); + udpGetOption(instanceData, interp, "-remote", optionValue); + Tcl_DStringAppend(optionValue, " -peer ", -1); + udpGetOption(instanceData, interp, "-peer", optionValue); + Tcl_DStringAppend(optionValue, " -mcastadd ", -1); + udpGetOption(instanceData, interp, "-mcastadd", optionValue); + Tcl_DStringAppend(optionValue, " -mcastdrop ", -1); + udpGetOption(instanceData, interp, "-mcastdrop", optionValue); + + } else { + + Tcl_DString ds, dsInt; + Tcl_DStringInit(&ds); + Tcl_DStringInit(&dsInt); + + if (!strcmp("-myport", optionName)) { + + Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE); + sprintf(Tcl_DStringValue(&ds), "%u", ntohs(statePtr->localport)); + + } else if (!strcmp("-remote", optionName)) { + + Tcl_DStringSetLength(&dsInt, TCL_INTEGER_SPACE); + sprintf(Tcl_DStringValue(&dsInt), "%u", + ntohs(statePtr->remoteport)); + Tcl_DStringAppendElement(&ds, statePtr->remotehost); + Tcl_DStringAppendElement(&ds, Tcl_DStringValue(&dsInt)); + + } else if (!strcmp("-peer", optionName)) { + + Tcl_DStringSetLength(&dsInt, TCL_INTEGER_SPACE); + sprintf(Tcl_DStringValue(&dsInt), "%u", statePtr->peerport); + Tcl_DStringAppendElement(&ds, statePtr->peerhost); + Tcl_DStringAppendElement(&ds, Tcl_DStringValue(&dsInt)); + + } else if (!strcmp("-mcastadd", optionName)) { + ; + } else if (!strcmp("-mcastdrop", optionName)) { + ; + } else { + r = Tcl_BadChannelOption(interp, optionName, options); + } + + Tcl_DStringAppendElement(optionValue, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&dsInt); + Tcl_DStringFree(&ds); + } + + return r; +} + +/* + * ---------------------------------------------------------------------- + * udpSetOption -- + * + * Handle channel configuration requests from the generic layer. + * + * ---------------------------------------------------------------------- + */ +static int +udpSetOption(ClientData instanceData, Tcl_Interp *interp, + CONST char *optionName, CONST char *newValue) +{ + UdpState *statePtr = (UdpState *)instanceData; + const char * options = "remote mcastadd mcastdrop"; + int r = TCL_OK; + + if (!strcmp("-remote", optionName)) { + + Tcl_Obj *valPtr; + int len; + + valPtr = Tcl_NewStringObj(newValue, -1); + r = Tcl_ListObjLength(interp, valPtr, &len); + if (r == TCL_OK) { + if (len < 1 || len > 2) { + Tcl_SetResult(interp, "wrong # args", TCL_STATIC); + r = TCL_ERROR; + } else { + Tcl_Obj *hostPtr, *portPtr; + + Tcl_ListObjIndex(interp, valPtr, 0, &hostPtr); + strcpy(statePtr->remotehost, Tcl_GetString(hostPtr)); + + if (len == 2) { + Tcl_ListObjIndex(interp, valPtr, 1, &portPtr); + r = udpGetService(interp, Tcl_GetString(portPtr), + &(statePtr->remoteport)); + } + } + } + + } else if (!strcmp("-mcastadd", optionName)) { + + Tcl_SetResult(interp, "E_NOTIMPL", TCL_STATIC); + r = TCL_ERROR; + + } else if (!strcmp("-mcastdrop", optionName)) { + + Tcl_SetResult(interp, "E_NOTIMPL", TCL_STATIC); + r = TCL_ERROR; + + } else { + + r = Tcl_BadChannelOption(interp, optionName, options); + + } + + return r; +} + +/* + * ---------------------------------------------------------------------- + * udpTrace -- + * ---------------------------------------------------------------------- + */ static void udpTrace(const char *format, ...) { @@ -1007,10 +1237,14 @@ udpTrace(const char *format, ...) } /* - * Return the service port number in network byte order from either a string - * representation of the port number or the service name. If the service - * string cannot be converted (ie: a name not present in the services - * database) then set a Tcl error. + * ---------------------------------------------------------------------- + * udpGetSetvice -- + * + * Return the service port number in network byte order from either a string + * representation of the port number or the service name. If the service + * string cannot be converted (ie: a name not present in the services + * database) then set a Tcl error. + * ---------------------------------------------------------------------- */ static int udpGetService(Tcl_Interp *interp, const char *service, @@ -1035,3 +1269,12 @@ udpGetService(Tcl_Interp *interp, const char *service, } return r; } + +/* + * ---------------------------------------------------------------------- + * + * Local variables: + * mode: c + * indent-tabs-mode: nil + * End: + */ diff --git a/tests/udp.test b/tests/udp.test index 2bcc8f9..14318b4 100644 --- a/tests/udp.test +++ b/tests/udp.test @@ -84,7 +84,7 @@ test udp-2.1 {udp_conf using service number} { set r} msg] $msg } {0 {localhost 123}} -test udp-2.2 {udp_open on named port} windows { +test udp-2.2 {udp_open on named port} {pcOnly} { list [catch { set port ntp set s [udp_open $port] diff --git a/win/tcludp.dsp b/win/tcludp.dsp index 0da73c9..4508c7e 100644 --- a/win/tcludp.dsp +++ b/win/tcludp.dsp @@ -1,115 +1,119 @@ -# Microsoft Developer Studio Project File - Name="tcludp" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=tcludp - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "tcludp.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "tcludp.mak" CFG="tcludp - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "tcludp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "tcludp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "tcludp - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCLUDP_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D VERSION=\"1.0.4\" /D "USE_TCL_STUBS" /D "TCLUDP_EXPORTS" /D "BUILD_udp" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x809 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 tclstub84.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/udp104.dll" - -!ELSEIF "$(CFG)" == "tcludp - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCLUDP_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D VERSION=\"1.0.4\" /D "USE_TCL_STUBS" /D "TCLUDP_EXPORTS" /D "BUILD_udp" /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x809 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 tclstub84.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/udp104d.dll" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "tcludp - Win32 Release" -# Name "tcludp - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\generic\udp_tcl.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\generic\udp_tcl.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\tcludp.rc -# End Source File -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="tcludp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=tcludp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tcludp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tcludp.mak" CFG="tcludp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tcludp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "tcludp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tcludp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCLUDP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D VERSION=\"1.0.5\" /D "USE_TCL_STUBS" /D "TCLUDP_EXPORTS" /D "BUILD_udp" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 tclstub84.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/udp105.dll" + +!ELSEIF "$(CFG)" == "tcludp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCLUDP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D VERSION=\"1.0.5\" /D "USE_TCL_STUBS" /D "TCLUDP_EXPORTS" /D "BUILD_udp" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 tclstub84.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug/udp105d.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "tcludp - Win32 Release" +# Name "tcludp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\generic\udp_tcl.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\generic\udp_tcl.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\tcludp.rc +# End Source File +# End Group +# Begin Source File + +SOURCE=..\tests\udp.test +# End Source File +# End Target +# End Project -- 2.23.0