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 if (!strchr(rt->app, '/'))
1613 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1614 av_md5_final(md5, hash);
1615 ff_data_to_hex(hashstr2, hash, 16, 1);
1616 hashstr2[32] = '\0';
1619 av_md5_update(md5, hashstr1, strlen(hashstr1));
1620 av_md5_update(md5, ":", 1);
1622 av_md5_update(md5, nonce, strlen(nonce));
1623 av_md5_update(md5, ":", 1);
1624 av_md5_update(md5, nc, strlen(nc));
1625 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, cnonce, strlen(cnonce));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, qop, strlen(qop));
1629 av_md5_update(md5, ":", 1);
1630 av_md5_update(md5, hashstr2, strlen(hashstr2));
1631 av_md5_final(md5, hash);
1632 ff_data_to_hex(hashstr1, hash, 16, 1);
1634 snprintf(rt->auth_params, sizeof(rt->auth_params),
1635 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1636 "llnw", user, nonce, cnonce, nc, hashstr1);
1642 static int handle_connect_error(URLContext *s, const char *desc)
1644 RTMPContext *rt = s->priv_data;
1645 char buf[300], *ptr, authmod[15];
1647 const char *user = "", *salt = "", *opaque = NULL,
1648 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1650 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1651 !(cptr = strstr(desc, "authmod=llnw"))) {
1652 av_log(s, AV_LOG_ERROR,
1653 "Unknown connect error (unsupported authentication method?)\n");
1654 return AVERROR_UNKNOWN;
1656 cptr += strlen("authmod=");
1657 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1658 authmod[i++] = *cptr++;
1661 if (!rt->username[0] || !rt->password[0]) {
1662 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1663 return AVERROR_UNKNOWN;
1666 if (strstr(desc, "?reason=authfailed")) {
1667 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1668 return AVERROR_UNKNOWN;
1669 } else if (strstr(desc, "?reason=nosuchuser")) {
1670 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1671 return AVERROR_UNKNOWN;
1674 if (rt->auth_tried) {
1675 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1676 return AVERROR_UNKNOWN;
1679 rt->auth_params[0] = '\0';
1681 if (strstr(desc, "code=403 need auth")) {
1682 snprintf(rt->auth_params, sizeof(rt->auth_params),
1683 "?authmod=%s&user=%s", authmod, rt->username);
1687 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1688 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1689 return AVERROR_UNKNOWN;
1692 av_strlcpy(buf, cptr + 1, sizeof(buf));
1696 char *next = strchr(ptr, '&');
1697 char *value = strchr(ptr, '=');
1702 if (!strcmp(ptr, "user")) {
1704 } else if (!strcmp(ptr, "salt")) {
1706 } else if (!strcmp(ptr, "opaque")) {
1708 } else if (!strcmp(ptr, "challenge")) {
1710 } else if (!strcmp(ptr, "nonce")) {
1716 if (!strcmp(authmod, "adobe")) {
1717 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1720 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1728 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1730 RTMPContext *rt = s->priv_data;
1731 const uint8_t *data_end = pkt->data + pkt->size;
1732 char *tracked_method = NULL;
1733 int level = AV_LOG_ERROR;
1734 uint8_t tmpstr[256];
1737 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1740 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1741 "description", tmpstr, sizeof(tmpstr))) {
1742 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1743 !strcmp(tracked_method, "releaseStream") ||
1744 !strcmp(tracked_method, "FCSubscribe") ||
1745 !strcmp(tracked_method, "FCPublish"))) {
1746 /* Gracefully ignore Adobe-specific historical artifact errors. */
1747 level = AV_LOG_WARNING;
1749 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1750 ret = handle_connect_error(s, tmpstr);
1752 rt->do_reconnect = 1;
1753 level = AV_LOG_VERBOSE;
1756 ret = AVERROR_UNKNOWN;
1757 av_log(s, level, "Server error: %s\n", tmpstr);
1760 av_free(tracked_method);
1764 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1766 RTMPContext *rt = s->priv_data;
1770 char statusmsg[128];
1773 const uint8_t *p = pkt->data;
1775 RTMPPacket spkt = { 0 };
1779 bytestream2_init(&gbc, p, pkt->size);
1780 if (ff_amf_read_string(&gbc, command, sizeof(command),
1782 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1783 return AVERROR_INVALIDDATA;
1786 ret = ff_amf_read_number(&gbc, &seqnum);
1789 ret = ff_amf_read_null(&gbc);
1792 if (!strcmp(command, "FCPublish") ||
1793 !strcmp(command, "publish")) {
1794 ret = ff_amf_read_string(&gbc, filename,
1795 sizeof(filename), &stringlen);
1798 pchar = strrchr(s->filename, '/');
1800 av_log(s, AV_LOG_WARNING,
1801 "Unable to find / in url %s, bad format\n",
1803 pchar = s->filename;
1806 if (strcmp(pchar, filename))
1807 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1808 " %s\n", filename, pchar);
1810 rt->state = STATE_RECEIVING;
1813 if (!strcmp(command, "FCPublish")) {
1814 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1816 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1817 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1821 ff_amf_write_string(&pp, "onFCPublish");
1822 } else if (!strcmp(command, "publish")) {
1824 // Send Stream Begin 1
1825 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1826 RTMP_PT_PING, 0, 6)) < 0) {
1827 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1831 bytestream2_init_writer(&pbc, pp, spkt.size);
1832 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1833 bytestream2_put_be32(&pbc, rt->nb_streamid);
1834 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1836 ff_rtmp_packet_destroy(&spkt);
1840 // Send onStatus(NetStream.Publish.Start)
1841 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1843 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1844 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1847 spkt.extra = pkt->extra;
1849 ff_amf_write_string(&pp, "onStatus");
1850 ff_amf_write_number(&pp, 0);
1851 ff_amf_write_null(&pp);
1853 ff_amf_write_object_start(&pp);
1854 ff_amf_write_field_name(&pp, "level");
1855 ff_amf_write_string(&pp, "status");
1856 ff_amf_write_field_name(&pp, "code");
1857 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1858 ff_amf_write_field_name(&pp, "description");
1859 snprintf(statusmsg, sizeof(statusmsg),
1860 "%s is now published", filename);
1861 ff_amf_write_string(&pp, statusmsg);
1862 ff_amf_write_field_name(&pp, "details");
1863 ff_amf_write_string(&pp, filename);
1864 ff_amf_write_field_name(&pp, "clientid");
1865 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1866 ff_amf_write_string(&pp, statusmsg);
1867 ff_amf_write_object_end(&pp);
1870 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1872 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1873 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1877 ff_amf_write_string(&pp, "_result");
1878 ff_amf_write_number(&pp, seqnum);
1879 ff_amf_write_null(&pp);
1880 if (!strcmp(command, "createStream")) {
1882 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1883 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1884 ff_amf_write_number(&pp, rt->nb_streamid);
1885 /* By now we don't control which streams are removed in
1886 * deleteStream. There is no stream creation control
1887 * if a client creates more than 2^32 - 2 streams. */
1890 spkt.size = pp - spkt.data;
1891 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1893 ff_rtmp_packet_destroy(&spkt);
1897 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1899 RTMPContext *rt = s->priv_data;
1900 char *tracked_method = NULL;
1903 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1906 if (!tracked_method) {
1907 /* Ignore this reply when the current method is not tracked. */
1911 if (!strcmp(tracked_method, "connect")) {
1912 if (!rt->is_input) {
1913 if ((ret = gen_release_stream(s, rt)) < 0)
1916 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1919 if ((ret = gen_server_bw(s, rt)) < 0)
1923 if ((ret = gen_create_stream(s, rt)) < 0)
1927 /* Send the FCSubscribe command when the name of live
1928 * stream is defined by the user or if it's a live stream. */
1929 if (rt->subscribe) {
1930 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1932 } else if (rt->live == -1) {
1933 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1937 } else if (!strcmp(tracked_method, "createStream")) {
1938 //extract a number from the result
1939 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1940 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1942 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1945 if (!rt->is_input) {
1946 if ((ret = gen_publish(s, rt)) < 0)
1949 if ((ret = gen_play(s, rt)) < 0)
1951 if ((ret = gen_buffer_time(s, rt)) < 0)
1957 av_free(tracked_method);
1961 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1963 RTMPContext *rt = s->priv_data;
1964 const uint8_t *data_end = pkt->data + pkt->size;
1965 const uint8_t *ptr = pkt->data + 11;
1966 uint8_t tmpstr[256];
1969 for (i = 0; i < 2; i++) {
1970 t = ff_amf_tag_size(ptr, data_end);
1976 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1977 if (!t && !strcmp(tmpstr, "error")) {
1978 if (!ff_amf_get_field_value(ptr, data_end,
1979 "description", tmpstr, sizeof(tmpstr)))
1980 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1984 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1985 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1986 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1987 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1988 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1989 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
1994 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1996 RTMPContext *rt = s->priv_data;
1999 //TODO: check for the messages sent for wrong state?
2000 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2001 if ((ret = handle_invoke_error(s, pkt)) < 0)
2003 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2004 if ((ret = handle_invoke_result(s, pkt)) < 0)
2006 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2007 if ((ret = handle_invoke_status(s, pkt)) < 0)
2009 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2010 if ((ret = gen_check_bw(s, rt)) < 0)
2012 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2013 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2014 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2015 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2016 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2017 if ((ret = send_invoke_response(s, pkt)) < 0)
2024 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2025 RTMPContext *rt = s->priv_data;
2026 const uint8_t *p = NULL;
2028 uint8_t commandbuffer[64];
2029 char statusmsg[128];
2035 const uint8_t *datatowrite;
2036 unsigned datatowritelength;
2039 bytestream2_init(&gbc, p, pkt->size);
2040 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2042 return AVERROR_INVALIDDATA;
2043 if (!strcmp(commandbuffer, "@setDataFrame")) {
2044 datatowrite = gbc.buffer;
2045 datatowritelength = bytestream2_get_bytes_left(&gbc);
2046 if (ff_amf_read_string(&gbc, statusmsg,
2047 sizeof(statusmsg), &stringlen))
2048 return AVERROR_INVALIDDATA;
2049 if (strcmp(statusmsg, "onMetaData")) {
2050 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2055 /* Provide ECMAArray to flv */
2056 ts = pkt->timestamp;
2058 // generate packet header and put data into buffer for FLV demuxer
2059 if (rt->flv_off < rt->flv_size) {
2060 old_flv_size = rt->flv_size;
2061 rt->flv_size += datatowritelength + 15;
2064 rt->flv_size = datatowritelength + 15;
2068 cp = av_realloc(rt->flv_data, rt->flv_size);
2070 return AVERROR(ENOMEM);
2072 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2073 bytestream2_skip_p(&pbc, old_flv_size);
2074 bytestream2_put_byte(&pbc, pkt->type);
2075 bytestream2_put_be24(&pbc, datatowritelength);
2076 bytestream2_put_be24(&pbc, ts);
2077 bytestream2_put_byte(&pbc, ts >> 24);
2078 bytestream2_put_be24(&pbc, 0);
2079 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2080 bytestream2_put_be32(&pbc, 0);
2086 * Parse received packet and possibly perform some action depending on
2087 * the packet contents.
2088 * @return 0 for no errors, negative values for serious errors which prevent
2089 * further communications, positive values for uncritical errors
2091 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2096 ff_rtmp_packet_dump(s, pkt);
2099 switch (pkt->type) {
2100 case RTMP_PT_BYTES_READ:
2101 av_dlog(s, "received bytes read report\n");
2103 case RTMP_PT_CHUNK_SIZE:
2104 if ((ret = handle_chunk_size(s, pkt)) < 0)
2108 if ((ret = handle_ping(s, pkt)) < 0)
2111 case RTMP_PT_CLIENT_BW:
2112 if ((ret = handle_client_bw(s, pkt)) < 0)
2115 case RTMP_PT_SERVER_BW:
2116 if ((ret = handle_server_bw(s, pkt)) < 0)
2119 case RTMP_PT_INVOKE:
2120 if ((ret = handle_invoke(s, pkt)) < 0)
2125 case RTMP_PT_METADATA:
2126 case RTMP_PT_NOTIFY:
2127 /* Audio, Video and Metadata packets are parsed in get_packet() */
2130 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2137 * Interact with the server by receiving and sending RTMP packets until
2138 * there is some significant data (media data or expected status notification).
2140 * @param s reading context
2141 * @param for_header non-zero value tells function to work until it
2142 * gets notification from the server that playing has been started,
2143 * otherwise function will work until some media data is received (or
2145 * @return 0 for successful operation, negative value in case of error
2147 static int get_packet(URLContext *s, int for_header)
2149 RTMPContext *rt = s->priv_data;
2152 const uint8_t *next;
2154 uint32_t ts, cts, pts=0;
2156 if (rt->state == STATE_STOPPED)
2160 RTMPPacket rpkt = { 0 };
2161 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2162 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2164 return AVERROR(EAGAIN);
2166 return AVERROR(EIO);
2169 rt->bytes_read += ret;
2170 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2171 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2172 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2174 rt->last_bytes_read = rt->bytes_read;
2177 ret = rtmp_parse_result(s, rt, &rpkt);
2179 // At this point we must check if we are in the seek state and continue
2180 // with the next packet. handle_invoke will get us out of this state
2181 // when the right message is encountered
2182 if (rt->state == STATE_SEEKING) {
2183 ff_rtmp_packet_destroy(&rpkt);
2184 // We continue, let the natural flow of things happen:
2185 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2189 if (ret < 0) {//serious error in current packet
2190 ff_rtmp_packet_destroy(&rpkt);
2193 if (rt->do_reconnect && for_header) {
2194 ff_rtmp_packet_destroy(&rpkt);
2197 if (rt->state == STATE_STOPPED) {
2198 ff_rtmp_packet_destroy(&rpkt);
2201 if (for_header && (rt->state == STATE_PLAYING ||
2202 rt->state == STATE_PUBLISHING ||
2203 rt->state == STATE_RECEIVING)) {
2204 ff_rtmp_packet_destroy(&rpkt);
2207 if (!rpkt.size || !rt->is_input) {
2208 ff_rtmp_packet_destroy(&rpkt);
2211 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2212 (rpkt.type == RTMP_PT_NOTIFY &&
2213 ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2214 ts = rpkt.timestamp;
2216 // generate packet header and put data into buffer for FLV demuxer
2218 rt->flv_size = rpkt.size + 15;
2219 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2220 bytestream_put_byte(&p, rpkt.type);
2221 bytestream_put_be24(&p, rpkt.size);
2222 bytestream_put_be24(&p, ts);
2223 bytestream_put_byte(&p, ts >> 24);
2224 bytestream_put_be24(&p, 0);
2225 bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2226 bytestream_put_be32(&p, 0);
2227 ff_rtmp_packet_destroy(&rpkt);
2229 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2230 ret = handle_notify(s, &rpkt);
2231 ff_rtmp_packet_destroy(&rpkt);
2233 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2237 } else if (rpkt.type == RTMP_PT_METADATA) {
2238 // we got raw FLV data, make it available for FLV demuxer
2240 rt->flv_size = rpkt.size;
2241 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2242 /* rewrite timestamps */
2244 ts = rpkt.timestamp;
2245 while (next - rpkt.data < rpkt.size - 11) {
2247 size = bytestream_get_be24(&next);
2249 cts = bytestream_get_be24(&next);
2250 cts |= bytestream_get_byte(&next) << 24;
2255 bytestream_put_be24(&p, ts);
2256 bytestream_put_byte(&p, ts >> 24);
2257 next += size + 3 + 4;
2259 memcpy(rt->flv_data, rpkt.data, rpkt.size);
2260 ff_rtmp_packet_destroy(&rpkt);
2263 ff_rtmp_packet_destroy(&rpkt);
2267 static int rtmp_close(URLContext *h)
2269 RTMPContext *rt = h->priv_data;
2272 if (!rt->is_input) {
2273 rt->flv_data = NULL;
2274 if (rt->out_pkt.size)
2275 ff_rtmp_packet_destroy(&rt->out_pkt);
2276 if (rt->state > STATE_FCPUBLISH)
2277 ret = gen_fcunpublish_stream(h, rt);
2279 if (rt->state > STATE_HANDSHAKED)
2280 ret = gen_delete_stream(h, rt);
2282 free_tracked_methods(rt);
2283 av_freep(&rt->flv_data);
2284 ffurl_close(rt->stream);
2289 * Open RTMP connection and verify that the stream can be played.
2291 * URL syntax: rtmp://server[:port][/app][/playpath]
2292 * where 'app' is first one or two directories in the path
2293 * (e.g. /ondemand/, /flash/live/, etc.)
2294 * and 'playpath' is a file name (the rest of the path,
2295 * may be prefixed with "mp4:")
2297 static int rtmp_open(URLContext *s, const char *uri, int flags)
2299 RTMPContext *rt = s->priv_data;
2300 char proto[8], hostname[256], path[1024], auth[100], *fname;
2304 AVDictionary *opts = NULL;
2307 if (rt->listen_timeout > 0)
2310 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2312 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2313 hostname, sizeof(hostname), &port,
2314 path, sizeof(path), s->filename);
2316 if (strchr(path, ' ')) {
2317 av_log(s, AV_LOG_WARNING,
2318 "Detected librtmp style URL parameters, these aren't supported "
2319 "by the libavformat internal RTMP handler currently enabled. "
2320 "See the documentation for the correct way to pass parameters.\n");
2324 char *ptr = strchr(auth, ':');
2327 av_strlcpy(rt->username, auth, sizeof(rt->username));
2328 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2332 if (rt->listen && strcmp(proto, "rtmp")) {
2333 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2335 return AVERROR(EINVAL);
2337 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2338 if (!strcmp(proto, "rtmpts"))
2339 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2341 /* open the http tunneling connection */
2342 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2343 } else if (!strcmp(proto, "rtmps")) {
2344 /* open the tls connection */
2346 port = RTMPS_DEFAULT_PORT;
2347 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2348 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2349 if (!strcmp(proto, "rtmpte"))
2350 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2352 /* open the encrypted connection */
2353 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2356 /* open the tcp connection */
2358 port = RTMP_DEFAULT_PORT;
2360 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2361 "?listen&listen_timeout=%d",
2362 rt->listen_timeout * 1000);
2364 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2368 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2369 &s->interrupt_callback, &opts)) < 0) {
2370 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2374 if (rt->swfverify) {
2375 if ((ret = rtmp_calc_swfhash(s)) < 0)
2379 rt->state = STATE_START;
2380 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2382 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2385 rt->out_chunk_size = 128;
2386 rt->in_chunk_size = 128; // Probably overwritten later
2387 rt->state = STATE_HANDSHAKED;
2389 // Keep the application name when it has been defined by the user.
2392 rt->app = av_malloc(APP_MAX_LENGTH);
2394 ret = AVERROR(ENOMEM);
2398 //extract "app" part from path
2399 if (!strncmp(path, "/ondemand/", 10)) {
2401 memcpy(rt->app, "ondemand", 9);
2403 char *next = *path ? path + 1 : path;
2404 char *p = strchr(next, '/');
2409 // make sure we do not mismatch a playpath for an application instance
2410 char *c = strchr(p + 1, ':');
2411 fname = strchr(p + 1, '/');
2412 if (!fname || (c && c < fname)) {
2414 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2417 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2423 // The name of application has been defined by the user, override it.
2424 if (strlen(old_app) >= APP_MAX_LENGTH) {
2425 ret = AVERROR(EINVAL);
2432 if (!rt->playpath) {
2433 int len = strlen(fname);
2435 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2436 if (!rt->playpath) {
2437 ret = AVERROR(ENOMEM);
2441 if (!strchr(fname, ':') && len >= 4 &&
2442 (!strcmp(fname + len - 4, ".f4v") ||
2443 !strcmp(fname + len - 4, ".mp4"))) {
2444 memcpy(rt->playpath, "mp4:", 5);
2445 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2446 fname[len - 4] = '\0';
2448 rt->playpath[0] = 0;
2450 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2454 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2456 ret = AVERROR(ENOMEM);
2459 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2460 port, "/%s", rt->app);
2463 if (!rt->flashver) {
2464 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2465 if (!rt->flashver) {
2466 ret = AVERROR(ENOMEM);
2470 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2471 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2472 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2474 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2475 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2479 rt->client_report_size = 1048576;
2481 rt->last_bytes_read = 0;
2482 rt->server_bw = 2500000;
2484 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2485 proto, path, rt->app, rt->playpath);
2487 if ((ret = gen_connect(s, rt)) < 0)
2490 if (read_connect(s, s->priv_data) < 0)
2496 ret = get_packet(s, 1);
2497 } while (ret == EAGAIN);
2501 if (rt->do_reconnect) {
2502 ffurl_close(rt->stream);
2504 rt->do_reconnect = 0;
2506 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2507 free_tracked_methods(rt);
2512 // generate FLV header for demuxer
2514 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2516 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2519 rt->flv_data = NULL;
2521 rt->skip_bytes = 13;
2524 s->max_packet_size = rt->stream->max_packet_size;
2529 av_dict_free(&opts);
2534 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2536 RTMPContext *rt = s->priv_data;
2537 int orig_size = size;
2541 int data_left = rt->flv_size - rt->flv_off;
2543 if (data_left >= size) {
2544 memcpy(buf, rt->flv_data + rt->flv_off, size);
2545 rt->flv_off += size;
2548 if (data_left > 0) {
2549 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2552 rt->flv_off = rt->flv_size;
2555 if ((ret = get_packet(s, 0)) < 0)
2561 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2564 RTMPContext *rt = s->priv_data;
2566 av_log(s, AV_LOG_DEBUG,
2567 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2568 stream_index, timestamp, flags);
2569 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2570 av_log(s, AV_LOG_ERROR,
2571 "Unable to send seek command on stream index %d at timestamp "
2572 "%"PRId64" with flags %08x\n",
2573 stream_index, timestamp, flags);
2576 rt->flv_off = rt->flv_size;
2577 rt->state = STATE_SEEKING;
2581 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2583 RTMPContext *rt = s->priv_data;
2584 int size_temp = size;
2585 int pktsize, pkttype;
2587 const uint8_t *buf_temp = buf;
2592 if (rt->skip_bytes) {
2593 int skip = FFMIN(rt->skip_bytes, size_temp);
2596 rt->skip_bytes -= skip;
2600 if (rt->flv_header_bytes < 11) {
2601 const uint8_t *header = rt->flv_header;
2602 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2603 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2604 rt->flv_header_bytes += copy;
2606 if (rt->flv_header_bytes < 11)
2609 pkttype = bytestream_get_byte(&header);
2610 pktsize = bytestream_get_be24(&header);
2611 ts = bytestream_get_be24(&header);
2612 ts |= bytestream_get_byte(&header) << 24;
2613 bytestream_get_be24(&header);
2614 rt->flv_size = pktsize;
2616 //force 12bytes header
2617 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2618 pkttype == RTMP_PT_NOTIFY) {
2619 if (pkttype == RTMP_PT_NOTIFY)
2621 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2624 //this can be a big packet, it's better to send it right here
2625 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2626 pkttype, ts, pktsize)) < 0)
2629 rt->out_pkt.extra = rt->main_channel_id;
2630 rt->flv_data = rt->out_pkt.data;
2632 if (pkttype == RTMP_PT_NOTIFY)
2633 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2636 if (rt->flv_size - rt->flv_off > size_temp) {
2637 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2638 rt->flv_off += size_temp;
2641 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2642 size_temp -= rt->flv_size - rt->flv_off;
2643 rt->flv_off += rt->flv_size - rt->flv_off;
2646 if (rt->flv_off == rt->flv_size) {
2649 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2653 rt->flv_header_bytes = 0;
2654 rt->flv_nb_packets++;
2656 } while (buf_temp - buf < size);
2658 if (rt->flv_nb_packets < rt->flush_interval)
2660 rt->flv_nb_packets = 0;
2662 /* set stream into nonblocking mode */
2663 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2665 /* try to read one byte from the stream */
2666 ret = ffurl_read(rt->stream, &c, 1);
2668 /* switch the stream back into blocking mode */
2669 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2671 if (ret == AVERROR(EAGAIN)) {
2672 /* no incoming data to handle */
2674 } else if (ret < 0) {
2676 } else if (ret == 1) {
2677 RTMPPacket rpkt = { 0 };
2679 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2681 rt->prev_pkt[0], c)) <= 0)
2684 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2687 ff_rtmp_packet_destroy(&rpkt);
2693 #define OFFSET(x) offsetof(RTMPContext, x)
2694 #define DEC AV_OPT_FLAG_DECODING_PARAM
2695 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2697 static const AVOption rtmp_options[] = {
2698 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2699 {"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},
2700 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2701 {"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},
2702 {"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},
2703 {"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"},
2704 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2705 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2706 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2707 {"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},
2708 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2709 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2710 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2711 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2712 {"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},
2713 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2714 {"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},
2715 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2716 {"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" },
2720 #define RTMP_PROTOCOL(flavor) \
2721 static const AVClass flavor##_class = { \
2722 .class_name = #flavor, \
2723 .item_name = av_default_item_name, \
2724 .option = rtmp_options, \
2725 .version = LIBAVUTIL_VERSION_INT, \
2728 URLProtocol ff_##flavor##_protocol = { \
2730 .url_open = rtmp_open, \
2731 .url_read = rtmp_read, \
2732 .url_read_seek = rtmp_seek, \
2733 .url_write = rtmp_write, \
2734 .url_close = rtmp_close, \
2735 .priv_data_size = sizeof(RTMPContext), \
2736 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2737 .priv_data_class= &flavor##_class, \
2742 RTMP_PROTOCOL(rtmpe)
2743 RTMP_PROTOCOL(rtmps)
2744 RTMP_PROTOCOL(rtmpt)
2745 RTMP_PROTOCOL(rtmpte)
2746 RTMP_PROTOCOL(rtmpts)