From: xiaotaow Date: Mon, 3 Mar 2003 05:56:21 +0000 (+0000) Subject: Changed by Pat to fit into TEA format. X-Git-Tag: tcludp-1_0_4~3 X-Git-Url: https://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=2f81f6a5b095bea6f774d73fda2cbb327744afa8;p=tcludp Changed by Pat to fit into TEA format. -Xiaotao --- diff --git a/src/README b/src/README deleted file mode 100644 index d1ab2cd..0000000 --- a/src/README +++ /dev/null @@ -1,77 +0,0 @@ -Tcl UDP extension - -1. History of the extension -2. Synopsis -3. How to build and test -4. How to use -5. Feedback - -1. History of the extension ----------------------------------------------------------------------- -Some of the code in this extension is copied from Michael Miller's tcludp -package. (http://www.neosoft.com/tcl/ftparchive/sorted/comm/tcludp-1.0/) -Compared with Michael's UDP extension, this extension provides Windows -support and provides the ability of using 'gets/puts' to read/write -the socket. In addition, it provides more configuration ability. - -2. Synopsis ----------------------------------------------------------------------- -udp_open ?port? -udp_conf sock host port -udp_conf sock ?option? (options: -myport -remote -peer) -udp_peek sock ?buffersize? - -udp_open will open a UDP sockets. If 'port' is specified, the UDP socket -will be opened on that port. Otherwise, the system will choose a port and -the user can use 'udp_conf -myport' to get the port number. - -'udp_conf sock host port' will define the remote host and port to send the -UDP packets to. Prior to using 'puts' to write to the socket, please use -udp_conf to set the remote host and port. - -'udp_conf sock ?option?' will get the socket information. -'udp_conf -myport' will get the local port of the socket -'udp_conf -remote' will get the remote host and port that the socket - will send packets to. -'udp_conf -peer' will get the remote host and port information of the - most recently received packet. - -udp_peek will peek a packet without removing it from the buffer. - -3. How to build and test ----------------------------------------------------------------------- -This extension is to add UDP support for Tcl. -This extension is for Tcl8.0 or later. -Before compiling, please modify the Makefile for proper Tcl path. -......................................... -To compile under Unix, -make -f makefile.unix -libudp.so will be in the ../unix directory -.......................................... -To compile under Linux, -make -f makefile.linux -libudp.so will be in the ../linux directory -........................................... -To compile under Windows -nmake -f makefile.vc -udp.dll will be in the ../win directory -........................................... -The ../test contains two test programs. One is for sending and the other -is for receiving UDP packet. - -4. How to use ----------------------------------------------------------------------- -Use Tcl 'load' command to load the library. -Use udp_open to open a socket. Use udp_conf to specify the remote host -and port and get the socket information. Use 'gets/puts' to receive/send -packets. Use udp_peek to peek the packets. - -5. Feedback ----------------------------------------------------------------------- -If you have any problem with this extension, please contact Xiaotao Wu - -Name : Xiaotao Wu -Email : xiaotaow@cs.columbia.edu, xw71@columbia.edu -URL : http://www.cs.columbia.edu/~xiaotaow -Phone : (212)939-7020, (212)939-7133, Fax: (801)751-0217 -SIP : sip:xiaotaow@conductor.cs.columbia.edu diff --git a/src/makefile.linux b/src/makefile.linux deleted file mode 100755 index c7e82b3..0000000 --- a/src/makefile.linux +++ /dev/null @@ -1,81 +0,0 @@ -# Generated automatically from Makefile.in by configure. -# -# This file is a Makefile for UDPTcl. -# -# - -include ../../makefile.linux.include - -# Set the CFLAGS variable to -g if you want debug option. You can also -# SPECIFY IT in the command line. E.g., type -# make CFLAGS=-g all -# -CFLAGS = -O -D_$(TCLVERSION) -DLINUX - -# The directory containing the Tcl sources and headers appropriate for -# this version of your shared library ("srcdir" will be replaced or -# has already been replaced by the configure script): -# TCL_INC_DIR = /usr/include -TCL_INC_DIR = $(TCLDIR)/generic - -# The directory containing the Tcl library archive file appropriate -# for this version of Tk: -#TCL_LIB_DIR = /usr/lib -TCL_LIB_DIR = $(TCLDIR)/unix - -# Libraries to use when linking: -# For Linux -LIBS = -L$(TCL_LIB_DIR) -l$(TCLLIB) -ldl -lm -lc - -#---------------------------------------------------------------- -# The information below is modified by the configure script when -# Makefile is generated from Makefile.in. You shouldn't normally -# modify any of this stuff by hand. -#---------------------------------------------------------------- - -CC = gcc -SHLIB_CFLAGS = -fPIC -# Linux ld -SHLIB_LD = /usr/bin/ld -G -z text -SHLIB_SUFFIX = .so -SHLIB_VERSION = -SRC_DIR = . -OBJ_DIR = ../obj -LIB_DIR = ../linux -AC_FLAGS = -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 - -CC_SWITCHES = $(CFLAGS) -I${TCL_INC_DIR} -I${SRC_DIR} ${SHLIB_CFLAGS} \ - $(AC_FLAGS) - -UDP_LIB_FILE = $(LIB_DIR)/libudp.so - -OBJS = \ - $(OBJ_DIR)/udp_tcl.o - -all: $(UDP_LIB_FILE) - -$(UDP_LIB_FILE): $(OBJ_DIR) $(LIB_DIR) $(OBJS) - rm -f $(UDP_LIB_FILE) - ${SHLIB_LD} -o $(UDP_LIB_FILE) ${OBJS} ${LIBS} - -#---------------------------------------------------------------------- - -$(OBJ_DIR)/udp_tcl.o: $(SRC_DIR)/udp_tcl.c - $(CC) $(CC_SWITCHES) -c $(SRC_DIR)/udp_tcl.c -o \ - $(OBJ_DIR)/udp_tcl.o - -#---------------------------------------------------------------------- - -$(OBJ_DIR): - if [ ! -d $(OBJ_DIR) ]; then \ - mkdir $(OBJ_DIR); \ - fi - -$(LIB_DIR): - if [ ! -d $(LIB_DIR) ]; then \ - mkdir $(LIB_DIR); \ - fi - -clean: - rm -f $(OBJ_DIR)/*.o $(LIB_DIR)/*${SHLIB_SUFFIX} $(LIB_DIR)/*.a - diff --git a/src/makefile.unix b/src/makefile.unix deleted file mode 100755 index 61e0256..0000000 --- a/src/makefile.unix +++ /dev/null @@ -1,94 +0,0 @@ -# -# This file is a Makefile for TclUDP for Tcl 8.4 under SunOS -# -# - -include ../../makefile.unix.include - -# Set the CFLAGS variable to -g if you want debug option. You can also -# specify it in the command line. E.g., type -# make CFLAGS=-g all -# -# Define SIPC_IPV6 for IPV6 support -# CFLAGS = -O -D_$(TCLVERSION) -DSIPC_IPV6 -CFLAGS = -O -D_$(TCLVERSION) - -# The directory containing the Tcl sources and headers appropriate for -# this version of your shared library ("srcdir" will be replaced or -# has already been replaced by the configure script): - -TCL_INC_DIR = $(TCLDIR)/generic - -# The directory containing the Tcl library archive file appropriate -# for this version of Tk: - -TCL_LIB_DIR = $(TCLDIR)/unix - -# Static library of Tcl - -TCL_STATIC = $(TCLDIR)/unix/lib$(TCLLIB).a - -# Libraries to use when linking: -# For Solaris -# LIBS = -L$(TCL_LIB_DIR) -l$(TCLVERSION) -ldl -lsocket -lnsl -lm -lc - -LIBS = $(TCL_STATIC) -ldl -lsocket -lnsl -lm -lc - -#---------------------------------------------------------------- -# The information below is modified by the configure script when -# Makefile is generated from Makefile.in. You shouldn't normally -# modify any of this stuff by hand. -#---------------------------------------------------------------- - -CC = gcc -SHLIB_CFLAGS = -fPIC -SHLIB_LD = /usr/ccs/bin/ld -G -z text -RANLIB = ranlib -SHLIB_SUFFIX = .so -SHLIB_VERSION = -SRC_DIR = . -OBJ_DIR = ../obj -LIB_DIR = ../unix -AC_FLAGS = -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 - -CC_SWITCHES = $(CFLAGS) -I${TCL_INC_DIR} -I${SRC_DIR} ${SHLIB_CFLAGS} \ - -D__SOLARIS__ $(AC_FLAGS) - -UDP_LIB_FILE = $(LIB_DIR)/libudp.so -UDP_STATIC_FILE = $(LIB_DIR)/libudp.a - -OBJS = \ - $(OBJ_DIR)/udp_tcl.o - -all: $(UDP_LIB_FILE) $(UTIL_STATIC_FILE) - -$(UDP_LIB_FILE): $(OBJ_DIR) $(LIB_DIR) $(OBJS) - rm -f $(UDP_LIB_FILE) - ${SHLIB_LD} -o $(UDP_LIB_FILE) ${OBJS} ${LIBS} - -$(UDP_STATIC_FILE): $(OBJ_DIR) $(LIB_DIR) $(OBJS) - rm -f $(UDP_STATIC_FILE) - ar cr $(UDP_STATIC_FILE) $(OBJS) - $(RANLIB) $(UDP_STATIC_FILE) - -#---------------------------------------------------------------------- - -$(OBJ_DIR)/udp_tcl.o: $(SRC_DIR)/udp_tcl.c - $(CC) $(CC_SWITCHES) -c $(SRC_DIR)/udp_tcl.c -o \ - $(OBJ_DIR)/udp_tcl.o - -#---------------------------------------------------------------------- - -$(OBJ_DIR): - if [ ! -d $(OBJ_DIR) ]; then \ - mkdir $(OBJ_DIR); \ - fi - -$(LIB_DIR): - if [ ! -d $(LIB_DIR) ]; then \ - mkdir $(LIB_DIR); \ - fi - -clean: - rm -f $(OBJ_DIR)/*.o $(LIB_DIR)/*${SHLIB_SUFFIX} $(LIB_DIR)/*.a - diff --git a/src/makefile.vc b/src/makefile.vc deleted file mode 100644 index 525ea6a..0000000 --- a/src/makefile.vc +++ /dev/null @@ -1,38 +0,0 @@ -include ..\..\makefile.vc.include - -SRC_DIR = . -WIN_DIR = ..\win -OBJ_DIR = ..\obj - -CP = copy -RM = del - -INCLUDES = -I$(TOOLS32)\include -I$(WIN_DIR) -I$(TCL_GENERIC_DIR) -I$(TK_GENERIC_DIR) -I$(MFC_DIR)\include - -#use -DDEBUG to enable debug output. The debug output will be sent to udp.dbg file -DEFINES = -nologo -D_$(TCLVERSION) -DWIN32 - -OBJS = $(OBJ_DIR)\udp_tcl.obj - -UDPDLL = udp.dll - -$(UDPDLL): $(OBJ_DIR) $(OBJS) $(WIN_DIR) - @set LIB=$(TOOLS32)\lib - cl $(OBJS) /LD -o $(WIN_DIR)\$(UDPDLL) /link Wsock32.lib winmm.lib user32.lib $(MFC_DIR)\lib\nafxcw.lib $(guilibsdll) $(TCL_LIB) - -$(OBJ_DIR): - -@if not exist $(OBJ_DIR)\nul mkdir $(OBJ_DIR) -$(WIN_DIR): - -@if not exist $(WIN_DIR)\nul mkdir $(WIN_DIR) - -$(OBJ_DIR)\udp_tcl.obj : $(SRC_DIR)\udp_tcl.c - $(cc32) $(cdebug) -c $(cvarsdll) $(INCLUDES) \ - $(DEFINES) /Fo$(OBJ_DIR)\udp_tcl.obj $(SRC_DIR)\udp_tcl.c - -clean: - -@if exist $(OBJ_DIR)\*.obj $(RM) $(OBJ_DIR)\*.obj - -@if exist $(WIN_DIR)\$(UDPDLL) $(RM) $(WIN_DIR)\$(UDPDLL) - -@if exist $(WIN_DIR)\udp.lib $(RM) $(WIN_DIR)\udp.lib - -@if exist $(WIN_DIR)\udp.exp $(RM) $(WIN_DIR)\udp.exp - -@if exist pkgIndex.tcl $(RM) pkgIndex.tcl - diff --git a/src/udp_tcl.c b/src/udp_tcl.c deleted file mode 100644 index ec22a2a..0000000 --- a/src/udp_tcl.c +++ /dev/null @@ -1,1058 +0,0 @@ -/****************************************************************************** - * UDP Extension for Tcl 8.4 - * - * Copyright 1999-2000 by Columbia University; all rights reserved - * - * Written by Xiaotao Wu - * Last modified: 11/03/2000 - ******************************************************************************/ -#include "udp_tcl.h" - -#ifdef WIN32 -#include -#include -#include -#include -#else -#ifdef LINUX -#include -#else -#include -#endif -#endif - -#ifdef DEBUG -FILE *dbg; -#endif - -#define MAXBUFFERSIZE 4096 - -static char errBuf[256]; - -EXTERN int Udp_Init(Tcl_Interp *); - -int udpOpen(ClientData , Tcl_Interp *, int , char *[]); -int udpConf(ClientData , Tcl_Interp *, int , char *[]); -int udpPeek(ClientData , Tcl_Interp *, int , char *[]); - -static int udpGet(ClientData instanceData,int direction,ClientData *handlePtr); -static void udpWatch(ClientData instanceData, int mask); -static int udpOutput(ClientData instanceData, 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); - -#ifdef WIN32 -static HANDLE waitForSock; -static HANDLE waitSockRead; -static HANDLE sockListLock; -static UdpState *sockList; -static UdpState *sockTail; -#endif - -/* - * udpClose - */ -int udpClose(ClientData instanceData, Tcl_Interp *interp) { - int sock; - int errorCode = 0; - UdpState *statePtr = (UdpState *) instanceData; -#ifdef WIN32 - UdpState *statePre; - - WaitForSingleObject(sockListLock, INFINITE); -#endif - - 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) { -#ifdef DEBUG - fprintf(dbg, "Remove %d from the list\n", sock); - fflush(dbg); -#endif - if (statePtr == sockList) { - sockList = statePtr->next; - } else { - statePre->next = statePtr->next; - if (sockTail == statePtr) - sockTail = statePre; - } - } - } -#endif - - ckfree((char *) statePtr); -#ifndef WIN32 - if (close(sock) < 0) { -#else - if (closesocket(sock) < 0) { -#endif - 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 -#ifdef DEBUG - fprintf(dbg, "UDP error - close %d", sock); - fflush(dbg); -#endif - } else { -#ifdef DEBUG - fprintf(dbg, "Close socket %d\n", sock); - fflush(dbg); -#endif - } - -#ifdef WIN32 - SetEvent(sockListLock); -#endif - - return errorCode; -} - -/* - * udpWatch - */ -static void udpWatch(ClientData instanceData, int mask) { -#ifndef WIN32 - UdpState *fsPtr = (UdpState *) instanceData; - if (mask) { -#ifdef DEBUG - fprintf(dbg, "Tcl_CreateFileHandler\n"); - fflush(dbg); -#endif - Tcl_CreateFileHandler(fsPtr->sock, mask, - (Tcl_FileProc *) Tcl_NotifyChannel, - (ClientData) fsPtr->channel); - } else { -#ifdef DEBUG - fprintf(dbg, "Tcl_DeleteFileHandler\n"); - fflush(dbg); -#endif - Tcl_DeleteFileHandler(fsPtr->sock); - } -#endif -} - -/* - * udpGet - */ -static int udpGet(ClientData instanceData,int direction,ClientData *handlePtr) { - UdpState *statePtr = (UdpState *) instanceData; -#ifdef DEBUG - fprintf(dbg, "UDP_get %d\n", statePtr->sock); - fflush(dbg); -#endif - return statePtr->sock; -} - -/* - * udpPeek - peek some data and set the peer information - */ -int udpPeek(ClientData clientData, Tcl_Interp *interp, int argc, 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, 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); -#endif - return TCL_OK; -} - -/* - * udpConf - */ -int udpConf(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { - Tcl_Channel chan; - UdpState *statePtr; - char *result; - char buf[128]; - struct hostent *name; - struct ip_mreq mreq; - struct sockaddr_in maddr; - int sock, ret; - - if (argc != 4 && argc != 3) { - result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } - chan = Tcl_GetChannel(interp, argv[1], NULL); - if (chan == (Tcl_Channel) NULL) { - return TCL_ERROR; - } - statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan); - sock = statePtr->sock; - - if (argc == 3) { - if (!strcmp(argv[2], "-myport")) { - sprintf(buf, "%d", statePtr->localport); - Tcl_AppendResult(interp, buf, (char *)NULL); - } else if (!strcmp(argv[2], "-remote")) { - sprintf(buf, "%s", statePtr->remotehost); - Tcl_AppendResult(interp, buf, (char *)NULL); - sprintf(buf, "%d", statePtr->remoteport); - Tcl_AppendElement(interp, buf); - } else if (!strcmp(argv[2], "-peer")) { - sprintf(buf, "%s", statePtr->peerhost); - Tcl_AppendResult(interp, buf, (char *)NULL); - sprintf(buf, "%d", statePtr->peerport); - Tcl_AppendElement(interp, buf); - } else { - result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } - return TCL_OK; - } else if (argc == 4) { - if (!strcmp(argv[2], "-mcastadd")) { - if (strlen(argv[3]) >= sizeof(statePtr->remotehost)) { - result = "hostname too long"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } - mreq.imr_multiaddr.s_addr = inet_addr(argv[3]); - if (mreq.imr_multiaddr.s_addr == -1) { - name = gethostbyname(argv[3]); - if (name == NULL) { -#ifdef DEBUG - fprintf(dbg, "UDP error - gethostbyname"); - fflush(dbg); -#endif - return TCL_ERROR; - } - memcpy(&mreq.imr_multiaddr.s_addr, name->h_addr, sizeof(mreq.imr_multiaddr.s_addr)); - } - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { -#ifdef DEBUG - fprintf(dbg, "UDP error - setsockopt - IP_ADD_MEMBERSHIP"); - fflush(dbg); -#endif - return TCL_ERROR; - } - maddr.sin_addr.s_addr = htonl(INADDR_ANY); - return TCL_OK; - } else if (!strcmp(argv[2], "-mcastdrop")) { - if (strlen(argv[3]) >= sizeof(statePtr->remotehost)) { - result = "hostname too long"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } - mreq.imr_multiaddr.s_addr = inet_addr(argv[3]); - if (mreq.imr_multiaddr.s_addr == -1) { - name = gethostbyname(argv[3]); - if (name == NULL) { -#ifdef DEBUG - fprintf(dbg, "UDP error - gethostbyname"); - fflush(dbg); -#endif - return TCL_ERROR; - } - memcpy(&mreq.imr_multiaddr.s_addr, name->h_addr, sizeof(mreq.imr_multiaddr.s_addr)); - } - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { -#ifdef DEBUG - fprintf(dbg, "UDP error - setsockopt - IP_DROP_MEMBERSHIP"); - fflush(dbg); -#endif - return TCL_ERROR; - } - return TCL_OK; - } else { - if (strlen(argv[2]) >= sizeof(statePtr->remotehost)) { - result = "hostname too long"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } - strcpy(statePtr->remotehost, argv[2]); - statePtr->remoteport = atoi(argv[3]); - return TCL_OK; - } - } else { - result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]"; - Tcl_SetResult (interp, result, NULL); - return TCL_ERROR; - } -} - -#ifdef WIN32 -/* - * UdpEventProc -- - */ -int UdpEventProc(Tcl_Event *evPtr, int flags) { - UdpEvent *eventPtr = (UdpEvent *) evPtr; - int mask = 0; - - mask |= TCL_READABLE; -#ifdef DEBUG - fprintf(dbg, "UdpEventProc\n"); - fflush(dbg); -#endif - Tcl_NotifyChannel(eventPtr->chan, mask); - return 1; -} - -/* - * UDP_SetupProc - called in Tcl_SetEventSource to do the setup step - */ -static void UDP_SetupProc(ClientData data, int flags) { - UdpState *statePtr; - Tcl_Time blockTime = { 0, 0 }; - -#ifdef DEBUG - fprintf(dbg, "setupProc\n"); - fflush(dbg); -#endif - - if (!(flags & TCL_FILE_EVENTS)) { - return; - } - - WaitForSingleObject(sockListLock, INFINITE); - for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) { - if (statePtr->packetNum > 0) { -#ifdef DEBUG - fprintf(dbg, "UDP_SetupProc\n"); - fflush(dbg); -#endif - Tcl_SetMaxBlockTime(&blockTime); - break; - } - } - SetEvent(sockListLock); -} - -/* - * UDP_CheckProc -- - */ -void UDP_CheckProc(ClientData data, int flags) { - UdpState *statePtr; - UdpEvent *evPtr; - int actual_size, socksize, reply; - int buffer_size = MAXBUFFERSIZE; - int port; - struct hostent *name; - char *remotehost, *message; -#ifdef SIPC_IPV6 - char number[128]; - struct sockaddr_in6 recvaddr; -#else - char number[32]; - struct sockaddr_in recvaddr; -#endif - PacketList *p; - -#ifdef DEBUG - fprintf(dbg, "checkProc\n"); - fflush(dbg); -#endif - - //synchronized - WaitForSingleObject(sockListLock, INFINITE); - - for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) { - if (statePtr->packetNum > 0) { - -#ifdef DEBUG - fprintf(dbg, "UDP_CheckProc\n"); - fflush(dbg); -#endif - //Read the data from socket and put it into statePtr - socksize = sizeof(recvaddr); -#ifdef SIPC_IPV6 - memset(number, 0, 128); -#else - memset(number, 0, 32); -#endif - memset(&recvaddr, 0, socksize); - - message = (char *)calloc(1, MAXBUFFERSIZE); - if (message == NULL) { -#ifdef DEBUG - fprintf(dbg, "calloc error\n"); - fflush(dbg); -#endif - exit(1); - } - - actual_size = recvfrom(statePtr->sock, message, buffer_size, 0, - (struct sockaddr *)&recvaddr, &socksize); - SetEvent(waitSockRead); - - if (actual_size < 0) { - if (WSAGetLastError() == WSAEMSGSIZE) { - actual_size = buffer_size; - } - } - - if (actual_size < 0) { -#ifdef DEBUG - fprintf(dbg, "UDP error - recvfrom %d\n", statePtr->sock); - fflush(dbg); -#endif - } else { - p = (PacketList *)calloc(1, sizeof(struct PacketList)); - 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; - } - -#ifdef DEBUG - fprintf(dbg, "Received %d bytes from %s:%d through %d\n", p->actual_size, p->r_host, p->r_port, statePtr->sock); - fwrite(p->message, 1, p->actual_size, dbg); - fflush(dbg); -#endif - } - - statePtr->packetNum--; - statePtr->doread = 1; -#ifdef DEBUG - fprintf(dbg, "packetNum is %d\n", statePtr->packetNum); - fflush(dbg); -#endif - 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); -#ifdef DEBUG - fprintf(dbg, "socket %d has data\n", statePtr->sock); - fflush(dbg); -#endif - } - } - } - - SetEvent(sockListLock); -} -#endif - -/* - *---------------------------------------------------------------------- - * udpOpen - opens a UDP socket and addds the file descriptor to the - * tcl interpreter - *---------------------------------------------------------------------- - */ -int udpOpen(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { - int sock; - char channelName[20]; - UdpState *statePtr; - char * result; - 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; -#ifdef WIN32 - UdpState *tmp; - static initd = 0; -#endif - - Tcl_ChannelType *Udp_ChannelType; - Udp_ChannelType = (Tcl_ChannelType *) ckalloc((unsigned) 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) { - localport = atoi(argv[1]); - } - - memset(channelName, 0, sizeof(channelName)); - -#ifdef SIPC_IPV6 - if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { -#else - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { -#endif - sprintf(errBuf,"%s","udp - socket"); -#ifdef DEBUG - fprintf(dbg, "UDP error - socket\n"); - fflush(dbg); -#endif - 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 = htons(localport); -#else - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0; - addr.sin_port = htons(localport); -#endif - if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) { - sprintf(errBuf,"%s","udp - bind"); -#ifdef DEBUG - fprintf(dbg, "UDP error - bind\n"); - fflush(dbg); -#endif - 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 = ntohs(sockaddr.sin6_port); -#else - localport = ntohs(sockaddr.sin_port); -#endif - } -#ifdef DEBUG - fprintf(dbg, "Open socket %d. Bind socket to port %d\n", sock, localport); - fflush(dbg); -#endif - - statePtr = (UdpState *) ckalloc((unsigned) 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; - } -#ifdef DEBUG - fprintf(dbg, "Append %d to sockList\n", statePtr->sock); - fflush(dbg); - for (tmp = sockList; tmp != NULL; tmp = tmp->next) { - fprintf(dbg, "%d --> ", tmp->sock); - fflush(dbg); - } - fprintf(dbg, "NULL\n"); - fflush(dbg); -#endif - SetEvent(sockListLock); - SetEvent(waitForSock); -#endif - return TCL_OK; -} - -#ifdef WIN32 - -/* - * InitSockets - */ -static int InitSockets() { - WSADATA wsaData; - WNDCLASS class; - HINSTANCE handle; - - /* - * Load the socket DLL and initialize the function table. - */ - - if (WSAStartup(0x0101, &wsaData)) - return 0; - - return 1; -} - -/* - * SocketThread - */ -static DWORD WINAPI SocketThread(LPVOID arg) { - fd_set readfds; //variable used for select - struct timeval timeout; - UdpState *statePtr; - int found; - int sockset; - - FD_ZERO(&readfds); - -#ifdef DEBUG - fprintf(dbg, "In socket thread\n"); - fflush(dbg); -#endif - while (1) { - FD_ZERO(&readfds); - timeout.tv_sec = 1; - timeout.tv_usec = 0; - //synchronized - WaitForSingleObject(sockListLock, INFINITE); - - //no socket, just wait, use event - if (sockList == NULL) { - SetEvent(sockListLock); -#ifdef DEBUG - fprintf(dbg, "Wait for adding socket\n"); - fflush(dbg); -#endif - WaitForSingleObject(waitForSock, INFINITE); - //synchronized - WaitForSingleObject(sockListLock, INFINITE); - } - - //set each socket for select - for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) { - FD_SET(statePtr->sock, &readfds); -#ifdef DEBUG - fprintf(dbg, "SET sock %d\n", statePtr->sock); - fflush(dbg); -#endif - } - - SetEvent(sockListLock); - -#ifdef DEBUG - fprintf(dbg, "Wait for select\n"); - fflush(dbg); -#endif - //block here - found = select(0, &readfds, NULL, NULL, &timeout); -#ifdef DEBUG - fprintf(dbg, "select end\n"); - fflush(dbg); -#endif - - if (found <= 0) { - //We closed the socket during select or time out - continue; - } - -#ifdef DEBUG - fprintf(dbg, "Packet comes in\n"); - fflush(dbg); -#endif - - WaitForSingleObject(sockListLock, INFINITE); - sockset = 0; - for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) { - if (FD_ISSET(statePtr->sock, &readfds)) { - statePtr->packetNum++; - sockset++; -#ifdef DEBUG - fprintf(dbg, "sock %d is set\n", statePtr->sock); - fflush(dbg); -#endif - break; - } - } - SetEvent(sockListLock); - - //wait for the socket data was read - if (sockset > 0) { -#ifdef DEBUG - fprintf(dbg, "Wait sock read\n"); - fflush(dbg); -#endif - //alert the thread to do event checking - Tcl_ThreadAlert(statePtr->threadId); - WaitForSingleObject(waitSockRead, INFINITE); -#ifdef DEBUG - fprintf(dbg, "Sock read finished\n"); - fflush(dbg); -#endif - } - } -} - -/* - * Udp_WinHasSockets -- - */ -int Udp_WinHasSockets(Tcl_Interp *interp) { - static int initialized = 0; /* 1 if the socket sys has been initialized. */ - static int hasSockets = 0; /* 1 if the system supports sockets. */ - HANDLE socketThread; - DWORD id; - - if (!initialized) { - OSVERSIONINFO info; - - initialized = 1; - - /* - * Find out if we're running on Win32s. - */ - - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&info); - - /* - * Check to see if Sockets are supported on this system. Since - * win32s panics if we call WSAStartup on a system that doesn't - * have winsock.dll, we need to look for it on the system first. - * If we find winsock, then load the library and initialize the - * stub table. - */ - - if ((info.dwPlatformId != VER_PLATFORM_WIN32s) - || (SearchPath(NULL, "WINSOCK", ".DLL", 0, NULL, NULL) != 0)) { - hasSockets = InitSockets(); - } - - /* - * Start the socketThread windows and set the thread priority of the - * socketThread as highest - */ - - sockList = NULL; - sockTail = NULL; - waitForSock = CreateEvent(NULL, FALSE, FALSE, NULL); - waitSockRead = CreateEvent(NULL, FALSE, FALSE, NULL); - sockListLock = CreateEvent(NULL, FALSE, TRUE, NULL); - - socketThread = CreateThread(NULL, 8000, SocketThread, NULL, 0, &id); - SetThreadPriority(socketThread, THREAD_PRIORITY_HIGHEST); - -#ifdef DEBUG - fprintf(dbg, "Initialize socket thread\n"); - fflush(dbg); -#endif - - if (socketThread == NULL) { -#ifdef DEBUG - fprintf(dbg, "Failed to create thread\n"); - fflush(dbg); -#endif - } - } - if (hasSockets) { - return TCL_OK; - } - if (interp != NULL) { - Tcl_AppendResult(interp, "sockets are not available on this system", - NULL); - } - return TCL_ERROR; -} - -#endif - -/* - * udpInit - */ -int Udp_Init(Tcl_Interp *interp) { -#ifdef DEBUG - dbg = fopen("udp.dbg", "wb"); -#endif - -#ifdef WIN32 - 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 TCL_OK; -} - -/* - * udpOutput-- - */ -static int udpOutput(ClientData instanceData, char *buf, int toWrite, int *errorCode) { - UdpState *statePtr = (UdpState *) instanceData; - int written; - int socksize; - struct hostent *name; -#ifdef SIPC_IPV6 - struct sockaddr_in6 sendaddr; - struct in6_addr inp; - int n, errnum; -#else - struct sockaddr_in sendaddr; - struct in_addr inp; -#endif - - *errorCode = 0; - errno = 0; - - if (toWrite > MAXBUFFERSIZE) { -#ifdef DEBUG - fprintf(dbg, "UDP error - MAXBUFFERSIZE"); - fflush(dbg); -#endif - return -1; - } - socksize = sizeof(sendaddr); - memset(&sendaddr, 0, socksize); - -#ifdef SIPC_IPV6 - n = inet_pton(AF_INET6, statePtr->remotehost, &sendaddr.sin6_addr); - if (n <= 0) { - name = getipnodebyname(statePtr->remotehost, AF_INET6, AI_DEFAULT, &errnum); -#else - sendaddr.sin_addr.s_addr = inet_addr(statePtr->remotehost); - if (sendaddr.sin_addr.s_addr == -1) { - name = gethostbyname(statePtr->remotehost); -#endif - if (name == NULL) { -#ifdef DEBUG - fprintf(dbg, "UDP error - gethostbyname"); - fflush(dbg); -#endif - return -1; - } -#ifdef SIPC_IPV6 - memcpy(&sendaddr.sin6_addr, name->h_addr, sizeof(sendaddr.sin6_addr)); - } - sendaddr.sin6_family = AF_INET6; - sendaddr.sin6_port = htons(statePtr->remoteport); -#else - memcpy(&sendaddr.sin_addr, name->h_addr, sizeof(sendaddr.sin_addr)); - } - sendaddr.sin_family = AF_INET; - sendaddr.sin_port = htons(statePtr->remoteport); -#endif - written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddr, socksize); - if (written < 0) { -#ifdef DEBUG - fprintf(dbg, "UDP error - sendto"); - fflush(dbg); -#endif - return -1; - } - -#ifdef DEBUG - fprintf(dbg, "Send %d to %s:%d through %d\n", written, statePtr->remotehost, statePtr->remoteport, statePtr->sock); - fflush(dbg); -#endif - - return written; -} - -/* - * udpInput - */ -static int udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode) { - UdpState *statePtr = (UdpState *) instanceData; - int bytesRead; - int actual_size, socksize, reply; - int buffer_size = MAXBUFFERSIZE; - int port; - char *remotehost; - struct hostent *name; -#ifdef SIPC_IPV6 - char number[128]; - struct sockaddr_in6 recvaddr; -#else - char number[32]; - struct sockaddr_in recvaddr; -#endif - int sock = statePtr->sock; - int i; -#ifdef WIN32 - PacketList *packets; -#endif - -#ifdef DEBUG - fprintf(dbg, "In udpInput\n"); - fflush(dbg); -#endif - - /* - * The caller of this function is looking for a stream oriented - * system, so it keeps calling the function until no bytes are - * returned, and then appends all the characters together. This - * is not what we want from UDP, so we fake it by returning a - * blank every other call. whenever the doread variable is 1 do - * a normal read, otherwise just return 0. - */ - if (statePtr->doread == 0) { - statePtr->doread = 1; /* next time we want to behave normally */ - *errorCode = EAGAIN; /* pretend that we would block */ -#ifdef DEBUG - fprintf(dbg, "Pretend we would block\n"); - fflush(dbg); -#endif - return 0; - } - - *errorCode = 0; - errno = 0; - - if (bufSize == 0) { - return 0; - } - -#ifdef WIN32 - packets = statePtr->packets; -#ifdef DEBUG - fprintf(dbg, "udp_recv\n"); - fflush(dbg); -#endif - if (packets == NULL) { -#ifdef DEBUG - fprintf(dbg, "packets is NULL\n"); - fflush(dbg); -#endif - return 0; - } - memcpy(buf, packets->message, packets->actual_size); - free((char *) packets->message); -#ifdef DEBUG - fprintf(dbg, "udp_recv message\n"); - fwrite(buf, 1, packets->actual_size, dbg); - fflush(dbg); -#endif - bufSize = packets->actual_size; - strcpy(statePtr->peerhost, packets->r_host); - statePtr->peerport = packets->r_port; - statePtr->packets = packets->next; - free((char *) packets); - bytesRead = bufSize; -#else - // else for Unix/Linux - socksize = sizeof(recvaddr); -#ifdef SIPC_IPV6 - memset(number, 0, 128); -#else - memset(number, 0, 32); -#endif - memset(&recvaddr, 0, socksize); - - bytesRead = recvfrom(sock, buf, buffer_size, 0, (struct sockaddr *)&recvaddr, &socksize); - if (bytesRead < 0) { -#ifdef DEBUG - fprintf(dbg, "UDP error - recvfrom %d\n", sock); - fflush(dbg); -#endif - *errorCode = errno; - return -1; - } - -#ifdef SIPC_IPV6 - remotehost = (char *)inet_ntop(AF_INET6, &recvaddr.sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost)); - port = ntohs(recvaddr.sin6_port); -#else - remotehost = (char *)inet_ntoa(recvaddr.sin_addr); - port = ntohs(recvaddr.sin_port); - strcpy(statePtr->peerhost, remotehost); -#endif - -#ifdef DEBUG - fprintf(dbg, "remotehost: %s\n", remotehost); - fflush(dbg); -#endif - statePtr->peerport = port; -#endif - - /* we don't want to return anything next time */ - if (bytesRead > 0) { buf[bytesRead] = '\0'; statePtr->doread = 0; } - -#ifdef DEBUG - fprintf(dbg, "udpInput end: %d, %s\n", bytesRead, buf); - fflush(dbg); -#endif - - if (bytesRead > -1) { - return bytesRead; - } - - *errorCode = errno; - return -1; -} - diff --git a/src/udp_tcl.h b/src/udp_tcl.h deleted file mode 100644 index eff1c86..0000000 --- a/src/udp_tcl.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef UDP_TCL_H -#define UDP_TCL_H -/* - *---------------------------------------------------------------------- - * UDP Extension for Tcl 8.4 - * - * Copyright 1999-2000 by Columbia University; all rights reserved - * - * Written by Xiaotao Wu - * Last modified: 11/03/2000 - *---------------------------------------------------------------------- - */ -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include "tcl.h" - -#ifdef WIN32 - -typedef u_short uint16_t; - -typedef struct { - Tcl_Event header; /* Information that is standard for */ - Tcl_Channel chan; /* Socket descriptor that is ready */ -} UdpEvent; - -typedef struct PacketList { - char *message; - int actual_size; - char r_host[256]; - int r_port; - struct PacketList *next; -} PacketList; - -#endif - -typedef struct UdpState { - Tcl_Channel channel; - int sock; - char remotehost[256]; /* send packets to */ - uint16_t remoteport; - char peerhost[256]; /* receive packets from */ - uint16_t peerport; - uint16_t localport; - int doread; -#ifdef WIN32 - HWND hwnd; - PacketList *packets; - PacketList *packetsTail; - int packetNum; - struct UdpState *next; - Tcl_ThreadId threadId; /* for Tcl_ThreadAlert */ -#endif -} UdpState; - -#endif