ftp.nice.ch/pub/next/unix/network/conferences/radio.1p3.s.tar.gz#/radio/broadcast.c

This is broadcast.c in view mode; [Download] [Up]

/***********************************************************
Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
Netherlands.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.

STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

******************************************************************/

/* Broadcast audio packets over UPD.
   Standard input should be an audio source, e.g., /dev/audio,
   or -- at CWI -- a pipeline like "rsh voorn ~guido/tmp/ship2sun".

   Command line options:

   -b ipaddr	IP address to broadcast to; may be repeated
		(default broadcast on local net)
   -p port	broadcast to this port number (default 54321)
   -c port	listen to this control port (default 54319)
   -t           time output; use when input is faster than realtime
		(e.g., read from a file file)
*/

#ifdef sun
#define SUNHACKS /* define this for SunOS */
#endif

#define BCASTCTLPORT      54319
#define RADIOCTLPORT      54320
#define RCVPORT           54321
#define SENDPORT          54318

#define BUFFERSIZE        1400
#define CTLPKTSIZE        100

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>

#ifdef SUNHACKS
#include <sys/sockio.h>		/* For SIOCGIF* */
#include <net/if.h>		/* For struct if* */
#endif

#ifdef REMHDR
#include <multimedia/libaudio.h>
#include <multimedia/audio_filehdr.h>
#endif

#ifdef NeXT
#include <sound/sound.h>
#endif

extern int optind;
extern char * optarg;

char *progname;
char infostring[100];
struct timeval zerotime;
struct timeval tstart;
int pdebug = 0;

#define NBCADDR 10		/* Max number of broadcast addresses */
int nbcaddr = 0;		/* Number of broadcast address options */
struct sockaddr_in bcaddr[NBCADDR];	/* Broadcast addresses */

#ifdef NeXT
char *cuserid( char *sp)
{
  static char buf[10];
         char *ssp;

  if( ( ssp = (char *)getlogin()) == NULL && sp != NULL) {
    *sp = '\0';
    return ssp; /* ?? */
  }
  if( sp == NULL)
    sp = buf;

  if( ssp == NULL)
    *sp = '\0';
  else
    strncpy( sp, ssp, 10);

  return sp;
}
#endif

main(argc, argv)
	int argc;
	char **argv;
{
	int port = RCVPORT;
	char *broadcastaddr = NULL;
	char buf[BUFFERSIZE];
	int on = 1;
	int i;
	int s, ctls;
	int c;
	int timing = 0;
	fd_set inputav;
	struct sockaddr_in locsin;
	struct sockaddr_in ctlsin;
	int ctlsinsize;
	int ctlport = BCASTCTLPORT;

	progname = argv[0];

/* Always change these two macros together! */
#define OPTIONS "b:p:c:dt"
#define USAGE	"usage: %s [-d] [-t] [-p port] [-c ctlport] [-b broadcastaddr] ...\n"

	while ((c = getopt(argc, argv, OPTIONS)) != EOF) {
		switch (c) {
		case '?':
			fprintf(stderr, USAGE, progname);
			exit(2);
		case 'b':
			if (nbcaddr >= NBCADDR) {
				fprintf(stderr,
					"%s: too many -b options (max %d)\n",
					progname, NBCADDR);
				exit(2);
			}
			if (setipaddr(optarg, &bcaddr[nbcaddr]) < 0) {
				fprintf(stderr,
					"%s: bad broadcast address '%s'\n",
					progname, broadcastaddr);
				exit(2);
			}
			nbcaddr++;
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 't':
			timing = 1;
			break;
		case 'd':
			pdebug = 1;
			break;
		case 'c':
			ctlport = atoi(optarg);
			break;
		}
	}


	s = opensock("data", (char *)NULL, SENDPORT, (char *)NULL, 0, 1);

	if (nbcaddr == 0) {
		configure(s, &bcaddr[0]);
		nbcaddr = 1;
	}

	for (i = 0; i < nbcaddr; i++) {
		bcaddr[i].sin_port = htons(port);
		bcaddr[i].sin_family = AF_INET;
	}

	sprintf(infostring, "radio:S:%s:%d", cuserid(0), port);

	ctls = opensock("control", (char *)NULL, ctlport, (char *)NULL, 0, 0);

	if(timing) {
#ifdef REMHDR
		Audio_hdr hp;
		(void) audio_read_filehdr(0, &hp, NULL, NULL);
#endif
#ifdef NeXT
		SNDSoundStruct s;

		(void) fread((void *)&s, sizeof(SNDSoundStruct), 1, stdin);

#endif
		gettimeofday(&tstart, 0);
	}

	for (;;) {
		int n = fread(buf, 1, BUFFERSIZE, stdin);
		if (n <= 0) {
			if (n < 0)
				perror("fread");
			break;
		}
		for (i = 0; i < nbcaddr; i++) {
			if(timing) {
				waiting(8000, BUFFERSIZE);
			}
			if (sendto(s, buf, n, 0,
				   &bcaddr[i], sizeof bcaddr[i]) != n) {
				perror("sendto");
				break;
			} 
		}
		if (pdebug) {
        	if(pdebug == 8) {
               		fprintf(stderr,"8 packets sent\n");
                        pdebug = 1;
                } else
                        pdebug++;
        }
		if (ctls >= 0) {
			FD_ZERO(&inputav);
			FD_SET(ctls, &inputav);
			if (select(ctls+1, &inputav, 0, 0, &zerotime) == 1) {
				ctlsinsize = sizeof(ctlsin);
				n = recvfrom(ctls, buf, BUFFERSIZE, 0,
					     &ctlsin, &ctlsinsize);
				if (n < 0) {
					perror("recvfrom");
					exit(1);
				}
				if (n >= 7 &&
				    strncmp(buf, "radio:s", 7) == 0) {
					sendto(ctls, infostring,
					       strlen(infostring), 0,
					       &ctlsin, ctlsinsize);
				}
				else {
					fprintf(stderr,
						"%s: Funny ctl message\n",
						progname);
				}
			}
		}
	}

	exit(0);
}

configure(s, addr_ret)
	int s;
	struct sockaddr_in *addr_ret;
{
#ifdef SUNHACKS
	char buf[BUFSIZ];
	struct ifconf ifc;
	struct ifreq ifreq;

	ifc.ifc_len = sizeof(buf);
	ifc.ifc_buf = buf;
	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
		perror("ioctl SIOCGIFCONF");
		exit(1);
	}
	ifreq = *ifc.ifc_req;
	if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
		perror("ioctl SIOCGIFBRDADDR");
		exit(1);
	}
	* (struct sockaddr *) addr_ret = ifreq.ifr_broadaddr;
#else
	addr_ret->sin_addr.s_addr = INADDR_BROADCAST;
#endif
}

/*
 * routine to sleep between consecutive packets
 */

waiting(rate, data)
	int rate;
	int data;
{
	static int bytes = 0; /* packets already sent */

	struct timeval tnow;
	int tsleep;

	bytes += data;
	gettimeofday(&tnow, 0);

	tsleep =  ((double) bytes/(double) rate) * 1000000
		- ((tnow.tv_sec - tstart.tv_sec) * 1000000
                    + tnow.tv_usec - tstart.tv_usec);
	if (tsleep > 0) {
		struct timeval t;

		t.tv_sec = tsleep / 1000000;
		t.tv_usec = tsleep % 1000000;
		(void) select(0, NULL, NULL, NULL, &t);
	}
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.