tools/sofa2wavs: fix build on Windows
[ffmpeg.git] / libavformat / rtmpproto.c
1 /*
2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
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
22 /**
23 * @file
24 * RTMP protocol
25 */
26
27 #include "config_components.h"
28
29 #include "libavcodec/bytestream.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/base64.h"
32 #include "libavutil/intfloat.h"
33 #include "libavutil/lfg.h"
34 #include "libavutil/md5.h"
35 #include "libavutil/mem.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/random_seed.h"
38 #include "avformat.h"
39 #include "internal.h"
40
41 #include "network.h"
42
43 #include "flv.h"
44 #include "rtmp.h"
45 #include "rtmpcrypt.h"
46 #include "rtmppkt.h"
47 #include "url.h"
48 #include "version.h"
49
50 #if CONFIG_ZLIB
51 #include <zlib.h>
52 #endif
53
54 #define APP_MAX_LENGTH 1024
55 #define TCURL_MAX_LENGTH 1024
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
58 #define RTMP_HEADER 11
59
60 /** RTMP protocol handler state */
61 typedef enum {
62 STATE_START, ///< client has not done anything yet
63 STATE_HANDSHAKED, ///< client has performed handshake
64 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
65 STATE_PLAYING, ///< client has started receiving multimedia data from server
66 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
67 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
68 STATE_RECEIVING, ///< received a publish command (for input)
69 STATE_SENDING, ///< received a play command (for output)
70 STATE_STOPPED, ///< the broadcast has been stopped
71 } ClientState;
72
73 typedef struct TrackedMethod {
74 char *name;
75 int id;
76 } TrackedMethod;
77
78 /** protocol handler context */
79 typedef struct RTMPContext {
80 const AVClass *class;
81 URLContext* stream; ///< TCP stream used in interactions with RTMP server
82 RTMPPacket *prev_pkt[2]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
83 int nb_prev_pkt[2]; ///< number of elements in prev_pkt
84 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
85 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
86 int is_input; ///< input/output flag
87 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
88 int live; ///< 0: recorded, -1: live, -2: both
89 char *app; ///< name of application
90 char *conn; ///< append arbitrary AMF data to the Connect message
91 ClientState state; ///< current state
92 int stream_id; ///< ID assigned by the server for the stream
93 uint8_t* flv_data; ///< buffer with data for demuxer
94 int flv_size; ///< current buffer size
95 int flv_off; ///< number of bytes read from current buffer
96 int flv_nb_packets; ///< number of flv packets published
97 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
98 uint32_t receive_report_size; ///< number of bytes after which we should report the number of received bytes to the peer
99 uint64_t bytes_read; ///< number of bytes read from server
100 uint64_t last_bytes_read; ///< number of bytes read last reported to server
101 uint32_t last_timestamp; ///< last timestamp received in a packet
102 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
103 int has_audio; ///< presence of audio data
104 int has_video; ///< presence of video data
105 int received_metadata; ///< Indicates if we have received metadata about the streams
106 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
107 int flv_header_bytes; ///< number of initialized bytes in flv_header
108 int nb_invokes; ///< keeps track of invoke messages
109 char* tcurl; ///< url of the target stream
110 char* flashver; ///< version of the flash plugin
111 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
112 int swfhash_len; ///< length of the SHA256 hash
113 int swfsize; ///< size of the decompressed SWF file
114 char* swfurl; ///< url of the swf player
115 char* swfverify; ///< URL to player swf file, compute hash/size automatically
116 char swfverification[42]; ///< hash of the SWF verification
117 char* pageurl; ///< url of the web page
118 char* subscribe; ///< name of live stream to subscribe
119 int max_sent_unacked; ///< max unacked sent bytes
120 int client_buffer_time; ///< client buffer time in ms
121 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
122 int encrypted; ///< use an encrypted connection (RTMPE only)
123 TrackedMethod*tracked_methods; ///< tracked methods buffer
124 int nb_tracked_methods; ///< number of tracked methods
125 int tracked_methods_size; ///< size of the tracked methods buffer
126 int listen; ///< listen mode flag
127 int listen_timeout; ///< listen timeout to wait for new connections
128 int nb_streamid; ///< The next stream id to return on createStream calls
129 double duration; ///< Duration of the stream in seconds as returned by the server (only valid if non-zero)
130 int tcp_nodelay; ///< Use TCP_NODELAY to disable Nagle's algorithm if set to 1
131 char *enhanced_codecs; ///< codec list in enhanced rtmp
132 char username[50];
133 char password[50];
134 char auth_params[500];
135 int do_reconnect;
136 int auth_tried;
137 } RTMPContext;
138
139 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
140 /** Client key used for digest signing */
141 static const uint8_t rtmp_player_key[] = {
142 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
143 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
144
145 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
146 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
147 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
148 };
149
150 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
151 /** Key used for RTMP server digest signing */
152 static const uint8_t rtmp_server_key[] = {
153 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
154 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
155 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
156
157 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
158 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
159 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
160 };
161
162 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
163 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt);
164 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt);
165
166 static size_t zstrlen(const char *c)
167 {
168 if(c)
169 return strlen(c);
170 return 0;
171 }
172
173 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
174 {
175 int err;
176
177 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
178 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
179 if ((err = av_reallocp_array(&rt->tracked_methods, rt->tracked_methods_size,
180 sizeof(*rt->tracked_methods))) < 0) {
181 rt->nb_tracked_methods = 0;
182 rt->tracked_methods_size = 0;
183 return err;
184 }
185 }
186
187 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
188 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
189 return AVERROR(ENOMEM);
190 rt->tracked_methods[rt->nb_tracked_methods].id = id;
191 rt->nb_tracked_methods++;
192
193 return 0;
194 }
195
196 static void del_tracked_method(RTMPContext *rt, int index)
197 {
198 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
199 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
200 rt->nb_tracked_methods--;
201 }
202
203 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
204 char **tracked_method)
205 {
206 RTMPContext *rt = s->priv_data;
207 GetByteContext gbc;
208 double pkt_id;
209 int ret;
210 int i;
211
212 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
213 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
214 return ret;
215
216 for (i = 0; i < rt->nb_tracked_methods; i++) {
217 if (rt->tracked_methods[i].id != pkt_id)
218 continue;
219
220 *tracked_method = rt->tracked_methods[i].name;
221 del_tracked_method(rt, i);
222 break;
223 }
224
225 return 0;
226 }
227
228 static void free_tracked_methods(RTMPContext *rt)
229 {
230 int i;
231
232 for (i = 0; i < rt->nb_tracked_methods; i ++)
233 av_freep(&rt->tracked_methods[i].name);
234 av_freep(&rt->tracked_methods);
235 rt->tracked_methods_size = 0;
236 rt->nb_tracked_methods = 0;
237 }
238
239 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
240 {
241 int ret;
242
243 if (pkt->type == RTMP_PT_INVOKE && track) {
244 GetByteContext gbc;
245 char name[128];
246 double pkt_id;
247 int len;
248
249 bytestream2_init(&gbc, pkt->data, pkt->size);
250 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
251 goto fail;
252
253 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
254 goto fail;
255
256 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
257 goto fail;
258 }
259
260 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
261 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
262 fail:
263 ff_rtmp_packet_destroy(pkt);
264 return ret;
265 }
266
267 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
268 {
269 char *field, *value;
270 char type;
271
272 /* The type must be B for Boolean, N for number, S for string, O for
273 * object, or Z for null. For Booleans the data must be either 0 or 1 for
274 * FALSE or TRUE, respectively. Likewise for Objects the data must be
275 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
276 * may be named, by prefixing the type with 'N' and specifying the name
277 * before the value (ie. NB:myFlag:1). This option may be used multiple times
278 * to construct arbitrary AMF sequences. */
279 if (param[0] && param[1] == ':') {
280 type = param[0];
281 value = param + 2;
282 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
283 type = param[1];
284 field = param + 3;
285 value = strchr(field, ':');
286 if (!value)
287 goto fail;
288 *value = '\0';
289 value++;
290
291 ff_amf_write_field_name(p, field);
292 } else {
293 goto fail;
294 }
295
296 switch (type) {
297 case 'B':
298 ff_amf_write_bool(p, value[0] != '0');
299 break;
300 case 'S':
301 ff_amf_write_string(p, value);
302 break;
303 case 'N':
304 ff_amf_write_number(p, strtod(value, NULL));
305 break;
306 case 'Z':
307 ff_amf_write_null(p);
308 break;
309 case 'O':
310 if (value[0] != '0')
311 ff_amf_write_object_start(p);
312 else
313 ff_amf_write_object_end(p);
314 break;
315 default:
316 goto fail;
317 break;
318 }
319
320 return 0;
321
322 fail:
323 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
324 return AVERROR(EINVAL);
325 }
326
327 /**
328 * Generate 'connect' call and send it to the server.
329 */
330 static int gen_connect(URLContext *s, RTMPContext *rt)
331 {
332 RTMPPacket pkt;
333 uint8_t *p;
334 int ret;
335
336 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
337 0, 4096 + APP_MAX_LENGTH
338 + strlen(rt->auth_params) + strlen(rt->flashver)
339 + zstrlen(rt->enhanced_codecs)/5*7
340 + zstrlen(rt->swfurl)
341 + zstrlen(rt->swfverify)
342 + zstrlen(rt->tcurl)
343 + zstrlen(rt->auth_params)
344 + zstrlen(rt->pageurl)
345 + zstrlen(rt->conn)*3
346 )) < 0)
347 return ret;
348
349 p = pkt.data;
350
351 ff_amf_write_string(&p, "connect");
352 ff_amf_write_number(&p, ++rt->nb_invokes);
353 ff_amf_write_object_start(&p);
354 ff_amf_write_field_name(&p, "app");
355 ff_amf_write_string2(&p, rt->app, rt->auth_params);
356
357 if (rt->enhanced_codecs) {
358 uint32_t list_len = 0;
359 char *fourcc_data = rt->enhanced_codecs;
360 int fourcc_str_len = strlen(fourcc_data);
361
362 // check the string, fourcc + ',' + ... + end fourcc correct length should be (4+1)*n+4
363 if ((fourcc_str_len + 1) % 5 != 0) {
364 av_log(s, AV_LOG_ERROR, "Malformed rtmp_enhanched_codecs, "
365 "should be of the form hvc1[,av01][,vp09][,...]\n");
366 ff_rtmp_packet_destroy(&pkt);
367 return AVERROR(EINVAL);
368 }
369
370 list_len = (fourcc_str_len + 1) / 5;
371 ff_amf_write_field_name(&p, "fourCcList");
372 ff_amf_write_array_start(&p, list_len);
373
374 while(fourcc_data - rt->enhanced_codecs < fourcc_str_len) {
375 unsigned char fourcc[5];
376 if (!strncmp(fourcc_data, "ac-3", 4) ||
377 !strncmp(fourcc_data, "av01", 4) ||
378 !strncmp(fourcc_data, "avc1", 4) ||
379 !strncmp(fourcc_data, "ec-3", 4) ||
380 !strncmp(fourcc_data, "fLaC", 4) ||
381 !strncmp(fourcc_data, "hvc1", 4) ||
382 !strncmp(fourcc_data, ".mp3", 4) ||
383 !strncmp(fourcc_data, "mp4a", 4) ||
384 !strncmp(fourcc_data, "Opus", 4) ||
385 !strncmp(fourcc_data, "vp09", 4)) {
386 av_strlcpy(fourcc, fourcc_data, sizeof(fourcc));
387 ff_amf_write_string(&p, fourcc);
388 } else {
389 av_log(s, AV_LOG_ERROR, "Unsupported codec fourcc, %.*s\n", 4, fourcc_data);
390 ff_rtmp_packet_destroy(&pkt);
391 return AVERROR_PATCHWELCOME;
392 }
393
394 fourcc_data += 5;
395 }
396 }
397
398 if (!rt->is_input) {
399 ff_amf_write_field_name(&p, "type");
400 ff_amf_write_string(&p, "nonprivate");
401 }
402 ff_amf_write_field_name(&p, "flashVer");
403 ff_amf_write_string(&p, rt->flashver);
404
405 if (rt->swfurl || rt->swfverify) {
406 ff_amf_write_field_name(&p, "swfUrl");
407 if (rt->swfurl)
408 ff_amf_write_string(&p, rt->swfurl);
409 else
410 ff_amf_write_string(&p, rt->swfverify);
411 }
412
413 ff_amf_write_field_name(&p, "tcUrl");
414 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
415 if (rt->is_input) {
416 ff_amf_write_field_name(&p, "fpad");
417 ff_amf_write_bool(&p, 0);
418 ff_amf_write_field_name(&p, "capabilities");
419 ff_amf_write_number(&p, 15.0);
420
421 /* Tell the server we support all the audio codecs except
422 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
423 * which are unused in the RTMP protocol implementation. */
424 ff_amf_write_field_name(&p, "audioCodecs");
425 ff_amf_write_number(&p, 4071.0);
426 ff_amf_write_field_name(&p, "videoCodecs");
427 ff_amf_write_number(&p, 252.0);
428 ff_amf_write_field_name(&p, "videoFunction");
429 ff_amf_write_number(&p, 1.0);
430
431 if (rt->pageurl) {
432 ff_amf_write_field_name(&p, "pageUrl");
433 ff_amf_write_string(&p, rt->pageurl);
434 }
435 }
436 ff_amf_write_object_end(&p);
437
438 if (rt->conn) {
439 char *param = rt->conn;
440
441 // Write arbitrary AMF data to the Connect message.
442 while (param) {
443 char *sep;
444 param += strspn(param, " ");
445 if (!*param)
446 break;
447 sep = strchr(param, ' ');
448 if (sep)
449 *sep = '\0';
450 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
451 // Invalid AMF parameter.
452 ff_rtmp_packet_destroy(&pkt);
453 return ret;
454 }
455
456 if (sep)
457 param = sep + 1;
458 else
459 break;
460 }
461 }
462
463 pkt.size = p - pkt.data;
464
465 return rtmp_send_packet(rt, &pkt, 1);
466 }
467
468
469 #define RTMP_CTRL_ABORT_MESSAGE (2)
470
471 static int read_connect(URLContext *s, RTMPContext *rt)
472 {
473 RTMPPacket pkt = { 0 };
474 uint8_t *p;
475 const uint8_t *cp;
476 int ret;
477 char command[64];
478 int stringlen;
479 double seqnum;
480 uint8_t tmpstr[256];
481 GetByteContext gbc;
482
483 // handle RTMP Protocol Control Messages
484 for (;;) {
485 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
486 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
487 return ret;
488 #ifdef DEBUG
489 ff_rtmp_packet_dump(s, &pkt);
490 #endif
491 if (pkt.type == RTMP_PT_CHUNK_SIZE) {
492 if ((ret = handle_chunk_size(s, &pkt)) < 0) {
493 ff_rtmp_packet_destroy(&pkt);
494 return ret;
495 }
496 } else if (pkt.type == RTMP_CTRL_ABORT_MESSAGE) {
497 av_log(s, AV_LOG_ERROR, "received abort message\n");
498 ff_rtmp_packet_destroy(&pkt);
499 return AVERROR_UNKNOWN;
500 } else if (pkt.type == RTMP_PT_BYTES_READ) {
501 av_log(s, AV_LOG_TRACE, "received acknowledgement\n");
502 } else if (pkt.type == RTMP_PT_WINDOW_ACK_SIZE) {
503 if ((ret = handle_window_ack_size(s, &pkt)) < 0) {
504 ff_rtmp_packet_destroy(&pkt);
505 return ret;
506 }
507 } else if (pkt.type == RTMP_PT_SET_PEER_BW) {
508 if ((ret = handle_set_peer_bw(s, &pkt)) < 0) {
509 ff_rtmp_packet_destroy(&pkt);
510 return ret;
511 }
512 } else if (pkt.type == RTMP_PT_INVOKE) {
513 // received RTMP Command Message
514 break;
515 } else {
516 av_log(s, AV_LOG_ERROR, "Unknown control message type (%d)\n", pkt.type);
517 }
518 ff_rtmp_packet_destroy(&pkt);
519 }
520
521 cp = pkt.data;
522 bytestream2_init(&gbc, cp, pkt.size);
523 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
524 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
525 ff_rtmp_packet_destroy(&pkt);
526 return AVERROR_INVALIDDATA;
527 }
528 if (strcmp(command, "connect")) {
529 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
530 ff_rtmp_packet_destroy(&pkt);
531 return AVERROR_INVALIDDATA;
532 }
533 ret = ff_amf_read_number(&gbc, &seqnum);
534 if (ret)
535 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
536 /* Here one could parse an AMF Object with data as flashVers and others. */
537 ret = ff_amf_get_field_value(gbc.buffer,
538 gbc.buffer + bytestream2_get_bytes_left(&gbc),
539 "app", tmpstr, sizeof(tmpstr));
540 if (ret)
541 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
542 if (!ret && strcmp(tmpstr, rt->app))
543 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
544 tmpstr, rt->app);
545 ff_rtmp_packet_destroy(&pkt);
546
547 // Send Window Acknowledgement Size (as defined in specification)
548 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
549 RTMP_PT_WINDOW_ACK_SIZE, 0, 4)) < 0)
550 return ret;
551 p = pkt.data;
552 // Inform the peer about how often we want acknowledgements about what
553 // we send. (We don't check for the acknowledgements currently.)
554 bytestream_put_be32(&p, rt->max_sent_unacked);
555 pkt.size = p - pkt.data;
556 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
557 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
558 ff_rtmp_packet_destroy(&pkt);
559 if (ret < 0)
560 return ret;
561 // Set Peer Bandwidth
562 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
563 RTMP_PT_SET_PEER_BW, 0, 5)) < 0)
564 return ret;
565 p = pkt.data;
566 // Tell the peer to only send this many bytes unless it gets acknowledgements.
567 // This could be any arbitrary value we want here.
568 bytestream_put_be32(&p, rt->max_sent_unacked);
569 bytestream_put_byte(&p, 2); // dynamic
570 pkt.size = p - pkt.data;
571 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
572 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
573 ff_rtmp_packet_destroy(&pkt);
574 if (ret < 0)
575 return ret;
576
577 // User control
578 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
579 RTMP_PT_USER_CONTROL, 0, 6)) < 0)
580 return ret;
581
582 p = pkt.data;
583 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
584 bytestream_put_be32(&p, 0); // Stream 0
585 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
586 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
587 ff_rtmp_packet_destroy(&pkt);
588 if (ret < 0)
589 return ret;
590
591 // Chunk size
592 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
593 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
594 return ret;
595
596 p = pkt.data;
597 bytestream_put_be32(&p, rt->out_chunk_size);
598 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
599 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
600 ff_rtmp_packet_destroy(&pkt);
601 if (ret < 0)
602 return ret;
603
604 // Send _result NetConnection.Connect.Success to connect
605 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
606 RTMP_PT_INVOKE, 0,
607 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
608 return ret;
609
610 p = pkt.data;
611 ff_amf_write_string(&p, "_result");
612 ff_amf_write_number(&p, seqnum);
613
614 ff_amf_write_object_start(&p);
615 ff_amf_write_field_name(&p, "fmsVer");
616 ff_amf_write_string(&p, "FMS/3,0,1,123");
617 ff_amf_write_field_name(&p, "capabilities");
618 ff_amf_write_number(&p, 31);
619 ff_amf_write_object_end(&p);
620
621 ff_amf_write_object_start(&p);
622 ff_amf_write_field_name(&p, "level");
623 ff_amf_write_string(&p, "status");
624 ff_amf_write_field_name(&p, "code");
625 ff_amf_write_string(&p, "NetConnection.Connect.Success");
626 ff_amf_write_field_name(&p, "description");
627 ff_amf_write_string(&p, "Connection succeeded.");
628 ff_amf_write_field_name(&p, "objectEncoding");
629 ff_amf_write_number(&p, 0);
630 ff_amf_write_object_end(&p);
631
632 pkt.size = p - pkt.data;
633 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
634 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
635 ff_rtmp_packet_destroy(&pkt);
636 if (ret < 0)
637 return ret;
638
639 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
640 RTMP_PT_INVOKE, 0, 30)) < 0)
641 return ret;
642 p = pkt.data;
643 ff_amf_write_string(&p, "onBWDone");
644 ff_amf_write_number(&p, 0);
645 ff_amf_write_null(&p);
646 ff_amf_write_number(&p, 8192);
647 pkt.size = p - pkt.data;
648 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
649 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
650 ff_rtmp_packet_destroy(&pkt);
651
652 return ret;
653 }
654
655 /**
656 * Generate 'releaseStream' call and send it to the server. It should make
657 * the server release some channel for media streams.
658 */
659 static int gen_release_stream(URLContext *s, RTMPContext *rt)
660 {
661 RTMPPacket pkt;
662 uint8_t *p;
663 int ret;
664
665 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
666 0, 29 + strlen(rt->playpath))) < 0)
667 return ret;
668
669 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
670 p = pkt.data;
671 ff_amf_write_string(&p, "releaseStream");
672 ff_amf_write_number(&p, ++rt->nb_invokes);
673 ff_amf_write_null(&p);
674 ff_amf_write_string(&p, rt->playpath);
675
676 return rtmp_send_packet(rt, &pkt, 1);
677 }
678
679 /**
680 * Generate 'FCPublish' call and send it to the server. It should make
681 * the server prepare for receiving media streams.
682 */
683 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
684 {
685 RTMPPacket pkt;
686 uint8_t *p;
687 int ret;
688
689 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
690 0, 25 + strlen(rt->playpath))) < 0)
691 return ret;
692
693 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
694 p = pkt.data;
695 ff_amf_write_string(&p, "FCPublish");
696 ff_amf_write_number(&p, ++rt->nb_invokes);
697 ff_amf_write_null(&p);
698 ff_amf_write_string(&p, rt->playpath);
699
700 return rtmp_send_packet(rt, &pkt, 1);
701 }
702
703 /**
704 * Generate 'FCUnpublish' call and send it to the server. It should make
705 * the server destroy stream.
706 */
707 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
708 {
709 RTMPPacket pkt;
710 uint8_t *p;
711 int ret;
712
713 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
714 0, 27 + strlen(rt->playpath))) < 0)
715 return ret;
716
717 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
718 p = pkt.data;
719 ff_amf_write_string(&p, "FCUnpublish");
720 ff_amf_write_number(&p, ++rt->nb_invokes);
721 ff_amf_write_null(&p);
722 ff_amf_write_string(&p, rt->playpath);
723
724 return rtmp_send_packet(rt, &pkt, 0);
725 }
726
727 /**
728 * Generate 'createStream' call and send it to the server. It should make
729 * the server allocate some channel for media streams.
730 */
731 static int gen_create_stream(URLContext *s, RTMPContext *rt)
732 {
733 RTMPPacket pkt;
734 uint8_t *p;
735 int ret;
736
737 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
738
739 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
740 0, 25)) < 0)
741 return ret;
742
743 p = pkt.data;
744 ff_amf_write_string(&p, "createStream");
745 ff_amf_write_number(&p, ++rt->nb_invokes);
746 ff_amf_write_null(&p);
747
748 return rtmp_send_packet(rt, &pkt, 1);
749 }
750
751
752 /**
753 * Generate 'deleteStream' call and send it to the server. It should make
754 * the server remove some channel for media streams.
755 */
756 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
757 {
758 RTMPPacket pkt;
759 uint8_t *p;
760 int ret;
761
762 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
763
764 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
765 0, 34)) < 0)
766 return ret;
767
768 p = pkt.data;
769 ff_amf_write_string(&p, "deleteStream");
770 ff_amf_write_number(&p, ++rt->nb_invokes);
771 ff_amf_write_null(&p);
772 ff_amf_write_number(&p, rt->stream_id);
773
774 return rtmp_send_packet(rt, &pkt, 0);
775 }
776
777 /**
778 * Generate 'getStreamLength' call and send it to the server. If the server
779 * knows the duration of the selected stream, it will reply with the duration
780 * in seconds.
781 */
782 static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
783 {
784 RTMPPacket pkt;
785 uint8_t *p;
786 int ret;
787
788 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
789 0, 31 + strlen(rt->playpath))) < 0)
790 return ret;
791
792 p = pkt.data;
793 ff_amf_write_string(&p, "getStreamLength");
794 ff_amf_write_number(&p, ++rt->nb_invokes);
795 ff_amf_write_null(&p);
796 ff_amf_write_string(&p, rt->playpath);
797
798 return rtmp_send_packet(rt, &pkt, 1);
799 }
800
801 /**
802 * Generate client buffer time and send it to the server.
803 */
804 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
805 {
806 RTMPPacket pkt;
807 uint8_t *p;
808 int ret;
809
810 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
811 1, 10)) < 0)
812 return ret;
813
814 p = pkt.data;
815 bytestream_put_be16(&p, 3); // SetBuffer Length
816 bytestream_put_be32(&p, rt->stream_id);
817 bytestream_put_be32(&p, rt->client_buffer_time);
818
819 return rtmp_send_packet(rt, &pkt, 0);
820 }
821
822 /**
823 * Generate 'play' call and send it to the server, then ping the server
824 * to start actual playing.
825 */
826 static int gen_play(URLContext *s, RTMPContext *rt)
827 {
828 RTMPPacket pkt;
829 uint8_t *p;
830 int ret;
831
832 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
833
834 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
835 0, 29 + strlen(rt->playpath))) < 0)
836 return ret;
837
838 pkt.extra = rt->stream_id;
839
840 p = pkt.data;
841 ff_amf_write_string(&p, "play");
842 ff_amf_write_number(&p, ++rt->nb_invokes);
843 ff_amf_write_null(&p);
844 ff_amf_write_string(&p, rt->playpath);
845 ff_amf_write_number(&p, rt->live * 1000);
846
847 return rtmp_send_packet(rt, &pkt, 1);
848 }
849
850 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
851 {
852 RTMPPacket pkt;
853 uint8_t *p;
854 int ret;
855
856 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
857 timestamp);
858
859 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
860 return ret;
861
862 pkt.extra = rt->stream_id;
863
864 p = pkt.data;
865 ff_amf_write_string(&p, "seek");
866 ff_amf_write_number(&p, 0); //no tracking back responses
867 ff_amf_write_null(&p); //as usual, the first null param
868 ff_amf_write_number(&p, timestamp); //where we want to jump
869
870 return rtmp_send_packet(rt, &pkt, 1);
871 }
872
873 /**
874 * Generate a pause packet that either pauses or unpauses the current stream.
875 */
876 static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
877 {
878 RTMPPacket pkt;
879 uint8_t *p;
880 int ret;
881
882 av_log(s, AV_LOG_DEBUG, "Sending pause command for timestamp %d\n",
883 timestamp);
884
885 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 29)) < 0)
886 return ret;
887
888 pkt.extra = rt->stream_id;
889
890 p = pkt.data;
891 ff_amf_write_string(&p, "pause");
892 ff_amf_write_number(&p, 0); //no tracking back responses
893 ff_amf_write_null(&p); //as usual, the first null param
894 ff_amf_write_bool(&p, pause); // pause or unpause
895 ff_amf_write_number(&p, timestamp); //where we pause the stream
896
897 return rtmp_send_packet(rt, &pkt, 1);
898 }
899
900 /**
901 * Generate 'publish' call and send it to the server.
902 */
903 static int gen_publish(URLContext *s, RTMPContext *rt)
904 {
905 RTMPPacket pkt;
906 uint8_t *p;
907 int ret;
908
909 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
910
911 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
912 0, 30 + strlen(rt->playpath))) < 0)
913 return ret;
914
915 pkt.extra = rt->stream_id;
916
917 p = pkt.data;
918 ff_amf_write_string(&p, "publish");
919 ff_amf_write_number(&p, ++rt->nb_invokes);
920 ff_amf_write_null(&p);
921 ff_amf_write_string(&p, rt->playpath);
922 ff_amf_write_string(&p, "live");
923
924 return rtmp_send_packet(rt, &pkt, 1);
925 }
926
927 /**
928 * Generate ping reply and send it to the server.
929 */
930 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
931 {
932 RTMPPacket pkt;
933 uint8_t *p;
934 int ret;
935
936 if (ppkt->size < 6) {
937 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
938 ppkt->size);
939 return AVERROR_INVALIDDATA;
940 }
941
942 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,RTMP_PT_USER_CONTROL,
943 ppkt->timestamp + 1, 6)) < 0)
944 return ret;
945
946 p = pkt.data;
947 bytestream_put_be16(&p, 7); // PingResponse
948 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
949
950 return rtmp_send_packet(rt, &pkt, 0);
951 }
952
953 /**
954 * Generate SWF verification message and send it to the server.
955 */
956 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
957 {
958 RTMPPacket pkt;
959 uint8_t *p;
960 int ret;
961
962 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
963 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
964 0, 44)) < 0)
965 return ret;
966
967 p = pkt.data;
968 bytestream_put_be16(&p, 27);
969 memcpy(p, rt->swfverification, 42);
970
971 return rtmp_send_packet(rt, &pkt, 0);
972 }
973
974 /**
975 * Generate window acknowledgement size message and send it to the server.
976 */
977 static int gen_window_ack_size(URLContext *s, RTMPContext *rt)
978 {
979 RTMPPacket pkt;
980 uint8_t *p;
981 int ret;
982
983 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_WINDOW_ACK_SIZE,
984 0, 4)) < 0)
985 return ret;
986
987 p = pkt.data;
988 bytestream_put_be32(&p, rt->max_sent_unacked);
989
990 return rtmp_send_packet(rt, &pkt, 0);
991 }
992
993 /**
994 * Generate check bandwidth message and send it to the server.
995 */
996 static int gen_check_bw(URLContext *s, RTMPContext *rt)
997 {
998 RTMPPacket pkt;
999 uint8_t *p;
1000 int ret;
1001
1002 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
1003 0, 21)) < 0)
1004 return ret;
1005
1006 p = pkt.data;
1007 ff_amf_write_string(&p, "_checkbw");
1008 ff_amf_write_number(&p, ++rt->nb_invokes);
1009 ff_amf_write_null(&p);
1010
1011 return rtmp_send_packet(rt, &pkt, 1);
1012 }
1013
1014 /**
1015 * Generate report on bytes read so far and send it to the server.
1016 */
1017 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
1018 {
1019 RTMPPacket pkt;
1020 uint8_t *p;
1021 int ret;
1022
1023 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
1024 ts, 4)) < 0)
1025 return ret;
1026
1027 p = pkt.data;
1028 bytestream_put_be32(&p, rt->bytes_read);
1029
1030 return rtmp_send_packet(rt, &pkt, 0);
1031 }
1032
1033 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
1034 const char *subscribe)
1035 {
1036 RTMPPacket pkt;
1037 uint8_t *p;
1038 int ret;
1039
1040 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
1041 0, 27 + strlen(subscribe))) < 0)
1042 return ret;
1043
1044 p = pkt.data;
1045 ff_amf_write_string(&p, "FCSubscribe");
1046 ff_amf_write_number(&p, ++rt->nb_invokes);
1047 ff_amf_write_null(&p);
1048 ff_amf_write_string(&p, subscribe);
1049
1050 return rtmp_send_packet(rt, &pkt, 1);
1051 }
1052
1053 /**
1054 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
1055 * will be stored) into that packet.
1056 *
1057 * @param buf handshake data (1536 bytes)
1058 * @param encrypted use an encrypted connection (RTMPE)
1059 * @return offset to the digest inside input data
1060 */
1061 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
1062 {
1063 int ret, digest_pos;
1064
1065 if (encrypted)
1066 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
1067 else
1068 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
1069
1070 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1071 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
1072 buf + digest_pos);
1073 if (ret < 0)
1074 return ret;
1075
1076 return digest_pos;
1077 }
1078
1079 /**
1080 * Verify that the received server response has the expected digest value.
1081 *
1082 * @param buf handshake data received from the server (1536 bytes)
1083 * @param off position to search digest offset from
1084 * @return 0 if digest is valid, digest position otherwise
1085 */
1086 static int rtmp_validate_digest(uint8_t *buf, int off)
1087 {
1088 uint8_t digest[32];
1089 int ret, digest_pos;
1090
1091 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
1092
1093 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1094 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
1095 digest);
1096 if (ret < 0)
1097 return ret;
1098
1099 if (!memcmp(digest, buf + digest_pos, 32))
1100 return digest_pos;
1101 return 0;
1102 }
1103
1104 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1105 uint8_t *buf)
1106 {
1107 uint8_t *p;
1108 int ret;
1109
1110 if (rt->swfhash_len != 32) {
1111 av_log(s, AV_LOG_ERROR,
1112 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1113 return AVERROR(EINVAL);
1114 }
1115
1116 p = &rt->swfverification[0];
1117 bytestream_put_byte(&p, 1);
1118 bytestream_put_byte(&p, 1);
1119 bytestream_put_be32(&p, rt->swfsize);
1120 bytestream_put_be32(&p, rt->swfsize);
1121
1122 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1123 return ret;
1124
1125 return 0;
1126 }
1127
1128 #if CONFIG_ZLIB
1129 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1130 uint8_t **out_data, int64_t *out_size)
1131 {
1132 z_stream zs = { 0 };
1133 void *ptr;
1134 int size;
1135 int ret = 0;
1136
1137 zs.avail_in = in_size;
1138 zs.next_in = in_data;
1139 ret = inflateInit(&zs);
1140 if (ret != Z_OK)
1141 return AVERROR_UNKNOWN;
1142
1143 do {
1144 uint8_t tmp_buf[16384];
1145
1146 zs.avail_out = sizeof(tmp_buf);
1147 zs.next_out = tmp_buf;
1148
1149 ret = inflate(&zs, Z_NO_FLUSH);
1150 if (ret != Z_OK && ret != Z_STREAM_END) {
1151 ret = AVERROR_UNKNOWN;
1152 goto fail;
1153 }
1154
1155 size = sizeof(tmp_buf) - zs.avail_out;
1156 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1157 ret = AVERROR(ENOMEM);
1158 goto fail;
1159 }
1160 *out_data = ptr;
1161
1162 memcpy(*out_data + *out_size, tmp_buf, size);
1163 *out_size += size;
1164 } while (zs.avail_out == 0);
1165
1166 fail:
1167 inflateEnd(&zs);
1168 return ret;
1169 }
1170 #endif
1171
1172 static int rtmp_calc_swfhash(URLContext *s)
1173 {
1174 RTMPContext *rt = s->priv_data;
1175 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1176 int64_t in_size;
1177 URLContext *stream = NULL;
1178 char swfhash[32];
1179 int swfsize;
1180 int ret = 0;
1181
1182 /* Get the SWF player file. */
1183 if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
1184 &s->interrupt_callback, NULL,
1185 s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
1186 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1187 goto fail;
1188 }
1189
1190 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1191 ret = AVERROR(EIO);
1192 goto fail;
1193 }
1194
1195 if (!(in_data = av_malloc(in_size))) {
1196 ret = AVERROR(ENOMEM);
1197 goto fail;
1198 }
1199
1200 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1201 goto fail;
1202
1203 if (in_size < 3) {
1204 ret = AVERROR_INVALIDDATA;
1205 goto fail;
1206 }
1207
1208 if (!memcmp(in_data, "CWS", 3)) {
1209 #if CONFIG_ZLIB
1210 int64_t out_size;
1211 /* Decompress the SWF player file using Zlib. */
1212 if (!(out_data = av_malloc(8))) {
1213 ret = AVERROR(ENOMEM);
1214 goto fail;
1215 }
1216 *in_data = 'F'; // magic stuff
1217 memcpy(out_data, in_data, 8);
1218 out_size = 8;
1219
1220 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1221 &out_data, &out_size)) < 0)
1222 goto fail;
1223 swfsize = out_size;
1224 swfdata = out_data;
1225 #else
1226 av_log(s, AV_LOG_ERROR,
1227 "Zlib is required for decompressing the SWF player file.\n");
1228 ret = AVERROR(EINVAL);
1229 goto fail;
1230 #endif
1231 } else {
1232 swfsize = in_size;
1233 swfdata = in_data;
1234 }
1235
1236 /* Compute the SHA256 hash of the SWF player file. */
1237 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1238 "Genuine Adobe Flash Player 001", 30,
1239 swfhash)) < 0)
1240 goto fail;
1241
1242 /* Set SWFVerification parameters. */
1243 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1244 rt->swfsize = swfsize;
1245
1246 fail:
1247 av_freep(&in_data);
1248 av_freep(&out_data);
1249 ffurl_close(stream);
1250 return ret;
1251 }
1252
1253 /**
1254 * Perform handshake with the server by means of exchanging pseudorandom data
1255 * signed with HMAC-SHA2 digest.
1256 *
1257 * @return 0 if handshake succeeds, negative value otherwise
1258 */
1259 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1260 {
1261 AVLFG rnd;
1262 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1263 3, // unencrypted data
1264 0, 0, 0, 0, // client uptime
1265 RTMP_CLIENT_VER1,
1266 RTMP_CLIENT_VER2,
1267 RTMP_CLIENT_VER3,
1268 RTMP_CLIENT_VER4,
1269 };
1270 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1271 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1272 int i;
1273 int server_pos, client_pos;
1274 uint8_t digest[32], signature[32];
1275 int ret;
1276 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1277 int type = 0;
1278 #endif
1279
1280 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1281
1282 av_lfg_init(&rnd, 0xDEADC0DE);
1283 // generate handshake packet - 1536 bytes of pseudorandom data
1284 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1285 tosend[i] = av_lfg_get(&rnd) >> 24;
1286
1287 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1288 if (rt->encrypted) {
1289 /* When the client wants to use RTMPE, we have to change the command
1290 * byte to 0x06 which means to use encrypted data and we have to set
1291 * the flash version to at least 9.0.115.0. */
1292 tosend[0] = 6;
1293 tosend[5] = 128;
1294 tosend[6] = 0;
1295 tosend[7] = 3;
1296 tosend[8] = 2;
1297
1298 /* Initialize the Diffie-Hellmann context and generate the public key
1299 * to send to the server. */
1300 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1301 return ret;
1302 }
1303 #endif
1304
1305 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1306 if (client_pos < 0)
1307 return client_pos;
1308
1309 if ((ret = ffurl_write(rt->stream, tosend,
1310 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1311 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1312 return ret;
1313 }
1314
1315 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1316 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1317 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1318 return ret;
1319 }
1320
1321 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1322 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1323 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1324 return ret;
1325 }
1326
1327 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1328 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1329 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1330
1331 if (rt->is_input && serverdata[5] >= 3) {
1332 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1333 if (server_pos < 0)
1334 return server_pos;
1335
1336 if (!server_pos) {
1337 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1338 type = 1;
1339 #endif
1340 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1341 if (server_pos < 0)
1342 return server_pos;
1343
1344 if (!server_pos) {
1345 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1346 return AVERROR(EIO);
1347 }
1348 }
1349
1350 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1351 * key are the last 32 bytes of the server handshake. */
1352 if (rt->swfsize) {
1353 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1354 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1355 return ret;
1356 }
1357
1358 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1359 rtmp_server_key, sizeof(rtmp_server_key),
1360 digest);
1361 if (ret < 0)
1362 return ret;
1363
1364 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1365 0, digest, 32, signature);
1366 if (ret < 0)
1367 return ret;
1368
1369 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1370 if (rt->encrypted) {
1371 /* Compute the shared secret key sent by the server and initialize
1372 * the RC4 encryption. */
1373 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1374 tosend + 1, type)) < 0)
1375 return ret;
1376
1377 /* Encrypt the signature received by the server. */
1378 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1379 }
1380 #endif
1381
1382 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1383 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1384 return AVERROR(EIO);
1385 }
1386
1387 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1388 tosend[i] = av_lfg_get(&rnd) >> 24;
1389 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1390 rtmp_player_key, sizeof(rtmp_player_key),
1391 digest);
1392 if (ret < 0)
1393 return ret;
1394
1395 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1396 digest, 32,
1397 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1398 if (ret < 0)
1399 return ret;
1400
1401 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1402 if (rt->encrypted) {
1403 /* Encrypt the signature to be send to the server. */
1404 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1405 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1406 serverdata[0]);
1407 }
1408 #endif
1409
1410 // write reply back to the server
1411 if ((ret = ffurl_write(rt->stream, tosend,
1412 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1413 return ret;
1414
1415 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1416 if (rt->encrypted) {
1417 /* Set RC4 keys for encryption and update the keystreams. */
1418 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1419 return ret;
1420 }
1421 #endif
1422 } else {
1423 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1424 if (rt->encrypted) {
1425 /* Compute the shared secret key sent by the server and initialize
1426 * the RC4 encryption. */
1427 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1428 tosend + 1, 1)) < 0)
1429 return ret;
1430
1431 if (serverdata[0] == 9) {
1432 /* Encrypt the signature received by the server. */
1433 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1434 serverdata[0]);
1435 }
1436 }
1437 #endif
1438
1439 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1440 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1441 return ret;
1442
1443 #if CONFIG_FFRTMPCRYPT_PROTOCOL
1444 if (rt->encrypted) {
1445 /* Set RC4 keys for encryption and update the keystreams. */
1446 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1447 return ret;
1448 }
1449 #endif
1450 }
1451
1452 return 0;
1453 }
1454
1455 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1456 uint32_t *second_int, char *arraydata,
1457 int size)
1458 {
1459 int inoutsize;
1460
1461 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1462 RTMP_HANDSHAKE_PACKET_SIZE);
1463 if (inoutsize <= 0)
1464 return AVERROR(EIO);
1465 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1466 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1467 " not following standard\n", (int)inoutsize);
1468 return AVERROR(EINVAL);
1469 }
1470
1471 *first_int = AV_RB32(arraydata);
1472 *second_int = AV_RB32(arraydata + 4);
1473 return 0;
1474 }
1475
1476 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1477 uint32_t second_int, char *arraydata, int size)
1478 {
1479 int inoutsize;
1480
1481 AV_WB32(arraydata, first_int);
1482 AV_WB32(arraydata + 4, second_int);
1483 inoutsize = ffurl_write(rt->stream, arraydata,
1484 RTMP_HANDSHAKE_PACKET_SIZE);
1485 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1486 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1487 return AVERROR(EIO);
1488 }
1489
1490 return 0;
1491 }
1492
1493 /**
1494 * rtmp handshake server side
1495 */
1496 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1497 {
1498 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1499 uint32_t hs_epoch;
1500 uint32_t hs_my_epoch;
1501 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1502 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1503 uint32_t zeroes;
1504 uint32_t temp = 0;
1505 int randomidx = 0;
1506 int inoutsize = 0;
1507 int ret;
1508
1509 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1510 if (inoutsize <= 0) {
1511 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1512 return AVERROR(EIO);
1513 }
1514 // Check Version
1515 if (buffer[0] != 3) {
1516 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1517 return AVERROR(EIO);
1518 }
1519 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1520 av_log(s, AV_LOG_ERROR,
1521 "Unable to write answer - RTMP S0\n");
1522 return AVERROR(EIO);
1523 }
1524 /* Receive C1 */
1525 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1526 RTMP_HANDSHAKE_PACKET_SIZE);
1527 if (ret) {
1528 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1529 return ret;
1530 }
1531 /* Send S1 */
1532 /* By now same epoch will be sent */
1533 hs_my_epoch = hs_epoch;
1534 /* Generate random */
1535 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1536 randomidx += 4)
1537 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1538
1539 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1540 RTMP_HANDSHAKE_PACKET_SIZE);
1541 if (ret) {
1542 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1543 return ret;
1544 }
1545 /* Send S2 */
1546 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1547 RTMP_HANDSHAKE_PACKET_SIZE);
1548 if (ret) {
1549 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1550 return ret;
1551 }
1552 /* Receive C2 */
1553 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1554 RTMP_HANDSHAKE_PACKET_SIZE);
1555 if (ret) {
1556 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1557 return ret;
1558 }
1559 if (temp != hs_my_epoch)
1560 av_log(s, AV_LOG_WARNING,
1561 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1562 if (memcmp(buffer + 8, hs_s1 + 8,
1563 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1564 av_log(s, AV_LOG_WARNING,
1565 "Erroneous C2 Message random does not match up\n");
1566
1567 return 0;
1568 }
1569
1570 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1571 {
1572 RTMPContext *rt = s->priv_data;
1573 int ret;
1574
1575 if (pkt->size < 4) {
1576 av_log(s, AV_LOG_ERROR,
1577 "Too short chunk size change packet (%d)\n",
1578 pkt->size);
1579 return AVERROR_INVALIDDATA;
1580 }
1581
1582 if (!rt->is_input) {
1583 /* Send the same chunk size change packet back to the server,
1584 * setting the outgoing chunk size to the same as the incoming one. */
1585 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1586 &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1587 return ret;
1588 rt->out_chunk_size = AV_RB32(pkt->data);
1589 }
1590
1591 rt->in_chunk_size = AV_RB32(pkt->data);
1592 if (rt->in_chunk_size <= 0) {
1593 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1594 rt->in_chunk_size);
1595 return AVERROR_INVALIDDATA;
1596 }
1597 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1598 rt->in_chunk_size);
1599
1600 return 0;
1601 }
1602
1603 static int handle_user_control(URLContext *s, RTMPPacket *pkt)
1604 {
1605 RTMPContext *rt = s->priv_data;
1606 int t, ret;
1607
1608 if (pkt->size < 2) {
1609 av_log(s, AV_LOG_ERROR, "Too short user control packet (%d)\n",
1610 pkt->size);
1611 return AVERROR_INVALIDDATA;
1612 }
1613
1614 t = AV_RB16(pkt->data);
1615 if (t == 6) { // PingRequest
1616 if ((ret = gen_pong(s, rt, pkt)) < 0)
1617 return ret;
1618 } else if (t == 26) {
1619 if (rt->swfsize) {
1620 if ((ret = gen_swf_verification(s, rt)) < 0)
1621 return ret;
1622 } else {
1623 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1624 }
1625 }
1626
1627 return 0;
1628 }
1629
1630 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt)
1631 {
1632 RTMPContext *rt = s->priv_data;
1633
1634 if (pkt->size < 4) {
1635 av_log(s, AV_LOG_ERROR,
1636 "Peer bandwidth packet is less than 4 bytes long (%d)\n",
1637 pkt->size);
1638 return AVERROR_INVALIDDATA;
1639 }
1640
1641 // We currently don't check how much the peer has acknowledged of
1642 // what we have sent. To do that properly, we should call
1643 // gen_window_ack_size here, to tell the peer that we want an
1644 // acknowledgement with (at least) that interval.
1645 rt->max_sent_unacked = AV_RB32(pkt->data);
1646 if (rt->max_sent_unacked <= 0) {
1647 av_log(s, AV_LOG_ERROR, "Incorrect set peer bandwidth %d\n",
1648 rt->max_sent_unacked);
1649 return AVERROR_INVALIDDATA;
1650
1651 }
1652 av_log(s, AV_LOG_DEBUG, "Max sent, unacked = %d\n", rt->max_sent_unacked);
1653
1654 return 0;
1655 }
1656
1657 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt)
1658 {
1659 RTMPContext *rt = s->priv_data;
1660
1661 if (pkt->size < 4) {
1662 av_log(s, AV_LOG_ERROR,
1663 "Too short window acknowledgement size packet (%d)\n",
1664 pkt->size);
1665 return AVERROR_INVALIDDATA;
1666 }
1667
1668 rt->receive_report_size = AV_RB32(pkt->data);
1669 if (rt->receive_report_size <= 0) {
1670 av_log(s, AV_LOG_ERROR, "Incorrect window acknowledgement size %d\n",
1671 rt->receive_report_size);
1672 return AVERROR_INVALIDDATA;
1673 }
1674 av_log(s, AV_LOG_DEBUG, "Window acknowledgement size = %d\n", rt->receive_report_size);
1675 // Send an Acknowledgement packet after receiving half the maximum
1676 // size, to make sure the peer can keep on sending without waiting
1677 // for acknowledgements.
1678 rt->receive_report_size >>= 1;
1679
1680 return 0;
1681 }
1682
1683 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1684 const char *opaque, const char *challenge)
1685 {
1686 uint8_t hash[16];
1687 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1688 struct AVMD5 *md5 = av_md5_alloc();
1689 if (!md5)
1690 return AVERROR(ENOMEM);
1691
1692 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1693
1694 av_md5_init(md5);
1695 av_md5_update(md5, user, strlen(user));
1696 av_md5_update(md5, salt, strlen(salt));
1697 av_md5_update(md5, rt->password, strlen(rt->password));
1698 av_md5_final(md5, hash);
1699 av_base64_encode(hashstr, sizeof(hashstr), hash,
1700 sizeof(hash));
1701 av_md5_init(md5);
1702 av_md5_update(md5, hashstr, strlen(hashstr));
1703 if (opaque)
1704 av_md5_update(md5, opaque, strlen(opaque));
1705 else if (challenge)
1706 av_md5_update(md5, challenge, strlen(challenge));
1707 av_md5_update(md5, challenge2, strlen(challenge2));
1708 av_md5_final(md5, hash);
1709 av_base64_encode(hashstr, sizeof(hashstr), hash,
1710 sizeof(hash));
1711 snprintf(rt->auth_params, sizeof(rt->auth_params),
1712 "?authmod=%s&user=%s&challenge=%s&response=%s",
1713 "adobe", user, challenge2, hashstr);
1714 if (opaque)
1715 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1716 "&opaque=%s", opaque);
1717
1718 av_free(md5);
1719 return 0;
1720 }
1721
1722 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1723 {
1724 uint8_t hash[16];
1725 char hashstr1[33], hashstr2[33];
1726 const char *realm = "live";
1727 const char *method = "publish";
1728 const char *qop = "auth";
1729 const char *nc = "00000001";
1730 char cnonce[10];
1731 struct AVMD5 *md5 = av_md5_alloc();
1732 if (!md5)
1733 return AVERROR(ENOMEM);
1734
1735 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1736
1737 av_md5_init(md5);
1738 av_md5_update(md5, user, strlen(user));
1739 av_md5_update(md5, ":", 1);
1740 av_md5_update(md5, realm, strlen(realm));
1741 av_md5_update(md5, ":", 1);
1742 av_md5_update(md5, rt->password, strlen(rt->password));
1743 av_md5_final(md5, hash);
1744 ff_data_to_hex(hashstr1, hash, 16, 1);
1745
1746 av_md5_init(md5);
1747 av_md5_update(md5, method, strlen(method));
1748 av_md5_update(md5, ":/", 2);
1749 av_md5_update(md5, rt->app, strlen(rt->app));
1750 if (!strchr(rt->app, '/'))
1751 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1752 av_md5_final(md5, hash);
1753 ff_data_to_hex(hashstr2, hash, 16, 1);
1754
1755 av_md5_init(md5);
1756 av_md5_update(md5, hashstr1, strlen(hashstr1));
1757 av_md5_update(md5, ":", 1);
1758 if (nonce)
1759 av_md5_update(md5, nonce, strlen(nonce));
1760 av_md5_update(md5, ":", 1);
1761 av_md5_update(md5, nc, strlen(nc));
1762 av_md5_update(md5, ":", 1);
1763 av_md5_update(md5, cnonce, strlen(cnonce));
1764 av_md5_update(md5, ":", 1);
1765 av_md5_update(md5, qop, strlen(qop));
1766 av_md5_update(md5, ":", 1);
1767 av_md5_update(md5, hashstr2, strlen(hashstr2));
1768 av_md5_final(md5, hash);
1769 ff_data_to_hex(hashstr1, hash, 16, 1);
1770
1771 snprintf(rt->auth_params, sizeof(rt->auth_params),
1772 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1773 "llnw", user, nonce, cnonce, nc, hashstr1);
1774
1775 av_free(md5);
1776 return 0;
1777 }
1778
1779 static int handle_connect_error(URLContext *s, const char *desc)
1780 {
1781 RTMPContext *rt = s->priv_data;
1782 char buf[300], *ptr, authmod[15];
1783 int i = 0, ret = 0;
1784 const char *user = "", *salt = "", *opaque = NULL,
1785 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1786
1787 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1788 !(cptr = strstr(desc, "authmod=llnw"))) {
1789 av_log(s, AV_LOG_ERROR,
1790 "Unknown connect error (unsupported authentication method?)\n");
1791 return AVERROR_UNKNOWN;
1792 }
1793 cptr += strlen("authmod=");
1794 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1795 authmod[i++] = *cptr++;
1796 authmod[i] = '\0';
1797
1798 if (!rt->username[0] || !rt->password[0]) {
1799 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1800 return AVERROR_UNKNOWN;
1801 }
1802
1803 if (strstr(desc, "?reason=authfailed")) {
1804 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1805 return AVERROR_UNKNOWN;
1806 } else if (strstr(desc, "?reason=nosuchuser")) {
1807 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1808 return AVERROR_UNKNOWN;
1809 }
1810
1811 if (rt->auth_tried) {
1812 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1813 return AVERROR_UNKNOWN;
1814 }
1815
1816 rt->auth_params[0] = '\0';
1817
1818 if (strstr(desc, "code=403 need auth")) {
1819 snprintf(rt->auth_params, sizeof(rt->auth_params),
1820 "?authmod=%s&user=%s", authmod, rt->username);
1821 return 0;
1822 }
1823
1824 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1825 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1826 return AVERROR_UNKNOWN;
1827 }
1828
1829 av_strlcpy(buf, cptr + 1, sizeof(buf));
1830 ptr = buf;
1831
1832 while (ptr) {
1833 char *next = strchr(ptr, '&');
1834 char *value = strchr(ptr, '=');
1835 if (next)
1836 *next++ = '\0';
1837 if (value) {
1838 *value++ = '\0';
1839 if (!strcmp(ptr, "user")) {
1840 user = value;
1841 } else if (!strcmp(ptr, "salt")) {
1842 salt = value;
1843 } else if (!strcmp(ptr, "opaque")) {
1844 opaque = value;
1845 } else if (!strcmp(ptr, "challenge")) {
1846 challenge = value;
1847 } else if (!strcmp(ptr, "nonce")) {
1848 nonce = value;
1849 } else {
1850 av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1851 }
1852 } else {
1853 av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1854 }
1855 ptr = next;
1856 }
1857
1858 if (!strcmp(authmod, "adobe")) {
1859 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1860 return ret;
1861 } else {
1862 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1863 return ret;
1864 }
1865
1866 rt->auth_tried = 1;
1867 return 0;
1868 }
1869
1870 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1871 {
1872 RTMPContext *rt = s->priv_data;
1873 const uint8_t *data_end = pkt->data + pkt->size;
1874 char *tracked_method = NULL;
1875 int level = AV_LOG_ERROR;
1876 uint8_t tmpstr[256];
1877 int ret;
1878
1879 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1880 return ret;
1881
1882 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1883 "description", tmpstr, sizeof(tmpstr))) {
1884 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1885 !strcmp(tracked_method, "releaseStream") ||
1886 !strcmp(tracked_method, "FCSubscribe") ||
1887 !strcmp(tracked_method, "FCPublish"))) {
1888 /* Gracefully ignore Adobe-specific historical artifact errors. */
1889 level = AV_LOG_WARNING;
1890 ret = 0;
1891 } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
1892 level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
1893 ret = 0;
1894 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1895 ret = handle_connect_error(s, tmpstr);
1896 if (!ret) {
1897 rt->do_reconnect = 1;
1898 level = AV_LOG_VERBOSE;
1899 }
1900 } else
1901 ret = AVERROR_UNKNOWN;
1902 av_log(s, level, "Server error: %s\n", tmpstr);
1903 }
1904
1905 av_free(tracked_method);
1906 return ret;
1907 }
1908
1909 static int write_begin(URLContext *s)
1910 {
1911 RTMPContext *rt = s->priv_data;
1912 PutByteContext pbc;
1913 RTMPPacket spkt = { 0 };
1914 int ret;
1915
1916 // Send Stream Begin 1
1917 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1918 RTMP_PT_USER_CONTROL, 0, 6)) < 0) {
1919 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1920 return ret;
1921 }
1922
1923 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1924 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1925 bytestream2_put_be32(&pbc, rt->nb_streamid);
1926
1927 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1928 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1929
1930 ff_rtmp_packet_destroy(&spkt);
1931
1932 return ret;
1933 }
1934
1935 static int write_status(URLContext *s, RTMPPacket *pkt,
1936 const char *status, const char *description, const char *details)
1937 {
1938 RTMPContext *rt = s->priv_data;
1939 RTMPPacket spkt = { 0 };
1940 uint8_t *pp;
1941 int ret;
1942
1943 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1944 RTMP_PT_INVOKE, 0,
1945 RTMP_PKTDATA_DEFAULT_SIZE
1946 + strlen(status) + strlen(description)
1947 + zstrlen(details))) < 0) {
1948 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1949 return ret;
1950 }
1951
1952 pp = spkt.data;
1953 spkt.extra = pkt->extra;
1954 ff_amf_write_string(&pp, "onStatus");
1955 ff_amf_write_number(&pp, 0);
1956 ff_amf_write_null(&pp);
1957
1958 ff_amf_write_object_start(&pp);
1959 ff_amf_write_field_name(&pp, "level");
1960 ff_amf_write_string(&pp, "status");
1961 ff_amf_write_field_name(&pp, "code");
1962 ff_amf_write_string(&pp, status);
1963 ff_amf_write_field_name(&pp, "description");
1964 ff_amf_write_string(&pp, description);
1965 if (details) {
1966 ff_amf_write_field_name(&pp, "details");
1967 ff_amf_write_string(&pp, details);
1968 }
1969 ff_amf_write_object_end(&pp);
1970
1971 spkt.size = pp - spkt.data;
1972 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1973 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1974 ff_rtmp_packet_destroy(&spkt);
1975
1976 return ret;
1977 }
1978
1979 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1980 {
1981 RTMPContext *rt = s->priv_data;
1982 double seqnum;
1983 char filename[128];
1984 char command[64];
1985 int stringlen;
1986 char *pchar;
1987 const uint8_t *p = pkt->data;
1988 uint8_t *pp = NULL;
1989 RTMPPacket spkt = { 0 };
1990 GetByteContext gbc;
1991 int ret;
1992
1993 bytestream2_init(&gbc, p, pkt->size);
1994 if (ff_amf_read_string(&gbc, command, sizeof(command),
1995 &stringlen)) {
1996 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1997 return AVERROR_INVALIDDATA;
1998 }
1999
2000 ret = ff_amf_read_number(&gbc, &seqnum);
2001 if (ret)
2002 return ret;
2003 ret = ff_amf_read_null(&gbc);
2004 if (ret)
2005 return ret;
2006 if (!strcmp(command, "FCPublish") ||
2007 !strcmp(command, "publish")) {
2008 ret = ff_amf_read_string(&gbc, filename,
2009 sizeof(filename), &stringlen);
2010 if (ret) {
2011 if (ret == AVERROR(EINVAL))
2012 av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n");
2013 else
2014 av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n");
2015 return ret;
2016 }
2017 // check with url
2018 if (s->filename) {
2019 pchar = strrchr(s->filename, '/');
2020 if (!pchar) {
2021 av_log(s, AV_LOG_WARNING,
2022 "Unable to find / in url %s, bad format\n",
2023 s->filename);
2024 pchar = s->filename;
2025 }
2026 pchar++;
2027 if (strcmp(pchar, filename))
2028 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
2029 " %s\n", filename, pchar);
2030 }
2031 rt->state = STATE_RECEIVING;
2032 }
2033
2034 if (!strcmp(command, "FCPublish")) {
2035 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2036 RTMP_PT_INVOKE, 0,
2037 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2038 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2039 return ret;
2040 }
2041 pp = spkt.data;
2042 ff_amf_write_string(&pp, "onFCPublish");
2043 } else if (!strcmp(command, "publish")) {
2044 char statusmsg[sizeof(filename) + 32];
2045 snprintf(statusmsg, sizeof(statusmsg), "%s is now published", filename);
2046 ret = write_begin(s);
2047 if (ret < 0)
2048 return ret;
2049
2050 // Send onStatus(NetStream.Publish.Start)
2051 return write_status(s, pkt, "NetStream.Publish.Start",
2052 statusmsg, filename);
2053 } else if (!strcmp(command, "play")) {
2054 ret = write_begin(s);
2055 if (ret < 0)
2056 return ret;
2057 rt->state = STATE_SENDING;
2058 return write_status(s, pkt, "NetStream.Play.Start",
2059 "playing stream", NULL);
2060 } else {
2061 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2062 RTMP_PT_INVOKE, 0,
2063 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2064 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2065 return ret;
2066 }
2067 pp = spkt.data;
2068 ff_amf_write_string(&pp, "_result");
2069 ff_amf_write_number(&pp, seqnum);
2070 ff_amf_write_null(&pp);
2071 if (!strcmp(command, "createStream")) {
2072 rt->nb_streamid++;
2073 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
2074 rt->nb_streamid++; /* Values 0 and 2 are reserved */
2075 ff_amf_write_number(&pp, rt->nb_streamid);
2076 /* By now we don't control which streams are removed in
2077 * deleteStream. There is no stream creation control
2078 * if a client creates more than 2^32 - 2 streams. */
2079 }
2080 }
2081 spkt.size = pp - spkt.data;
2082 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
2083 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
2084 ff_rtmp_packet_destroy(&spkt);
2085 return ret;
2086 }
2087
2088 /**
2089 * Read the AMF_NUMBER response ("_result") to a function call
2090 * (e.g. createStream()). This response should be made up of the AMF_STRING
2091 * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
2092 * successful response, we will return set the value to number (otherwise number
2093 * will not be changed).
2094 *
2095 * @return 0 if reading the value succeeds, negative value otherwise
2096 */
2097 static int read_number_result(RTMPPacket *pkt, double *number)
2098 {
2099 // We only need to fit "_result" in this.
2100 uint8_t strbuffer[8];
2101 int stringlen;
2102 double numbuffer;
2103 GetByteContext gbc;
2104
2105 bytestream2_init(&gbc, pkt->data, pkt->size);
2106
2107 // Value 1/4: "_result" as AMF_STRING
2108 if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
2109 return AVERROR_INVALIDDATA;
2110 if (strcmp(strbuffer, "_result"))
2111 return AVERROR_INVALIDDATA;
2112 // Value 2/4: The callee reference number
2113 if (ff_amf_read_number(&gbc, &numbuffer))
2114 return AVERROR_INVALIDDATA;
2115 // Value 3/4: Null
2116 if (ff_amf_read_null(&gbc))
2117 return AVERROR_INVALIDDATA;
2118 // Value 4/4: The response as AMF_NUMBER
2119 if (ff_amf_read_number(&gbc, &numbuffer))
2120 return AVERROR_INVALIDDATA;
2121 else
2122 *number = numbuffer;
2123
2124 return 0;
2125 }
2126
2127 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
2128 {
2129 RTMPContext *rt = s->priv_data;
2130 char *tracked_method = NULL;
2131 int ret = 0;
2132
2133 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
2134 return ret;
2135
2136 if (!tracked_method) {
2137 /* Ignore this reply when the current method is not tracked. */
2138 return ret;
2139 }
2140
2141 if (!strcmp(tracked_method, "connect")) {
2142 if (!rt->is_input) {
2143 if ((ret = gen_release_stream(s, rt)) < 0)
2144 goto fail;
2145
2146 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
2147 goto fail;
2148 } else {
2149 if ((ret = gen_window_ack_size(s, rt)) < 0)
2150 goto fail;
2151 }
2152
2153 if ((ret = gen_create_stream(s, rt)) < 0)
2154 goto fail;
2155
2156 if (rt->is_input) {
2157 /* Send the FCSubscribe command when the name of live
2158 * stream is defined by the user or if it's a live stream. */
2159 if (rt->subscribe) {
2160 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
2161 goto fail;
2162 } else if (rt->live == -1) {
2163 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2164 goto fail;
2165 }
2166 }
2167 } else if (!strcmp(tracked_method, "createStream")) {
2168 double stream_id;
2169 if (read_number_result(pkt, &stream_id)) {
2170 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2171 } else {
2172 rt->stream_id = stream_id;
2173 }
2174
2175 if (!rt->is_input) {
2176 if ((ret = gen_publish(s, rt)) < 0)
2177 goto fail;
2178 } else {
2179 if (rt->live != -1) {
2180 if ((ret = gen_get_stream_length(s, rt)) < 0)
2181 goto fail;
2182 }
2183 if ((ret = gen_play(s, rt)) < 0)
2184 goto fail;
2185 if ((ret = gen_buffer_time(s, rt)) < 0)
2186 goto fail;
2187 }
2188 } else if (!strcmp(tracked_method, "getStreamLength")) {
2189 if (read_number_result(pkt, &rt->duration)) {
2190 av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n");
2191 }
2192 }
2193
2194 fail:
2195 av_free(tracked_method);
2196 return ret;
2197 }
2198
2199 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2200 {
2201 RTMPContext *rt = s->priv_data;
2202 const uint8_t *data_end = pkt->data + pkt->size;
2203 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2204 uint8_t tmpstr[256];
2205 int i, t;
2206
2207 for (i = 0; i < 2; i++) {
2208 t = ff_amf_tag_size(ptr, data_end);
2209 if (t < 0)
2210 return 1;
2211 ptr += t;
2212 }
2213
2214 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2215 if (!t && !strcmp(tmpstr, "error")) {
2216 t = ff_amf_get_field_value(ptr, data_end,
2217 "description", tmpstr, sizeof(tmpstr));
2218 if (t || !tmpstr[0])
2219 t = ff_amf_get_field_value(ptr, data_end, "code",
2220 tmpstr, sizeof(tmpstr));
2221 if (!t)
2222 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2223 return -1;
2224 }
2225
2226 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2227 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2228 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2229 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2230 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2231 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2232
2233 return 0;
2234 }
2235
2236 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2237 {
2238 RTMPContext *rt = s->priv_data;
2239 int ret = 0;
2240
2241 //TODO: check for the messages sent for wrong state?
2242 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2243 if ((ret = handle_invoke_error(s, pkt)) < 0)
2244 return ret;
2245 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2246 if ((ret = handle_invoke_result(s, pkt)) < 0)
2247 return ret;
2248 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2249 if ((ret = handle_invoke_status(s, pkt)) < 0)
2250 return ret;
2251 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2252 if ((ret = gen_check_bw(s, rt)) < 0)
2253 return ret;
2254 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2255 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2256 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2257 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2258 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2259 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2260 if ((ret = send_invoke_response(s, pkt)) < 0)
2261 return ret;
2262 }
2263
2264 return ret;
2265 }
2266
2267 static int update_offset(RTMPContext *rt, int size)
2268 {
2269 int old_flv_size;
2270
2271 // generate packet header and put data into buffer for FLV demuxer
2272 if (rt->flv_off < rt->flv_size) {
2273 // There is old unread data in the buffer, thus append at the end
2274 old_flv_size = rt->flv_size;
2275 rt->flv_size += size;
2276 } else {
2277 // All data has been read, write the new data at the start of the buffer
2278 old_flv_size = 0;
2279 rt->flv_size = size;
2280 rt->flv_off = 0;
2281 }
2282
2283 return old_flv_size;
2284 }
2285
2286 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2287 {
2288 int old_flv_size, ret;
2289 PutByteContext pbc;
2290 const uint8_t *data = pkt->data + skip;
2291 const int size = pkt->size - skip;
2292 uint32_t ts = pkt->timestamp;
2293
2294 if (pkt->type == RTMP_PT_AUDIO) {
2295 rt->has_audio = 1;
2296 } else if (pkt->type == RTMP_PT_VIDEO) {
2297 rt->has_video = 1;
2298 }
2299
2300 old_flv_size = update_offset(rt, size + 15);
2301
2302 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2303 rt->flv_size = rt->flv_off = 0;
2304 return ret;
2305 }
2306 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2307 bytestream2_skip_p(&pbc, old_flv_size);
2308 bytestream2_put_byte(&pbc, pkt->type);
2309 bytestream2_put_be24(&pbc, size);
2310 bytestream2_put_be24(&pbc, ts);
2311 bytestream2_put_byte(&pbc, ts >> 24);
2312 bytestream2_put_be24(&pbc, 0);
2313 bytestream2_put_buffer(&pbc, data, size);
2314 bytestream2_put_be32(&pbc, size + RTMP_HEADER);
2315
2316 return 0;
2317 }
2318
2319 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2320 {
2321 RTMPContext *rt = s->priv_data;
2322 uint8_t commandbuffer[64];
2323 char statusmsg[128];
2324 int stringlen, ret, skip = 0;
2325 GetByteContext gbc;
2326
2327 bytestream2_init(&gbc, pkt->data, pkt->size);
2328 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2329 &stringlen))
2330 return AVERROR_INVALIDDATA;
2331
2332 if (!strcmp(commandbuffer, "onMetaData")) {
2333 // metadata properties should be stored in a mixed array
2334 if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2335 // We have found a metaData Array so flv can determine the streams
2336 // from this.
2337 rt->received_metadata = 1;
2338 // skip 32-bit max array index
2339 bytestream2_skip(&gbc, 4);
2340 while (bytestream2_get_bytes_left(&gbc) > 3) {
2341 if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2342 &stringlen))
2343 return AVERROR_INVALIDDATA;
2344 // We do not care about the content of the property (yet).
2345 stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2346 if (stringlen < 0)
2347 return AVERROR_INVALIDDATA;
2348 bytestream2_skip(&gbc, stringlen);
2349
2350 // The presence of the following properties indicates that the
2351 // respective streams are present.
2352 if (!strcmp(statusmsg, "videocodecid")) {
2353 rt->has_video = 1;
2354 }
2355 if (!strcmp(statusmsg, "audiocodecid")) {
2356 rt->has_audio = 1;
2357 }
2358 }
2359 if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2360 return AVERROR_INVALIDDATA;
2361 }
2362 }
2363
2364 // Skip the @setDataFrame string and validate it is a notification
2365 if (!strcmp(commandbuffer, "@setDataFrame")) {
2366 skip = gbc.buffer - pkt->data;
2367 ret = ff_amf_read_string(&gbc, statusmsg,
2368 sizeof(statusmsg), &stringlen);
2369 if (ret < 0)
2370 return AVERROR_INVALIDDATA;
2371 }
2372
2373 return append_flv_data(rt, pkt, skip);
2374 }
2375
2376 /**
2377 * Parse received packet and possibly perform some action depending on
2378 * the packet contents.
2379 * @return 0 for no errors, negative values for serious errors which prevent
2380 * further communications, positive values for uncritical errors
2381 */
2382 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2383 {
2384 int ret;
2385
2386 #ifdef DEBUG
2387 ff_rtmp_packet_dump(s, pkt);
2388 #endif
2389
2390 switch (pkt->type) {
2391 case RTMP_PT_BYTES_READ:
2392 av_log(s, AV_LOG_TRACE, "received bytes read report\n");
2393 break;
2394 case RTMP_PT_CHUNK_SIZE:
2395 if ((ret = handle_chunk_size(s, pkt)) < 0)
2396 return ret;
2397 break;
2398 case RTMP_PT_USER_CONTROL:
2399 if ((ret = handle_user_control(s, pkt)) < 0)
2400 return ret;
2401 break;
2402 case RTMP_PT_SET_PEER_BW:
2403 if ((ret = handle_set_peer_bw(s, pkt)) < 0)
2404 return ret;
2405 break;
2406 case RTMP_PT_WINDOW_ACK_SIZE:
2407 if ((ret = handle_window_ack_size(s, pkt)) < 0)
2408 return ret;
2409 break;
2410 case RTMP_PT_INVOKE:
2411 if ((ret = handle_invoke(s, pkt)) < 0)
2412 return ret;
2413 break;
2414 case RTMP_PT_VIDEO:
2415 case RTMP_PT_AUDIO:
2416 case RTMP_PT_METADATA:
2417 case RTMP_PT_NOTIFY:
2418 /* Audio, Video and Metadata packets are parsed in get_packet() */
2419 break;
2420 default:
2421 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2422 break;
2423 }
2424 return 0;
2425 }
2426
2427 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2428 {
2429 int ret, old_flv_size, type;
2430 const uint8_t *next;
2431 uint8_t *p;
2432 uint32_t size;
2433 uint32_t ts, cts, pts = 0;
2434
2435 old_flv_size = update_offset(rt, pkt->size);
2436
2437 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2438 rt->flv_size = rt->flv_off = 0;
2439 return ret;
2440 }
2441
2442 next = pkt->data;
2443 p = rt->flv_data + old_flv_size;
2444
2445 /* copy data while rewriting timestamps */
2446 ts = pkt->timestamp;
2447
2448 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2449 type = bytestream_get_byte(&next);
2450 size = bytestream_get_be24(&next);
2451 cts = bytestream_get_be24(&next);
2452 cts |= bytestream_get_byte(&next) << 24;
2453 if (!pts)
2454 pts = cts;
2455 ts += cts - pts;
2456 pts = cts;
2457 if (size + 3 + 4 > pkt->data + pkt->size - next)
2458 break;
2459 bytestream_put_byte(&p, type);
2460 bytestream_put_be24(&p, size);
2461 bytestream_put_be24(&p, ts);
2462 bytestream_put_byte(&p, ts >> 24);
2463 memcpy(p, next, size + 3 + 4);
2464 p += size + 3;
2465 bytestream_put_be32(&p, size + RTMP_HEADER);
2466 next += size + 3 + 4;
2467 }
2468 if (p != rt->flv_data + rt->flv_size) {
2469 av_log(rt, AV_LOG_WARNING, "Incomplete flv packets in "
2470 "RTMP_PT_METADATA packet\n");
2471 rt->flv_size = p - rt->flv_data;
2472 }
2473
2474 return 0;
2475 }
2476
2477 /**
2478 * Interact with the server by receiving and sending RTMP packets until
2479 * there is some significant data (media data or expected status notification).
2480 *
2481 * @param s reading context
2482 * @param for_header non-zero value tells function to work until it
2483 * gets notification from the server that playing has been started,
2484 * otherwise function will work until some media data is received (or
2485 * an error happens)
2486 * @return 0 for successful operation, negative value in case of error
2487 */
2488 static int get_packet(URLContext *s, int for_header)
2489 {
2490 RTMPContext *rt = s->priv_data;
2491 int ret;
2492
2493 if (rt->state == STATE_STOPPED)
2494 return AVERROR_EOF;
2495
2496 for (;;) {
2497 RTMPPacket rpkt = { 0 };
2498 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2499 rt->in_chunk_size, &rt->prev_pkt[0],
2500 &rt->nb_prev_pkt[0])) <= 0) {
2501 if (ret == 0) {
2502 return AVERROR(EAGAIN);
2503 } else {
2504 return AVERROR(EIO);
2505 }
2506 }
2507
2508 // Track timestamp for later use
2509 rt->last_timestamp = rpkt.timestamp;
2510
2511 rt->bytes_read += ret;
2512 if (rt->bytes_read - rt->last_bytes_read > rt->receive_report_size) {
2513 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2514 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0) {
2515 ff_rtmp_packet_destroy(&rpkt);
2516 return ret;
2517 }
2518 rt->last_bytes_read = rt->bytes_read;
2519 }
2520
2521 ret = rtmp_parse_result(s, rt, &rpkt);
2522
2523 // At this point we must check if we are in the seek state and continue
2524 // with the next packet. handle_invoke will get us out of this state
2525 // when the right message is encountered
2526 if (rt->state == STATE_SEEKING) {
2527 ff_rtmp_packet_destroy(&rpkt);
2528 // We continue, let the natural flow of things happen:
2529 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2530 continue;
2531 }
2532
2533 if (ret < 0) {//serious error in current packet
2534 ff_rtmp_packet_destroy(&rpkt);
2535 return ret;
2536 }
2537 if (rt->do_reconnect && for_header) {
2538 ff_rtmp_packet_destroy(&rpkt);
2539 return 0;
2540 }
2541 if (rt->state == STATE_STOPPED) {
2542 ff_rtmp_packet_destroy(&rpkt);
2543 return AVERROR_EOF;
2544 }
2545 if (for_header && (rt->state == STATE_PLAYING ||
2546 rt->state == STATE_PUBLISHING ||
2547 rt->state == STATE_SENDING ||
2548 rt->state == STATE_RECEIVING)) {
2549 ff_rtmp_packet_destroy(&rpkt);
2550 return 0;
2551 }
2552 if (!rpkt.size || !rt->is_input) {
2553 ff_rtmp_packet_destroy(&rpkt);
2554 continue;
2555 }
2556 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2557 ret = append_flv_data(rt, &rpkt, 0);
2558 ff_rtmp_packet_destroy(&rpkt);
2559 return ret;
2560 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2561 ret = handle_notify(s, &rpkt);
2562 ff_rtmp_packet_destroy(&rpkt);
2563 return ret;
2564 } else if (rpkt.type == RTMP_PT_METADATA) {
2565 ret = handle_metadata(rt, &rpkt);
2566 ff_rtmp_packet_destroy(&rpkt);
2567 return ret;
2568 }
2569 ff_rtmp_packet_destroy(&rpkt);
2570 }
2571 }
2572
2573 static int rtmp_close(URLContext *h)
2574 {
2575 RTMPContext *rt = h->priv_data;
2576 int ret = 0, i, j;
2577
2578 if (!rt->is_input) {
2579 rt->flv_data = NULL;
2580 if (rt->out_pkt.size)
2581 ff_rtmp_packet_destroy(&rt->out_pkt);
2582 if (rt->state > STATE_FCPUBLISH)
2583 ret = gen_fcunpublish_stream(h, rt);
2584 }
2585 if (rt->state > STATE_HANDSHAKED)
2586 ret = gen_delete_stream(h, rt);
2587 for (i = 0; i < 2; i++) {
2588 for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2589 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2590 av_freep(&rt->prev_pkt[i]);
2591 }
2592
2593 free_tracked_methods(rt);
2594 av_freep(&rt->flv_data);
2595 ffurl_closep(&rt->stream);
2596 return ret;
2597 }
2598
2599 /**
2600 * Insert a fake onMetadata packet into the FLV stream to notify the FLV
2601 * demuxer about the duration of the stream.
2602 *
2603 * This should only be done if there was no real onMetadata packet sent by the
2604 * server at the start of the stream and if we were able to retrieve a valid
2605 * duration via a getStreamLength call.
2606 *
2607 * @return 0 for successful operation, negative value in case of error
2608 */
2609 static int inject_fake_duration_metadata(RTMPContext *rt)
2610 {
2611 // We need to insert the metadata packet directly after the FLV
2612 // header, i.e. we need to move all other already read data by the
2613 // size of our fake metadata packet.
2614
2615 uint8_t* p;
2616 // Keep old flv_data pointer
2617 uint8_t* old_flv_data = rt->flv_data;
2618 // Allocate a new flv_data pointer with enough space for the additional package
2619 if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) {
2620 rt->flv_data = old_flv_data;
2621 return AVERROR(ENOMEM);
2622 }
2623
2624 // Copy FLV header
2625 memcpy(rt->flv_data, old_flv_data, 13);
2626 // Copy remaining packets
2627 memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13);
2628 // Increase the size by the injected packet
2629 rt->flv_size += 55;
2630 // Delete the old FLV data
2631 av_freep(&old_flv_data);
2632
2633 p = rt->flv_data + 13;
2634 bytestream_put_byte(&p, FLV_TAG_TYPE_META);
2635 bytestream_put_be24(&p, 40); // size of data part (sum of all parts below)
2636 bytestream_put_be24(&p, 0); // timestamp
2637 bytestream_put_be32(&p, 0); // reserved
2638
2639 // first event name as a string
2640 bytestream_put_byte(&p, AMF_DATA_TYPE_STRING);
2641 // "onMetaData" as AMF string
2642 bytestream_put_be16(&p, 10);
2643 bytestream_put_buffer(&p, "onMetaData", 10);
2644
2645 // mixed array (hash) with size and string/type/data tuples
2646 bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY);
2647 bytestream_put_be32(&p, 1); // metadata_count
2648
2649 // "duration" as AMF string
2650 bytestream_put_be16(&p, 8);
2651 bytestream_put_buffer(&p, "duration", 8);
2652 bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER);
2653 bytestream_put_be64(&p, av_double2int(rt->duration));
2654
2655 // Finalise object
2656 bytestream_put_be16(&p, 0); // Empty string
2657 bytestream_put_byte(&p, AMF_END_OF_OBJECT);
2658 bytestream_put_be32(&p, 40 + RTMP_HEADER); // size of data part (sum of all parts above)
2659
2660 return 0;
2661 }
2662
2663 /**
2664 * Open RTMP connection and verify that the stream can be played.
2665 *
2666 * URL syntax: rtmp://server[:port][/app][/playpath]
2667 * where 'app' is first one or two directories in the path
2668 * (e.g. /ondemand/, /flash/live/, etc.)
2669 * and 'playpath' is a file name (the rest of the path,
2670 * may be prefixed with "mp4:")
2671 */
2672 static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
2673 {
2674 RTMPContext *rt = s->priv_data;
2675 char proto[8], hostname[256], path[1024], auth[100], *fname;
2676 char *old_app, *qmark, *n, fname_buffer[1024];
2677 uint8_t buf[2048];
2678 int port;
2679 int ret;
2680
2681 if (rt->listen_timeout > 0)
2682 rt->listen = 1;
2683
2684 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2685
2686 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2687 hostname, sizeof(hostname), &port,
2688 path, sizeof(path), s->filename);
2689
2690 n = strchr(path, ' ');
2691 if (n) {
2692 av_log(s, AV_LOG_WARNING,
2693 "Detected librtmp style URL parameters, these aren't supported "
2694 "by the libavformat internal RTMP handler currently enabled. "
2695 "See the documentation for the correct way to pass parameters.\n");
2696 *n = '\0'; // Trim not supported part
2697 }
2698
2699 if (auth[0]) {
2700 char *ptr = strchr(auth, ':');
2701 if (ptr) {
2702 *ptr = '\0';
2703 av_strlcpy(rt->username, auth, sizeof(rt->username));
2704 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2705 }
2706 }
2707
2708 if (rt->listen && strcmp(proto, "rtmp")) {
2709 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2710 proto);
2711 return AVERROR(EINVAL);
2712 }
2713 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2714 if (!strcmp(proto, "rtmpts"))
2715 av_dict_set(opts, "ffrtmphttp_tls", "1", AV_DICT_MATCH_CASE);
2716
2717 /* open the http tunneling connection */
2718 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2719 } else if (!strcmp(proto, "rtmps")) {
2720 /* open the tls connection */
2721 if (port < 0)
2722 port = RTMPS_DEFAULT_PORT;
2723 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2724 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2725 if (!strcmp(proto, "rtmpte"))
2726 av_dict_set(opts, "ffrtmpcrypt_tunneling", "1", 1);
2727
2728 /* open the encrypted connection */
2729 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2730 rt->encrypted = 1;
2731 } else {
2732 /* open the tcp connection */
2733 if (port < 0)
2734 port = RTMP_DEFAULT_PORT;
2735 if (rt->listen)
2736 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2737 "?listen&listen_timeout=%d&tcp_nodelay=%d",
2738 rt->listen_timeout * 1000, rt->tcp_nodelay);
2739 else
2740 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, "?tcp_nodelay=%d", rt->tcp_nodelay);
2741 }
2742
2743 reconnect:
2744 if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2745 &s->interrupt_callback, opts,
2746 s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
2747 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2748 goto fail;
2749 }
2750
2751 if (rt->swfverify) {
2752 if ((ret = rtmp_calc_swfhash(s)) < 0)
2753 goto fail;
2754 }
2755
2756 rt->state = STATE_START;
2757 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2758 goto fail;
2759 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2760 goto fail;
2761
2762 rt->out_chunk_size = 128;
2763 rt->in_chunk_size = 128; // Probably overwritten later
2764 rt->state = STATE_HANDSHAKED;
2765
2766 // Keep the application name when it has been defined by the user.
2767 old_app = rt->app;
2768
2769 rt->app = av_malloc(APP_MAX_LENGTH);
2770 if (!rt->app) {
2771 ret = AVERROR(ENOMEM);
2772 goto fail;
2773 }
2774
2775 //extract "app" part from path
2776 qmark = strchr(path, '?');
2777 if (qmark && strstr(qmark, "slist=")) {
2778 char* amp;
2779 // After slist we have the playpath, the full path is used as app
2780 av_strlcpy(rt->app, path + 1, APP_MAX_LENGTH);
2781 fname = strstr(path, "slist=") + 6;
2782 // Strip any further query parameters from fname
2783 amp = strchr(fname, '&');
2784 if (amp) {
2785 av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2786 sizeof(fname_buffer)));
2787 fname = fname_buffer;
2788 }
2789 } else if (!strncmp(path, "/ondemand/", 10)) {
2790 fname = path + 10;
2791 memcpy(rt->app, "ondemand", 9);
2792 } else {
2793 char *next = *path ? path + 1 : path;
2794 char *p = strchr(next, '/');
2795 if (!p) {
2796 if (old_app) {
2797 // If name of application has been defined by the user, assume that
2798 // playpath is provided in the URL
2799 fname = next;
2800 } else {
2801 fname = NULL;
2802 av_strlcpy(rt->app, next, APP_MAX_LENGTH);
2803 }
2804 } else {
2805 // make sure we do not mismatch a playpath for an application instance
2806 char *c = strchr(p + 1, ':');
2807 fname = strchr(p + 1, '/');
2808 if (!fname || (c && c < fname)) {
2809 fname = p + 1;
2810 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2811 } else {
2812 fname++;
2813 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2814 }
2815 }
2816 }
2817
2818 if (old_app) {
2819 // The name of application has been defined by the user, override it.
2820 if (strlen(old_app) >= APP_MAX_LENGTH) {
2821 ret = AVERROR(EINVAL);
2822 goto fail;
2823 }
2824 av_free(rt->app);
2825 rt->app = old_app;
2826 }
2827
2828 if (!rt->playpath) {
2829 int max_len = 1;
2830 if (fname)
2831 max_len = strlen(fname) + 5; // add prefix "mp4:"
2832 rt->playpath = av_malloc(max_len);
2833 if (!rt->playpath) {
2834 ret = AVERROR(ENOMEM);
2835 goto fail;
2836 }
2837
2838 if (fname) {
2839 int len = strlen(fname);
2840 if (!strchr(fname, ':') && len >= 4 &&
2841 (!strcmp(fname + len - 4, ".f4v") ||
2842 !strcmp(fname + len - 4, ".mp4"))) {
2843 memcpy(rt->playpath, "mp4:", 5);
2844 } else {
2845 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2846 fname[len - 4] = '\0';
2847 rt->playpath[0] = 0;
2848 }
2849 av_strlcat(rt->playpath, fname, max_len);
2850 } else {
2851 rt->playpath[0] = '\0';
2852 }
2853 }
2854
2855 if (!rt->tcurl) {
2856 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2857 if (!rt->tcurl) {
2858 ret = AVERROR(ENOMEM);
2859 goto fail;
2860 }
2861 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2862 port, "/%s", rt->app);
2863 }
2864
2865 if (!rt->flashver) {
2866 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2867 if (!rt->flashver) {
2868 ret = AVERROR(ENOMEM);
2869 goto fail;
2870 }
2871 if (rt->is_input) {
2872 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2873 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2874 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2875 } else {
2876 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2877 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2878 }
2879 }
2880 if ( strlen(rt->flashver) > FLASHVER_MAX_LENGTH
2881 || strlen(rt->tcurl ) > TCURL_MAX_LENGTH
2882 ) {
2883 ret = AVERROR(EINVAL);
2884 goto fail;
2885 }
2886
2887 rt->receive_report_size = 1048576;
2888 rt->bytes_read = 0;
2889 rt->has_audio = 0;
2890 rt->has_video = 0;
2891 rt->received_metadata = 0;
2892 rt->last_bytes_read = 0;
2893 rt->max_sent_unacked = 2500000;
2894 rt->duration = 0;
2895
2896 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2897 proto, path, rt->app, rt->playpath);
2898 if (!rt->listen) {
2899 if ((ret = gen_connect(s, rt)) < 0)
2900 goto fail;
2901 } else {
2902 if ((ret = read_connect(s, s->priv_data)) < 0)
2903 goto fail;
2904 }
2905
2906 do {
2907 ret = get_packet(s, 1);
2908 } while (ret == AVERROR(EAGAIN));
2909 if (ret < 0)
2910 goto fail;
2911
2912 if (rt->do_reconnect) {
2913 int i;
2914 ffurl_closep(&rt->stream);
2915 rt->do_reconnect = 0;
2916 rt->nb_invokes = 0;
2917 for (i = 0; i < 2; i++)
2918 memset(rt->prev_pkt[i], 0,
2919 sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2920 free_tracked_methods(rt);
2921 goto reconnect;
2922 }
2923
2924 if (rt->is_input) {
2925 // generate FLV header for demuxer
2926 rt->flv_size = 13;
2927 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2928 goto fail;
2929 rt->flv_off = 0;
2930 memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2931
2932 // Read packets until we reach the first A/V packet or read metadata.
2933 // If there was a metadata package in front of the A/V packets, we can
2934 // build the FLV header from this. If we do not receive any metadata,
2935 // the FLV decoder will allocate the needed streams when their first
2936 // audio or video packet arrives.
2937 while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2938 if ((ret = get_packet(s, 0)) < 0)
2939 goto fail;
2940 }
2941
2942 // Either after we have read the metadata or (if there is none) the
2943 // first packet of an A/V stream, we have a better knowledge about the
2944 // streams, so set the FLV header accordingly.
2945 if (rt->has_audio) {
2946 rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO;
2947 }
2948 if (rt->has_video) {
2949 rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO;
2950 }
2951
2952 // If we received the first packet of an A/V stream and no metadata but
2953 // the server returned a valid duration, create a fake metadata packet
2954 // to inform the FLV decoder about the duration.
2955 if (!rt->received_metadata && rt->duration > 0) {
2956 if ((ret = inject_fake_duration_metadata(rt)) < 0)
2957 goto fail;
2958 }
2959 } else {
2960 rt->flv_size = 0;
2961 rt->flv_data = NULL;
2962 rt->flv_off = 0;
2963 rt->skip_bytes = 13;
2964 }
2965
2966 s->max_packet_size = rt->stream->max_packet_size;
2967 s->is_streamed = 1;
2968 return 0;
2969
2970 fail:
2971 rtmp_close(s);
2972 return ret;
2973 }
2974
2975 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2976 {
2977 RTMPContext *rt = s->priv_data;
2978 int orig_size = size;
2979 int ret;
2980
2981 while (size > 0) {
2982 int data_left = rt->flv_size - rt->flv_off;
2983
2984 if (data_left >= size) {
2985 memcpy(buf, rt->flv_data + rt->flv_off, size);
2986 rt->flv_off += size;
2987 return orig_size;
2988 }
2989 if (data_left > 0) {
2990 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2991 buf += data_left;
2992 size -= data_left;
2993 rt->flv_off = rt->flv_size;
2994 return data_left;
2995 }
2996 if ((ret = get_packet(s, 0)) < 0)
2997 return ret;
2998 }
2999 return orig_size;
3000 }
3001
3002 static int64_t rtmp_seek(void *opaque, int stream_index, int64_t timestamp,
3003 int flags)
3004 {
3005 URLContext *s = opaque;
3006 RTMPContext *rt = s->priv_data;
3007 int ret;
3008 av_log(s, AV_LOG_DEBUG,
3009 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
3010 stream_index, timestamp, flags);
3011 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
3012 av_log(s, AV_LOG_ERROR,
3013 "Unable to send seek command on stream index %d at timestamp "
3014 "%"PRId64" with flags %08x\n",
3015 stream_index, timestamp, flags);
3016 return ret;
3017 }
3018 rt->flv_off = rt->flv_size;
3019 rt->state = STATE_SEEKING;
3020 return timestamp;
3021 }
3022
3023 static int rtmp_pause(void *opaque, int pause)
3024 {
3025 URLContext *s = opaque;
3026 RTMPContext *rt = s->priv_data;
3027 int ret;
3028 av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n",
3029 rt->last_timestamp);
3030 if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) {
3031 av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n",
3032 rt->last_timestamp);
3033 return ret;
3034 }
3035 return 0;
3036 }
3037
3038 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
3039 {
3040 RTMPContext *rt = s->priv_data;
3041 int size_temp = size;
3042 int pktsize, pkttype, copy;
3043 uint32_t ts;
3044 const uint8_t *buf_temp = buf;
3045 uint8_t c;
3046 int ret;
3047
3048 do {
3049 if (rt->skip_bytes) {
3050 int skip = FFMIN(rt->skip_bytes, size_temp);
3051 buf_temp += skip;
3052 size_temp -= skip;
3053 rt->skip_bytes -= skip;
3054 continue;
3055 }
3056
3057 if (rt->flv_header_bytes < RTMP_HEADER) {
3058 const uint8_t *header = rt->flv_header;
3059 int channel = RTMP_AUDIO_CHANNEL;
3060
3061 copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
3062 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
3063 rt->flv_header_bytes += copy;
3064 size_temp -= copy;
3065 if (rt->flv_header_bytes < RTMP_HEADER)
3066 break;
3067
3068 pkttype = bytestream_get_byte(&header);
3069 pktsize = bytestream_get_be24(&header);
3070 ts = bytestream_get_be24(&header);
3071 ts |= bytestream_get_byte(&header) << 24;
3072 bytestream_get_be24(&header);
3073 rt->flv_size = pktsize;
3074
3075 if (pkttype == RTMP_PT_VIDEO)
3076 channel = RTMP_VIDEO_CHANNEL;
3077
3078 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
3079 pkttype == RTMP_PT_NOTIFY) {
3080 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
3081 &rt->nb_prev_pkt[1],
3082 channel)) < 0)
3083 return ret;
3084 // Force sending a full 12 bytes header by clearing the
3085 // channel id, to make it not match a potential earlier
3086 // packet in the same channel.
3087 rt->prev_pkt[1][channel].channel_id = 0;
3088 }
3089
3090 //this can be a big packet, it's better to send it right here
3091 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
3092 pkttype, ts, pktsize)) < 0)
3093 return ret;
3094
3095 // If rt->listen, then we're running as a a server and should
3096 // use the ID that we've sent in Stream Begin and in the
3097 // _result to createStream.
3098 // Otherwise, we're running as a client and should use the ID
3099 // that we've received in the createStream from the server.
3100 rt->out_pkt.extra = (rt->listen) ? rt->nb_streamid : rt->stream_id;
3101 rt->flv_data = rt->out_pkt.data;
3102 }
3103
3104 copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
3105 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
3106 rt->flv_off += copy;
3107 size_temp -= copy;
3108
3109 if (rt->flv_off == rt->flv_size) {
3110 rt->skip_bytes = 4;
3111
3112 if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
3113 // For onMetaData and |RtmpSampleAccess packets, we want
3114 // @setDataFrame prepended to the packet before it gets sent.
3115 // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
3116 // and onCuePoint).
3117 uint8_t commandbuffer[64];
3118 int stringlen = 0;
3119 GetByteContext gbc;
3120
3121 bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
3122 if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
3123 &stringlen)) {
3124 if (!strcmp(commandbuffer, "onMetaData") ||
3125 !strcmp(commandbuffer, "|RtmpSampleAccess")) {
3126 uint8_t *ptr;
3127 if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
3128 rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
3129 return ret;
3130 }
3131 memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
3132 rt->out_pkt.size += 16;
3133 ptr = rt->out_pkt.data;
3134 ff_amf_write_string(&ptr, "@setDataFrame");
3135 }
3136 }
3137 }
3138
3139 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
3140 return ret;
3141 rt->flv_size = 0;
3142 rt->flv_off = 0;
3143 rt->flv_header_bytes = 0;
3144 rt->flv_nb_packets++;
3145 }
3146 } while (buf_temp - buf < size);
3147
3148 if (rt->flv_nb_packets < rt->flush_interval)
3149 return size;
3150 rt->flv_nb_packets = 0;
3151
3152 /* set stream into nonblocking mode */
3153 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
3154
3155 /* try to read one byte from the stream */
3156 ret = ffurl_read(rt->stream, &c, 1);
3157
3158 /* switch the stream back into blocking mode */
3159 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
3160
3161 if (ret == AVERROR(EAGAIN)) {
3162 /* no incoming data to handle */
3163 return size;
3164 } else if (ret < 0) {
3165 return ret;
3166 } else if (ret == 1) {
3167 RTMPPacket rpkt = { 0 };
3168
3169 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
3170 rt->in_chunk_size,
3171 &rt->prev_pkt[0],
3172 &rt->nb_prev_pkt[0], c)) <= 0)
3173 return ret;
3174
3175 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
3176 return ret;
3177
3178 ff_rtmp_packet_destroy(&rpkt);
3179 }
3180
3181 return size;
3182 }
3183
3184 #define OFFSET(x) offsetof(RTMPContext, x)
3185 #define DEC AV_OPT_FLAG_DECODING_PARAM
3186 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3187
3188 static const AVOption rtmp_options[] = {
3189 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3190 {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
3191 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3192 {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3193 {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
3194 {"rtmp_enhanced_codecs", "Specify the codec(s) to use in an enhanced rtmp live stream", OFFSET(enhanced_codecs), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, ENC},
3195 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_live"},
3196 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, .unit = "rtmp_live"},
3197 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, .unit = "rtmp_live"},
3198 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, .unit = "rtmp_live"},
3199 {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3200 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3201 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3202 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
3203 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
3204 {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3205 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3206 {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3207 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3208 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3209 {"tcp_nodelay", "Use TCP_NODELAY to disable Nagle's algorithm", OFFSET(tcp_nodelay), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC|ENC},
3210 {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, .unit = "rtmp_listen" },
3211 { NULL },
3212 };
3213
3214 #define RTMP_PROTOCOL_0(flavor)
3215 #define RTMP_PROTOCOL_1(flavor) \
3216 static const AVClass flavor##_class = { \
3217 .class_name = #flavor, \
3218 .item_name = av_default_item_name, \
3219 .option = rtmp_options, \
3220 .version = LIBAVUTIL_VERSION_INT, \
3221 }; \
3222 \
3223 const URLProtocol ff_##flavor##_protocol = { \
3224 .name = #flavor, \
3225 .url_open2 = rtmp_open, \
3226 .url_read = rtmp_read, \
3227 .url_read_seek = rtmp_seek, \
3228 .url_read_pause = rtmp_pause, \
3229 .url_write = rtmp_write, \
3230 .url_close = rtmp_close, \
3231 .priv_data_size = sizeof(RTMPContext), \
3232 .flags = URL_PROTOCOL_FLAG_NETWORK, \
3233 .priv_data_class= &flavor##_class, \
3234 };
3235 #define RTMP_PROTOCOL_2(flavor, enabled) \
3236 RTMP_PROTOCOL_ ## enabled(flavor)
3237 #define RTMP_PROTOCOL_3(flavor, config) \
3238 RTMP_PROTOCOL_2(flavor, config)
3239 #define RTMP_PROTOCOL(flavor, uppercase) \
3240 RTMP_PROTOCOL_3(flavor, CONFIG_ ## uppercase ## _PROTOCOL)
3241
3242 RTMP_PROTOCOL(rtmp, RTMP)
3243 RTMP_PROTOCOL(rtmpe, RTMPE)
3244 RTMP_PROTOCOL(rtmps, RTMPS)
3245 RTMP_PROTOCOL(rtmpt, RTMPT)
3246 RTMP_PROTOCOL(rtmpte, RTMPTE)
3247 RTMP_PROTOCOL(rtmpts, RTMPTS)