FFmpeg coverage


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