2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 128
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56 #define RTMP_HEADER 11
58 /** RTMP protocol handler state */
60 STATE_START, ///< client has not done anything yet
61 STATE_HANDSHAKED, ///< client has performed handshake
62 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
63 STATE_PLAYING, ///< client has started receiving multimedia data from server
64 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66 STATE_RECEIVING, ///< received a publish command (for input)
67 STATE_SENDING, ///< received a play command (for output)
68 STATE_STOPPED, ///< the broadcast has been stopped
71 typedef struct TrackedMethod {
76 /** protocol handler context */
77 typedef struct RTMPContext {
79 URLContext* stream; ///< TCP stream used in interactions with RTMP server
80 RTMPPacket *prev_pkt[2]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81 int nb_prev_pkt[2]; ///< number of elements in prev_pkt
82 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
83 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
84 int is_input; ///< input/output flag
85 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
86 int live; ///< 0: recorded, -1: live, -2: both
87 char *app; ///< name of application
88 char *conn; ///< append arbitrary AMF data to the Connect message
89 ClientState state; ///< current state
90 int stream_id; ///< ID assigned by the server for the stream
91 uint8_t* flv_data; ///< buffer with data for demuxer
92 int flv_size; ///< current buffer size
93 int flv_off; ///< number of bytes read from current buffer
94 int flv_nb_packets; ///< number of flv packets published
95 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
96 uint32_t client_report_size; ///< number of bytes after which client should report to server
97 uint32_t bytes_read; ///< number of bytes read from server
98 uint32_t last_bytes_read; ///< number of bytes read last reported to server
99 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
100 int has_audio; ///< presence of audio data
101 int has_video; ///< presence of video data
102 int received_metadata; ///< Indicates if we have received metadata about the streams
103 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
104 int flv_header_bytes; ///< number of initialized bytes in flv_header
105 int nb_invokes; ///< keeps track of invoke messages
106 char* tcurl; ///< url of the target stream
107 char* flashver; ///< version of the flash plugin
108 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
109 int swfhash_len; ///< length of the SHA256 hash
110 int swfsize; ///< size of the decompressed SWF file
111 char* swfurl; ///< url of the swf player
112 char* swfverify; ///< URL to player swf file, compute hash/size automatically
113 char swfverification[42]; ///< hash of the SWF verification
114 char* pageurl; ///< url of the web page
115 char* subscribe; ///< name of live stream to subscribe
116 int server_bw; ///< server bandwidth
117 int client_buffer_time; ///< client buffer time in ms
118 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
119 int encrypted; ///< use an encrypted connection (RTMPE only)
120 TrackedMethod*tracked_methods; ///< tracked methods buffer
121 int nb_tracked_methods; ///< number of tracked methods
122 int tracked_methods_size; ///< size of the tracked methods buffer
123 int listen; ///< listen mode flag
124 int listen_timeout; ///< listen timeout to wait for new connections
125 int nb_streamid; ///< The next stream id to return on createStream calls
128 char auth_params[500];
133 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
134 /** Client key used for digest signing */
135 static const uint8_t rtmp_player_key[] = {
136 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
137 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
139 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
140 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
141 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
144 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
145 /** Key used for RTMP server digest signing */
146 static const uint8_t rtmp_server_key[] = {
147 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
148 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
149 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
151 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
152 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
153 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
156 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
158 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
162 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
163 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
164 if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
165 sizeof(*rt->tracked_methods))) < 0) {
166 rt->nb_tracked_methods = 0;
167 rt->tracked_methods_size = 0;
172 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
173 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
174 return AVERROR(ENOMEM);
175 rt->tracked_methods[rt->nb_tracked_methods].id = id;
176 rt->nb_tracked_methods++;
181 static void del_tracked_method(RTMPContext *rt, int index)
183 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
184 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
185 rt->nb_tracked_methods--;
188 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
189 char **tracked_method)
191 RTMPContext *rt = s->priv_data;
197 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
198 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
201 for (i = 0; i < rt->nb_tracked_methods; i++) {
202 if (rt->tracked_methods[i].id != pkt_id)
205 *tracked_method = rt->tracked_methods[i].name;
206 del_tracked_method(rt, i);
213 static void free_tracked_methods(RTMPContext *rt)
217 for (i = 0; i < rt->nb_tracked_methods; i ++)
218 av_free(rt->tracked_methods[i].name);
219 av_free(rt->tracked_methods);
220 rt->tracked_methods = NULL;
221 rt->tracked_methods_size = 0;
222 rt->nb_tracked_methods = 0;
225 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
229 if (pkt->type == RTMP_PT_INVOKE && track) {
235 bytestream2_init(&gbc, pkt->data, pkt->size);
236 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
239 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
242 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
246 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
247 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
249 ff_rtmp_packet_destroy(pkt);
253 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
258 /* The type must be B for Boolean, N for number, S for string, O for
259 * object, or Z for null. For Booleans the data must be either 0 or 1 for
260 * FALSE or TRUE, respectively. Likewise for Objects the data must be
261 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
262 * may be named, by prefixing the type with 'N' and specifying the name
263 * before the value (ie. NB:myFlag:1). This option may be used multiple times
264 * to construct arbitrary AMF sequences. */
265 if (param[0] && param[1] == ':') {
268 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
271 value = strchr(field, ':');
277 if (!field || !value)
280 ff_amf_write_field_name(p, field);
287 ff_amf_write_bool(p, value[0] != '0');
290 ff_amf_write_string(p, value);
293 ff_amf_write_number(p, strtod(value, NULL));
296 ff_amf_write_null(p);
300 ff_amf_write_object_start(p);
302 ff_amf_write_object_end(p);
312 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
313 return AVERROR(EINVAL);
317 * Generate 'connect' call and send it to the server.
319 static int gen_connect(URLContext *s, RTMPContext *rt)
325 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
331 ff_amf_write_string(&p, "connect");
332 ff_amf_write_number(&p, ++rt->nb_invokes);
333 ff_amf_write_object_start(&p);
334 ff_amf_write_field_name(&p, "app");
335 ff_amf_write_string2(&p, rt->app, rt->auth_params);
338 ff_amf_write_field_name(&p, "type");
339 ff_amf_write_string(&p, "nonprivate");
341 ff_amf_write_field_name(&p, "flashVer");
342 ff_amf_write_string(&p, rt->flashver);
345 ff_amf_write_field_name(&p, "swfUrl");
346 ff_amf_write_string(&p, rt->swfurl);
349 ff_amf_write_field_name(&p, "tcUrl");
350 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
352 ff_amf_write_field_name(&p, "fpad");
353 ff_amf_write_bool(&p, 0);
354 ff_amf_write_field_name(&p, "capabilities");
355 ff_amf_write_number(&p, 15.0);
357 /* Tell the server we support all the audio codecs except
358 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
359 * which are unused in the RTMP protocol implementation. */
360 ff_amf_write_field_name(&p, "audioCodecs");
361 ff_amf_write_number(&p, 4071.0);
362 ff_amf_write_field_name(&p, "videoCodecs");
363 ff_amf_write_number(&p, 252.0);
364 ff_amf_write_field_name(&p, "videoFunction");
365 ff_amf_write_number(&p, 1.0);
368 ff_amf_write_field_name(&p, "pageUrl");
369 ff_amf_write_string(&p, rt->pageurl);
372 ff_amf_write_object_end(&p);
375 char *param = rt->conn;
377 // Write arbitrary AMF data to the Connect message.
380 param += strspn(param, " ");
383 sep = strchr(param, ' ');
386 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
387 // Invalid AMF parameter.
388 ff_rtmp_packet_destroy(&pkt);
399 pkt.size = p - pkt.data;
401 return rtmp_send_packet(rt, &pkt, 1);
404 static int read_connect(URLContext *s, RTMPContext *rt)
406 RTMPPacket pkt = { 0 };
416 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
417 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
420 if (pkt.type == RTMP_PT_CHUNK_SIZE) {
421 if ((ret = handle_chunk_size(s, &pkt)) < 0)
423 ff_rtmp_packet_destroy(&pkt);
424 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
425 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
430 bytestream2_init(&gbc, cp, pkt.size);
431 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
432 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
433 ff_rtmp_packet_destroy(&pkt);
434 return AVERROR_INVALIDDATA;
436 if (strcmp(command, "connect")) {
437 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
438 ff_rtmp_packet_destroy(&pkt);
439 return AVERROR_INVALIDDATA;
441 ret = ff_amf_read_number(&gbc, &seqnum);
443 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
444 /* Here one could parse an AMF Object with data as flashVers and others. */
445 ret = ff_amf_get_field_value(gbc.buffer,
446 gbc.buffer + bytestream2_get_bytes_left(&gbc),
447 "app", tmpstr, sizeof(tmpstr));
449 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
450 if (!ret && strcmp(tmpstr, rt->app))
451 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
453 ff_rtmp_packet_destroy(&pkt);
455 // Send Window Acknowledgement Size (as defined in speficication)
456 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
457 RTMP_PT_SERVER_BW, 0, 4)) < 0)
460 bytestream_put_be32(&p, rt->server_bw);
461 pkt.size = p - pkt.data;
462 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
463 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
464 ff_rtmp_packet_destroy(&pkt);
467 // Send Peer Bandwidth
468 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
469 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
472 bytestream_put_be32(&p, rt->server_bw);
473 bytestream_put_byte(&p, 2); // dynamic
474 pkt.size = p - pkt.data;
475 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
476 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
477 ff_rtmp_packet_destroy(&pkt);
482 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
483 RTMP_PT_PING, 0, 6)) < 0)
487 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
488 bytestream_put_be32(&p, 0);
489 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
490 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
491 ff_rtmp_packet_destroy(&pkt);
496 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
497 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
501 bytestream_put_be32(&p, rt->out_chunk_size);
502 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
503 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
504 ff_rtmp_packet_destroy(&pkt);
508 // Send result_ NetConnection.Connect.Success to connect
509 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
511 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
515 ff_amf_write_string(&p, "_result");
516 ff_amf_write_number(&p, seqnum);
518 ff_amf_write_object_start(&p);
519 ff_amf_write_field_name(&p, "fmsVer");
520 ff_amf_write_string(&p, "FMS/3,0,1,123");
521 ff_amf_write_field_name(&p, "capabilities");
522 ff_amf_write_number(&p, 31);
523 ff_amf_write_object_end(&p);
525 ff_amf_write_object_start(&p);
526 ff_amf_write_field_name(&p, "level");
527 ff_amf_write_string(&p, "status");
528 ff_amf_write_field_name(&p, "code");
529 ff_amf_write_string(&p, "NetConnection.Connect.Success");
530 ff_amf_write_field_name(&p, "description");
531 ff_amf_write_string(&p, "Connection succeeded.");
532 ff_amf_write_field_name(&p, "objectEncoding");
533 ff_amf_write_number(&p, 0);
534 ff_amf_write_object_end(&p);
536 pkt.size = p - pkt.data;
537 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
538 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
539 ff_rtmp_packet_destroy(&pkt);
543 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
544 RTMP_PT_INVOKE, 0, 30)) < 0)
547 ff_amf_write_string(&p, "onBWDone");
548 ff_amf_write_number(&p, 0);
549 ff_amf_write_null(&p);
550 ff_amf_write_number(&p, 8192);
551 pkt.size = p - pkt.data;
552 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
553 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
554 ff_rtmp_packet_destroy(&pkt);
560 * Generate 'releaseStream' call and send it to the server. It should make
561 * the server release some channel for media streams.
563 static int gen_release_stream(URLContext *s, RTMPContext *rt)
569 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
570 0, 29 + strlen(rt->playpath))) < 0)
573 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
575 ff_amf_write_string(&p, "releaseStream");
576 ff_amf_write_number(&p, ++rt->nb_invokes);
577 ff_amf_write_null(&p);
578 ff_amf_write_string(&p, rt->playpath);
580 return rtmp_send_packet(rt, &pkt, 1);
584 * Generate 'FCPublish' call and send it to the server. It should make
585 * the server preapare for receiving media streams.
587 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
593 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
594 0, 25 + strlen(rt->playpath))) < 0)
597 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
599 ff_amf_write_string(&p, "FCPublish");
600 ff_amf_write_number(&p, ++rt->nb_invokes);
601 ff_amf_write_null(&p);
602 ff_amf_write_string(&p, rt->playpath);
604 return rtmp_send_packet(rt, &pkt, 1);
608 * Generate 'FCUnpublish' call and send it to the server. It should make
609 * the server destroy stream.
611 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
617 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
618 0, 27 + strlen(rt->playpath))) < 0)
621 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
623 ff_amf_write_string(&p, "FCUnpublish");
624 ff_amf_write_number(&p, ++rt->nb_invokes);
625 ff_amf_write_null(&p);
626 ff_amf_write_string(&p, rt->playpath);
628 return rtmp_send_packet(rt, &pkt, 0);
632 * Generate 'createStream' call and send it to the server. It should make
633 * the server allocate some channel for media streams.
635 static int gen_create_stream(URLContext *s, RTMPContext *rt)
641 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
643 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
648 ff_amf_write_string(&p, "createStream");
649 ff_amf_write_number(&p, ++rt->nb_invokes);
650 ff_amf_write_null(&p);
652 return rtmp_send_packet(rt, &pkt, 1);
657 * Generate 'deleteStream' call and send it to the server. It should make
658 * the server remove some channel for media streams.
660 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
666 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
668 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
673 ff_amf_write_string(&p, "deleteStream");
674 ff_amf_write_number(&p, ++rt->nb_invokes);
675 ff_amf_write_null(&p);
676 ff_amf_write_number(&p, rt->stream_id);
678 return rtmp_send_packet(rt, &pkt, 0);
682 * Generate client buffer time and send it to the server.
684 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
690 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
695 bytestream_put_be16(&p, 3);
696 bytestream_put_be32(&p, rt->stream_id);
697 bytestream_put_be32(&p, rt->client_buffer_time);
699 return rtmp_send_packet(rt, &pkt, 0);
703 * Generate 'play' call and send it to the server, then ping the server
704 * to start actual playing.
706 static int gen_play(URLContext *s, RTMPContext *rt)
712 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
714 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
715 0, 29 + strlen(rt->playpath))) < 0)
718 pkt.extra = rt->stream_id;
721 ff_amf_write_string(&p, "play");
722 ff_amf_write_number(&p, ++rt->nb_invokes);
723 ff_amf_write_null(&p);
724 ff_amf_write_string(&p, rt->playpath);
725 ff_amf_write_number(&p, rt->live * 1000);
727 return rtmp_send_packet(rt, &pkt, 1);
730 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
736 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
739 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
742 pkt.extra = rt->stream_id;
745 ff_amf_write_string(&p, "seek");
746 ff_amf_write_number(&p, 0); //no tracking back responses
747 ff_amf_write_null(&p); //as usual, the first null param
748 ff_amf_write_number(&p, timestamp); //where we want to jump
750 return rtmp_send_packet(rt, &pkt, 1);
754 * Generate 'publish' call and send it to the server.
756 static int gen_publish(URLContext *s, RTMPContext *rt)
762 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
764 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
765 0, 30 + strlen(rt->playpath))) < 0)
768 pkt.extra = rt->stream_id;
771 ff_amf_write_string(&p, "publish");
772 ff_amf_write_number(&p, ++rt->nb_invokes);
773 ff_amf_write_null(&p);
774 ff_amf_write_string(&p, rt->playpath);
775 ff_amf_write_string(&p, "live");
777 return rtmp_send_packet(rt, &pkt, 1);
781 * Generate ping reply and send it to the server.
783 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
789 if (ppkt->size < 6) {
790 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
792 return AVERROR_INVALIDDATA;
795 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
796 ppkt->timestamp + 1, 6)) < 0)
800 bytestream_put_be16(&p, 7);
801 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
803 return rtmp_send_packet(rt, &pkt, 0);
807 * Generate SWF verification message and send it to the server.
809 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
815 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
816 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
821 bytestream_put_be16(&p, 27);
822 memcpy(p, rt->swfverification, 42);
824 return rtmp_send_packet(rt, &pkt, 0);
828 * Generate server bandwidth message and send it to the server.
830 static int gen_server_bw(URLContext *s, RTMPContext *rt)
836 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
841 bytestream_put_be32(&p, rt->server_bw);
843 return rtmp_send_packet(rt, &pkt, 0);
847 * Generate check bandwidth message and send it to the server.
849 static int gen_check_bw(URLContext *s, RTMPContext *rt)
855 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
860 ff_amf_write_string(&p, "_checkbw");
861 ff_amf_write_number(&p, ++rt->nb_invokes);
862 ff_amf_write_null(&p);
864 return rtmp_send_packet(rt, &pkt, 1);
868 * Generate report on bytes read so far and send it to the server.
870 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
876 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
881 bytestream_put_be32(&p, rt->bytes_read);
883 return rtmp_send_packet(rt, &pkt, 0);
886 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
887 const char *subscribe)
893 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
894 0, 27 + strlen(subscribe))) < 0)
898 ff_amf_write_string(&p, "FCSubscribe");
899 ff_amf_write_number(&p, ++rt->nb_invokes);
900 ff_amf_write_null(&p);
901 ff_amf_write_string(&p, subscribe);
903 return rtmp_send_packet(rt, &pkt, 1);
906 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
907 const uint8_t *key, int keylen, uint8_t *dst)
910 uint8_t hmac_buf[64+32] = {0};
913 sha = av_sha_alloc();
915 return AVERROR(ENOMEM);
918 memcpy(hmac_buf, key, keylen);
920 av_sha_init(sha, 256);
921 av_sha_update(sha,key, keylen);
922 av_sha_final(sha, hmac_buf);
924 for (i = 0; i < 64; i++)
925 hmac_buf[i] ^= HMAC_IPAD_VAL;
927 av_sha_init(sha, 256);
928 av_sha_update(sha, hmac_buf, 64);
930 av_sha_update(sha, src, len);
931 } else { //skip 32 bytes used for storing digest
932 av_sha_update(sha, src, gap);
933 av_sha_update(sha, src + gap + 32, len - gap - 32);
935 av_sha_final(sha, hmac_buf + 64);
937 for (i = 0; i < 64; i++)
938 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
939 av_sha_init(sha, 256);
940 av_sha_update(sha, hmac_buf, 64+32);
941 av_sha_final(sha, dst);
948 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
951 int i, digest_pos = 0;
953 for (i = 0; i < 4; i++)
954 digest_pos += buf[i + off];
955 digest_pos = digest_pos % mod_val + add_val;
961 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
962 * will be stored) into that packet.
964 * @param buf handshake data (1536 bytes)
965 * @param encrypted use an encrypted connection (RTMPE)
966 * @return offset to the digest inside input data
968 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
973 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
975 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
977 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
978 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
987 * Verify that the received server response has the expected digest value.
989 * @param buf handshake data received from the server (1536 bytes)
990 * @param off position to search digest offset from
991 * @return 0 if digest is valid, digest position otherwise
993 static int rtmp_validate_digest(uint8_t *buf, int off)
998 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
1000 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1001 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
1006 if (!memcmp(digest, buf + digest_pos, 32))
1011 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1017 if (rt->swfhash_len != 32) {
1018 av_log(s, AV_LOG_ERROR,
1019 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1020 return AVERROR(EINVAL);
1023 p = &rt->swfverification[0];
1024 bytestream_put_byte(&p, 1);
1025 bytestream_put_byte(&p, 1);
1026 bytestream_put_be32(&p, rt->swfsize);
1027 bytestream_put_be32(&p, rt->swfsize);
1029 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1036 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1037 uint8_t **out_data, int64_t *out_size)
1039 z_stream zs = { 0 };
1044 zs.avail_in = in_size;
1045 zs.next_in = in_data;
1046 ret = inflateInit(&zs);
1048 return AVERROR_UNKNOWN;
1051 uint8_t tmp_buf[16384];
1053 zs.avail_out = sizeof(tmp_buf);
1054 zs.next_out = tmp_buf;
1056 ret = inflate(&zs, Z_NO_FLUSH);
1057 if (ret != Z_OK && ret != Z_STREAM_END) {
1058 ret = AVERROR_UNKNOWN;
1062 size = sizeof(tmp_buf) - zs.avail_out;
1063 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1064 ret = AVERROR(ENOMEM);
1069 memcpy(*out_data + *out_size, tmp_buf, size);
1071 } while (zs.avail_out == 0);
1079 static int rtmp_calc_swfhash(URLContext *s)
1081 RTMPContext *rt = s->priv_data;
1082 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1083 int64_t in_size, out_size;
1089 /* Get the SWF player file. */
1090 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1091 &s->interrupt_callback, NULL)) < 0) {
1092 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1096 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1101 if (!(in_data = av_malloc(in_size))) {
1102 ret = AVERROR(ENOMEM);
1106 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1110 ret = AVERROR_INVALIDDATA;
1114 if (!memcmp(in_data, "CWS", 3)) {
1115 /* Decompress the SWF player file using Zlib. */
1116 if (!(out_data = av_malloc(8))) {
1117 ret = AVERROR(ENOMEM);
1120 *in_data = 'F'; // magic stuff
1121 memcpy(out_data, in_data, 8);
1125 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1126 &out_data, &out_size)) < 0)
1129 av_log(s, AV_LOG_ERROR,
1130 "Zlib is required for decompressing the SWF player file.\n");
1131 ret = AVERROR(EINVAL);
1141 /* Compute the SHA256 hash of the SWF player file. */
1142 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1143 "Genuine Adobe Flash Player 001", 30,
1147 /* Set SWFVerification parameters. */
1148 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1149 rt->swfsize = swfsize;
1153 av_freep(&out_data);
1154 ffurl_close(stream);
1159 * Perform handshake with the server by means of exchanging pseudorandom data
1160 * signed with HMAC-SHA2 digest.
1162 * @return 0 if handshake succeeds, negative value otherwise
1164 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1167 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1168 3, // unencrypted data
1169 0, 0, 0, 0, // client uptime
1175 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1176 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1178 int server_pos, client_pos;
1179 uint8_t digest[32], signature[32];
1182 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1184 av_lfg_init(&rnd, 0xDEADC0DE);
1185 // generate handshake packet - 1536 bytes of pseudorandom data
1186 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1187 tosend[i] = av_lfg_get(&rnd) >> 24;
1189 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1190 /* When the client wants to use RTMPE, we have to change the command
1191 * byte to 0x06 which means to use encrypted data and we have to set
1192 * the flash version to at least 9.0.115.0. */
1199 /* Initialize the Diffie-Hellmann context and generate the public key
1200 * to send to the server. */
1201 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1205 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1209 if ((ret = ffurl_write(rt->stream, tosend,
1210 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1211 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1215 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1216 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1217 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1221 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1222 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1223 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1227 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1228 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1229 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1231 if (rt->is_input && serverdata[5] >= 3) {
1232 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1238 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1243 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1244 return AVERROR(EIO);
1248 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1249 * key are the last 32 bytes of the server handshake. */
1251 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1252 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1256 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1257 rtmp_server_key, sizeof(rtmp_server_key),
1262 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1263 0, digest, 32, signature);
1267 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1268 /* Compute the shared secret key sent by the server and initialize
1269 * the RC4 encryption. */
1270 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1271 tosend + 1, type)) < 0)
1274 /* Encrypt the signature received by the server. */
1275 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1278 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1279 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1280 return AVERROR(EIO);
1283 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1284 tosend[i] = av_lfg_get(&rnd) >> 24;
1285 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1286 rtmp_player_key, sizeof(rtmp_player_key),
1291 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1293 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1297 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1298 /* Encrypt the signature to be send to the server. */
1299 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1300 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1304 // write reply back to the server
1305 if ((ret = ffurl_write(rt->stream, tosend,
1306 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1309 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1310 /* Set RC4 keys for encryption and update the keystreams. */
1311 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1315 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1316 /* Compute the shared secret key sent by the server and initialize
1317 * the RC4 encryption. */
1318 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1319 tosend + 1, 1)) < 0)
1322 if (serverdata[0] == 9) {
1323 /* Encrypt the signature received by the server. */
1324 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1329 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1330 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1333 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1334 /* Set RC4 keys for encryption and update the keystreams. */
1335 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1343 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1344 uint32_t *second_int, char *arraydata,
1349 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1350 RTMP_HANDSHAKE_PACKET_SIZE);
1352 return AVERROR(EIO);
1353 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1354 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1355 " not following standard\n", (int)inoutsize);
1356 return AVERROR(EINVAL);
1359 *first_int = AV_RB32(arraydata);
1360 *second_int = AV_RB32(arraydata + 4);
1364 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1365 uint32_t second_int, char *arraydata, int size)
1369 AV_WB32(arraydata, first_int);
1370 AV_WB32(arraydata + 4, second_int);
1371 inoutsize = ffurl_write(rt->stream, arraydata,
1372 RTMP_HANDSHAKE_PACKET_SIZE);
1373 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1374 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1375 return AVERROR(EIO);
1382 * rtmp handshake server side
1384 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1386 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1388 uint32_t hs_my_epoch;
1389 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1390 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1397 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1398 if (inoutsize <= 0) {
1399 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1400 return AVERROR(EIO);
1403 if (buffer[0] != 3) {
1404 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1405 return AVERROR(EIO);
1407 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1408 av_log(s, AV_LOG_ERROR,
1409 "Unable to write answer - RTMP S0\n");
1410 return AVERROR(EIO);
1413 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1414 RTMP_HANDSHAKE_PACKET_SIZE);
1416 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1420 /* By now same epoch will be sent */
1421 hs_my_epoch = hs_epoch;
1422 /* Generate random */
1423 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1425 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1427 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1428 RTMP_HANDSHAKE_PACKET_SIZE);
1430 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1434 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1435 RTMP_HANDSHAKE_PACKET_SIZE);
1437 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1441 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1442 RTMP_HANDSHAKE_PACKET_SIZE);
1444 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1447 if (temp != hs_my_epoch)
1448 av_log(s, AV_LOG_WARNING,
1449 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1450 if (memcmp(buffer + 8, hs_s1 + 8,
1451 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1452 av_log(s, AV_LOG_WARNING,
1453 "Erroneous C2 Message random does not match up\n");
1458 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1460 RTMPContext *rt = s->priv_data;
1463 if (pkt->size < 4) {
1464 av_log(s, AV_LOG_ERROR,
1465 "Too short chunk size change packet (%d)\n",
1467 return AVERROR_INVALIDDATA;
1470 if (!rt->is_input) {
1471 /* Send the same chunk size change packet back to the server,
1472 * setting the outgoing chunk size to the same as the incoming one. */
1473 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1474 &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1476 rt->out_chunk_size = AV_RB32(pkt->data);
1479 rt->in_chunk_size = AV_RB32(pkt->data);
1480 if (rt->in_chunk_size <= 0) {
1481 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1483 return AVERROR_INVALIDDATA;
1485 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1491 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1493 RTMPContext *rt = s->priv_data;
1496 if (pkt->size < 2) {
1497 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1499 return AVERROR_INVALIDDATA;
1502 t = AV_RB16(pkt->data);
1504 if ((ret = gen_pong(s, rt, pkt)) < 0)
1506 } else if (t == 26) {
1508 if ((ret = gen_swf_verification(s, rt)) < 0)
1511 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1518 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1520 RTMPContext *rt = s->priv_data;
1522 if (pkt->size < 4) {
1523 av_log(s, AV_LOG_ERROR,
1524 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1526 return AVERROR_INVALIDDATA;
1529 rt->client_report_size = AV_RB32(pkt->data);
1530 if (rt->client_report_size <= 0) {
1531 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1532 rt->client_report_size);
1533 return AVERROR_INVALIDDATA;
1536 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1537 rt->client_report_size >>= 1;
1542 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1544 RTMPContext *rt = s->priv_data;
1546 if (pkt->size < 4) {
1547 av_log(s, AV_LOG_ERROR,
1548 "Too short server bandwidth report packet (%d)\n",
1550 return AVERROR_INVALIDDATA;
1553 rt->server_bw = AV_RB32(pkt->data);
1554 if (rt->server_bw <= 0) {
1555 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1557 return AVERROR_INVALIDDATA;
1559 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1564 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1565 const char *opaque, const char *challenge)
1568 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1569 struct AVMD5 *md5 = av_md5_alloc();
1571 return AVERROR(ENOMEM);
1573 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1576 av_md5_update(md5, user, strlen(user));
1577 av_md5_update(md5, salt, strlen(salt));
1578 av_md5_update(md5, rt->password, strlen(rt->password));
1579 av_md5_final(md5, hash);
1580 av_base64_encode(hashstr, sizeof(hashstr), hash,
1583 av_md5_update(md5, hashstr, strlen(hashstr));
1585 av_md5_update(md5, opaque, strlen(opaque));
1587 av_md5_update(md5, challenge, strlen(challenge));
1588 av_md5_update(md5, challenge2, strlen(challenge2));
1589 av_md5_final(md5, hash);
1590 av_base64_encode(hashstr, sizeof(hashstr), hash,
1592 snprintf(rt->auth_params, sizeof(rt->auth_params),
1593 "?authmod=%s&user=%s&challenge=%s&response=%s",
1594 "adobe", user, challenge2, hashstr);
1596 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1597 "&opaque=%s", opaque);
1603 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1606 char hashstr1[33], hashstr2[33];
1607 const char *realm = "live";
1608 const char *method = "publish";
1609 const char *qop = "auth";
1610 const char *nc = "00000001";
1612 struct AVMD5 *md5 = av_md5_alloc();
1614 return AVERROR(ENOMEM);
1616 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1619 av_md5_update(md5, user, strlen(user));
1620 av_md5_update(md5, ":", 1);
1621 av_md5_update(md5, realm, strlen(realm));
1622 av_md5_update(md5, ":", 1);
1623 av_md5_update(md5, rt->password, strlen(rt->password));
1624 av_md5_final(md5, hash);
1625 ff_data_to_hex(hashstr1, hash, 16, 1);
1626 hashstr1[32] = '\0';
1629 av_md5_update(md5, method, strlen(method));
1630 av_md5_update(md5, ":/", 2);
1631 av_md5_update(md5, rt->app, strlen(rt->app));
1632 if (!strchr(rt->app, '/'))
1633 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1634 av_md5_final(md5, hash);
1635 ff_data_to_hex(hashstr2, hash, 16, 1);
1636 hashstr2[32] = '\0';
1639 av_md5_update(md5, hashstr1, strlen(hashstr1));
1640 av_md5_update(md5, ":", 1);
1642 av_md5_update(md5, nonce, strlen(nonce));
1643 av_md5_update(md5, ":", 1);
1644 av_md5_update(md5, nc, strlen(nc));
1645 av_md5_update(md5, ":", 1);
1646 av_md5_update(md5, cnonce, strlen(cnonce));
1647 av_md5_update(md5, ":", 1);
1648 av_md5_update(md5, qop, strlen(qop));
1649 av_md5_update(md5, ":", 1);
1650 av_md5_update(md5, hashstr2, strlen(hashstr2));
1651 av_md5_final(md5, hash);
1652 ff_data_to_hex(hashstr1, hash, 16, 1);
1654 snprintf(rt->auth_params, sizeof(rt->auth_params),
1655 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1656 "llnw", user, nonce, cnonce, nc, hashstr1);
1662 static int handle_connect_error(URLContext *s, const char *desc)
1664 RTMPContext *rt = s->priv_data;
1665 char buf[300], *ptr, authmod[15];
1667 const char *user = "", *salt = "", *opaque = NULL,
1668 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1670 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1671 !(cptr = strstr(desc, "authmod=llnw"))) {
1672 av_log(s, AV_LOG_ERROR,
1673 "Unknown connect error (unsupported authentication method?)\n");
1674 return AVERROR_UNKNOWN;
1676 cptr += strlen("authmod=");
1677 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1678 authmod[i++] = *cptr++;
1681 if (!rt->username[0] || !rt->password[0]) {
1682 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1683 return AVERROR_UNKNOWN;
1686 if (strstr(desc, "?reason=authfailed")) {
1687 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1688 return AVERROR_UNKNOWN;
1689 } else if (strstr(desc, "?reason=nosuchuser")) {
1690 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1691 return AVERROR_UNKNOWN;
1694 if (rt->auth_tried) {
1695 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1696 return AVERROR_UNKNOWN;
1699 rt->auth_params[0] = '\0';
1701 if (strstr(desc, "code=403 need auth")) {
1702 snprintf(rt->auth_params, sizeof(rt->auth_params),
1703 "?authmod=%s&user=%s", authmod, rt->username);
1707 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1708 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1709 return AVERROR_UNKNOWN;
1712 av_strlcpy(buf, cptr + 1, sizeof(buf));
1716 char *next = strchr(ptr, '&');
1717 char *value = strchr(ptr, '=');
1722 if (!strcmp(ptr, "user")) {
1724 } else if (!strcmp(ptr, "salt")) {
1726 } else if (!strcmp(ptr, "opaque")) {
1728 } else if (!strcmp(ptr, "challenge")) {
1730 } else if (!strcmp(ptr, "nonce")) {
1736 if (!strcmp(authmod, "adobe")) {
1737 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1740 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1748 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1750 RTMPContext *rt = s->priv_data;
1751 const uint8_t *data_end = pkt->data + pkt->size;
1752 char *tracked_method = NULL;
1753 int level = AV_LOG_ERROR;
1754 uint8_t tmpstr[256];
1757 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1760 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1761 "description", tmpstr, sizeof(tmpstr))) {
1762 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1763 !strcmp(tracked_method, "releaseStream") ||
1764 !strcmp(tracked_method, "FCSubscribe") ||
1765 !strcmp(tracked_method, "FCPublish"))) {
1766 /* Gracefully ignore Adobe-specific historical artifact errors. */
1767 level = AV_LOG_WARNING;
1769 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1770 ret = handle_connect_error(s, tmpstr);
1772 rt->do_reconnect = 1;
1773 level = AV_LOG_VERBOSE;
1776 ret = AVERROR_UNKNOWN;
1777 av_log(s, level, "Server error: %s\n", tmpstr);
1780 av_free(tracked_method);
1784 static int write_begin(URLContext *s)
1786 RTMPContext *rt = s->priv_data;
1788 RTMPPacket spkt = { 0 };
1791 // Send Stream Begin 1
1792 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1793 RTMP_PT_PING, 0, 6)) < 0) {
1794 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1798 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1799 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1800 bytestream2_put_be32(&pbc, rt->nb_streamid);
1802 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1803 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1805 ff_rtmp_packet_destroy(&spkt);
1810 static int write_status(URLContext *s, RTMPPacket *pkt,
1811 const char *status, const char *filename)
1813 RTMPContext *rt = s->priv_data;
1814 RTMPPacket spkt = { 0 };
1815 char statusmsg[128];
1819 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1821 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1822 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1827 spkt.extra = pkt->extra;
1828 ff_amf_write_string(&pp, "onStatus");
1829 ff_amf_write_number(&pp, 0);
1830 ff_amf_write_null(&pp);
1832 ff_amf_write_object_start(&pp);
1833 ff_amf_write_field_name(&pp, "level");
1834 ff_amf_write_string(&pp, "status");
1835 ff_amf_write_field_name(&pp, "code");
1836 ff_amf_write_string(&pp, status);
1837 ff_amf_write_field_name(&pp, "description");
1838 snprintf(statusmsg, sizeof(statusmsg),
1839 "%s is now published", filename);
1840 ff_amf_write_string(&pp, statusmsg);
1841 ff_amf_write_field_name(&pp, "details");
1842 ff_amf_write_string(&pp, filename);
1843 ff_amf_write_field_name(&pp, "clientid");
1844 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1845 ff_amf_write_string(&pp, statusmsg);
1846 ff_amf_write_object_end(&pp);
1848 spkt.size = pp - spkt.data;
1849 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1850 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1851 ff_rtmp_packet_destroy(&spkt);
1856 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1858 RTMPContext *rt = s->priv_data;
1864 const uint8_t *p = pkt->data;
1866 RTMPPacket spkt = { 0 };
1870 bytestream2_init(&gbc, p, pkt->size);
1871 if (ff_amf_read_string(&gbc, command, sizeof(command),
1873 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1874 return AVERROR_INVALIDDATA;
1877 ret = ff_amf_read_number(&gbc, &seqnum);
1880 ret = ff_amf_read_null(&gbc);
1883 if (!strcmp(command, "FCPublish") ||
1884 !strcmp(command, "publish")) {
1885 ret = ff_amf_read_string(&gbc, filename,
1886 sizeof(filename), &stringlen);
1889 pchar = strrchr(s->filename, '/');
1891 av_log(s, AV_LOG_WARNING,
1892 "Unable to find / in url %s, bad format\n",
1894 pchar = s->filename;
1897 if (strcmp(pchar, filename))
1898 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1899 " %s\n", filename, pchar);
1901 rt->state = STATE_RECEIVING;
1904 if (!strcmp(command, "FCPublish")) {
1905 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1907 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1908 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1912 ff_amf_write_string(&pp, "onFCPublish");
1913 } else if (!strcmp(command, "publish")) {
1914 ret = write_begin(s);
1918 // Send onStatus(NetStream.Publish.Start)
1919 return write_status(s, pkt, "NetStream.Publish.Start",
1921 } else if (!strcmp(command, "play")) {
1922 ret = write_begin(s);
1925 rt->state = STATE_SENDING;
1926 return write_status(s, pkt, "NetStream.Play.Start",
1929 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1931 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1932 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1936 ff_amf_write_string(&pp, "_result");
1937 ff_amf_write_number(&pp, seqnum);
1938 ff_amf_write_null(&pp);
1939 if (!strcmp(command, "createStream")) {
1941 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1942 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1943 ff_amf_write_number(&pp, rt->nb_streamid);
1944 /* By now we don't control which streams are removed in
1945 * deleteStream. There is no stream creation control
1946 * if a client creates more than 2^32 - 2 streams. */
1949 spkt.size = pp - spkt.data;
1950 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1951 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1952 ff_rtmp_packet_destroy(&spkt);
1956 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1958 RTMPContext *rt = s->priv_data;
1959 char *tracked_method = NULL;
1962 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1965 if (!tracked_method) {
1966 /* Ignore this reply when the current method is not tracked. */
1970 if (!strcmp(tracked_method, "connect")) {
1971 if (!rt->is_input) {
1972 if ((ret = gen_release_stream(s, rt)) < 0)
1975 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1978 if ((ret = gen_server_bw(s, rt)) < 0)
1982 if ((ret = gen_create_stream(s, rt)) < 0)
1986 /* Send the FCSubscribe command when the name of live
1987 * stream is defined by the user or if it's a live stream. */
1988 if (rt->subscribe) {
1989 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1991 } else if (rt->live == -1) {
1992 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1996 } else if (!strcmp(tracked_method, "createStream")) {
1997 //extract a number from the result
1998 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1999 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2001 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
2004 if (!rt->is_input) {
2005 if ((ret = gen_publish(s, rt)) < 0)
2008 if ((ret = gen_play(s, rt)) < 0)
2010 if ((ret = gen_buffer_time(s, rt)) < 0)
2016 av_free(tracked_method);
2020 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2022 RTMPContext *rt = s->priv_data;
2023 const uint8_t *data_end = pkt->data + pkt->size;
2024 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2025 uint8_t tmpstr[256];
2028 for (i = 0; i < 2; i++) {
2029 t = ff_amf_tag_size(ptr, data_end);
2035 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2036 if (!t && !strcmp(tmpstr, "error")) {
2037 t = ff_amf_get_field_value(ptr, data_end,
2038 "description", tmpstr, sizeof(tmpstr));
2039 if (t || !tmpstr[0])
2040 t = ff_amf_get_field_value(ptr, data_end, "code",
2041 tmpstr, sizeof(tmpstr));
2043 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2047 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2048 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2049 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2050 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2051 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2052 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2057 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2059 RTMPContext *rt = s->priv_data;
2062 //TODO: check for the messages sent for wrong state?
2063 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2064 if ((ret = handle_invoke_error(s, pkt)) < 0)
2066 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2067 if ((ret = handle_invoke_result(s, pkt)) < 0)
2069 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2070 if ((ret = handle_invoke_status(s, pkt)) < 0)
2072 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2073 if ((ret = gen_check_bw(s, rt)) < 0)
2075 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2076 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2077 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2078 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2079 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2080 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2081 if ((ret = send_invoke_response(s, pkt)) < 0)
2088 static int update_offset(RTMPContext *rt, int size)
2092 // generate packet header and put data into buffer for FLV demuxer
2093 if (rt->flv_off < rt->flv_size) {
2094 // There is old unread data in the buffer, thus append at the end
2095 old_flv_size = rt->flv_size;
2096 rt->flv_size += size;
2098 // All data has been read, write the new data at the start of the buffer
2100 rt->flv_size = size;
2104 return old_flv_size;
2107 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2109 int old_flv_size, ret;
2111 const uint8_t *data = pkt->data + skip;
2112 const int size = pkt->size - skip;
2113 uint32_t ts = pkt->timestamp;
2115 if (pkt->type == RTMP_PT_AUDIO) {
2117 } else if (pkt->type == RTMP_PT_VIDEO) {
2121 old_flv_size = update_offset(rt, size + 15);
2123 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2124 rt->flv_size = rt->flv_off = 0;
2127 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2128 bytestream2_skip_p(&pbc, old_flv_size);
2129 bytestream2_put_byte(&pbc, pkt->type);
2130 bytestream2_put_be24(&pbc, size);
2131 bytestream2_put_be24(&pbc, ts);
2132 bytestream2_put_byte(&pbc, ts >> 24);
2133 bytestream2_put_be24(&pbc, 0);
2134 bytestream2_put_buffer(&pbc, data, size);
2135 bytestream2_put_be32(&pbc, 0);
2140 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2142 RTMPContext *rt = s->priv_data;
2143 uint8_t commandbuffer[64];
2144 char statusmsg[128];
2145 int stringlen, ret, skip = 0;
2148 bytestream2_init(&gbc, pkt->data, pkt->size);
2149 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2151 return AVERROR_INVALIDDATA;
2153 if (!strcmp(commandbuffer, "onMetaData")) {
2154 // metadata properties should be stored in a mixed array
2155 if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2156 // We have found a metaData Array so flv can determine the streams
2158 rt->received_metadata = 1;
2159 // skip 32-bit max array index
2160 bytestream2_skip(&gbc, 4);
2161 while (bytestream2_get_bytes_left(&gbc) > 3) {
2162 if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2164 return AVERROR_INVALIDDATA;
2165 // We do not care about the content of the property (yet).
2166 stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2168 return AVERROR_INVALIDDATA;
2169 bytestream2_skip(&gbc, stringlen);
2171 // The presence of the following properties indicates that the
2172 // respective streams are present.
2173 if (!strcmp(statusmsg, "videocodecid")) {
2176 if (!strcmp(statusmsg, "audiocodecid")) {
2180 if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2181 return AVERROR_INVALIDDATA;
2185 // Skip the @setDataFrame string and validate it is a notification
2186 if (!strcmp(commandbuffer, "@setDataFrame")) {
2187 skip = gbc.buffer - pkt->data;
2188 ret = ff_amf_read_string(&gbc, statusmsg,
2189 sizeof(statusmsg), &stringlen);
2191 return AVERROR_INVALIDDATA;
2194 return append_flv_data(rt, pkt, skip);
2198 * Parse received packet and possibly perform some action depending on
2199 * the packet contents.
2200 * @return 0 for no errors, negative values for serious errors which prevent
2201 * further communications, positive values for uncritical errors
2203 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2208 ff_rtmp_packet_dump(s, pkt);
2211 switch (pkt->type) {
2212 case RTMP_PT_BYTES_READ:
2213 av_dlog(s, "received bytes read report\n");
2215 case RTMP_PT_CHUNK_SIZE:
2216 if ((ret = handle_chunk_size(s, pkt)) < 0)
2220 if ((ret = handle_ping(s, pkt)) < 0)
2223 case RTMP_PT_CLIENT_BW:
2224 if ((ret = handle_client_bw(s, pkt)) < 0)
2227 case RTMP_PT_SERVER_BW:
2228 if ((ret = handle_server_bw(s, pkt)) < 0)
2231 case RTMP_PT_INVOKE:
2232 if ((ret = handle_invoke(s, pkt)) < 0)
2237 case RTMP_PT_METADATA:
2238 case RTMP_PT_NOTIFY:
2239 /* Audio, Video and Metadata packets are parsed in get_packet() */
2242 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2248 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2250 int ret, old_flv_size, type;
2251 const uint8_t *next;
2254 uint32_t ts, cts, pts = 0;
2256 old_flv_size = update_offset(rt, pkt->size);
2258 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2259 rt->flv_size = rt->flv_off = 0;
2264 p = rt->flv_data + old_flv_size;
2266 /* copy data while rewriting timestamps */
2267 ts = pkt->timestamp;
2269 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2270 type = bytestream_get_byte(&next);
2271 size = bytestream_get_be24(&next);
2272 cts = bytestream_get_be24(&next);
2273 cts |= bytestream_get_byte(&next) << 24;
2278 if (size + 3 + 4 > pkt->data + pkt->size - next)
2280 bytestream_put_byte(&p, type);
2281 bytestream_put_be24(&p, size);
2282 bytestream_put_be24(&p, ts);
2283 bytestream_put_byte(&p, ts >> 24);
2284 memcpy(p, next, size + 3 + 4);
2285 next += size + 3 + 4;
2288 if (p != rt->flv_data + rt->flv_size) {
2289 av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2290 "RTMP_PT_METADATA packet\n");
2291 rt->flv_size = p - rt->flv_data;
2298 * Interact with the server by receiving and sending RTMP packets until
2299 * there is some significant data (media data or expected status notification).
2301 * @param s reading context
2302 * @param for_header non-zero value tells function to work until it
2303 * gets notification from the server that playing has been started,
2304 * otherwise function will work until some media data is received (or
2306 * @return 0 for successful operation, negative value in case of error
2308 static int get_packet(URLContext *s, int for_header)
2310 RTMPContext *rt = s->priv_data;
2313 if (rt->state == STATE_STOPPED)
2317 RTMPPacket rpkt = { 0 };
2318 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2319 rt->in_chunk_size, &rt->prev_pkt[0],
2320 &rt->nb_prev_pkt[0])) <= 0) {
2322 return AVERROR(EAGAIN);
2324 return AVERROR(EIO);
2327 rt->bytes_read += ret;
2328 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2329 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2330 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2332 rt->last_bytes_read = rt->bytes_read;
2335 ret = rtmp_parse_result(s, rt, &rpkt);
2337 // At this point we must check if we are in the seek state and continue
2338 // with the next packet. handle_invoke will get us out of this state
2339 // when the right message is encountered
2340 if (rt->state == STATE_SEEKING) {
2341 ff_rtmp_packet_destroy(&rpkt);
2342 // We continue, let the natural flow of things happen:
2343 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2347 if (ret < 0) {//serious error in current packet
2348 ff_rtmp_packet_destroy(&rpkt);
2351 if (rt->do_reconnect && for_header) {
2352 ff_rtmp_packet_destroy(&rpkt);
2355 if (rt->state == STATE_STOPPED) {
2356 ff_rtmp_packet_destroy(&rpkt);
2359 if (for_header && (rt->state == STATE_PLAYING ||
2360 rt->state == STATE_PUBLISHING ||
2361 rt->state == STATE_SENDING ||
2362 rt->state == STATE_RECEIVING)) {
2363 ff_rtmp_packet_destroy(&rpkt);
2366 if (!rpkt.size || !rt->is_input) {
2367 ff_rtmp_packet_destroy(&rpkt);
2370 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2371 ret = append_flv_data(rt, &rpkt, 0);
2372 ff_rtmp_packet_destroy(&rpkt);
2374 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2375 ret = handle_notify(s, &rpkt);
2376 ff_rtmp_packet_destroy(&rpkt);
2378 } else if (rpkt.type == RTMP_PT_METADATA) {
2379 ret = handle_metadata(rt, &rpkt);
2380 ff_rtmp_packet_destroy(&rpkt);
2383 ff_rtmp_packet_destroy(&rpkt);
2387 static int rtmp_close(URLContext *h)
2389 RTMPContext *rt = h->priv_data;
2392 if (!rt->is_input) {
2393 rt->flv_data = NULL;
2394 if (rt->out_pkt.size)
2395 ff_rtmp_packet_destroy(&rt->out_pkt);
2396 if (rt->state > STATE_FCPUBLISH)
2397 ret = gen_fcunpublish_stream(h, rt);
2399 if (rt->state > STATE_HANDSHAKED)
2400 ret = gen_delete_stream(h, rt);
2401 for (i = 0; i < 2; i++) {
2402 for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2403 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2404 av_freep(&rt->prev_pkt[i]);
2407 free_tracked_methods(rt);
2408 av_freep(&rt->flv_data);
2409 ffurl_close(rt->stream);
2414 * Open RTMP connection and verify that the stream can be played.
2416 * URL syntax: rtmp://server[:port][/app][/playpath]
2417 * where 'app' is first one or two directories in the path
2418 * (e.g. /ondemand/, /flash/live/, etc.)
2419 * and 'playpath' is a file name (the rest of the path,
2420 * may be prefixed with "mp4:")
2422 static int rtmp_open(URLContext *s, const char *uri, int flags)
2424 RTMPContext *rt = s->priv_data;
2425 char proto[8], hostname[256], path[1024], auth[100], *fname;
2426 char *old_app, *qmark, fname_buffer[1024];
2429 AVDictionary *opts = NULL;
2432 if (rt->listen_timeout > 0)
2435 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2437 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2438 hostname, sizeof(hostname), &port,
2439 path, sizeof(path), s->filename);
2441 if (strchr(path, ' ')) {
2442 av_log(s, AV_LOG_WARNING,
2443 "Detected librtmp style URL parameters, these aren't supported "
2444 "by the libavformat internal RTMP handler currently enabled. "
2445 "See the documentation for the correct way to pass parameters.\n");
2449 char *ptr = strchr(auth, ':');
2452 av_strlcpy(rt->username, auth, sizeof(rt->username));
2453 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2457 if (rt->listen && strcmp(proto, "rtmp")) {
2458 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2460 return AVERROR(EINVAL);
2462 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2463 if (!strcmp(proto, "rtmpts"))
2464 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2466 /* open the http tunneling connection */
2467 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2468 } else if (!strcmp(proto, "rtmps")) {
2469 /* open the tls connection */
2471 port = RTMPS_DEFAULT_PORT;
2472 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2473 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2474 if (!strcmp(proto, "rtmpte"))
2475 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2477 /* open the encrypted connection */
2478 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2481 /* open the tcp connection */
2483 port = RTMP_DEFAULT_PORT;
2485 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2486 "?listen&listen_timeout=%d",
2487 rt->listen_timeout * 1000);
2489 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2493 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2494 &s->interrupt_callback, &opts)) < 0) {
2495 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2499 if (rt->swfverify) {
2500 if ((ret = rtmp_calc_swfhash(s)) < 0)
2504 rt->state = STATE_START;
2505 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2507 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2510 rt->out_chunk_size = 128;
2511 rt->in_chunk_size = 128; // Probably overwritten later
2512 rt->state = STATE_HANDSHAKED;
2514 // Keep the application name when it has been defined by the user.
2517 rt->app = av_malloc(APP_MAX_LENGTH);
2519 ret = AVERROR(ENOMEM);
2523 //extract "app" part from path
2524 qmark = strchr(path, '?');
2525 if (qmark && strstr(qmark, "slist=")) {
2527 // After slist we have the playpath, before the params, the app
2528 av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH));
2529 fname = strstr(path, "slist=") + 6;
2530 // Strip any further query parameters from fname
2531 amp = strchr(fname, '&');
2533 av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2534 sizeof(fname_buffer)));
2535 fname = fname_buffer;
2537 } else if (!strncmp(path, "/ondemand/", 10)) {
2539 memcpy(rt->app, "ondemand", 9);
2541 char *next = *path ? path + 1 : path;
2542 char *p = strchr(next, '/');
2547 // make sure we do not mismatch a playpath for an application instance
2548 char *c = strchr(p + 1, ':');
2549 fname = strchr(p + 1, '/');
2550 if (!fname || (c && c < fname)) {
2552 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2555 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2561 // The name of application has been defined by the user, override it.
2566 if (!rt->playpath) {
2567 int len = strlen(fname);
2569 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2570 if (!rt->playpath) {
2571 ret = AVERROR(ENOMEM);
2575 if (!strchr(fname, ':') && len >= 4 &&
2576 (!strcmp(fname + len - 4, ".f4v") ||
2577 !strcmp(fname + len - 4, ".mp4"))) {
2578 memcpy(rt->playpath, "mp4:", 5);
2580 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2581 fname[len - 4] = '\0';
2582 rt->playpath[0] = 0;
2584 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2588 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2590 ret = AVERROR(ENOMEM);
2593 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2594 port, "/%s", rt->app);
2597 if (!rt->flashver) {
2598 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2599 if (!rt->flashver) {
2600 ret = AVERROR(ENOMEM);
2604 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2605 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2606 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2608 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2609 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2613 rt->client_report_size = 1048576;
2617 rt->received_metadata = 0;
2618 rt->last_bytes_read = 0;
2619 rt->server_bw = 2500000;
2621 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2622 proto, path, rt->app, rt->playpath);
2624 if ((ret = gen_connect(s, rt)) < 0)
2627 if ((ret = read_connect(s, s->priv_data)) < 0)
2632 ret = get_packet(s, 1);
2633 } while (ret == AVERROR(EAGAIN));
2637 if (rt->do_reconnect) {
2639 ffurl_close(rt->stream);
2641 rt->do_reconnect = 0;
2643 for (i = 0; i < 2; i++)
2644 memset(rt->prev_pkt[i], 0,
2645 sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2646 free_tracked_methods(rt);
2652 // generate FLV header for demuxer
2654 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2657 memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2659 // Read packets until we reach the first A/V packet or read metadata.
2660 // If there was a metadata package in front of the A/V packets, we can
2661 // build the FLV header from this. If we do not receive any metadata,
2662 // the FLV decoder will allocate the needed streams when their first
2663 // audio or video packet arrives.
2664 while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2665 if ((ret = get_packet(s, 0)) < 0)
2669 // Either after we have read the metadata or (if there is none) the
2670 // first packet of an A/V stream, we have a better knowledge about the
2671 // streams, so set the FLV header accordingly.
2672 if (rt->has_audio) {
2673 rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO;
2675 if (rt->has_video) {
2676 rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO;
2680 rt->flv_data = NULL;
2682 rt->skip_bytes = 13;
2685 s->max_packet_size = rt->stream->max_packet_size;
2690 av_dict_free(&opts);
2695 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2697 RTMPContext *rt = s->priv_data;
2698 int orig_size = size;
2702 int data_left = rt->flv_size - rt->flv_off;
2704 if (data_left >= size) {
2705 memcpy(buf, rt->flv_data + rt->flv_off, size);
2706 rt->flv_off += size;
2709 if (data_left > 0) {
2710 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2713 rt->flv_off = rt->flv_size;
2716 if ((ret = get_packet(s, 0)) < 0)
2722 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2725 RTMPContext *rt = s->priv_data;
2727 av_log(s, AV_LOG_DEBUG,
2728 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2729 stream_index, timestamp, flags);
2730 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2731 av_log(s, AV_LOG_ERROR,
2732 "Unable to send seek command on stream index %d at timestamp "
2733 "%"PRId64" with flags %08x\n",
2734 stream_index, timestamp, flags);
2737 rt->flv_off = rt->flv_size;
2738 rt->state = STATE_SEEKING;
2742 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2744 RTMPContext *rt = s->priv_data;
2745 int size_temp = size;
2746 int pktsize, pkttype;
2748 const uint8_t *buf_temp = buf;
2753 if (rt->skip_bytes) {
2754 int skip = FFMIN(rt->skip_bytes, size_temp);
2757 rt->skip_bytes -= skip;
2761 if (rt->flv_header_bytes < RTMP_HEADER) {
2762 const uint8_t *header = rt->flv_header;
2763 int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2764 int channel = RTMP_AUDIO_CHANNEL;
2765 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2766 rt->flv_header_bytes += copy;
2768 if (rt->flv_header_bytes < RTMP_HEADER)
2771 pkttype = bytestream_get_byte(&header);
2772 pktsize = bytestream_get_be24(&header);
2773 ts = bytestream_get_be24(&header);
2774 ts |= bytestream_get_byte(&header) << 24;
2775 bytestream_get_be24(&header);
2776 rt->flv_size = pktsize;
2778 if (pkttype == RTMP_PT_VIDEO)
2779 channel = RTMP_VIDEO_CHANNEL;
2781 //force 12bytes header
2782 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2783 pkttype == RTMP_PT_NOTIFY) {
2784 if (pkttype == RTMP_PT_NOTIFY)
2786 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2787 &rt->nb_prev_pkt[1],
2790 rt->prev_pkt[1][channel].channel_id = 0;
2793 //this can be a big packet, it's better to send it right here
2794 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2795 pkttype, ts, pktsize)) < 0)
2798 rt->out_pkt.extra = rt->stream_id;
2799 rt->flv_data = rt->out_pkt.data;
2801 if (pkttype == RTMP_PT_NOTIFY)
2802 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2805 if (rt->flv_size - rt->flv_off > size_temp) {
2806 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2807 rt->flv_off += size_temp;
2810 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2811 size_temp -= rt->flv_size - rt->flv_off;
2812 rt->flv_off += rt->flv_size - rt->flv_off;
2815 if (rt->flv_off == rt->flv_size) {
2818 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2822 rt->flv_header_bytes = 0;
2823 rt->flv_nb_packets++;
2825 } while (buf_temp - buf < size);
2827 if (rt->flv_nb_packets < rt->flush_interval)
2829 rt->flv_nb_packets = 0;
2831 /* set stream into nonblocking mode */
2832 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2834 /* try to read one byte from the stream */
2835 ret = ffurl_read(rt->stream, &c, 1);
2837 /* switch the stream back into blocking mode */
2838 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2840 if (ret == AVERROR(EAGAIN)) {
2841 /* no incoming data to handle */
2843 } else if (ret < 0) {
2845 } else if (ret == 1) {
2846 RTMPPacket rpkt = { 0 };
2848 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2851 &rt->nb_prev_pkt[0], c)) <= 0)
2854 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2857 ff_rtmp_packet_destroy(&rpkt);
2863 #define OFFSET(x) offsetof(RTMPContext, x)
2864 #define DEC AV_OPT_FLAG_DECODING_PARAM
2865 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2867 static const AVOption rtmp_options[] = {
2868 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2869 {"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},
2870 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2871 {"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},
2872 {"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},
2873 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2874 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2875 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2876 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2877 {"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},
2878 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2879 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2880 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2881 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2882 {"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},
2883 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2884 {"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},
2885 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2886 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2887 {"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, "rtmp_listen" },
2891 #define RTMP_PROTOCOL(flavor) \
2892 static const AVClass flavor##_class = { \
2893 .class_name = #flavor, \
2894 .item_name = av_default_item_name, \
2895 .option = rtmp_options, \
2896 .version = LIBAVUTIL_VERSION_INT, \
2899 URLProtocol ff_##flavor##_protocol = { \
2901 .url_open = rtmp_open, \
2902 .url_read = rtmp_read, \
2903 .url_read_seek = rtmp_seek, \
2904 .url_write = rtmp_write, \
2905 .url_close = rtmp_close, \
2906 .priv_data_size = sizeof(RTMPContext), \
2907 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2908 .priv_data_class= &flavor##_class, \
2913 RTMP_PROTOCOL(rtmpe)
2914 RTMP_PROTOCOL(rtmps)
2915 RTMP_PROTOCOL(rtmpt)
2916 RTMP_PROTOCOL(rtmpte)
2917 RTMP_PROTOCOL(rtmpts)