21.9 Receiving IP Multicast
Infrastructure Session Announcements
The IP multicast infrastructure is the portion
of the Internet with inter-domain multicast enabled. Multicast is
not enabled on the entire Internet; the IP multicast infrastructure
started life as the "MBone" in 1992 as an overlay network and moved
toward being deployed as part of the Internet infrastructure in
1998. Multicast is widely deployed within enterprises, but being
part of the inter-domain IP multicast infrastructure is less
common.
To receive a multimedia conference on the IP
multicast infrastructure, a site needs to know only the multicast
address of the conference and the UDP ports for the conference's
data streams (audio and video, for example). The Session Announcement Protocol, or SAP (RFC
2974 [Handley, Perkins, and Whelan 2000]), describes the way this
is done (the packet headers and frequency with which these
announcements are multicast to the IP multicast infrastructure),
and the Session Description
Protocol, or SDP (RFC 2327 [Handley and Jacobson 1998]),
describes the contents of these announcements (how the multicast
addresses and UDP port numbers are specified). A site wishing to
announce a session on the IP multicast infrastructure periodically
sends a multicast packet containing a description of the session to
a well-known multicast group and UDP port. Sites on the IP
multicast infrastructure run a program named sdr to
receive these announcements. This program does a lot: Not only does
it receive session announcements, but it also provides an
interactive user interface that displays the information and lets
the user send announcements.
In this section, we will develop a simple
program that only receives these session announcements to show an
example of a simple multicast receiving program. Our goal is to
show the simplicity of a multicast receiver, not to delve into the
details of this one application.
Figure
21.14 shows our main program that receives periodic
SAP/SDP announcements.
Well-Known name and Well-Known
port
2鈥?
The multicast address assigned for SAP announcements is
224.2.127.254 and its name is sap.mcast.net. All the
well-known multicast addresses (see http://www.iana.org/assignments/multicast-addresses)
appear in the DNS under the mcast.net hierarchy. The
well-known UDP port is 9875.
Figure 21.14
main program to receive SAP/SDP announcements.
mysdr/main.c
1 #include "unp.h"
2 #define SAP_NAME "sap.mcast.net" /* default group name and port */
3 #define SAP_PORT "9875"
4 void loop(int, socklen_t);
5 int
6 main(int argc, char **argv)
7 {
8 int sockfd;
9 const int on = 1;
10 socklen_t salen;
11 struct sockaddr *sa;
12 if (argc == 1)
13 sockfd = Udp_client(SAP_NAME, SAP_PORT, (void **) &sa, &salen);
14 else if (argc == 4)
15 sockfd = Udp_client(argv[1], argv[2], (void **) &sa, &salen);
16 else
17 err_quit("usage: mysdr <mcast-addr> <port#> <interface-name>");
18 Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
19 Bind(sockfd, sa, salen);
20 Mcast_join(sockfd, sa, salen, (argc == 4) ? argv[3] : NULL, 0);
21 loop(sockfd, salen); /* receive and print */
22 exit(0);
23 }
Create UDP socket
12鈥?7
We call our udp_client function to look up the name and
port, and it fills in the appropriate socket address structure. We
use the defaults if no command-line arguments are specified;
otherwise, we take the multicast address, port, and interface name
from the command-line arguments.
bind port
18鈥?9
We set the SO_REUSEADDR socket option to allow multiple
instances of this program to run on a host, and bind the
port to the socket. By binding the multicast address to the socket,
we prevent the socket from receiving any other UDP datagrams that
may be received for the port. Binding this multicast address is not
required, but it provides filtering by the kernel of packets in
which we are not interested.
Join multicast group
20 We
call our mcast_join function to join the group. If the
interface name was specified as a command-line argument, it is
passed to our function; otherwise, we let the kernel choose the
interface on which the group is joined.
21 We
call our loop function, shown in Figure 21.15, to read and print all the
announcements.
Figure 21.15
Loop that receives and prints SAP/SDP announcements.
mysdr/loop.c
1 #include "mysdr.h"
2 void
3 loop(int sockfd, socklen_t salen)
4 {
5 socklen_t len;
6 ssize_t n;
7 char *p;
8 struct sockaddr *sa;
9 struct sap_packet {
10 uint32_t sap_header;
11 uint32_t sap_src;
12 char sap_data[BUFFSIZE];
13 } buf;
14 sa = Malloc(salen);
15 for ( ; ; ) {
16 len = salen;
17 n = Recvfrom(sockfd, &buf, sizeof(buf) - 1, 0, sa, &len);
18 ((char *) &buf)[n] = 0; /* null terminate */
19 buf.sap_header = ntohl(buf.sap_header);
20 printf("From %s hash 0x%04x\n", Sock_ntop(sa, len),
21 buf.sap_header & SAP_HASH_MASK);
22 if (((buf.sap_header & SAP_VERSION_MASK) >> SAP_VERSION_SHIFT) > 1) {
23 err_msg("... version field not 1 (0x%08x)", buf.sap_header);
24 continue;
25 }
26 if (buf.sap_header & SAP_IPV6) {
27 err_msg("... IPv6");
28 continue;
29 }
30 if (buf.sap_header & (SAP_DELETE | SAP_ENCRYPTED | SAP_COMPRESSED)) {
31 err_msg("... can't parse this packet type (0x%08x)",
32 buf.sap_header);
33 continue;
34 }
35 p = buf.sap_data + ((buf.sap_header & SAP_AUTHLEN_MASK)
36 >> SAP_AUTHLEN_SHIFT);
37 if (strcmp(p, "application/sdp") == 0)
38 p += 16;
39 printf("%s\n", p);
40 }
41 }
Packet format
9鈥?3
sap_packet describes the SDP packet: a 32-bit SAP header,
followed by a 32-bit source address, followed by the actual
announcement. The announcement is simply lines of ISO 8859鈥? text
and should not exceed 1,024 bytes. Only one session announcement is
allowed in each UDP datagram.
Read UDP datagram, print sender and
contents
15鈥?1
recvfrom waits for the next UDP datagram destined to our
socket. When one arrives, we place a null byte at the end of the
buffer, fix the byte order of the header field, and print the
source of the packet and SAP hash.
Check SAP header
22鈥?4
We check the SAP header to see if it is a type that we handle. We
don't handle SAP packets with IPv6 addresses in the header, or
compressed or encrypted packets.
Find beginning of announcement and
print
35鈥?9
We skip over any authentication data that may be present, skip over
the packet content type if it's present, and then print out the
contents of the packet.
Figure
21.16 shows some typical output from our program.
Figure 21.16
Typical SAP/SDP announcement.
freebsd % mysdr
From 128.223.83.33:1028 hash 0x0000
v=0
o=- 60345 0 IN IP4 128.223.214.198
s=UO Broadcast - NASA Videos - 25 Years of Progress
i=25 Years of Progress, parts 1-13. Broadcast with Cisco System's
IP/TV using MPEG1 codec (6 hours 5 Minutes; repeats) More information
about IP/TV and the client needed to view this program is available
from http://videolab.uoregon.edu/download.html
u=http://videolab.uoregon.edu/
e=Hans Kuhn <multicast@lists.uoregon.edu>
p=Hans Kuhn <541/346-1758>
b=AS:1000
t=0 0
a=type:broadcast
a=tool:IP/TV Content Manager 3.2.24
a=x-iptv-file:1 name y:25yop1234567890123.mpg
m=video 63096 RTP/AVP 32 31 96
c=IN IP4 224.2.245.25/127
a=framerate:30
a=rtpmap:96 WBIH/90000
a=x-iptv-svr:video blaster2.uoregon.edu file 1 loop
m=audio 31954 RTP/AVP 14 96 0 3 5 97 98 99 100 101 102 10 11 103 104 105 106
c=IN IP4 224.2.216.85/127
a=rtpmap:96 X-WAVE/8000
a=rtpmap:97 L8/8000/2
a=rtpmap:98 L8/8000
a=rtpmap:99 L8/22050/2
a=rtpmap:100 L8/22050
a=rtpmap:101 L8/11025/2
a=rtpmap:102 L8/11025
a=rtpmap:103 L16/22050/2
a=rtpmap:104 L16/22050
a=rtpmap:105 L16/22050/2
a=rtpmap:106 L16/11025
a=x-iptv-svr:audio blaster2.uoregon.edu file 1 loop
This announcement describes the NASA coverage on
the IP Multicast Infrastructure of a space shuttle mission. The SDP
session description consists of numerous lines of the form
type=value
where the type
is always one character and is case-significant. The value is a structured text string that depends
on the type. Spaces are not
allowed around the equals sign. v=0 is the version.
0= is the origin. - indicates
no particular username, 60345 is the session ID,
0 is the version number for this announcement, IN
is the network type, IP4 is the address type, and
128.223.214.198 is the address. The five-tuple consisting
of the username, session ID, network type, address type, and
address form a globally unique identifier for the session.
s= defines the session name, and
i= is information about the session. We have wrapped the
latter every 80 characters. u= provides a Uniform Resource
Identifier (URI) for more information about the session, and
e= and p= provide the email address and phone
number of the person responsible for the conference.
b= provides a measure of the expected
bandwidth for this session. t= provides the starting time
and stopping time, both in NTP units, which are seconds since
January 1, 1900, UTC. In this case, this session is "permanent;"
having no particular start or stop time, so both start and stop
time are specified as 0.
The a= lines are attributes; either of
the session, if they appear before any m= lines, or of the
media, if they appear after a m= line.
The m= lines are the media
announcements. The first of these two lines specifies that the
video is on port 63096 and its format is RTP, using the Audio/Video
Profile or AVP, with possible payload types 32, 31 or 96 (which are
MPEG, H.261, and WBIH, respectively). The c= line that
follows provides the connection information, which in this example,
specifies that it is IP-based, using IPv4, with a multicast address
of 224.2.245.25 and a TTL of 127. Although these are separated by a
slash, like the CIDR prefix format, they are not meant to represent
a prefix and a mask.
The next m= line specifies that the
audio is on port 31954 and may be in any of a number of RTP/AVP
payload types, some of which are standard and some of which are
specified below using a=rtpmap: attributes. The
c= line that follows provides the connection information
for the audio, which in this example specifies that it is IP-based,
using IPv4, with a multicast address of 224.2.216.85 and a TTL of
127.
|