#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);
#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");
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) {
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);
}
}
-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);