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_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 if (!field || !value)
272 ff_amf_write_field_name(p, field);
279 ff_amf_write_bool(p, value[0] != '0');
282 ff_amf_write_string(p, value);
285 ff_amf_write_number(p, strtod(value, NULL));
288 ff_amf_write_null(p);
292 ff_amf_write_object_start(p);
294 ff_amf_write_object_end(p);
304 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
305 return AVERROR(EINVAL);
309 * Generate 'connect' call and send it to the server.
311 static int gen_connect(URLContext *s, RTMPContext *rt)
317 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
323 ff_amf_write_string(&p, "connect");
324 ff_amf_write_number(&p, ++rt->nb_invokes);
325 ff_amf_write_object_start(&p);
326 ff_amf_write_field_name(&p, "app");
327 ff_amf_write_string2(&p, rt->app, rt->auth_params);
330 ff_amf_write_field_name(&p, "type");
331 ff_amf_write_string(&p, "nonprivate");
333 ff_amf_write_field_name(&p, "flashVer");
334 ff_amf_write_string(&p, rt->flashver);
337 ff_amf_write_field_name(&p, "swfUrl");
338 ff_amf_write_string(&p, rt->swfurl);
341 ff_amf_write_field_name(&p, "tcUrl");
342 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
344 ff_amf_write_field_name(&p, "fpad");
345 ff_amf_write_bool(&p, 0);
346 ff_amf_write_field_name(&p, "capabilities");
347 ff_amf_write_number(&p, 15.0);
349 /* Tell the server we support all the audio codecs except
350 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
351 * which are unused in the RTMP protocol implementation. */
352 ff_amf_write_field_name(&p, "audioCodecs");
353 ff_amf_write_number(&p, 4071.0);
354 ff_amf_write_field_name(&p, "videoCodecs");
355 ff_amf_write_number(&p, 252.0);
356 ff_amf_write_field_name(&p, "videoFunction");
357 ff_amf_write_number(&p, 1.0);
360 ff_amf_write_field_name(&p, "pageUrl");
361 ff_amf_write_string(&p, rt->pageurl);
364 ff_amf_write_object_end(&p);
367 char *param = rt->conn;
369 // Write arbitrary AMF data to the Connect message.
370 while (param != NULL) {
372 param += strspn(param, " ");
375 sep = strchr(param, ' ');
378 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
379 // Invalid AMF parameter.
380 ff_rtmp_packet_destroy(&pkt);
391 pkt.size = p - pkt.data;
393 return rtmp_send_packet(rt, &pkt, 1);
396 static int read_connect(URLContext *s, RTMPContext *rt)
398 RTMPPacket pkt = { 0 };
408 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
409 rt->prev_pkt[1])) < 0)
412 bytestream2_init(&gbc, cp, pkt.size);
413 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
414 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
415 ff_rtmp_packet_destroy(&pkt);
416 return AVERROR_INVALIDDATA;
418 if (strcmp(command, "connect")) {
419 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
420 ff_rtmp_packet_destroy(&pkt);
421 return AVERROR_INVALIDDATA;
423 ret = ff_amf_read_number(&gbc, &seqnum);
425 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
426 /* Here one could parse an AMF Object with data as flashVers and others. */
427 ret = ff_amf_get_field_value(gbc.buffer,
428 gbc.buffer + bytestream2_get_bytes_left(&gbc),
429 "app", tmpstr, sizeof(tmpstr));
431 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
432 if (!ret && strcmp(tmpstr, rt->app))
433 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
435 ff_rtmp_packet_destroy(&pkt);
437 // Send Window Acknowledgement Size (as defined in speficication)
438 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
439 RTMP_PT_SERVER_BW, 0, 4)) < 0)
442 bytestream_put_be32(&p, rt->server_bw);
443 pkt.size = p - pkt.data;
444 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
446 ff_rtmp_packet_destroy(&pkt);
449 // Send Peer Bandwidth
450 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
451 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
454 bytestream_put_be32(&p, rt->server_bw);
455 bytestream_put_byte(&p, 2); // dynamic
456 pkt.size = p - pkt.data;
457 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
459 ff_rtmp_packet_destroy(&pkt);
464 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
465 RTMP_PT_PING, 0, 6)) < 0)
469 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
470 bytestream_put_be32(&p, 0);
471 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
473 ff_rtmp_packet_destroy(&pkt);
478 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
479 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
483 bytestream_put_be32(&p, rt->out_chunk_size);
484 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
486 ff_rtmp_packet_destroy(&pkt);
490 // Send result_ NetConnection.Connect.Success to connect
491 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
493 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
497 ff_amf_write_string(&p, "_result");
498 ff_amf_write_number(&p, seqnum);
500 ff_amf_write_object_start(&p);
501 ff_amf_write_field_name(&p, "fmsVer");
502 ff_amf_write_string(&p, "FMS/3,0,1,123");
503 ff_amf_write_field_name(&p, "capabilities");
504 ff_amf_write_number(&p, 31);
505 ff_amf_write_object_end(&p);
507 ff_amf_write_object_start(&p);
508 ff_amf_write_field_name(&p, "level");
509 ff_amf_write_string(&p, "status");
510 ff_amf_write_field_name(&p, "code");
511 ff_amf_write_string(&p, "NetConnection.Connect.Success");
512 ff_amf_write_field_name(&p, "description");
513 ff_amf_write_string(&p, "Connection succeeded.");
514 ff_amf_write_field_name(&p, "objectEncoding");
515 ff_amf_write_number(&p, 0);
516 ff_amf_write_object_end(&p);
518 pkt.size = p - pkt.data;
519 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
521 ff_rtmp_packet_destroy(&pkt);
525 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
526 RTMP_PT_INVOKE, 0, 30)) < 0)
529 ff_amf_write_string(&p, "onBWDone");
530 ff_amf_write_number(&p, 0);
531 ff_amf_write_null(&p);
532 ff_amf_write_number(&p, 8192);
533 pkt.size = p - pkt.data;
534 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
536 ff_rtmp_packet_destroy(&pkt);
542 * Generate 'releaseStream' call and send it to the server. It should make
543 * the server release some channel for media streams.
545 static int gen_release_stream(URLContext *s, RTMPContext *rt)
551 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
552 0, 29 + strlen(rt->playpath))) < 0)
555 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
557 ff_amf_write_string(&p, "releaseStream");
558 ff_amf_write_number(&p, ++rt->nb_invokes);
559 ff_amf_write_null(&p);
560 ff_amf_write_string(&p, rt->playpath);
562 return rtmp_send_packet(rt, &pkt, 1);
566 * Generate 'FCPublish' call and send it to the server. It should make
567 * the server preapare for receiving media streams.
569 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
575 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
576 0, 25 + strlen(rt->playpath))) < 0)
579 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
581 ff_amf_write_string(&p, "FCPublish");
582 ff_amf_write_number(&p, ++rt->nb_invokes);
583 ff_amf_write_null(&p);
584 ff_amf_write_string(&p, rt->playpath);
586 return rtmp_send_packet(rt, &pkt, 1);
590 * Generate 'FCUnpublish' call and send it to the server. It should make
591 * the server destroy stream.
593 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
599 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
600 0, 27 + strlen(rt->playpath))) < 0)
603 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
605 ff_amf_write_string(&p, "FCUnpublish");
606 ff_amf_write_number(&p, ++rt->nb_invokes);
607 ff_amf_write_null(&p);
608 ff_amf_write_string(&p, rt->playpath);
610 return rtmp_send_packet(rt, &pkt, 0);
614 * Generate 'createStream' call and send it to the server. It should make
615 * the server allocate some channel for media streams.
617 static int gen_create_stream(URLContext *s, RTMPContext *rt)
623 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
625 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
630 ff_amf_write_string(&p, "createStream");
631 ff_amf_write_number(&p, ++rt->nb_invokes);
632 ff_amf_write_null(&p);
634 return rtmp_send_packet(rt, &pkt, 1);
639 * Generate 'deleteStream' call and send it to the server. It should make
640 * the server remove some channel for media streams.
642 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
648 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
650 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
655 ff_amf_write_string(&p, "deleteStream");
656 ff_amf_write_number(&p, ++rt->nb_invokes);
657 ff_amf_write_null(&p);
658 ff_amf_write_number(&p, rt->main_channel_id);
660 return rtmp_send_packet(rt, &pkt, 0);
664 * Generate client buffer time and send it to the server.
666 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
672 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
677 bytestream_put_be16(&p, 3);
678 bytestream_put_be32(&p, rt->main_channel_id);
679 bytestream_put_be32(&p, rt->client_buffer_time);
681 return rtmp_send_packet(rt, &pkt, 0);
685 * Generate 'play' call and send it to the server, then ping the server
686 * to start actual playing.
688 static int gen_play(URLContext *s, RTMPContext *rt)
694 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
696 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
697 0, 29 + strlen(rt->playpath))) < 0)
700 pkt.extra = rt->main_channel_id;
703 ff_amf_write_string(&p, "play");
704 ff_amf_write_number(&p, ++rt->nb_invokes);
705 ff_amf_write_null(&p);
706 ff_amf_write_string(&p, rt->playpath);
707 ff_amf_write_number(&p, rt->live);
709 return rtmp_send_packet(rt, &pkt, 1);
712 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
718 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
721 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
724 pkt.extra = rt->main_channel_id;
727 ff_amf_write_string(&p, "seek");
728 ff_amf_write_number(&p, 0); //no tracking back responses
729 ff_amf_write_null(&p); //as usual, the first null param
730 ff_amf_write_number(&p, timestamp); //where we want to jump
732 return rtmp_send_packet(rt, &pkt, 1);
736 * Generate 'publish' call and send it to the server.
738 static int gen_publish(URLContext *s, RTMPContext *rt)
744 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
746 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
747 0, 30 + strlen(rt->playpath))) < 0)
750 pkt.extra = rt->main_channel_id;
753 ff_amf_write_string(&p, "publish");
754 ff_amf_write_number(&p, ++rt->nb_invokes);
755 ff_amf_write_null(&p);
756 ff_amf_write_string(&p, rt->playpath);
757 ff_amf_write_string(&p, "live");
759 return rtmp_send_packet(rt, &pkt, 1);
763 * Generate ping reply and send it to the server.
765 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
771 if (ppkt->size < 6) {
772 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
774 return AVERROR_INVALIDDATA;
777 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
778 ppkt->timestamp + 1, 6)) < 0)
782 bytestream_put_be16(&p, 7);
783 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
785 return rtmp_send_packet(rt, &pkt, 0);
789 * Generate SWF verification message and send it to the server.
791 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
797 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
798 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
803 bytestream_put_be16(&p, 27);
804 memcpy(p, rt->swfverification, 42);
806 return rtmp_send_packet(rt, &pkt, 0);
810 * Generate server bandwidth message and send it to the server.
812 static int gen_server_bw(URLContext *s, RTMPContext *rt)
818 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
823 bytestream_put_be32(&p, rt->server_bw);
825 return rtmp_send_packet(rt, &pkt, 0);
829 * Generate check bandwidth message and send it to the server.
831 static int gen_check_bw(URLContext *s, RTMPContext *rt)
837 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
842 ff_amf_write_string(&p, "_checkbw");
843 ff_amf_write_number(&p, ++rt->nb_invokes);
844 ff_amf_write_null(&p);
846 return rtmp_send_packet(rt, &pkt, 1);
850 * Generate report on bytes read so far and send it to the server.
852 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
858 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
863 bytestream_put_be32(&p, rt->bytes_read);
865 return rtmp_send_packet(rt, &pkt, 0);
868 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
869 const char *subscribe)
875 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
876 0, 27 + strlen(subscribe))) < 0)
880 ff_amf_write_string(&p, "FCSubscribe");
881 ff_amf_write_number(&p, ++rt->nb_invokes);
882 ff_amf_write_null(&p);
883 ff_amf_write_string(&p, subscribe);
885 return rtmp_send_packet(rt, &pkt, 1);
888 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
889 const uint8_t *key, int keylen, uint8_t *dst)
892 uint8_t hmac_buf[64+32] = {0};
895 sha = av_sha_alloc();
897 return AVERROR(ENOMEM);
900 memcpy(hmac_buf, key, keylen);
902 av_sha_init(sha, 256);
903 av_sha_update(sha,key, keylen);
904 av_sha_final(sha, hmac_buf);
906 for (i = 0; i < 64; i++)
907 hmac_buf[i] ^= HMAC_IPAD_VAL;
909 av_sha_init(sha, 256);
910 av_sha_update(sha, hmac_buf, 64);
912 av_sha_update(sha, src, len);
913 } else { //skip 32 bytes used for storing digest
914 av_sha_update(sha, src, gap);
915 av_sha_update(sha, src + gap + 32, len - gap - 32);
917 av_sha_final(sha, hmac_buf + 64);
919 for (i = 0; i < 64; i++)
920 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
921 av_sha_init(sha, 256);
922 av_sha_update(sha, hmac_buf, 64+32);
923 av_sha_final(sha, dst);
930 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
933 int i, digest_pos = 0;
935 for (i = 0; i < 4; i++)
936 digest_pos += buf[i + off];
937 digest_pos = digest_pos % mod_val + add_val;
943 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
944 * will be stored) into that packet.
946 * @param buf handshake data (1536 bytes)
947 * @param encrypted use an encrypted connection (RTMPE)
948 * @return offset to the digest inside input data
950 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
955 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
957 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
959 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
960 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
969 * Verify that the received server response has the expected digest value.
971 * @param buf handshake data received from the server (1536 bytes)
972 * @param off position to search digest offset from
973 * @return 0 if digest is valid, digest position otherwise
975 static int rtmp_validate_digest(uint8_t *buf, int off)
980 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
982 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
983 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
988 if (!memcmp(digest, buf + digest_pos, 32))
993 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
999 if (rt->swfhash_len != 32) {
1000 av_log(s, AV_LOG_ERROR,
1001 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1002 return AVERROR(EINVAL);
1005 p = &rt->swfverification[0];
1006 bytestream_put_byte(&p, 1);
1007 bytestream_put_byte(&p, 1);
1008 bytestream_put_be32(&p, rt->swfsize);
1009 bytestream_put_be32(&p, rt->swfsize);
1011 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1018 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1019 uint8_t **out_data, int64_t *out_size)
1021 z_stream zs = { 0 };
1026 zs.avail_in = in_size;
1027 zs.next_in = in_data;
1028 ret = inflateInit(&zs);
1030 return AVERROR_UNKNOWN;
1033 uint8_t tmp_buf[16384];
1035 zs.avail_out = sizeof(tmp_buf);
1036 zs.next_out = tmp_buf;
1038 ret = inflate(&zs, Z_NO_FLUSH);
1039 if (ret != Z_OK && ret != Z_STREAM_END) {
1040 ret = AVERROR_UNKNOWN;
1044 size = sizeof(tmp_buf) - zs.avail_out;
1045 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1046 ret = AVERROR(ENOMEM);
1051 memcpy(*out_data + *out_size, tmp_buf, size);
1053 } while (zs.avail_out == 0);
1061 static int rtmp_calc_swfhash(URLContext *s)
1063 RTMPContext *rt = s->priv_data;
1064 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1065 int64_t in_size, out_size;
1071 /* Get the SWF player file. */
1072 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1073 &s->interrupt_callback, NULL)) < 0) {
1074 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1078 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1083 if (!(in_data = av_malloc(in_size))) {
1084 ret = AVERROR(ENOMEM);
1088 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1092 ret = AVERROR_INVALIDDATA;
1096 if (!memcmp(in_data, "CWS", 3)) {
1097 /* Decompress the SWF player file using Zlib. */
1098 if (!(out_data = av_malloc(8))) {
1099 ret = AVERROR(ENOMEM);
1102 *in_data = 'F'; // magic stuff
1103 memcpy(out_data, in_data, 8);
1107 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1108 &out_data, &out_size)) < 0)
1111 av_log(s, AV_LOG_ERROR,
1112 "Zlib is required for decompressing the SWF player file.\n");
1113 ret = AVERROR(EINVAL);
1123 /* Compute the SHA256 hash of the SWF player file. */
1124 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1125 "Genuine Adobe Flash Player 001", 30,
1129 /* Set SWFVerification parameters. */
1130 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1131 rt->swfsize = swfsize;
1135 av_freep(&out_data);
1136 ffurl_close(stream);
1141 * Perform handshake with the server by means of exchanging pseudorandom data
1142 * signed with HMAC-SHA2 digest.
1144 * @return 0 if handshake succeeds, negative value otherwise
1146 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1149 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1150 3, // unencrypted data
1151 0, 0, 0, 0, // client uptime
1157 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1158 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1160 int server_pos, client_pos;
1161 uint8_t digest[32], signature[32];
1164 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1166 av_lfg_init(&rnd, 0xDEADC0DE);
1167 // generate handshake packet - 1536 bytes of pseudorandom data
1168 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1169 tosend[i] = av_lfg_get(&rnd) >> 24;
1171 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1172 /* When the client wants to use RTMPE, we have to change the command
1173 * byte to 0x06 which means to use encrypted data and we have to set
1174 * the flash version to at least 9.0.115.0. */
1181 /* Initialize the Diffie-Hellmann context and generate the public key
1182 * to send to the server. */
1183 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1187 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1191 if ((ret = ffurl_write(rt->stream, tosend,
1192 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1193 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1197 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1198 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1199 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1203 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1204 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1205 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1209 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1210 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1211 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1213 if (rt->is_input && serverdata[5] >= 3) {
1214 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1220 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1225 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1226 return AVERROR(EIO);
1230 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1231 * key are the last 32 bytes of the server handshake. */
1233 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1234 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1238 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1239 rtmp_server_key, sizeof(rtmp_server_key),
1244 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1245 0, digest, 32, signature);
1249 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1250 /* Compute the shared secret key sent by the server and initialize
1251 * the RC4 encryption. */
1252 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1253 tosend + 1, type)) < 0)
1256 /* Encrypt the signature received by the server. */
1257 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1260 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1261 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1262 return AVERROR(EIO);
1265 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1266 tosend[i] = av_lfg_get(&rnd) >> 24;
1267 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1268 rtmp_player_key, sizeof(rtmp_player_key),
1273 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1275 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1279 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1280 /* Encrypt the signature to be send to the server. */
1281 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1282 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1286 // write reply back to the server
1287 if ((ret = ffurl_write(rt->stream, tosend,
1288 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1291 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1292 /* Set RC4 keys for encryption and update the keystreams. */
1293 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1297 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1298 /* Compute the shared secret key sent by the server and initialize
1299 * the RC4 encryption. */
1300 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1301 tosend + 1, 1)) < 0)
1304 if (serverdata[0] == 9) {
1305 /* Encrypt the signature received by the server. */
1306 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1311 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1312 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1315 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1316 /* Set RC4 keys for encryption and update the keystreams. */
1317 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1325 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1326 uint32_t *second_int, char *arraydata,
1331 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1332 RTMP_HANDSHAKE_PACKET_SIZE);
1334 return AVERROR(EIO);
1335 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1336 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1337 " not following standard\n", (int)inoutsize);
1338 return AVERROR(EINVAL);
1341 *first_int = AV_RB32(arraydata);
1342 *second_int = AV_RB32(arraydata + 4);
1346 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1347 uint32_t second_int, char *arraydata, int size)
1351 AV_WB32(arraydata, first_int);
1352 AV_WB32(arraydata + 4, first_int);
1353 inoutsize = ffurl_write(rt->stream, arraydata,
1354 RTMP_HANDSHAKE_PACKET_SIZE);
1355 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1356 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1357 return AVERROR(EIO);
1364 * rtmp handshake server side
1366 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1368 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1370 uint32_t hs_my_epoch;
1371 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1372 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1379 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1380 if (inoutsize <= 0) {
1381 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1382 return AVERROR(EIO);
1385 if (buffer[0] != 3) {
1386 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1387 return AVERROR(EIO);
1389 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1390 av_log(s, AV_LOG_ERROR,
1391 "Unable to write answer - RTMP S0\n");
1392 return AVERROR(EIO);
1395 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1396 RTMP_HANDSHAKE_PACKET_SIZE);
1398 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1402 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1404 /* By now same epoch will be sent */
1405 hs_my_epoch = hs_epoch;
1406 /* Generate random */
1407 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1409 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1411 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1412 RTMP_HANDSHAKE_PACKET_SIZE);
1414 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1418 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1419 RTMP_HANDSHAKE_PACKET_SIZE);
1421 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1425 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1426 RTMP_HANDSHAKE_PACKET_SIZE);
1428 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1431 if (temp != hs_my_epoch)
1432 av_log(s, AV_LOG_WARNING,
1433 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1434 if (memcmp(buffer + 8, hs_s1 + 8,
1435 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1436 av_log(s, AV_LOG_WARNING,
1437 "Erroneous C2 Message random does not match up\n");
1442 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1444 RTMPContext *rt = s->priv_data;
1447 if (pkt->size < 4) {
1448 av_log(s, AV_LOG_ERROR,
1449 "Too short chunk size change packet (%d)\n",
1451 return AVERROR_INVALIDDATA;
1454 if (!rt->is_input) {
1455 /* Send the same chunk size change packet back to the server,
1456 * setting the outgoing chunk size to the same as the incoming one. */
1457 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1458 rt->prev_pkt[1])) < 0)
1460 rt->out_chunk_size = AV_RB32(pkt->data);
1463 rt->in_chunk_size = AV_RB32(pkt->data);
1464 if (rt->in_chunk_size <= 0) {
1465 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1467 return AVERROR_INVALIDDATA;
1469 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1475 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1477 RTMPContext *rt = s->priv_data;
1480 if (pkt->size < 2) {
1481 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1483 return AVERROR_INVALIDDATA;
1486 t = AV_RB16(pkt->data);
1488 if ((ret = gen_pong(s, rt, pkt)) < 0)
1490 } else if (t == 26) {
1492 if ((ret = gen_swf_verification(s, rt)) < 0)
1495 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1502 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1504 RTMPContext *rt = s->priv_data;
1506 if (pkt->size < 4) {
1507 av_log(s, AV_LOG_ERROR,
1508 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1510 return AVERROR_INVALIDDATA;
1513 rt->client_report_size = AV_RB32(pkt->data);
1514 if (rt->client_report_size <= 0) {
1515 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1516 rt->client_report_size);
1517 return AVERROR_INVALIDDATA;
1520 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1521 rt->client_report_size >>= 1;
1526 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1528 RTMPContext *rt = s->priv_data;
1530 if (pkt->size < 4) {
1531 av_log(s, AV_LOG_ERROR,
1532 "Too short server bandwidth report packet (%d)\n",
1534 return AVERROR_INVALIDDATA;
1537 rt->server_bw = AV_RB32(pkt->data);
1538 if (rt->server_bw <= 0) {
1539 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1541 return AVERROR_INVALIDDATA;
1543 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1548 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1549 const char *opaque, const char *challenge)
1552 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1553 struct AVMD5 *md5 = av_md5_alloc();
1555 return AVERROR(ENOMEM);
1557 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1560 av_md5_update(md5, user, strlen(user));
1561 av_md5_update(md5, salt, strlen(salt));
1562 av_md5_update(md5, rt->password, strlen(rt->password));
1563 av_md5_final(md5, hash);
1564 av_base64_encode(hashstr, sizeof(hashstr), hash,
1567 av_md5_update(md5, hashstr, strlen(hashstr));
1569 av_md5_update(md5, opaque, strlen(opaque));
1571 av_md5_update(md5, challenge, strlen(challenge));
1572 av_md5_update(md5, challenge2, strlen(challenge2));
1573 av_md5_final(md5, hash);
1574 av_base64_encode(hashstr, sizeof(hashstr), hash,
1576 snprintf(rt->auth_params, sizeof(rt->auth_params),
1577 "?authmod=%s&user=%s&challenge=%s&response=%s",
1578 "adobe", user, challenge2, hashstr);
1580 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1581 "&opaque=%s", opaque);
1587 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1590 char hashstr1[33], hashstr2[33];
1591 const char *realm = "live";
1592 const char *method = "publish";
1593 const char *qop = "auth";
1594 const char *nc = "00000001";
1596 struct AVMD5 *md5 = av_md5_alloc();
1598 return AVERROR(ENOMEM);
1600 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1603 av_md5_update(md5, user, strlen(user));
1604 av_md5_update(md5, ":", 1);
1605 av_md5_update(md5, realm, strlen(realm));
1606 av_md5_update(md5, ":", 1);
1607 av_md5_update(md5, rt->password, strlen(rt->password));
1608 av_md5_final(md5, hash);
1609 ff_data_to_hex(hashstr1, hash, 16, 1);
1610 hashstr1[32] = '\0';
1613 av_md5_update(md5, method, strlen(method));
1614 av_md5_update(md5, ":/", 2);
1615 av_md5_update(md5, rt->app, strlen(rt->app));
1616 if (!strchr(rt->app, '/'))
1617 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1618 av_md5_final(md5, hash);
1619 ff_data_to_hex(hashstr2, hash, 16, 1);
1620 hashstr2[32] = '\0';
1623 av_md5_update(md5, hashstr1, strlen(hashstr1));
1624 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, nonce, strlen(nonce));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, nc, strlen(nc));
1629 av_md5_update(md5, ":", 1);
1630 av_md5_update(md5, cnonce, strlen(cnonce));
1631 av_md5_update(md5, ":", 1);
1632 av_md5_update(md5, qop, strlen(qop));
1633 av_md5_update(md5, ":", 1);
1634 av_md5_update(md5, hashstr2, strlen(hashstr2));
1635 av_md5_final(md5, hash);
1636 ff_data_to_hex(hashstr1, hash, 16, 1);
1638 snprintf(rt->auth_params, sizeof(rt->auth_params),
1639 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1640 "llnw", user, nonce, cnonce, nc, hashstr1);
1646 static int handle_connect_error(URLContext *s, const char *desc)
1648 RTMPContext *rt = s->priv_data;
1649 char buf[300], *ptr, authmod[15];
1651 const char *user = "", *salt = "", *opaque = NULL,
1652 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1654 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1655 !(cptr = strstr(desc, "authmod=llnw"))) {
1656 av_log(s, AV_LOG_ERROR,
1657 "Unknown connect error (unsupported authentication method?)\n");
1658 return AVERROR_UNKNOWN;
1660 cptr += strlen("authmod=");
1661 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1662 authmod[i++] = *cptr++;
1665 if (!rt->username[0] || !rt->password[0]) {
1666 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1667 return AVERROR_UNKNOWN;
1670 if (strstr(desc, "?reason=authfailed")) {
1671 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1672 return AVERROR_UNKNOWN;
1673 } else if (strstr(desc, "?reason=nosuchuser")) {
1674 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1675 return AVERROR_UNKNOWN;
1678 if (rt->auth_tried) {
1679 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1680 return AVERROR_UNKNOWN;
1683 rt->auth_params[0] = '\0';
1685 if (strstr(desc, "code=403 need auth")) {
1686 snprintf(rt->auth_params, sizeof(rt->auth_params),
1687 "?authmod=%s&user=%s", authmod, rt->username);
1691 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1692 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1693 return AVERROR_UNKNOWN;
1696 av_strlcpy(buf, cptr + 1, sizeof(buf));
1700 char *next = strchr(ptr, '&');
1701 char *value = strchr(ptr, '=');
1706 if (!strcmp(ptr, "user")) {
1708 } else if (!strcmp(ptr, "salt")) {
1710 } else if (!strcmp(ptr, "opaque")) {
1712 } else if (!strcmp(ptr, "challenge")) {
1714 } else if (!strcmp(ptr, "nonce")) {
1720 if (!strcmp(authmod, "adobe")) {
1721 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1724 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1732 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1734 RTMPContext *rt = s->priv_data;
1735 const uint8_t *data_end = pkt->data + pkt->size;
1736 char *tracked_method = NULL;
1737 int level = AV_LOG_ERROR;
1738 uint8_t tmpstr[256];
1741 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1744 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1745 "description", tmpstr, sizeof(tmpstr))) {
1746 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1747 !strcmp(tracked_method, "releaseStream") ||
1748 !strcmp(tracked_method, "FCSubscribe") ||
1749 !strcmp(tracked_method, "FCPublish"))) {
1750 /* Gracefully ignore Adobe-specific historical artifact errors. */
1751 level = AV_LOG_WARNING;
1753 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1754 ret = handle_connect_error(s, tmpstr);
1756 rt->do_reconnect = 1;
1757 level = AV_LOG_VERBOSE;
1760 ret = AVERROR_UNKNOWN;
1761 av_log(s, level, "Server error: %s\n", tmpstr);
1764 av_free(tracked_method);
1768 static int write_begin(URLContext *s)
1770 RTMPContext *rt = s->priv_data;
1772 RTMPPacket spkt = { 0 };
1775 // Send Stream Begin 1
1776 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1777 RTMP_PT_PING, 0, 6)) < 0) {
1778 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1782 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1783 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1784 bytestream2_put_be32(&pbc, rt->nb_streamid);
1786 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1789 ff_rtmp_packet_destroy(&spkt);
1794 static int write_status(URLContext *s, RTMPPacket *pkt,
1795 const char *status, const char *filename)
1797 RTMPContext *rt = s->priv_data;
1798 RTMPPacket spkt = { 0 };
1799 char statusmsg[128];
1803 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1805 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1806 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1811 spkt.extra = pkt->extra;
1812 ff_amf_write_string(&pp, "onStatus");
1813 ff_amf_write_number(&pp, 0);
1814 ff_amf_write_null(&pp);
1816 ff_amf_write_object_start(&pp);
1817 ff_amf_write_field_name(&pp, "level");
1818 ff_amf_write_string(&pp, "status");
1819 ff_amf_write_field_name(&pp, "code");
1820 ff_amf_write_string(&pp, status);
1821 ff_amf_write_field_name(&pp, "description");
1822 snprintf(statusmsg, sizeof(statusmsg),
1823 "%s is now published", filename);
1824 ff_amf_write_string(&pp, statusmsg);
1825 ff_amf_write_field_name(&pp, "details");
1826 ff_amf_write_string(&pp, filename);
1827 ff_amf_write_field_name(&pp, "clientid");
1828 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1829 ff_amf_write_string(&pp, statusmsg);
1830 ff_amf_write_object_end(&pp);
1832 spkt.size = pp - spkt.data;
1833 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1835 ff_rtmp_packet_destroy(&spkt);
1840 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1842 RTMPContext *rt = s->priv_data;
1848 const uint8_t *p = pkt->data;
1850 RTMPPacket spkt = { 0 };
1854 bytestream2_init(&gbc, p, pkt->size);
1855 if (ff_amf_read_string(&gbc, command, sizeof(command),
1857 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1858 return AVERROR_INVALIDDATA;
1861 ret = ff_amf_read_number(&gbc, &seqnum);
1864 ret = ff_amf_read_null(&gbc);
1867 if (!strcmp(command, "FCPublish") ||
1868 !strcmp(command, "publish")) {
1869 ret = ff_amf_read_string(&gbc, filename,
1870 sizeof(filename), &stringlen);
1873 pchar = strrchr(s->filename, '/');
1875 av_log(s, AV_LOG_WARNING,
1876 "Unable to find / in url %s, bad format\n",
1878 pchar = s->filename;
1881 if (strcmp(pchar, filename))
1882 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1883 " %s\n", filename, pchar);
1885 rt->state = STATE_RECEIVING;
1888 if (!strcmp(command, "FCPublish")) {
1889 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1891 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1892 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1896 ff_amf_write_string(&pp, "onFCPublish");
1897 } else if (!strcmp(command, "publish")) {
1898 ret = write_begin(s);
1902 // Send onStatus(NetStream.Publish.Start)
1903 return write_status(s, pkt, "NetStream.Publish.Start",
1905 } else if (!strcmp(command, "play")) {
1906 ret = write_begin(s);
1909 rt->state = STATE_SENDING;
1910 return write_status(s, pkt, "NetStream.Play.Start",
1913 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1915 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1916 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1920 ff_amf_write_string(&pp, "_result");
1921 ff_amf_write_number(&pp, seqnum);
1922 ff_amf_write_null(&pp);
1923 if (!strcmp(command, "createStream")) {
1925 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1926 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1927 ff_amf_write_number(&pp, rt->nb_streamid);
1928 /* By now we don't control which streams are removed in
1929 * deleteStream. There is no stream creation control
1930 * if a client creates more than 2^32 - 2 streams. */
1933 spkt.size = pp - spkt.data;
1934 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1936 ff_rtmp_packet_destroy(&spkt);
1940 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1942 RTMPContext *rt = s->priv_data;
1943 char *tracked_method = NULL;
1946 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1949 if (!tracked_method) {
1950 /* Ignore this reply when the current method is not tracked. */
1954 if (!strcmp(tracked_method, "connect")) {
1955 if (!rt->is_input) {
1956 if ((ret = gen_release_stream(s, rt)) < 0)
1959 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1962 if ((ret = gen_server_bw(s, rt)) < 0)
1966 if ((ret = gen_create_stream(s, rt)) < 0)
1970 /* Send the FCSubscribe command when the name of live
1971 * stream is defined by the user or if it's a live stream. */
1972 if (rt->subscribe) {
1973 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1975 } else if (rt->live == -1) {
1976 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1980 } else if (!strcmp(tracked_method, "createStream")) {
1981 //extract a number from the result
1982 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1983 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1985 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1988 if (!rt->is_input) {
1989 if ((ret = gen_publish(s, rt)) < 0)
1992 if ((ret = gen_play(s, rt)) < 0)
1994 if ((ret = gen_buffer_time(s, rt)) < 0)
2000 av_free(tracked_method);
2004 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2006 RTMPContext *rt = s->priv_data;
2007 const uint8_t *data_end = pkt->data + pkt->size;
2008 const uint8_t *ptr = pkt->data + 11;
2009 uint8_t tmpstr[256];
2012 for (i = 0; i < 2; i++) {
2013 t = ff_amf_tag_size(ptr, data_end);
2019 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2020 if (!t && !strcmp(tmpstr, "error")) {
2021 if (!ff_amf_get_field_value(ptr, data_end,
2022 "description", tmpstr, sizeof(tmpstr)))
2023 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2027 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2028 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2029 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2030 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2031 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2032 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2037 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2039 RTMPContext *rt = s->priv_data;
2042 //TODO: check for the messages sent for wrong state?
2043 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2044 if ((ret = handle_invoke_error(s, pkt)) < 0)
2046 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2047 if ((ret = handle_invoke_result(s, pkt)) < 0)
2049 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2050 if ((ret = handle_invoke_status(s, pkt)) < 0)
2052 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2053 if ((ret = gen_check_bw(s, rt)) < 0)
2055 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2056 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2057 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2058 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2059 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2060 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2061 if ((ret = send_invoke_response(s, pkt)) < 0)
2068 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2069 RTMPContext *rt = s->priv_data;
2070 const uint8_t *p = NULL;
2072 uint8_t commandbuffer[64];
2073 char statusmsg[128];
2079 const uint8_t *datatowrite;
2080 unsigned datatowritelength;
2083 bytestream2_init(&gbc, p, pkt->size);
2084 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2086 return AVERROR_INVALIDDATA;
2087 if (!strcmp(commandbuffer, "@setDataFrame")) {
2088 datatowrite = gbc.buffer;
2089 datatowritelength = bytestream2_get_bytes_left(&gbc);
2090 if (ff_amf_read_string(&gbc, statusmsg,
2091 sizeof(statusmsg), &stringlen))
2092 return AVERROR_INVALIDDATA;
2093 if (strcmp(statusmsg, "onMetaData")) {
2094 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2099 /* Provide ECMAArray to flv */
2100 ts = pkt->timestamp;
2102 // generate packet header and put data into buffer for FLV demuxer
2103 if (rt->flv_off < rt->flv_size) {
2104 old_flv_size = rt->flv_size;
2105 rt->flv_size += datatowritelength + 15;
2108 rt->flv_size = datatowritelength + 15;
2112 cp = av_realloc(rt->flv_data, rt->flv_size);
2114 return AVERROR(ENOMEM);
2116 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2117 bytestream2_skip_p(&pbc, old_flv_size);
2118 bytestream2_put_byte(&pbc, pkt->type);
2119 bytestream2_put_be24(&pbc, datatowritelength);
2120 bytestream2_put_be24(&pbc, ts);
2121 bytestream2_put_byte(&pbc, ts >> 24);
2122 bytestream2_put_be24(&pbc, 0);
2123 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2124 bytestream2_put_be32(&pbc, 0);
2130 * Parse received packet and possibly perform some action depending on
2131 * the packet contents.
2132 * @return 0 for no errors, negative values for serious errors which prevent
2133 * further communications, positive values for uncritical errors
2135 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2140 ff_rtmp_packet_dump(s, pkt);
2143 switch (pkt->type) {
2144 case RTMP_PT_BYTES_READ:
2145 av_dlog(s, "received bytes read report\n");
2147 case RTMP_PT_CHUNK_SIZE:
2148 if ((ret = handle_chunk_size(s, pkt)) < 0)
2152 if ((ret = handle_ping(s, pkt)) < 0)
2155 case RTMP_PT_CLIENT_BW:
2156 if ((ret = handle_client_bw(s, pkt)) < 0)
2159 case RTMP_PT_SERVER_BW:
2160 if ((ret = handle_server_bw(s, pkt)) < 0)
2163 case RTMP_PT_INVOKE:
2164 if ((ret = handle_invoke(s, pkt)) < 0)
2169 case RTMP_PT_METADATA:
2170 case RTMP_PT_NOTIFY:
2171 /* Audio, Video and Metadata packets are parsed in get_packet() */
2174 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2181 * Interact with the server by receiving and sending RTMP packets until
2182 * there is some significant data (media data or expected status notification).
2184 * @param s reading context
2185 * @param for_header non-zero value tells function to work until it
2186 * gets notification from the server that playing has been started,
2187 * otherwise function will work until some media data is received (or
2189 * @return 0 for successful operation, negative value in case of error
2191 static int get_packet(URLContext *s, int for_header)
2193 RTMPContext *rt = s->priv_data;
2196 const uint8_t *next;
2198 uint32_t ts, cts, pts=0;
2200 if (rt->state == STATE_STOPPED)
2204 RTMPPacket rpkt = { 0 };
2205 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2206 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2208 return AVERROR(EAGAIN);
2210 return AVERROR(EIO);
2213 rt->bytes_read += ret;
2214 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2215 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2216 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2218 rt->last_bytes_read = rt->bytes_read;
2221 ret = rtmp_parse_result(s, rt, &rpkt);
2223 // At this point we must check if we are in the seek state and continue
2224 // with the next packet. handle_invoke will get us out of this state
2225 // when the right message is encountered
2226 if (rt->state == STATE_SEEKING) {
2227 ff_rtmp_packet_destroy(&rpkt);
2228 // We continue, let the natural flow of things happen:
2229 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2233 if (ret < 0) {//serious error in current packet
2234 ff_rtmp_packet_destroy(&rpkt);
2237 if (rt->do_reconnect && for_header) {
2238 ff_rtmp_packet_destroy(&rpkt);
2241 if (rt->state == STATE_STOPPED) {
2242 ff_rtmp_packet_destroy(&rpkt);
2245 if (for_header && (rt->state == STATE_PLAYING ||
2246 rt->state == STATE_PUBLISHING ||
2247 rt->state == STATE_SENDING ||
2248 rt->state == STATE_RECEIVING)) {
2249 ff_rtmp_packet_destroy(&rpkt);
2252 if (!rpkt.size || !rt->is_input) {
2253 ff_rtmp_packet_destroy(&rpkt);
2256 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2257 (rpkt.type == RTMP_PT_NOTIFY &&
2258 ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2259 ts = rpkt.timestamp;
2261 // generate packet header and put data into buffer for FLV demuxer
2263 rt->flv_size = rpkt.size + 15;
2264 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2265 bytestream_put_byte(&p, rpkt.type);
2266 bytestream_put_be24(&p, rpkt.size);
2267 bytestream_put_be24(&p, ts);
2268 bytestream_put_byte(&p, ts >> 24);
2269 bytestream_put_be24(&p, 0);
2270 bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2271 bytestream_put_be32(&p, 0);
2272 ff_rtmp_packet_destroy(&rpkt);
2274 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2275 ret = handle_notify(s, &rpkt);
2276 ff_rtmp_packet_destroy(&rpkt);
2278 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2282 } else if (rpkt.type == RTMP_PT_METADATA) {
2283 // we got raw FLV data, make it available for FLV demuxer
2285 rt->flv_size = rpkt.size;
2286 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2287 /* rewrite timestamps */
2289 ts = rpkt.timestamp;
2290 while (next - rpkt.data < rpkt.size - 11) {
2292 size = bytestream_get_be24(&next);
2294 cts = bytestream_get_be24(&next);
2295 cts |= bytestream_get_byte(&next) << 24;
2300 bytestream_put_be24(&p, ts);
2301 bytestream_put_byte(&p, ts >> 24);
2302 next += size + 3 + 4;
2304 memcpy(rt->flv_data, rpkt.data, rpkt.size);
2305 ff_rtmp_packet_destroy(&rpkt);
2308 ff_rtmp_packet_destroy(&rpkt);
2312 static int rtmp_close(URLContext *h)
2314 RTMPContext *rt = h->priv_data;
2317 if (!rt->is_input) {
2318 rt->flv_data = NULL;
2319 if (rt->out_pkt.size)
2320 ff_rtmp_packet_destroy(&rt->out_pkt);
2321 if (rt->state > STATE_FCPUBLISH)
2322 ret = gen_fcunpublish_stream(h, rt);
2324 if (rt->state > STATE_HANDSHAKED)
2325 ret = gen_delete_stream(h, rt);
2327 free_tracked_methods(rt);
2328 av_freep(&rt->flv_data);
2329 ffurl_close(rt->stream);
2334 * Open RTMP connection and verify that the stream can be played.
2336 * URL syntax: rtmp://server[:port][/app][/playpath]
2337 * where 'app' is first one or two directories in the path
2338 * (e.g. /ondemand/, /flash/live/, etc.)
2339 * and 'playpath' is a file name (the rest of the path,
2340 * may be prefixed with "mp4:")
2342 static int rtmp_open(URLContext *s, const char *uri, int flags)
2344 RTMPContext *rt = s->priv_data;
2345 char proto[8], hostname[256], path[1024], auth[100], *fname;
2349 AVDictionary *opts = NULL;
2352 if (rt->listen_timeout > 0)
2355 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2357 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2358 hostname, sizeof(hostname), &port,
2359 path, sizeof(path), s->filename);
2361 if (strchr(path, ' ')) {
2362 av_log(s, AV_LOG_WARNING,
2363 "Detected librtmp style URL parameters, these aren't supported "
2364 "by the libavformat internal RTMP handler currently enabled. "
2365 "See the documentation for the correct way to pass parameters.\n");
2369 char *ptr = strchr(auth, ':');
2372 av_strlcpy(rt->username, auth, sizeof(rt->username));
2373 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2377 if (rt->listen && strcmp(proto, "rtmp")) {
2378 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2380 return AVERROR(EINVAL);
2382 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2383 if (!strcmp(proto, "rtmpts"))
2384 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2386 /* open the http tunneling connection */
2387 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2388 } else if (!strcmp(proto, "rtmps")) {
2389 /* open the tls connection */
2391 port = RTMPS_DEFAULT_PORT;
2392 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2393 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2394 if (!strcmp(proto, "rtmpte"))
2395 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2397 /* open the encrypted connection */
2398 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2401 /* open the tcp connection */
2403 port = RTMP_DEFAULT_PORT;
2405 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2406 "?listen&listen_timeout=%d",
2407 rt->listen_timeout * 1000);
2409 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2413 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2414 &s->interrupt_callback, &opts)) < 0) {
2415 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2419 if (rt->swfverify) {
2420 if ((ret = rtmp_calc_swfhash(s)) < 0)
2424 rt->state = STATE_START;
2425 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2427 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2430 rt->out_chunk_size = 128;
2431 rt->in_chunk_size = 128; // Probably overwritten later
2432 rt->state = STATE_HANDSHAKED;
2434 // Keep the application name when it has been defined by the user.
2437 rt->app = av_malloc(APP_MAX_LENGTH);
2439 ret = AVERROR(ENOMEM);
2443 //extract "app" part from path
2444 if (!strncmp(path, "/ondemand/", 10)) {
2446 memcpy(rt->app, "ondemand", 9);
2448 char *next = *path ? path + 1 : path;
2449 char *p = strchr(next, '/');
2454 // make sure we do not mismatch a playpath for an application instance
2455 char *c = strchr(p + 1, ':');
2456 fname = strchr(p + 1, '/');
2457 if (!fname || (c && c < fname)) {
2459 av_strlcpy(rt->app, path + 1, p - path);
2462 av_strlcpy(rt->app, path + 1, fname - path - 1);
2468 // The name of application has been defined by the user, override it.
2473 if (!rt->playpath) {
2474 int len = strlen(fname);
2476 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2477 if (!rt->playpath) {
2478 ret = AVERROR(ENOMEM);
2482 if (!strchr(fname, ':') && len >= 4 &&
2483 (!strcmp(fname + len - 4, ".f4v") ||
2484 !strcmp(fname + len - 4, ".mp4"))) {
2485 memcpy(rt->playpath, "mp4:", 5);
2486 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2487 fname[len - 4] = '\0';
2489 rt->playpath[0] = 0;
2491 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2495 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2497 ret = AVERROR(ENOMEM);
2500 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2501 port, "/%s", rt->app);
2504 if (!rt->flashver) {
2505 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2506 if (!rt->flashver) {
2507 ret = AVERROR(ENOMEM);
2511 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2512 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2513 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2515 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2516 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2520 rt->client_report_size = 1048576;
2522 rt->last_bytes_read = 0;
2523 rt->server_bw = 2500000;
2525 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2526 proto, path, rt->app, rt->playpath);
2528 if ((ret = gen_connect(s, rt)) < 0)
2531 if (read_connect(s, s->priv_data) < 0)
2536 ret = get_packet(s, 1);
2537 } while (ret == EAGAIN);
2541 if (rt->do_reconnect) {
2542 ffurl_close(rt->stream);
2544 rt->do_reconnect = 0;
2546 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2547 free_tracked_methods(rt);
2552 // generate FLV header for demuxer
2554 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2556 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2559 rt->flv_data = NULL;
2561 rt->skip_bytes = 13;
2564 s->max_packet_size = rt->stream->max_packet_size;
2569 av_dict_free(&opts);
2574 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2576 RTMPContext *rt = s->priv_data;
2577 int orig_size = size;
2581 int data_left = rt->flv_size - rt->flv_off;
2583 if (data_left >= size) {
2584 memcpy(buf, rt->flv_data + rt->flv_off, size);
2585 rt->flv_off += size;
2588 if (data_left > 0) {
2589 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2592 rt->flv_off = rt->flv_size;
2595 if ((ret = get_packet(s, 0)) < 0)
2601 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2604 RTMPContext *rt = s->priv_data;
2606 av_log(s, AV_LOG_DEBUG,
2607 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2608 stream_index, timestamp, flags);
2609 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2610 av_log(s, AV_LOG_ERROR,
2611 "Unable to send seek command on stream index %d at timestamp "
2612 "%"PRId64" with flags %08x\n",
2613 stream_index, timestamp, flags);
2616 rt->flv_off = rt->flv_size;
2617 rt->state = STATE_SEEKING;
2621 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2623 RTMPContext *rt = s->priv_data;
2624 int size_temp = size;
2625 int pktsize, pkttype;
2627 const uint8_t *buf_temp = buf;
2632 if (rt->skip_bytes) {
2633 int skip = FFMIN(rt->skip_bytes, size_temp);
2636 rt->skip_bytes -= skip;
2640 if (rt->flv_header_bytes < 11) {
2641 const uint8_t *header = rt->flv_header;
2642 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2643 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2644 rt->flv_header_bytes += copy;
2646 if (rt->flv_header_bytes < 11)
2649 pkttype = bytestream_get_byte(&header);
2650 pktsize = bytestream_get_be24(&header);
2651 ts = bytestream_get_be24(&header);
2652 ts |= bytestream_get_byte(&header) << 24;
2653 bytestream_get_be24(&header);
2654 rt->flv_size = pktsize;
2656 //force 12bytes header
2657 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2658 pkttype == RTMP_PT_NOTIFY) {
2659 if (pkttype == RTMP_PT_NOTIFY)
2661 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2664 //this can be a big packet, it's better to send it right here
2665 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2666 pkttype, ts, pktsize)) < 0)
2669 rt->out_pkt.extra = rt->main_channel_id;
2670 rt->flv_data = rt->out_pkt.data;
2672 if (pkttype == RTMP_PT_NOTIFY)
2673 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2676 if (rt->flv_size - rt->flv_off > size_temp) {
2677 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2678 rt->flv_off += size_temp;
2681 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2682 size_temp -= rt->flv_size - rt->flv_off;
2683 rt->flv_off += rt->flv_size - rt->flv_off;
2686 if (rt->flv_off == rt->flv_size) {
2689 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2693 rt->flv_header_bytes = 0;
2694 rt->flv_nb_packets++;
2696 } while (buf_temp - buf < size);
2698 if (rt->flv_nb_packets < rt->flush_interval)
2700 rt->flv_nb_packets = 0;
2702 /* set stream into nonblocking mode */
2703 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2705 /* try to read one byte from the stream */
2706 ret = ffurl_read(rt->stream, &c, 1);
2708 /* switch the stream back into blocking mode */
2709 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2711 if (ret == AVERROR(EAGAIN)) {
2712 /* no incoming data to handle */
2714 } else if (ret < 0) {
2716 } else if (ret == 1) {
2717 RTMPPacket rpkt = { 0 };
2719 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2721 rt->prev_pkt[0], c)) <= 0)
2724 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2727 ff_rtmp_packet_destroy(&rpkt);
2733 #define OFFSET(x) offsetof(RTMPContext, x)
2734 #define DEC AV_OPT_FLAG_DECODING_PARAM
2735 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2737 static const AVOption rtmp_options[] = {
2738 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2739 {"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},
2740 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2741 {"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},
2742 {"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},
2743 {"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"},
2744 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2745 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2746 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2747 {"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},
2748 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2749 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2750 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2751 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2752 {"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},
2753 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2754 {"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},
2755 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2756 {"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" },
2760 #define RTMP_PROTOCOL(flavor) \
2761 static const AVClass flavor##_class = { \
2762 .class_name = #flavor, \
2763 .item_name = av_default_item_name, \
2764 .option = rtmp_options, \
2765 .version = LIBAVUTIL_VERSION_INT, \
2768 URLProtocol ff_##flavor##_protocol = { \
2770 .url_open = rtmp_open, \
2771 .url_read = rtmp_read, \
2772 .url_read_seek = rtmp_seek, \
2773 .url_write = rtmp_write, \
2774 .url_close = rtmp_close, \
2775 .priv_data_size = sizeof(RTMPContext), \
2776 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2777 .priv_data_class= &flavor##_class, \
2782 RTMP_PROTOCOL(rtmpe)
2783 RTMP_PROTOCOL(rtmps)
2784 RTMP_PROTOCOL(rtmpt)
2785 RTMP_PROTOCOL(rtmpte)
2786 RTMP_PROTOCOL(rtmpts)