Tcl UDP

Check-in [ef5c5c83f4]
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:Branch to test specifying the interface to use for multicast
Timelines: family | ancestors | descendants | both | mcastif
Files: files | file ages | folders
SHA1: ef5c5c83f49757ba8b8443b3b4cb9efff35d1eb4
User & Date: hypnotoad 2014-08-22 15:43:04
Context
2014-08-22
16:02
Typo fix Leaf check-in: d62a2a4f64 user: hypnotoad tags: mcastif
15:43
Branch to test specifying the interface to use for multicast check-in: ef5c5c83f4 user: hypnotoad tags: mcastif
2014-08-21
14:32
Checking in patch submitted to sourceforge: https://sourceforge.net/p/tcludp/bugs/42 check-in: 1b24c4d641 user: hypnotoad tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/udp_tcl.c.

115
116
117
118
119
120
121

122
123
124
125
126
127
128
...
423
424
425
426
427
428
429

430
431
432
433
434
435
436
...
446
447
448
449
450
451
452

453
454
455
456
457
458
459
....
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
....
1493
1494
1495
1496
1497
1498
1499


1500
1501
1502
1503
1504
1505
1506
....
1754
1755
1756
1757
1758
1759
1760












































1761
1762
1763
1764
1765
1766
1767
                          const char *proto, int *portPtr);
static void udpTrace(const char *format, ...);
static int  udpGetService(Tcl_Interp *interp, const char *service,
                          unsigned short *servicePort);
static Tcl_Obj *ErrorToObj(const char * prefix);
static int hasOption(int argc, CONST84 char * argv[],const char* option );
static int udpSetRemoteOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);

static int udpSetMulticastAddOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetMulticastDropOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetBroadcastOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpGetBroadcastOption(UdpState* statePtr, Tcl_Interp *interp, int* value);
static int udpSetMcastloopOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpGetMcastloopOption(UdpState *statePtr, Tcl_Interp *interp, unsigned char * value);
static int udpSetTtlOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
................................................................................
		"udp_conf fileId [-mcastadd] [-mcastdrop] groupaddr | "
#ifdef WIN32
		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif_index\" | "
#else
		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif\" | "
#endif
		"udp_conf fileId remotehost remoteport | "

		"udp_conf fileId [-myport] [-remote] [-peer] [-mcastgroups] [-mcastloop] [-broadcast] [-ttl]";
	
	if (argc >= 2) {
		chan = Tcl_GetChannel(interp, (char *)argv[1], NULL);
		if (chan != (Tcl_Channel) NULL) {
			statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan);
		}
................................................................................
	}
	
	if (argc == 4 && statePtr != NULL) {
		if (hasOption(argc,argv,"-mcastloop") ||
			hasOption(argc,argv,"-broadcast") ||
			hasOption(argc,argv,"-mcastadd") ||
			hasOption(argc,argv,"-mcastdrop") ||

			hasOption(argc,argv,"-ttl")) { 
			r = Tcl_SetChannelOption(interp, statePtr->channel, argv[2], argv[3]);
		} else {
			sprintf(remoteOptions, "%s %s",argv[2],argv[3] );
			r = Tcl_SetChannelOption(interp, statePtr->channel, "-remote", remoteOptions);
		}
	}
................................................................................
		freeaddrinfo(result);

		sendaddrv6.sin6_family = AF_INET6;
		sendaddrv6.sin6_port = statePtr->remoteport;

		written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddrv6, socksize);
	} else {
		socksize = sizeof(sendaddrv4);
		memset(&sendaddrv4, 0, socksize);
        sendaddrv4.sin_addr.s_addr = inet_addr(statePtr->remotehost);

        if (sendaddrv4.sin_addr.s_addr == -1) {
            name = gethostbyname(statePtr->remotehost);
			if (name == NULL) {
				UDPTRACE("UDP error - gethostbyname");
				return -1;
			}
			memcpy(&sendaddrv4.sin_addr, name->h_addr, sizeof(sendaddrv4.sin_addr));
		}


		sendaddrv4.sin_family = AF_INET;
		sendaddrv4.sin_port = statePtr->remoteport;

		written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddrv4, socksize);
	}

	if (written < 0) {
		UDPTRACE("UDP error - sendto");
		return -1;
	}

................................................................................
{
    UdpState *statePtr = (UdpState *)instanceData;
    CONST84 char * options = "remote mcastadd mcastdrop mcastloop broadcast ttl";
    int r = TCL_OK;
	
    if (!strcmp("-remote", optionName)) {
		r = udpSetRemoteOption(statePtr,interp,(const char *)newValue);


    } else if (!strcmp("-mcastadd", optionName)) {
		r = udpSetMulticastAddOption(statePtr, interp, (const char *)newValue);		
    } else if (!strcmp("-mcastdrop", optionName)) {
		r = udpSetMulticastDropOption(statePtr, interp, (const char *)newValue);				
    } else if (!strcmp("-broadcast", optionName)) {
		r = udpSetBroadcastOption(statePtr, interp, (const char*) newValue);		
     } else if (!strcmp("-mcastloop", optionName)) {
................................................................................
	} else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(newValue,-1));
	}

	return result;
}













































