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->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->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.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.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.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.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.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.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 %"PRId64"\n",
717 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
720 pkt.extra = rt->main_channel_id;
723 ff_amf_write_string(&p, "seek");
724 ff_amf_write_number(&p, 0); //no tracking back responses
725 ff_amf_write_null(&p); //as usual, the first null param
726 ff_amf_write_number(&p, timestamp); //where we want to jump
728 return rtmp_send_packet(rt, &pkt, 1);
732 * Generate 'publish' call and send it to the server.
734 static int gen_publish(URLContext *s, RTMPContext *rt)
740 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
742 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
743 0, 30 + strlen(rt->playpath))) < 0)
746 pkt.extra = rt->main_channel_id;
749 ff_amf_write_string(&p, "publish");
750 ff_amf_write_number(&p, ++rt->nb_invokes);
751 ff_amf_write_null(&p);
752 ff_amf_write_string(&p, rt->playpath);
753 ff_amf_write_string(&p, "live");
755 return rtmp_send_packet(rt, &pkt, 1);
759 * Generate ping reply and send it to the server.
761 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
767 if (ppkt->size < 6) {
768 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
770 return AVERROR_INVALIDDATA;
773 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
774 ppkt->timestamp + 1, 6)) < 0)
778 bytestream_put_be16(&p, 7);
779 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
781 return rtmp_send_packet(rt, &pkt, 0);
785 * Generate SWF verification message and send it to the server.
787 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
793 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
794 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
799 bytestream_put_be16(&p, 27);
800 memcpy(p, rt->swfverification, 42);
802 return rtmp_send_packet(rt, &pkt, 0);
806 * Generate server bandwidth message and send it to the server.
808 static int gen_server_bw(URLContext *s, RTMPContext *rt)
814 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
819 bytestream_put_be32(&p, rt->server_bw);
821 return rtmp_send_packet(rt, &pkt, 0);
825 * Generate check bandwidth message and send it to the server.
827 static int gen_check_bw(URLContext *s, RTMPContext *rt)
833 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
838 ff_amf_write_string(&p, "_checkbw");
839 ff_amf_write_number(&p, ++rt->nb_invokes);
840 ff_amf_write_null(&p);
842 return rtmp_send_packet(rt, &pkt, 1);
846 * Generate report on bytes read so far and send it to the server.
848 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
854 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
859 bytestream_put_be32(&p, rt->bytes_read);
861 return rtmp_send_packet(rt, &pkt, 0);
864 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
865 const char *subscribe)
871 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
872 0, 27 + strlen(subscribe))) < 0)
876 ff_amf_write_string(&p, "FCSubscribe");
877 ff_amf_write_number(&p, ++rt->nb_invokes);
878 ff_amf_write_null(&p);
879 ff_amf_write_string(&p, subscribe);
881 return rtmp_send_packet(rt, &pkt, 1);
884 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
885 const uint8_t *key, int keylen, uint8_t *dst)
888 uint8_t hmac_buf[64+32] = {0};
891 sha = av_sha_alloc();
893 return AVERROR(ENOMEM);
896 memcpy(hmac_buf, key, keylen);
898 av_sha_init(sha, 256);
899 av_sha_update(sha,key, keylen);
900 av_sha_final(sha, hmac_buf);
902 for (i = 0; i < 64; i++)
903 hmac_buf[i] ^= HMAC_IPAD_VAL;
905 av_sha_init(sha, 256);
906 av_sha_update(sha, hmac_buf, 64);
908 av_sha_update(sha, src, len);
909 } else { //skip 32 bytes used for storing digest
910 av_sha_update(sha, src, gap);
911 av_sha_update(sha, src + gap + 32, len - gap - 32);
913 av_sha_final(sha, hmac_buf + 64);
915 for (i = 0; i < 64; i++)
916 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
917 av_sha_init(sha, 256);
918 av_sha_update(sha, hmac_buf, 64+32);
919 av_sha_final(sha, dst);
926 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
929 int i, digest_pos = 0;
931 for (i = 0; i < 4; i++)
932 digest_pos += buf[i + off];
933 digest_pos = digest_pos % mod_val + add_val;
939 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
940 * will be stored) into that packet.
942 * @param buf handshake data (1536 bytes)
943 * @param encrypted use an encrypted connection (RTMPE)
944 * @return offset to the digest inside input data
946 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
951 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
953 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
955 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
956 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
965 * Verify that the received server response has the expected digest value.
967 * @param buf handshake data received from the server (1536 bytes)
968 * @param off position to search digest offset from
969 * @return 0 if digest is valid, digest position otherwise
971 static int rtmp_validate_digest(uint8_t *buf, int off)
976 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
978 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
979 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
984 if (!memcmp(digest, buf + digest_pos, 32))
989 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
995 if (rt->swfhash_len != 32) {
996 av_log(s, AV_LOG_ERROR,
997 "Hash of the decompressed SWF file is not 32 bytes long.\n");
998 return AVERROR(EINVAL);
1001 p = &rt->swfverification[0];
1002 bytestream_put_byte(&p, 1);
1003 bytestream_put_byte(&p, 1);
1004 bytestream_put_be32(&p, rt->swfsize);
1005 bytestream_put_be32(&p, rt->swfsize);
1007 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1014 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1015 uint8_t **out_data, int64_t *out_size)
1017 z_stream zs = { 0 };
1022 zs.avail_in = in_size;
1023 zs.next_in = in_data;
1024 ret = inflateInit(&zs);
1026 return AVERROR_UNKNOWN;
1029 uint8_t tmp_buf[16384];
1031 zs.avail_out = sizeof(tmp_buf);
1032 zs.next_out = tmp_buf;
1034 ret = inflate(&zs, Z_NO_FLUSH);
1035 if (ret != Z_OK && ret != Z_STREAM_END) {
1036 ret = AVERROR_UNKNOWN;
1040 size = sizeof(tmp_buf) - zs.avail_out;
1041 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1042 ret = AVERROR(ENOMEM);
1047 memcpy(*out_data + *out_size, tmp_buf, size);
1049 } while (zs.avail_out == 0);
1057 static int rtmp_calc_swfhash(URLContext *s)
1059 RTMPContext *rt = s->priv_data;
1060 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1061 int64_t in_size, out_size;
1067 /* Get the SWF player file. */
1068 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1069 &s->interrupt_callback, NULL)) < 0) {
1070 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1074 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1079 if (!(in_data = av_malloc(in_size))) {
1080 ret = AVERROR(ENOMEM);
1084 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1088 ret = AVERROR_INVALIDDATA;
1092 if (!memcmp(in_data, "CWS", 3)) {
1093 /* Decompress the SWF player file using Zlib. */
1094 if (!(out_data = av_malloc(8))) {
1095 ret = AVERROR(ENOMEM);
1098 *in_data = 'F'; // magic stuff
1099 memcpy(out_data, in_data, 8);
1103 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1104 &out_data, &out_size)) < 0)
1107 av_log(s, AV_LOG_ERROR,
1108 "Zlib is required for decompressing the SWF player file.\n");
1109 ret = AVERROR(EINVAL);
1119 /* Compute the SHA256 hash of the SWF player file. */
1120 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1121 "Genuine Adobe Flash Player 001", 30,
1125 /* Set SWFVerification parameters. */
1126 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1127 rt->swfsize = swfsize;
1131 av_freep(&out_data);
1132 ffurl_close(stream);
1137 * Perform handshake with the server by means of exchanging pseudorandom data
1138 * signed with HMAC-SHA2 digest.
1140 * @return 0 if handshake succeeds, negative value otherwise
1142 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1145 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1146 3, // unencrypted data
1147 0, 0, 0, 0, // client uptime
1153 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1154 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1156 int server_pos, client_pos;
1157 uint8_t digest[32], signature[32];
1160 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1162 av_lfg_init(&rnd, 0xDEADC0DE);
1163 // generate handshake packet - 1536 bytes of pseudorandom data
1164 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1165 tosend[i] = av_lfg_get(&rnd) >> 24;
1167 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1168 /* When the client wants to use RTMPE, we have to change the command
1169 * byte to 0x06 which means to use encrypted data and we have to set
1170 * the flash version to at least 9.0.115.0. */
1177 /* Initialize the Diffie-Hellmann context and generate the public key
1178 * to send to the server. */
1179 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1183 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1187 if ((ret = ffurl_write(rt->stream, tosend,
1188 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1189 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1193 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1194 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1195 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1199 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1200 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1201 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1205 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1206 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1207 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1209 if (rt->is_input && serverdata[5] >= 3) {
1210 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1216 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1221 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1222 return AVERROR(EIO);
1226 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1227 * key are the last 32 bytes of the server handshake. */
1229 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1230 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1234 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1235 rtmp_server_key, sizeof(rtmp_server_key),
1240 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1241 0, digest, 32, signature);
1245 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1246 /* Compute the shared secret key sent by the server and initialize
1247 * the RC4 encryption. */
1248 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1249 tosend + 1, type)) < 0)
1252 /* Encrypt the signature received by the server. */
1253 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1256 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1257 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1258 return AVERROR(EIO);
1261 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1262 tosend[i] = av_lfg_get(&rnd) >> 24;
1263 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1264 rtmp_player_key, sizeof(rtmp_player_key),
1269 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1271 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1275 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1276 /* Encrypt the signature to be send to the server. */
1277 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1278 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1282 // write reply back to the server
1283 if ((ret = ffurl_write(rt->stream, tosend,
1284 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1287 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1288 /* Set RC4 keys for encryption and update the keystreams. */
1289 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1293 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1294 /* Compute the shared secret key sent by the server and initialize
1295 * the RC4 encryption. */
1296 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1297 tosend + 1, 1)) < 0)
1300 if (serverdata[0] == 9) {
1301 /* Encrypt the signature received by the server. */
1302 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1307 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1308 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1311 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1312 /* Set RC4 keys for encryption and update the keystreams. */
1313 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1321 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1322 uint32_t *second_int, char *arraydata,
1327 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1328 RTMP_HANDSHAKE_PACKET_SIZE);
1330 return AVERROR(EIO);
1331 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1332 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1333 " not following standard\n", (int)inoutsize);
1334 return AVERROR(EINVAL);
1337 *first_int = AV_RB32(arraydata);
1338 *second_int = AV_RB32(arraydata + 4);
1342 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1343 uint32_t second_int, char *arraydata, int size)
1347 AV_WB32(arraydata, first_int);
1348 AV_WB32(arraydata + 4, first_int);
1349 inoutsize = ffurl_write(rt->stream, arraydata,
1350 RTMP_HANDSHAKE_PACKET_SIZE);
1351 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1352 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1353 return AVERROR(EIO);
1360 * rtmp handshake server side
1362 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1364 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1366 uint32_t hs_my_epoch;
1367 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1368 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1375 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1376 if (inoutsize <= 0) {
1377 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1378 return AVERROR(EIO);
1381 if (buffer[0] != 3) {
1382 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1383 return AVERROR(EIO);
1385 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1386 av_log(s, AV_LOG_ERROR,
1387 "Unable to write answer - RTMP S0\n");
1388 return AVERROR(EIO);
1391 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1392 RTMP_HANDSHAKE_PACKET_SIZE);
1394 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1398 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1400 /* By now same epoch will be sent */
1401 hs_my_epoch = hs_epoch;
1402 /* Generate random */
1403 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1405 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1407 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1408 RTMP_HANDSHAKE_PACKET_SIZE);
1410 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1414 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1415 RTMP_HANDSHAKE_PACKET_SIZE);
1417 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1421 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1422 RTMP_HANDSHAKE_PACKET_SIZE);
1424 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1427 if (temp != hs_my_epoch)
1428 av_log(s, AV_LOG_WARNING,
1429 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1430 if (memcmp(buffer + 8, hs_s1 + 8,
1431 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1432 av_log(s, AV_LOG_WARNING,
1433 "Erroneous C2 Message random does not match up\n");
1438 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1440 RTMPContext *rt = s->priv_data;
1443 if (pkt->size < 4) {
1444 av_log(s, AV_LOG_ERROR,
1445 "Too short chunk size change packet (%d)\n",
1447 return AVERROR_INVALIDDATA;
1450 if (!rt->is_input) {
1451 /* Send the same chunk size change packet back to the server,
1452 * setting the outgoing chunk size to the same as the incoming one. */
1453 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1454 rt->prev_pkt[1])) < 0)
1456 rt->out_chunk_size = AV_RB32(pkt->data);
1459 rt->in_chunk_size = AV_RB32(pkt->data);
1460 if (rt->in_chunk_size <= 0) {
1461 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1463 return AVERROR_INVALIDDATA;
1465 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1471 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1473 RTMPContext *rt = s->priv_data;
1476 if (pkt->size < 2) {
1477 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1479 return AVERROR_INVALIDDATA;
1482 t = AV_RB16(pkt->data);
1484 if ((ret = gen_pong(s, rt, pkt)) < 0)
1486 } else if (t == 26) {
1488 if ((ret = gen_swf_verification(s, rt)) < 0)
1491 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1498 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1500 RTMPContext *rt = s->priv_data;
1502 if (pkt->size < 4) {
1503 av_log(s, AV_LOG_ERROR,
1504 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1506 return AVERROR_INVALIDDATA;
1509 rt->client_report_size = AV_RB32(pkt->data);
1510 if (rt->client_report_size <= 0) {
1511 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1512 rt->client_report_size);
1513 return AVERROR_INVALIDDATA;
1516 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1517 rt->client_report_size >>= 1;
1522 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1524 RTMPContext *rt = s->priv_data;
1526 if (pkt->size < 4) {
1527 av_log(s, AV_LOG_ERROR,
1528 "Too short server bandwidth report packet (%d)\n",
1530 return AVERROR_INVALIDDATA;
1533 rt->server_bw = AV_RB32(pkt->data);
1534 if (rt->server_bw <= 0) {
1535 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1537 return AVERROR_INVALIDDATA;
1539 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1544 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1545 const char *opaque, const char *challenge)
1548 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1549 struct AVMD5 *md5 = av_md5_alloc();
1551 return AVERROR(ENOMEM);
1553 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1556 av_md5_update(md5, user, strlen(user));
1557 av_md5_update(md5, salt, strlen(salt));
1558 av_md5_update(md5, rt->password, strlen(rt->password));
1559 av_md5_final(md5, hash);
1560 av_base64_encode(hashstr, sizeof(hashstr), hash,
1563 av_md5_update(md5, hashstr, strlen(hashstr));
1565 av_md5_update(md5, opaque, strlen(opaque));
1567 av_md5_update(md5, challenge, strlen(challenge));
1568 av_md5_update(md5, challenge2, strlen(challenge2));
1569 av_md5_final(md5, hash);
1570 av_base64_encode(hashstr, sizeof(hashstr), hash,
1572 snprintf(rt->auth_params, sizeof(rt->auth_params),
1573 "?authmod=%s&user=%s&challenge=%s&response=%s",
1574 "adobe", user, challenge2, hashstr);
1576 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1577 "&opaque=%s", opaque);
1583 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1586 char hashstr1[33], hashstr2[33];
1587 const char *realm = "live";
1588 const char *method = "publish";
1589 const char *qop = "auth";
1590 const char *nc = "00000001";
1592 struct AVMD5 *md5 = av_md5_alloc();
1594 return AVERROR(ENOMEM);
1596 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1599 av_md5_update(md5, user, strlen(user));
1600 av_md5_update(md5, ":", 1);
1601 av_md5_update(md5, realm, strlen(realm));
1602 av_md5_update(md5, ":", 1);
1603 av_md5_update(md5, rt->password, strlen(rt->password));
1604 av_md5_final(md5, hash);
1605 ff_data_to_hex(hashstr1, hash, 16, 1);
1606 hashstr1[32] = '\0';
1609 av_md5_update(md5, method, strlen(method));
1610 av_md5_update(md5, ":/", 2);
1611 av_md5_update(md5, rt->app, strlen(rt->app));
1612 av_md5_final(md5, hash);
1613 ff_data_to_hex(hashstr2, hash, 16, 1);
1614 hashstr2[32] = '\0';
1617 av_md5_update(md5, hashstr1, strlen(hashstr1));
1618 av_md5_update(md5, ":", 1);
1620 av_md5_update(md5, nonce, strlen(nonce));
1621 av_md5_update(md5, ":", 1);
1622 av_md5_update(md5, nc, strlen(nc));
1623 av_md5_update(md5, ":", 1);
1624 av_md5_update(md5, cnonce, strlen(cnonce));
1625 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, qop, strlen(qop));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, hashstr2, strlen(hashstr2));
1629 av_md5_final(md5, hash);
1630 ff_data_to_hex(hashstr1, hash, 16, 1);
1632 snprintf(rt->auth_params, sizeof(rt->auth_params),
1633 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1634 "llnw", user, nonce, cnonce, nc, hashstr1);
1640 static int handle_connect_error(URLContext *s, const char *desc)
1642 RTMPContext *rt = s->priv_data;
1643 char buf[300], *ptr, authmod[15];
1645 const char *user = "", *salt = "", *opaque = NULL,
1646 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1648 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1649 !(cptr = strstr(desc, "authmod=llnw"))) {
1650 av_log(s, AV_LOG_ERROR,
1651 "Unknown connect error (unsupported authentication method?)\n");
1652 return AVERROR_UNKNOWN;
1654 cptr += strlen("authmod=");
1655 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1656 authmod[i++] = *cptr++;
1659 if (!rt->username[0] || !rt->password[0]) {
1660 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1661 return AVERROR_UNKNOWN;
1664 if (strstr(desc, "?reason=authfailed")) {
1665 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1666 return AVERROR_UNKNOWN;
1667 } else if (strstr(desc, "?reason=nosuchuser")) {
1668 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1669 return AVERROR_UNKNOWN;
1672 if (rt->auth_tried) {
1673 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1674 return AVERROR_UNKNOWN;
1677 rt->auth_params[0] = '\0';
1679 if (strstr(desc, "code=403 need auth")) {
1680 snprintf(rt->auth_params, sizeof(rt->auth_params),
1681 "?authmod=%s&user=%s", authmod, rt->username);
1685 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1686 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1687 return AVERROR_UNKNOWN;
1690 av_strlcpy(buf, cptr + 1, sizeof(buf));
1694 char *next = strchr(ptr, '&');
1695 char *value = strchr(ptr, '=');
1700 if (!strcmp(ptr, "user")) {
1702 } else if (!strcmp(ptr, "salt")) {
1704 } else if (!strcmp(ptr, "opaque")) {
1706 } else if (!strcmp(ptr, "challenge")) {
1708 } else if (!strcmp(ptr, "nonce")) {
1714 if (!strcmp(authmod, "adobe")) {
1715 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1718 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1726 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1728 RTMPContext *rt = s->priv_data;
1729 const uint8_t *data_end = pkt->data + pkt->size;
1730 char *tracked_method = NULL;
1731 int level = AV_LOG_ERROR;
1732 uint8_t tmpstr[256];
1735 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1738 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1739 "description", tmpstr, sizeof(tmpstr))) {
1740 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1741 !strcmp(tracked_method, "releaseStream") ||
1742 !strcmp(tracked_method, "FCSubscribe") ||
1743 !strcmp(tracked_method, "FCPublish"))) {
1744 /* Gracefully ignore Adobe-specific historical artifact errors. */
1745 level = AV_LOG_WARNING;
1747 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1748 ret = handle_connect_error(s, tmpstr);
1750 rt->do_reconnect = 1;
1751 level = AV_LOG_VERBOSE;
1754 ret = AVERROR_UNKNOWN;
1755 av_log(s, level, "Server error: %s\n", tmpstr);
1758 av_free(tracked_method);
1762 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1764 RTMPContext *rt = s->priv_data;
1768 char statusmsg[128];
1771 const uint8_t *p = pkt->data;
1773 RTMPPacket spkt = { 0 };
1777 bytestream2_init(&gbc, p, pkt->size);
1778 if (ff_amf_read_string(&gbc, command, sizeof(command),
1780 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1781 return AVERROR_INVALIDDATA;
1784 ret = ff_amf_read_number(&gbc, &seqnum);
1787 ret = ff_amf_read_null(&gbc);
1790 if (!strcmp(command, "FCPublish") ||
1791 !strcmp(command, "publish")) {
1792 ret = ff_amf_read_string(&gbc, filename,
1793 sizeof(filename), &stringlen);
1796 pchar = strrchr(s->filename, '/');
1798 av_log(s, AV_LOG_WARNING,
1799 "Unable to find / in url %s, bad format\n",
1801 pchar = s->filename;
1804 if (strcmp(pchar, filename))
1805 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1806 " %s\n", filename, pchar);
1808 rt->state = STATE_RECEIVING;
1811 if (!strcmp(command, "FCPublish")) {
1812 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1814 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1815 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1819 ff_amf_write_string(&pp, "onFCPublish");
1820 } else if (!strcmp(command, "publish")) {
1822 // Send Stream Begin 1
1823 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1824 RTMP_PT_PING, 0, 6)) < 0) {
1825 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1829 bytestream2_init_writer(&pbc, pp, spkt.size);
1830 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1831 bytestream2_put_be32(&pbc, rt->nb_streamid);
1832 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1834 ff_rtmp_packet_destroy(&spkt);
1838 // Send onStatus(NetStream.Publish.Start)
1839 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1841 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1842 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1845 spkt.extra = pkt->extra;
1847 ff_amf_write_string(&pp, "onStatus");
1848 ff_amf_write_number(&pp, 0);
1849 ff_amf_write_null(&pp);
1851 ff_amf_write_object_start(&pp);
1852 ff_amf_write_field_name(&pp, "level");
1853 ff_amf_write_string(&pp, "status");
1854 ff_amf_write_field_name(&pp, "code");
1855 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1856 ff_amf_write_field_name(&pp, "description");
1857 snprintf(statusmsg, sizeof(statusmsg),
1858 "%s is now published", filename);
1859 ff_amf_write_string(&pp, statusmsg);
1860 ff_amf_write_field_name(&pp, "details");
1861 ff_amf_write_string(&pp, filename);
1862 ff_amf_write_field_name(&pp, "clientid");
1863 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1864 ff_amf_write_string(&pp, statusmsg);
1865 ff_amf_write_object_end(&pp);
1868 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1870 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1871 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1875 ff_amf_write_string(&pp, "_result");
1876 ff_amf_write_number(&pp, seqnum);
1877 ff_amf_write_null(&pp);
1878 if (!strcmp(command, "createStream")) {
1880 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1881 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1882 ff_amf_write_number(&pp, rt->nb_streamid);
1883 /* By now we don't control which streams are removed in
1884 * deleteStream. There is no stream creation control
1885 * if a client creates more than 2^32 - 2 streams. */
1888 spkt.size = pp - spkt.data;
1889 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1891 ff_rtmp_packet_destroy(&spkt);
1895 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1897 RTMPContext *rt = s->priv_data;
1898 char *tracked_method = NULL;
1901 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1904 if (!tracked_method) {
1905 /* Ignore this reply when the current method is not tracked. */
1909 if (!strcmp(tracked_method, "connect")) {
1910 if (!rt->is_input) {
1911 if ((ret = gen_release_stream(s, rt)) < 0)
1914 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1917 if ((ret = gen_server_bw(s, rt)) < 0)
1921 if ((ret = gen_create_stream(s, rt)) < 0)
1925 /* Send the FCSubscribe command when the name of live
1926 * stream is defined by the user or if it's a live stream. */
1927 if (rt->subscribe) {
1928 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1930 } else if (rt->live == -1) {
1931 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1935 } else if (!strcmp(tracked_method, "createStream")) {
1936 //extract a number from the result
1937 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1938 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1940 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1943 if (!rt->is_input) {
1944 if ((ret = gen_publish(s, rt)) < 0)
1947 if ((ret = gen_play(s, rt)) < 0)
1949 if ((ret = gen_buffer_time(s, rt)) < 0)
1955 av_free(tracked_method);
1959 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1961 RTMPContext *rt = s->priv_data;
1962 const uint8_t *data_end = pkt->data + pkt->size;
1963 const uint8_t *ptr = pkt->data + 11;
1964 uint8_t tmpstr[256];
1967 for (i = 0; i < 2; i++) {
1968 t = ff_amf_tag_size(ptr, data_end);
1974 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1975 if (!t && !strcmp(tmpstr, "error")) {
1976 if (!ff_amf_get_field_value(ptr, data_end,
1977 "description", tmpstr, sizeof(tmpstr)))
1978 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1982 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1983 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1984 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1985 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1986 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1987 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
1992 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1994 RTMPContext *rt = s->priv_data;
1997 //TODO: check for the messages sent for wrong state?
1998 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
1999 if ((ret = handle_invoke_error(s, pkt)) < 0)
2001 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2002 if ((ret = handle_invoke_result(s, pkt)) < 0)
2004 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2005 if ((ret = handle_invoke_status(s, pkt)) < 0)
2007 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2008 if ((ret = gen_check_bw(s, rt)) < 0)
2010 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2011 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2012 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2013 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2014 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2015 if ((ret = send_invoke_response(s, pkt)) < 0)
2022 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2023 RTMPContext *rt = s->priv_data;
2024 const uint8_t *p = NULL;
2026 uint8_t commandbuffer[64];
2027 char statusmsg[128];
2033 const uint8_t *datatowrite;
2034 unsigned datatowritelength;
2037 bytestream2_init(&gbc, p, pkt->size);
2038 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2040 return AVERROR_INVALIDDATA;
2041 if (!strcmp(commandbuffer, "@setDataFrame")) {
2042 datatowrite = gbc.buffer;
2043 datatowritelength = bytestream2_get_bytes_left(&gbc);
2044 if (ff_amf_read_string(&gbc, statusmsg,
2045 sizeof(statusmsg), &stringlen))
2046 return AVERROR_INVALIDDATA;
2047 if (strcmp(statusmsg, "onMetaData")) {
2048 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2053 /* Provide ECMAArray to flv */
2054 ts = pkt->timestamp;
2056 // generate packet header and put data into buffer for FLV demuxer
2057 if (rt->flv_off < rt->flv_size) {
2058 old_flv_size = rt->flv_size;
2059 rt->flv_size += datatowritelength + 15;
2062 rt->flv_size = datatowritelength + 15;
2066 cp = av_realloc(rt->flv_data, rt->flv_size);
2068 return AVERROR(ENOMEM);
2070 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2071 bytestream2_skip_p(&pbc, old_flv_size);
2072 bytestream2_put_byte(&pbc, pkt->type);
2073 bytestream2_put_be24(&pbc, datatowritelength);
2074 bytestream2_put_be24(&pbc, ts);
2075 bytestream2_put_byte(&pbc, ts >> 24);
2076 bytestream2_put_be24(&pbc, 0);
2077 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2078 bytestream2_put_be32(&pbc, 0);
2084 * Parse received packet and possibly perform some action depending on
2085 * the packet contents.
2086 * @return 0 for no errors, negative values for serious errors which prevent
2087 * further communications, positive values for uncritical errors
2089 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2094 ff_rtmp_packet_dump(s, pkt);
2097 switch (pkt->type) {
2098 case RTMP_PT_BYTES_READ:
2099 av_dlog(s, "received bytes read report\n");
2101 case RTMP_PT_CHUNK_SIZE:
2102 if ((ret = handle_chunk_size(s, pkt)) < 0)
2106 if ((ret = handle_ping(s, pkt)) < 0)
2109 case RTMP_PT_CLIENT_BW:
2110 if ((ret = handle_client_bw(s, pkt)) < 0)
2113 case RTMP_PT_SERVER_BW:
2114 if ((ret = handle_server_bw(s, pkt)) < 0)
2117 case RTMP_PT_INVOKE:
2118 if ((ret = handle_invoke(s, pkt)) < 0)
2123 case RTMP_PT_METADATA:
2124 case RTMP_PT_NOTIFY:
2125 /* Audio, Video and Metadata packets are parsed in get_packet() */
2128 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2135 * Interact with the server by receiving and sending RTMP packets until
2136 * there is some significant data (media data or expected status notification).
2138 * @param s reading context
2139 * @param for_header non-zero value tells function to work until it
2140 * gets notification from the server that playing has been started,
2141 * otherwise function will work until some media data is received (or
2143 * @return 0 for successful operation, negative value in case of error
2145 static int get_packet(URLContext *s, int for_header)
2147 RTMPContext *rt = s->priv_data;
2150 const uint8_t *next;
2152 uint32_t ts, cts, pts=0;
2154 if (rt->state == STATE_STOPPED)
2158 RTMPPacket rpkt = { 0 };
2159 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2160 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2162 return AVERROR(EAGAIN);
2164 return AVERROR(EIO);
2167 rt->bytes_read += ret;
2168 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2169 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2170 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2172 rt->last_bytes_read = rt->bytes_read;
2175 ret = rtmp_parse_result(s, rt, &rpkt);
2177 // At this point we must check if we are in the seek state and continue
2178 // with the next packet. handle_invoke will get us out of this state
2179 // when the right message is encountered
2180 if (rt->state == STATE_SEEKING) {
2181 ff_rtmp_packet_destroy(&rpkt);
2182 // We continue, let the natural flow of things happen:
2183 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2187 if (ret < 0) {//serious error in current packet
2188 ff_rtmp_packet_destroy(&rpkt);
2191 if (rt->do_reconnect && for_header) {
2192 ff_rtmp_packet_destroy(&rpkt);
2195 if (rt->state == STATE_STOPPED) {
2196 ff_rtmp_packet_destroy(&rpkt);
2199 if (for_header && (rt->state == STATE_PLAYING ||
2200 rt->state == STATE_PUBLISHING ||
2201 rt->state == STATE_RECEIVING)) {
2202 ff_rtmp_packet_destroy(&rpkt);
2205 if (!rpkt.size || !rt->is_input) {
2206 ff_rtmp_packet_destroy(&rpkt);
2209 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2210 (rpkt.type == RTMP_PT_NOTIFY &&
2211 ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2212 ts = rpkt.timestamp;
2214 // generate packet header and put data into buffer for FLV demuxer
2216 rt->flv_size = rpkt.size + 15;
2217 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2218 bytestream_put_byte(&p, rpkt.type);
2219 bytestream_put_be24(&p, rpkt.size);
2220 bytestream_put_be24(&p, ts);
2221 bytestream_put_byte(&p, ts >> 24);
2222 bytestream_put_be24(&p, 0);
2223 bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2224 bytestream_put_be32(&p, 0);
2225 ff_rtmp_packet_destroy(&rpkt);
2227 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2228 ret = handle_notify(s, &rpkt);
2229 ff_rtmp_packet_destroy(&rpkt);
2231 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2235 } else if (rpkt.type == RTMP_PT_METADATA) {
2236 // we got raw FLV data, make it available for FLV demuxer
2238 rt->flv_size = rpkt.size;
2239 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2240 /* rewrite timestamps */
2242 ts = rpkt.timestamp;
2243 while (next - rpkt.data < rpkt.size - 11) {
2245 size = bytestream_get_be24(&next);
2247 cts = bytestream_get_be24(&next);
2248 cts |= bytestream_get_byte(&next) << 24;
2253 bytestream_put_be24(&p, ts);
2254 bytestream_put_byte(&p, ts >> 24);
2255 next += size + 3 + 4;
2257 memcpy(rt->flv_data, rpkt.data, rpkt.size);
2258 ff_rtmp_packet_destroy(&rpkt);
2261 ff_rtmp_packet_destroy(&rpkt);
2265 static int rtmp_close(URLContext *h)
2267 RTMPContext *rt = h->priv_data;
2270 if (!rt->is_input) {
2271 rt->flv_data = NULL;
2272 if (rt->out_pkt.size)
2273 ff_rtmp_packet_destroy(&rt->out_pkt);
2274 if (rt->state > STATE_FCPUBLISH)
2275 ret = gen_fcunpublish_stream(h, rt);
2277 if (rt->state > STATE_HANDSHAKED)
2278 ret = gen_delete_stream(h, rt);
2280 free_tracked_methods(rt);
2281 av_freep(&rt->flv_data);
2282 ffurl_close(rt->stream);
2287 * Open RTMP connection and verify that the stream can be played.
2289 * URL syntax: rtmp://server[:port][/app][/playpath]
2290 * where 'app' is first one or two directories in the path
2291 * (e.g. /ondemand/, /flash/live/, etc.)
2292 * and 'playpath' is a file name (the rest of the path,
2293 * may be prefixed with "mp4:")
2295 static int rtmp_open(URLContext *s, const char *uri, int flags)
2297 RTMPContext *rt = s->priv_data;
2298 char proto[8], hostname[256], path[1024], auth[100], *fname;
2302 AVDictionary *opts = NULL;
2305 if (rt->listen_timeout > 0)
2308 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2310 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2311 hostname, sizeof(hostname), &port,
2312 path, sizeof(path), s->filename);
2314 if (strchr(path, ' ')) {
2315 av_log(s, AV_LOG_WARNING,
2316 "Detected librtmp style URL parameters, these aren't supported "
2317 "by the libavformat internal RTMP handler currently enabled. "
2318 "See the documentation for the correct way to pass parameters.\n");
2322 char *ptr = strchr(auth, ':');
2325 av_strlcpy(rt->username, auth, sizeof(rt->username));
2326 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2330 if (rt->listen && strcmp(proto, "rtmp")) {
2331 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2333 return AVERROR(EINVAL);
2335 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2336 if (!strcmp(proto, "rtmpts"))
2337 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2339 /* open the http tunneling connection */
2340 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2341 } else if (!strcmp(proto, "rtmps")) {
2342 /* open the tls connection */
2344 port = RTMPS_DEFAULT_PORT;
2345 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2346 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2347 if (!strcmp(proto, "rtmpte"))
2348 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2350 /* open the encrypted connection */
2351 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2354 /* open the tcp connection */
2356 port = RTMP_DEFAULT_PORT;
2358 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2359 "?listen&listen_timeout=%d",
2360 rt->listen_timeout * 1000);
2362 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2366 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2367 &s->interrupt_callback, &opts)) < 0) {
2368 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2372 if (rt->swfverify) {
2373 if ((ret = rtmp_calc_swfhash(s)) < 0)
2377 rt->state = STATE_START;
2378 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2380 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2383 rt->out_chunk_size = 128;
2384 rt->in_chunk_size = 128; // Probably overwritten later
2385 rt->state = STATE_HANDSHAKED;
2387 // Keep the application name when it has been defined by the user.
2390 rt->app = av_malloc(APP_MAX_LENGTH);
2392 ret = AVERROR(ENOMEM);
2396 //extract "app" part from path
2397 if (!strncmp(path, "/ondemand/", 10)) {
2399 memcpy(rt->app, "ondemand", 9);
2401 char *next = *path ? path + 1 : path;
2402 char *p = strchr(next, '/');
2407 // make sure we do not mismatch a playpath for an application instance
2408 char *c = strchr(p + 1, ':');
2409 fname = strchr(p + 1, '/');
2410 if (!fname || (c && c < fname)) {
2412 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2415 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2421 // The name of application has been defined by the user, override it.
2422 if (strlen(old_app) >= APP_MAX_LENGTH) {
2423 ret = AVERROR(EINVAL);
2430 if (!rt->playpath) {
2431 int len = strlen(fname);
2433 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2434 if (!rt->playpath) {
2435 ret = AVERROR(ENOMEM);
2439 if (!strchr(fname, ':') && len >= 4 &&
2440 (!strcmp(fname + len - 4, ".f4v") ||
2441 !strcmp(fname + len - 4, ".mp4"))) {
2442 memcpy(rt->playpath, "mp4:", 5);
2443 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2444 fname[len - 4] = '\0';
2446 rt->playpath[0] = 0;
2448 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2452 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2454 ret = AVERROR(ENOMEM);
2457 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2458 port, "/%s", rt->app);
2461 if (!rt->flashver) {
2462 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2463 if (!rt->flashver) {
2464 ret = AVERROR(ENOMEM);
2468 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2469 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2470 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2472 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2473 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2477 rt->client_report_size = 1048576;
2479 rt->last_bytes_read = 0;
2480 rt->server_bw = 2500000;
2482 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2483 proto, path, rt->app, rt->playpath);
2485 if ((ret = gen_connect(s, rt)) < 0)
2488 if (read_connect(s, s->priv_data) < 0)
2494 ret = get_packet(s, 1);
2495 } while (ret == EAGAIN);
2499 if (rt->do_reconnect) {
2500 ffurl_close(rt->stream);
2502 rt->do_reconnect = 0;
2504 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2505 free_tracked_methods(rt);
2510 // generate FLV header for demuxer
2512 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2514 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2517 rt->flv_data = NULL;
2519 rt->skip_bytes = 13;
2522 s->max_packet_size = rt->stream->max_packet_size;
2527 av_dict_free(&opts);
2532 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2534 RTMPContext *rt = s->priv_data;
2535 int orig_size = size;
2539 int data_left = rt->flv_size - rt->flv_off;
2541 if (data_left >= size) {
2542 memcpy(buf, rt->flv_data + rt->flv_off, size);
2543 rt->flv_off += size;
2546 if (data_left > 0) {
2547 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2550 rt->flv_off = rt->flv_size;
2553 if ((ret = get_packet(s, 0)) < 0)
2559 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2562 RTMPContext *rt = s->priv_data;
2564 av_log(s, AV_LOG_DEBUG,
2565 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2566 stream_index, timestamp, flags);
2567 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2568 av_log(s, AV_LOG_ERROR,
2569 "Unable to send seek command on stream index %d at timestamp "
2570 "%"PRId64" with flags %08x\n",
2571 stream_index, timestamp, flags);
2574 rt->flv_off = rt->flv_size;
2575 rt->state = STATE_SEEKING;
2579 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2581 RTMPContext *rt = s->priv_data;
2582 int size_temp = size;
2583 int pktsize, pkttype;
2585 const uint8_t *buf_temp = buf;
2590 if (rt->skip_bytes) {
2591 int skip = FFMIN(rt->skip_bytes, size_temp);
2594 rt->skip_bytes -= skip;
2598 if (rt->flv_header_bytes < 11) {
2599 const uint8_t *header = rt->flv_header;
2600 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2601 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2602 rt->flv_header_bytes += copy;
2604 if (rt->flv_header_bytes < 11)
2607 pkttype = bytestream_get_byte(&header);
2608 pktsize = bytestream_get_be24(&header);
2609 ts = bytestream_get_be24(&header);
2610 ts |= bytestream_get_byte(&header) << 24;
2611 bytestream_get_be24(&header);
2612 rt->flv_size = pktsize;
2614 //force 12bytes header
2615 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2616 pkttype == RTMP_PT_NOTIFY) {
2617 if (pkttype == RTMP_PT_NOTIFY)
2619 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2622 //this can be a big packet, it's better to send it right here
2623 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2624 pkttype, ts, pktsize)) < 0)
2627 rt->out_pkt.extra = rt->main_channel_id;
2628 rt->flv_data = rt->out_pkt.data;
2630 if (pkttype == RTMP_PT_NOTIFY)
2631 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2634 if (rt->flv_size - rt->flv_off > size_temp) {
2635 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2636 rt->flv_off += size_temp;
2639 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2640 size_temp -= rt->flv_size - rt->flv_off;
2641 rt->flv_off += rt->flv_size - rt->flv_off;
2644 if (rt->flv_off == rt->flv_size) {
2647 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2651 rt->flv_header_bytes = 0;
2652 rt->flv_nb_packets++;
2654 } while (buf_temp - buf < size);
2656 if (rt->flv_nb_packets < rt->flush_interval)
2658 rt->flv_nb_packets = 0;
2660 /* set stream into nonblocking mode */
2661 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2663 /* try to read one byte from the stream */
2664 ret = ffurl_read(rt->stream, &c, 1);
2666 /* switch the stream back into blocking mode */
2667 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2669 if (ret == AVERROR(EAGAIN)) {
2670 /* no incoming data to handle */
2672 } else if (ret < 0) {
2674 } else if (ret == 1) {
2675 RTMPPacket rpkt = { 0 };
2677 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2679 rt->prev_pkt[0], c)) <= 0)
2682 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2685 ff_rtmp_packet_destroy(&rpkt);
2691 #define OFFSET(x) offsetof(RTMPContext, x)
2692 #define DEC AV_OPT_FLAG_DECODING_PARAM
2693 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2695 static const AVOption rtmp_options[] = {
2696 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2697 {"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},
2698 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2699 {"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},
2700 {"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},
2701 {"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"},
2702 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2703 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2704 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2705 {"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},
2706 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2707 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2708 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2709 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2710 {"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},
2711 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2712 {"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},
2713 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2714 {"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" },
2718 #define RTMP_PROTOCOL(flavor) \
2719 static const AVClass flavor##_class = { \
2720 .class_name = #flavor, \
2721 .item_name = av_default_item_name, \
2722 .option = rtmp_options, \
2723 .version = LIBAVUTIL_VERSION_INT, \
2726 URLProtocol ff_##flavor##_protocol = { \
2728 .url_open = rtmp_open, \
2729 .url_read = rtmp_read, \
2730 .url_read_seek = rtmp_seek, \
2731 .url_write = rtmp_write, \
2732 .url_close = rtmp_close, \
2733 .priv_data_size = sizeof(RTMPContext), \
2734 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2735 .priv_data_class= &flavor##_class, \
2740 RTMP_PROTOCOL(rtmpe)
2741 RTMP_PROTOCOL(rtmps)
2742 RTMP_PROTOCOL(rtmpt)
2743 RTMP_PROTOCOL(rtmpte)
2744 RTMP_PROTOCOL(rtmpts)