chiark / gitweb /
mcastsoundd wip
authorianmdlvl <ianmdlvl>
Sun, 15 May 2005 20:27:39 +0000 (20:27 +0000)
committerianmdlvl <ianmdlvl>
Sun, 15 May 2005 20:27:39 +0000 (20:27 +0000)
cprogs/mcastsoundd.c

index 499bae46aa93080d2dba8f8467d5461efec67c1d..8a8c67010de2c7bffb37f24e5a025e094d30210a 100644 (file)
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "myopt.h"
+
 typedef unsigned char Byte;
 
+static int ov_mode= 'r';
+static const char *ov_requ=  "127.0.0.1";
 static const char *ov_mcast= "239.193.27.221";
+
+static int ov_port_requ= 4101;
 static int ov_port_ctrl= 4101;
 static int ov_port_data= -1;
 
-static int mcast_fd;
-static struct sockaddr_in mcast_sa;
+static const struct cmdinfo cmdinfos[]= {
+  { "server",     0, &ov_mode,0,0, 's' },
+  { "player",     0, &ov_mode,0,0, 'p' },
+  { "request",    0, &ov_mode,0,0, 'r' },
+  { "mcast-addr", 1, 0,&ov_mcast },
+  { "requ-addr",  1, 0,&ov_requ },
+  { "requ-port",  1, &ov_port_requ },
+  { "ctrl-port",  1, &ov_port_ctrl },
+  { "data-port",  1, &ov_port_data },
+  0
+};
+
+
+static int mcast_fd, requ_fd;
+static struct sockaddr_in requ_sa, ctrl_sa, data_sa;
 
 static void sysfail(const char *m) { perror(m); exit(16); }
 
 static Byte packet[1024];
 static int packet_len;
 
+/*---------- marshalling ----------*/
+
 static uint64_t htonll(uint64_t v) {
 #if LITTLE_ENDIAN
   return (v >> 32) | (v << 32);
@@ -129,6 +150,8 @@ MARS
 #undef FR0
 #undef MAR
 
+/*---------- general stuff ----------*/
+
 static void nonblock(int fd) {
   int r;
   r= fcntl(fd,F_GETFL);  if (r<0) sysfail("nonblock fcntl F_GETFL");
@@ -146,12 +169,40 @@ static void blocksignals(int how) {
   if (r) sysfail("sigprocmask");
 }
 
+static int mksocket(int type, int proto,
+                   const struct sockaddr_in *sa, const char *what) {
+  int fd, r;
+
+  fd= socket(PF_INET, type, proto);
+  if (fd<0) sysfail("socket %s",what);
+
+  r= bind(fd, (struct sockaddr*)&mcast_sa, sizeof(*sa));
+  if (r) sysfail("bind %s",what);
+
+  return fd;
+}
+
+static void mkmcastrecv(const struct sockaddr_in *sa, const char *what) {
+  struct ip_mreq mreq;
+  int r;
+
+  mcast_fd= mksocket(SOCK_DGRAM, IPPROTO_UDP, sa, what);
+
+  mreq.imr_multiaddr= sa->sin_addr;
+  mreq.imr_interface.s_addr= INADDR_ANY;
+  r= setsockopt(mcast_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+  if (r) sysfail("add mcast membership %s", what);
+}
+
+/*---------- player ----------*/
+
 static void recvd_play(void) {
   Mar_CTRL_PLAY pkt;
   int r;
 
   r= unmar_CTRL_PLAY(&pkt);
   if (r) { fprintf(stderr,"bad PLAY packet\n"); return; }
+  
 }
 
 static void recvd_stop(void) {
@@ -165,23 +216,11 @@ static void recvd_stop(void) {
 static void player(void) {
   struct sockaddr_in peer_sa, old_peer_sa;
   socklen_t peer_salen;
-  struct ip_mreq mreq;
   int r;
-  
-  memset(&old_peer_sa, 0, sizeof(old_peer_sa));
-
-  mcast_fd= socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-  if (mcast_fd<0) sysfail("mcast_fd socket");
-
-  r= bind(mcast_fd, (struct sockaddr*)&mcast_sa, sizeof(mcast_sa));
-  if (r) sysfail("mcast_fd bind");
 
-  mcast_sa.sin_port= htons(ov_port_ctrl);
+  mkmcastrecv(&ctrl_sa, "ctrl");
   
-  mreq.imr_multiaddr= mcast_sa.sin_addr;
-  mreq.imr_interface.s_addr= INADDR_ANY;
-  r= setsockopt(mcast_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-  if (r) sysfail("mcast_fd add memb");
+  memset(&old_peer_sa, 0, sizeof(old_peer_sa));
 
   for (;;) {
     peer_salen= sizeof(peer_sa);
@@ -229,16 +268,55 @@ static void player(void) {
   }
 }
 
-int main(int argc, const char *const *argv) {
+/*---------- server ----------*/
+
+void server(void) {
+  requ_fd= mksocket(SOCK_STREAM, IPPROTO_TCP, &requ_sa, "requ");
+  
+
+/*---------- main ----------*/
+
+static void argaddr(struct sin_addr *sa, const char *addr_name, int port) {
+  memset(sa,0,sizeof(*sa));
+  sa->sin_family= AF_INET;
+  
+  r= inet_aton(ov_mcast, &mcast_sa.sin_addr);
+  if (!r) badusage("invalid addr `%s'", addr_name);
+
+  if (port<0 || port>65536) badusage("invalid port %d",port);
+
+  sa->sin_port= htons(port);
+}
+
+int main(int argc, const char **argv) {
   int r;
 
   if (ov_port_data < 0) ov_port_data= ov_port_ctrl+1;
+  myopt(&argv, cmdinfos);
+
+  argaddr(&requ_sa, ov_requ,  ov_requ_port);
+  argaddr(&ctrl_sa, ov_mcast, ov_ctrl_port);
+  argaddr(&data_sa, ov_data,  ov_data_port);
 
-  memset(&mcast_sa,0,sizeof(mcast_sa));
-  mcast_sa.sin_family= AF_INET;
-  r= inet_aton(ov_mcast, &mcast_sa.sin_addr);  assert(r);
+  if (argv[1] && ov_mode != 'p')
+    badusage("mode takes no non-option arguments");
+
+  switch (ov_mode) {
+  case 'p':
+    player();
+    break;
+  case 's':
+    server();
+    break;
+  case 'r':
+    if (!argv[1] || argv[2])
+      badusage("play-requester takes one non-option argument");
+    request(argv[1]);
+    break;
+  default:
+    abort();
+  }
 
-  player();
   nonblock(0);
   mar_CTRL_PLAY(0);
   mar_CTRL_STOP(0);