From: michael Date: Sat, 1 Jul 2006 18:07:29 +0000 (+0000) Subject: implement (probably working) multicast X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/record-dvb/commitdiff_plain/fbc24ab023eb1ae6572fccff3fa1140c3e01c8b7?hp=cda833b266970ebc861d5e84779f13571b05834e implement (probably working) multicast --- diff --git a/common.c b/common.c index 97ec807..80327f5 100644 --- a/common.c +++ b/common.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include "common.h" @@ -62,3 +65,28 @@ struct dvb_host *parse(char *urlpart, char *defport) return dvbhost; } + +int resolve(struct dvb_host *dvbhost, struct sockaddr_in *server) +{ + struct addrinfo *s_addrinfo, addrhints; + int res; + + bzero(&addrhints, sizeof(struct addrinfo)); + addrhints.ai_family = PF_INET; + addrhints.ai_socktype = dvbhost->socktype; + + if ((res = getaddrinfo(dvbhost->hostname, dvbhost->port, &addrhints, &s_addrinfo))) { + fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(res)); + return -1; + } + + bzero(server, sizeof(struct sockaddr_in)); + server->sin_family = AF_INET; + server->sin_addr.s_addr = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_addr.s_addr; + server->sin_port = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_port; + + freeaddrinfo(s_addrinfo); + + return 0; +} + diff --git a/common.h b/common.h index 5f7b1f8..b7015da 100644 --- a/common.h +++ b/common.h @@ -2,6 +2,8 @@ struct dvb_host { char *hostname; char *port; char *location; + int socktype; }; struct dvb_host *parse(char *urlpart, char *defport); +int resolve(struct dvb_host *dvbhost, struct sockaddr_in *server); diff --git a/http.c b/http.c index 65c1238..ca756bd 100644 --- a/http.c +++ b/http.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "common.h" #include "http.h" @@ -28,22 +27,19 @@ int open_http(char *url) { int fd; struct sockaddr_in server; - struct dvb_host *dvbhost; - struct addrinfo *s_addrinfo, addrhints; + static struct dvb_host *dvbhost = NULL; char buffer[BUFFSIZE]; int i; if(!is_http(url)) return -1; - dvbhost = parse(&(url[7]), "80"); - - bzero(&addrhints, sizeof(struct addrinfo)); - addrhints.ai_family = PF_INET; - addrhints.ai_socktype = SOCK_STREAM; + if (!dvbhost) { + dvbhost = parse(&(url[7]), "80"); + dvbhost->socktype = SOCK_STREAM; + } - if ((i = getaddrinfo(dvbhost->hostname, dvbhost->port, &addrhints, &s_addrinfo))) { - fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(i)); + if (resolve(dvbhost, &server) < 0) { return -1; } @@ -52,19 +48,11 @@ int open_http(char *url) return -1; } - bzero(&server, sizeof(struct sockaddr_in)); - server.sin_family = AF_INET; - server.sin_addr.s_addr = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_addr.s_addr; - server.sin_port = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_port; - if (connect(fd, (struct sockaddr*) &server, sizeof(server)) < 0) { perror("connect"); return -1; } - freeaddrinfo(s_addrinfo); - - snprintf(buffer, BUFFSIZE-1, "GET /%s HTTP/1.0\n\n",dvbhost->location); buffer[BUFFSIZE-1] = 0; send(fd, buffer, strlen(buffer), 0); diff --git a/mcast.c b/mcast.c index e328932..5f7dadc 100644 --- a/mcast.c +++ b/mcast.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include "common.h" #include "mcast.h" @@ -19,16 +22,41 @@ int is_mcast(char *url) int open_mcast(char *url) { - struct dvb_host *dvbhost; + static struct dvb_host *dvbhost = NULL; + struct sockaddr_in server; + struct ip_mreq mreq; int fd; if(!is_mcast(url)) return -1; - dvbhost = parse(&(url[6]), "2000"); + if (!dvbhost) { + dvbhost = parse(&(url[6]), "2000"); + dvbhost->socktype = SOCK_DGRAM; + } - fprintf(stderr,"multicast currently unimplemented!\n"); - return -1; + if (resolve(dvbhost, &server) < 0) { + return -1; + } + + bzero(&mreq, sizeof(mreq)); + mreq.imr_multiaddr = server.sin_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + return -1; + } + + if (bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { + perror("bind"); + return -1; + } + + if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + perror("setsockopt"); + return -1; + } return fd; } diff --git a/record-dvb.c b/record-dvb.c index d32eba1..b27ce74 100644 --- a/record-dvb.c +++ b/record-dvb.c @@ -40,7 +40,8 @@ void record(int(*open_fn)(char *), char *url, char *outfile, int duration) do { if ((bytes = recv(in, buffer, CHUNKSIZE, 0)) < 1) { /* TODO: Insert better connection-loss recovery here */ - in = (*open_fn)(url); + if ((in = (*open_fn)(url)) < 0) + sleep(1); } written = 0; do {