add SAP/SDP support
authormichael <michael>
Sun, 2 Jul 2006 00:32:46 +0000 (00:32 +0000)
committermichael <michael>
Sun, 2 Jul 2006 00:32:46 +0000 (00:32 +0000)
Makefile
record-dvb.c
sap.c [new file with mode: 0644]
sap.h [new file with mode: 0644]

index e0ba4f3f9d3d08cb4a6605916094b2f82ed889ae..ad5e035041d4cc3baf947aabf92cf38eca350236 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CFLAGS =-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -g
 
-COMMONOBJS = http.o mcast.o common.o
+COMMONOBJS = http.o mcast.o sap.o common.o
 OBJS = record-dvb.o dump-mcast.o $(COMMONOBJS)
 
 all: record-dvb dump-mcast
index bb69447e7b72d9a101c244d739046f7f7a9e45db..d87d3e789ce362110c7161030ad1918e10398b12 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "http.h"
 #include "mcast.h"
+#include "sap.h"
 
 #define CHUNKSIZE      3000
 #define GTOD_INTERVAL  100
@@ -97,12 +98,20 @@ int main(int argc, char **argv)
                exit(EXIT_FAILURE);
        }
 
+       if (!is_http(url) && !is_mcast(url)) {
+               char *service_url;
+               if ((service_url = get_url_from_sap(url))) {
+                       printf("SAP says: '%s' -> %s\n", url, service_url);
+                       url = service_url;
+               }
+       }
+
        if (is_http(url)) {
                open_fn = &open_http;
        } else if (is_mcast(url)) {
                open_fn = &open_mcast;
        } else {
-               printf("URL %s not supported!\n", url);
+               printf("URL '%s' not supported!\n", url);
                exit(EXIT_FAILURE);
        }
 
