2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of FFmpeg.
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.
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.
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
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 1024
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
57 /** RTMP protocol handler state */
59 STATE_START, ///< client has not done anything yet
60 STATE_HANDSHAKED, ///< client has performed handshake
61 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
62 STATE_PLAYING, ///< client has started receiving multimedia data from server
63 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
64 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
65 STATE_RECEIVING, ///< received a publish command (for input)
66 STATE_STOPPED, ///< the broadcast has been stopped
69 typedef struct TrackedMethod {
74 /** protocol handler context */
75 typedef struct RTMPContext {
77 URLContext* stream; ///< TCP stream used in interactions with RTMP server
78 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
79 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
80 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
81 int is_input; ///< input/output flag
82 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
83 int live; ///< 0: recorded, -1: live, -2: both
84 char *app; ///< name of application
85 char *conn; ///< append arbitrary AMF data to the Connect message
86 ClientState state; ///< current state
87 int main_channel_id; ///< an additional channel ID which is used for some invocations
88 uint8_t* flv_data; ///< buffer with data for demuxer
89 int flv_size; ///< current buffer size
90 int flv_off; ///< number of bytes read from current buffer
91 int flv_nb_packets; ///< number of flv packets published
92 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
93 uint32_t client_report_size; ///< number of bytes after which client should report to server
94 uint32_t bytes_read; ///< number of bytes read from server
95 uint32_t last_bytes_read; ///< number of bytes read last reported to server
96 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
97 uint8_t flv_header[11]; ///< partial incoming flv packet header
98 int flv_header_bytes; ///< number of initialized bytes in flv_header
99 int nb_invokes; ///< keeps track of invoke messages
100 char* tcurl; ///< url of the target stream
101 char* flashver; ///< version of the flash plugin
102 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
103 int swfhash_len; ///< length of the SHA256 hash
104 int swfsize; ///< size of the decompressed SWF file
105 char* swfurl; ///< url of the swf player
106 char* swfverify; ///< URL to player swf file, compute hash/size automatically
107 char swfverification[42]; ///< hash of the SWF verification
108 char* pageurl; ///< url of the web page
109 char* subscribe; ///< name of live stream to subscribe
110 int server_bw; ///< server bandwidth
111 int client_buffer_time; ///< client buffer time in ms
112 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
113 int encrypted; ///< use an encrypted connection (RTMPE only)
114 TrackedMethod*tracked_methods; ///< tracked methods buffer
115 int nb_tracked_methods; ///< number of tracked methods
116 int tracked_methods_size; ///< size of the tracked methods buffer
117 int listen; ///< listen mode flag
118 int listen_timeout; ///< listen timeout to wait for new connections
119 int nb_streamid; ///< The next stream id to return on createStream calls
122 char auth_params[500];
127 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
128 /** Client key used for digest signing */
129 static const uint8_t rtmp_player_key[] = {
130 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
131 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
133 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
134 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
135 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
138 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
139 /** Key used for RTMP server digest signing */
140 static const uint8_t rtmp_server_key[] = {
141 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
142 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
143 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
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
150 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
154 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
155 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
156 ptr = av_realloc(rt->tracked_methods,
157 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
159 return AVERROR(ENOMEM);
160 rt->tracked_methods = ptr;
163 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
164 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
165 return AVERROR(ENOMEM);
166 rt->tracked_methods[rt->nb_tracked_methods].id = id;
167 rt->nb_tracked_methods++;
172 static void del_tracked_method(RTMPContext *rt, int index)
174 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
175 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
176 rt->nb_tracked_methods--;
179 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
180 char **tracked_method)
182 RTMPContext *rt = s->priv_data;
188 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
189 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
192 for (i = 0; i < rt->nb_tracked_methods; i++) {
193 if (rt->tracked_methods[i].id != pkt_id)
196 *tracked_method = rt->tracked_methods[i].name;
197 del_tracked_method(rt, i);
204 static void free_tracked_methods(RTMPContext *rt)
208 for (i = 0; i < rt->nb_tracked_methods; i ++)
209 av_free(rt->tracked_methods[i].name);
210 av_free(rt->tracked_methods);
211 rt->tracked_methods = NULL;
212 rt->tracked_methods_size = 0;
213 rt->nb_tracked_methods = 0;
216 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
220 if (pkt->type == RTMP_PT_INVOKE && track) {
226 bytestream2_init(&gbc, pkt->data, pkt->data_size);
227 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
230 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
233 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
237 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
240 ff_rtmp_packet_destroy(pkt);
244 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
249 /* The type must be B for Boolean, N for number, S for string, O for
250 * object, or Z for null. For Booleans the data must be either 0 or 1 for
251 * FALSE or TRUE, respectively. Likewise for Objects the data must be
252 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
253 * may be named, by prefixing the type with 'N' and specifying the name
254 * before the value (ie. NB:myFlag:1). This option may be used multiple times
255 * to construct arbitrary AMF sequences. */
256 if (param[0] && param[1] == ':') {
259 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
262 value = strchr(field, ':');
268 ff_amf_write_field_name(p, field);
275 ff_amf_write_bool(p, value[0] != '0');
278 ff_amf_write_string(p, value);
281 ff_amf_write_number(p, strtod(value, NULL));
284 ff_amf_write_null(p);
288 ff_amf_write_object_start(p);
290 ff_amf_write_object_end(p);
300 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
301 return AVERROR(EINVAL);
305 * Generate 'connect' call and send it to the server.
307 static int gen_connect(URLContext *s, RTMPContext *rt)
313 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
314 0, 4096 + APP_MAX_LENGTH)) < 0)
319 ff_amf_write_string(&p, "connect");
320 ff_amf_write_number(&p, ++rt->nb_invokes);
321 ff_amf_write_object_start(&p);
322 ff_amf_write_field_name(&p, "app");
323 ff_amf_write_string2(&p, rt->app, rt->auth_params);
326 ff_amf_write_field_name(&p, "type");
327 ff_amf_write_string(&p, "nonprivate");
329 ff_amf_write_field_name(&p, "flashVer");
330 ff_amf_write_string(&p, rt->flashver);
333 ff_amf_write_field_name(&p, "swfUrl");
334 ff_amf_write_string(&p, rt->swfurl);
337 ff_amf_write_field_name(&p, "tcUrl");
338 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
340 ff_amf_write_field_name(&p, "fpad");
341 ff_amf_write_bool(&p, 0);
342 ff_amf_write_field_name(&p, "capabilities");
343 ff_amf_write_number(&p, 15.0);
345 /* Tell the server we support all the audio codecs except
346 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
347 * which are unused in the RTMP protocol implementation. */
348 ff_amf_write_field_name(&p, "audioCodecs");
349 ff_amf_write_number(&p, 4071.0);
350 ff_amf_write_field_name(&p, "videoCodecs");
351 ff_amf_write_number(&p, 252.0);
352 ff_amf_write_field_name(&p, "videoFunction");
353 ff_amf_write_number(&p, 1.0);
356 ff_amf_write_field_name(&p, "pageUrl");
357 ff_amf_write_string(&p, rt->pageurl);
360 ff_amf_write_object_end(&p);
363 char *param = rt->conn;
365 // Write arbitrary AMF data to the Connect message.
366 while (param != NULL) {
368 param += strspn(param, " ");
371 sep = strchr(param, ' ');
374 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
375 // Invalid AMF parameter.
376 ff_rtmp_packet_destroy(&pkt);
387 pkt.data_size = p - pkt.data;
389 return rtmp_send_packet(rt, &pkt, 1);
392 static int read_connect(URLContext *s, RTMPContext *rt)
394 RTMPPacket pkt = { 0 };
404 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
405 rt->prev_pkt[1])) < 0)
408 bytestream2_init(&gbc, cp, pkt.data_size);
409 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
410 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
411 ff_rtmp_packet_destroy(&pkt);
412 return AVERROR_INVALIDDATA;
414 if (strcmp(command, "connect")) {
415 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
416 ff_rtmp_packet_destroy(&pkt);
417 return AVERROR_INVALIDDATA;
419 ret = ff_amf_read_number(&gbc, &seqnum);
421 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
422 /* Here one could parse an AMF Object with data as flashVers and others. */
423 ret = ff_amf_get_field_value(gbc.buffer,
424 gbc.buffer + bytestream2_get_bytes_left(&gbc),
425 "app", tmpstr, sizeof(tmpstr));
427 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
428 if (!ret && strcmp(tmpstr, rt->app))
429 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
431 ff_rtmp_packet_destroy(&pkt);
433 // Send Window Acknowledgement Size (as defined in speficication)
434 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
435 RTMP_PT_SERVER_BW, 0, 4)) < 0)
438 bytestream_put_be32(&p, rt->server_bw);
439 pkt.data_size = p - pkt.data;
440 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
442 ff_rtmp_packet_destroy(&pkt);
445 // Send Peer Bandwidth
446 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
447 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
450 bytestream_put_be32(&p, rt->server_bw);
451 bytestream_put_byte(&p, 2); // dynamic
452 pkt.data_size = p - pkt.data;
453 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
455 ff_rtmp_packet_destroy(&pkt);
460 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
461 RTMP_PT_PING, 0, 6)) < 0)
465 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
466 bytestream_put_be32(&p, 0);
467 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
469 ff_rtmp_packet_destroy(&pkt);
474 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
475 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
479 bytestream_put_be32(&p, rt->out_chunk_size);
480 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
482 ff_rtmp_packet_destroy(&pkt);
486 // Send result_ NetConnection.Connect.Success to connect
487 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
489 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
493 ff_amf_write_string(&p, "_result");
494 ff_amf_write_number(&p, seqnum);
496 ff_amf_write_object_start(&p);
497 ff_amf_write_field_name(&p, "fmsVer");
498 ff_amf_write_string(&p, "FMS/3,0,1,123");
499 ff_amf_write_field_name(&p, "capabilities");
500 ff_amf_write_number(&p, 31);
501 ff_amf_write_object_end(&p);
503 ff_amf_write_object_start(&p);
504 ff_amf_write_field_name(&p, "level");
505 ff_amf_write_string(&p, "status");
506 ff_amf_write_field_name(&p, "code");
507 ff_amf_write_string(&p, "NetConnection.Connect.Success");
508 ff_amf_write_field_name(&p, "description");
509 ff_amf_write_string(&p, "Connection succeeded.");
510 ff_amf_write_field_name(&p, "objectEncoding");
511 ff_amf_write_number(&p, 0);
512 ff_amf_write_object_end(&p);
514 pkt.data_size = p - pkt.data;
515 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
517 ff_rtmp_packet_destroy(&pkt);
521 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
522 RTMP_PT_INVOKE, 0, 30)) < 0)
525 ff_amf_write_string(&p, "onBWDone");
526 ff_amf_write_number(&p, 0);
527 ff_amf_write_null(&p);
528 ff_amf_write_number(&p, 8192);
529 pkt.data_size = p - pkt.data;
530 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
532 ff_rtmp_packet_destroy(&pkt);
538 * Generate 'releaseStream' call and send it to the server. It should make
539 * the server release some channel for media streams.
541 static int gen_release_stream(URLContext *s, RTMPContext *rt)
547 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
548 0, 29 + strlen(rt->playpath))) < 0)
551 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
553 ff_amf_write_string(&p, "releaseStream");
554 ff_amf_write_number(&p, ++rt->nb_invokes);
555 ff_amf_write_null(&p);
556 ff_amf_write_string(&p, rt->playpath);
558 return rtmp_send_packet(rt, &pkt, 1);
562 * Generate 'FCPublish' call and send it to the server. It should make
563 * the server preapare for receiving media streams.
565 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
571 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
572 0, 25 + strlen(rt->playpath))) < 0)
575 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
577 ff_amf_write_string(&p, "FCPublish");
578 ff_amf_write_number(&p, ++rt->nb_invokes);
579 ff_amf_write_null(&p);
580 ff_amf_write_string(&p, rt->playpath);
582 return rtmp_send_packet(rt, &pkt, 1);
586 * Generate 'FCUnpublish' call and send it to the server. It should make
587 * the server destroy stream.
589 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
595 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
596 0, 27 + strlen(rt->playpath))) < 0)
599 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
601 ff_amf_write_string(&p, "FCUnpublish");
602 ff_amf_write_number(&p, ++rt->nb_invokes);
603 ff_amf_write_null(&p);
604 ff_amf_write_string(&p, rt->playpath);
606 return rtmp_send_packet(rt, &pkt, 0);
610 * Generate 'createStream' call and send it to the server. It should make
611 * the server allocate some channel for media streams.
613 static int gen_create_stream(URLContext *s, RTMPContext *rt)
619 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
621 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
626 ff_amf_write_string(&p, "createStream");
627 ff_amf_write_number(&p, ++rt->nb_invokes);
628 ff_amf_write_null(&p);
630 return rtmp_send_packet(rt, &pkt, 1);
635 * Generate 'deleteStream' call and send it to the server. It should make
636 * the server remove some channel for media streams.
638 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
644 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
646 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
651 ff_amf_write_string(&p, "deleteStream");
652 ff_amf_write_number(&p, ++rt->nb_invokes);
653 ff_amf_write_null(&p);
654 ff_amf_write_number(&p, rt->main_channel_id);
656 return rtmp_send_packet(rt, &pkt, 0);
660 * Generate client buffer time and send it to the server.
662 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
668 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
673 bytestream_put_be16(&p, 3);
674 bytestream_put_be32(&p, rt->main_channel_id);
675 bytestream_put_be32(&p, rt->client_buffer_time);
677 return rtmp_send_packet(rt, &pkt, 0);
681 * Generate 'play' call and send it to the server, then ping the server
682 * to start actual playing.
684 static int gen_play(URLContext *s, RTMPContext *rt)
690 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
692 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
693 0, 29 + strlen(rt->playpath))) < 0)
696 pkt.extra = rt->main_channel_id;
699 ff_amf_write_string(&p, "play");
700 ff_amf_write_number(&p, ++rt->nb_invokes);
701 ff_amf_write_null(&p);
702 ff_amf_write_string(&p, rt->playpath);
703 ff_amf_write_number(&p, rt->live);
705 return rtmp_send_packet(rt, &pkt, 1);
708 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
714 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %lld\n", timestamp);
716 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
719 pkt.extra = rt->main_channel_id;
722 ff_amf_write_string(&p, "seek");
723 ff_amf_write_number(&p, 0); //no tracking back responses
724 ff_amf_write_null(&p); //as usual, the first null param
725 ff_amf_write_number(&p, timestamp); //where we want to jump
727 return rtmp_send_packet(rt, &pkt, 1);
731 * Generate 'publish' call and send it to the server.
733 static int gen_publish(URLContext *s, RTMPContext *rt)
739 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
741 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
742 0, 30 + strlen(rt->playpath))) < 0)
745 pkt.extra = rt->main_channel_id;
748 ff_amf_write_string(&p, "publish");
749 ff_amf_write_number(&p, ++rt->nb_invokes);
750 ff_amf_write_null(&p);
751 ff_amf_write_string(&p, rt->playpath);
752 ff_amf_write_string(&p, "live");
754 return rtmp_send_packet(rt, &pkt, 1);
758 * Generate ping reply and send it to the server.
760 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
766 if (ppkt->data_size < 6) {
767 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
769 return AVERROR_INVALIDDATA;
772 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
773 ppkt->timestamp + 1, 6)) < 0)
777 bytestream_put_be16(&p, 7);
778 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
780 return rtmp_send_packet(rt, &pkt, 0);
784 * Generate SWF verification message and send it to the server.
786 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
792 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
793 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
798 bytestream_put_be16(&p, 27);
799 memcpy(p, rt->swfverification, 42);
801 return rtmp_send_packet(rt, &pkt, 0);
805 * Generate server bandwidth message and send it to the server.
807 static int gen_server_bw(URLContext *s, RTMPContext *rt)
813 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
818 bytestream_put_be32(&p, rt->server_bw);
820 return rtmp_send_packet(rt, &pkt, 0);
824 * Generate check bandwidth message and send it to the server.
826 static int gen_check_bw(URLContext *s, RTMPContext *rt)
832 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
837 ff_amf_write_string(&p, "_checkbw");
838 ff_amf_write_number(&p, ++rt->nb_invokes);
839 ff_amf_write_null(&p);
841 return rtmp_send_packet(rt, &pkt, 1);
845 * Generate report on bytes read so far and send it to the server.
847 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
853 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
858 bytestream_put_be32(&p, rt->bytes_read);
860 return rtmp_send_packet(rt, &pkt, 0);
863 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
864 const char *subscribe)
870 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
871 0, 27 + strlen(subscribe))) < 0)
875 ff_amf_write_string(&p, "FCSubscribe");
876 ff_amf_write_number(&p, ++rt->nb_invokes);
877 ff_amf_write_null(&p);
878 ff_amf_write_string(&p, subscribe);
880 return rtmp_send_packet(rt, &pkt, 1);
883 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
884 const uint8_t *key, int keylen, uint8_t *dst)
887 uint8_t hmac_buf[64+32] = {0};
890 sha = av_sha_alloc();
892 return AVERROR(ENOMEM);
895 memcpy(hmac_buf, key, keylen);
897 av_sha_init(sha, 256);
898 av_sha_update(sha,key, keylen);
899 av_sha_final(sha, hmac_buf);
901 for (i = 0; i < 64; i++)
902 hmac_buf[i] ^= HMAC_IPAD_VAL;
904 av_sha_init(sha, 256);
905 av_sha_update(sha, hmac_buf, 64);
907 av_sha_update(sha, src, len);
908 } else { //skip 32 bytes used for storing digest
909 av_sha_update(sha, src, gap);
910 av_sha_update(sha, src + gap + 32, len - gap - 32);
912 av_sha_final(sha, hmac_buf + 64);
914 for (i = 0; i < 64; i++)
915 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
916 av_sha_init(sha, 256);
917 av_sha_update(sha, hmac_buf, 64+32);
918 av_sha_final(sha, dst);
925 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
928 int i, digest_pos = 0;
930 for (i = 0; i < 4; i++)
931 digest_pos += buf[i + off];
932 digest_pos = digest_pos % mod_val + add_val;
938 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
939 * will be stored) into that packet.
941 * @param buf handshake data (1536 bytes)
942 * @param encrypted use an encrypted connection (RTMPE)
943 * @return offset to the digest inside input data
945 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
950 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
952 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
954 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
955 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
964 * Verify that the received server response has the expected digest value.
966 * @param buf handshake data received from the server (1536 bytes)
967 * @param off position to search digest offset from
968 * @return 0 if digest is valid, digest position otherwise
970 static int rtmp_validate_digest(uint8_t *buf, int off)
975 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
977 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
978 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
983 if (!memcmp(digest, buf + digest_pos, 32))
988 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
994 if (rt->swfhash_len != 32) {
995 av_log(s, AV_LOG_ERROR,
996 "Hash of the decompressed SWF file is not 32 bytes long.\n");
997 return AVERROR(EINVAL);
1000 p = &rt->swfverification[0];
1001 bytestream_put_byte(&p, 1);
1002 bytestream_put_byte(&p, 1);
1003 bytestream_put_be32(&p, rt->swfsize);
1004 bytestream_put_be32(&p, rt->swfsize);
1006 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1013 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1014 uint8_t **out_data, int64_t *out_size)
1016 z_stream zs = { 0 };
1021 zs.avail_in = in_size;
1022 zs.next_in = in_data;
1023 ret = inflateInit(&zs);
1025 return AVERROR_UNKNOWN;
1028 uint8_t tmp_buf[16384];
1030 zs.avail_out = sizeof(tmp_buf);
1031 zs.next_out = tmp_buf;
1033 ret = inflate(&zs, Z_NO_FLUSH);
1034 if (ret != Z_OK && ret != Z_STREAM_END) {
1035 ret = AVERROR_UNKNOWN;
1039 size = sizeof(tmp_buf) - zs.avail_out;
1040 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1041 ret = AVERROR(ENOMEM);
1046 memcpy(*out_data + *out_size, tmp_buf, size);
1048 } while (zs.avail_out == 0);
1056 static int rtmp_calc_swfhash(URLContext *s)
1058 RTMPContext *rt = s->priv_data;
1059 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1060 int64_t in_size, out_size;
1066 /* Get the SWF player file. */
1067 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1068 &s->interrupt_callback, NULL)) < 0) {
1069 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1073 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1078 if (!(in_data = av_malloc(in_size))) {
1079 ret = AVERROR(ENOMEM);
1083 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1087 ret = AVERROR_INVALIDDATA;
1091 if (!memcmp(in_data, "CWS", 3)) {
1092 /* Decompress the SWF player file using Zlib. */
1093 if (!(out_data = av_malloc(8))) {
1094 ret = AVERROR(ENOMEM);
1097 *in_data = 'F'; // magic stuff
1098 memcpy(out_data, in_data, 8);
1102 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1103 &out_data, &out_size)) < 0)
1106 av_log(s, AV_LOG_ERROR,
1107 "Zlib is required for decompressing the SWF player file.\n");
1108 ret = AVERROR(EINVAL);
1118 /* Compute the SHA256 hash of the SWF player file. */
1119 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1120 "Genuine Adobe Flash Player 001", 30,
1124 /* Set SWFVerification parameters. */
1125 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1126 rt->swfsize = swfsize;
1130 av_freep(&out_data);
1131 ffurl_close(stream);
1136 * Perform handshake with the server by means of exchanging pseudorandom data
1137 * signed with HMAC-SHA2 digest.
1139 * @return 0 if handshake succeeds, negative value otherwise
1141 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1144 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1145 3, // unencrypted data
1146 0, 0, 0, 0, // client uptime
1152 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1153 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1155 int server_pos, client_pos;
1156 uint8_t digest[32], signature[32];
1159 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1161 av_lfg_init(&rnd, 0xDEADC0DE);
1162 // generate handshake packet - 1536 bytes of pseudorandom data
1163 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1164 tosend[i] = av_lfg_get(&rnd) >> 24;
1166 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1167 /* When the client wants to use RTMPE, we have to change the command
1168 * byte to 0x06 which means to use encrypted data and we have to set
1169 * the flash version to at least 9.0.115.0. */
1176 /* Initialize the Diffie-Hellmann context and generate the public key
1177 * to send to the server. */
1178 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1182 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1186 if ((ret = ffurl_write(rt->stream, tosend,
1187 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1188 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1192 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1193 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1194 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1198 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1199 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1200 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1204 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1205 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1206 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1208 if (rt->is_input && serverdata[5] >= 3) {
1209 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1215 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1220 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1221 return AVERROR(EIO);
1225 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1226 * key are the last 32 bytes of the server handshake. */
1228 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1229 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1233 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1234 rtmp_server_key, sizeof(rtmp_server_key),
1239 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1240 0, digest, 32, signature);
1244 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1245 /* Compute the shared secret key sent by the server and initialize
1246 * the RC4 encryption. */
1247 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1248 tosend + 1, type)) < 0)
1251 /* Encrypt the signature received by the server. */
1252 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1255 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1256 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1257 return AVERROR(EIO);
1260 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1261 tosend[i] = av_lfg_get(&rnd) >> 24;
1262 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1263 rtmp_player_key, sizeof(rtmp_player_key),
1268 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1270 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1274 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1275 /* Encrypt the signature to be send to the server. */
1276 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1277 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1281 // write reply back to the server
1282 if ((ret = ffurl_write(rt->stream, tosend,
1283 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1286 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1287 /* Set RC4 keys for encryption and update the keystreams. */
1288 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1292 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1293 /* Compute the shared secret key sent by the server and initialize
1294 * the RC4 encryption. */
1295 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1296 tosend + 1, 1)) < 0)
1299 if (serverdata[0] == 9) {
1300 /* Encrypt the signature received by the server. */
1301 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1306 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1307 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1310 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1311 /* Set RC4 keys for encryption and update the keystreams. */
1312 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1320 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1321 uint32_t *second_int, char *arraydata,
1326 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1327 RTMP_HANDSHAKE_PACKET_SIZE);
1329 return AVERROR(EIO);
1330 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1331 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1332 " not following standard\n", (int)inoutsize);
1333 return AVERROR(EINVAL);
1336 *first_int = AV_RB32(arraydata);
1337 *second_int = AV_RB32(arraydata + 4);
1341 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1342 uint32_t second_int, char *arraydata, int size)
1346 AV_WB32(arraydata, first_int);
1347 AV_WB32(arraydata + 4, first_int);
1348 inoutsize = ffurl_write(rt->stream, arraydata,
1349 RTMP_HANDSHAKE_PACKET_SIZE);
1350 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1351 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1352 return AVERROR(EIO);
1359 * rtmp handshake server side
1361 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1363 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1365 uint32_t hs_my_epoch;
1366 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1367 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1374 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1375 if (inoutsize <= 0) {
1376 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1377 return AVERROR(EIO);
1380 if (buffer[0] != 3) {
1381 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1382 return AVERROR(EIO);
1384 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1385 av_log(s, AV_LOG_ERROR,
1386 "Unable to write answer - RTMP S0\n");
1387 return AVERROR(EIO);
1390 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1391 RTMP_HANDSHAKE_PACKET_SIZE);
1393 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1397 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1399 /* By now same epoch will be sent */
1400 hs_my_epoch = hs_epoch;
1401 /* Generate random */
1402 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1404 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1406 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1407 RTMP_HANDSHAKE_PACKET_SIZE);
1409 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1413 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1414 RTMP_HANDSHAKE_PACKET_SIZE);
1416 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1420 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1421 RTMP_HANDSHAKE_PACKET_SIZE);
1423 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1426 if (temp != hs_my_epoch)
1427 av_log(s, AV_LOG_WARNING,
1428 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1429 if (memcmp(buffer + 8, hs_s1 + 8,
1430 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1431 av_log(s, AV_LOG_WARNING,
1432 "Erroneous C2 Message random does not match up\n");
1437 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1439 RTMPContext *rt = s->priv_data;
1442 if (pkt->data_size < 4) {
1443 av_log(s, AV_LOG_ERROR,
1444 "Too short chunk size change packet (%d)\n",
1446 return AVERROR_INVALIDDATA;
1449 if (!rt->is_input) {
1450 /* Send the same chunk size change packet back to the server,
1451 * setting the outgoing chunk size to the same as the incoming one. */
1452 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1453 rt->prev_pkt[1])) < 0)
1455 rt->out_chunk_size = AV_RB32(pkt->data);
1458 rt->in_chunk_size = AV_RB32(pkt->data);
1459 if (rt->in_chunk_size <= 0) {
1460 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1462 return AVERROR_INVALIDDATA;
1464 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1470 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1472 RTMPContext *rt = s->priv_data;
1475 if (pkt->data_size < 2) {
1476 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1478 return AVERROR_INVALIDDATA;
1481 t = AV_RB16(pkt->data);
1483 if ((ret = gen_pong(s, rt, pkt)) < 0)
1485 } else if (t == 26) {
1487 if ((ret = gen_swf_verification(s, rt)) < 0)
1490 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1497 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1499 RTMPContext *rt = s->priv_data;
1501 if (pkt->data_size < 4) {
1502 av_log(s, AV_LOG_ERROR,
1503 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1505 return AVERROR_INVALIDDATA;
1508 rt->client_report_size = AV_RB32(pkt->data);
1509 if (rt->client_report_size <= 0) {
1510 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1511 rt->client_report_size);
1512 return AVERROR_INVALIDDATA;
1515 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1516 rt->client_report_size >>= 1;
1521 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1523 RTMPContext *rt = s->priv_data;
1525 if (pkt->data_size < 4) {
1526 av_log(s, AV_LOG_ERROR,
1527 "Too short server bandwidth report packet (%d)\n",
1529 return AVERROR_INVALIDDATA;
1532 rt->server_bw = AV_RB32(pkt->data);
1533 if (rt->server_bw <= 0) {
1534 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1536 return AVERROR_INVALIDDATA;
1538 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1543 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1544 const char *opaque, const char *challenge)
1547 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1548 struct AVMD5 *md5 = av_md5_alloc();
1550 return AVERROR(ENOMEM);
1552 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1555 av_md5_update(md5, user, strlen(user));
1556 av_md5_update(md5, salt, strlen(salt));
1557 av_md5_update(md5, rt->password, strlen(rt->password));
1558 av_md5_final(md5, hash);
1559 av_base64_encode(hashstr, sizeof(hashstr), hash,
1562 av_md5_update(md5, hashstr, strlen(hashstr));
1564 av_md5_update(md5, opaque, strlen(opaque));
1566 av_md5_update(md5, challenge, strlen(challenge));
1567 av_md5_update(md5, challenge2, strlen(challenge2));
1568 av_md5_final(md5, hash);
1569 av_base64_encode(hashstr, sizeof(hashstr), hash,
1571 snprintf(rt->auth_params, sizeof(rt->auth_params),
1572 "?authmod=%s&user=%s&challenge=%s&response=%s",
1573 "adobe", user, challenge2, hashstr);
1575 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1576 "&opaque=%s", opaque);
1582 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1585 char hashstr1[33], hashstr2[33];
1586 const char *realm = "live";
1587 const char *method = "publish";
1588 const char *qop = "auth";
1589 const char *nc = "00000001";
1591 struct AVMD5 *md5 = av_md5_alloc();
1593 return AVERROR(ENOMEM);
1595 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1598 av_md5_update(md5, user, strlen(user));
1599 av_md5_update(md5, ":", 1);
1600 av_md5_update(md5, realm, strlen(realm));
1601 av_md5_update(md5, ":", 1);
1602 av_md5_update(md5, rt->password, strlen(rt->password));
1603 av_md5_final(md5, hash);
1604 ff_data_to_hex(hashstr1, hash, 16, 1);
1605 hashstr1[32] = '\0';
1608 av_md5_update(md5, method, strlen(method));
1609 av_md5_update(md5, ":/", 2);
1610 av_md5_update(md5, rt->app, strlen(rt->app));
1611 av_md5_final(md5, hash);
1612 ff_data_to_hex(hashstr2, hash, 16, 1);
1613 hashstr2[32] = '\0';
1616 av_md5_update(md5, hashstr1, strlen(hashstr1));
1617 av_md5_update(md5, ":", 1);
1619 av_md5_update(md5, nonce, strlen(nonce));
1620 av_md5_update(md5, ":", 1);
1621 av_md5_update(md5, nc, strlen(nc));
1622 av_md5_update(md5, ":", 1);
1623 av_md5_update(md5, cnonce, strlen(cnonce));
1624 av_md5_update(md5, ":", 1);
1625 av_md5_update(md5, qop, strlen(qop));
1626 av_md5_update(md5, ":", 1);
1627 av_md5_update(md5, hashstr2, strlen(hashstr2));
1628 av_md5_final(md5, hash);
1629 ff_data_to_hex(hashstr1, hash, 16, 1);
1631 snprintf(rt->auth_params, sizeof(rt->auth_params),
1632 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1633 "llnw", user, nonce, cnonce, nc, hashstr1);
1639 static int handle_connect_error(URLContext *s, const char *desc)
1641 RTMPContext *rt = s->priv_data;
1642 char buf[300], *ptr, authmod[15];
1644 const char *user = "", *salt = "", *opaque = NULL,
1645 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1647 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1648 !(cptr = strstr(desc, "authmod=llnw"))) {
1649 av_log(s, AV_LOG_ERROR,
1650 "Unknown connect error (unsupported authentication method?)\n");
1651 return AVERROR_UNKNOWN;
1653 cptr += strlen("authmod=");
1654 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1655 authmod[i++] = *cptr++;
1658 if (!rt->username[0] || !rt->password[0]) {
1659 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1660 return AVERROR_UNKNOWN;
1663 if (strstr(desc, "?reason=authfailed")) {
1664 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1665 return AVERROR_UNKNOWN;
1666 } else if (strstr(desc, "?reason=nosuchuser")) {
1667 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1668 return AVERROR_UNKNOWN;
1671 if (rt->auth_tried) {
1672 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1673 return AVERROR_UNKNOWN;
1676 rt->auth_params[0] = '\0';
1678 if (strstr(desc, "code=403 need auth")) {
1679 snprintf(rt->auth_params, sizeof(rt->auth_params),
1680 "?authmod=%s&user=%s", authmod, rt->username);
1684 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1685 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1686 return AVERROR_UNKNOWN;
1689 av_strlcpy(buf, cptr + 1, sizeof(buf));
1693 char *next = strchr(ptr, '&');
1694 char *value = strchr(ptr, '=');
1699 if (!strcmp(ptr, "user")) {
1701 } else if (!strcmp(ptr, "salt")) {
1703 } else if (!strcmp(ptr, "opaque")) {
1705 } else if (!strcmp(ptr, "challenge")) {
1707 } else if (!strcmp(ptr, "nonce")) {
1713 if (!strcmp(authmod, "adobe")) {
1714 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1717 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1725 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1727 RTMPContext *rt = s->priv_data;
1728 const uint8_t *data_end = pkt->data + pkt->data_size;
1729 char *tracked_method = NULL;
1730 int level = AV_LOG_ERROR;
1731 uint8_t tmpstr[256];
1734 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1737 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1738 "description", tmpstr, sizeof(tmpstr))) {
1739 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1740 !strcmp(tracked_method, "releaseStream") ||
1741 !strcmp(tracked_method, "FCSubscribe") ||
1742 !strcmp(tracked_method, "FCPublish"))) {
1743 /* Gracefully ignore Adobe-specific historical artifact errors. */
1744 level = AV_LOG_WARNING;
1746 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1747 ret = handle_connect_error(s, tmpstr);
1749 rt->do_reconnect = 1;
1750 level = AV_LOG_VERBOSE;
1753 ret = AVERROR_UNKNOWN;
1754 av_log(s, level, "Server error: %s\n", tmpstr);
1757 av_free(tracked_method);
1761 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1763 RTMPContext *rt = s->priv_data;
1767 char statusmsg[128];
1770 const uint8_t *p = pkt->data;
1772 RTMPPacket spkt = { 0 };
1776 bytestream2_init(&gbc, p, pkt->data_size);
1777 if (ff_amf_read_string(&gbc, command, sizeof(command),
1779 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1780 return AVERROR_INVALIDDATA;
1783 ret = ff_amf_read_number(&gbc, &seqnum);
1786 ret = ff_amf_read_null(&gbc);
1789 if (!strcmp(command, "FCPublish") ||
1790 !strcmp(command, "publish")) {
1791 ret = ff_amf_read_string(&gbc, filename,
1792 sizeof(filename), &stringlen);
1795 pchar = strrchr(s->filename, '/');
1797 av_log(s, AV_LOG_WARNING,
1798 "Unable to find / in url %s, bad format\n",
1800 pchar = s->filename;
1803 if (strcmp(pchar, filename))
1804 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1805 " %s\n", filename, pchar);
1807 rt->state = STATE_RECEIVING;
1810 if (!strcmp(command, "FCPublish")) {
1811 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1813 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1814 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1818 ff_amf_write_string(&pp, "onFCPublish");
1819 } else if (!strcmp(command, "publish")) {
1821 // Send Stream Begin 1
1822 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1823 RTMP_PT_PING, 0, 6)) < 0) {
1824 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1828 bytestream2_init_writer(&pbc, pp, spkt.data_size);
1829 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1830 bytestream2_put_be32(&pbc, rt->nb_streamid);
1831 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1833 ff_rtmp_packet_destroy(&spkt);
1837 // Send onStatus(NetStream.Publish.Start)
1838 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1840 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1841 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1844 spkt.extra = pkt->extra;
1846 ff_amf_write_string(&pp, "onStatus");
1847 ff_amf_write_number(&pp, 0);
1848 ff_amf_write_null(&pp);
1850 ff_amf_write_object_start(&pp);
1851 ff_amf_write_field_name(&pp, "level");
1852 ff_amf_write_string(&pp, "status");
1853 ff_amf_write_field_name(&pp, "code");
1854 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1855 ff_amf_write_field_name(&pp, "description");
1856 snprintf(statusmsg, sizeof(statusmsg),
1857 "%s is now published", filename);
1858 ff_amf_write_string(&pp, statusmsg);
1859 ff_amf_write_field_name(&pp, "details");
1860 ff_amf_write_string(&pp, filename);
1861 ff_amf_write_field_name(&pp, "clientid");
1862 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1863 ff_amf_write_string(&pp, statusmsg);
1864 ff_amf_write_object_end(&pp);
1867 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1869 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1870 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1874 ff_amf_write_string(&pp, "_result");
1875 ff_amf_write_number(&pp, seqnum);
1876 ff_amf_write_null(&pp);
1877 if (!strcmp(command, "createStream")) {
1879 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1880 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1881 ff_amf_write_number(&pp, rt->nb_streamid);
1882 /* By now we don't control which streams are removed in
1883 * deleteStream. There is no stream creation control
1884 * if a client creates more than 2^32 - 2 streams. */
1887 spkt.data_size = pp - spkt.data;
1888 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1890 ff_rtmp_packet_destroy(&spkt);
1894 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1896 RTMPContext *rt = s->priv_data;
1897 char *tracked_method = NULL;
1900 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1903 if (!tracked_method) {
1904 /* Ignore this reply when the current method is not tracked. */
1908 if (!memcmp(tracked_method, "connect", 7)) {
1909 if (!rt->is_input) {
1910 if ((ret = gen_release_stream(s, rt)) < 0)
1913 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1916 if ((ret = gen_server_bw(s, rt)) < 0)
1920 if ((ret = gen_create_stream(s, rt)) < 0)
1924 /* Send the FCSubscribe command when the name of live
1925 * stream is defined by the user or if it's a live stream. */
1926 if (rt->subscribe) {
1927 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1929 } else if (rt->live == -1) {
1930 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1934 } else if (!memcmp(tracked_method, "createStream", 12)) {
1935 //extract a number from the result
1936 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1937 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1939 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1942 if (!rt->is_input) {
1943 if ((ret = gen_publish(s, rt)) < 0)
1946 if ((ret = gen_play(s, rt)) < 0)
1948 if ((ret = gen_buffer_time(s, rt)) < 0)
1954 av_free(tracked_method);
1958 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1960 RTMPContext *rt = s->priv_data;
1961 const uint8_t *data_end = pkt->data + pkt->data_size;
1962 const uint8_t *ptr = pkt->data + 11;
1963 uint8_t tmpstr[256];
1966 for (i = 0; i < 2; i++) {
1967 t = ff_amf_tag_size(ptr, data_end);
1973 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1974 if (!t && !strcmp(tmpstr, "error")) {
1975 if (!ff_amf_get_field_value(ptr, data_end,
1976 "description", tmpstr, sizeof(tmpstr)))
1977 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1981 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1982 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1983 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1984 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1985 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1986 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
1991 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1993 RTMPContext *rt = s->priv_data;
1996 //TODO: check for the messages sent for wrong state?
1997 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1998 if ((ret = handle_invoke_error(s, pkt)) < 0)
2000 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
2001 if ((ret = handle_invoke_result(s, pkt)) < 0)
2003 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
2004 if ((ret = handle_invoke_status(s, pkt)) < 0)
2006 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
2007 if ((ret = gen_check_bw(s, rt)) < 0)
2009 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
2010 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
2011 !memcmp(pkt->data, "\002\000\007publish", 10) ||
2012 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
2013 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
2014 if ((ret = send_invoke_response(s, pkt)) < 0)
2021 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2022 RTMPContext *rt = s->priv_data;
2023 const uint8_t *p = NULL;
2025 uint8_t commandbuffer[64];
2026 char statusmsg[128];
2032 const uint8_t *datatowrite;
2033 unsigned datatowritelength;
2036 bytestream2_init(&gbc, p, pkt->data_size);
2037 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2039 return AVERROR_INVALIDDATA;
2040 if (!strcmp(commandbuffer, "@setDataFrame")) {
2041 datatowrite = gbc.buffer;
2042 datatowritelength = bytestream2_get_bytes_left(&gbc);
2043 if (ff_amf_read_string(&gbc, statusmsg,
2044 sizeof(statusmsg), &stringlen))
2045 return AVERROR_INVALIDDATA;
2046 if (strcmp(statusmsg, "onMetaData")) {
2047 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2052 /* Provide ECMAArray to flv */
2053 ts = pkt->timestamp;
2055 // generate packet header and put data into buffer for FLV demuxer
2056 if (rt->flv_off < rt->flv_size) {
2057 old_flv_size = rt->flv_size;
2058 rt->flv_size += datatowritelength + 15;
2061 rt->flv_size = datatowritelength + 15;
2065 cp = av_realloc(rt->flv_data, rt->flv_size);
2067 return AVERROR(ENOMEM);
2069 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2070 bytestream2_skip_p(&pbc, old_flv_size);
2071 bytestream2_put_byte(&pbc, pkt->type);
2072 bytestream2_put_be24(&pbc, datatowritelength);
2073 bytestream2_put_be24(&pbc, ts);
2074 bytestream2_put_byte(&pbc, ts >> 24);
2075 bytestream2_put_be24(&pbc, 0);
2076 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2077 bytestream2_put_be32(&pbc, 0);
2083 * Parse received packet and possibly perform some action depending on
2084 * the packet contents.
2085 * @return 0 for no errors, negative values for serious errors which prevent
2086 * further communications, positive values for uncritical errors
2088 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2093 ff_rtmp_packet_dump(s, pkt);
2096 switch (pkt->type) {
2097 case RTMP_PT_BYTES_READ:
2098 av_dlog(s, "received bytes read report\n");
2100 case RTMP_PT_CHUNK_SIZE:
2101 if ((ret = handle_chunk_size(s, pkt)) < 0)
2105 if ((ret = handle_ping(s, pkt)) < 0)
2108 case RTMP_PT_CLIENT_BW:
2109 if ((ret = handle_client_bw(s, pkt)) < 0)
2112 case RTMP_PT_SERVER_BW:
2113 if ((ret = handle_server_bw(s, pkt)) < 0)
2116 case RTMP_PT_INVOKE:
2117 if ((ret = handle_invoke(s, pkt)) < 0)
2122 case RTMP_PT_METADATA:
2123 case RTMP_PT_NOTIFY:
2124 /* Audio, Video and Metadata packets are parsed in get_packet() */
2127 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2134 * Interact with the server by receiving and sending RTMP packets until
2135 * there is some significant data (media data or expected status notification).
2137 * @param s reading context
2138 * @param for_header non-zero value tells function to work until it
2139 * gets notification from the server that playing has been started,
2140 * otherwise function will work until some media data is received (or
2142 * @return 0 for successful operation, negative value in case of error
2144 static int get_packet(URLContext *s, int for_header)
2146 RTMPContext *rt = s->priv_data;
2149 const uint8_t *next;
2151 uint32_t ts, cts, pts=0;
2153 if (rt->state == STATE_STOPPED)
2157 RTMPPacket rpkt = { 0 };
2158 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2159 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2161 return AVERROR(EAGAIN);
2163 return AVERROR(EIO);
2166 rt->bytes_read += ret;
2167 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2168 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2169 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2171 rt->last_bytes_read = rt->bytes_read;
2174 ret = rtmp_parse_result(s, rt, &rpkt);
2176 // At this point we must check if we are in the seek state and continue
2177 // with the next packet. handle_invoke will get us out of this state
2178 // when the right message is encountered
2179 if (rt->state == STATE_SEEKING) {
2180 ff_rtmp_packet_destroy(&rpkt);
2181 // We continue, let the natural flow of things happen:
2182 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2186 if (ret < 0) {//serious error in current packet
2187 ff_rtmp_packet_destroy(&rpkt);
2190 if (rt->do_reconnect && for_header) {
2191 ff_rtmp_packet_destroy(&rpkt);
2194 if (rt->state == STATE_STOPPED) {
2195 ff_rtmp_packet_destroy(&rpkt);
2198 if (for_header && (rt->state == STATE_PLAYING ||
2199 rt->state == STATE_PUBLISHING ||
2200 rt->state == STATE_RECEIVING)) {
2201 ff_rtmp_packet_destroy(&rpkt);
2204 if (!rpkt.data_size || !rt->is_input) {
2205 ff_rtmp_packet_destroy(&rpkt);
2208 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2209 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2210 ts = rpkt.timestamp;
2212 // generate packet header and put data into buffer for FLV demuxer
2214 rt->flv_size = rpkt.data_size + 15;
2215 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2216 bytestream_put_byte(&p, rpkt.type);
2217 bytestream_put_be24(&p, rpkt.data_size);
2218 bytestream_put_be24(&p, ts);
2219 bytestream_put_byte(&p, ts >> 24);
2220 bytestream_put_be24(&p, 0);
2221 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2222 bytestream_put_be32(&p, 0);
2223 ff_rtmp_packet_destroy(&rpkt);
2225 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2226 ret = handle_notify(s, &rpkt);
2227 ff_rtmp_packet_destroy(&rpkt);
2229 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2233 } else if (rpkt.type == RTMP_PT_METADATA) {
2234 // we got raw FLV data, make it available for FLV demuxer
2236 rt->flv_size = rpkt.data_size;
2237 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2238 /* rewrite timestamps */
2240 ts = rpkt.timestamp;
2241 while (next - rpkt.data < rpkt.data_size - 11) {
2243 data_size = bytestream_get_be24(&next);
2245 cts = bytestream_get_be24(&next);
2246 cts |= bytestream_get_byte(&next) << 24;
2251 bytestream_put_be24(&p, ts);
2252 bytestream_put_byte(&p, ts >> 24);
2253 next += data_size + 3 + 4;
2255 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2256 ff_rtmp_packet_destroy(&rpkt);
2259 ff_rtmp_packet_destroy(&rpkt);
2263 static int rtmp_close(URLContext *h)
2265 RTMPContext *rt = h->priv_data;
2268 if (!rt->is_input) {
2269 rt->flv_data = NULL;
2270 if (rt->out_pkt.data_size)
2271 ff_rtmp_packet_destroy(&rt->out_pkt);
2272 if (rt->state > STATE_FCPUBLISH)
2273 ret = gen_fcunpublish_stream(h, rt);
2275 if (rt->state > STATE_HANDSHAKED)
2276 ret = gen_delete_stream(h, rt);
2278 free_tracked_methods(rt);
2279 av_freep(&rt->flv_data);
2280 ffurl_close(rt->stream);
2285 * Open RTMP connection and verify that the stream can be played.
2287 * URL syntax: rtmp://server[:port][/app][/playpath]
2288 * where 'app' is first one or two directories in the path
2289 * (e.g. /ondemand/, /flash/live/, etc.)
2290 * and 'playpath' is a file name (the rest of the path,
2291 * may be prefixed with "mp4:")
2293 static int rtmp_open(URLContext *s, const char *uri, int flags)
2295 RTMPContext *rt = s->priv_data;
2296 char proto[8], hostname[256], path[1024], auth[100], *fname;
2300 AVDictionary *opts = NULL;
2303 if (rt->listen_timeout > 0)
2306 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2308 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2309 hostname, sizeof(hostname), &port,
2310 path, sizeof(path), s->filename);
2313 char *ptr = strchr(auth, ':');
2316 av_strlcpy(rt->username, auth, sizeof(rt->username));
2317 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2321 if (rt->listen && strcmp(proto, "rtmp")) {
2322 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2324 return AVERROR(EINVAL);
2326 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2327 if (!strcmp(proto, "rtmpts"))
2328 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2330 /* open the http tunneling connection */
2331 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2332 } else if (!strcmp(proto, "rtmps")) {
2333 /* open the tls connection */
2335 port = RTMPS_DEFAULT_PORT;
2336 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2337 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2338 if (!strcmp(proto, "rtmpte"))
2339 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2341 /* open the encrypted connection */
2342 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2345 /* open the tcp connection */
2347 port = RTMP_DEFAULT_PORT;
2349 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2350 "?listen&listen_timeout=%d",
2351 rt->listen_timeout * 1000);
2353 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2357 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2358 &s->interrupt_callback, &opts)) < 0) {
2359 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2363 if (rt->swfverify) {
2364 if ((ret = rtmp_calc_swfhash(s)) < 0)
2368 rt->state = STATE_START;
2369 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2371 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2374 rt->out_chunk_size = 128;
2375 rt->in_chunk_size = 128; // Probably overwritten later
2376 rt->state = STATE_HANDSHAKED;
2378 // Keep the application name when it has been defined by the user.
2381 rt->app = av_malloc(APP_MAX_LENGTH);
2383 ret = AVERROR(ENOMEM);
2387 //extract "app" part from path
2388 if (!strncmp(path, "/ondemand/", 10)) {
2390 memcpy(rt->app, "ondemand", 9);
2392 char *next = *path ? path + 1 : path;
2393 char *p = strchr(next, '/');
2398 // make sure we do not mismatch a playpath for an application instance
2399 char *c = strchr(p + 1, ':');
2400 fname = strchr(p + 1, '/');
2401 if (!fname || (c && c < fname)) {
2403 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2406 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2412 // The name of application has been defined by the user, override it.
2413 if (strlen(old_app) >= APP_MAX_LENGTH) {
2414 ret = AVERROR(EINVAL);
2421 if (!rt->playpath) {
2422 int len = strlen(fname);
2424 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2425 if (!rt->playpath) {
2426 ret = AVERROR(ENOMEM);
2430 if (!strchr(fname, ':') && len >= 4 &&
2431 (!strcmp(fname + len - 4, ".f4v") ||
2432 !strcmp(fname + len - 4, ".mp4"))) {
2433 memcpy(rt->playpath, "mp4:", 5);
2434 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2435 fname[len - 4] = '\0';
2437 rt->playpath[0] = 0;
2439 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2443 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2445 ret = AVERROR(ENOMEM);
2448 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2449 port, "/%s", rt->app);
2452 if (!rt->flashver) {
2453 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2454 if (!rt->flashver) {
2455 ret = AVERROR(ENOMEM);
2459 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2460 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2461 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2463 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2464 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2468 rt->client_report_size = 1048576;
2470 rt->last_bytes_read = 0;
2471 rt->server_bw = 2500000;
2473 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2474 proto, path, rt->app, rt->playpath);
2476 if ((ret = gen_connect(s, rt)) < 0)
2479 if (read_connect(s, s->priv_data) < 0)
2485 ret = get_packet(s, 1);
2486 } while (ret == EAGAIN);
2490 if (rt->do_reconnect) {
2491 ffurl_close(rt->stream);
2493 rt->do_reconnect = 0;
2495 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2496 free_tracked_methods(rt);
2501 // generate FLV header for demuxer
2503 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2505 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2508 rt->flv_data = NULL;
2510 rt->skip_bytes = 13;
2513 s->max_packet_size = rt->stream->max_packet_size;
2518 av_dict_free(&opts);
2523 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2525 RTMPContext *rt = s->priv_data;
2526 int orig_size = size;
2530 int data_left = rt->flv_size - rt->flv_off;
2532 if (data_left >= size) {
2533 memcpy(buf, rt->flv_data + rt->flv_off, size);
2534 rt->flv_off += size;
2537 if (data_left > 0) {
2538 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2541 rt->flv_off = rt->flv_size;
2544 if ((ret = get_packet(s, 0)) < 0)
2550 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2553 RTMPContext *rt = s->priv_data;
2555 av_log(s, AV_LOG_DEBUG,
2556 "Seek on stream index %d at timestamp %lld with flags %08x\n",
2557 stream_index, timestamp, flags);
2558 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2559 av_log(s, AV_LOG_ERROR,
2560 "Unable to send seek command on stream index %d at timestamp %lld with flags %08x\n",
2561 stream_index, timestamp, flags);
2564 rt->flv_off = rt->flv_size;
2565 rt->state = STATE_SEEKING;
2569 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2571 RTMPContext *rt = s->priv_data;
2572 int size_temp = size;
2573 int pktsize, pkttype;
2575 const uint8_t *buf_temp = buf;
2580 if (rt->skip_bytes) {
2581 int skip = FFMIN(rt->skip_bytes, size_temp);
2584 rt->skip_bytes -= skip;
2588 if (rt->flv_header_bytes < 11) {
2589 const uint8_t *header = rt->flv_header;
2590 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2591 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2592 rt->flv_header_bytes += copy;
2594 if (rt->flv_header_bytes < 11)
2597 pkttype = bytestream_get_byte(&header);
2598 pktsize = bytestream_get_be24(&header);
2599 ts = bytestream_get_be24(&header);
2600 ts |= bytestream_get_byte(&header) << 24;
2601 bytestream_get_be24(&header);
2602 rt->flv_size = pktsize;
2604 //force 12bytes header
2605 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2606 pkttype == RTMP_PT_NOTIFY) {
2607 if (pkttype == RTMP_PT_NOTIFY)
2609 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2612 //this can be a big packet, it's better to send it right here
2613 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2614 pkttype, ts, pktsize)) < 0)
2617 rt->out_pkt.extra = rt->main_channel_id;
2618 rt->flv_data = rt->out_pkt.data;
2620 if (pkttype == RTMP_PT_NOTIFY)
2621 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2624 if (rt->flv_size - rt->flv_off > size_temp) {
2625 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2626 rt->flv_off += size_temp;
2629 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2630 size_temp -= rt->flv_size - rt->flv_off;
2631 rt->flv_off += rt->flv_size - rt->flv_off;
2634 if (rt->flv_off == rt->flv_size) {
2637 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2641 rt->flv_header_bytes = 0;
2642 rt->flv_nb_packets++;
2644 } while (buf_temp - buf < size);
2646 if (rt->flv_nb_packets < rt->flush_interval)
2648 rt->flv_nb_packets = 0;
2650 /* set stream into nonblocking mode */
2651 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2653 /* try to read one byte from the stream */
2654 ret = ffurl_read(rt->stream, &c, 1);
2656 /* switch the stream back into blocking mode */
2657 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2659 if (ret == AVERROR(EAGAIN)) {
2660 /* no incoming data to handle */
2662 } else if (ret < 0) {
2664 } else if (ret == 1) {
2665 RTMPPacket rpkt = { 0 };
2667 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2669 rt->prev_pkt[0], c)) <= 0)
2672 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2675 ff_rtmp_packet_destroy(&rpkt);
2681 #define OFFSET(x) offsetof(RTMPContext, x)
2682 #define DEC AV_OPT_FLAG_DECODING_PARAM
2683 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2685 static const AVOption rtmp_options[] = {
2686 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2687 {"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},
2688 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2689 {"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},
2690 {"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},
2691 {"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"},
2692 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2693 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2694 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2695 {"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},
2696 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2697 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2698 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2699 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2700 {"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},
2701 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2702 {"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},
2703 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2704 {"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" },
2708 #define RTMP_PROTOCOL(flavor) \
2709 static const AVClass flavor##_class = { \
2710 .class_name = #flavor, \
2711 .item_name = av_default_item_name, \
2712 .option = rtmp_options, \
2713 .version = LIBAVUTIL_VERSION_INT, \
2716 URLProtocol ff_##flavor##_protocol = { \
2718 .url_open = rtmp_open, \
2719 .url_read = rtmp_read, \
2720 .url_read_seek = rtmp_seek, \
2721 .url_write = rtmp_write, \
2722 .url_close = rtmp_close, \
2723 .priv_data_size = sizeof(RTMPContext), \
2724 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2725 .priv_data_class= &flavor##_class, \
2730 RTMP_PROTOCOL(rtmpe)
2731 RTMP_PROTOCOL(rtmps)
2732 RTMP_PROTOCOL(rtmpt)
2733 RTMP_PROTOCOL(rtmpte)
2734 RTMP_PROTOCOL(rtmpts)