2 * RTMP network protocol
3 * Copyright (c) 2009 Kostya Shishkov
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
53 #define APP_MAX_LENGTH 128
54 #define PLAYPATH_MAX_LENGTH 256
55 #define TCURL_MAX_LENGTH 512
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
59 /** RTMP protocol handler state */
61 STATE_START, ///< client has not done anything yet
62 STATE_HANDSHAKED, ///< client has performed handshake
63 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
64 STATE_PLAYING, ///< client has started receiving multimedia data from server
65 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66 STATE_RECEIVING, ///< received a publish command (for input)
67 STATE_STOPPED, ///< the broadcast has been stopped
70 typedef struct TrackedMethod {
75 /** protocol handler context */
76 typedef struct RTMPContext {
78 URLContext* stream; ///< TCP stream used in interactions with RTMP server
79 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
80 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
81 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
82 int is_input; ///< input/output flag
83 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
84 int live; ///< 0: recorded, -1: live, -2: both
85 char *app; ///< name of application
86 char *conn; ///< append arbitrary AMF data to the Connect message
87 ClientState state; ///< current state
88 int main_channel_id; ///< an additional channel ID which is used for some invocations
89 uint8_t* flv_data; ///< buffer with data for demuxer
90 int flv_size; ///< current buffer size
91 int flv_off; ///< number of bytes read from current buffer
92 int flv_nb_packets; ///< number of flv packets published
93 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
94 uint32_t client_report_size; ///< number of bytes after which client should report to server
95 uint32_t bytes_read; ///< number of bytes read from server
96 uint32_t last_bytes_read; ///< number of bytes read last reported to server
97 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
98 uint8_t flv_header[11]; ///< partial incoming flv packet header
99 int flv_header_bytes; ///< number of initialized bytes in flv_header
100 int nb_invokes; ///< keeps track of invoke messages
101 char* tcurl; ///< url of the target stream
102 char* flashver; ///< version of the flash plugin
103 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
104 int swfhash_len; ///< length of the SHA256 hash
105 int swfsize; ///< size of the decompressed SWF file
106 char* swfurl; ///< url of the swf player
107 char* swfverify; ///< URL to player swf file, compute hash/size automatically
108 char swfverification[42]; ///< hash of the SWF verification
109 char* pageurl; ///< url of the web page
110 char* subscribe; ///< name of live stream to subscribe
111 int server_bw; ///< server bandwidth
112 int client_buffer_time; ///< client buffer time in ms
113 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
114 int encrypted; ///< use an encrypted connection (RTMPE only)
115 TrackedMethod*tracked_methods; ///< tracked methods buffer
116 int nb_tracked_methods; ///< number of tracked methods
117 int tracked_methods_size; ///< size of the tracked methods buffer
118 int listen; ///< listen mode flag
119 int listen_timeout; ///< listen timeout to wait for new connections
120 int nb_streamid; ///< The next stream id to return on createStream calls
123 char auth_params[500];
128 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
129 /** Client key used for digest signing */
130 static const uint8_t rtmp_player_key[] = {
131 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
132 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
134 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
135 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
136 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
139 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
140 /** Key used for RTMP server digest signing */
141 static const uint8_t rtmp_server_key[] = {
142 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
143 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
144 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
146 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
147 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
148 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
151 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
155 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
156 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
157 ptr = av_realloc(rt->tracked_methods,
158 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
160 return AVERROR(ENOMEM);
161 rt->tracked_methods = ptr;
164 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
165 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
166 return AVERROR(ENOMEM);
167 rt->tracked_methods[rt->nb_tracked_methods].id = id;
168 rt->nb_tracked_methods++;
173 static void del_tracked_method(RTMPContext *rt, int index)
175 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
176 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
177 rt->nb_tracked_methods--;
180 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
181 char **tracked_method)
183 RTMPContext *rt = s->priv_data;
189 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
190 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
193 for (i = 0; i < rt->nb_tracked_methods; i++) {
194 if (rt->tracked_methods[i].id != pkt_id)
197 *tracked_method = rt->tracked_methods[i].name;
198 del_tracked_method(rt, i);
205 static void free_tracked_methods(RTMPContext *rt)
209 for (i = 0; i < rt->nb_tracked_methods; i ++)
210 av_free(rt->tracked_methods[i].name);
211 av_free(rt->tracked_methods);
212 rt->tracked_methods = NULL;
213 rt->tracked_methods_size = 0;
214 rt->nb_tracked_methods = 0;
217 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
221 if (pkt->type == RTMP_PT_INVOKE && track) {
227 bytestream2_init(&gbc, pkt->data, pkt->data_size);
228 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
231 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
234 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
238 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
241 ff_rtmp_packet_destroy(pkt);
245 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
250 /* The type must be B for Boolean, N for number, S for string, O for
251 * object, or Z for null. For Booleans the data must be either 0 or 1 for
252 * FALSE or TRUE, respectively. Likewise for Objects the data must be
253 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
254 * may be named, by prefixing the type with 'N' and specifying the name
255 * before the value (ie. NB:myFlag:1). This option may be used multiple times
256 * to construct arbitrary AMF sequences. */
257 if (param[0] && param[1] == ':') {
260 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
263 value = strchr(field, ':');
269 if (!field || !value)
272 ff_amf_write_field_name(p, field);
279 ff_amf_write_bool(p, value[0] != '0');
282 ff_amf_write_string(p, value);
285 ff_amf_write_number(p, strtod(value, NULL));
288 ff_amf_write_null(p);
292 ff_amf_write_object_start(p);
294 ff_amf_write_object_end(p);
304 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
305 return AVERROR(EINVAL);
309 * Generate 'connect' call and send it to the server.
311 static int gen_connect(URLContext *s, RTMPContext *rt)
317 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
323 ff_amf_write_string(&p, "connect");
324 ff_amf_write_number(&p, ++rt->nb_invokes);
325 ff_amf_write_object_start(&p);
326 ff_amf_write_field_name(&p, "app");
327 ff_amf_write_string2(&p, rt->app, rt->auth_params);
330 ff_amf_write_field_name(&p, "type");
331 ff_amf_write_string(&p, "nonprivate");
333 ff_amf_write_field_name(&p, "flashVer");
334 ff_amf_write_string(&p, rt->flashver);
337 ff_amf_write_field_name(&p, "swfUrl");
338 ff_amf_write_string(&p, rt->swfurl);
341 ff_amf_write_field_name(&p, "tcUrl");
342 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
344 ff_amf_write_field_name(&p, "fpad");
345 ff_amf_write_bool(&p, 0);
346 ff_amf_write_field_name(&p, "capabilities");
347 ff_amf_write_number(&p, 15.0);
349 /* Tell the server we support all the audio codecs except
350 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
351 * which are unused in the RTMP protocol implementation. */
352 ff_amf_write_field_name(&p, "audioCodecs");
353 ff_amf_write_number(&p, 4071.0);
354 ff_amf_write_field_name(&p, "videoCodecs");
355 ff_amf_write_number(&p, 252.0);
356 ff_amf_write_field_name(&p, "videoFunction");
357 ff_amf_write_number(&p, 1.0);
360 ff_amf_write_field_name(&p, "pageUrl");
361 ff_amf_write_string(&p, rt->pageurl);
364 ff_amf_write_object_end(&p);
367 char *param = rt->conn;
369 // Write arbitrary AMF data to the Connect message.
370 while (param != NULL) {
372 param += strspn(param, " ");
375 sep = strchr(param, ' ');
378 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
379 // Invalid AMF parameter.
380 ff_rtmp_packet_destroy(&pkt);
391 pkt.data_size = p - pkt.data;
393 return rtmp_send_packet(rt, &pkt, 1);
396 static int read_connect(URLContext *s, RTMPContext *rt)
398 RTMPPacket pkt = { 0 };
408 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
409 rt->prev_pkt[1])) < 0)
412 bytestream2_init(&gbc, cp, pkt.data_size);
413 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
414 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
415 ff_rtmp_packet_destroy(&pkt);
416 return AVERROR_INVALIDDATA;
418 if (strcmp(command, "connect")) {
419 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
420 ff_rtmp_packet_destroy(&pkt);
421 return AVERROR_INVALIDDATA;
423 ret = ff_amf_read_number(&gbc, &seqnum);
425 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
426 /* Here one could parse an AMF Object with data as flashVers and others. */
427 ret = ff_amf_get_field_value(gbc.buffer,
428 gbc.buffer + bytestream2_get_bytes_left(&gbc),
429 "app", tmpstr, sizeof(tmpstr));
431 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
432 if (!ret && strcmp(tmpstr, rt->app))
433 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
435 ff_rtmp_packet_destroy(&pkt);
437 // Send Window Acknowledgement Size (as defined in speficication)
438 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
439 RTMP_PT_SERVER_BW, 0, 4)) < 0)
442 bytestream_put_be32(&p, rt->server_bw);
443 pkt.data_size = p - pkt.data;
444 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
446 ff_rtmp_packet_destroy(&pkt);
449 // Send Peer Bandwidth
450 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
451 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
454 bytestream_put_be32(&p, rt->server_bw);
455 bytestream_put_byte(&p, 2); // dynamic
456 pkt.data_size = p - pkt.data;
457 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
459 ff_rtmp_packet_destroy(&pkt);
464 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
465 RTMP_PT_PING, 0, 6)) < 0)
469 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
470 bytestream_put_be32(&p, 0);
471 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
473 ff_rtmp_packet_destroy(&pkt);
478 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
479 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
483 bytestream_put_be32(&p, rt->out_chunk_size);
484 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
486 ff_rtmp_packet_destroy(&pkt);
490 // Send result_ NetConnection.Connect.Success to connect
491 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
493 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
497 ff_amf_write_string(&p, "_result");
498 ff_amf_write_number(&p, seqnum);
500 ff_amf_write_object_start(&p);
501 ff_amf_write_field_name(&p, "fmsVer");
502 ff_amf_write_string(&p, "FMS/3,0,1,123");
503 ff_amf_write_field_name(&p, "capabilities");
504 ff_amf_write_number(&p, 31);
505 ff_amf_write_object_end(&p);
507 ff_amf_write_object_start(&p);
508 ff_amf_write_field_name(&p, "level");
509 ff_amf_write_string(&p, "status");
510 ff_amf_write_field_name(&p, "code");
511 ff_amf_write_string(&p, "NetConnection.Connect.Success");
512 ff_amf_write_field_name(&p, "description");
513 ff_amf_write_string(&p, "Connection succeeded.");
514 ff_amf_write_field_name(&p, "objectEncoding");
515 ff_amf_write_number(&p, 0);
516 ff_amf_write_object_end(&p);
518 pkt.data_size = p - pkt.data;
519 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
521 ff_rtmp_packet_destroy(&pkt);
525 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
526 RTMP_PT_INVOKE, 0, 30)) < 0)
529 ff_amf_write_string(&p, "onBWDone");
530 ff_amf_write_number(&p, 0);
531 ff_amf_write_null(&p);
532 ff_amf_write_number(&p, 8192);
533 pkt.data_size = p - pkt.data;
534 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
536 ff_rtmp_packet_destroy(&pkt);
542 * Generate 'releaseStream' call and send it to the server. It should make
543 * the server release some channel for media streams.
545 static int gen_release_stream(URLContext *s, RTMPContext *rt)
551 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
552 0, 29 + strlen(rt->playpath))) < 0)
555 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
557 ff_amf_write_string(&p, "releaseStream");
558 ff_amf_write_number(&p, ++rt->nb_invokes);
559 ff_amf_write_null(&p);
560 ff_amf_write_string(&p, rt->playpath);
562 return rtmp_send_packet(rt, &pkt, 1);
566 * Generate 'FCPublish' call and send it to the server. It should make
567 * the server preapare for receiving media streams.
569 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
575 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
576 0, 25 + strlen(rt->playpath))) < 0)
579 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
581 ff_amf_write_string(&p, "FCPublish");
582 ff_amf_write_number(&p, ++rt->nb_invokes);
583 ff_amf_write_null(&p);
584 ff_amf_write_string(&p, rt->playpath);
586 return rtmp_send_packet(rt, &pkt, 1);
590 * Generate 'FCUnpublish' call and send it to the server. It should make
591 * the server destroy stream.
593 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
599 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
600 0, 27 + strlen(rt->playpath))) < 0)
603 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
605 ff_amf_write_string(&p, "FCUnpublish");
606 ff_amf_write_number(&p, ++rt->nb_invokes);
607 ff_amf_write_null(&p);
608 ff_amf_write_string(&p, rt->playpath);
610 return rtmp_send_packet(rt, &pkt, 0);
614 * Generate 'createStream' call and send it to the server. It should make
615 * the server allocate some channel for media streams.
617 static int gen_create_stream(URLContext *s, RTMPContext *rt)
623 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
625 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
630 ff_amf_write_string(&p, "createStream");
631 ff_amf_write_number(&p, ++rt->nb_invokes);
632 ff_amf_write_null(&p);
634 return rtmp_send_packet(rt, &pkt, 1);
639 * Generate 'deleteStream' call and send it to the server. It should make
640 * the server remove some channel for media streams.
642 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
648 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
650 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
655 ff_amf_write_string(&p, "deleteStream");
656 ff_amf_write_number(&p, ++rt->nb_invokes);
657 ff_amf_write_null(&p);
658 ff_amf_write_number(&p, rt->main_channel_id);
660 return rtmp_send_packet(rt, &pkt, 0);
664 * Generate client buffer time and send it to the server.
666 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
672 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
677 bytestream_put_be16(&p, 3);
678 bytestream_put_be32(&p, rt->main_channel_id);
679 bytestream_put_be32(&p, rt->client_buffer_time);
681 return rtmp_send_packet(rt, &pkt, 0);
685 * Generate 'play' call and send it to the server, then ping the server
686 * to start actual playing.
688 static int gen_play(URLContext *s, RTMPContext *rt)
694 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
696 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
697 0, 29 + strlen(rt->playpath))) < 0)
700 pkt.extra = rt->main_channel_id;
703 ff_amf_write_string(&p, "play");
704 ff_amf_write_number(&p, ++rt->nb_invokes);
705 ff_amf_write_null(&p);
706 ff_amf_write_string(&p, rt->playpath);
707 ff_amf_write_number(&p, rt->live);
709 return rtmp_send_packet(rt, &pkt, 1);
713 * Generate 'publish' call and send it to the server.
715 static int gen_publish(URLContext *s, RTMPContext *rt)
721 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
723 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
724 0, 30 + strlen(rt->playpath))) < 0)
727 pkt.extra = rt->main_channel_id;
730 ff_amf_write_string(&p, "publish");
731 ff_amf_write_number(&p, ++rt->nb_invokes);
732 ff_amf_write_null(&p);
733 ff_amf_write_string(&p, rt->playpath);
734 ff_amf_write_string(&p, "live");
736 return rtmp_send_packet(rt, &pkt, 1);
740 * Generate ping reply and send it to the server.
742 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
748 if (ppkt->data_size < 6) {
749 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
751 return AVERROR_INVALIDDATA;
754 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
755 ppkt->timestamp + 1, 6)) < 0)
759 bytestream_put_be16(&p, 7);
760 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
762 return rtmp_send_packet(rt, &pkt, 0);
766 * Generate SWF verification message and send it to the server.
768 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
774 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
775 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
780 bytestream_put_be16(&p, 27);
781 memcpy(p, rt->swfverification, 42);
783 return rtmp_send_packet(rt, &pkt, 0);
787 * Generate server bandwidth message and send it to the server.
789 static int gen_server_bw(URLContext *s, RTMPContext *rt)
795 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
800 bytestream_put_be32(&p, rt->server_bw);
802 return rtmp_send_packet(rt, &pkt, 0);
806 * Generate check bandwidth message and send it to the server.
808 static int gen_check_bw(URLContext *s, RTMPContext *rt)
814 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
819 ff_amf_write_string(&p, "_checkbw");
820 ff_amf_write_number(&p, ++rt->nb_invokes);
821 ff_amf_write_null(&p);
823 return rtmp_send_packet(rt, &pkt, 1);
827 * Generate report on bytes read so far and send it to the server.
829 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
835 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
840 bytestream_put_be32(&p, rt->bytes_read);
842 return rtmp_send_packet(rt, &pkt, 0);
845 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
846 const char *subscribe)
852 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
853 0, 27 + strlen(subscribe))) < 0)
857 ff_amf_write_string(&p, "FCSubscribe");
858 ff_amf_write_number(&p, ++rt->nb_invokes);
859 ff_amf_write_null(&p);
860 ff_amf_write_string(&p, subscribe);
862 return rtmp_send_packet(rt, &pkt, 1);
865 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
866 const uint8_t *key, int keylen, uint8_t *dst)
869 uint8_t hmac_buf[64+32] = {0};
872 sha = av_sha_alloc();
874 return AVERROR(ENOMEM);
877 memcpy(hmac_buf, key, keylen);
879 av_sha_init(sha, 256);
880 av_sha_update(sha,key, keylen);
881 av_sha_final(sha, hmac_buf);
883 for (i = 0; i < 64; i++)
884 hmac_buf[i] ^= HMAC_IPAD_VAL;
886 av_sha_init(sha, 256);
887 av_sha_update(sha, hmac_buf, 64);
889 av_sha_update(sha, src, len);
890 } else { //skip 32 bytes used for storing digest
891 av_sha_update(sha, src, gap);
892 av_sha_update(sha, src + gap + 32, len - gap - 32);
894 av_sha_final(sha, hmac_buf + 64);
896 for (i = 0; i < 64; i++)
897 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
898 av_sha_init(sha, 256);
899 av_sha_update(sha, hmac_buf, 64+32);
900 av_sha_final(sha, dst);
907 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
910 int i, digest_pos = 0;
912 for (i = 0; i < 4; i++)
913 digest_pos += buf[i + off];
914 digest_pos = digest_pos % mod_val + add_val;
920 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
921 * will be stored) into that packet.
923 * @param buf handshake data (1536 bytes)
924 * @param encrypted use an encrypted connection (RTMPE)
925 * @return offset to the digest inside input data
927 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
932 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
934 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
936 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
937 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
946 * Verify that the received server response has the expected digest value.
948 * @param buf handshake data received from the server (1536 bytes)
949 * @param off position to search digest offset from
950 * @return 0 if digest is valid, digest position otherwise
952 static int rtmp_validate_digest(uint8_t *buf, int off)
957 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
959 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
960 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
965 if (!memcmp(digest, buf + digest_pos, 32))
970 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
976 if (rt->swfhash_len != 32) {
977 av_log(s, AV_LOG_ERROR,
978 "Hash of the decompressed SWF file is not 32 bytes long.\n");
979 return AVERROR(EINVAL);
982 p = &rt->swfverification[0];
983 bytestream_put_byte(&p, 1);
984 bytestream_put_byte(&p, 1);
985 bytestream_put_be32(&p, rt->swfsize);
986 bytestream_put_be32(&p, rt->swfsize);
988 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
995 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
996 uint8_t **out_data, int64_t *out_size)
1003 zs.avail_in = in_size;
1004 zs.next_in = in_data;
1005 ret = inflateInit(&zs);
1007 return AVERROR_UNKNOWN;
1010 uint8_t tmp_buf[16384];
1012 zs.avail_out = sizeof(tmp_buf);
1013 zs.next_out = tmp_buf;
1015 ret = inflate(&zs, Z_NO_FLUSH);
1016 if (ret != Z_OK && ret != Z_STREAM_END) {
1017 ret = AVERROR_UNKNOWN;
1021 size = sizeof(tmp_buf) - zs.avail_out;
1022 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1023 ret = AVERROR(ENOMEM);
1028 memcpy(*out_data + *out_size, tmp_buf, size);
1030 } while (zs.avail_out == 0);
1038 static int rtmp_calc_swfhash(URLContext *s)
1040 RTMPContext *rt = s->priv_data;
1041 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1042 int64_t in_size, out_size;
1048 /* Get the SWF player file. */
1049 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1050 &s->interrupt_callback, NULL)) < 0) {
1051 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1055 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1060 if (!(in_data = av_malloc(in_size))) {
1061 ret = AVERROR(ENOMEM);
1065 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1069 ret = AVERROR_INVALIDDATA;
1073 if (!memcmp(in_data, "CWS", 3)) {
1074 /* Decompress the SWF player file using Zlib. */
1075 if (!(out_data = av_malloc(8))) {
1076 ret = AVERROR(ENOMEM);
1079 *in_data = 'F'; // magic stuff
1080 memcpy(out_data, in_data, 8);
1084 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1085 &out_data, &out_size)) < 0)
1088 av_log(s, AV_LOG_ERROR,
1089 "Zlib is required for decompressing the SWF player file.\n");
1090 ret = AVERROR(EINVAL);
1100 /* Compute the SHA256 hash of the SWF player file. */
1101 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1102 "Genuine Adobe Flash Player 001", 30,
1106 /* Set SWFVerification parameters. */
1107 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1108 rt->swfsize = swfsize;
1112 av_freep(&out_data);
1113 ffurl_close(stream);
1118 * Perform handshake with the server by means of exchanging pseudorandom data
1119 * signed with HMAC-SHA2 digest.
1121 * @return 0 if handshake succeeds, negative value otherwise
1123 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1126 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1127 3, // unencrypted data
1128 0, 0, 0, 0, // client uptime
1134 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1135 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1137 int server_pos, client_pos;
1138 uint8_t digest[32], signature[32];
1141 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1143 av_lfg_init(&rnd, 0xDEADC0DE);
1144 // generate handshake packet - 1536 bytes of pseudorandom data
1145 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1146 tosend[i] = av_lfg_get(&rnd) >> 24;
1148 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1149 /* When the client wants to use RTMPE, we have to change the command
1150 * byte to 0x06 which means to use encrypted data and we have to set
1151 * the flash version to at least 9.0.115.0. */
1158 /* Initialize the Diffie-Hellmann context and generate the public key
1159 * to send to the server. */
1160 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1164 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1168 if ((ret = ffurl_write(rt->stream, tosend,
1169 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1170 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1174 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1175 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1176 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1180 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1181 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1182 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1186 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1187 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1188 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1190 if (rt->is_input && serverdata[5] >= 3) {
1191 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1197 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1202 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1203 return AVERROR(EIO);
1207 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1208 * key are the last 32 bytes of the server handshake. */
1210 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1211 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1215 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1216 rtmp_server_key, sizeof(rtmp_server_key),
1221 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1222 0, digest, 32, signature);
1226 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1227 /* Compute the shared secret key sent by the server and initialize
1228 * the RC4 encryption. */
1229 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1230 tosend + 1, type)) < 0)
1233 /* Encrypt the signature received by the server. */
1234 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1237 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1238 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1239 return AVERROR(EIO);
1242 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1243 tosend[i] = av_lfg_get(&rnd) >> 24;
1244 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1245 rtmp_player_key, sizeof(rtmp_player_key),
1250 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1252 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1256 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1257 /* Encrypt the signature to be send to the server. */
1258 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1259 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1263 // write reply back to the server
1264 if ((ret = ffurl_write(rt->stream, tosend,
1265 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1268 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1269 /* Set RC4 keys for encryption and update the keystreams. */
1270 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1274 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1275 /* Compute the shared secret key sent by the server and initialize
1276 * the RC4 encryption. */
1277 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1278 tosend + 1, 1)) < 0)
1281 if (serverdata[0] == 9) {
1282 /* Encrypt the signature received by the server. */
1283 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1288 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1289 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1292 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1293 /* Set RC4 keys for encryption and update the keystreams. */
1294 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1302 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1303 uint32_t *second_int, char *arraydata,
1308 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1309 RTMP_HANDSHAKE_PACKET_SIZE);
1311 return AVERROR(EIO);
1312 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1313 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1314 " not following standard\n", (int)inoutsize);
1315 return AVERROR(EINVAL);
1318 *first_int = AV_RB32(arraydata);
1319 *second_int = AV_RB32(arraydata + 4);
1323 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1324 uint32_t second_int, char *arraydata, int size)
1328 AV_WB32(arraydata, first_int);
1329 AV_WB32(arraydata + 4, first_int);
1330 inoutsize = ffurl_write(rt->stream, arraydata,
1331 RTMP_HANDSHAKE_PACKET_SIZE);
1332 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1333 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1334 return AVERROR(EIO);
1341 * rtmp handshake server side
1343 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1345 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1347 uint32_t hs_my_epoch;
1348 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1349 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1356 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1357 if (inoutsize <= 0) {
1358 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1359 return AVERROR(EIO);
1362 if (buffer[0] != 3) {
1363 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1364 return AVERROR(EIO);
1366 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1367 av_log(s, AV_LOG_ERROR,
1368 "Unable to write answer - RTMP S0\n");
1369 return AVERROR(EIO);
1372 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1373 RTMP_HANDSHAKE_PACKET_SIZE);
1375 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1379 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1381 /* By now same epoch will be sent */
1382 hs_my_epoch = hs_epoch;
1383 /* Generate random */
1384 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1386 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1388 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1389 RTMP_HANDSHAKE_PACKET_SIZE);
1391 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1395 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1396 RTMP_HANDSHAKE_PACKET_SIZE);
1398 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1402 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1403 RTMP_HANDSHAKE_PACKET_SIZE);
1405 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1408 if (temp != hs_my_epoch)
1409 av_log(s, AV_LOG_WARNING,
1410 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1411 if (memcmp(buffer + 8, hs_s1 + 8,
1412 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1413 av_log(s, AV_LOG_WARNING,
1414 "Erroneous C2 Message random does not match up\n");
1419 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1421 RTMPContext *rt = s->priv_data;
1424 if (pkt->data_size < 4) {
1425 av_log(s, AV_LOG_ERROR,
1426 "Too short chunk size change packet (%d)\n",
1428 return AVERROR_INVALIDDATA;
1431 if (!rt->is_input) {
1432 /* Send the same chunk size change packet back to the server,
1433 * setting the outgoing chunk size to the same as the incoming one. */
1434 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1435 rt->prev_pkt[1])) < 0)
1437 rt->out_chunk_size = AV_RB32(pkt->data);
1440 rt->in_chunk_size = AV_RB32(pkt->data);
1441 if (rt->in_chunk_size <= 0) {
1442 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1444 return AVERROR_INVALIDDATA;
1446 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1452 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1454 RTMPContext *rt = s->priv_data;
1457 if (pkt->data_size < 2) {
1458 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1460 return AVERROR_INVALIDDATA;
1463 t = AV_RB16(pkt->data);
1465 if ((ret = gen_pong(s, rt, pkt)) < 0)
1467 } else if (t == 26) {
1469 if ((ret = gen_swf_verification(s, rt)) < 0)
1472 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1479 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1481 RTMPContext *rt = s->priv_data;
1483 if (pkt->data_size < 4) {
1484 av_log(s, AV_LOG_ERROR,
1485 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1487 return AVERROR_INVALIDDATA;
1490 rt->client_report_size = AV_RB32(pkt->data);
1491 if (rt->client_report_size <= 0) {
1492 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1493 rt->client_report_size);
1494 return AVERROR_INVALIDDATA;
1497 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1498 rt->client_report_size >>= 1;
1503 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1505 RTMPContext *rt = s->priv_data;
1507 if (pkt->data_size < 4) {
1508 av_log(s, AV_LOG_ERROR,
1509 "Too short server bandwidth report packet (%d)\n",
1511 return AVERROR_INVALIDDATA;
1514 rt->server_bw = AV_RB32(pkt->data);
1515 if (rt->server_bw <= 0) {
1516 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1518 return AVERROR_INVALIDDATA;
1520 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1525 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1526 const char *opaque, const char *challenge)
1529 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1530 struct AVMD5 *md5 = av_md5_alloc();
1532 return AVERROR(ENOMEM);
1534 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1537 av_md5_update(md5, user, strlen(user));
1538 av_md5_update(md5, salt, strlen(salt));
1539 av_md5_update(md5, rt->password, strlen(rt->password));
1540 av_md5_final(md5, hash);
1541 av_base64_encode(hashstr, sizeof(hashstr), hash,
1544 av_md5_update(md5, hashstr, strlen(hashstr));
1546 av_md5_update(md5, opaque, strlen(opaque));
1548 av_md5_update(md5, challenge, strlen(challenge));
1549 av_md5_update(md5, challenge2, strlen(challenge2));
1550 av_md5_final(md5, hash);
1551 av_base64_encode(hashstr, sizeof(hashstr), hash,
1553 snprintf(rt->auth_params, sizeof(rt->auth_params),
1554 "?authmod=%s&user=%s&challenge=%s&response=%s",
1555 "adobe", user, challenge2, hashstr);
1557 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1558 "&opaque=%s", opaque);
1564 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1567 char hashstr1[33], hashstr2[33];
1568 const char *realm = "live";
1569 const char *method = "publish";
1570 const char *qop = "auth";
1571 const char *nc = "00000001";
1573 struct AVMD5 *md5 = av_md5_alloc();
1575 return AVERROR(ENOMEM);
1577 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1580 av_md5_update(md5, user, strlen(user));
1581 av_md5_update(md5, ":", 1);
1582 av_md5_update(md5, realm, strlen(realm));
1583 av_md5_update(md5, ":", 1);
1584 av_md5_update(md5, rt->password, strlen(rt->password));
1585 av_md5_final(md5, hash);
1586 ff_data_to_hex(hashstr1, hash, 16, 1);
1587 hashstr1[32] = '\0';
1590 av_md5_update(md5, method, strlen(method));
1591 av_md5_update(md5, ":/", 2);
1592 av_md5_update(md5, rt->app, strlen(rt->app));
1593 av_md5_final(md5, hash);
1594 ff_data_to_hex(hashstr2, hash, 16, 1);
1595 hashstr2[32] = '\0';
1598 av_md5_update(md5, hashstr1, strlen(hashstr1));
1599 av_md5_update(md5, ":", 1);
1601 av_md5_update(md5, nonce, strlen(nonce));
1602 av_md5_update(md5, ":", 1);
1603 av_md5_update(md5, nc, strlen(nc));
1604 av_md5_update(md5, ":", 1);
1605 av_md5_update(md5, cnonce, strlen(cnonce));
1606 av_md5_update(md5, ":", 1);
1607 av_md5_update(md5, qop, strlen(qop));
1608 av_md5_update(md5, ":", 1);
1609 av_md5_update(md5, hashstr2, strlen(hashstr2));
1610 av_md5_final(md5, hash);
1611 ff_data_to_hex(hashstr1, hash, 16, 1);
1613 snprintf(rt->auth_params, sizeof(rt->auth_params),
1614 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1615 "llnw", user, nonce, cnonce, nc, hashstr1);
1621 static int handle_connect_error(URLContext *s, const char *desc)
1623 RTMPContext *rt = s->priv_data;
1624 char buf[300], *ptr, authmod[15];
1626 const char *user = "", *salt = "", *opaque = NULL,
1627 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1629 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1630 !(cptr = strstr(desc, "authmod=llnw"))) {
1631 av_log(s, AV_LOG_ERROR,
1632 "Unknown connect error (unsupported authentication method?)\n");
1633 return AVERROR_UNKNOWN;
1635 cptr += strlen("authmod=");
1636 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1637 authmod[i++] = *cptr++;
1640 if (!rt->username[0] || !rt->password[0]) {
1641 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1642 return AVERROR_UNKNOWN;
1645 if (strstr(desc, "?reason=authfailed")) {
1646 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1647 return AVERROR_UNKNOWN;
1648 } else if (strstr(desc, "?reason=nosuchuser")) {
1649 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1650 return AVERROR_UNKNOWN;
1653 if (rt->auth_tried) {
1654 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1655 return AVERROR_UNKNOWN;
1658 rt->auth_params[0] = '\0';
1660 if (strstr(desc, "code=403 need auth")) {
1661 snprintf(rt->auth_params, sizeof(rt->auth_params),
1662 "?authmod=%s&user=%s", authmod, rt->username);
1666 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1667 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1668 return AVERROR_UNKNOWN;
1671 av_strlcpy(buf, cptr + 1, sizeof(buf));
1675 char *next = strchr(ptr, '&');
1676 char *value = strchr(ptr, '=');
1681 if (!strcmp(ptr, "user")) {
1683 } else if (!strcmp(ptr, "salt")) {
1685 } else if (!strcmp(ptr, "opaque")) {
1687 } else if (!strcmp(ptr, "challenge")) {
1689 } else if (!strcmp(ptr, "nonce")) {
1695 if (!strcmp(authmod, "adobe")) {
1696 if ((ret = do_adobe_auth(rt, user, salt, challenge, opaque)) < 0)
1699 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1707 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1709 RTMPContext *rt = s->priv_data;
1710 const uint8_t *data_end = pkt->data + pkt->data_size;
1711 char *tracked_method = NULL;
1712 int level = AV_LOG_ERROR;
1713 uint8_t tmpstr[256];
1716 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1719 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1720 "description", tmpstr, sizeof(tmpstr))) {
1721 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1722 !strcmp(tracked_method, "releaseStream") ||
1723 !strcmp(tracked_method, "FCSubscribe") ||
1724 !strcmp(tracked_method, "FCPublish"))) {
1725 /* Gracefully ignore Adobe-specific historical artifact errors. */
1726 level = AV_LOG_WARNING;
1728 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1729 ret = handle_connect_error(s, tmpstr);
1731 rt->do_reconnect = 1;
1732 level = AV_LOG_VERBOSE;
1735 ret = AVERROR_UNKNOWN;
1736 av_log(s, level, "Server error: %s\n", tmpstr);
1739 av_free(tracked_method);
1743 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1745 RTMPContext *rt = s->priv_data;
1749 char statusmsg[128];
1752 const uint8_t *p = pkt->data;
1754 RTMPPacket spkt = { 0 };
1758 bytestream2_init(&gbc, p, pkt->data_size);
1759 if (ff_amf_read_string(&gbc, command, sizeof(command),
1761 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1762 return AVERROR_INVALIDDATA;
1765 ret = ff_amf_read_number(&gbc, &seqnum);
1768 ret = ff_amf_read_null(&gbc);
1771 if (!strcmp(command, "FCPublish") ||
1772 !strcmp(command, "publish")) {
1773 ret = ff_amf_read_string(&gbc, filename,
1774 sizeof(filename), &stringlen);
1777 pchar = strrchr(s->filename, '/');
1779 av_log(s, AV_LOG_WARNING,
1780 "Unable to find / in url %s, bad format\n",
1782 pchar = s->filename;
1785 if (strcmp(pchar, filename))
1786 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1787 " %s\n", filename, pchar);
1789 rt->state = STATE_RECEIVING;
1792 if (!strcmp(command, "FCPublish")) {
1793 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1795 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1796 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1800 ff_amf_write_string(&pp, "onFCPublish");
1801 } else if (!strcmp(command, "publish")) {
1803 // Send Stream Begin 1
1804 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1805 RTMP_PT_PING, 0, 6)) < 0) {
1806 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1810 bytestream2_init_writer(&pbc, pp, spkt.data_size);
1811 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1812 bytestream2_put_be32(&pbc, rt->nb_streamid);
1813 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1815 ff_rtmp_packet_destroy(&spkt);
1819 // Send onStatus(NetStream.Publish.Start)
1820 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1822 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1823 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1826 spkt.extra = pkt->extra;
1828 ff_amf_write_string(&pp, "onStatus");
1829 ff_amf_write_number(&pp, 0);
1830 ff_amf_write_null(&pp);
1832 ff_amf_write_object_start(&pp);
1833 ff_amf_write_field_name(&pp, "level");
1834 ff_amf_write_string(&pp, "status");
1835 ff_amf_write_field_name(&pp, "code");
1836 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1837 ff_amf_write_field_name(&pp, "description");
1838 snprintf(statusmsg, sizeof(statusmsg),
1839 "%s is now published", filename);
1840 ff_amf_write_string(&pp, statusmsg);
1841 ff_amf_write_field_name(&pp, "details");
1842 ff_amf_write_string(&pp, filename);
1843 ff_amf_write_field_name(&pp, "clientid");
1844 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1845 ff_amf_write_string(&pp, statusmsg);
1846 ff_amf_write_object_end(&pp);
1849 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1851 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1852 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1856 ff_amf_write_string(&pp, "_result");
1857 ff_amf_write_number(&pp, seqnum);
1858 ff_amf_write_null(&pp);
1859 if (!strcmp(command, "createStream")) {
1861 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1862 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1863 ff_amf_write_number(&pp, rt->nb_streamid);
1864 /* By now we don't control which streams are removed in
1865 * deleteStream. There is no stream creation control
1866 * if a client creates more than 2^32 - 2 streams. */
1869 spkt.data_size = pp - spkt.data;
1870 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1872 ff_rtmp_packet_destroy(&spkt);
1876 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1878 RTMPContext *rt = s->priv_data;
1879 char *tracked_method = NULL;
1882 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1885 if (!tracked_method) {
1886 /* Ignore this reply when the current method is not tracked. */
1890 if (!memcmp(tracked_method, "connect", 7)) {
1891 if (!rt->is_input) {
1892 if ((ret = gen_release_stream(s, rt)) < 0)
1895 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1898 if ((ret = gen_server_bw(s, rt)) < 0)
1902 if ((ret = gen_create_stream(s, rt)) < 0)
1906 /* Send the FCSubscribe command when the name of live
1907 * stream is defined by the user or if it's a live stream. */
1908 if (rt->subscribe) {
1909 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1911 } else if (rt->live == -1) {
1912 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1916 } else if (!memcmp(tracked_method, "createStream", 12)) {
1917 //extract a number from the result
1918 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1919 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1921 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1924 if (!rt->is_input) {
1925 if ((ret = gen_publish(s, rt)) < 0)
1928 if ((ret = gen_play(s, rt)) < 0)
1930 if ((ret = gen_buffer_time(s, rt)) < 0)
1936 av_free(tracked_method);
1940 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1942 RTMPContext *rt = s->priv_data;
1943 const uint8_t *data_end = pkt->data + pkt->data_size;
1944 const uint8_t *ptr = pkt->data + 11;
1945 uint8_t tmpstr[256];
1948 for (i = 0; i < 2; i++) {
1949 t = ff_amf_tag_size(ptr, data_end);
1955 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1956 if (!t && !strcmp(tmpstr, "error")) {
1957 if (!ff_amf_get_field_value(ptr, data_end,
1958 "description", tmpstr, sizeof(tmpstr)))
1959 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1963 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1964 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1965 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1966 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1967 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1972 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1974 RTMPContext *rt = s->priv_data;
1977 //TODO: check for the messages sent for wrong state?
1978 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1979 if ((ret = handle_invoke_error(s, pkt)) < 0)
1981 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1982 if ((ret = handle_invoke_result(s, pkt)) < 0)
1984 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1985 if ((ret = handle_invoke_status(s, pkt)) < 0)
1987 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1988 if ((ret = gen_check_bw(s, rt)) < 0)
1990 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1991 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
1992 !memcmp(pkt->data, "\002\000\007publish", 10) ||
1993 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
1994 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1995 if (ret = send_invoke_response(s, pkt) < 0)
2002 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2003 RTMPContext *rt = s->priv_data;
2004 const uint8_t *p = NULL;
2006 uint8_t commandbuffer[64];
2007 char statusmsg[128];
2013 const uint8_t *datatowrite;
2014 unsigned datatowritelength;
2017 bytestream2_init(&gbc, p, pkt->data_size);
2018 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2020 return AVERROR_INVALIDDATA;
2021 if (!strcmp(commandbuffer, "@setDataFrame")) {
2022 datatowrite = gbc.buffer;
2023 datatowritelength = bytestream2_get_bytes_left(&gbc);
2024 if (ff_amf_read_string(&gbc, statusmsg,
2025 sizeof(statusmsg), &stringlen))
2026 return AVERROR_INVALIDDATA;
2027 if (strcmp(statusmsg, "onMetaData")) {
2028 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2033 /* Provide ECMAArray to flv */
2034 ts = pkt->timestamp;
2036 // generate packet header and put data into buffer for FLV demuxer
2037 if (rt->flv_off < rt->flv_size) {
2038 old_flv_size = rt->flv_size;
2039 rt->flv_size += datatowritelength + 15;
2042 rt->flv_size = datatowritelength + 15;
2046 cp = av_realloc(rt->flv_data, rt->flv_size);
2048 return AVERROR(ENOMEM);
2050 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2051 bytestream2_skip_p(&pbc, old_flv_size);
2052 bytestream2_put_byte(&pbc, pkt->type);
2053 bytestream2_put_be24(&pbc, datatowritelength);
2054 bytestream2_put_be24(&pbc, ts);
2055 bytestream2_put_byte(&pbc, ts >> 24);
2056 bytestream2_put_be24(&pbc, 0);
2057 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2058 bytestream2_put_be32(&pbc, 0);
2064 * Parse received packet and possibly perform some action depending on
2065 * the packet contents.
2066 * @return 0 for no errors, negative values for serious errors which prevent
2067 * further communications, positive values for uncritical errors
2069 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2074 ff_rtmp_packet_dump(s, pkt);
2077 switch (pkt->type) {
2078 case RTMP_PT_BYTES_READ:
2079 av_dlog(s, "received bytes read report\n");
2081 case RTMP_PT_CHUNK_SIZE:
2082 if ((ret = handle_chunk_size(s, pkt)) < 0)
2086 if ((ret = handle_ping(s, pkt)) < 0)
2089 case RTMP_PT_CLIENT_BW:
2090 if ((ret = handle_client_bw(s, pkt)) < 0)
2093 case RTMP_PT_SERVER_BW:
2094 if ((ret = handle_server_bw(s, pkt)) < 0)
2097 case RTMP_PT_INVOKE:
2098 if ((ret = handle_invoke(s, pkt)) < 0)
2103 case RTMP_PT_METADATA:
2104 case RTMP_PT_NOTIFY:
2105 /* Audio, Video and Metadata packets are parsed in get_packet() */
2108 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2115 * Interact with the server by receiving and sending RTMP packets until
2116 * there is some significant data (media data or expected status notification).
2118 * @param s reading context
2119 * @param for_header non-zero value tells function to work until it
2120 * gets notification from the server that playing has been started,
2121 * otherwise function will work until some media data is received (or
2123 * @return 0 for successful operation, negative value in case of error
2125 static int get_packet(URLContext *s, int for_header)
2127 RTMPContext *rt = s->priv_data;
2130 const uint8_t *next;
2132 uint32_t ts, cts, pts=0;
2134 if (rt->state == STATE_STOPPED)
2138 RTMPPacket rpkt = { 0 };
2139 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2140 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2142 return AVERROR(EAGAIN);
2144 return AVERROR(EIO);
2147 rt->bytes_read += ret;
2148 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2149 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2150 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2152 rt->last_bytes_read = rt->bytes_read;
2155 ret = rtmp_parse_result(s, rt, &rpkt);
2156 if (ret < 0) {//serious error in current packet
2157 ff_rtmp_packet_destroy(&rpkt);
2160 if (rt->do_reconnect && for_header) {
2161 ff_rtmp_packet_destroy(&rpkt);
2164 if (rt->state == STATE_STOPPED) {
2165 ff_rtmp_packet_destroy(&rpkt);
2168 if (for_header && (rt->state == STATE_PLAYING ||
2169 rt->state == STATE_PUBLISHING ||
2170 rt->state == STATE_RECEIVING)) {
2171 ff_rtmp_packet_destroy(&rpkt);
2174 if (!rpkt.data_size || !rt->is_input) {
2175 ff_rtmp_packet_destroy(&rpkt);
2178 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2179 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2180 ts = rpkt.timestamp;
2182 // generate packet header and put data into buffer for FLV demuxer
2184 rt->flv_size = rpkt.data_size + 15;
2185 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2186 bytestream_put_byte(&p, rpkt.type);
2187 bytestream_put_be24(&p, rpkt.data_size);
2188 bytestream_put_be24(&p, ts);
2189 bytestream_put_byte(&p, ts >> 24);
2190 bytestream_put_be24(&p, 0);
2191 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2192 bytestream_put_be32(&p, 0);
2193 ff_rtmp_packet_destroy(&rpkt);
2195 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2196 ret = handle_notify(s, &rpkt);
2197 ff_rtmp_packet_destroy(&rpkt);
2199 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2203 } else if (rpkt.type == RTMP_PT_METADATA) {
2204 // we got raw FLV data, make it available for FLV demuxer
2206 rt->flv_size = rpkt.data_size;
2207 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2208 /* rewrite timestamps */
2210 ts = rpkt.timestamp;
2211 while (next - rpkt.data < rpkt.data_size - 11) {
2213 data_size = bytestream_get_be24(&next);
2215 cts = bytestream_get_be24(&next);
2216 cts |= bytestream_get_byte(&next) << 24;
2221 bytestream_put_be24(&p, ts);
2222 bytestream_put_byte(&p, ts >> 24);
2223 next += data_size + 3 + 4;
2225 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2226 ff_rtmp_packet_destroy(&rpkt);
2229 ff_rtmp_packet_destroy(&rpkt);
2233 static int rtmp_close(URLContext *h)
2235 RTMPContext *rt = h->priv_data;
2238 if (!rt->is_input) {
2239 rt->flv_data = NULL;
2240 if (rt->out_pkt.data_size)
2241 ff_rtmp_packet_destroy(&rt->out_pkt);
2242 if (rt->state > STATE_FCPUBLISH)
2243 ret = gen_fcunpublish_stream(h, rt);
2245 if (rt->state > STATE_HANDSHAKED)
2246 ret = gen_delete_stream(h, rt);
2248 free_tracked_methods(rt);
2249 av_freep(&rt->flv_data);
2250 ffurl_close(rt->stream);
2255 * Open RTMP connection and verify that the stream can be played.
2257 * URL syntax: rtmp://server[:port][/app][/playpath]
2258 * where 'app' is first one or two directories in the path
2259 * (e.g. /ondemand/, /flash/live/, etc.)
2260 * and 'playpath' is a file name (the rest of the path,
2261 * may be prefixed with "mp4:")
2263 static int rtmp_open(URLContext *s, const char *uri, int flags)
2265 RTMPContext *rt = s->priv_data;
2266 char proto[8], hostname[256], path[1024], auth[100], *fname;
2270 AVDictionary *opts = NULL;
2273 if (rt->listen_timeout > 0)
2276 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2278 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2279 hostname, sizeof(hostname), &port,
2280 path, sizeof(path), s->filename);
2283 char *ptr = strchr(auth, ':');
2286 av_strlcpy(rt->username, auth, sizeof(rt->username));
2287 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2291 if (rt->listen && strcmp(proto, "rtmp")) {
2292 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2294 return AVERROR(EINVAL);
2296 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2297 if (!strcmp(proto, "rtmpts"))
2298 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2300 /* open the http tunneling connection */
2301 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2302 } else if (!strcmp(proto, "rtmps")) {
2303 /* open the tls connection */
2305 port = RTMPS_DEFAULT_PORT;
2306 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2307 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2308 if (!strcmp(proto, "rtmpte"))
2309 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2311 /* open the encrypted connection */
2312 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2315 /* open the tcp connection */
2317 port = RTMP_DEFAULT_PORT;
2319 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2320 "?listen&listen_timeout=%d",
2321 rt->listen_timeout * 1000);
2323 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2327 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2328 &s->interrupt_callback, &opts)) < 0) {
2329 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2333 if (rt->swfverify) {
2334 if ((ret = rtmp_calc_swfhash(s)) < 0)
2338 rt->state = STATE_START;
2339 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2341 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2344 rt->out_chunk_size = 128;
2345 rt->in_chunk_size = 128; // Probably overwritten later
2346 rt->state = STATE_HANDSHAKED;
2348 // Keep the application name when it has been defined by the user.
2351 rt->app = av_malloc(APP_MAX_LENGTH);
2353 ret = AVERROR(ENOMEM);
2357 //extract "app" part from path
2358 if (!strncmp(path, "/ondemand/", 10)) {
2360 memcpy(rt->app, "ondemand", 9);
2362 char *next = *path ? path + 1 : path;
2363 char *p = strchr(next, '/');
2368 // make sure we do not mismatch a playpath for an application instance
2369 char *c = strchr(p + 1, ':');
2370 fname = strchr(p + 1, '/');
2371 if (!fname || (c && c < fname)) {
2373 av_strlcpy(rt->app, path + 1, p - path);
2376 av_strlcpy(rt->app, path + 1, fname - path - 1);
2382 // The name of application has been defined by the user, override it.
2387 if (!rt->playpath) {
2388 int len = strlen(fname);
2390 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2391 if (!rt->playpath) {
2392 ret = AVERROR(ENOMEM);
2396 if (!strchr(fname, ':') && len >= 4 &&
2397 (!strcmp(fname + len - 4, ".f4v") ||
2398 !strcmp(fname + len - 4, ".mp4"))) {
2399 memcpy(rt->playpath, "mp4:", 5);
2400 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2401 fname[len - 4] = '\0';
2403 rt->playpath[0] = 0;
2405 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2409 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2411 ret = AVERROR(ENOMEM);
2414 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2415 port, "/%s", rt->app);
2418 if (!rt->flashver) {
2419 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2420 if (!rt->flashver) {
2421 ret = AVERROR(ENOMEM);
2425 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2426 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2427 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2429 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2430 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2434 rt->client_report_size = 1048576;
2436 rt->last_bytes_read = 0;
2437 rt->server_bw = 2500000;
2439 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2440 proto, path, rt->app, rt->playpath);
2442 if ((ret = gen_connect(s, rt)) < 0)
2445 if (read_connect(s, s->priv_data) < 0)
2451 ret = get_packet(s, 1);
2452 } while (ret == EAGAIN);
2456 if (rt->do_reconnect) {
2457 ffurl_close(rt->stream);
2459 rt->do_reconnect = 0;
2461 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2462 free_tracked_methods(rt);
2467 // generate FLV header for demuxer
2469 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2471 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2474 rt->flv_data = NULL;
2476 rt->skip_bytes = 13;
2479 s->max_packet_size = rt->stream->max_packet_size;
2484 av_dict_free(&opts);
2489 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2491 RTMPContext *rt = s->priv_data;
2492 int orig_size = size;
2496 int data_left = rt->flv_size - rt->flv_off;
2498 if (data_left >= size) {
2499 memcpy(buf, rt->flv_data + rt->flv_off, size);
2500 rt->flv_off += size;
2503 if (data_left > 0) {
2504 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2507 rt->flv_off = rt->flv_size;
2510 if ((ret = get_packet(s, 0)) < 0)
2516 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2518 RTMPContext *rt = s->priv_data;
2519 int size_temp = size;
2520 int pktsize, pkttype;
2522 const uint8_t *buf_temp = buf;
2527 if (rt->skip_bytes) {
2528 int skip = FFMIN(rt->skip_bytes, size_temp);
2531 rt->skip_bytes -= skip;
2535 if (rt->flv_header_bytes < 11) {
2536 const uint8_t *header = rt->flv_header;
2537 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2538 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2539 rt->flv_header_bytes += copy;
2541 if (rt->flv_header_bytes < 11)
2544 pkttype = bytestream_get_byte(&header);
2545 pktsize = bytestream_get_be24(&header);
2546 ts = bytestream_get_be24(&header);
2547 ts |= bytestream_get_byte(&header) << 24;
2548 bytestream_get_be24(&header);
2549 rt->flv_size = pktsize;
2551 //force 12bytes header
2552 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2553 pkttype == RTMP_PT_NOTIFY) {
2554 if (pkttype == RTMP_PT_NOTIFY)
2556 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2559 //this can be a big packet, it's better to send it right here
2560 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2561 pkttype, ts, pktsize)) < 0)
2564 rt->out_pkt.extra = rt->main_channel_id;
2565 rt->flv_data = rt->out_pkt.data;
2567 if (pkttype == RTMP_PT_NOTIFY)
2568 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2571 if (rt->flv_size - rt->flv_off > size_temp) {
2572 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2573 rt->flv_off += size_temp;
2576 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2577 size_temp -= rt->flv_size - rt->flv_off;
2578 rt->flv_off += rt->flv_size - rt->flv_off;
2581 if (rt->flv_off == rt->flv_size) {
2584 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2588 rt->flv_header_bytes = 0;
2589 rt->flv_nb_packets++;
2591 } while (buf_temp - buf < size);
2593 if (rt->flv_nb_packets < rt->flush_interval)
2595 rt->flv_nb_packets = 0;
2597 /* set stream into nonblocking mode */
2598 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2600 /* try to read one byte from the stream */
2601 ret = ffurl_read(rt->stream, &c, 1);
2603 /* switch the stream back into blocking mode */
2604 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2606 if (ret == AVERROR(EAGAIN)) {
2607 /* no incoming data to handle */
2609 } else if (ret < 0) {
2611 } else if (ret == 1) {
2612 RTMPPacket rpkt = { 0 };
2614 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2616 rt->prev_pkt[0], c)) <= 0)
2619 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2622 ff_rtmp_packet_destroy(&rpkt);
2628 #define OFFSET(x) offsetof(RTMPContext, x)
2629 #define DEC AV_OPT_FLAG_DECODING_PARAM
2630 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2632 static const AVOption rtmp_options[] = {
2633 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2634 {"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},
2635 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2636 {"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},
2637 {"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},
2638 {"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"},
2639 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2640 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2641 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2642 {"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},
2643 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2644 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2645 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2646 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2647 {"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},
2648 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2649 {"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},
2650 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2651 {"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" },
2655 #define RTMP_PROTOCOL(flavor) \
2656 static const AVClass flavor##_class = { \
2657 .class_name = #flavor, \
2658 .item_name = av_default_item_name, \
2659 .option = rtmp_options, \
2660 .version = LIBAVUTIL_VERSION_INT, \
2663 URLProtocol ff_##flavor##_protocol = { \
2665 .url_open = rtmp_open, \
2666 .url_read = rtmp_read, \
2667 .url_write = rtmp_write, \
2668 .url_close = rtmp_close, \
2669 .priv_data_size = sizeof(RTMPContext), \
2670 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2671 .priv_data_class= &flavor##_class, \
2676 RTMP_PROTOCOL(rtmpe)
2677 RTMP_PROTOCOL(rtmps)
2678 RTMP_PROTOCOL(rtmpt)
2679 RTMP_PROTOCOL(rtmpte)
2680 RTMP_PROTOCOL(rtmpts)