]>
cvs.zerfleddert.de Git - record-dvb/blob - sap.c
4 #include <sys/socket.h>
5 #include <netinet/in.h>
12 #include <sys/select.h>
17 #define SAP_ADDR "224.2.127.254"
19 #define SAP_MAX_SIZE 1024
23 #define BUFFSIZE SAP_MAX_SIZE
32 struct sdp_info
*parse_sdp(char *sdp
, int len
)
35 static struct sdp_info sdpinfo
;
39 * o=- 6dca 1 IN IP4 192.168.100.17:2000
42 * c=IN IP4 192.168.100.17/1
43 * m=video 2000 http 33
48 bzero(&sdpinfo
, sizeof(struct sdp_info
));
51 while(*pos
!= 0 && (pos
-sdp
) < len
) {
58 if (!strncasecmp("s=", line
, 2)) {
59 sdpinfo
.service
= line
+ 2;
60 } else if (!strncasecmp("c=", line
, 2)) {
65 if (poscnt
== 2 && *line
== '/') {
74 /* c=<network type> <address type> <connection address> */
76 sdpinfo
.host
= line
+ 1;
83 } else if (!strncasecmp("m=", line
, 2)) {
92 /* m=<media> <port> <transport> <fmt list> */
94 sdpinfo
.port
= line
+ 1;
97 sdpinfo
.proto
= line
+ 1;
116 char *get_url_from_sap(char *service
)
118 struct timeval start
, curr
;
120 unsigned char buffer
[BUFFSIZE
];
121 struct in_addr sapinaddr
;
125 snprintf(buffer
,BUFFSIZE
,"udp://%s:%u", SAP_ADDR
, SAP_PORT
);
127 fd
= open_mcast(buffer
);
129 gettimeofday(&start
, NULL
);
136 int sap_version
, sap_addrtype
, sap_messagetype
, sap_encrypted
, sap_compressed
;
137 uint8_t sender_address
[16]; /* This might be IPv6! */
138 unsigned char auth_len
;
139 unsigned short msgid
;
141 struct sdp_info
*sdpinfo
;
149 if ((retval
= select(fd
+1, &rfds
, NULL
, NULL
, &tv
)) == -1) {
155 gettimeofday(&curr
, NULL
);
159 bzero(buffer
, BUFFSIZE
);
160 if ((recvd
= recv(fd
, buffer
, BUFFSIZE
, 0)) < 1) {
165 gettimeofday(&curr
, NULL
);
167 sap_version
= (buffer
[0] >> 5) & 0x7;
168 sap_addrtype
= (buffer
[0] >> 4) & 0x1;
169 sap_messagetype
= (buffer
[0] >> 2) & 0x1;
170 sap_encrypted
= (buffer
[0] >> 1) & 0x1;
171 sap_compressed
= buffer
[0] & 0x1;
172 auth_len
= buffer
[1];
173 msgid
= buffer
[2] << 8 | buffer
[3];
174 memcpy(sender_address
, buffer
+4, (sap_addrtype
?16:4));
175 sdp
= buffer
+ 4 /* (sap_*, auth_len, msgid) */ + (sap_addrtype
?16:4) + auth_len
;
179 printf("SAP-Version: %d\n", sap_version
);
180 printf("Adresstyp: %s\n", (sap_addrtype
?"IPv6":"IPv4"));
181 printf("Messagetype: %s\n", (sap_messagetype
?"Announcement":"Deletion"));
182 printf("Encrypted: %d\n", sap_encrypted
);
183 printf("Compressed: %d\n", sap_compressed
);
184 printf("Authentication Length: %d\n", auth_len
);
185 printf("Sender: %u\n", *((in_addr_t
*)sender_address
));
186 printf("Message Identifier Hash: %u\n", msgid
);
189 #if 0 /* Getstream gets this wrong, see rfc2974 */
191 continue; /* We are not interested in deletions */
194 if (sap_encrypted
|| sap_compressed
)
197 sdpinfo
= parse_sdp(sdp
, recvd
-(sdp
-buffer
));
199 if (sdpinfo
->service
&& sdpinfo
->proto
&& sdpinfo
->port
) {
200 char hostbuf
[INET6_ADDRSTRLEN
];
202 if (!sdpinfo
->host
) {
205 struct in6_addr in6addr
;
207 memcpy(in6addr
.in6_u
.u6_addr8
, sender_address
, 16);
208 if (!(sdpinfo
->host
= (char*)inet_ntop(AF_INET6
, &in6addr
, hostbuf
, INET6_ADDRSTRLEN
))) {
213 struct in_addr inaddr
;
215 inaddr
.s_addr
= *((in_addr_t
*)sender_address
);
216 if (!(sdpinfo
->host
= (char*)inet_ntop(AF_INET
, &inaddr
, hostbuf
, INET6_ADDRSTRLEN
))) {
224 printf("%s -> %s://%s:%s\n", sdpinfo
->service
, sdpinfo
->proto
, sdpinfo
->host
, sdpinfo
->port
);
227 if (strlen(service
) < strlen(sdpinfo
->service
)) {
228 sdpinfo
->service
+= strlen(sdpinfo
->service
) - strlen(service
);
231 if (!strncasecmp(service
, sdpinfo
->service
, strlen(service
))) {
232 int len
= strlen(sdpinfo
->host
)+strlen(sdpinfo
->proto
)+strlen(sdpinfo
->port
)+5;
234 if (!(url
= malloc(len
))) {
239 snprintf(url
, len
, "%s://%s:%s", sdpinfo
->proto
, sdpinfo
->host
, sdpinfo
->port
);
245 } while(curr
.tv_sec
< start
.tv_sec
+SAP_TIMEOUT
||
246 ((curr
.tv_sec
== start
.tv_sec
+SAP_TIMEOUT
) && (curr
.tv_usec
< start
.tv_usec
)));
248 if (!(inet_aton(SAP_ADDR
, &sapinaddr
))) {
252 mreq
.imr_multiaddr
.s_addr
= sapinaddr
.s_addr
;
253 mreq
.imr_interface
.s_addr
= INADDR_ANY
;
254 setsockopt (fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
));