|
/* 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
|