diff --git a/sap.c b/sap.c
new file mode 100644 (file)
index 0000000..8dfa694
--- /dev/null
+++ b/sap.c
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>         
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <string.h>
+#include <strings.h>
+
+#include "mcast.h"
+#include "sap.h"
+
+#define SAP_ADDR       "224.2.127.254"
+#define SAP_PORT       9875
+#define SAP_MAX_SIZE   1024
+
+#define SAP_TIMEOUT    3
+
+#define BUFFSIZE       SAP_MAX_SIZE
+
+char *get_url_from_sap(char *service)
+{
+       struct timeval start, curr;
+       struct ip_mreq mreq;
+       unsigned char buffer[BUFFSIZE];
+       char *url = NULL;
+       int fd;
+
+       snprintf(buffer,BUFFSIZE,"udp://%s:%u", SAP_ADDR, SAP_PORT);
+
+       fd = open_mcast(buffer);
+
+       gettimeofday(&start, NULL);
+
+       do {
+               int recvd;
+               int sap_version, sap_addrtype, sap_messagetype, sap_encrypted, sap_compressed;
+               in_addr_t sender_address;
+               unsigned char auth_len;
+               unsigned short msgid;
+               unsigned char *payload, *pos, *host = NULL, *proto = NULL, *port = NULL, *sname = NULL;
+
+               if ((recvd = recv(fd, buffer, BUFFSIZE, 0)) < 1) {
+                       perror("recv");
+                       return NULL;
+               }
+
+               gettimeofday(&curr, NULL);
+
+               sap_version = (buffer[0] >> 5) & 0x7;
+               sap_addrtype = (buffer[0] >> 4) & 0x1;
+               sap_messagetype = (buffer[0] >> 2) & 0x1;
+               sap_encrypted = (buffer[0] >> 1) & 0x1;
+               sap_compressed = buffer[0] & 0x1;
+               auth_len = buffer[1];
+               msgid = buffer[2] << 8 | buffer[3];
+               memcpy(&sender_address, buffer+4, (sap_addrtype?16:4));
+               payload = buffer + 4 /* (sap_*, auth_len, msgid) */ + (sap_addrtype?16:4) + auth_len;
+
+#ifdef DEBUG
+               printf("\n");
+               printf("SAP-Version: %d\n", sap_version);
+               printf("Adresstyp: %s\n", (sap_addrtype?"IPv6":"IPv4"));
+               printf("Messagetype: %s\n", (sap_messagetype?"Announcement":"Deletion"));
+               printf("Encrypted: %d\n", sap_encrypted);
+               printf("Compressed: %d\n", sap_compressed);
+               printf("Authentication Length: %d\n", auth_len);
+               printf("Sender: %u\n", sender_address);
+               printf("Message Identifier Hash: %u\n", msgid);
+#endif
+
+               if (sap_addrtype)
+                       continue; /* We don't support IPv6 for now */
+
+#if 0 /* Getstream gets this wrong, see rfc2974 */
+               if (sap_messagetype)
+                       continue; /* We are not interested in deletions */
+#endif
+
+               if (sap_encrypted || sap_compressed)
+                       continue;
+               /* RFC 2327
+                * v=0
+                * o=- 6dca 1 IN IP4 192.168.100.17:2000
+                * s=TV Das Erste
+                * t=0 0
+                * c=IN IP4 192.168.100.17/1
+                * m=video 2000 http 33
+                * a=tool:getstream
+                * a=type:broadcast
+                */
+
+               pos = payload;
+               while(*pos != 0 && (pos-buffer) < BUFFSIZE) {
+                       if (*pos == 0x0d) {
+                               *pos = 0;
+                       }
+
+                       if (*pos == 0x0a) {
+                               *pos = 0;
+
+                               if (!strncasecmp("s=", payload, 2)) {
+                                       sname = payload + 2;
+                               } else if (!strncasecmp("c=", payload, 2)) {
+                                       int poscnt = 0;
+
+                                       payload += 2;
+                                       while (*payload != 0) {
+                                               if (poscnt == 2 && *payload == '/') {
+                                                       *payload = 0;
+                                                       break;
+                                               }
+
+                                               if (*payload == ' ') {
+                                                       *payload = 0;
+                                                       poscnt++;
+
+                                                       /* c=<network type> <address type> <connection address> */
+                                                       if (poscnt == 2) { 
+                                                               host = payload + 1;
+                                                       }
+
+                                                       if (poscnt > 2) {
+                                                               break;
+                                                       }
+                                               }
+                                               payload++;
+                                       }
+                               } else if (!strncasecmp("m=", payload, 2)) {
+                                       int poscnt = 0;
+
+                                       payload += 2;
+                                       while (*payload != 0) {
+                                               if (*payload == ' ') {
+                                                       *payload = 0;
+                                                       poscnt++;
+
+                                                       /* m=<media> <port> <transport> <fmt list> */
+                                                       if (poscnt == 1) { 
+                                                               port = payload + 1;
+                                                       }
+
+                                                       if (poscnt == 2) { 
+                                                               proto = payload + 1;
+                                                       }
+
+                                                       if (poscnt > 2) {
+                                                               break;
+                                                       }
+                                               }
+                                               payload++;
+                                       }
+                               }
+
+                               payload = ++pos;
+                               continue;
+                       }
+                       pos++;
+               }
+
+               if (sname && proto && port) {
+                       if (!host) {
+                                struct in_addr inaddr;
+
+                                inaddr.s_addr = sender_address;
+                                host = inet_ntoa(inaddr);
+                       }
+
+#ifdef DEBUG
+                       printf("%s -> %s://%s:%s\n", sname, proto, host, port);
+#endif
+
+                       if (strlen(service) < strlen(sname)) {
+                               sname += strlen(sname) - strlen(service);
+                       }
+
+                       if (!strncasecmp(service, sname, strlen(service))) {
+                               int len = strlen(host)+strlen(proto)+strlen(port)+5;
+
+                               if (!(url = malloc(len))) {
+                                       perror("malloc");
+                                       return NULL;
+                               }
+
+                               snprintf(url, len, "%s://%s:%s", proto, host, port);
+                               url[len-1] = 0;
+                               break;
+                       }
+               }
+
+       } while(curr.tv_sec < start.tv_sec+SAP_TIMEOUT);
+
+       mreq.imr_multiaddr.s_addr = inet_addr(SAP_ADDR);
+       mreq.imr_interface.s_addr = INADDR_ANY;
+       setsockopt (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
+
+       return url;
+}
diff --git a/sap.h b/sap.h
new file mode 100644 (file)
index 0000000..8bc599f
--- /dev/null
+++ b/sap.h
@@ -0,0 +1 @@
+char *get_url_from_sap(char *service);
Impressum, Datenschutz