2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 128
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
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_PUBLISHING, ///< client has started sending multimedia data to server (for output)
64 STATE_RECEIVING, ///< received a publish command (for input)
65 STATE_STOPPED, ///< the broadcast has been stopped
68 typedef struct TrackedMethod {
73 /** protocol handler context */
74 typedef struct RTMPContext {
76 URLContext* stream; ///< TCP stream used in interactions with RTMP server
77 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
78 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
79 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
80 int is_input; ///< input/output flag
81 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
82 int live; ///< 0: recorded, -1: live, -2: both
83 char *app; ///< name of application
84 char *conn; ///< append arbitrary AMF data to the Connect message
85 ClientState state; ///< current state
86 int main_channel_id; ///< an additional channel ID which is used for some invocations
87 uint8_t* flv_data; ///< buffer with data for demuxer
88 int flv_size; ///< current buffer size
89 int flv_off; ///< number of bytes read from current buffer
90 int flv_nb_packets; ///< number of flv packets published
91 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
92 uint32_t client_report_size; ///< number of bytes after which client should report to server
93 uint32_t bytes_read; ///< number of bytes read from server
94 uint32_t last_bytes_read; ///< number of bytes read last reported to server
95 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
96 uint8_t flv_header[11]; ///< partial incoming flv packet header
97 int flv_header_bytes; ///< number of initialized bytes in flv_header
98 int nb_invokes; ///< keeps track of invoke messages
99 char* tcurl; ///< url of the target stream
100 char* flashver; ///< version of the flash plugin
101 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
102 int swfhash_len; ///< length of the SHA256 hash
103 int swfsize; ///< size of the decompressed SWF file
104 char* swfurl; ///< url of the swf player
105 char* swfverify; ///< URL to player swf file, compute hash/size automatically
106 char swfverification[42]; ///< hash of the SWF verification
107 char* pageurl; ///< url of the web page
108 char* subscribe; ///< name of live stream to subscribe
109 int server_bw; ///< server bandwidth
110 int client_buffer_time; ///< client buffer time in ms
111 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
112 int encrypted; ///< use an encrypted connection (RTMPE only)
113 TrackedMethod*tracked_methods; ///< tracked methods buffer
114 int nb_tracked_methods; ///< number of tracked methods
115 int tracked_methods_size; ///< size of the tracked methods buffer
116 int listen; ///< listen mode flag
117 int listen_timeout; ///< listen timeout to wait for new connections
118 int nb_streamid; ///< The next stream id to return on createStream calls
121 char auth_params[500];
126 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
127 /** Client key used for digest signing */
128 static const uint8_t rtmp_player_key[] = {
129 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
130 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
132 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
133 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
134 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
137 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
138 /** Key used for RTMP server digest signing */
139 static const uint8_t rtmp_server_key[] = {
140 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
141 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
142 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
144 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
145 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
146 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
149 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
153 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
154 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
155 ptr = av_realloc(rt->tracked_methods,
156 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
158 return AVERROR(ENOMEM);
159 rt->tracked_methods = ptr;
162 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
163 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
164 return AVERROR(ENOMEM);
165 rt->tracked_methods[rt->nb_tracked_methods].id = id;
166 rt->nb_tracked_methods++;
171 static void del_tracked_method(RTMPContext *rt, int index)
173 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
174 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
175 rt->nb_tracked_methods--;
178 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
179 char **tracked_method)
181 RTMPContext *rt = s->priv_data;
187 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
188 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
191 for (i = 0; i < rt->nb_tracked_methods; i++) {
192 if (rt->tracked_methods[i].id != pkt_id)
195 *tracked_method = rt->tracked_methods[i].name;
196 del_tracked_method(rt, i);
203 static void free_tracked_methods(RTMPContext *rt)
207 for (i = 0; i < rt->nb_tracked_methods; i ++)
208 av_free(rt->tracked_methods[i].name);
209 av_free(rt->tracked_methods);
210 rt->tracked_methods = NULL;
211 rt->tracked_methods_size = 0;
212 rt->nb_tracked_methods = 0;
215 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
219 if (pkt->type == RTMP_PT_INVOKE && track) {
225 bytestream2_init(&gbc, pkt->data, pkt->data_size);
226 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
229 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
232 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
236 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
239 ff_rtmp_packet_destroy(pkt);
243 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
248 /* The type must be B for Boolean, N for number, S for string, O for
249 * object, or Z for null. For Booleans the data must be either 0 or 1 for
250 * FALSE or TRUE, respectively. Likewise for Objects the data must be
251 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
252 * may be named, by prefixing the type with 'N' and specifying the name
253 * before the value (ie. NB:myFlag:1). This option may be used multiple times
254 * to construct arbitrary AMF sequences. */
255 if (param[0] && param[1] == ':') {
258 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
261 value = strchr(field, ':');
267 if (!field || !value)
270 ff_amf_write_field_name(p, field);
277 ff_amf_write_bool(p, value[0] != '0');
280 ff_amf_write_string(p, value);
283 ff_amf_write_number(p, strtod(value, NULL));
286 ff_amf_write_null(p);
290 ff_amf_write_object_start(p);
292 ff_amf_write_object_end(p);
302 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
303 return AVERROR(EINVAL);
307 * Generate 'connect' call and send it to the server.
309 static int gen_connect(URLContext *s, RTMPContext *rt)
315 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
321 ff_amf_write_string(&p, "connect");
322 ff_amf_write_number(&p, ++rt->nb_invokes);
323 ff_amf_write_object_start(&p);
324 ff_amf_write_field_name(&p, "app");
325 ff_amf_write_string2(&p, rt->app, rt->auth_params);
328 ff_amf_write_field_name(&p, "type");
329 ff_amf_write_string(&p, "nonprivate");
331 ff_amf_write_field_name(&p, "flashVer");
332 ff_amf_write_string(&p, rt->flashver);
335 ff_amf_write_field_name(&p, "swfUrl");
336 ff_amf_write_string(&p, rt->swfurl);
339 ff_amf_write_field_name(&p, "tcUrl");
340 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
342 ff_amf_write_field_name(&p, "fpad");
343 ff_amf_write_bool(&p, 0);
344 ff_amf_write_field_name(&p, "capabilities");
345 ff_amf_write_number(&p, 15.0);
347 /* Tell the server we support all the audio codecs except
348 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
349 * which are unused in the RTMP protocol implementation. */
350 ff_amf_write_field_name(&p, "audioCodecs");
351 ff_amf_write_number(&p, 4071.0);
352 ff_amf_write_field_name(&p, "videoCodecs");
353 ff_amf_write_number(&p, 252.0);
354 ff_amf_write_field_name(&p, "videoFunction");
355 ff_amf_write_number(&p, 1.0);
358 ff_amf_write_field_name(&p, "pageUrl");
359 ff_amf_write_string(&p, rt->pageurl);
362 ff_amf_write_object_end(&p);
365 char *param = rt->conn;
367 // Write arbitrary AMF data to the Connect message.
368 while (param != NULL) {
370 param += strspn(param, " ");
373 sep = strchr(param, ' ');
376 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
377 // Invalid AMF parameter.
378 ff_rtmp_packet_destroy(&pkt);
389 pkt.data_size = p - pkt.data;
391 return rtmp_send_packet(rt, &pkt, 1);
394 static int read_connect(URLContext *s, RTMPContext *rt)
396 RTMPPacket pkt = { 0 };
406 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
407 rt->prev_pkt[1])) < 0)
410 bytestream2_init(&gbc, cp, pkt.data_size);
411 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
412 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
413 ff_rtmp_packet_destroy(&pkt);
414 return AVERROR_INVALIDDATA;
416 if (strcmp(command, "connect")) {
417 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
418 ff_rtmp_packet_destroy(&pkt);
419 return AVERROR_INVALIDDATA;
421 ret = ff_amf_read_number(&gbc, &seqnum);
423 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
424 /* Here one could parse an AMF Object with data as flashVers and others. */
425 ret = ff_amf_get_field_value(gbc.buffer,
426 gbc.buffer + bytestream2_get_bytes_left(&gbc),
427 "app", tmpstr, sizeof(tmpstr));
429 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
430 if (!ret && strcmp(tmpstr, rt->app))
431 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
433 ff_rtmp_packet_destroy(&pkt);
435 // Send Window Acknowledgement Size (as defined in speficication)
436 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
437 RTMP_PT_SERVER_BW, 0, 4)) < 0)
440 bytestream_put_be32(&p, rt->server_bw);
441 pkt.data_size = p - pkt.data;
442 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
444 ff_rtmp_packet_destroy(&pkt);
447 // Send Peer Bandwidth
448 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
449 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
452 bytestream_put_be32(&p, rt->server_bw);
453 bytestream_put_byte(&p, 2); // dynamic
454 pkt.data_size = p - pkt.data;
455 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
457 ff_rtmp_packet_destroy(&pkt);
462 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
463 RTMP_PT_PING, 0, 6)) < 0)
467 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
468 bytestream_put_be32(&p, 0);
469 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
471 ff_rtmp_packet_destroy(&pkt);
476 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
477 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
481 bytestream_put_be32(&p, rt->out_chunk_size);
482 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
484 ff_rtmp_packet_destroy(&pkt);
488 // Send result_ NetConnection.Connect.Success to connect
489 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
491 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
495 ff_amf_write_string(&p, "_result");
496 ff_amf_write_number(&p, seqnum);
498 ff_amf_write_object_start(&p);
499 ff_amf_write_field_name(&p, "fmsVer");
500 ff_amf_write_string(&p, "FMS/3,0,1,123");
501 ff_amf_write_field_name(&p, "capabilities");
502 ff_amf_write_number(&p, 31);
503 ff_amf_write_object_end(&p);
505 ff_amf_write_object_start(&p);
506 ff_amf_write_field_name(&p, "level");
507 ff_amf_write_string(&p, "status");
508 ff_amf_write_field_name(&p, "code");
509 ff_amf_write_string(&p, "NetConnection.Connect.Success");
510 ff_amf_write_field_name(&p, "description");
511 ff_amf_write_string(&p, "Connection succeeded.");
512 ff_amf_write_field_name(&p, "objectEncoding");
513 ff_amf_write_number(&p, 0);
514 ff_amf_write_object_end(&p);
516 pkt.data_size = p - pkt.data;
517 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
519 ff_rtmp_packet_destroy(&pkt);
523 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
524 RTMP_PT_INVOKE, 0, 30)) < 0)
527 ff_amf_write_string(&p, "onBWDone");
528 ff_amf_write_number(&p, 0);
529 ff_amf_write_null(&p);
530 ff_amf_write_number(&p, 8192);
531 pkt.data_size = p - pkt.data;
532 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
534 ff_rtmp_packet_destroy(&pkt);
540 * Generate 'releaseStream' call and send it to the server. It should make
541 * the server release some channel for media streams.
543 static int gen_release_stream(URLContext *s, RTMPContext *rt)
549 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
550 0, 29 + strlen(rt->playpath))) < 0)
553 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
555 ff_amf_write_string(&p, "releaseStream");
556 ff_amf_write_number(&p, ++rt->nb_invokes);
557 ff_amf_write_null(&p);
558 ff_amf_write_string(&p, rt->playpath);
560 return rtmp_send_packet(rt, &pkt, 1);
564 * Generate 'FCPublish' call and send it to the server. It should make
565 * the server preapare for receiving media streams.
567 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
573 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
574 0, 25 + strlen(rt->playpath))) < 0)
577 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
579 ff_amf_write_string(&p, "FCPublish");
580 ff_amf_write_number(&p, ++rt->nb_invokes);
581 ff_amf_write_null(&p);
582 ff_amf_write_string(&p, rt->playpath);
584 return rtmp_send_packet(rt, &pkt, 1);
588 * Generate 'FCUnpublish' call and send it to the server. It should make
589 * the server destroy stream.
591 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
597 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
598 0, 27 + strlen(rt->playpath))) < 0)
601 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
603 ff_amf_write_string(&p, "FCUnpublish");
604 ff_amf_write_number(&p, ++rt->nb_invokes);
605 ff_amf_write_null(&p);
606 ff_amf_write_string(&p, rt->playpath);
608 return rtmp_send_packet(rt, &pkt, 0);
612 * Generate 'createStream' call and send it to the server. It should make
613 * the server allocate some channel for media streams.
615 static int gen_create_stream(URLContext *s, RTMPContext *rt)
621 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
623 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
628 ff_amf_write_string(&p, "createStream");
629 ff_amf_write_number(&p, ++rt->nb_invokes);
630 ff_amf_write_null(&p);
632 return rtmp_send_packet(rt, &pkt, 1);
637 * Generate 'deleteStream' call and send it to the server. It should make
638 * the server remove some channel for media streams.
640 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
646 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
648 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
653 ff_amf_write_string(&p, "deleteStream");
654 ff_amf_write_number(&p, ++rt->nb_invokes);
655 ff_amf_write_null(&p);
656 ff_amf_write_number(&p, rt->main_channel_id);
658 return rtmp_send_packet(rt, &pkt, 0);
662 * Generate client buffer time and send it to the server.
664 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
670 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
675 bytestream_put_be16(&p, 3);
676 bytestream_put_be32(&p, rt->main_channel_id);
677 bytestream_put_be32(&p, rt->client_buffer_time);
679 return rtmp_send_packet(rt, &pkt, 0);
683 * Generate 'play' call and send it to the server, then ping the server
684 * to start actual playing.
686 static int gen_play(URLContext *s, RTMPContext *rt)
692 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
694 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
695 0, 29 + strlen(rt->playpath))) < 0)
698 pkt.extra = rt->main_channel_id;
701 ff_amf_write_string(&p, "play");
702 ff_amf_write_number(&p, ++rt->nb_invokes);
703 ff_amf_write_null(&p);
704 ff_amf_write_string(&p, rt->playpath);
705 ff_amf_write_number(&p, rt->live);
707 return rtmp_send_packet(rt, &pkt, 1);
711 * Generate 'publish' call and send it to the server.
713 static int gen_publish(URLContext *s, RTMPContext *rt)
719 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
721 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
722 0, 30 + strlen(rt->playpath))) < 0)
725 pkt.extra = rt->main_channel_id;
728 ff_amf_write_string(&p, "publish");
729 ff_amf_write_number(&p, ++rt->nb_invokes);
730 ff_amf_write_null(&p);
731 ff_amf_write_string(&p, rt->playpath);
732 ff_amf_write_string(&p, "live");
734 return rtmp_send_packet(rt, &pkt, 1);
738 * Generate ping reply and send it to the server.
740 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
746 if (ppkt->data_size < 6) {
747 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
749 return AVERROR_INVALIDDATA;
752 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
753 ppkt->timestamp + 1, 6)) < 0)
757 bytestream_put_be16(&p, 7);
758 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
760 return rtmp_send_packet(rt, &pkt, 0);
764 * Generate SWF verification message and send it to the server.
766 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
772 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
773 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
778 bytestream_put_be16(&p, 27);
779 memcpy(p, rt->swfverification, 42);
781 return rtmp_send_packet(rt, &pkt, 0);
785 * Generate server bandwidth message and send it to the server.
787 static int gen_server_bw(URLContext *s, RTMPContext *rt)
793 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
798 bytestream_put_be32(&p, rt->server_bw);
800 return rtmp_send_packet(rt, &pkt, 0);
804 * Generate check bandwidth message and send it to the server.
806 static int gen_check_bw(URLContext *s, RTMPContext *rt)
812 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
817 ff_amf_write_string(&p, "_checkbw");
818 ff_amf_write_number(&p, ++rt->nb_invokes);
819 ff_amf_write_null(&p);
821 return rtmp_send_packet(rt, &pkt, 1);
825 * Generate report on bytes read so far and send it to the server.
827 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
833 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
838 bytestream_put_be32(&p, rt->bytes_read);
840 return rtmp_send_packet(rt, &pkt, 0);
843 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
844 const char *subscribe)
850 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
851 0, 27 + strlen(subscribe))) < 0)
855 ff_amf_write_string(&p, "FCSubscribe");
856 ff_amf_write_number(&p, ++rt->nb_invokes);
857 ff_amf_write_null(&p);
858 ff_amf_write_string(&p, subscribe);
860 return rtmp_send_packet(rt, &pkt, 1);
863 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
864 const uint8_t *key, int keylen, uint8_t *dst)
867 uint8_t hmac_buf[64+32] = {0};
870 sha = av_sha_alloc();
872 return AVERROR(ENOMEM);
875 memcpy(hmac_buf, key, keylen);
877 av_sha_init(sha, 256);
878 av_sha_update(sha,key, keylen);
879 av_sha_final(sha, hmac_buf);
881 for (i = 0; i < 64; i++)
882 hmac_buf[i] ^= HMAC_IPAD_VAL;
884 av_sha_init(sha, 256);
885 av_sha_update(sha, hmac_buf, 64);
887 av_sha_update(sha, src, len);
888 } else { //skip 32 bytes used for storing digest
889 av_sha_update(sha, src, gap);
890 av_sha_update(sha, src + gap + 32, len - gap - 32);
892 av_sha_final(sha, hmac_buf + 64);
894 for (i = 0; i < 64; i++)
895 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
896 av_sha_init(sha, 256);
897 av_sha_update(sha, hmac_buf, 64+32);
898 av_sha_final(sha, dst);
905 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
908 int i, digest_pos = 0;
910 for (i = 0; i < 4; i++)
911 digest_pos += buf[i + off];
912 digest_pos = digest_pos % mod_val + add_val;
918 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
919 * will be stored) into that packet.
921 * @param buf handshake data (1536 bytes)
922 * @param encrypted use an encrypted connection (RTMPE)
923 * @return offset to the digest inside input data
925 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
930 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
932 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
934 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
935 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
944 * Verify that the received server response has the expected digest value.
946 * @param buf handshake data received from the server (1536 bytes)
947 * @param off position to search digest offset from
948 * @return 0 if digest is valid, digest position otherwise
950 static int rtmp_validate_digest(uint8_t *buf, int off)
955 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
957 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
958 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
963 if (!memcmp(digest, buf + digest_pos, 32))
968 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
974 if (rt->swfhash_len != 32) {
975 av_log(s, AV_LOG_ERROR,
976 "Hash of the decompressed SWF file is not 32 bytes long.\n");
977 return AVERROR(EINVAL);
980 p = &rt->swfverification[0];
981 bytestream_put_byte(&p, 1);
982 bytestream_put_byte(&p, 1);
983 bytestream_put_be32(&p, rt->swfsize);
984 bytestream_put_be32(&p, rt->swfsize);
986 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
993 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
994 uint8_t **out_data, int64_t *out_size)
1001 zs.avail_in = in_size;
1002 zs.next_in = in_data;
1003 ret = inflateInit(&zs);
1005 return AVERROR_UNKNOWN;
1008 uint8_t tmp_buf[16384];
1010 zs.avail_out = sizeof(tmp_buf);
1011 zs.next_out = tmp_buf;
1013 ret = inflate(&zs, Z_NO_FLUSH);
1014 if (ret != Z_OK && ret != Z_STREAM_END) {
1015 ret = AVERROR_UNKNOWN;
1019 size = sizeof(tmp_buf) - zs.avail_out;
1020 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1021 ret = AVERROR(ENOMEM);
1026 memcpy(*out_data + *out_size, tmp_buf, size);
1028 } while (zs.avail_out == 0);
1036 static int rtmp_calc_swfhash(URLContext *s)
1038 RTMPContext *rt = s->priv_data;
1039 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1040 int64_t in_size, out_size;
1046 /* Get the SWF player file. */
1047 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1048 &s->interrupt_callback, NULL)) < 0) {
1049 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1053 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1058 if (!(in_data = av_malloc(in_size))) {
1059 ret = AVERROR(ENOMEM);
1063 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1067 ret = AVERROR_INVALIDDATA;
1071 if (!memcmp(in_data, "CWS", 3)) {
1072 /* Decompress the SWF player file using Zlib. */
1073 if (!(out_data = av_malloc(8))) {
1074 ret = AVERROR(ENOMEM);
1077 *in_data = 'F'; // magic stuff
1078 memcpy(out_data, in_data, 8);
1082 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1083 &out_data, &out_size)) < 0)
1086 av_log(s, AV_LOG_ERROR,
1087 "Zlib is required for decompressing the SWF player file.\n");
1088 ret = AVERROR(EINVAL);
1098 /* Compute the SHA256 hash of the SWF player file. */
1099 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1100 "Genuine Adobe Flash Player 001", 30,
1104 /* Set SWFVerification parameters. */
1105 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1106 rt->swfsize = swfsize;
1110 av_freep(&out_data);
1111 ffurl_close(stream);
1116 * Perform handshake with the server by means of exchanging pseudorandom data
1117 * signed with HMAC-SHA2 digest.
1119 * @return 0 if handshake succeeds, negative value otherwise
1121 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1124 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1125 3, // unencrypted data
1126 0, 0, 0, 0, // client uptime
1132 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1133 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1135 int server_pos, client_pos;
1136 uint8_t digest[32], signature[32];
1139 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1141 av_lfg_init(&rnd, 0xDEADC0DE);
1142 // generate handshake packet - 1536 bytes of pseudorandom data
1143 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1144 tosend[i] = av_lfg_get(&rnd) >> 24;
1146 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1147 /* When the client wants to use RTMPE, we have to change the command
1148 * byte to 0x06 which means to use encrypted data and we have to set
1149 * the flash version to at least 9.0.115.0. */
1156 /* Initialize the Diffie-Hellmann context and generate the public key
1157 * to send to the server. */
1158 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1162 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1166 if ((ret = ffurl_write(rt->stream, tosend,
1167 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1168 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1172 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1173 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1174 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1178 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1179 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1180 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1184 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1185 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1186 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1188 if (rt->is_input && serverdata[5] >= 3) {
1189 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1195 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1200 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1201 return AVERROR(EIO);
1205 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1206 * key are the last 32 bytes of the server handshake. */
1208 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1209 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1213 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1214 rtmp_server_key, sizeof(rtmp_server_key),
1219 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1220 0, digest, 32, signature);
1224 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1225 /* Compute the shared secret key sent by the server and initialize
1226 * the RC4 encryption. */
1227 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1228 tosend + 1, type)) < 0)
1231 /* Encrypt the signature received by the server. */
1232 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1235 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1236 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1237 return AVERROR(EIO);
1240 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1241 tosend[i] = av_lfg_get(&rnd) >> 24;
1242 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1243 rtmp_player_key, sizeof(rtmp_player_key),
1248 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1250 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1254 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1255 /* Encrypt the signature to be send to the server. */
1256 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1257 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1261 // write reply back to the server
1262 if ((ret = ffurl_write(rt->stream, tosend,
1263 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1266 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1267 /* Set RC4 keys for encryption and update the keystreams. */
1268 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1272 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1273 /* Compute the shared secret key sent by the server and initialize
1274 * the RC4 encryption. */
1275 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1276 tosend + 1, 1)) < 0)
1279 if (serverdata[0] == 9) {
1280 /* Encrypt the signature received by the server. */
1281 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1286 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1287 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1290 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1291 /* Set RC4 keys for encryption and update the keystreams. */
1292 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1300 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1301 uint32_t *second_int, char *arraydata,
1306 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1307 RTMP_HANDSHAKE_PACKET_SIZE);
1309 return AVERROR(EIO);
1310 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1311 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1312 " not following standard\n", (int)inoutsize);
1313 return AVERROR(EINVAL);
1316 *first_int = AV_RB32(arraydata);
1317 *second_int = AV_RB32(arraydata + 4);
1321 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1322 uint32_t second_int, char *arraydata, int size)
1326 AV_WB32(arraydata, first_int);
1327 AV_WB32(arraydata + 4, first_int);
1328 inoutsize = ffurl_write(rt->stream, arraydata,
1329 RTMP_HANDSHAKE_PACKET_SIZE);
1330 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1331 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1332 return AVERROR(EIO);
1339 * rtmp handshake server side
1341 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1343 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1345 uint32_t hs_my_epoch;
1346 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1347 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1354 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1355 if (inoutsize <= 0) {
1356 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1357 return AVERROR(EIO);
1360 if (buffer[0] != 3) {
1361 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1362 return AVERROR(EIO);
1364 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1365 av_log(s, AV_LOG_ERROR,
1366 "Unable to write answer - RTMP S0\n");
1367 return AVERROR(EIO);
1370 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1371 RTMP_HANDSHAKE_PACKET_SIZE);
1373 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1377 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1379 /* By now same epoch will be sent */
1380 hs_my_epoch = hs_epoch;
1381 /* Generate random */
1382 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1384 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1386 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1387 RTMP_HANDSHAKE_PACKET_SIZE);
1389 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1393 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1394 RTMP_HANDSHAKE_PACKET_SIZE);
1396 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1400 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1401 RTMP_HANDSHAKE_PACKET_SIZE);
1403 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1406 if (temp != hs_my_epoch)
1407 av_log(s, AV_LOG_WARNING,
1408 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1409 if (memcmp(buffer + 8, hs_s1 + 8,
1410 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1411 av_log(s, AV_LOG_WARNING,
1412 "Erroneous C2 Message random does not match up\n");
1417 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1419 RTMPContext *rt = s->priv_data;
1422 if (pkt->data_size < 4) {
1423 av_log(s, AV_LOG_ERROR,
1424 "Too short chunk size change packet (%d)\n",
1426 return AVERROR_INVALIDDATA;
1429 if (!rt->is_input) {
1430 /* Send the same chunk size change packet back to the server,
1431 * setting the outgoing chunk size to the same as the incoming one. */
1432 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1433 rt->prev_pkt[1])) < 0)
1435 rt->out_chunk_size = AV_RB32(pkt->data);
1438 rt->in_chunk_size = AV_RB32(pkt->data);
1439 if (rt->in_chunk_size <= 0) {
1440 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1442 return AVERROR_INVALIDDATA;
1444 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1450 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1452 RTMPContext *rt = s->priv_data;
1455 if (pkt->data_size < 2) {
1456 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1458 return AVERROR_INVALIDDATA;
1461 t = AV_RB16(pkt->data);
1463 if ((ret = gen_pong(s, rt, pkt)) < 0)
1465 } else if (t == 26) {
1467 if ((ret = gen_swf_verification(s, rt)) < 0)
1470 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1477 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1479 RTMPContext *rt = s->priv_data;
1481 if (pkt->data_size < 4) {
1482 av_log(s, AV_LOG_ERROR,
1483 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1485 return AVERROR_INVALIDDATA;
1488 rt->client_report_size = AV_RB32(pkt->data);
1489 if (rt->client_report_size <= 0) {
1490 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1491 rt->client_report_size);
1492 return AVERROR_INVALIDDATA;
1495 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1496 rt->client_report_size >>= 1;
1501 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1503 RTMPContext *rt = s->priv_data;
1505 if (pkt->data_size < 4) {
1506 av_log(s, AV_LOG_ERROR,
1507 "Too short server bandwidth report packet (%d)\n",
1509 return AVERROR_INVALIDDATA;
1512 rt->server_bw = AV_RB32(pkt->data);
1513 if (rt->server_bw <= 0) {
1514 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1516 return AVERROR_INVALIDDATA;
1518 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1523 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1524 const char *opaque, const char *challenge)
1527 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1528 struct AVMD5 *md5 = av_md5_alloc();
1530 return AVERROR(ENOMEM);
1532 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1535 av_md5_update(md5, user, strlen(user));
1536 av_md5_update(md5, salt, strlen(salt));
1537 av_md5_update(md5, rt->password, strlen(rt->password));
1538 av_md5_final(md5, hash);
1539 av_base64_encode(hashstr, sizeof(hashstr), hash,
1542 av_md5_update(md5, hashstr, strlen(hashstr));
1544 av_md5_update(md5, opaque, strlen(opaque));
1546 av_md5_update(md5, challenge, strlen(challenge));
1547 av_md5_update(md5, challenge2, strlen(challenge2));
1548 av_md5_final(md5, hash);
1549 av_base64_encode(hashstr, sizeof(hashstr), hash,
1551 snprintf(rt->auth_params, sizeof(rt->auth_params),
1552 "?authmod=%s&user=%s&challenge=%s&response=%s",
1553 "adobe", user, challenge2, hashstr);
1555 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1556 "&opaque=%s", opaque);
1562 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1565 char hashstr1[33], hashstr2[33];
1566 const char *realm = "live";
1567 const char *method = "publish";
1568 const char *qop = "auth";
1569 const char *nc = "00000001";
1571 struct AVMD5 *md5 = av_md5_alloc();
1573 return AVERROR(ENOMEM);
1575 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1578 av_md5_update(md5, user, strlen(user));
1579 av_md5_update(md5, ":", 1);
1580 av_md5_update(md5, realm, strlen(realm));
1581 av_md5_update(md5, ":", 1);
1582 av_md5_update(md5, rt->password, strlen(rt->password));
1583 av_md5_final(md5, hash);
1584 ff_data_to_hex(hashstr1, hash, 16, 1);
1585 hashstr1[32] = '\0';
1588 av_md5_update(md5, method, strlen(method));
1589 av_md5_update(md5, ":/", 2);
1590 av_md5_update(md5, rt->app, strlen(rt->app));
1591 av_md5_final(md5, hash);
1592 ff_data_to_hex(hashstr2, hash, 16, 1);
1593 hashstr2[32] = '\0';
1596 av_md5_update(md5, hashstr1, strlen(hashstr1));
1597 av_md5_update(md5, ":", 1);
1599 av_md5_update(md5, nonce, strlen(nonce));
1600 av_md5_update(md5, ":", 1);
1601 av_md5_update(md5, nc, strlen(nc));
1602 av_md5_update(md5, ":", 1);
1603 av_md5_update(md5, cnonce, strlen(cnonce));
1604 av_md5_update(md5, ":", 1);
1605 av_md5_update(md5, qop, strlen(qop));
1606 av_md5_update(md5, ":", 1);
1607 av_md5_update(md5, hashstr2, strlen(hashstr2));
1608 av_md5_final(md5, hash);
1609 ff_data_to_hex(hashstr1, hash, 16, 1);
1611 snprintf(rt->auth_params, sizeof(rt->auth_params),
1612 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1613 "llnw", user, nonce, cnonce, nc, hashstr1);
1619 static int handle_connect_error(URLContext *s, const char *desc)
1621 RTMPContext *rt = s->priv_data;
1622 char buf[300], *ptr, authmod[15];
1624 const char *user = "", *salt = "", *opaque = NULL,
1625 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1627 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1628 !(cptr = strstr(desc, "authmod=llnw"))) {
1629 av_log(s, AV_LOG_ERROR,
1630 "Unknown connect error (unsupported authentication method?)\n");
1631 return AVERROR_UNKNOWN;
1633 cptr += strlen("authmod=");
1634 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1635 authmod[i++] = *cptr++;
1638 if (!rt->username[0] || !rt->password[0]) {
1639 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1640 return AVERROR_UNKNOWN;
1643 if (strstr(desc, "?reason=authfailed")) {
1644 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1645 return AVERROR_UNKNOWN;
1646 } else if (strstr(desc, "?reason=nosuchuser")) {
1647 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1648 return AVERROR_UNKNOWN;
1651 if (rt->auth_tried) {
1652 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1653 return AVERROR_UNKNOWN;
1656 rt->auth_params[0] = '\0';
1658 if (strstr(desc, "code=403 need auth")) {
1659 snprintf(rt->auth_params, sizeof(rt->auth_params),
1660 "?authmod=%s&user=%s", authmod, rt->username);
1664 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1665 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1666 return AVERROR_UNKNOWN;
1669 av_strlcpy(buf, cptr + 1, sizeof(buf));
1673 char *next = strchr(ptr, '&');
1674 char *value = strchr(ptr, '=');
1679 if (!strcmp(ptr, "user")) {
1681 } else if (!strcmp(ptr, "salt")) {
1683 } else if (!strcmp(ptr, "opaque")) {
1685 } else if (!strcmp(ptr, "challenge")) {
1687 } else if (!strcmp(ptr, "nonce")) {
1693 if (!strcmp(authmod, "adobe")) {
1694 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1697 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1705 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1707 RTMPContext *rt = s->priv_data;
1708 const uint8_t *data_end = pkt->data + pkt->data_size;
1709 char *tracked_method = NULL;
1710 int level = AV_LOG_ERROR;
1711 uint8_t tmpstr[256];
1714 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1717 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1718 "description", tmpstr, sizeof(tmpstr))) {
1719 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1720 !strcmp(tracked_method, "releaseStream") ||
1721 !strcmp(tracked_method, "FCSubscribe") ||
1722 !strcmp(tracked_method, "FCPublish"))) {
1723 /* Gracefully ignore Adobe-specific historical artifact errors. */
1724 level = AV_LOG_WARNING;
1726 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1727 ret = handle_connect_error(s, tmpstr);
1729 rt->do_reconnect = 1;
1730 level = AV_LOG_VERBOSE;
1733 ret = AVERROR_UNKNOWN;
1734 av_log(s, level, "Server error: %s\n", tmpstr);
1737 av_free(tracked_method);
1741 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1743 RTMPContext *rt = s->priv_data;
1747 char statusmsg[128];
1750 const uint8_t *p = pkt->data;
1752 RTMPPacket spkt = { 0 };
1756 bytestream2_init(&gbc, p, pkt->data_size);
1757 if (ff_amf_read_string(&gbc, command, sizeof(command),
1759 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1760 return AVERROR_INVALIDDATA;
1763 ret = ff_amf_read_number(&gbc, &seqnum);
1766 ret = ff_amf_read_null(&gbc);
1769 if (!strcmp(command, "FCPublish") ||
1770 !strcmp(command, "publish")) {
1771 ret = ff_amf_read_string(&gbc, filename,
1772 sizeof(filename), &stringlen);
1775 pchar = strrchr(s->filename, '/');
1777 av_log(s, AV_LOG_WARNING,
1778 "Unable to find / in url %s, bad format\n",
1780 pchar = s->filename;
1783 if (strcmp(pchar, filename))
1784 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1785 " %s\n", filename, pchar);
1787 rt->state = STATE_RECEIVING;
1790 if (!strcmp(command, "FCPublish")) {
1791 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1793 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1794 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1798 ff_amf_write_string(&pp, "onFCPublish");
1799 } else if (!strcmp(command, "publish")) {
1801 // Send Stream Begin 1
1802 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1803 RTMP_PT_PING, 0, 6)) < 0) {
1804 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1808 bytestream2_init_writer(&pbc, pp, spkt.data_size);
1809 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1810 bytestream2_put_be32(&pbc, rt->nb_streamid);
1811 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1813 ff_rtmp_packet_destroy(&spkt);
1817 // Send onStatus(NetStream.Publish.Start)
1818 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1820 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1821 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1824 spkt.extra = pkt->extra;
1826 ff_amf_write_string(&pp, "onStatus");
1827 ff_amf_write_number(&pp, 0);
1828 ff_amf_write_null(&pp);
1830 ff_amf_write_object_start(&pp);
1831 ff_amf_write_field_name(&pp, "level");
1832 ff_amf_write_string(&pp, "status");
1833 ff_amf_write_field_name(&pp, "code");
1834 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1835 ff_amf_write_field_name(&pp, "description");
1836 snprintf(statusmsg, sizeof(statusmsg),
1837 "%s is now published", filename);
1838 ff_amf_write_string(&pp, statusmsg);
1839 ff_amf_write_field_name(&pp, "details");
1840 ff_amf_write_string(&pp, filename);
1841 ff_amf_write_field_name(&pp, "clientid");
1842 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1843 ff_amf_write_string(&pp, statusmsg);
1844 ff_amf_write_object_end(&pp);
1847 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1849 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1850 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1854 ff_amf_write_string(&pp, "_result");
1855 ff_amf_write_number(&pp, seqnum);
1856 ff_amf_write_null(&pp);
1857 if (!strcmp(command, "createStream")) {
1859 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1860 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1861 ff_amf_write_number(&pp, rt->nb_streamid);
1862 /* By now we don't control which streams are removed in
1863 * deleteStream. There is no stream creation control
1864 * if a client creates more than 2^32 - 2 streams. */
1867 spkt.data_size = pp - spkt.data;
1868 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1870 ff_rtmp_packet_destroy(&spkt);
1874 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1876 RTMPContext *rt = s->priv_data;
1877 char *tracked_method = NULL;
1880 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1883 if (!tracked_method) {
1884 /* Ignore this reply when the current method is not tracked. */
1888 if (!memcmp(tracked_method, "connect", 7)) {
1889 if (!rt->is_input) {
1890 if ((ret = gen_release_stream(s, rt)) < 0)
1893 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1896 if ((ret = gen_server_bw(s, rt)) < 0)
1900 if ((ret = gen_create_stream(s, rt)) < 0)
1904 /* Send the FCSubscribe command when the name of live
1905 * stream is defined by the user or if it's a live stream. */
1906 if (rt->subscribe) {
1907 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1909 } else if (rt->live == -1) {
1910 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1914 } else if (!memcmp(tracked_method, "createStream", 12)) {
1915 //extract a number from the result
1916 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1917 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1919 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1922 if (!rt->is_input) {
1923 if ((ret = gen_publish(s, rt)) < 0)
1926 if ((ret = gen_play(s, rt)) < 0)
1928 if ((ret = gen_buffer_time(s, rt)) < 0)
1934 av_free(tracked_method);
1938 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1940 RTMPContext *rt = s->priv_data;
1941 const uint8_t *data_end = pkt->data + pkt->data_size;
1942 const uint8_t *ptr = pkt->data + 11;
1943 uint8_t tmpstr[256];
1946 for (i = 0; i < 2; i++) {
1947 t = ff_amf_tag_size(ptr, data_end);
1953 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1954 if (!t && !strcmp(tmpstr, "error")) {
1955 if (!ff_amf_get_field_value(ptr, data_end,
1956 "description", tmpstr, sizeof(tmpstr)))
1957 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1961 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1962 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1963 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1964 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1965 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1970 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1972 RTMPContext *rt = s->priv_data;
1975 //TODO: check for the messages sent for wrong state?
1976 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1977 if ((ret = handle_invoke_error(s, pkt)) < 0)
1979 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1980 if ((ret = handle_invoke_result(s, pkt)) < 0)
1982 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1983 if ((ret = handle_invoke_status(s, pkt)) < 0)
1985 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1986 if ((ret = gen_check_bw(s, rt)) < 0)
1988 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1989 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
1990 !memcmp(pkt->data, "\002\000\007publish", 10) ||
1991 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
1992 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1993 if ((ret = send_invoke_response(s, pkt)) < 0)
2000 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2001 RTMPContext *rt = s->priv_data;
2002 const uint8_t *p = NULL;
2004 uint8_t commandbuffer[64];
2005 char statusmsg[128];
2011 const uint8_t *datatowrite;
2012 unsigned datatowritelength;
2015 bytestream2_init(&gbc, p, pkt->data_size);
2016 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2018 return AVERROR_INVALIDDATA;
2019 if (!strcmp(commandbuffer, "@setDataFrame")) {
2020 datatowrite = gbc.buffer;
2021 datatowritelength = bytestream2_get_bytes_left(&gbc);
2022 if (ff_amf_read_string(&gbc, statusmsg,
2023 sizeof(statusmsg), &stringlen))
2024 return AVERROR_INVALIDDATA;
2025 if (strcmp(statusmsg, "onMetaData")) {
2026 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2031 /* Provide ECMAArray to flv */
2032 ts = pkt->timestamp;
2034 // generate packet header and put data into buffer for FLV demuxer
2035 if (rt->flv_off < rt->flv_size) {
2036 old_flv_size = rt->flv_size;
2037 rt->flv_size += datatowritelength + 15;
2040 rt->flv_size = datatowritelength + 15;
2044 cp = av_realloc(rt->flv_data, rt->flv_size);
2046 return AVERROR(ENOMEM);
2048 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2049 bytestream2_skip_p(&pbc, old_flv_size);
2050 bytestream2_put_byte(&pbc, pkt->type);
2051 bytestream2_put_be24(&pbc, datatowritelength);
2052 bytestream2_put_be24(&pbc, ts);
2053 bytestream2_put_byte(&pbc, ts >> 24);
2054 bytestream2_put_be24(&pbc, 0);
2055 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2056 bytestream2_put_be32(&pbc, 0);
2062 * Parse received packet and possibly perform some action depending on
2063 * the packet contents.
2064 * @return 0 for no errors, negative values for serious errors which prevent
2065 * further communications, positive values for uncritical errors
2067 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2072 ff_rtmp_packet_dump(s, pkt);
2075 switch (pkt->type) {
2076 case RTMP_PT_BYTES_READ:
2077 av_dlog(s, "received bytes read report\n");
2079 case RTMP_PT_CHUNK_SIZE:
2080 if ((ret = handle_chunk_size(s, pkt)) < 0)
2084 if ((ret = handle_ping(s, pkt)) < 0)
2087 case RTMP_PT_CLIENT_BW:
2088 if ((ret = handle_client_bw(s, pkt)) < 0)
2091 case RTMP_PT_SERVER_BW:
2092 if ((ret = handle_server_bw(s, pkt)) < 0)
2095 case RTMP_PT_INVOKE:
2096 if ((ret = handle_invoke(s, pkt)) < 0)
2101 case RTMP_PT_METADATA:
2102 case RTMP_PT_NOTIFY:
2103 /* Audio, Video and Metadata packets are parsed in get_packet() */
2106 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2113 * Interact with the server by receiving and sending RTMP packets until
2114 * there is some significant data (media data or expected status notification).
2116 * @param s reading context
2117 * @param for_header non-zero value tells function to work until it
2118 * gets notification from the server that playing has been started,
2119 * otherwise function will work until some media data is received (or
2121 * @return 0 for successful operation, negative value in case of error
2123 static int get_packet(URLContext *s, int for_header)
2125 RTMPContext *rt = s->priv_data;
2128 const uint8_t *next;
2130 uint32_t ts, cts, pts=0;
2132 if (rt->state == STATE_STOPPED)
2136 RTMPPacket rpkt = { 0 };
2137 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2138 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2140 return AVERROR(EAGAIN);
2142 return AVERROR(EIO);
2145 rt->bytes_read += ret;
2146 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2147 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2148 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2150 rt->last_bytes_read = rt->bytes_read;
2153 ret = rtmp_parse_result(s, rt, &rpkt);
2154 if (ret < 0) {//serious error in current packet
2155 ff_rtmp_packet_destroy(&rpkt);
2158 if (rt->do_reconnect && for_header) {
2159 ff_rtmp_packet_destroy(&rpkt);
2162 if (rt->state == STATE_STOPPED) {
2163 ff_rtmp_packet_destroy(&rpkt);
2166 if (for_header && (rt->state == STATE_PLAYING ||
2167 rt->state == STATE_PUBLISHING ||
2168 rt->state == STATE_RECEIVING)) {
2169 ff_rtmp_packet_destroy(&rpkt);
2172 if (!rpkt.data_size || !rt->is_input) {
2173 ff_rtmp_packet_destroy(&rpkt);
2176 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2177 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2178 ts = rpkt.timestamp;
2180 // generate packet header and put data into buffer for FLV demuxer
2182 rt->flv_size = rpkt.data_size + 15;
2183 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2184 bytestream_put_byte(&p, rpkt.type);
2185 bytestream_put_be24(&p, rpkt.data_size);
2186 bytestream_put_be24(&p, ts);
2187 bytestream_put_byte(&p, ts >> 24);
2188 bytestream_put_be24(&p, 0);
2189 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2190 bytestream_put_be32(&p, 0);
2191 ff_rtmp_packet_destroy(&rpkt);
2193 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2194 ret = handle_notify(s, &rpkt);
2195 ff_rtmp_packet_destroy(&rpkt);
2197 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2201 } else if (rpkt.type == RTMP_PT_METADATA) {
2202 // we got raw FLV data, make it available for FLV demuxer
2204 rt->flv_size = rpkt.data_size;
2205 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2206 /* rewrite timestamps */
2208 ts = rpkt.timestamp;
2209 while (next - rpkt.data < rpkt.data_size - 11) {
2211 data_size = bytestream_get_be24(&next);
2213 cts = bytestream_get_be24(&next);
2214 cts |= bytestream_get_byte(&next) << 24;
2219 bytestream_put_be24(&p, ts);
2220 bytestream_put_byte(&p, ts >> 24);
2221 next += data_size + 3 + 4;
2223 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2224 ff_rtmp_packet_destroy(&rpkt);
2227 ff_rtmp_packet_destroy(&rpkt);
2231 static int rtmp_close(URLContext *h)
2233 RTMPContext *rt = h->priv_data;
2236 if (!rt->is_input) {
2237 rt->flv_data = NULL;
2238 if (rt->out_pkt.data_size)
2239 ff_rtmp_packet_destroy(&rt->out_pkt);
2240 if (rt->state > STATE_FCPUBLISH)
2241 ret = gen_fcunpublish_stream(h, rt);
2243 if (rt->state > STATE_HANDSHAKED)
2244 ret = gen_delete_stream(h, rt);
2246 free_tracked_methods(rt);
2247 av_freep(&rt->flv_data);
2248 ffurl_close(rt->stream);
2253 * Open RTMP connection and verify that the stream can be played.
2255 * URL syntax: rtmp://server[:port][/app][/playpath]
2256 * where 'app' is first one or two directories in the path
2257 * (e.g. /ondemand/, /flash/live/, etc.)
2258 * and 'playpath' is a file name (the rest of the path,
2259 * may be prefixed with "mp4:")
2261 static int rtmp_open(URLContext *s, const char *uri, int flags)
2263 RTMPContext *rt = s->priv_data;
2264 char proto[8], hostname[256], path[1024], auth[100], *fname;
2268 AVDictionary *opts = NULL;
2271 if (rt->listen_timeout > 0)
2274 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2276 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2277 hostname, sizeof(hostname), &port,
2278 path, sizeof(path), s->filename);
2281 char *ptr = strchr(auth, ':');
2284 av_strlcpy(rt->username, auth, sizeof(rt->username));
2285 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2289 if (rt->listen && strcmp(proto, "rtmp")) {
2290 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2292 return AVERROR(EINVAL);
2294 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2295 if (!strcmp(proto, "rtmpts"))
2296 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2298 /* open the http tunneling connection */
2299 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2300 } else if (!strcmp(proto, "rtmps")) {
2301 /* open the tls connection */
2303 port = RTMPS_DEFAULT_PORT;
2304 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2305 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2306 if (!strcmp(proto, "rtmpte"))
2307 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2309 /* open the encrypted connection */
2310 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2313 /* open the tcp connection */
2315 port = RTMP_DEFAULT_PORT;
2317 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2318 "?listen&listen_timeout=%d",
2319 rt->listen_timeout * 1000);
2321 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2325 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2326 &s->interrupt_callback, &opts)) < 0) {
2327 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2331 if (rt->swfverify) {
2332 if ((ret = rtmp_calc_swfhash(s)) < 0)
2336 rt->state = STATE_START;
2337 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2339 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2342 rt->out_chunk_size = 128;
2343 rt->in_chunk_size = 128; // Probably overwritten later
2344 rt->state = STATE_HANDSHAKED;
2346 // Keep the application name when it has been defined by the user.
2349 rt->app = av_malloc(APP_MAX_LENGTH);
2351 ret = AVERROR(ENOMEM);
2355 //extract "app" part from path
2356 if (!strncmp(path, "/ondemand/", 10)) {
2358 memcpy(rt->app, "ondemand", 9);
2360 char *next = *path ? path + 1 : path;
2361 char *p = strchr(next, '/');
2366 // make sure we do not mismatch a playpath for an application instance
2367 char *c = strchr(p + 1, ':');
2368 fname = strchr(p + 1, '/');
2369 if (!fname || (c && c < fname)) {
2371 av_strlcpy(rt->app, path + 1, p - path);
2374 av_strlcpy(rt->app, path + 1, fname - path - 1);
2380 // The name of application has been defined by the user, override it.
2385 if (!rt->playpath) {
2386 int len = strlen(fname);
2388 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2389 if (!rt->playpath) {
2390 ret = AVERROR(ENOMEM);
2394 if (!strchr(fname, ':') && len >= 4 &&
2395 (!strcmp(fname + len - 4, ".f4v") ||
2396 !strcmp(fname + len - 4, ".mp4"))) {
2397 memcpy(rt->playpath, "mp4:", 5);
2398 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2399 fname[len - 4] = '\0';
2401 rt->playpath[0] = 0;
2403 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2407 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2409 ret = AVERROR(ENOMEM);
2412 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2413 port, "/%s", rt->app);
2416 if (!rt->flashver) {
2417 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2418 if (!rt->flashver) {
2419 ret = AVERROR(ENOMEM);
2423 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2424 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2425 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2427 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2428 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2432 rt->client_report_size = 1048576;
2434 rt->last_bytes_read = 0;
2435 rt->server_bw = 2500000;
2437 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2438 proto, path, rt->app, rt->playpath);
2440 if ((ret = gen_connect(s, rt)) < 0)
2443 if (read_connect(s, s->priv_data) < 0)
2449 ret = get_packet(s, 1);
2450 } while (ret == EAGAIN);
2454 if (rt->do_reconnect) {
2455 ffurl_close(rt->stream);
2457 rt->do_reconnect = 0;
2459 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2460 free_tracked_methods(rt);
2465 // generate FLV header for demuxer
2467 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2469 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2472 rt->flv_data = NULL;
2474 rt->skip_bytes = 13;
2477 s->max_packet_size = rt->stream->max_packet_size;
2482 av_dict_free(&opts);
2487 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2489 RTMPContext *rt = s->priv_data;
2490 int orig_size = size;
2494 int data_left = rt->flv_size - rt->flv_off;
2496 if (data_left >= size) {
2497 memcpy(buf, rt->flv_data + rt->flv_off, size);
2498 rt->flv_off += size;
2501 if (data_left > 0) {
2502 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2505 rt->flv_off = rt->flv_size;
2508 if ((ret = get_packet(s, 0)) < 0)
2514 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2516 RTMPContext *rt = s->priv_data;
2517 int size_temp = size;
2518 int pktsize, pkttype;
2520 const uint8_t *buf_temp = buf;
2525 if (rt->skip_bytes) {
2526 int skip = FFMIN(rt->skip_bytes, size_temp);
2529 rt->skip_bytes -= skip;
2533 if (rt->flv_header_bytes < 11) {
2534 const uint8_t *header = rt->flv_header;
2535 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2536 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2537 rt->flv_header_bytes += copy;
2539 if (rt->flv_header_bytes < 11)
2542 pkttype = bytestream_get_byte(&header);
2543 pktsize = bytestream_get_be24(&header);
2544 ts = bytestream_get_be24(&header);
2545 ts |= bytestream_get_byte(&header) << 24;
2546 bytestream_get_be24(&header);
2547 rt->flv_size = pktsize;
2549 //force 12bytes header
2550 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2551 pkttype == RTMP_PT_NOTIFY) {
2552 if (pkttype == RTMP_PT_NOTIFY)
2554 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2557 //this can be a big packet, it's better to send it right here
2558 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2559 pkttype, ts, pktsize)) < 0)
2562 rt->out_pkt.extra = rt->main_channel_id;
2563 rt->flv_data = rt->out_pkt.data;
2565 if (pkttype == RTMP_PT_NOTIFY)
2566 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2569 if (rt->flv_size - rt->flv_off > size_temp) {
2570 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2571 rt->flv_off += size_temp;
2574 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2575 size_temp -= rt->flv_size - rt->flv_off;
2576 rt->flv_off += rt->flv_size - rt->flv_off;
2579 if (rt->flv_off == rt->flv_size) {
2582 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2586 rt->flv_header_bytes = 0;
2587 rt->flv_nb_packets++;
2589 } while (buf_temp - buf < size);
2591 if (rt->flv_nb_packets < rt->flush_interval)
2593 rt->flv_nb_packets = 0;
2595 /* set stream into nonblocking mode */
2596 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2598 /* try to read one byte from the stream */
2599 ret = ffurl_read(rt->stream, &c, 1);
2601 /* switch the stream back into blocking mode */
2602 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2604 if (ret == AVERROR(EAGAIN)) {
2605 /* no incoming data to handle */
2607 } else if (ret < 0) {
2609 } else if (ret == 1) {
2610 RTMPPacket rpkt = { 0 };
2612 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2614 rt->prev_pkt[0], c)) <= 0)
2617 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2620 ff_rtmp_packet_destroy(&rpkt);
2626 #define OFFSET(x) offsetof(RTMPContext, x)
2627 #define DEC AV_OPT_FLAG_DECODING_PARAM
2628 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2630 static const AVOption rtmp_options[] = {
2631 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2632 {"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},
2633 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2634 {"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},
2635 {"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},
2636 {"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"},
2637 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2638 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2639 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2640 {"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},
2641 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2642 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2643 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2644 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2645 {"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},
2646 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2647 {"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},
2648 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2649 {"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" },
2653 #define RTMP_PROTOCOL(flavor) \
2654 static const AVClass flavor##_class = { \
2655 .class_name = #flavor, \
2656 .item_name = av_default_item_name, \
2657 .option = rtmp_options, \
2658 .version = LIBAVUTIL_VERSION_INT, \
2661 URLProtocol ff_##flavor##_protocol = { \
2663 .url_open = rtmp_open, \
2664 .url_read = rtmp_read, \
2665 .url_write = rtmp_write, \
2666 .url_close = rtmp_close, \
2667 .priv_data_size = sizeof(RTMPContext), \
2668 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2669 .priv_data_class= &flavor##_class, \
2674 RTMP_PROTOCOL(rtmpe)
2675 RTMP_PROTOCOL(rtmps)
2676 RTMP_PROTOCOL(rtmpt)
2677 RTMP_PROTOCOL(rtmpte)
2678 RTMP_PROTOCOL(rtmpts)