Tcl UDP

Check-in [565c05d10a]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Modifications to allow udp to compile under 8.7+
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA3-256: 565c05d10a3857c144c3d9bc09a6fe477131cbea99ccad028a5532499da39a74
User & Date: seandeelywoods 2018-10-01 23:14:39
Context
2018-10-01
23:14
Modifications to allow udp to compile under 8.7+ Leaf check-in: 565c05d10a user: seandeelywoods tags: trunk
2017-12-26
14:27
Store HTML docs in repo since generation at install time mandates availability of mpexpand check-in: d9c46224c6 user: apnadkarni tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/udp_tcl.c.

    84     84   
    85     85   FILE *dbg;
    86     86   
    87     87   #define MAXBUFFERSIZE 4096
    88     88   
    89     89   static char errBuf[256];
    90     90   
    91         -/*
    92         - * Channel handling procedures 
    93         - */
    94         -static Tcl_DriverOutputProc    udpOutput;
    95         -static Tcl_DriverInputProc     udpInput;
    96         -static Tcl_DriverCloseProc     udpClose;
    97         -static Tcl_DriverWatchProc     udpWatch;
    98         -static Tcl_DriverGetHandleProc udpGetHandle;
    99         -static Tcl_DriverSetOptionProc udpSetOption;
   100         -static Tcl_DriverGetOptionProc udpGetOption;
   101         -
   102     91   /*
   103     92    * Tcl command procedures
   104     93    */
   105     94   int Udp_CmdProc(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
   106     95   int udpOpen(ClientData , Tcl_Interp *, int , CONST84 char * []);
   107     96   int udpConf(ClientData , Tcl_Interp *, int , CONST84 char * []);
   108     97   int udpPeek(ClientData , Tcl_Interp *, int , CONST84 char * []);
................................................................................
   143    132   static HANDLE waitForSock;
   144    133   static HANDLE waitSockRead;
   145    134   static HANDLE sockListLock;
   146    135   static UdpState *sockList;
   147    136   
   148    137   #endif /* ! WIN32 */
   149    138   
   150         -/*
   151         - * This structure describes the channel type for accessing UDP.
   152         - */
   153         -static Tcl_ChannelType Udp_ChannelType = {
   154         -    "udp",                 /* Type name.                                    */
   155         -    NULL,                  /* Set blocking/nonblocking behaviour. NULL'able */
   156         -    udpClose,              /* Close channel, clean instance data            */
   157         -    udpInput,              /* Handle read request                           */
   158         -    udpOutput,             /* Handle write request                          */
   159         -    NULL,                  /* Move location of access point.      NULL'able */
   160         -    udpSetOption,          /* Set options.                        NULL'able */
   161         -    udpGetOption,          /* Get options.                        NULL'able */
   162         -    udpWatch,              /* Initialize notifier                           */
   163         -    udpGetHandle,          /* Get OS handle from the channel.               */
   164         -};
   165    139   
   166    140   /*
   167    141    * ----------------------------------------------------------------------
   168    142    * udpInit
   169    143    * ----------------------------------------------------------------------
   170    144    */
   171    145   int
................................................................................
   183    157   #ifdef WIN32
   184    158       if (Udp_WinHasSockets(interp) != TCL_OK) {
   185    159           return TCL_ERROR;
   186    160       }
   187    161       Tcl_CreateEventSource(UDP_SetupProc, UDP_CheckProc, NULL);
   188    162   #endif
   189    163   
   190         -    Tcl_CreateCommand(interp, "udp_open", udpOpen , 
          164  +    Tcl_CreateCommand(interp, "udp_open", udpOpen ,
          165  +                      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
          166  +    Tcl_CreateCommand(interp, "udp_conf", udpConf ,
   191    167                         (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
   192         -    Tcl_CreateCommand(interp, "udp_conf", udpConf , 
          168  +    Tcl_CreateCommand(interp, "udp_peek", udpPeek ,
   193    169                         (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
   194         -    Tcl_CreateCommand(interp, "udp_peek", udpPeek , 
   195         -                      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
   196         -    
          170  +
   197    171       r = Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
   198    172       return r;
   199    173   }
   200    174   
   201    175   int
   202    176   Udp_SafeInit(Tcl_Interp *interp)
   203    177   {
................................................................................
   237    211    * checkOption --
   238    212    *
   239    213    *  Checks if the specified option is part of the specified command line options.
   240    214    *  Returns 1 if option is present, otherwise 0.
   241    215    * ----------------------------------------------------------------------
   242    216    */
   243    217   static int
   244         -hasOption(int argc, CONST84 char * argv[],const char* option ) 
          218  +hasOption(int argc, CONST84 char * argv[],const char* option )
   245    219   {
   246    220   	int i;
   247    221   	for (i=0;i<argc;i++) {
   248    222   		if (strcmp(option, argv[i])==0) {
   249    223   			/* Option found. */
   250    224   			return 1;
   251    225   		}
   252    226   	}
   253    227   	return 0;
   254    228   }
   255    229   
   256         -/*
   257         - * ----------------------------------------------------------------------
   258         - * udpOpen --
   259         - *
   260         - *  opens a UDP socket and addds the file descriptor to the tcl
   261         - *  interpreter
   262         - * ----------------------------------------------------------------------
   263         - */
   264         -int
   265         -udpOpen(ClientData clientData, Tcl_Interp *interp,
   266         -        int argc, CONST84 char * argv[]) 
   267         -{
   268         -#ifdef WIN32
   269         -    SOCKET sock;
   270         -#else
   271         -    int sock;
   272         -#endif
   273         -    char channelName[20];
   274         -    UdpState *statePtr;
   275         -    uint16_t localport = 0;
   276         -    int reuse = 0;
   277         -	struct sockaddr_storage addr,sockaddr;
   278         -	socklen_t addr_len;
   279         -    unsigned long status = 1;
   280         -    socklen_t len;
   281         -	short ss_family = AF_INET; /* Default ipv4 */ 
   282         -	char errmsg[] = "upd_open [remoteport] [ipv6] [reuse]";
   283         -	int remaining_options = argc;
   284         -	
   285         -    if (argc >= 2) {		
   286         -		if (hasOption(argc,argv,"reuse")) {
   287         -           reuse = 1;
   288         -           remaining_options--;
   289         - 		}
   290         -
   291         -		if (hasOption(argc,argv,"ipv6")) {
   292         - 			ss_family = AF_INET6;
   293         - 			remaining_options--;			
   294         - 		}
   295         -		/* The remaining option must be the port (if specified) */
   296         -		if (remaining_options == 2) {
   297         -		   if (udpGetService(interp, argv[1], &localport) != TCL_OK) {
   298         -				Tcl_SetResult (interp, errmsg, NULL);
   299         -				return TCL_ERROR;
   300         -		   }
   301         -		}
   302         -    } 
   303         -    memset(channelName, 0, sizeof(channelName));
   304         -    
   305         -	sock = socket(ss_family, SOCK_DGRAM, 0);
   306         -    if (sock < 0) {
   307         -        snprintf(errBuf, 255, "failed to create socket");
   308         -        errBuf[255] = 0;
   309         -        UDPTRACE("%s\n", errBuf);
   310         -        Tcl_AppendResult(interp, errBuf, (char *)NULL);
   311         -        return TCL_ERROR;
   312         -    } 
   313         -
   314         -    /*
   315         -     * bug #1477669: avoid socket inheritence after exec
   316         -     */
   317         -
   318         -#if HAVE_FLAG_FD_CLOEXEC
   319         -    fcntl(sock, F_SETFD, FD_CLOEXEC);
   320         -#else
   321         -#ifdef WIN32
   322         -    if (SetHandleInformation((HANDLE)sock, HANDLE_FLAG_INHERIT, 0) == 0) {
   323         -        Tcl_AppendResult(interp, "failed to set close-on-exec bit", NULL);
   324         -        return TCL_ERROR;
   325         -    }
   326         -#endif /* WIN32 */
   327         -#endif /* HAVE_FLAG_FD_CLOEXEC */
   328         -
   329         -    if (reuse) {
   330         -        int one = 1;
   331         -#ifdef SO_REUSEPORT
   332         -        if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
   333         -                       (const char *)&one, sizeof(one)) < 0) {
   334         -#else
   335         -        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
   336         -                       (const char *)&one, sizeof(one)) < 0) {
   337         -#endif
   338         -             Tcl_SetObjResult(interp, 
   339         -                             ErrorToObj("error setting socket option"));
   340         -            closesocket(sock);
   341         -            return TCL_ERROR;
   342         -        }
   343         -    }
   344         -     
   345         -	memset(&addr, 0, sizeof(addr));
   346         -	if (ss_family == AF_INET6) {
   347         -		((struct sockaddr_in6 *) &addr)->sin6_family = AF_INET6;
   348         -		((struct sockaddr_in6 *) &addr)->sin6_port = localport;
   349         -		addr_len = sizeof(struct sockaddr_in6);
   350         -	} else {
   351         -		((struct sockaddr_in *) &addr)->sin_family = AF_INET;
   352         -		((struct sockaddr_in *) &addr)->sin_port = localport;
   353         -		addr_len = sizeof(struct sockaddr_in);
   354         -	}
   355         -	if ( bind(sock,(struct sockaddr *)&addr, addr_len) < 0) {
   356         -        Tcl_SetObjResult(interp, 
   357         -                         ErrorToObj("failed to bind socket to port"));
   358         -
   359         -        closesocket(sock);
   360         -        return TCL_ERROR;
   361         -    }
   362         -
   363         -    ioctlsocket(sock, FIONBIO, &status);
   364         -
   365         -    if (localport == 0) {
   366         -        len = sizeof(sockaddr);
   367         -		getsockname(sock, (struct sockaddr *)&sockaddr, &len);
   368         - 		if (ss_family == AF_INET6) {
   369         -			localport = ((struct sockaddr_in6 *) &sockaddr)->sin6_port;
   370         -		} else {
   371         -			localport = ((struct sockaddr_in *) &sockaddr)->sin_port;
   372         -		}
   373         -    }
   374         -    
   375         -    UDPTRACE("Open socket %d. Bind socket to port %d\n", 
   376         -             sock, ntohs(localport));
   377         -
   378         -    statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState));
   379         -    memset(statePtr, 0, sizeof(UdpState));
   380         -    statePtr->sock = sock;
   381         -    sprintf(channelName, "sock" SOCKET_PRINTF_FMT, statePtr->sock);
   382         -    statePtr->channel = Tcl_CreateChannel(&Udp_ChannelType, channelName,
   383         -                                          (ClientData) statePtr,
   384         -                                          (TCL_READABLE | TCL_WRITABLE | TCL_MODE_NONBLOCKING));
   385         -    statePtr->doread = 1;
   386         -    statePtr->multicast = 0;
   387         -    statePtr->groupsObj = Tcl_NewListObj(0, NULL);
   388         -    Tcl_IncrRefCount(statePtr->groupsObj);
   389         -    statePtr->localport = localport;
   390         -	statePtr->ss_family = ss_family;
   391         -    Tcl_RegisterChannel(interp, statePtr->channel);
   392         -#ifdef WIN32
   393         -    statePtr->threadId = Tcl_GetCurrentThread();    
   394         -    statePtr->packetNum = 0;
   395         -    statePtr->next = NULL;
   396         -    statePtr->packets = NULL;
   397         -    statePtr->packetsTail = NULL;
   398         -#endif
   399         -    /* Tcl_SetChannelOption(interp, statePtr->channel, "-blocking", "0"); */
   400         -    Tcl_AppendResult(interp, channelName, (char *)NULL);
   401         -#ifdef WIN32
   402         -    WaitForSingleObject(sockListLock, INFINITE);
   403         -    statePtr->next = sockList;
   404         -    sockList = statePtr;
   405         -
   406         -    UDPTRACE("Added %d to sockList\n", statePtr->sock);
   407         -    SetEvent(sockListLock);
   408         -    SetEvent(waitForSock);
   409         -#endif
   410         -    return TCL_OK;
   411         -}
   412    230   
   413    231   /*
   414    232   * ----------------------------------------------------------------------
   415    233   * udpConf --
   416    234   * ----------------------------------------------------------------------
   417    235   */
   418    236   int
   419    237   udpConf(ClientData clientData, Tcl_Interp *interp,
   420         -		int argc, CONST84 char * argv[]) 
          238  +		int argc, CONST84 char * argv[])
   421    239   {
   422    240   	Tcl_Channel chan;
   423    241   	char remoteOptions[255];
   424    242   	UdpState *statePtr = NULL;
   425    243   	int r = TCL_ERROR;
   426    244   	Tcl_DString ds;
   427         -	char errmsg[] = 
          245  +	char errmsg[] =
   428    246   		"udp_conf fileId [-mcastadd] [-mcastdrop] groupaddr | "
   429    247   #ifdef WIN32
   430    248   		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif_index\" | "
   431    249   #else
   432    250   		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif\" | "
   433    251   #endif
   434    252   		"udp_conf fileId remotehost remoteport | "
   435    253   		"udp_conf fileId -mcastif ipaddr | "
   436    254   		"udp_conf fileId [-myport] [-remote] [-peer] [-mcastgroups] [-mcastloop] [-broadcast] [-ttl]";
   437         -	
          255  +
   438    256   	if (argc >= 2) {
   439    257   		chan = Tcl_GetChannel(interp, (char *)argv[1], NULL);
   440    258   		if (chan != (Tcl_Channel) NULL) {
   441    259   			statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan);
   442    260   		}
   443    261   	}
   444         -	
          262  +
   445    263   	if (argc == 3 && statePtr != NULL) {
   446    264   		Tcl_DStringInit(&ds);
   447    265   		r = Tcl_GetChannelOption(interp, statePtr->channel, argv[2], &ds);
   448    266   		if (r == TCL_OK) {
   449    267   			Tcl_DStringResult(interp, &ds);
   450    268   		}
   451         -		Tcl_DStringFree(&ds);	     
          269  +		Tcl_DStringFree(&ds);
   452    270   	}
   453         -	
          271  +
   454    272   	if (argc == 4 && statePtr != NULL) {
   455    273   		if (hasOption(argc,argv,"-mcastloop") ||
   456    274   			hasOption(argc,argv,"-broadcast") ||
   457    275   			hasOption(argc,argv,"-mcastadd") ||
   458    276   			hasOption(argc,argv,"-mcastdrop") ||
   459    277   			hasOption(argc,argv,"-mcastif") ||
   460         -			hasOption(argc,argv,"-ttl")) { 
          278  +			hasOption(argc,argv,"-ttl")) {
   461    279   			r = Tcl_SetChannelOption(interp, statePtr->channel, argv[2], argv[3]);
   462    280   		} else {
   463    281   			sprintf(remoteOptions, "%s %s",argv[2],argv[3] );
   464    282   			r = Tcl_SetChannelOption(interp, statePtr->channel, "-remote", remoteOptions);
   465    283   		}
   466    284   	}
   467         -	
          285  +
   468    286   	if (r != TCL_OK) {
   469    287   		Tcl_SetResult (interp, errmsg, NULL);
   470    288   	}
   471    289   	return r;
   472    290   }
   473    291   
   474    292   /*
................................................................................
   486    304       int actual_size;
   487    305       socklen_t socksize;
   488    306       char message[17];
   489    307   	struct sockaddr_storage recvaddr;
   490    308   
   491    309       Tcl_Channel chan;
   492    310       UdpState *statePtr;
   493         -    
          311  +
   494    312       if (argc < 2) {
   495    313   	Tcl_WrongNumArgs(interp, 0, NULL, "udp_peek sock ?buffersize?");
   496    314           return TCL_ERROR;
   497    315       }
   498    316       chan = Tcl_GetChannel(interp, (char *)argv[1], NULL);
   499    317       if (chan == (Tcl_Channel) NULL) {
   500    318           return TCL_ERROR;
   501    319       }
   502    320       statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan);
   503         -   
          321  +
   504    322       if (argc > 2) {
   505    323           buffer_size = atoi(argv[2]);
   506    324           if (buffer_size > 16) buffer_size = 16;
   507    325       }
   508         -    
          326  +
   509    327       memset(message, 0 , sizeof(message));
   510    328       actual_size = recvfrom(statePtr->sock, message, buffer_size, MSG_PEEK,
   511    329                              (struct sockaddr *)&recvaddr, &socksize);
   512         -    
          330  +
   513    331       if (actual_size < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
   514    332           Tcl_SetObjResult(interp,  ErrorToObj("udppeek error"));
   515    333           return TCL_ERROR;
   516    334       }
   517         -    
          335  +
   518    336   	if (statePtr->ss_family == AF_INET6) {
   519    337   		inet_ntop(AF_INET6, &((struct sockaddr_in6*)&recvaddr)->sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
   520    338   		statePtr->peerport = ntohs(((struct sockaddr_in6*)&recvaddr)->sin6_port);
   521    339   	} else {
   522    340   		inet_ntop(AF_INET, &((struct sockaddr_in*)&recvaddr)->sin_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
   523    341   		statePtr->peerport = ntohs(((struct sockaddr_in*)&recvaddr)->sin_port);
   524    342   	}
................................................................................
   543    361    * ----------------------------------------------------------------------
   544    362    */
   545    363   int
   546    364   UdpEventProc(Tcl_Event *evPtr, int flags)
   547    365   {
   548    366       UdpEvent *eventPtr = (UdpEvent *) evPtr;
   549    367       int mask = 0;
   550         -    
          368  +
   551    369       mask |= TCL_READABLE;
   552    370       UDPTRACE("UdpEventProc\n");
   553    371       Tcl_NotifyChannel(eventPtr->chan, mask);
   554    372       return 1;
   555    373   }
   556    374   
   557    375   /*
   558    376    * ----------------------------------------------------------------------
   559    377    * UDP_SetupProc - called in Tcl_SetEventSource to do the setup step
   560    378    * ----------------------------------------------------------------------
   561    379    */
   562         -static void 
   563         -UDP_SetupProc(ClientData data, int flags) 
          380  +static void
          381  +UDP_SetupProc(ClientData data, int flags)
   564    382   {
   565    383       UdpState *statePtr;
   566    384       Tcl_Time blockTime = { 0, 0 };
   567         -    
          385  +
   568    386       /* UDPTRACE("setupProc\n"); */
   569         -    
          387  +
   570    388       if (!(flags & TCL_FILE_EVENTS)) {
   571    389           return;
   572    390       }
   573         -    
          391  +
   574    392       WaitForSingleObject(sockListLock, INFINITE);
   575    393       for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) {
   576    394           if (statePtr->packetNum > 0) {
   577    395               UDPTRACE("UDP_SetupProc\n");
   578    396               Tcl_SetMaxBlockTime(&blockTime);
   579    397               break;
   580    398           }
................................................................................
   583    401   }
   584    402   
   585    403   /*
   586    404    * ----------------------------------------------------------------------
   587    405    * UDP_CheckProc --
   588    406    * ----------------------------------------------------------------------
   589    407    */
   590         -void 
   591         -UDP_CheckProc(ClientData data, int flags) 
          408  +void
          409  +UDP_CheckProc(ClientData data, int flags)
   592    410   {
   593    411       UdpState *statePtr;
   594    412       UdpEvent *evPtr;
   595    413       int actual_size;
   596    414       socklen_t socksize;
   597    415       int buffer_size = MAXBUFFERSIZE;
   598    416       char *message;
................................................................................
   602    420   	char hostaddr[256];
   603    421   	char* portaddr;
   604    422   	char remoteaddr[256];
   605    423     	int remoteaddrlen = sizeof(remoteaddr);
   606    424   	memset(hostaddr, 0 , sizeof(hostaddr));
   607    425   	memset(remoteaddr,0,sizeof(remoteaddr));
   608    426   #endif /*  WIN32 */
   609         -	
          427  +
   610    428       /* UDPTRACE("checkProc\n"); */
   611         -    
          429  +
   612    430       /* synchronized */
   613    431       WaitForSingleObject(sockListLock, INFINITE);
   614         -    
          432  +
   615    433       for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) {
   616    434           if (statePtr->packetNum > 0) {
   617    435               UDPTRACE("UDP_CheckProc\n");
   618    436               /* Read the data from socket and put it into statePtr */
   619    437               socksize = sizeof(recvaddr);
   620    438               memset(&recvaddr, 0, socksize);
   621         -              
          439  +
   622    440               message = (char *)ckalloc(MAXBUFFERSIZE);
   623    441               if (message == NULL) {
   624    442                   UDPTRACE("ckalloc error\n");
   625    443                   exit(1);
   626    444               }
   627    445               memset(message, 0, MAXBUFFERSIZE);
   628         -            
          446  +
   629    447               actual_size = recvfrom(statePtr->sock, message, buffer_size, 0,
   630    448                                      (struct sockaddr *)&recvaddr, &socksize);
   631    449               SetEvent(waitSockRead);
   632         -            
          450  +
   633    451               if (actual_size < 0) {
   634    452                   UDPTRACE("UDP error - recvfrom %d\n", statePtr->sock);
   635    453                   ckfree(message);
   636    454               } else {
   637    455                   p = (PacketList *)ckalloc(sizeof(struct PacketList));
   638    456                   p->message = message;
   639    457                   p->actual_size = actual_size;
   640    458   #ifdef WIN32
   641         -				/* 
          459  +				/*
   642    460   				 * In windows, do not use getnameinfo() since this function does
   643    461   				 * not work correctly in case of multithreaded. Also inet_ntop() is
   644    462   				 * not available in older windows versions.
   645    463   				 */
   646    464   				if (WSAAddressToStringA((struct sockaddr *)&recvaddr,socksize,
   647    465   					NULL,remoteaddr,&remoteaddrlen)==0) {
   648         -					/* 
   649         -					 * We now have an address in the format of <ip address>:<port> 
          466  +					/*
          467  +					 * We now have an address in the format of <ip address>:<port>
   650    468   					 * Search backwards for the last ':'
   651    469   					 */
   652    470   					portaddr = strrchr(remoteaddr,':') + 1;
   653    471   					strncpy(hostaddr,remoteaddr,strlen(remoteaddr)-strlen(portaddr)-1);
   654    472   					statePtr->peerport = atoi(portaddr);
   655    473   					p->r_port = statePtr->peerport;
   656    474   					strcpy(statePtr->peerhost,hostaddr);
................................................................................
   657    475   					strcpy(p->r_host,hostaddr);
   658    476   				}
   659    477   #else
   660    478   				if (statePtr->ss_family == AF_INET ) {
   661    479   					inet_ntop(AF_INET, ((struct sockaddr_in*)&recvaddr)->sin_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
   662    480   					inet_ntop(AF_INET, ((struct sockaddr_in*)&recvaddr)->sin_addr, p->r_host, sizeof(p->r_host) );
   663    481   	               	p->r_port = ntohs(((struct sockaddr_in*)&recvaddr)->sin_port);
   664         -                	statePtr->peerport = ntohs(((struct sockaddr_in*)&recvaddr)->sin_port);                					
   665         -				} else {					
          482  +                	statePtr->peerport = ntohs(((struct sockaddr_in*)&recvaddr)->sin_port);
          483  +				} else {
   666    484   					inet_ntop(AF_INET6, ((struct sockaddr_in6*)&recvaddr)->sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
   667    485   					inet_ntop(AF_INET6, ((struct sockaddr_in6*)&recvaddr)->sin6_addr, p->r_host, sizeof(p->r_host) );
   668    486     				    p->r_port = ntohs(((struct sockaddr_in6*)&recvaddr)->sin6_port);
   669    487   				    statePtr->peerport = ntohs(((struct sockaddr_in6*)&recvaddr)->sin6_port);
   670    488   				}
   671    489   #endif /*  WIN32 */
   672    490   
   673    491                   p->next = NULL;
   674         -                 
          492  +
   675    493                   if (statePtr->packets == NULL) {
   676    494                       statePtr->packets = p;
   677    495                       statePtr->packetsTail = p;
   678    496                   } else {
   679    497                       statePtr->packetsTail->next = p;
   680    498                       statePtr->packetsTail = p;
   681    499                   }
   682         -                
          500  +
   683    501                   UDPTRACE("Received %d bytes from %s:%d through %d\n",
   684    502                            p->actual_size, p->r_host, p->r_port, statePtr->sock);
   685    503                   UDPTRACE("%s\n", p->message);
   686    504               }
   687         -            
          505  +
   688    506               statePtr->packetNum--;
   689    507               statePtr->doread = 1;
   690    508               UDPTRACE("packetNum is %d\n", statePtr->packetNum);
   691         -            
          509  +
   692    510               if (actual_size >= 0) {
   693    511                   evPtr = (UdpEvent *) ckalloc(sizeof(UdpEvent));
   694    512                   evPtr->header.proc = UdpEventProc;
   695    513                   evPtr->chan = statePtr->channel;
   696    514                   Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
   697    515                   UDPTRACE("socket %d has data\n", statePtr->sock);
   698    516               }
   699    517           }
   700    518       }
   701         -    
          519  +
   702    520       SetEvent(sockListLock);
   703    521   }
   704    522   
   705    523   /*
   706    524    * ----------------------------------------------------------------------
   707    525    * InitSockets
   708    526    * ----------------------------------------------------------------------
   709    527    */
   710    528   static int
   711         -InitSockets() 
          529  +InitSockets()
   712    530   {
   713    531       WSADATA wsaData;
   714    532   
   715    533       /*
   716    534        * Load the socket DLL and initialize the function table.
   717    535        */
   718         -    
          536  +
   719    537       if (WSAStartup(0x0101, &wsaData))
   720    538           return 0;
   721         -    
          539  +
   722    540       return 1;
   723    541   }
   724    542   
   725    543   /*
   726    544    * ----------------------------------------------------------------------
   727    545    * SocketThread
   728    546    * ----------------------------------------------------------------------
   729    547    */
   730    548   static DWORD WINAPI
   731         -SocketThread(LPVOID arg) 
          549  +SocketThread(LPVOID arg)
   732    550   {
   733    551       fd_set readfds; /* variable used for select */
   734    552       struct timeval timeout;
   735    553       UdpState *statePtr;
   736    554       int found;
   737    555       int sockset;
   738         -    
          556  +
   739    557       FD_ZERO(&readfds);
   740         -    
          558  +
   741    559       UDPTRACE("In socket thread\n");
   742         -    
          560  +
   743    561       while (1) {
   744    562           FD_ZERO(&readfds);
   745    563           timeout.tv_sec  = 1;
   746    564           timeout.tv_usec = 0;
   747    565           /* synchronized */
   748    566           WaitForSingleObject(sockListLock, INFINITE);
   749         -        
          567  +
   750    568           /* no socket, just wait, use event */
   751    569           if (sockList == NULL) {
   752    570               SetEvent(sockListLock);
   753    571               UDPTRACE("Wait for adding socket\n");
   754    572               WaitForSingleObject(waitForSock, INFINITE);
   755    573               /* synchronized */
   756    574               WaitForSingleObject(sockListLock, INFINITE);
   757    575           }
   758         -        
          576  +
   759    577           /* set each socket for select */
   760    578           for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) {
   761    579               FD_SET((unsigned int)statePtr->sock, &readfds);
   762    580               UDPTRACE("SET sock %d\n", statePtr->sock);
   763    581           }
   764         -        
          582  +
   765    583           SetEvent(sockListLock);
   766    584           UDPTRACE("Wait for select\n");
   767    585           /* block here */
   768    586           found = select(0, &readfds, NULL, NULL, &timeout);
   769    587           UDPTRACE("select end\n");
   770         -        
          588  +
   771    589           if (found <= 0) {
   772    590               /* We closed the socket during select or time out */
   773    591               continue;
   774    592           }
   775         -        
          593  +
   776    594           UDPTRACE("Packet comes in\n");
   777         -        
          595  +
   778    596           WaitForSingleObject(sockListLock, INFINITE);
   779    597           sockset = 0;
   780    598           for (statePtr = sockList; statePtr != NULL; statePtr=statePtr->next) {
   781    599               if (FD_ISSET(statePtr->sock, &readfds)) {
   782    600                   statePtr->packetNum++;
   783    601                   sockset++;
   784         -                UDPTRACE("sock %d is set\n", statePtr->sock); 
          602  +                UDPTRACE("sock %d is set\n", statePtr->sock);
   785    603                   break;
   786    604               }
   787    605           }
   788    606           SetEvent(sockListLock);
   789         -        
          607  +
   790    608           /* wait for the socket data was read */
   791    609           if (sockset > 0) {
   792    610               UDPTRACE( "Wait sock read\n");
   793    611               /* alert the thread to do event checking */
   794    612               Tcl_ThreadAlert(statePtr->threadId);
   795    613               WaitForSingleObject(waitSockRead, INFINITE);
   796    614               UDPTRACE("Sock read finished\n");
................................................................................
   806    624   int
   807    625   Udp_WinHasSockets(Tcl_Interp *interp)
   808    626   {
   809    627       static int initialized = 0; /* 1 if the socket sys has been initialized. */
   810    628       static int hasSockets = 0;  /* 1 if the system supports sockets. */
   811    629       HANDLE socketThread;
   812    630       DWORD id;
   813         -    
          631  +
   814    632       if (!initialized) {
   815    633           initialized = 1;
   816         -        
          634  +
   817    635           /* Load the library and initialize the stub table. */
   818    636           hasSockets = InitSockets();
   819         -        
          637  +
   820    638           /*
   821    639            * Start the socketThread window and set the thread priority of the
   822    640            * socketThread as highest
   823    641            */
   824         -        
          642  +
   825    643           sockList = NULL;
   826    644           waitForSock = CreateEvent(NULL, FALSE, FALSE, NULL);
   827    645           waitSockRead = CreateEvent(NULL, FALSE, FALSE, NULL);
   828    646           sockListLock = CreateEvent(NULL, FALSE, TRUE, NULL);
   829         -        
          647  +
   830    648           socketThread = CreateThread(NULL, 8000, SocketThread, NULL, 0, &id);
   831         -        SetThreadPriority(socketThread, THREAD_PRIORITY_HIGHEST); 
   832         -        
          649  +        SetThreadPriority(socketThread, THREAD_PRIORITY_HIGHEST);
          650  +
   833    651           UDPTRACE("Initialize socket thread\n");
   834    652   
   835    653           if (socketThread == NULL) {
   836    654               UDPTRACE("Failed to create thread\n");
   837    655           }
   838    656       }
   839    657       if (hasSockets) {
................................................................................
   843    661           Tcl_AppendResult(interp, "sockets are not available on this system",
   844    662                            NULL);
   845    663       }
   846    664       return TCL_ERROR;
   847    665   }
   848    666   
   849    667   #endif /* ! WIN32 */
          668  +
          669  +
          670  +
          671  +/*
          672  + * Channel handling procedures
          673  + */
          674  +
          675  +
   850    676   
   851    677   /*
   852    678    * ----------------------------------------------------------------------
   853    679    * udpClose --
   854    680    *  Called from the channel driver code to cleanup and close
   855    681    *  the socket.
   856    682    *
................................................................................
   858    684    *  0 if successful, the value of errno if failed.
   859    685    *
   860    686    * Side effects:
   861    687    *  The socket is closed.
   862    688    *
   863    689    * ----------------------------------------------------------------------
   864    690    */
   865         -static int 
   866         -udpClose(ClientData instanceData, Tcl_Interp *interp)
          691  +static int udpClose(
          692  +ClientData instanceData, Tcl_Interp *interp
          693  +)
   867    694   {
   868    695   #ifdef _WIN32
   869    696       SOCKET sock;
   870    697   #else
   871    698       int sock;
   872    699   #endif
   873    700       int errorCode = 0;
   874    701       int objc;
   875    702       Tcl_Obj **objv;
   876    703       UdpState *statePtr = (UdpState *) instanceData;
   877    704   #ifdef WIN32
   878    705       UdpState *tmp, *p;
   879         -    
          706  +
   880    707       WaitForSingleObject(sockListLock, INFINITE);
   881    708   #endif /* ! WIN32 */
   882         -    
          709  +
   883    710       sock = statePtr->sock;
   884         -	
          711  +
   885    712   #ifdef WIN32
   886         -	
          713  +
   887    714       /* remove the statePtr from the list */
   888    715       for (tmp = p = sockList; p != NULL; tmp = p, p = p->next) {
   889    716   		if (p->sock == sock) {
   890    717               UDPTRACE("Remove %d from the list\n", p->sock);
   891    718   			if (p == sockList) {
   892    719   				sockList = sockList->next;
   893    720   			} else {
   894    721   				tmp->next = p->next;
   895    722   			}
   896    723   		}
   897    724       }
   898         -	
          725  +
   899    726   #endif /* ! WIN32 */
   900         -	
          727  +
   901    728       /*
   902    729   	* If there are multicast groups added they should be dropped.
   903    730   	*/
   904    731       if (statePtr->groupsObj) {
   905    732   		int n = 0;
   906    733   		Tcl_Obj *dupGroupList = Tcl_DuplicateObj(statePtr->groupsObj);
   907    734   		Tcl_IncrRefCount(dupGroupList);
   908    735   		Tcl_ListObjGetElements(interp, dupGroupList, &objc, &objv);
   909    736   		for (n = 0; n < objc; n++) {
   910    737   			if (statePtr->ss_family==AF_INET) {
   911         -				UdpMulticast(statePtr, interp, 
          738  +				UdpMulticast(statePtr, interp,
   912    739   					Tcl_GetString(objv[n]), IP_DROP_MEMBERSHIP);
   913    740   			} else {
   914         -				UdpMulticast(statePtr, interp, 
          741  +				UdpMulticast(statePtr, interp,
   915    742   					Tcl_GetString(objv[n]), IPV6_LEAVE_GROUP);
   916    743   			}
   917    744   		}
   918    745   		Tcl_DecrRefCount(dupGroupList);
   919    746   		Tcl_DecrRefCount(statePtr->groupsObj);
   920    747       }
   921         -    
          748  +
   922    749       /* No - doing this causes a infinite recursion. Let Tcl handle this.
   923    750   	*   Tcl_UnregisterChannel(interp, statePtr->channel);
   924    751   	*/
   925    752       if (closesocket(sock) < 0) {
   926    753           errorCode = errno;
   927    754       }
   928    755       ckfree((char *) statePtr);
................................................................................
   932    759   #else
   933    760           sprintf(errBuf, "udp_close: " SOCKET_PRINTF_FMT ", error: %d\n", sock, WSAGetLastError());
   934    761   #endif
   935    762           UDPTRACE("UDP error - close %d", sock);
   936    763       } else {
   937    764           UDPTRACE("Close socket %d\n", sock);
   938    765       }
   939         -    
          766  +
   940    767   #ifdef WIN32
   941    768       SetEvent(sockListLock);
   942    769   #endif
   943         -    
          770  +
   944    771       return errorCode;
   945    772   }
   946    773   
   947    774   /*
   948    775    * ----------------------------------------------------------------------
   949    776    * udpWatch --
   950    777    * ----------------------------------------------------------------------
   951    778    */
   952         -static void 
   953         -udpWatch(ClientData instanceData, int mask)
          779  +static int udpWatch(
          780  +ClientData instanceData, int mask
          781  +)
   954    782   {
   955    783   #ifndef WIN32
   956    784       UdpState *fsPtr = (UdpState *) instanceData;
   957    785       if (mask) {
   958    786           UDPTRACE("Tcl_CreateFileHandler\n");
   959    787           Tcl_CreateFileHandler(fsPtr->sock, mask,
   960    788                                 (Tcl_FileProc *) Tcl_NotifyChannel,
................................................................................
   974    802    * Results:
   975    803    *   Puts the socket into handlePtr and returns TCL_OK;
   976    804    *
   977    805    * Side Effects:
   978    806    *   None
   979    807    * ----------------------------------------------------------------------
   980    808    */
   981         -static int
   982         -udpGetHandle(ClientData instanceData, int direction, ClientData *handlePtr)
          809  +static int udpGetHandle(
          810  +ClientData instanceData, int direction, ClientData *handlePtr
          811  +)
   983    812   {
   984    813       UdpState *statePtr = (UdpState *) instanceData;
   985    814       UDPTRACE("udpGetHandle %ld\n", (long)statePtr->sock);
   986    815   #ifndef WIN32
   987    816       *handlePtr = (ClientData) (intptr_t) statePtr->sock;
   988    817   #else
   989    818       *handlePtr = (ClientData) statePtr->sock;
................................................................................
   992    821   }
   993    822   
   994    823   /*
   995    824    * ----------------------------------------------------------------------
   996    825    * udpOutput--
   997    826    * ----------------------------------------------------------------------
   998    827    */
   999         -static int
  1000         -udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCode)
          828  +static int udpOutput(
          829  +ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCode
          830  +)
  1001    831   {
  1002    832   	UdpState *statePtr = (UdpState *) instanceData;
  1003    833       int written;
  1004    834       int socksize;
  1005    835       struct hostent *name;
  1006    836       struct sockaddr_in sendaddrv4;
  1007    837       struct sockaddr_in6 sendaddrv6;
  1008    838   	struct addrinfo hints, *result;
  1009    839   
  1010    840       if (toWrite > MAXBUFFERSIZE) {
  1011    841           UDPTRACE("UDP error - MAXBUFFERSIZE");
  1012    842           return -1;
  1013    843       }
  1014         - 
          844  +
  1015    845    	if (statePtr->ss_family == AF_INET6) {
  1016    846   		socksize = sizeof(sendaddrv6);
  1017    847   		memset(&sendaddrv6, 0, socksize);
  1018    848   		memset(&hints, 0, sizeof(struct addrinfo));
  1019    849   		hints.ai_family = AF_INET6;
  1020    850   		hints.ai_socktype = SOCK_DGRAM;
  1021    851   		hints.ai_protocol = IPPROTO_UDP;
................................................................................
  1084    914   }
  1085    915   
  1086    916   /*
  1087    917    * ----------------------------------------------------------------------
  1088    918    * udpInput
  1089    919    * ----------------------------------------------------------------------
  1090    920    */
  1091         -static int 
  1092         -udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode) 
          921  +static int udpInput(
          922  +ClientData instanceData, char *buf, int bufSize, int *errorCode
          923  +)
  1093    924   {
  1094    925       UdpState *statePtr = (UdpState *) instanceData;
  1095    926       int bytesRead;
  1096    927   
  1097    928   #ifdef WIN32
  1098    929       PacketList *packets;
  1099    930   #else /* ! WIN32 */
  1100    931       socklen_t socksize;
  1101    932       int buffer_size = MAXBUFFERSIZE;
  1102    933       int sock = statePtr->sock;
  1103    934   	struct sockaddr_storage recvaddr;
  1104    935   #endif /* ! WIN32 */
  1105         -    
          936  +
  1106    937       UDPTRACE("In udpInput\n");
  1107         -    
          938  +
  1108    939       /*
  1109    940        * The caller of this function is looking for a stream oriented
  1110    941        * system, so it keeps calling the function until no bytes are
  1111    942        * returned, and then appends all the characters together.  This
  1112    943        * is not what we want from UDP, so we fake it by returning a
  1113    944        * blank every other call.  whenever the doread variable is 1 do
  1114    945        * a normal read, otherwise just return -1 to indicate that we want
................................................................................
  1116    947        */
  1117    948       if (statePtr->doread == 0) {
  1118    949           statePtr->doread = 1;  /* next time we want to behave normally */
  1119    950           *errorCode = EAGAIN;   /* pretend that we would block */
  1120    951           UDPTRACE("Pretend we would block\n");
  1121    952           return -1;
  1122    953       }
  1123         -    
          954  +
  1124    955       *errorCode = 0;
  1125    956       errno = 0;
  1126         -    
          957  +
  1127    958       if (bufSize == 0) {
  1128    959           return 0;
  1129    960       }
  1130         -    
          961  +
  1131    962   #ifdef WIN32
  1132    963       packets = statePtr->packets;
  1133    964       UDPTRACE("udp_recv\n");
  1134    965   
  1135    966       if (packets == NULL) {
  1136    967           UDPTRACE("packets is NULL\n");
  1137    968           *errorCode = EAGAIN;
................................................................................
  1145    976       statePtr->peerport = packets->r_port;
  1146    977       statePtr->packets = packets->next;
  1147    978       ckfree((char *) packets);
  1148    979       bytesRead = bufSize;
  1149    980   #else /* ! WIN32 */
  1150    981       socksize = sizeof(recvaddr);
  1151    982       memset(&recvaddr, 0, socksize);
  1152         -   
          983  +
  1153    984       bytesRead = recvfrom(sock, buf, buffer_size, 0,
  1154    985                            (struct sockaddr *)&recvaddr, &socksize);
  1155    986       if (bytesRead < 0) {
  1156    987           UDPTRACE("UDP error - recvfrom %d\n", sock);
  1157    988           *errorCode = errno;
  1158    989           return -1;
  1159    990       }
  1160         -    
          991  +
  1161    992   	if (statePtr->ss_family == AF_INET6) {
  1162    993   		inet_ntop(AF_INET6, &((struct sockaddr_in6*)&recvaddr)->sin6_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
  1163    994   		statePtr->peerport = ntohs(((struct sockaddr_in6*)&recvaddr)->sin6_port);
  1164    995   	} else {
  1165    996   		inet_ntop(AF_INET, &((struct sockaddr_in*)&recvaddr)->sin_addr, statePtr->peerhost, sizeof(statePtr->peerhost) );
  1166    997   		statePtr->peerport = ntohs(((struct sockaddr_in*)&recvaddr)->sin_port);
  1167    998   	}
  1168         - 	    
          999  +
  1169   1000       UDPTRACE("remotehost: %s:%d\n", statePtr->peerhost, statePtr->peerport);
  1170   1001   #endif /* ! WIN32 */
  1171         -    
         1002  +
  1172   1003       /* we don't want to return anything next time */
  1173   1004       if (bytesRead > 0) {
  1174   1005           buf[bytesRead] = '\0';
  1175   1006           statePtr->doread = 0;
  1176   1007       }
  1177         -    
         1008  +
  1178   1009       UDPTRACE("udpInput end: %d, %s\n", bytesRead, buf);
  1179   1010   
  1180   1011       if (bytesRead == 0) {
  1181   1012           *errorCode = EAGAIN;
  1182   1013           return -1;
  1183   1014       }
  1184   1015       if (bytesRead == 0) {
  1185   1016           *errorCode = EAGAIN;
  1186   1017           return -1;
  1187   1018       }
  1188   1019       if (bytesRead > -1) {
  1189   1020           return bytesRead;
  1190   1021       }
  1191         -    
         1022  +
  1192   1023       *errorCode = errno;
  1193   1024       return -1;
  1194   1025   }
  1195   1026   
  1196         -/* ---------------------------------------------------------------------- 
         1027  +
         1028  +/* ----------------------------------------------------------------------
  1197   1029    *
  1198   1030    * LSearch --
  1199   1031    *
  1200   1032    * 	Find a string item in a list and return the index of -1.
  1201   1033    */
  1202   1034   
  1203   1035   static int
................................................................................
  1215   1047   }
  1216   1048   
  1217   1049   /*
  1218   1050    * ----------------------------------------------------------------------
  1219   1051    *
  1220   1052    * UdpMulticast --
  1221   1053    *
  1222         - *	Action should be IP_ADD_MEMBERSHIP | IPV6_JOIN_GROUP 
         1054  + *	Action should be IP_ADD_MEMBERSHIP | IPV6_JOIN_GROUP
  1223   1055    *  or IP_DROP_MEMBERSHIP | IPV6_LEAVE_GROUP
  1224   1056    *
  1225   1057    */
  1226   1058   
  1227   1059   static int
  1228         -UdpMulticast(UdpState *statePtr, Tcl_Interp *interp, 
         1060  +UdpMulticast(UdpState *statePtr, Tcl_Interp *interp,
  1229   1061       const char *grp, int action)
  1230   1062   {
  1231   1063   	int r;
  1232   1064   	Tcl_Obj *tcllist , *multicastgrp , *nw_interface;
  1233   1065   	int len,result;
  1234   1066   	int nwinterface_index =-1;
  1235   1067   #ifndef WIN32
  1236   1068   	struct ifreq ifreq;
  1237   1069   #endif /* ! WIN32 */
  1238   1070   
  1239         -	/* 
         1071  +	/*
  1240   1072   	 * Parameter 'grp' can be:
  1241         -	 *  Windows: <multicast group> or {<multicast group> <network interface index>} 
  1242         -	 *  Not Windows: <multicast group> or {<multicast group> <network interface name>} 
  1243         -	 */ 
         1073  +	 *  Windows: <multicast group> or {<multicast group> <network interface index>}
         1074  +	 *  Not Windows: <multicast group> or {<multicast group> <network interface name>}
         1075  +	 */
  1244   1076   	tcllist = Tcl_NewStringObj(grp, -1);
  1245   1077   	result = Tcl_ListObjLength(interp, tcllist, &len);
  1246   1078   	if (result == TCL_OK) {
  1247   1079   		if (len==2) {
  1248   1080   			Tcl_ListObjIndex(interp, tcllist, 0, &multicastgrp);
  1249   1081   			Tcl_ListObjIndex(interp, tcllist, 1, &nw_interface);
  1250   1082   #ifdef WIN32
................................................................................
  1254   1086   			}
  1255   1087   #else
  1256   1088   			int lenPtr = -1;
  1257   1089   			if (nw_interface->length > IFNAMSIZ ) {
  1258   1090   				Tcl_SetResult(interp, "unknown network interface", TCL_STATIC);
  1259   1091   				return TCL_ERROR;
  1260   1092   			}
  1261         -			
         1093  +
  1262   1094   			if (statePtr->ss_family == AF_INET) {
  1263   1095   				/* For IPv4, we need the network interface address. */
  1264   1096   				strcpy(ifreq.ifr_name,Tcl_GetStringFromObj(nw_interface,&lenPtr));
  1265   1097   				if (ioctl(statePtr->sock, SIOCGIFADDR, &ifreq) < 0 ) {
  1266   1098   					Tcl_SetResult(interp, "unknown network interface", TCL_STATIC);
  1267   1099   					return TCL_ERROR;
  1268   1100   				}
  1269         -			} 
         1101  +			}
  1270   1102   			nwinterface_index = if_nametoindex(Tcl_GetStringFromObj(nw_interface,&lenPtr));
  1271   1103   			if (nwinterface_index == 0 ) {
  1272   1104   				Tcl_SetResult(interp, "unknown network interface", TCL_STATIC);
  1273   1105   				return TCL_ERROR;
  1274   1106   			}
  1275   1107   #endif /* ! WIN32 */
  1276   1108   		} else if (len==1) {
................................................................................
  1280   1112   			return TCL_ERROR;
  1281   1113   		}
  1282   1114   	}
  1283   1115   
  1284   1116   	if (statePtr->ss_family == AF_INET) {
  1285   1117   		struct ip_mreq mreq;
  1286   1118   		struct hostent *name;
  1287         -		
         1119  +
  1288   1120   		memset(&mreq, 0, sizeof(mreq));
  1289         -		
         1121  +
  1290   1122   		mreq.imr_multiaddr.s_addr = inet_addr(Tcl_GetString(multicastgrp));
  1291   1123   		if (mreq.imr_multiaddr.s_addr == -1) {
  1292   1124   			name = gethostbyname(Tcl_GetString(multicastgrp));
  1293   1125   			if (name == NULL) {
  1294   1126   				if (interp != NULL) {
  1295   1127   					Tcl_SetResult(interp, "invalid group name", TCL_STATIC);
  1296   1128   				}
  1297   1129   				return TCL_ERROR;
  1298   1130   			}
  1299   1131   			memcpy(&mreq.imr_multiaddr.s_addr, name->h_addr, sizeof(mreq.imr_multiaddr));
  1300   1132   		}
  1301         -		
         1133  +
  1302   1134   		if (nwinterface_index==-1) {
  1303   1135   			/* No interface index specified. Let the system use the default interface. */
  1304   1136   			mreq.imr_interface.s_addr = INADDR_ANY;
  1305   1137   		} else {
  1306   1138   #ifdef WIN32
  1307   1139   			/* Using an interface index of x is indicated by 0.0.0.x */
  1308   1140   			mreq.imr_interface.s_addr = htonl(nwinterface_index);
  1309   1141   #else
  1310   1142   			memcpy(&mreq.imr_interface, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr));
  1311   1143   #endif
  1312   1144   		}
  1313         -		
         1145  +
  1314   1146   		if (setsockopt(statePtr->sock, IPPROTO_IP, action, (const char*)&mreq, sizeof(mreq)) < 0) {
  1315   1147   			if (interp != NULL) {
  1316   1148   				Tcl_SetObjResult(interp, ErrorToObj("error changing multicast group"));
  1317   1149   			}
  1318   1150   			return TCL_ERROR;
  1319   1151   		}
  1320   1152   	} else {
................................................................................
  1323   1155   		struct addrinfo *result = NULL;
  1324   1156   
  1325   1157   		memset(&hints, 0, sizeof(hints));
  1326   1158   
  1327   1159   		hints.ai_family = statePtr->ss_family;
  1328   1160   		hints.ai_socktype = SOCK_DGRAM;
  1329   1161   		hints.ai_protocol = IPPROTO_UDP;
  1330         -		
         1162  +
  1331   1163   		r = getaddrinfo(Tcl_GetString(multicastgrp), NULL, &hints, &result);
  1332   1164   
  1333   1165   		if (r != 0 ) {
  1334         -			Tcl_SetResult(interp, "invalid group name", TCL_STATIC);	
         1166  +			Tcl_SetResult(interp, "invalid group name", TCL_STATIC);
  1335   1167   			freeaddrinfo(result);
  1336   1168   			return TCL_ERROR;
  1337   1169   		} else {
  1338   1170   			memcpy(&mreq6.ipv6mr_multiaddr, &((struct sockaddr_in6*)(result->ai_addr))->sin6_addr,sizeof(mreq6.ipv6mr_multiaddr));
  1339   1171   			freeaddrinfo(result);
  1340   1172   		}
  1341   1173   
................................................................................
  1348   1180   		}
  1349   1181   
  1350   1182   		if (setsockopt(statePtr->sock, IPPROTO_IPV6, action, (const char*)&mreq6, sizeof(mreq6)) < 0) {
  1351   1183   			if (interp != NULL) {
  1352   1184   				Tcl_SetObjResult(interp, ErrorToObj("error changing multicast group"));
  1353   1185   			}
  1354   1186   			return TCL_ERROR;
  1355         -		}	
         1187  +		}
  1356   1188   	}
  1357   1189   
  1358   1190       if (action == IP_ADD_MEMBERSHIP || action == IPV6_JOIN_GROUP) {
  1359   1191   		int ndx = LSearch(statePtr->groupsObj, grp);
  1360   1192   		if (ndx == -1) {
  1361   1193   			Tcl_Obj *newPtr;
  1362   1194   			statePtr->multicast++;
................................................................................
  1393   1225   }
  1394   1226   
  1395   1227   /*
  1396   1228   * ----------------------------------------------------------------------
  1397   1229   * udpGetOption --
  1398   1230   * ----------------------------------------------------------------------
  1399   1231   */
  1400         -static int 
  1401         -udpGetOption(ClientData instanceData, Tcl_Interp *interp,
  1402         -			 CONST84 char *optionName, Tcl_DString *optionValue)
         1232  +static int udpGetOption(
         1233  +ClientData instanceData, Tcl_Interp *interp,
         1234  +CONST84 char *optionName, Tcl_DString *optionValue
         1235  +)
  1403   1236   {
  1404   1237   	UdpState *statePtr = (UdpState *)instanceData;
  1405   1238   	CONST84 char * options[] = { "myport", "remote", "peer", "mcastgroups", "mcastloop", "broadcast", "ttl", NULL};
  1406   1239   	int r = TCL_OK;
  1407         -	
         1240  +
  1408   1241   	if (optionName == NULL) {
  1409   1242   		Tcl_DString ds;
  1410   1243   		const char **p;
  1411         -		
         1244  +
  1412   1245   		Tcl_DStringInit(&ds);
  1413   1246   		for (p = options; *p != NULL; p++) {
  1414   1247   			char op[16];
  1415   1248   			sprintf(op, "-%s", *p);
  1416   1249   			Tcl_DStringSetLength(&ds, 0);
  1417   1250   			udpGetOption(instanceData, interp, op, &ds);
  1418   1251   			Tcl_DStringAppend(optionValue, " ", 1);
  1419   1252   			Tcl_DStringAppend(optionValue, op, -1);
  1420   1253   			Tcl_DStringAppend(optionValue, " ", 1);
  1421   1254   			Tcl_DStringAppendElement(optionValue, Tcl_DStringValue(&ds));
  1422   1255   		}
  1423         -		
         1256  +
  1424   1257   	} else {
  1425         -		
         1258  +
  1426   1259   		Tcl_DString ds, dsInt;
  1427   1260   		Tcl_DStringInit(&ds);
  1428   1261   		Tcl_DStringInit(&dsInt);
  1429         -		
         1262  +
  1430   1263   		if (!strcmp("-myport", optionName)) {
  1431         -			
         1264  +
  1432   1265   			Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
  1433   1266   			sprintf(Tcl_DStringValue(&ds), "%u", ntohs(statePtr->localport));
  1434         -			
         1267  +
  1435   1268   		} else if (!strcmp("-remote", optionName)) {
  1436   1269               if (statePtr->remotehost && *statePtr->remotehost) {
  1437   1270   				Tcl_DStringSetLength(&dsInt, TCL_INTEGER_SPACE);
  1438         -				sprintf(Tcl_DStringValue(&dsInt), "%u", 
         1271  +				sprintf(Tcl_DStringValue(&dsInt), "%u",
  1439   1272   					ntohs(statePtr->remoteport));
  1440   1273   				Tcl_DStringAppendElement(&ds, statePtr->remotehost);
  1441   1274   				Tcl_DStringAppendElement(&ds, Tcl_DStringValue(&dsInt));
  1442   1275   			}
  1443         -			
         1276  +
  1444   1277   		} else if (!strcmp("-peer", optionName)) {
  1445         -			
         1278  +
  1446   1279              if (statePtr->peerhost && *statePtr->peerhost) {
  1447   1280    				Tcl_DStringSetLength(&dsInt, TCL_INTEGER_SPACE);
  1448   1281   				sprintf(Tcl_DStringValue(&dsInt), "%u", statePtr->peerport);
  1449   1282   				Tcl_DStringAppendElement(&ds, statePtr->peerhost);
  1450   1283   				Tcl_DStringAppendElement(&ds, Tcl_DStringValue(&dsInt));
  1451   1284   		   }
  1452         -			
         1285  +
  1453   1286   		} else if (!strcmp("-mcastgroups", optionName)) {
  1454         -			
         1287  +
  1455   1288   			int objc, n;
  1456   1289   			Tcl_Obj **objv;
  1457   1290   			Tcl_ListObjGetElements(interp, statePtr->groupsObj, &objc, &objv);
  1458   1291   			for (n = 0; n < objc; n++) {
  1459   1292   				Tcl_DStringAppendElement(&ds, Tcl_GetString(objv[n]));
  1460   1293   			}
  1461         -			
         1294  +
  1462   1295   		} else if (!strcmp("-broadcast", optionName)) {
  1463   1296   			int tmp =1;
  1464   1297   			r = udpGetBroadcastOption(statePtr,interp,&tmp);
  1465   1298   			if (r==TCL_OK) {
  1466   1299   				Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
  1467   1300   				sprintf(Tcl_DStringValue(&ds), "%d", tmp);
  1468         -			}			 
         1301  +			}
  1469   1302   		} else if (!strcmp("-mcastloop", optionName)) {
  1470         -			unsigned char tmp = 0;			 
         1303  +			unsigned char tmp = 0;
  1471   1304   			r = udpGetMcastloopOption(statePtr, interp,&tmp);
  1472   1305   			if (r==TCL_OK) {
  1473   1306   				Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
  1474   1307   				sprintf(Tcl_DStringValue(&ds), "%d", (int)tmp);
  1475         -			}			 			 
         1308  +			}
  1476   1309   		} else if (!strcmp("-ttl", optionName)) {
  1477         -			
         1310  +
  1478   1311   			unsigned int tmp = 0;
  1479   1312   			r = udpGetTtlOption(statePtr,interp,&tmp);
  1480   1313   			if (r==TCL_OK) {
  1481   1314   				Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
  1482   1315   				sprintf(Tcl_DStringValue(&ds), "%u", tmp);
  1483         -			}			 
         1316  +			}
  1484   1317   		} else {
  1485   1318   			CONST84 char **p;
  1486   1319   			Tcl_DString tmp;
  1487   1320   			Tcl_DStringInit(&tmp);
  1488   1321   			for (p = options; *p != NULL; p++)
  1489   1322   				Tcl_DStringAppendElement(&tmp, *p);
  1490   1323   			r = Tcl_BadChannelOption(interp, optionName, Tcl_DStringValue(&tmp));
  1491   1324   			Tcl_DStringFree(&tmp);
  1492   1325   		}
  1493         -		
         1326  +
  1494   1327   		if (r == TCL_OK) {
  1495   1328   			Tcl_DStringAppend(optionValue, Tcl_DStringValue(&ds), -1);
  1496   1329   		}
  1497   1330   		Tcl_DStringFree(&dsInt);
  1498   1331   		Tcl_DStringFree(&ds);
  1499   1332   	}
  1500         -	
         1333  +
  1501   1334   	return r;
  1502   1335   }
  1503   1336   
  1504   1337   /*
  1505   1338    * ----------------------------------------------------------------------
  1506   1339    * udpSetOption --
  1507   1340    *
  1508   1341    *  Handle channel configuration requests from the generic layer.
  1509   1342    *
  1510   1343    * ----------------------------------------------------------------------
  1511   1344    */
  1512         -static int
  1513         -udpSetOption(ClientData instanceData, Tcl_Interp *interp,
  1514         -             CONST84 char *optionName, CONST84 char *newValue)
         1345  +static int udpSetOption(
         1346  +ClientData instanceData, Tcl_Interp *interp,
         1347  +CONST84 char *optionName, CONST84 char *newValue
         1348  +)
  1515   1349   {
  1516   1350       UdpState *statePtr = (UdpState *)instanceData;
  1517   1351       CONST84 char * options = "remote mcastadd mcastdrop mcastloop broadcast ttl";
  1518   1352       int r = TCL_OK;
  1519         -	
         1353  +
  1520   1354       if (!strcmp("-remote", optionName)) {
  1521   1355   		r = udpSetRemoteOption(statePtr,interp,(const char *)newValue);
  1522   1356   #ifndef WIN32
  1523   1357       } else if (!strcmp("-mcastif", optionName)) {
  1524   1358   		r = udpSetMulticastIFOption(statePtr,interp,(const char *)newValue);
  1525   1359   #endif
  1526   1360       } else if (!strcmp("-mcastadd", optionName)) {
  1527         -		r = udpSetMulticastAddOption(statePtr, interp, (const char *)newValue);		
         1361  +		r = udpSetMulticastAddOption(statePtr, interp, (const char *)newValue);
  1528   1362       } else if (!strcmp("-mcastdrop", optionName)) {
  1529         -		r = udpSetMulticastDropOption(statePtr, interp, (const char *)newValue);				
         1363  +		r = udpSetMulticastDropOption(statePtr, interp, (const char *)newValue);
  1530   1364       } else if (!strcmp("-broadcast", optionName)) {
  1531         -		r = udpSetBroadcastOption(statePtr, interp, (const char*) newValue);		
         1365  +		r = udpSetBroadcastOption(statePtr, interp, (const char*) newValue);
  1532   1366        } else if (!strcmp("-mcastloop", optionName)) {
  1533   1367   		r = udpSetMcastloopOption(statePtr, interp, (const char*) newValue);
  1534   1368   	 } else if (!strcmp("-ttl", optionName)) {
  1535         -		r = udpSetTtlOption(statePtr, interp, (const char*) newValue);		
         1369  +		r = udpSetTtlOption(statePtr, interp, (const char*) newValue);
  1536   1370       } else {
  1537   1371           Tcl_BadChannelOption(interp, optionName, options);
  1538   1372   		r=TCL_ERROR;
  1539   1373       }
  1540   1374   
  1541   1375       return r;
  1542   1376   }
................................................................................
  1570   1404   			cmd = IPV6_UNICAST_HOPS;
  1571   1405   		}
  1572   1406   		result = getsockopt(statePtr->sock, IPPROTO_IPV6, cmd, (char*)value, &optlen);
  1573   1407   	}
  1574   1408   
  1575   1409   	if (result==TCL_ERROR) {
  1576   1410   		Tcl_SetObjResult(interp, Tcl_NewStringObj("error getting -ttl",-1));
  1577         -	} 
         1411  +	}
  1578   1412   	return result;
  1579   1413   }
  1580   1414   
  1581   1415   /*
  1582   1416    * ----------------------------------------------------------------------
  1583   1417    * udpSetTtlOption --
  1584   1418    *
................................................................................
  1589   1423   static int
  1590   1424   udpSetTtlOption(UdpState *statePtr, Tcl_Interp *interp,CONST84 char *newValue)
  1591   1425   {
  1592   1426   	int result = TCL_ERROR;
  1593   1427   	int tmp = 0;
  1594   1428   	int cmd;
  1595   1429   	result = Tcl_GetInt(interp, newValue, &tmp);
  1596         -	
         1430  +
  1597   1431   	if (statePtr->ss_family==AF_INET) {
  1598   1432   		if (statePtr->multicast > 0) {
  1599   1433   			cmd = IP_MULTICAST_TTL;
  1600   1434   		} else {
  1601   1435   			cmd = IP_TTL;
  1602   1436   		}
  1603   1437   		if (result == TCL_OK) {
................................................................................
  1636   1470   	int result = TCL_ERROR;
  1637   1471   	socklen_t optlen=sizeof(int);
  1638   1472   	if (statePtr->ss_family == AF_INET) {
  1639   1473   		result = getsockopt(statePtr->sock, IPPROTO_IP, IP_MULTICAST_LOOP,value, &optlen);
  1640   1474   	} else {
  1641   1475   		result = getsockopt(statePtr->sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,value, &optlen);
  1642   1476   	}
  1643         -	
         1477  +
  1644   1478   	if (result == TCL_ERROR) {
  1645   1479   		Tcl_SetObjResult(interp, Tcl_NewStringObj("error getting -mcastloop",-1));
  1646         -	} 
  1647         -	
         1480  +	}
         1481  +
  1648   1482   	return result;
  1649   1483   }
  1650   1484   
  1651   1485   /*
  1652   1486    * ----------------------------------------------------------------------
  1653   1487    * udpSetMcastloopOption --
  1654   1488    *
................................................................................
  1672   1506   	}
  1673   1507   
  1674   1508   	if (result == TCL_ERROR) {
  1675   1509   		Tcl_SetObjResult(interp, Tcl_NewStringObj("error setting -mcastloop",-1));
  1676   1510   	} else {
  1677   1511   		Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
  1678   1512   	}
  1679         -	
  1680         -	
         1513  +
         1514  +
  1681   1515   	return result;
  1682   1516   }
  1683   1517   
  1684   1518   /*
  1685   1519    * ----------------------------------------------------------------------
  1686   1520    * udpGetBroadcastOption --
  1687   1521    *
................................................................................
  1697   1531   	if (statePtr->ss_family == AF_INET6 ) {
  1698   1532   		Tcl_SetObjResult(interp, Tcl_NewStringObj("broadcast not supported under ipv6",-1));
  1699   1533   		return TCL_ERROR;
  1700   1534   	}
  1701   1535   	if (getsockopt(statePtr->sock, SOL_SOCKET, SO_BROADCAST, (char*)value, &optlen)) {
  1702   1536   		Tcl_SetObjResult(interp, Tcl_NewStringObj("error getting -broadcast",-1));
  1703   1537   		result = TCL_ERROR;
  1704         -	} 
  1705         -	
         1538  +	}
         1539  +
  1706   1540   	return result;
  1707   1541   }
  1708   1542   
  1709   1543   /*
  1710   1544    * ----------------------------------------------------------------------
  1711   1545    * udpSetBroadcastOption --
  1712   1546    *
................................................................................
  1723   1557   	if (statePtr->ss_family == AF_INET6 ) {
  1724   1558   			Tcl_SetObjResult(interp, ErrorToObj("broadcast not supported under ipv6"));
  1725   1559   			return TCL_ERROR;
  1726   1560   	}
  1727   1561   
  1728   1562   	result = Tcl_GetInt(interp, newValue, &tmp);
  1729   1563   	if (result == TCL_OK ) {
  1730         -		if (setsockopt(statePtr->sock, SOL_SOCKET, SO_BROADCAST, 
         1564  +		if (setsockopt(statePtr->sock, SOL_SOCKET, SO_BROADCAST,
  1731   1565   			(const char *)&tmp, sizeof(int))) {
  1732   1566   			Tcl_SetObjResult(interp, Tcl_NewStringObj("error setting -broadcast",-1));
  1733   1567   			result = TCL_ERROR;
  1734   1568   		} else {
  1735   1569   			Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
  1736   1570   		}
  1737   1571   	}
  1738         -	
         1572  +
  1739   1573   	return result;
  1740   1574   }
  1741   1575   
  1742   1576   /*
  1743   1577    * ----------------------------------------------------------------------
  1744   1578    * udpSetRemoteOption --
  1745   1579    *
................................................................................
  1747   1581    *
  1748   1582    * ----------------------------------------------------------------------
  1749   1583    */
  1750   1584   static int
  1751   1585   udpSetRemoteOption(UdpState *statePtr, Tcl_Interp *interp,CONST84 char *newValue)
  1752   1586   {
  1753   1587   	int result;
  1754         -	
         1588  +
  1755   1589   	Tcl_Obj *valPtr;
  1756   1590   	int len;
  1757         -	
         1591  +
  1758   1592   	valPtr = Tcl_NewStringObj(newValue, -1);
  1759   1593   	result = Tcl_ListObjLength(interp, valPtr, &len);
  1760   1594   	if (result == TCL_OK) {
  1761   1595   		if (len < 1 || len > 2) {
  1762   1596   			Tcl_SetResult(interp, "wrong # args", TCL_STATIC);
  1763   1597   			result = TCL_ERROR;
  1764   1598   		} else {
  1765   1599   			Tcl_Obj *hostPtr, *portPtr;
  1766         -			
         1600  +
  1767   1601   			Tcl_ListObjIndex(interp, valPtr, 0, &hostPtr);
  1768   1602   			strcpy(statePtr->remotehost, Tcl_GetString(hostPtr));
  1769         -			
         1603  +
  1770   1604   			if (len == 2) {
  1771         -				Tcl_ListObjIndex(interp, valPtr, 1, &portPtr);            
         1605  +				Tcl_ListObjIndex(interp, valPtr, 1, &portPtr);
  1772   1606   				result = udpGetService(interp, Tcl_GetString(portPtr),
  1773   1607   					&(statePtr->remoteport));
  1774   1608   			}
  1775   1609   		}
  1776   1610   	}
  1777   1611   
  1778   1612   	if (result==TCL_ERROR) {
................................................................................
  1805   1639         return TCL_ERROR;
  1806   1640       }
  1807   1641       if (setsockopt(statePtr->sock, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&interface_addr, sizeof(interface_addr)) < 0) {
  1808   1642         if (interp != NULL) {
  1809   1643           Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif"));
  1810   1644         }
  1811   1645         return TCL_ERROR;
  1812         -    }		
         1646  +    }
  1813   1647     } else {
  1814   1648       struct in6_addr interface_addr;
  1815   1649       if(inet_pton(AF_INET6,newValue,&interface_addr)==0) {
  1816   1650         if (interp != NULL) {
  1817   1651           Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif (bad IP)"));
  1818   1652         }
  1819   1653         return TCL_ERROR;
................................................................................
  1839   1673    */
  1840   1674   static int
  1841   1675   udpSetMulticastAddOption(UdpState *statePtr, Tcl_Interp *interp,CONST84 char *newValue)
  1842   1676   {
  1843   1677    	int result;
  1844   1678   
  1845   1679   	if (statePtr->ss_family == AF_INET) {
  1846         -		result = UdpMulticast(statePtr, interp, 
  1847         -				(const char *)newValue, IP_ADD_MEMBERSHIP);		
         1680  +		result = UdpMulticast(statePtr, interp,
         1681  +				(const char *)newValue, IP_ADD_MEMBERSHIP);
  1848   1682   	} else {
  1849         -		result = UdpMulticast(statePtr, interp, 
  1850         -				(const char *)newValue, IPV6_JOIN_GROUP);		
         1683  +		result = UdpMulticast(statePtr, interp,
         1684  +				(const char *)newValue, IPV6_JOIN_GROUP);
  1851   1685   	}
  1852   1686   	return result;
  1853   1687   }
  1854   1688   
  1855   1689   /*
  1856   1690    * ----------------------------------------------------------------------
  1857   1691    * udpSetMulticastDropOption --
................................................................................
  1862   1696    */
  1863   1697   static int
  1864   1698   udpSetMulticastDropOption(UdpState *statePtr, Tcl_Interp *interp,CONST84 char *newValue)
  1865   1699   {
  1866   1700    	int result;
  1867   1701   
  1868   1702   	if (statePtr->ss_family == AF_INET) {
  1869         -		result = UdpMulticast(statePtr, interp, 
  1870         -				(const char *)newValue, IP_DROP_MEMBERSHIP);		
         1703  +		result = UdpMulticast(statePtr, interp,
         1704  +				(const char *)newValue, IP_DROP_MEMBERSHIP);
  1871   1705   	} else {
  1872         -		result = UdpMulticast(statePtr, interp, 
  1873         -				(const char *)newValue, IPV6_LEAVE_GROUP);		
         1706  +		result = UdpMulticast(statePtr, interp,
         1707  +				(const char *)newValue, IPV6_LEAVE_GROUP);
  1874   1708   	}
  1875   1709   
  1876   1710   	if (result==TCL_ERROR) {
  1877   1711   		Tcl_SetObjResult(interp, Tcl_NewStringObj("error setting -mcastdrop",-1));
  1878         -	} 
         1712  +	}
  1879   1713   
  1880   1714   	return result;
  1881   1715   }
  1882   1716   
  1883   1717   static Tcl_Obj *
  1884   1718   ErrorToObj(const char * prefix)
  1885   1719   {
................................................................................
  1911   1745    * udpTrace --
  1912   1746    * ----------------------------------------------------------------------
  1913   1747    */
  1914   1748   static void
  1915   1749   udpTrace(const char *format, ...)
  1916   1750   {
  1917   1751       va_list args;
  1918         -    
         1752  +
  1919   1753   #ifdef WIN32
  1920   1754   
  1921   1755       static char buffer[1024];
  1922   1756       va_start (args, format);
  1923   1757       _vsnprintf(buffer, 1023, format, args);
  1924   1758       OutputDebugStringA(buffer);
  1925   1759   
................................................................................
  1960   1794    *
  1961   1795    * UdpSockGetPort --
  1962   1796    *
  1963   1797    *      Maps from a string, which could be a service name, to a port.
  1964   1798    *      Used by socket creation code to get port numbers and resolve
  1965   1799    *      registered service names to port numbers.
  1966   1800    *
  1967         - *      NOTE: this is a copy of TclSockGetPort.   
         1801  + *      NOTE: this is a copy of TclSockGetPort.
  1968   1802    *
  1969   1803    * Results:
  1970   1804    *      A standard Tcl result.  On success, the port number is returned
  1971   1805    *      in portPtr. On failure, an error message is left in the interp's
  1972   1806    *      result.
  1973   1807    *
  1974   1808    * Side effects:
................................................................................
  2007   1841       if (*portPtr > 0xFFFF) {
  2008   1842           Tcl_AppendResult(interp, "couldn't open socket: port number too high",
  2009   1843                            (char *) NULL);
  2010   1844           return TCL_ERROR;
  2011   1845       }
  2012   1846       return TCL_OK;
  2013   1847   }
         1848  +
         1849  +
         1850  +
         1851  +/*
         1852  + * This structure describes the channel type for accessing UDP.
         1853  + */
         1854  +static Tcl_ChannelType Udp_ChannelType = {
         1855  +    "udp",                 /* Type name.                                    */
         1856  +#ifdef TCL_CHANNEL_VERSION_4
         1857  +    TCL_CHANNEL_VERSION_4,	/* v5 channel */
         1858  +    udpClose,              /* Close channel, clean instance data            */
         1859  +    udpInput,              /* Handle read request                           */
         1860  +    udpOutput,             /* Handle write request                          */
         1861  +    NULL,                  /* Seek proc. */
         1862  +    udpSetOption,          /* Set options.                        NULL'able */
         1863  +    udpGetOption,          /* Get options.                        NULL'able */
         1864  +    udpWatch,              /* Initialize notifier                           */
         1865  +    udpGetHandle,          /* Get OS handle from the channel.               */
         1866  +    NULL,			/* close2proc */
         1867  +    NULL,     /* Set blocking/nonblocking behaviour. NULL'able */
         1868  +    NULL,			/* Flush proc. */
         1869  +    NULL,			/* Handling of events bubbling up. */
         1870  +    NULL,	    /* Wide seek proc. */
         1871  +    NULL,			/* Thread action. */
         1872  +#else
         1873  +    NULL,     /* Set blocking/nonblocking behaviour. NULL'able */
         1874  +    udpClose,              /* Close channel, clean instance data            */
         1875  +    udpInput,              /* Handle read request                           */
         1876  +    udpOutput,             /* Handle write request                          */
         1877  +    NULL,                  /* Seek proc. */
         1878  +    udpSetOption,          /* Set options.                        NULL'able */
         1879  +    udpGetOption,          /* Get options.                        NULL'able */
         1880  +    udpWatch,              /* Initialize notifier                           */
         1881  +    udpGetHandle,          /* Get OS handle from the channel.               */
         1882  +#endif
         1883  +};
         1884  +
         1885  +/*
         1886  + * ----------------------------------------------------------------------
         1887  + * udpOpen --
         1888  + *
         1889  + *  opens a UDP socket and addds the file descriptor to the tcl
         1890  + *  interpreter
         1891  + * ----------------------------------------------------------------------
         1892  + */
         1893  +int
         1894  +udpOpen(ClientData clientData, Tcl_Interp *interp,
         1895  +        int argc, CONST84 char * argv[])
         1896  +{
         1897  +#ifdef WIN32
         1898  +    SOCKET sock;
         1899  +#else
         1900  +    int sock;
         1901  +#endif
         1902  +    char channelName[20];
         1903  +    UdpState *statePtr;
         1904  +    uint16_t localport = 0;
         1905  +    int reuse = 0;
         1906  +	struct sockaddr_storage addr,sockaddr;
         1907  +	socklen_t addr_len;
         1908  +    unsigned long status = 1;
         1909  +    socklen_t len;
         1910  +	short ss_family = AF_INET; /* Default ipv4 */
         1911  +	char errmsg[] = "upd_open [remoteport] [ipv6] [reuse]";
         1912  +	int remaining_options = argc;
         1913  +
         1914  +    if (argc >= 2) {
         1915  +		if (hasOption(argc,argv,"reuse")) {
         1916  +           reuse = 1;
         1917  +           remaining_options--;
         1918  + 		}
         1919  +
         1920  +		if (hasOption(argc,argv,"ipv6")) {
         1921  + 			ss_family = AF_INET6;
         1922  + 			remaining_options--;
         1923  + 		}
         1924  +		/* The remaining option must be the port (if specified) */
         1925  +		if (remaining_options == 2) {
         1926  +		   if (udpGetService(interp, argv[1], &localport) != TCL_OK) {
         1927  +				Tcl_SetResult (interp, errmsg, NULL);
         1928  +				return TCL_ERROR;
         1929  +		   }
         1930  +		}
         1931  +    }
         1932  +    memset(channelName, 0, sizeof(channelName));
         1933  +
         1934  +	sock = socket(ss_family, SOCK_DGRAM, 0);
         1935  +    if (sock < 0) {
         1936  +        snprintf(errBuf, 255, "failed to create socket");
         1937  +        errBuf[255] = 0;
         1938  +        UDPTRACE("%s\n", errBuf);
         1939  +        Tcl_AppendResult(interp, errBuf, (char *)NULL);
         1940  +        return TCL_ERROR;
         1941  +    }
         1942  +
         1943  +    /*
         1944  +     * bug #1477669: avoid socket inheritence after exec
         1945  +     */
         1946  +
         1947  +#if HAVE_FLAG_FD_CLOEXEC
         1948  +    fcntl(sock, F_SETFD, FD_CLOEXEC);
         1949  +#else
         1950  +#ifdef WIN32
         1951  +    if (SetHandleInformation((HANDLE)sock, HANDLE_FLAG_INHERIT, 0) == 0) {
         1952  +        Tcl_AppendResult(interp, "failed to set close-on-exec bit", NULL);
         1953  +        return TCL_ERROR;
         1954  +    }
         1955  +#endif /* WIN32 */
         1956  +#endif /* HAVE_FLAG_FD_CLOEXEC */
         1957  +
         1958  +    if (reuse) {
         1959  +        int one = 1;
         1960  +#ifdef SO_REUSEPORT
         1961  +        if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
         1962  +                       (const char *)&one, sizeof(one)) < 0) {
         1963  +#else
         1964  +        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
         1965  +                       (const char *)&one, sizeof(one)) < 0) {
         1966  +#endif
         1967  +             Tcl_SetObjResult(interp,
         1968  +                             ErrorToObj("error setting socket option"));
         1969  +            closesocket(sock);
         1970  +            return TCL_ERROR;
         1971  +        }
         1972  +    }
         1973  +
         1974  +	memset(&addr, 0, sizeof(addr));
         1975  +	if (ss_family == AF_INET6) {
         1976  +		((struct sockaddr_in6 *) &addr)->sin6_family = AF_INET6;
         1977  +		((struct sockaddr_in6 *) &addr)->sin6_port = localport;
         1978  +		addr_len = sizeof(struct sockaddr_in6);
         1979  +	} else {
         1980  +		((struct sockaddr_in *) &addr)->sin_family = AF_INET;
         1981  +		((struct sockaddr_in *) &addr)->sin_port = localport;
         1982  +		addr_len = sizeof(struct sockaddr_in);
         1983  +	}
         1984  +	if ( bind(sock,(struct sockaddr *)&addr, addr_len) < 0) {
         1985  +        Tcl_SetObjResult(interp,
         1986  +                         ErrorToObj("failed to bind socket to port"));
         1987  +
         1988  +        closesocket(sock);
         1989  +        return TCL_ERROR;
         1990  +    }
         1991  +
         1992  +    ioctlsocket(sock, FIONBIO, &status);
         1993  +
         1994  +    if (localport == 0) {
         1995  +        len = sizeof(sockaddr);
         1996  +		getsockname(sock, (struct sockaddr *)&sockaddr, &len);
         1997  + 		if (ss_family == AF_INET6) {
         1998  +			localport = ((struct sockaddr_in6 *) &sockaddr)->sin6_port;
         1999  +		} else {
         2000  +			localport = ((struct sockaddr_in *) &sockaddr)->sin_port;
         2001  +		}
         2002  +    }
         2003  +
         2004  +    UDPTRACE("Open socket %d. Bind socket to port %d\n",
         2005  +             sock, ntohs(localport));
         2006  +
         2007  +    statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState));
         2008  +    memset(statePtr, 0, sizeof(UdpState));
         2009  +    statePtr->sock = sock;
         2010  +    sprintf(channelName, "sock" SOCKET_PRINTF_FMT, statePtr->sock);
         2011  +    statePtr->channel = Tcl_CreateChannel(&Udp_ChannelType, channelName,
         2012  +                                          (ClientData) statePtr,
         2013  +                                          (TCL_READABLE | TCL_WRITABLE | TCL_MODE_NONBLOCKING));
         2014  +    statePtr->doread = 1;
         2015  +    statePtr->multicast = 0;
         2016  +    statePtr->groupsObj = Tcl_NewListObj(0, NULL);
         2017  +    Tcl_IncrRefCount(statePtr->groupsObj);
         2018  +    statePtr->localport = localport;
         2019  +	statePtr->ss_family = ss_family;
         2020  +    Tcl_RegisterChannel(interp, statePtr->channel);
         2021  +#ifdef WIN32
         2022  +    statePtr->threadId = Tcl_GetCurrentThread();
         2023  +    statePtr->packetNum = 0;
         2024  +    statePtr->next = NULL;
         2025  +    statePtr->packets = NULL;
         2026  +    statePtr->packetsTail = NULL;
         2027  +#endif
         2028  +    /* Tcl_SetChannelOption(interp, statePtr->channel, "-blocking", "0"); */
         2029  +    Tcl_AppendResult(interp, channelName, (char *)NULL);
         2030  +#ifdef WIN32
         2031  +    WaitForSingleObject(sockListLock, INFINITE);
         2032  +    statePtr->next = sockList;
         2033  +    sockList = statePtr;
         2034  +
         2035  +    UDPTRACE("Added %d to sockList\n", statePtr->sock);
         2036  +    SetEvent(sockListLock);
         2037  +    SetEvent(waitForSock);
         2038  +#endif
         2039  +    return TCL_OK;
         2040  +}
         2041  +
  2014   2042   
  2015   2043   /*
  2016   2044    * ----------------------------------------------------------------------
  2017   2045    *
  2018   2046    * Local variables:
  2019   2047    * mode: c
  2020   2048    * indent-tabs-mode: nil
  2021   2049    * End:
  2022   2050    */