2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 1024
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
57 /** RTMP protocol handler state */
59 STATE_START, ///< client has not done anything yet
60 STATE_HANDSHAKED, ///< client has performed handshake
61 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
62 STATE_PLAYING, ///< client has started receiving multimedia data from server
63 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
64 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
65 STATE_RECEIVING, ///< received a publish command (for input)
66 STATE_SENDING, ///< received a play command (for output)
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->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->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 ff_amf_write_field_name(p, field);
276 ff_amf_write_bool(p, value[0] != '0');
279 ff_amf_write_string(p, value);
282 ff_amf_write_number(p, strtod(value, NULL));
285 ff_amf_write_null(p);
289 ff_amf_write_object_start(p);
291 ff_amf_write_object_end(p);
301 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
302 return AVERROR(EINVAL);
306 * Generate 'connect' call and send it to the server.
308 static int gen_connect(URLContext *s, RTMPContext *rt)
314 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
315 0, 4096 + APP_MAX_LENGTH)) < 0)
320 ff_amf_write_string(&p, "connect");
321 ff_amf_write_number(&p, ++rt->nb_invokes);
322 ff_amf_write_object_start(&p);
323 ff_amf_write_field_name(&p, "app");
324 ff_amf_write_string2(&p, rt->app, rt->auth_params);
327 ff_amf_write_field_name(&p, "type");
328 ff_amf_write_string(&p, "nonprivate");
330 ff_amf_write_field_name(&p, "flashVer");
331 ff_amf_write_string(&p, rt->flashver);
334 ff_amf_write_field_name(&p, "swfUrl");
335 ff_amf_write_string(&p, rt->swfurl);
338 ff_amf_write_field_name(&p, "tcUrl");
339 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
341 ff_amf_write_field_name(&p, "fpad");
342 ff_amf_write_bool(&p, 0);
343 ff_amf_write_field_name(&p, "capabilities");
344 ff_amf_write_number(&p, 15.0);
346 /* Tell the server we support all the audio codecs except
347 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
348 * which are unused in the RTMP protocol implementation. */
349 ff_amf_write_field_name(&p, "audioCodecs");
350 ff_amf_write_number(&p, 4071.0);
351 ff_amf_write_field_name(&p, "videoCodecs");
352 ff_amf_write_number(&p, 252.0);
353 ff_amf_write_field_name(&p, "videoFunction");
354 ff_amf_write_number(&p, 1.0);
357 ff_amf_write_field_name(&p, "pageUrl");
358 ff_amf_write_string(&p, rt->pageurl);
361 ff_amf_write_object_end(&p);
364 char *param = rt->conn;
366 // Write arbitrary AMF data to the Connect message.
367 while (param != NULL) {
369 param += strspn(param, " ");
372 sep = strchr(param, ' ');
375 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
376 // Invalid AMF parameter.
377 ff_rtmp_packet_destroy(&pkt);
388 pkt.size = p - pkt.data;
390 return rtmp_send_packet(rt, &pkt, 1);
393 static int read_connect(URLContext *s, RTMPContext *rt)
395 RTMPPacket pkt = { 0 };
405 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
406 rt->prev_pkt[1])) < 0)
409 bytestream2_init(&gbc, cp, pkt.size);
410 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
411 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
412 ff_rtmp_packet_destroy(&pkt);
413 return AVERROR_INVALIDDATA;
415 if (strcmp(command, "connect")) {
416 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
417 ff_rtmp_packet_destroy(&pkt);
418 return AVERROR_INVALIDDATA;
420 ret = ff_amf_read_number(&gbc, &seqnum);
422 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
423 /* Here one could parse an AMF Object with data as flashVers and others. */
424 ret = ff_amf_get_field_value(gbc.buffer,
425 gbc.buffer + bytestream2_get_bytes_left(&gbc),
426 "app", tmpstr, sizeof(tmpstr));
428 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
429 if (!ret && strcmp(tmpstr, rt->app))
430 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
432 ff_rtmp_packet_destroy(&pkt);
434 // Send Window Acknowledgement Size (as defined in speficication)
435 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
436 RTMP_PT_SERVER_BW, 0, 4)) < 0)
439 bytestream_put_be32(&p, rt->server_bw);
440 pkt.size = p - pkt.data;
441 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
443 ff_rtmp_packet_destroy(&pkt);
446 // Send Peer Bandwidth
447 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
448 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
451 bytestream_put_be32(&p, rt->server_bw);
452 bytestream_put_byte(&p, 2); // dynamic
453 pkt.size = p - pkt.data;
454 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
456 ff_rtmp_packet_destroy(&pkt);
461 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
462 RTMP_PT_PING, 0, 6)) < 0)
466 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
467 bytestream_put_be32(&p, 0);
468 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
470 ff_rtmp_packet_destroy(&pkt);
475 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
476 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
480 bytestream_put_be32(&p, rt->out_chunk_size);
481 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
483 ff_rtmp_packet_destroy(&pkt);
487 // Send result_ NetConnection.Connect.Success to connect
488 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
490 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
494 ff_amf_write_string(&p, "_result");
495 ff_amf_write_number(&p, seqnum);
497 ff_amf_write_object_start(&p);
498 ff_amf_write_field_name(&p, "fmsVer");
499 ff_amf_write_string(&p, "FMS/3,0,1,123");
500 ff_amf_write_field_name(&p, "capabilities");
501 ff_amf_write_number(&p, 31);
502 ff_amf_write_object_end(&p);
504 ff_amf_write_object_start(&p);
505 ff_amf_write_field_name(&p, "level");
506 ff_amf_write_string(&p, "status");
507 ff_amf_write_field_name(&p, "code");
508 ff_amf_write_string(&p, "NetConnection.Connect.Success");
509 ff_amf_write_field_name(&p, "description");
510 ff_amf_write_string(&p, "Connection succeeded.");
511 ff_amf_write_field_name(&p, "objectEncoding");
512 ff_amf_write_number(&p, 0);
513 ff_amf_write_object_end(&p);
515 pkt.size = p - pkt.data;
516 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
518 ff_rtmp_packet_destroy(&pkt);
522 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
523 RTMP_PT_INVOKE, 0, 30)) < 0)
526 ff_amf_write_string(&p, "onBWDone");
527 ff_amf_write_number(&p, 0);
528 ff_amf_write_null(&p);
529 ff_amf_write_number(&p, 8192);
530 pkt.size = p - pkt.data;
531 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
533 ff_rtmp_packet_destroy(&pkt);
539 * Generate 'releaseStream' call and send it to the server. It should make
540 * the server release some channel for media streams.
542 static int gen_release_stream(URLContext *s, RTMPContext *rt)
548 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
549 0, 29 + strlen(rt->playpath))) < 0)
552 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
554 ff_amf_write_string(&p, "releaseStream");
555 ff_amf_write_number(&p, ++rt->nb_invokes);
556 ff_amf_write_null(&p);
557 ff_amf_write_string(&p, rt->playpath);
559 return rtmp_send_packet(rt, &pkt, 1);
563 * Generate 'FCPublish' call and send it to the server. It should make
564 * the server preapare for receiving media streams.
566 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
572 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
573 0, 25 + strlen(rt->playpath))) < 0)
576 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
578 ff_amf_write_string(&p, "FCPublish");
579 ff_amf_write_number(&p, ++rt->nb_invokes);
580 ff_amf_write_null(&p);
581 ff_amf_write_string(&p, rt->playpath);
583 return rtmp_send_packet(rt, &pkt, 1);
587 * Generate 'FCUnpublish' call and send it to the server. It should make
588 * the server destroy stream.
590 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
596 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
597 0, 27 + strlen(rt->playpath))) < 0)
600 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
602 ff_amf_write_string(&p, "FCUnpublish");
603 ff_amf_write_number(&p, ++rt->nb_invokes);
604 ff_amf_write_null(&p);
605 ff_amf_write_string(&p, rt->playpath);
607 return rtmp_send_packet(rt, &pkt, 0);
611 * Generate 'createStream' call and send it to the server. It should make
612 * the server allocate some channel for media streams.
614 static int gen_create_stream(URLContext *s, RTMPContext *rt)
620 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
622 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
627 ff_amf_write_string(&p, "createStream");
628 ff_amf_write_number(&p, ++rt->nb_invokes);
629 ff_amf_write_null(&p);
631 return rtmp_send_packet(rt, &pkt, 1);
636 * Generate 'deleteStream' call and send it to the server. It should make
637 * the server remove some channel for media streams.
639 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
645 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
647 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
652 ff_amf_write_string(&p, "deleteStream");
653 ff_amf_write_number(&p, ++rt->nb_invokes);
654 ff_amf_write_null(&p);
655 ff_amf_write_number(&p, rt->main_channel_id);
657 return rtmp_send_packet(rt, &pkt, 0);
661 * Generate client buffer time and send it to the server.
663 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
669 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
674 bytestream_put_be16(&p, 3);
675 bytestream_put_be32(&p, rt->main_channel_id);
676 bytestream_put_be32(&p, rt->client_buffer_time);
678 return rtmp_send_packet(rt, &pkt, 0);
682 * Generate 'play' call and send it to the server, then ping the server
683 * to start actual playing.
685 static int gen_play(URLContext *s, RTMPContext *rt)
691 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
693 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
694 0, 29 + strlen(rt->playpath))) < 0)
697 pkt.extra = rt->main_channel_id;
700 ff_amf_write_string(&p, "play");
701 ff_amf_write_number(&p, ++rt->nb_invokes);
702 ff_amf_write_null(&p);
703 ff_amf_write_string(&p, rt->playpath);
704 ff_amf_write_number(&p, rt->live);
706 return rtmp_send_packet(rt, &pkt, 1);
709 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
715 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
718 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
721 pkt.extra = rt->main_channel_id;
724 ff_amf_write_string(&p, "seek");
725 ff_amf_write_number(&p, 0); //no tracking back responses
726 ff_amf_write_null(&p); //as usual, the first null param
727 ff_amf_write_number(&p, timestamp); //where we want to jump
729 return rtmp_send_packet(rt, &pkt, 1);
733 * Generate 'publish' call and send it to the server.
735 static int gen_publish(URLContext *s, RTMPContext *rt)
741 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
743 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
744 0, 30 + strlen(rt->playpath))) < 0)
747 pkt.extra = rt->main_channel_id;
750 ff_amf_write_string(&p, "publish");
751 ff_amf_write_number(&p, ++rt->nb_invokes);
752 ff_amf_write_null(&p);
753 ff_amf_write_string(&p, rt->playpath);
754 ff_amf_write_string(&p, "live");
756 return rtmp_send_packet(rt, &pkt, 1);
760 * Generate ping reply and send it to the server.
762 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
768 if (ppkt->size < 6) {
769 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
771 return AVERROR_INVALIDDATA;
774 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
775 ppkt->timestamp + 1, 6)) < 0)
779 bytestream_put_be16(&p, 7);
780 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
782 return rtmp_send_packet(rt, &pkt, 0);
786 * Generate SWF verification message and send it to the server.
788 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
794 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
795 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
800 bytestream_put_be16(&p, 27);
801 memcpy(p, rt->swfverification, 42);
803 return rtmp_send_packet(rt, &pkt, 0);
807 * Generate server bandwidth message and send it to the server.
809 static int gen_server_bw(URLContext *s, RTMPContext *rt)
815 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
820 bytestream_put_be32(&p, rt->server_bw);
822 return rtmp_send_packet(rt, &pkt, 0);
826 * Generate check bandwidth message and send it to the server.
828 static int gen_check_bw(URLContext *s, RTMPContext *rt)
834 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
839 ff_amf_write_string(&p, "_checkbw");
840 ff_amf_write_number(&p, ++rt->nb_invokes);
841 ff_amf_write_null(&p);
843 return rtmp_send_packet(rt, &pkt, 1);
847 * Generate report on bytes read so far and send it to the server.
849 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
855 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
860 bytestream_put_be32(&p, rt->bytes_read);
862 return rtmp_send_packet(rt, &pkt, 0);
865 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
866 const char *subscribe)
872 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
873 0, 27 + strlen(subscribe))) < 0)
877 ff_amf_write_string(&p, "FCSubscribe");
878 ff_amf_write_number(&p, ++rt->nb_invokes);
879 ff_amf_write_null(&p);
880 ff_amf_write_string(&p, subscribe);
882 return rtmp_send_packet(rt, &pkt, 1);
885 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
886 const uint8_t *key, int keylen, uint8_t *dst)
889 uint8_t hmac_buf[64+32] = {0};
892 sha = av_sha_alloc();
894 return AVERROR(ENOMEM);
897 memcpy(hmac_buf, key, keylen);
899 av_sha_init(sha, 256);
900 av_sha_update(sha,key, keylen);
901 av_sha_final(sha, hmac_buf);
903 for (i = 0; i < 64; i++)
904 hmac_buf[i] ^= HMAC_IPAD_VAL;
906 av_sha_init(sha, 256);
907 av_sha_update(sha, hmac_buf, 64);
909 av_sha_update(sha, src, len);
910 } else { //skip 32 bytes used for storing digest
911 av_sha_update(sha, src, gap);
912 av_sha_update(sha, src + gap + 32, len - gap - 32);
914 av_sha_final(sha, hmac_buf + 64);
916 for (i = 0; i < 64; i++)
917 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
918 av_sha_init(sha, 256);
919 av_sha_update(sha, hmac_buf, 64+32);
920 av_sha_final(sha, dst);
927 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
930 int i, digest_pos = 0;
932 for (i = 0; i < 4; i++)
933 digest_pos += buf[i + off];
934 digest_pos = digest_pos % mod_val + add_val;
940 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
941 * will be stored) into that packet.
943 * @param buf handshake data (1536 bytes)
944 * @param encrypted use an encrypted connection (RTMPE)
945 * @return offset to the digest inside input data
947 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
952 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
954 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
956 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
957 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
966 * Verify that the received server response has the expected digest value.
968 * @param buf handshake data received from the server (1536 bytes)
969 * @param off position to search digest offset from
970 * @return 0 if digest is valid, digest position otherwise
972 static int rtmp_validate_digest(uint8_t *buf, int off)
977 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
979 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
980 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
985 if (!memcmp(digest, buf + digest_pos, 32))
990 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
996 if (rt->swfhash_len != 32) {
997 av_log(s, AV_LOG_ERROR,
998 "Hash of the decompressed SWF file is not 32 bytes long.\n");
999 return AVERROR(EINVAL);
1002 p = &rt->swfverification[0];
1003 bytestream_put_byte(&p, 1);
1004 bytestream_put_byte(&p, 1);
1005 bytestream_put_be32(&p, rt->swfsize);
1006 bytestream_put_be32(&p, rt->swfsize);
1008 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1015 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1016 uint8_t **out_data, int64_t *out_size)
1018 z_stream zs = { 0 };
1023 zs.avail_in = in_size;
1024 zs.next_in = in_data;
1025 ret = inflateInit(&zs);
1027 return AVERROR_UNKNOWN;
1030 uint8_t tmp_buf[16384];
1032 zs.avail_out = sizeof(tmp_buf);
1033 zs.next_out = tmp_buf;
1035 ret = inflate(&zs, Z_NO_FLUSH);
1036 if (ret != Z_OK && ret != Z_STREAM_END) {
1037 ret = AVERROR_UNKNOWN;
1041 size = sizeof(tmp_buf) - zs.avail_out;
1042 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1043 ret = AVERROR(ENOMEM);
1048 memcpy(*out_data + *out_size, tmp_buf, size);
1050 } while (zs.avail_out == 0);
1058 static int rtmp_calc_swfhash(URLContext *s)
1060 RTMPContext *rt = s->priv_data;
1061 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1062 int64_t in_size, out_size;
1068 /* Get the SWF player file. */
1069 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1070 &s->interrupt_callback, NULL)) < 0) {
1071 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1075 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1080 if (!(in_data = av_malloc(in_size))) {
1081 ret = AVERROR(ENOMEM);
1085 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1089 ret = AVERROR_INVALIDDATA;
1093 if (!memcmp(in_data, "CWS", 3)) {
1094 /* Decompress the SWF player file using Zlib. */
1095 if (!(out_data = av_malloc(8))) {
1096 ret = AVERROR(ENOMEM);
1099 *in_data = 'F'; // magic stuff
1100 memcpy(out_data, in_data, 8);
1104 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1105 &out_data, &out_size)) < 0)
1108 av_log(s, AV_LOG_ERROR,
1109 "Zlib is required for decompressing the SWF player file.\n");
1110 ret = AVERROR(EINVAL);
1120 /* Compute the SHA256 hash of the SWF player file. */
1121 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1122 "Genuine Adobe Flash Player 001", 30,
1126 /* Set SWFVerification parameters. */
1127 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1128 rt->swfsize = swfsize;
1132 av_freep(&out_data);
1133 ffurl_close(stream);
1138 * Perform handshake with the server by means of exchanging pseudorandom data
1139 * signed with HMAC-SHA2 digest.
1141 * @return 0 if handshake succeeds, negative value otherwise
1143 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1146 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1147 3, // unencrypted data
1148 0, 0, 0, 0, // client uptime
1154 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1155 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1157 int server_pos, client_pos;
1158 uint8_t digest[32], signature[32];
1161 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1163 av_lfg_init(&rnd, 0xDEADC0DE);
1164 // generate handshake packet - 1536 bytes of pseudorandom data
1165 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1166 tosend[i] = av_lfg_get(&rnd) >> 24;
1168 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1169 /* When the client wants to use RTMPE, we have to change the command
1170 * byte to 0x06 which means to use encrypted data and we have to set
1171 * the flash version to at least 9.0.115.0. */
1178 /* Initialize the Diffie-Hellmann context and generate the public key
1179 * to send to the server. */
1180 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1184 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1188 if ((ret = ffurl_write(rt->stream, tosend,
1189 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1190 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1194 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1195 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1196 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1200 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1201 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1202 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1206 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1207 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1208 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1210 if (rt->is_input && serverdata[5] >= 3) {
1211 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1217 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1222 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1223 return AVERROR(EIO);
1227 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1228 * key are the last 32 bytes of the server handshake. */
1230 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1231 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1235 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1236 rtmp_server_key, sizeof(rtmp_server_key),
1241 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1242 0, digest, 32, signature);
1246 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1247 /* Compute the shared secret key sent by the server and initialize
1248 * the RC4 encryption. */
1249 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1250 tosend + 1, type)) < 0)
1253 /* Encrypt the signature received by the server. */
1254 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1257 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1258 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1259 return AVERROR(EIO);
1262 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1263 tosend[i] = av_lfg_get(&rnd) >> 24;
1264 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1265 rtmp_player_key, sizeof(rtmp_player_key),
1270 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1272 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1276 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1277 /* Encrypt the signature to be send to the server. */
1278 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1279 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1283 // write reply back to the server
1284 if ((ret = ffurl_write(rt->stream, tosend,
1285 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1288 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1289 /* Set RC4 keys for encryption and update the keystreams. */
1290 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1294 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1295 /* Compute the shared secret key sent by the server and initialize
1296 * the RC4 encryption. */
1297 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1298 tosend + 1, 1)) < 0)
1301 if (serverdata[0] == 9) {
1302 /* Encrypt the signature received by the server. */
1303 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1308 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1309 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1312 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1313 /* Set RC4 keys for encryption and update the keystreams. */
1314 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1322 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1323 uint32_t *second_int, char *arraydata,
1328 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1329 RTMP_HANDSHAKE_PACKET_SIZE);
1331 return AVERROR(EIO);
1332 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1333 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1334 " not following standard\n", (int)inoutsize);
1335 return AVERROR(EINVAL);
1338 *first_int = AV_RB32(arraydata);
1339 *second_int = AV_RB32(arraydata + 4);
1343 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1344 uint32_t second_int, char *arraydata, int size)
1348 AV_WB32(arraydata, first_int);
1349 AV_WB32(arraydata + 4, first_int);
1350 inoutsize = ffurl_write(rt->stream, arraydata,
1351 RTMP_HANDSHAKE_PACKET_SIZE);
1352 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1353 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1354 return AVERROR(EIO);
1361 * rtmp handshake server side
1363 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1365 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1367 uint32_t hs_my_epoch;
1368 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1369 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1376 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1377 if (inoutsize <= 0) {
1378 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1379 return AVERROR(EIO);
1382 if (buffer[0] != 3) {
1383 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1384 return AVERROR(EIO);
1386 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1387 av_log(s, AV_LOG_ERROR,
1388 "Unable to write answer - RTMP S0\n");
1389 return AVERROR(EIO);
1392 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1393 RTMP_HANDSHAKE_PACKET_SIZE);
1395 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1399 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1401 /* By now same epoch will be sent */
1402 hs_my_epoch = hs_epoch;
1403 /* Generate random */
1404 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1406 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1408 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1409 RTMP_HANDSHAKE_PACKET_SIZE);
1411 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1415 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1416 RTMP_HANDSHAKE_PACKET_SIZE);
1418 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1422 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1423 RTMP_HANDSHAKE_PACKET_SIZE);
1425 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1428 if (temp != hs_my_epoch)
1429 av_log(s, AV_LOG_WARNING,
1430 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1431 if (memcmp(buffer + 8, hs_s1 + 8,
1432 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1433 av_log(s, AV_LOG_WARNING,
1434 "Erroneous C2 Message random does not match up\n");
1439 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1441 RTMPContext *rt = s->priv_data;
1444 if (pkt->size < 4) {
1445 av_log(s, AV_LOG_ERROR,
1446 "Too short chunk size change packet (%d)\n",
1448 return AVERROR_INVALIDDATA;
1451 if (!rt->is_input) {
1452 /* Send the same chunk size change packet back to the server,
1453 * setting the outgoing chunk size to the same as the incoming one. */
1454 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1455 rt->prev_pkt[1])) < 0)
1457 rt->out_chunk_size = AV_RB32(pkt->data);
1460 rt->in_chunk_size = AV_RB32(pkt->data);
1461 if (rt->in_chunk_size <= 0) {
1462 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1464 return AVERROR_INVALIDDATA;
1466 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1472 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1474 RTMPContext *rt = s->priv_data;
1477 if (pkt->size < 2) {
1478 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1480 return AVERROR_INVALIDDATA;
1483 t = AV_RB16(pkt->data);
1485 if ((ret = gen_pong(s, rt, pkt)) < 0)
1487 } else if (t == 26) {
1489 if ((ret = gen_swf_verification(s, rt)) < 0)
1492 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1499 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1501 RTMPContext *rt = s->priv_data;
1503 if (pkt->size < 4) {
1504 av_log(s, AV_LOG_ERROR,
1505 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1507 return AVERROR_INVALIDDATA;
1510 rt->client_report_size = AV_RB32(pkt->data);
1511 if (rt->client_report_size <= 0) {
1512 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1513 rt->client_report_size);
1514 return AVERROR_INVALIDDATA;
1517 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1518 rt->client_report_size >>= 1;
1523 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1525 RTMPContext *rt = s->priv_data;
1527 if (pkt->size < 4) {
1528 av_log(s, AV_LOG_ERROR,
1529 "Too short server bandwidth report packet (%d)\n",
1531 return AVERROR_INVALIDDATA;
1534 rt->server_bw = AV_RB32(pkt->data);
1535 if (rt->server_bw <= 0) {
1536 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1538 return AVERROR_INVALIDDATA;
1540 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1545 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1546 const char *opaque, const char *challenge)
1549 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1550 struct AVMD5 *md5 = av_md5_alloc();
1552 return AVERROR(ENOMEM);
1554 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1557 av_md5_update(md5, user, strlen(user));
1558 av_md5_update(md5, salt, strlen(salt));
1559 av_md5_update(md5, rt->password, strlen(rt->password));
1560 av_md5_final(md5, hash);
1561 av_base64_encode(hashstr, sizeof(hashstr), hash,
1564 av_md5_update(md5, hashstr, strlen(hashstr));
1566 av_md5_update(md5, opaque, strlen(opaque));
1568 av_md5_update(md5, challenge, strlen(challenge));
1569 av_md5_update(md5, challenge2, strlen(challenge2));
1570 av_md5_final(md5, hash);
1571 av_base64_encode(hashstr, sizeof(hashstr), hash,
1573 snprintf(rt->auth_params, sizeof(rt->auth_params),
1574 "?authmod=%s&user=%s&challenge=%s&response=%s",
1575 "adobe", user, challenge2, hashstr);
1577 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1578 "&opaque=%s", opaque);
1584 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1587 char hashstr1[33], hashstr2[33];
1588 const char *realm = "live";
1589 const char *method = "publish";
1590 const char *qop = "auth";
1591 const char *nc = "00000001";
1593 struct AVMD5 *md5 = av_md5_alloc();
1595 return AVERROR(ENOMEM);
1597 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1600 av_md5_update(md5, user, strlen(user));
1601 av_md5_update(md5, ":", 1);
1602 av_md5_update(md5, realm, strlen(realm));
1603 av_md5_update(md5, ":", 1);
1604 av_md5_update(md5, rt->password, strlen(rt->password));
1605 av_md5_final(md5, hash);
1606 ff_data_to_hex(hashstr1, hash, 16, 1);
1607 hashstr1[32] = '\0';
1610 av_md5_update(md5, method, strlen(method));
1611 av_md5_update(md5, ":/", 2);
1612 av_md5_update(md5, rt->app, strlen(rt->app));
1613 if (!strchr(rt->app, '/'))
1614 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1615 av_md5_final(md5, hash);
1616 ff_data_to_hex(hashstr2, hash, 16, 1);
1617 hashstr2[32] = '\0';
1620 av_md5_update(md5, hashstr1, strlen(hashstr1));
1621 av_md5_update(md5, ":", 1);
1623 av_md5_update(md5, nonce, strlen(nonce));
1624 av_md5_update(md5, ":", 1);
1625 av_md5_update(md5, nc, strlen(nc));
1626 av_md5_update(md5, ":", 1);
1627 av_md5_update(md5, cnonce, strlen(cnonce));
1628 av_md5_update(md5, ":", 1);
1629 av_md5_update(md5, qop, strlen(qop));
1630 av_md5_update(md5, ":", 1);
1631 av_md5_update(md5, hashstr2, strlen(hashstr2));
1632 av_md5_final(md5, hash);
1633 ff_data_to_hex(hashstr1, hash, 16, 1);
1635 snprintf(rt->auth_params, sizeof(rt->auth_params),
1636 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1637 "llnw", user, nonce, cnonce, nc, hashstr1);
1643 static int handle_connect_error(URLContext *s, const char *desc)
1645 RTMPContext *rt = s->priv_data;
1646 char buf[300], *ptr, authmod[15];
1648 const char *user = "", *salt = "", *opaque = NULL,
1649 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1651 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1652 !(cptr = strstr(desc, "authmod=llnw"))) {
1653 av_log(s, AV_LOG_ERROR,
1654 "Unknown connect error (unsupported authentication method?)\n");
1655 return AVERROR_UNKNOWN;
1657 cptr += strlen("authmod=");
1658 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1659 authmod[i++] = *cptr++;
1662 if (!rt->username[0] || !rt->password[0]) {
1663 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1664 return AVERROR_UNKNOWN;
1667 if (strstr(desc, "?reason=authfailed")) {
1668 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1669 return AVERROR_UNKNOWN;
1670 } else if (strstr(desc, "?reason=nosuchuser")) {
1671 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1672 return AVERROR_UNKNOWN;
1675 if (rt->auth_tried) {
1676 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1677 return AVERROR_UNKNOWN;
1680 rt->auth_params[0] = '\0';
1682 if (strstr(desc, "code=403 need auth")) {
1683 snprintf(rt->auth_params, sizeof(rt->auth_params),
1684 "?authmod=%s&user=%s", authmod, rt->username);
1688 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1689 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1690 return AVERROR_UNKNOWN;
1693 av_strlcpy(buf, cptr + 1, sizeof(buf));
1697 char *next = strchr(ptr, '&');
1698 char *value = strchr(ptr, '=');
1703 if (!strcmp(ptr, "user")) {
1705 } else if (!strcmp(ptr, "salt")) {
1707 } else if (!strcmp(ptr, "opaque")) {
1709 } else if (!strcmp(ptr, "challenge")) {
1711 } else if (!strcmp(ptr, "nonce")) {
1717 if (!strcmp(authmod, "adobe")) {
1718 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1721 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1729 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1731 RTMPContext *rt = s->priv_data;
1732 const uint8_t *data_end = pkt->data + pkt->size;
1733 char *tracked_method = NULL;
1734 int level = AV_LOG_ERROR;
1735 uint8_t tmpstr[256];
1738 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1741 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1742 "description", tmpstr, sizeof(tmpstr))) {
1743 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1744 !strcmp(tracked_method, "releaseStream") ||
1745 !strcmp(tracked_method, "FCSubscribe") ||
1746 !strcmp(tracked_method, "FCPublish"))) {
1747 /* Gracefully ignore Adobe-specific historical artifact errors. */
1748 level = AV_LOG_WARNING;
1750 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1751 ret = handle_connect_error(s, tmpstr);
1753 rt->do_reconnect = 1;
1754 level = AV_LOG_VERBOSE;
1757 ret = AVERROR_UNKNOWN;
1758 av_log(s, level, "Server error: %s\n", tmpstr);
1761 av_free(tracked_method);
1765 static int write_begin(URLContext *s)
1767 RTMPContext *rt = s->priv_data;
1769 RTMPPacket spkt = { 0 };
1772 // Send Stream Begin 1
1773 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1774 RTMP_PT_PING, 0, 6)) < 0) {
1775 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1779 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1780 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1781 bytestream2_put_be32(&pbc, rt->nb_streamid);
1783 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1786 ff_rtmp_packet_destroy(&spkt);
1791 static int write_status(URLContext *s, RTMPPacket *pkt,
1792 const char *status, const char *filename)
1794 RTMPContext *rt = s->priv_data;
1795 RTMPPacket spkt = { 0 };
1796 char statusmsg[128];
1800 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1802 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1803 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1808 spkt.extra = pkt->extra;
1809 ff_amf_write_string(&pp, "onStatus");
1810 ff_amf_write_number(&pp, 0);
1811 ff_amf_write_null(&pp);
1813 ff_amf_write_object_start(&pp);
1814 ff_amf_write_field_name(&pp, "level");
1815 ff_amf_write_string(&pp, "status");
1816 ff_amf_write_field_name(&pp, "code");
1817 ff_amf_write_string(&pp, status);
1818 ff_amf_write_field_name(&pp, "description");
1819 snprintf(statusmsg, sizeof(statusmsg),
1820 "%s is now published", filename);
1821 ff_amf_write_string(&pp, statusmsg);
1822 ff_amf_write_field_name(&pp, "details");
1823 ff_amf_write_string(&pp, filename);
1824 ff_amf_write_field_name(&pp, "clientid");
1825 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1826 ff_amf_write_string(&pp, statusmsg);
1827 ff_amf_write_object_end(&pp);
1829 spkt.size = pp - spkt.data;
1830 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1832 ff_rtmp_packet_destroy(&spkt);
1837 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1839 RTMPContext *rt = s->priv_data;
1845 const uint8_t *p = pkt->data;
1847 RTMPPacket spkt = { 0 };
1851 bytestream2_init(&gbc, p, pkt->size);
1852 if (ff_amf_read_string(&gbc, command, sizeof(command),
1854 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1855 return AVERROR_INVALIDDATA;
1858 ret = ff_amf_read_number(&gbc, &seqnum);
1861 ret = ff_amf_read_null(&gbc);
1864 if (!strcmp(command, "FCPublish") ||
1865 !strcmp(command, "publish")) {
1866 ret = ff_amf_read_string(&gbc, filename,
1867 sizeof(filename), &stringlen);
1870 pchar = strrchr(s->filename, '/');
1872 av_log(s, AV_LOG_WARNING,
1873 "Unable to find / in url %s, bad format\n",
1875 pchar = s->filename;
1878 if (strcmp(pchar, filename))
1879 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1880 " %s\n", filename, pchar);
1882 rt->state = STATE_RECEIVING;
1885 if (!strcmp(command, "FCPublish")) {
1886 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1888 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1889 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1893 ff_amf_write_string(&pp, "onFCPublish");
1894 } else if (!strcmp(command, "publish")) {
1895 ret = write_begin(s);
1899 // Send onStatus(NetStream.Publish.Start)
1900 return write_status(s, pkt, "NetStream.Publish.Start",
1902 } else if (!strcmp(command, "play")) {
1903 ret = write_begin(s);
1906 rt->state = STATE_SENDING;
1907 return write_status(s, pkt, "NetStream.Play.Start",
1910 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1912 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1913 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1917 ff_amf_write_string(&pp, "_result");
1918 ff_amf_write_number(&pp, seqnum);
1919 ff_amf_write_null(&pp);
1920 if (!strcmp(command, "createStream")) {
1922 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1923 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1924 ff_amf_write_number(&pp, rt->nb_streamid);
1925 /* By now we don't control which streams are removed in
1926 * deleteStream. There is no stream creation control
1927 * if a client creates more than 2^32 - 2 streams. */
1930 spkt.size = pp - spkt.data;
1931 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1933 ff_rtmp_packet_destroy(&spkt);
1937 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1939 RTMPContext *rt = s->priv_data;
1940 char *tracked_method = NULL;
1943 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1946 if (!tracked_method) {
1947 /* Ignore this reply when the current method is not tracked. */
1951 if (!strcmp(tracked_method, "connect")) {
1952 if (!rt->is_input) {
1953 if ((ret = gen_release_stream(s, rt)) < 0)
1956 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1959 if ((ret = gen_server_bw(s, rt)) < 0)
1963 if ((ret = gen_create_stream(s, rt)) < 0)
1967 /* Send the FCSubscribe command when the name of live
1968 * stream is defined by the user or if it's a live stream. */
1969 if (rt->subscribe) {
1970 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1972 } else if (rt->live == -1) {
1973 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1977 } else if (!strcmp(tracked_method, "createStream")) {
1978 //extract a number from the result
1979 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1980 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1982 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1985 if (!rt->is_input) {
1986 if ((ret = gen_publish(s, rt)) < 0)
1989 if ((ret = gen_play(s, rt)) < 0)
1991 if ((ret = gen_buffer_time(s, rt)) < 0)
1997 av_free(tracked_method);
2001 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2003 RTMPContext *rt = s->priv_data;
2004 const uint8_t *data_end = pkt->data + pkt->size;
2005 const uint8_t *ptr = pkt->data + 11;
2006 uint8_t tmpstr[256];
2009 for (i = 0; i < 2; i++) {
2010 t = ff_amf_tag_size(ptr, data_end);
2016 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2017 if (!t && !strcmp(tmpstr, "error")) {
2018 if (!ff_amf_get_field_value(ptr, data_end,
2019 "description", tmpstr, sizeof(tmpstr)))
2020 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2024 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2025 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2026 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2027 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2028 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2029 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2034 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2036 RTMPContext *rt = s->priv_data;
2039 //TODO: check for the messages sent for wrong state?
2040 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2041 if ((ret = handle_invoke_error(s, pkt)) < 0)
2043 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2044 if ((ret = handle_invoke_result(s, pkt)) < 0)
2046 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2047 if ((ret = handle_invoke_status(s, pkt)) < 0)
2049 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2050 if ((ret = gen_check_bw(s, rt)) < 0)
2052 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2053 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2054 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2055 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2056 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2057 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2058 if ((ret = send_invoke_response(s, pkt)) < 0)
2065 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2066 RTMPContext *rt = s->priv_data;
2067 const uint8_t *p = NULL;
2069 uint8_t commandbuffer[64];
2070 char statusmsg[128];
2076 const uint8_t *datatowrite;
2077 unsigned datatowritelength;
2080 bytestream2_init(&gbc, p, pkt->size);
2081 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2083 return AVERROR_INVALIDDATA;
2084 if (!strcmp(commandbuffer, "@setDataFrame")) {
2085 datatowrite = gbc.buffer;
2086 datatowritelength = bytestream2_get_bytes_left(&gbc);
2087 if (ff_amf_read_string(&gbc, statusmsg,
2088 sizeof(statusmsg), &stringlen))
2089 return AVERROR_INVALIDDATA;
2090 if (strcmp(statusmsg, "onMetaData")) {
2091 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2096 /* Provide ECMAArray to flv */
2097 ts = pkt->timestamp;
2099 // generate packet header and put data into buffer for FLV demuxer
2100 if (rt->flv_off < rt->flv_size) {
2101 old_flv_size = rt->flv_size;
2102 rt->flv_size += datatowritelength + 15;
2105 rt->flv_size = datatowritelength + 15;
2109 cp = av_realloc(rt->flv_data, rt->flv_size);
2111 return AVERROR(ENOMEM);
2113 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2114 bytestream2_skip_p(&pbc, old_flv_size);
2115 bytestream2_put_byte(&pbc, pkt->type);
2116 bytestream2_put_be24(&pbc, datatowritelength);
2117 bytestream2_put_be24(&pbc, ts);
2118 bytestream2_put_byte(&pbc, ts >> 24);
2119 bytestream2_put_be24(&pbc, 0);
2120 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2121 bytestream2_put_be32(&pbc, 0);
2127 * Parse received packet and possibly perform some action depending on
2128 * the packet contents.
2129 * @return 0 for no errors, negative values for serious errors which prevent
2130 * further communications, positive values for uncritical errors
2132 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2137 ff_rtmp_packet_dump(s, pkt);
2140 switch (pkt->type) {
2141 case RTMP_PT_BYTES_READ:
2142 av_dlog(s, "received bytes read report\n");
2144 case RTMP_PT_CHUNK_SIZE:
2145 if ((ret = handle_chunk_size(s, pkt)) < 0)
2149 if ((ret = handle_ping(s, pkt)) < 0)
2152 case RTMP_PT_CLIENT_BW:
2153 if ((ret = handle_client_bw(s, pkt)) < 0)
2156 case RTMP_PT_SERVER_BW:
2157 if ((ret = handle_server_bw(s, pkt)) < 0)
2160 case RTMP_PT_INVOKE:
2161 if ((ret = handle_invoke(s, pkt)) < 0)
2166 case RTMP_PT_METADATA:
2167 case RTMP_PT_NOTIFY:
2168 /* Audio, Video and Metadata packets are parsed in get_packet() */
2171 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2178 * Interact with the server by receiving and sending RTMP packets until
2179 * there is some significant data (media data or expected status notification).
2181 * @param s reading context
2182 * @param for_header non-zero value tells function to work until it
2183 * gets notification from the server that playing has been started,
2184 * otherwise function will work until some media data is received (or
2186 * @return 0 for successful operation, negative value in case of error
2188 static int get_packet(URLContext *s, int for_header)
2190 RTMPContext *rt = s->priv_data;
2193 const uint8_t *next;
2195 uint32_t ts, cts, pts=0;
2197 if (rt->state == STATE_STOPPED)
2201 RTMPPacket rpkt = { 0 };
2202 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2203 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2205 return AVERROR(EAGAIN);
2207 return AVERROR(EIO);
2210 rt->bytes_read += ret;
2211 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2212 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2213 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2215 rt->last_bytes_read = rt->bytes_read;
2218 ret = rtmp_parse_result(s, rt, &rpkt);
2220 // At this point we must check if we are in the seek state and continue
2221 // with the next packet. handle_invoke will get us out of this state
2222 // when the right message is encountered
2223 if (rt->state == STATE_SEEKING) {
2224 ff_rtmp_packet_destroy(&rpkt);
2225 // We continue, let the natural flow of things happen:
2226 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2230 if (ret < 0) {//serious error in current packet
2231 ff_rtmp_packet_destroy(&rpkt);
2234 if (rt->do_reconnect && for_header) {
2235 ff_rtmp_packet_destroy(&rpkt);
2238 if (rt->state == STATE_STOPPED) {
2239 ff_rtmp_packet_destroy(&rpkt);
2242 if (for_header && (rt->state == STATE_PLAYING ||
2243 rt->state == STATE_PUBLISHING ||
2244 rt->state == STATE_SENDING ||
2245 rt->state == STATE_RECEIVING)) {
2246 ff_rtmp_packet_destroy(&rpkt);
2249 if (!rpkt.size || !rt->is_input) {
2250 ff_rtmp_packet_destroy(&rpkt);
2253 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2254 (rpkt.type == RTMP_PT_NOTIFY &&
2255 ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2256 ts = rpkt.timestamp;
2258 // generate packet header and put data into buffer for FLV demuxer
2260 rt->flv_size = rpkt.size + 15;
2261 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2262 bytestream_put_byte(&p, rpkt.type);
2263 bytestream_put_be24(&p, rpkt.size);
2264 bytestream_put_be24(&p, ts);
2265 bytestream_put_byte(&p, ts >> 24);
2266 bytestream_put_be24(&p, 0);
2267 bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2268 bytestream_put_be32(&p, 0);
2269 ff_rtmp_packet_destroy(&rpkt);
2271 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2272 ret = handle_notify(s, &rpkt);
2273 ff_rtmp_packet_destroy(&rpkt);
2275 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2279 } else if (rpkt.type == RTMP_PT_METADATA) {
2280 // we got raw FLV data, make it available for FLV demuxer
2282 rt->flv_size = rpkt.size;
2283 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2284 /* rewrite timestamps */
2286 ts = rpkt.timestamp;
2287 while (next - rpkt.data < rpkt.size - 11) {
2289 size = bytestream_get_be24(&next);
2291 cts = bytestream_get_be24(&next);
2292 cts |= bytestream_get_byte(&next) << 24;
2297 bytestream_put_be24(&p, ts);
2298 bytestream_put_byte(&p, ts >> 24);
2299 next += size + 3 + 4;
2301 memcpy(rt->flv_data, rpkt.data, rpkt.size);
2302 ff_rtmp_packet_destroy(&rpkt);
2305 ff_rtmp_packet_destroy(&rpkt);
2309 static int rtmp_close(URLContext *h)
2311 RTMPContext *rt = h->priv_data;
2314 if (!rt->is_input) {
2315 rt->flv_data = NULL;
2316 if (rt->out_pkt.size)
2317 ff_rtmp_packet_destroy(&rt->out_pkt);
2318 if (rt->state > STATE_FCPUBLISH)
2319 ret = gen_fcunpublish_stream(h, rt);
2321 if (rt->state > STATE_HANDSHAKED)
2322 ret = gen_delete_stream(h, rt);
2324 free_tracked_methods(rt);
2325 av_freep(&rt->flv_data);
2326 ffurl_close(rt->stream);
2331 * Open RTMP connection and verify that the stream can be played.
2333 * URL syntax: rtmp://server[:port][/app][/playpath]
2334 * where 'app' is first one or two directories in the path
2335 * (e.g. /ondemand/, /flash/live/, etc.)
2336 * and 'playpath' is a file name (the rest of the path,
2337 * may be prefixed with "mp4:")
2339 static int rtmp_open(URLContext *s, const char *uri, int flags)
2341 RTMPContext *rt = s->priv_data;
2342 char proto[8], hostname[256], path[1024], auth[100], *fname;
2346 AVDictionary *opts = NULL;
2349 if (rt->listen_timeout > 0)
2352 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2354 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2355 hostname, sizeof(hostname), &port,
2356 path, sizeof(path), s->filename);
2358 if (strchr(path, ' ')) {
2359 av_log(s, AV_LOG_WARNING,
2360 "Detected librtmp style URL parameters, these aren't supported "
2361 "by the libavformat internal RTMP handler currently enabled. "
2362 "See the documentation for the correct way to pass parameters.\n");
2366 char *ptr = strchr(auth, ':');
2369 av_strlcpy(rt->username, auth, sizeof(rt->username));
2370 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2374 if (rt->listen && strcmp(proto, "rtmp")) {
2375 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2377 return AVERROR(EINVAL);
2379 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2380 if (!strcmp(proto, "rtmpts"))
2381 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2383 /* open the http tunneling connection */
2384 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2385 } else if (!strcmp(proto, "rtmps")) {
2386 /* open the tls connection */
2388 port = RTMPS_DEFAULT_PORT;
2389 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2390 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2391 if (!strcmp(proto, "rtmpte"))
2392 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2394 /* open the encrypted connection */
2395 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2398 /* open the tcp connection */
2400 port = RTMP_DEFAULT_PORT;
2402 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2403 "?listen&listen_timeout=%d",
2404 rt->listen_timeout * 1000);
2406 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2410 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2411 &s->interrupt_callback, &opts)) < 0) {
2412 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2416 if (rt->swfverify) {
2417 if ((ret = rtmp_calc_swfhash(s)) < 0)
2421 rt->state = STATE_START;
2422 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2424 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2427 rt->out_chunk_size = 128;
2428 rt->in_chunk_size = 128; // Probably overwritten later
2429 rt->state = STATE_HANDSHAKED;
2431 // Keep the application name when it has been defined by the user.
2434 rt->app = av_malloc(APP_MAX_LENGTH);
2436 ret = AVERROR(ENOMEM);
2440 //extract "app" part from path
2441 if (!strncmp(path, "/ondemand/", 10)) {
2443 memcpy(rt->app, "ondemand", 9);
2445 char *next = *path ? path + 1 : path;
2446 char *p = strchr(next, '/');
2451 // make sure we do not mismatch a playpath for an application instance
2452 char *c = strchr(p + 1, ':');
2453 fname = strchr(p + 1, '/');
2454 if (!fname || (c && c < fname)) {
2456 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2459 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2465 // The name of application has been defined by the user, override it.
2466 if (strlen(old_app) >= APP_MAX_LENGTH) {
2467 ret = AVERROR(EINVAL);
2474 if (!rt->playpath) {
2475 int len = strlen(fname);
2477 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2478 if (!rt->playpath) {
2479 ret = AVERROR(ENOMEM);
2483 if (!strchr(fname, ':') && len >= 4 &&
2484 (!strcmp(fname + len - 4, ".f4v") ||
2485 !strcmp(fname + len - 4, ".mp4"))) {
2486 memcpy(rt->playpath, "mp4:", 5);
2487 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2488 fname[len - 4] = '\0';
2490 rt->playpath[0] = 0;
2492 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2496 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2498 ret = AVERROR(ENOMEM);
2501 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2502 port, "/%s", rt->app);
2505 if (!rt->flashver) {
2506 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2507 if (!rt->flashver) {
2508 ret = AVERROR(ENOMEM);
2512 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2513 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2514 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2516 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2517 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2521 rt->client_report_size = 1048576;
2523 rt->last_bytes_read = 0;
2524 rt->server_bw = 2500000;
2526 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2527 proto, path, rt->app, rt->playpath);
2529 if ((ret = gen_connect(s, rt)) < 0)
2532 if (read_connect(s, s->priv_data) < 0)
2537 ret = get_packet(s, 1);
2538 } while (ret == EAGAIN);
2542 if (rt->do_reconnect) {
2543 ffurl_close(rt->stream);
2545 rt->do_reconnect = 0;
2547 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2548 free_tracked_methods(rt);
2553 // generate FLV header for demuxer
2555 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2557 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2560 rt->flv_data = NULL;
2562 rt->skip_bytes = 13;
2565 s->max_packet_size = rt->stream->max_packet_size;
2570 av_dict_free(&opts);
2575 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2577 RTMPContext *rt = s->priv_data;
2578 int orig_size = size;
2582 int data_left = rt->flv_size - rt->flv_off;
2584 if (data_left >= size) {
2585 memcpy(buf, rt->flv_data + rt->flv_off, size);
2586 rt->flv_off += size;
2589 if (data_left > 0) {
2590 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2593 rt->flv_off = rt->flv_size;
2596 if ((ret = get_packet(s, 0)) < 0)
2602 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2605 RTMPContext *rt = s->priv_data;
2607 av_log(s, AV_LOG_DEBUG,
2608 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2609 stream_index, timestamp, flags);
2610 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2611 av_log(s, AV_LOG_ERROR,
2612 "Unable to send seek command on stream index %d at timestamp "
2613 "%"PRId64" with flags %08x\n",
2614 stream_index, timestamp, flags);
2617 rt->flv_off = rt->flv_size;
2618 rt->state = STATE_SEEKING;
2622 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2624 RTMPContext *rt = s->priv_data;
2625 int size_temp = size;
2626 int pktsize, pkttype;
2628 const uint8_t *buf_temp = buf;
2633 if (rt->skip_bytes) {
2634 int skip = FFMIN(rt->skip_bytes, size_temp);
2637 rt->skip_bytes -= skip;
2641 if (rt->flv_header_bytes < 11) {
2642 const uint8_t *header = rt->flv_header;
2643 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2644 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2645 rt->flv_header_bytes += copy;
2647 if (rt->flv_header_bytes < 11)
2650 pkttype = bytestream_get_byte(&header);
2651 pktsize = bytestream_get_be24(&header);
2652 ts = bytestream_get_be24(&header);
2653 ts |= bytestream_get_byte(&header) << 24;
2654 bytestream_get_be24(&header);
2655 rt->flv_size = pktsize;
2657 //force 12bytes header
2658 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2659 pkttype == RTMP_PT_NOTIFY) {
2660 if (pkttype == RTMP_PT_NOTIFY)
2662 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2665 //this can be a big packet, it's better to send it right here
2666 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2667 pkttype, ts, pktsize)) < 0)
2670 rt->out_pkt.extra = rt->main_channel_id;
2671 rt->flv_data = rt->out_pkt.data;
2673 if (pkttype == RTMP_PT_NOTIFY)
2674 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2677 if (rt->flv_size - rt->flv_off > size_temp) {
2678 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2679 rt->flv_off += size_temp;
2682 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2683 size_temp -= rt->flv_size - rt->flv_off;
2684 rt->flv_off += rt->flv_size - rt->flv_off;
2687 if (rt->flv_off == rt->flv_size) {
2690 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2694 rt->flv_header_bytes = 0;
2695 rt->flv_nb_packets++;
2697 } while (buf_temp - buf < size);
2699 if (rt->flv_nb_packets < rt->flush_interval)
2701 rt->flv_nb_packets = 0;
2703 /* set stream into nonblocking mode */
2704 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2706 /* try to read one byte from the stream */
2707 ret = ffurl_read(rt->stream, &c, 1);
2709 /* switch the stream back into blocking mode */
2710 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2712 if (ret == AVERROR(EAGAIN)) {
2713 /* no incoming data to handle */
2715 } else if (ret < 0) {
2717 } else if (ret == 1) {
2718 RTMPPacket rpkt = { 0 };
2720 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2722 rt->prev_pkt[0], c)) <= 0)
2725 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2728 ff_rtmp_packet_destroy(&rpkt);
2734 #define OFFSET(x) offsetof(RTMPContext, x)
2735 #define DEC AV_OPT_FLAG_DECODING_PARAM
2736 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2738 static const AVOption rtmp_options[] = {
2739 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2740 {"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},
2741 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2742 {"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},
2743 {"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},
2744 {"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"},
2745 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2746 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2747 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2748 {"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},
2749 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2750 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2751 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2752 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2753 {"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},
2754 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2755 {"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},
2756 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2757 {"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" },
2761 #define RTMP_PROTOCOL(flavor) \
2762 static const AVClass flavor##_class = { \
2763 .class_name = #flavor, \
2764 .item_name = av_default_item_name, \
2765 .option = rtmp_options, \
2766 .version = LIBAVUTIL_VERSION_INT, \
2769 URLProtocol ff_##flavor##_protocol = { \
2771 .url_open = rtmp_open, \
2772 .url_read = rtmp_read, \
2773 .url_read_seek = rtmp_seek, \
2774 .url_write = rtmp_write, \
2775 .url_close = rtmp_close, \
2776 .priv_data_size = sizeof(RTMPContext), \
2777 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2778 .priv_data_class= &flavor##_class, \
2783 RTMP_PROTOCOL(rtmpe)
2784 RTMP_PROTOCOL(rtmps)
2785 RTMP_PROTOCOL(rtmpt)
2786 RTMP_PROTOCOL(rtmpte)
2787 RTMP_PROTOCOL(rtmpts)