1 /*
2 * Session Announcement Protocol (RFC 2974) muxer
3 * Copyright (c) 2010 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
34
40 };
41
43 {
45 int i;
46
49 if (!rtpctx)
50 continue;
55 }
56
58 sap->
ann[0] |= 4;
/* Session deletion*/
60 }
61
66 return 0;
67 }
68
70 {
72 char host[1024], path[1024], url[1024], announce_addr[50] = "";
73 char *option_list;
74 int port = 9875, base_port = 5004, i, pos = 0, same_port = 0, ttl = 255;
78 socklen_t addrlen = sizeof(localaddr);
79 int udp_fd;
81
84
85 /* extract hostname and port */
86 av_url_split(NULL, 0, NULL, 0, host,
sizeof(host), &base_port,
88 if (base_port < 0)
89 base_port = 5004;
90
91 /* search for options */
92 option_list = strrchr(path, '?');
93 if (option_list) {
96 port = strtol(buf, NULL, 10);
97 }
99 same_port = strtol(buf, NULL, 10);
100 }
102 ttl = strtol(buf, NULL, 10);
103 }
105 av_strlcpy(announce_addr, buf,
sizeof(announce_addr));
106 }
107 }
108
109 if (!announce_addr[0]) {
110 struct addrinfo hints = { 0 }, *ai = NULL;
115 goto fail;
116 }
117 if (ai->ai_family == AF_INET) {
118 /* Also known as sap.mcast.net */
119 av_strlcpy(announce_addr,
"224.2.127.254",
sizeof(announce_addr));
120 #if HAVE_STRUCT_SOCKADDR_IN6
121 } else if (ai->ai_family == AF_INET6) {
122 /* With IPv6, you can use the same destination in many different
123 * multicast subnets, to choose how far you want it routed.
124 * This one is intended to be routed globally. */
125 av_strlcpy(announce_addr,
"ff0e::2:7ffe",
sizeof(announce_addr));
126 #endif
127 } else {
130 "address family\n", host);
132 goto fail;
133 }
135 }
136
138 if (!contexts) {
140 goto fail;
141 }
142
146
147 ff_url_join(url,
sizeof(url),
"rtp", NULL, host, base_port,
148 "?ttl=%d", ttl);
149 if (!same_port)
150 base_port += 2;
152 if (ret) {
154 goto fail;
155 }
157 if (ret < 0)
158 goto fail;
160 av_strlcpy(contexts[i]->filename, url,
sizeof(contexts[i]->filename));
161 }
162
165
166 ff_url_join(url,
sizeof(url),
"udp", NULL, announce_addr, port,
167 "?ttl=%d&connect=1", ttl);
170 if (ret) {
172 goto fail;
173 }
174
176 if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) {
178 goto fail;
179 }
181 #if HAVE_STRUCT_SOCKADDR_IN6
183 #endif
184 ) {
187 goto fail;
188 }
193 goto fail;
194 }
195 sap->
ann[pos] = (1 << 5);
196 #if HAVE_STRUCT_SOCKADDR_IN6
198 sap->
ann[pos] |= 0x10;
199 #endif
200 pos++;
201 sap->
ann[pos++] = 0;
/* Authentication length */
203 pos += 2;
205 memcpy(&sap->
ann[pos], &((
struct sockaddr_in*)&localaddr)->sin_addr,
206 sizeof(struct in_addr));
207 pos += sizeof(struct in_addr);
208 #if HAVE_STRUCT_SOCKADDR_IN6
209 } else {
210 memcpy(&sap->
ann[pos], &((
struct sockaddr_in6*)&localaddr)->sin6_addr,
211 sizeof(struct in6_addr));
212 pos += sizeof(struct in6_addr);
213 #endif
214 }
215
217 pos += strlen(&sap->
ann[pos]) + 1;
218
222 goto fail;
223 }
226 pos += strlen(&sap->
ann[pos]);
228
231 "packet\n");
232 goto fail;
233 }
234
235 return 0;
236
237 fail:
241 }
242
244 {
248
251 /* Don't abort even if we get "Destination unreachable" */
252 if (ret < 0 && ret !=
AVERROR(ECONNREFUSED))
255 }
258 }
259
263 .priv_data_size =
sizeof(
struct SAPState),
270 };