/*
 * ----------------------------------------------------------------------
 * udpSetMulticastAddOption --
 *
 *  Handle multicast add configuration requests.
 *
 * ----------------------------------------------------------------------






>







 







>







 







>







 







|
|
|

|

|
|
|
|
|
|
>
|
|
|
<
|







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
....
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
....
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
....
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
                          const char *proto, int *portPtr);
static void udpTrace(const char *format, ...);
static int  udpGetService(Tcl_Interp *interp, const char *service,
                          unsigned short *servicePort);
static Tcl_Obj *ErrorToObj(const char * prefix);
static int hasOption(int argc, CONST84 char * argv[],const char* option );
static int udpSetRemoteOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetMulticastIFOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetMulticastAddOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetMulticastDropOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpSetBroadcastOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpGetBroadcastOption(UdpState* statePtr, Tcl_Interp *interp, int* value);
static int udpSetMcastloopOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
static int udpGetMcastloopOption(UdpState *statePtr, Tcl_Interp *interp, unsigned char * value);
static int udpSetTtlOption(UdpState* statePtr, Tcl_Interp *interp, CONST84 char *newValue);
................................................................................
		"udp_conf fileId [-mcastadd] [-mcastdrop] groupaddr | "
#ifdef WIN32
		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif_index\" | "
#else
		"udp_conf fileId [-mcastadd] [-mcastdrop] \"groupaddr netwif\" | "
#endif
		"udp_conf fileId remotehost remoteport | "
		"udp_conf fileId -mcastif ipaddr | "
		"udp_conf fileId [-myport] [-remote] [-peer] [-mcastgroups] [-mcastloop] [-broadcast] [-ttl]";
	
	if (argc >= 2) {
		chan = Tcl_GetChannel(interp, (char *)argv[1], NULL);
		if (chan != (Tcl_Channel) NULL) {
			statePtr = (UdpState *) Tcl_GetChannelInstanceData(chan);
		}
................................................................................
	}
	
	if (argc == 4 && statePtr != NULL) {
		if (hasOption(argc,argv,"-mcastloop") ||
			hasOption(argc,argv,"-broadcast") ||
			hasOption(argc,argv,"-mcastadd") ||
			hasOption(argc,argv,"-mcastdrop") ||
			hasOption(argc,argv,"-mcastif") ||
			hasOption(argc,argv,"-ttl")) { 
			r = Tcl_SetChannelOption(interp, statePtr->channel, argv[2], argv[3]);
		} else {
			sprintf(remoteOptions, "%s %s",argv[2],argv[3] );
			r = Tcl_SetChannelOption(interp, statePtr->channel, "-remote", remoteOptions);
		}
	}
................................................................................
		freeaddrinfo(result);

		sendaddrv6.sin6_family = AF_INET6;
		sendaddrv6.sin6_port = statePtr->remoteport;

		written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddrv6, socksize);
	} else {
          socksize = sizeof(sendaddrv4);
          memset(&sendaddrv4, 0, socksize);
          struct in_addr remote_addr;

          if(inet_aton(statePtr->remotehost,&remote_addr)==0) {
            name = gethostbyname(statePtr->remotehost);
            if (name == NULL) {
              UDPTRACE("UDP error - gethostbyname");
              return -1;
            }
            memcpy(&sendaddrv4.sin_addr, name->h_addr, sizeof(sendaddrv4.sin_addr));
          } else {
            sendaddrv4.sin_addr=remote_addr;
          }
          sendaddrv4.sin_family = AF_INET;
          sendaddrv4.sin_port = statePtr->remoteport;

          written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddrv4, socksize);
	}

	if (written < 0) {
		UDPTRACE("UDP error - sendto");
		return -1;
	}

................................................................................
{
    UdpState *statePtr = (UdpState *)instanceData;
    CONST84 char * options = "remote mcastadd mcastdrop mcastloop broadcast ttl";
    int r = TCL_OK;
	
    if (!strcmp("-remote", optionName)) {
		r = udpSetRemoteOption(statePtr,interp,(const char *)newValue);
    } else if (!strcmp("-mcastif", optionName)) {
		r = udpSetMulticastIFOption(statePtr,interp,(const char *)newValue);                
    } else if (!strcmp("-mcastadd", optionName)) {
		r = udpSetMulticastAddOption(statePtr, interp, (const char *)newValue);		
    } else if (!strcmp("-mcastdrop", optionName)) {
		r = udpSetMulticastDropOption(statePtr, interp, (const char *)newValue);				
    } else if (!strcmp("-broadcast", optionName)) {
		r = udpSetBroadcastOption(statePtr, interp, (const char*) newValue);		
     } else if (!strcmp("-mcastloop", optionName)) {
................................................................................
	} else {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(newValue,-1));
	}

	return result;
}


/*
 * ----------------------------------------------------------------------
 * udpSetMulticastIFOption --
 *
 *  Specify the default gateway interface for multicast
 *
 * ----------------------------------------------------------------------
 */
static int
udpSetMulticastIFOption(UdpState *statePtr, Tcl_Interp *interp,CONST84 char *newValue)
{
  if (statePtr->ss_family == AF_INET) {
    struct in_addr interface_addr;
    if(inet_aton(statePtr->remotehost,&interface_addr)==0) {
      if (interp != NULL) {
        Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif (bad IP)"));
      }
      return TCL_ERROR;
    }
    if (setsockopt(statePtr->sock, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&interface_addr, sizeof(interface_addr)) < 0) {
      if (interp != NULL) {
        Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif"));
      }
      return TCL_ERROR;
    }		
  } else {
    struct in6_addr interface_addr;
    if(inet_pton(AF_INET6,statePtr->remotehost,&interface_addr)==0) {
      if (interp != NULL) {
        Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif (bad IP)"));
      }
      return TCL_ERROR;
    }
    if (setsockopt(statePtr->sock, IPPROTO_IP, IPV6_MULTICAST_IF, (const char*)&interface_addr, sizeof(interface_addr)) < 0) {
      if (interp != NULL) {
        Tcl_SetObjResult(interp, ErrorToObj("error setting -mcastif"));
      }
      return TCL_ERROR;
    }
  }
  return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 * udpSetMulticastAddOption --
 *
 *  Handle multicast add configuration requests.
 *
 * ----------------------------------------------------------------------