FFmpeg coverage


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