Fixed udpGetHandle to perform as per specs.
authorpatthoyts <patthoyts>
Wed, 12 Mar 2003 00:21:15 +0000 (00:21 +0000)
committerpatthoyts <patthoyts>
Wed, 12 Mar 2003 00:21:15 +0000 (00:21 +0000)
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
configure
configure.in
generic/udp_tcl.c
tests/udp.test
win/tcludp.dsp

index f6f08d257ca5db898d10579ea2a93e92549b5b23..4bc13ee2c2ddf78a8092872269f41eb0897922c8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2003-03-12  Pat Thoyts  <patthoyts@users.sourceforge.net>
+
+       * win/tcludp.dsp:
+       * configure.in: bumped patchlevel to 1.0.5
+
+2003-03-05  Pat Thoyts  <patthoyts@users.sourceforge.net>
+
+       * 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  <patthoyts@users.sourceforge.net>
 
        * generic/udp_tcl.c: Fix include list to use the autoconfig test
index b3d1da9199d2bb632f0bda619b44f39b7671cc80..5787270e21599200485ce628248cd148cfe795d9 100755 (executable)
--- 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}
index e07e4c02fd378d3d0cb00d0d7919c064aaa1b15d..a697d17f8d4d4995d66278f7239ff46bbf81dc71 100644 (file)
@@ -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}
index 89605b3b75f648c655ee0b086f9d4010780dc3ef..5f8874902598d0ddd8a01384b70509c464b7219b 100644 (file)
@@ -20,9 +20,6 @@
 
 #ifdef WIN32
 #include <stdlib.h>
-#include <tcl.h>
-#include <winsock.h>
-#include <stdio.h>
 #include <malloc.h>
 #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:
+ */
index 2bcc8f933241e54463ecf633335c6eeab913bfb5..14318b42acecfc40ad4e96a2e835d552e8368233 100644 (file)
@@ -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]
index 0da73c9089b825e596e687ee5663815ea0e10588..4508c7e93f5ec77641adc0a596f3193266483a58 100644 (file)
-# Microsoft Developer Studio Project File - Name="tcludp" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=tcludp - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "tcludp.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "tcludp.mak" CFG="tcludp - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "tcludp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "tcludp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "tcludp - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCLUDP_EXPORTS" /YX /FD /c\r
-# 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\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x809 /d "NDEBUG"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# 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\r
-# 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"\r
-\r
-!ELSEIF  "$(CFG)" == "tcludp - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# 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\r
-# 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\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x809 /d "_DEBUG"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# 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\r
-# 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\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "tcludp - Win32 Release"\r
-# Name "tcludp - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=..\generic\udp_tcl.c\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=..\generic\udp_tcl.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# Begin Source File\r
-\r
-SOURCE=.\tcludp.rc\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
+# 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