[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference lassie::ucx

Title:DEC TCP/IP Services for OpenVMS
Notice:Note 2-SSB Kits, 3-FT Kits, 4-Patch Info, 7-QAR System
Moderator:ucxaxp.ucx.lkg.dec.com::TIBBERT
Created:Thu Nov 17 1994
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:5568
Total number of notes:21492

5217.0. "UCX 4.1 & Multicast IP application " by PADNOM::CHEMINANT () Wed Feb 12 1997 12:16

    
    A customer is complaining that UCX 4.1 multicast IP is not 
    compliant with the RFC 1112 :
    
     "If the sending host is itself a member of the destination 
      group on tghe outgoing interface, a copy of the outgoing 
      datagram must be looped-back for local delivery, unless 
      inhibited by the sender.(level 2 implementations only.)"
    
    He means that :
     . Running the multicast Client (sending a message) ,and 
       multicast Server (receiving the message) application 
       on the same node , the Server application is never
       receiving the multicast message !
     . Running the Client application on one UCX node, and the
       Server application on another UCX node, this one receives
       the multicast message.
    
     Any comment will be a appreciated.
     Thanks.
     Gait.
       
T.RTitleUserPersonal
Name
DateLines
5217.1Client & Server multicast ApplicationPADNOM::CHEMINANTWed Feb 12 1997 12:17335
    
    
    /* Please compile with symbol SERVER defined and after with symbol CLIENT */
/* if you run this program on different machines all is OK */
/* on the same machine we don't receive the  message */


#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unixlib.h>
#include <in.h>

#include <ssdef.h>
#include <iodef.h>
#include <descrip.h>
#include <ucx$inetdef.h>

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

#define OK(s) ((s&1) == 1)
#define SIGNAL(s) if(((status=s)&1 != 1) lib$signal(status)

typedef struct {
	short cond;
	short count;
	int specific;
	} IOSB_T;

typedef struct {
	unsigned int length;
	void *buffer;
	} ITLIST2_T;

typedef struct {
	unsigned int length;
	void *buffer;
	int *retlen;
	} ITLIST3_T;

typedef struct {
	unsigned short length;
	unsigned short code;
	void *buffer;
	} ITCLIST2_T;

assign(char *device, short *chan)
{
	$DESCRIPTOR(devdsc, "");

	devdsc.dsc$a_pointer = device;
	devdsc.dsc$w_length = strlen(device);

	return sys$assign(&devdsc, chan, 0, 0);
}

qiow(short chan, int func, void *p1,void *p2,void *p3,void *p4,void *p5,void *p6)
{
	IOSB_T iosb;
	int status;

	if(!OK(status=sys$qiow(0, chan, func, &iosb,0,0,p1,p2,p3,p4,p5,p6)))
	{
		printf("Cannot execute QIO (status=%d)\n", status);
		exit(0);
	}
	
	if(!OK(iosb.cond))
	{
		printf("QIO iosb error (status=%d)\n", iosb.cond);
		exit(0);
	}
	return iosb.count;	
}

setopt(short chan, int opt, int lev, void *optBuf, int bufLen)
{
	ITCLIST2_T itemlst_dsc[1];
	ITCLIST2_T item_dsc[1];

	itemlst_dsc[0].length = sizeof(ITCLIST2_T);
	itemlst_dsc[0].code = lev;
	itemlst_dsc[0].buffer = item_dsc;

	item_dsc[0].length = bufLen;
	item_dsc[0].code = opt;
	item_dsc[0].buffer = optBuf;

	qiow(chan, IO$_SETMODE, 0, 0, 0, 0, itemlst_dsc, 0);
}

snd(short chan, void *buffer, int *len)
{
	qiow(chan, IO$_WRITEVBLK, buffer, len, 0, 0, 0, 0);
}

sndto(short chan, void *buffer, int len, struct sockaddr_in *to)
{
	ITLIST2_T sockadd_dsc[2];

	sockadd_dsc[0].length = sizeof(struct sockaddr_in);
	sockadd_dsc[0].buffer = to;
	sockadd_dsc[1].length = 0;	

	qiow(chan, IO$_WRITEVBLK, buffer, len, sockadd_dsc, 0, 0, 0);
}

rcv(short chan, void *buffer, int len)
{
	return qiow(chan, IO$_READVBLK, buffer, len, 0, 0, 0, 0);
}

rcvfrom(short chan, void *buffer, int len, struct sockaddr_in *from)
{
	ITLIST3_T sockadd3_dsc[2];
	int aLen;

	sockadd3_dsc[0].length = sizeof(struct sockaddr_in);
	sockadd3_dsc[0].buffer = from;
	sockadd3_dsc[0].retlen = &aLen;
	sockadd3_dsc[1].length = 0;

	return qiow(chan, IO$_WRITEVBLK, buffer, len, sockadd3_dsc, 0, 0, 0);
}

setMulticast(short chan, struct in_addr *aBuffer, int val)
{
	struct ip_mreq {
		struct in_addr group;
		struct in_addr interface;
		} mreq;
	int opt;

	memcpy(&mreq.group, aBuffer, sizeof(struct in_addr));
	mreq.interface.s_addr = INADDR_ANY;
	opt = val? UCX$C_IP_ADD_MEMBERSHIP: UCX$C_IP_DROP_MEMBERSHIP;

	setopt(chan, opt, IPPROTO_IP, &mreq, sizeof(mreq));
}

struct sockaddr_in *makeNameOf(char *host, char *service,
		char *protocol, struct sockaddr_in *name)
{
	struct servent *pse;
	struct hostent *phe;

	memset(name, 0, sizeof(struct sockaddr_in));
	name->sin_family = AF_INET;

	/* map service name to port number */
	if(service != NULL)
	{
	  if(!(name->sin_port=htons((u_short)atoi(service))))
	    if(pse=getservbyname(service, protocol))
		name->sin_port = htons(ntohs((u_short)pse->s_port));
	    else
	    {
		printf("Cannot get \"%s\" service entry\n", service);
		return NULL;
	    }
	}

	/* map host name to IP address, allowing for dotted decimal */
	if(!(host == NULL))
	{
	  if(phe=gethostbyname(host))
		memcpy((char *)&name->sin_addr, phe->h_addr, phe->h_length);
	  else if( (name->sin_addr.s_addr=inet_addr(host)) == INADDR_NONE)
	  {
		printf("Cannot get \"%s\" host entry\n", host);
		return NULL;
	  }
	}
	return name;
}

short *createPassive(char *service, char *protocol)
{
	struct protoent *ppe;
	struct servent *pse;
	int type;
	short sockdef_dsc[2];
	ITLIST2_T sockadd_dsc[2];
	struct sockaddr_in name;
	int status;
	short chan;

	memset((char *)&name, 0, sizeof(struct sockaddr_in));
	name.sin_family = AF_INET;
	name.sin_addr.s_addr = INADDR_ANY;

	/* map service name to port number */
	if(!(name.sin_port=htons((u_short)atoi(service))))
	  if(pse=getservbyname(service, protocol))
		name.sin_port = htons(ntohs((u_short)pse->s_port));
	  else
	  {
		printf("Cannot get \"%s\" service entry\n", service);
		exit(0);
	  }

	/* map protocol name to protocol number */
	if(!(ppe=getprotobyname(protocol)))
	{
		printf("Cannot get \"%s\" protocol entry\n", protocol);
		exit(0);
	}

	/* choose a socket type */
	if(!strcmp(protocol, "udp")) type = SOCK_DGRAM;
	else type = SOCK_STREAM;

	/* allocate, bind socket and put in passive state */
	if(!OK(status=assign("UCX$DEVICE", &chan)))
	{
	  printf("Cannot assign to UCX (status=%d)\n", status);
	  exit(0);
	}

	sockdef_dsc[0] = ppe->p_proto;
	sockdef_dsc[1] = type;
	sockadd_dsc[0].length = sizeof(struct sockaddr_in);
	sockadd_dsc[0].buffer = (char *)&name;
	sockadd_dsc[1].length = 0;	

	qiow(chan, IO$_SETMODE, sockdef_dsc, 0, sockadd_dsc, 0, 0, 0);

	return chan;
}

short *createActive(char *service, char *host, char *protocol)
{
	struct protoent *ppe;
	int type;
	short sockdef_dsc[2];
	ITLIST2_T sockadd_dsc[2];
	ITLIST2_T sockloc_dsc[2];
	struct sockaddr_in locname, name;
	int status;
	short chan;

	/* make local name */
	if(makeNameOf(NULL, service, protocol, &locname) == NULL)
	{
	  printf("Cannot make name of local host, %s, %s\n",
							service, protocol);
	  exit(0);
	}

	/* make inet name */
	if(makeNameOf(host, service, protocol, &name) == NULL)
	{
	  printf("Cannot make name of remote host, %s, %s\n",
							service, protocol);
	  exit(0);
	}

	/* map protocol name to protocol number */
	if(!(ppe=getprotobyname(protocol)))
	{
		printf("Cannot get \"%s\" protocol entry\n", protocol);
	  	exit(0);
	}

	/* choose a socket type */
	if(!strcmp(protocol, "udp")) type = SOCK_DGRAM;
	else type = SOCK_STREAM;

	/* allocate and connect socket */
	if(!OK(status=assign("UCX$DEVICE", &chan)))
	{
	  printf("Cannot assign to UCX (status=%d)\n", status);
	  exit(0);
	}

	sockdef_dsc[0] = ppe->p_proto;
	sockdef_dsc[1] = type;
	sockloc_dsc[0].length = sizeof(struct sockaddr_in);
	sockloc_dsc[0].buffer = &locname;
	sockloc_dsc[1].length = 0;
	sockadd_dsc[0].length = sizeof(struct sockaddr_in);
	sockadd_dsc[0].buffer = &name;
	sockadd_dsc[1].length = 0;

	qiow(chan, IO$_SETMODE, sockdef_dsc, 0, sockloc_dsc, 0, 0, 0);
	return chan;
}

#ifdef CLIENT
main()
{
struct sockaddr_in multicastName;
short activeChan, passiveChan;


	if(makeNameOf("224.10.10.10", "5000", "udp", &multicastName)==NULL)
	{
		printf("Cannot create multicast name\n");
		exit(0);
	}
	activeChan = createActive(NULL, NULL, "udp");
	sndto(activeChan, "multicast", strlen("multicast"), &multicastName);
}
#endif

#ifdef SERVER
main()
{
struct sockaddr_in multicastname;
short activeChan, passiveChan;
struct in_addr multicast;
char buffer[256];
int len;

	if(makeNameOf("224.10.10.10", "5000", "udp", &multicastname)==NULL)
	{
		printf("Cannot create multicast name\n");
		exit(0);
	}
	passiveChan = createPassive("5000", "udp");
	multicast.s_addr=inet_addr("224.10.10.10");
	setMulticast(passiveChan, &multicast, 1);
	while(1)
	{
		len = rcv(passiveChan, buffer, strlen("multicast"));
		buffer[len] = 0;
		printf("Received %s\n", buffer);
	}
}
#endif