FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/rtmpproto.c
Date: 2025-01-20 09:27:23
Exec Total Coverage
Lines: 0 1603 0.0%
Functions: 0 62 0.0%
Branches: 0 886 0.0%

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