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.