};
static struct { struct inqnode *head, *tail; } inq;
-static int sdev;
+static int master, sdev;
static time_t now;
+static void usageerr(const char *m) {
+ fprintf(stderr,"bad usage: %s\n",m);
+ exit(12);
+}
+
+static void bindmaster(const char *bindname) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_un sun;
+ } su;
+ socklen_t sulen;
+ const char *colon;
+ char *copy, *ep;
+ int r;
+ unsigned long portul;
+ struct hostent *he;
+ struct servent *se;
+
+ memset(&su,0,sizeof(su));
+
+ if (bindname[0]=='/' || bindname[0]=='.') {
+
+ if (strlen(bindname) >= sizeof(su.sun.sun_path))
+ usageerr("AF_UNIX bind path too long");
+ sulen= sizeof(su.sun);
+ su.sun.sun_family= AF_UNIX;
+ strcpy(su.sun.sun_path, bindname);
+
+ } else if (bindname[0] != ':' && (colon= strrchr(bindname,':'))) {
+
+ sulen= sizeof(su.sin);
+ su.sin.sin_family= AF_INET;
+
+ copy= xmalloc(colon - bindname + 1);
+ memcpy(copy,bindname, colon - bindname + 1);
+ copy[colon - bindname]= 0;
+ portul= strtoul(colon+1,&ep,0);
+
+ if (!*ep) {
+ if (!portul || portul>=65536) usageerr("invalid port number");
+ su.sin.sin_port= htons(portul);
+ } else {
+ se= getservbyname(colon+1, "tcp");
+ if (!se) { fprintf(stderr,"unknown service `%s'\n",colon+1); exit(4); }
+ su.sin.sin_port= htons(se->s_port);
+ }
+
+ if (!strcmp(copy,"any")) {
+ su.sin.sin_addr.s_addr= INADDR_ANY;
+ } else if (!inet_aton(copy,&su.sin.sin_addr)) {
+ he= gethostbyname(copy);
+ if (!he) { herror(copy); exit(4); }
+ if (he->h_addrtype != AF_INET ||
+ he->h_length != sizeof(su.sin.sin_addr) ||
+ !he->h_addr_list[0] ||
+ he->h_addr_list[1]) {
+ fprintf(stderr,"hostname lookup `%s' did not yield"
+ " exactly one IPv4 address\n",copy);
+ exit(4);
+ }
+ memcpy(&su.sin.sin_addr, he->h_addr_list[0], sizeof(su.sin.sin_addr));
+ }
+
+ } else {
+ usageerr("unknown bind name");
+ exit(12);
+ }
+
+ master= socket(su.sa.sa_family,SOCK_STREAM,0);
+ if (master<0) { perror("socket"); exit(8); }
+
+ r= bind(master, &su.sa, sulen);
+ if (r) { perror("bind"); exit(8); }
+
+ r= listen(master, 5);
+ if (r) { perror("listen"); exit(8); }
+}
+
static void opensounddevice(void) {
int r;
char cbuf[200];
r= system(cbuf); if (r) { fprintf(stderr,"sox gave %d\n",r); exit(5); }
}
+void wrbuf_report(const char *m) {
+ printf("writing %s\n", m);
+}
+
static void selectcopy(void) {
int slave= inq.head ? inq.head->fd : -1;
wrbufcore_prepselect(slave, sdev);
- FD_SET(0,&readfds);
+ fdsetset(master,&readfds);
callselect();
wrbufcore_afterselect(slave, sdev);
}
for (searchold= inq.head ? inq.head->next : 0;
searchold;
searchold= nextsearchold) {
- nextsearchold= searchold;
+ nextsearchold= searchold->next;
if (searchold->accepted < now-maxstartdelay) {
printf("expired %p\n",searchold);
LIST_UNLINK(inq,searchold);
int slave;
struct inqnode *new;
- if (!FD_ISSET(0,&readfds)) return;
+ if (!FD_ISSET(master,&readfds)) return;
- slave= accept(0,0,0);
+ slave= accept(master,0,0);
if (slave < 0) {
if (!(errno == EINTR ||
errno == EAGAIN ||
int main(int argc, const char *const *argv) {
assert(argv[0]);
- if (argv[1]) { fputs("no arguments allowed\n",stderr); exit(12); }
+ if (!argv[1] || argv[2] || argv[1][0]=='-')
+ usageerr("no options allowed, must have one argument (bindname)");
buffersize= 44100*4* 5/*seconds*/;
opensounddevice();
+ bindmaster(argv[1]);
nonblock(sdev,1);
- nonblock(0,1);
+ nonblock(master,1);
startupcore();
wrbufcore_startup();
#include "rwbuffer.h"
static size_t waitfill;
-static int writing;
+
+int writing;
void wrbufcore_startup(void) {
waitfill= (buffersize*3)/4;
writing=0;
+ maxselfd=0;
+}
+
+void fdsetset(int fd, fd_set *set) {
+ FD_SET(fd,set);
+ if (fd >= maxselfd) maxselfd= fd+1;
}
void wrbufcore_prepselect(int rdfd, int wrfd) {
FD_ZERO(&readfds);
- if (rdfd>=0 && !seeneof && used+1<buffersize) FD_SET(rdfd,&readfds);
-
+ if (rdfd>=0 && !seeneof && used+1<buffersize) fdsetset(rdfd,&readfds);
+
FD_ZERO(&writefds);
- if (writing) FD_SET(wrfd,&writefds);
+ if (writing) fdsetset(wrfd,&writefds);
}
void wrbufcore_afterselect(int rdfd, int wrfd) {
if (FD_ISSET(wrfd,&writefds) &&
!(rdfd>=0 && FD_ISSET(rdfd,&readfds)) &&
!used) {
+ wrbuf_report("stopping");
writing= 0;
FD_CLR(wrfd,&writefds);
}
r= read(rdfd,rp,min(buffersize-1-used,buf+buffersize-rp));
if (!r) {
seeneof=1; writing=1;
+ wrbuf_report("seeneof");
} else if (r<0) {
if (!(errno == EAGAIN || errno == EINTR)) { perror("read"); exit(1); }
} else {
rp+= r;
if (rp == buf+buffersize) rp=buf;
}
- if (used > waitfill) writing=1;
+ if (used > waitfill) {
+ if (!writing) wrbuf_report("starting");
+ writing=1;
+ }
}
if (FD_ISSET(wrfd,&writefds) && used) {