2 * RTMP network protocol
3 * Copyright (c) 2009 Kostya 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"
53 #define APP_MAX_LENGTH 1024
54 #define PLAYPATH_MAX_LENGTH 256
55 #define TCURL_MAX_LENGTH 512
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
59 /** RTMP protocol handler state */
61 STATE_START, ///< client has not done anything yet
62 STATE_HANDSHAKED, ///< client has performed handshake
63 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
64 STATE_PLAYING, ///< client has started receiving multimedia data from server
65 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66 STATE_RECEIVING, ///< received a publish command (for input)
67 STATE_STOPPED, ///< the broadcast has been stopped
70 typedef struct TrackedMethod {
75 /** protocol handler context */
76 typedef struct RTMPContext {
78 URLContext* stream; ///< TCP stream used in interactions with RTMP server
79 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
80 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
81 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
82 int is_input; ///< input/output flag
83 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
84 int live; ///< 0: recorded, -1: live, -2: both
85 char *app; ///< name of application
86 char *conn; ///< append arbitrary AMF data to the Connect message
87 ClientState state; ///< current state
88 int main_channel_id; ///< an additional channel ID which is used for some invocations
89 uint8_t* flv_data; ///< buffer with data for demuxer
90 int flv_size; ///< current buffer size
91 int flv_off; ///< number of bytes read from current buffer
92 int flv_nb_packets; ///< number of flv packets published
93 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
94 uint32_t client_report_size; ///< number of bytes after which client should report to server
95 uint32_t bytes_read; ///< number of bytes read from server
96 uint32_t last_bytes_read; ///< number of bytes read last reported to server
97 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
98 uint8_t flv_header[11]; ///< partial incoming flv packet header
99 int flv_header_bytes; ///< number of initialized bytes in flv_header
100 int nb_invokes; ///< keeps track of invoke messages
101 char* tcurl; ///< url of the target stream
102 char* flashver; ///< version of the flash plugin
103 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
104 int swfhash_len; ///< length of the SHA256 hash
105 int swfsize; ///< size of the decompressed SWF file
106 char* swfurl; ///< url of the swf player
107 char* swfverify; ///< URL to player swf file, compute hash/size automatically
108 char swfverification[42]; ///< hash of the SWF verification
109 char* pageurl; ///< url of the web page
110 char* subscribe; ///< name of live stream to subscribe
111 int server_bw; ///< server bandwidth
112 int client_buffer_time; ///< client buffer time in ms
113 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
114 int encrypted; ///< use an encrypted connection (RTMPE only)
115 TrackedMethod*tracked_methods; ///< tracked methods buffer
116 int nb_tracked_methods; ///< number of tracked methods
117 int tracked_methods_size; ///< size of the tracked methods buffer
118 int listen; ///< listen mode flag
119 int listen_timeout; ///< listen timeout to wait for new connections
120 int nb_streamid; ///< The next stream id to return on createStream calls
123 char auth_params[500];
128 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
129 /** Client key used for digest signing */
130 static const uint8_t rtmp_player_key[] = {
131 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
132 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
134 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
135 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
136 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
139 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
140 /** Key used for RTMP server digest signing */
141 static const uint8_t rtmp_server_key[] = {
142 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
143 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
144 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
146 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
147 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
148 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
151 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
155 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
156 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
157 ptr = av_realloc(rt->tracked_methods,
158 rt->tracked_methods_size * sizeof(*rt->tracked_methods));
160 return AVERROR(ENOMEM);
161 rt->tracked_methods = ptr;
164 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
165 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
166 return AVERROR(ENOMEM);
167 rt->tracked_methods[rt->nb_tracked_methods].id = id;
168 rt->nb_tracked_methods++;
173 static void del_tracked_method(RTMPContext *rt, int index)
175 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
176 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
177 rt->nb_tracked_methods--;
180 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
181 char **tracked_method)
183 RTMPContext *rt = s->priv_data;
189 bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset);
190 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
193 for (i = 0; i < rt->nb_tracked_methods; i++) {
194 if (rt->tracked_methods[i].id != pkt_id)
197 *tracked_method = rt->tracked_methods[i].name;
198 del_tracked_method(rt, i);
205 static void free_tracked_methods(RTMPContext *rt)
209 for (i = 0; i < rt->nb_tracked_methods; i ++)
210 av_free(rt->tracked_methods[i].name);
211 av_free(rt->tracked_methods);
212 rt->tracked_methods = NULL;
213 rt->tracked_methods_size = 0;
214 rt->nb_tracked_methods = 0;
217 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
221 if (pkt->type == RTMP_PT_INVOKE && track) {
227 bytestream2_init(&gbc, pkt->data, pkt->data_size);
228 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
231 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
234 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
238 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
241 ff_rtmp_packet_destroy(pkt);
245 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
250 /* The type must be B for Boolean, N for number, S for string, O for
251 * object, or Z for null. For Booleans the data must be either 0 or 1 for
252 * FALSE or TRUE, respectively. Likewise for Objects the data must be
253 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
254 * may be named, by prefixing the type with 'N' and specifying the name
255 * before the value (ie. NB:myFlag:1). This option may be used multiple times
256 * to construct arbitrary AMF sequences. */
257 if (param[0] && param[1] == ':') {
260 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
263 value = strchr(field, ':');
269 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.data_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.data_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.data_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.data_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.data_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.data_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);
710 * Generate 'publish' call and send it to the server.
712 static int gen_publish(URLContext *s, RTMPContext *rt)
718 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
720 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
721 0, 30 + strlen(rt->playpath))) < 0)
724 pkt.extra = rt->main_channel_id;
727 ff_amf_write_string(&p, "publish");
728 ff_amf_write_number(&p, ++rt->nb_invokes);
729 ff_amf_write_null(&p);
730 ff_amf_write_string(&p, rt->playpath);
731 ff_amf_write_string(&p, "live");
733 return rtmp_send_packet(rt, &pkt, 1);
737 * Generate ping reply and send it to the server.
739 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
745 if (ppkt->data_size < 6) {
746 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
748 return AVERROR_INVALIDDATA;
751 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
752 ppkt->timestamp + 1, 6)) < 0)
756 bytestream_put_be16(&p, 7);
757 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
759 return rtmp_send_packet(rt, &pkt, 0);
763 * Generate SWF verification message and send it to the server.
765 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
771 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
772 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
777 bytestream_put_be16(&p, 27);
778 memcpy(p, rt->swfverification, 42);
780 return rtmp_send_packet(rt, &pkt, 0);
784 * Generate server bandwidth message and send it to the server.
786 static int gen_server_bw(URLContext *s, RTMPContext *rt)
792 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
797 bytestream_put_be32(&p, rt->server_bw);
799 return rtmp_send_packet(rt, &pkt, 0);
803 * Generate check bandwidth message and send it to the server.
805 static int gen_check_bw(URLContext *s, RTMPContext *rt)
811 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
816 ff_amf_write_string(&p, "_checkbw");
817 ff_amf_write_number(&p, ++rt->nb_invokes);
818 ff_amf_write_null(&p);
820 return rtmp_send_packet(rt, &pkt, 1);
824 * Generate report on bytes read so far and send it to the server.
826 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
832 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
837 bytestream_put_be32(&p, rt->bytes_read);
839 return rtmp_send_packet(rt, &pkt, 0);
842 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
843 const char *subscribe)
849 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
850 0, 27 + strlen(subscribe))) < 0)
854 ff_amf_write_string(&p, "FCSubscribe");
855 ff_amf_write_number(&p, ++rt->nb_invokes);
856 ff_amf_write_null(&p);
857 ff_amf_write_string(&p, subscribe);
859 return rtmp_send_packet(rt, &pkt, 1);
862 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
863 const uint8_t *key, int keylen, uint8_t *dst)
866 uint8_t hmac_buf[64+32] = {0};
869 sha = av_sha_alloc();
871 return AVERROR(ENOMEM);
874 memcpy(hmac_buf, key, keylen);
876 av_sha_init(sha, 256);
877 av_sha_update(sha,key, keylen);
878 av_sha_final(sha, hmac_buf);
880 for (i = 0; i < 64; i++)
881 hmac_buf[i] ^= HMAC_IPAD_VAL;
883 av_sha_init(sha, 256);
884 av_sha_update(sha, hmac_buf, 64);
886 av_sha_update(sha, src, len);
887 } else { //skip 32 bytes used for storing digest
888 av_sha_update(sha, src, gap);
889 av_sha_update(sha, src + gap + 32, len - gap - 32);
891 av_sha_final(sha, hmac_buf + 64);
893 for (i = 0; i < 64; i++)
894 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
895 av_sha_init(sha, 256);
896 av_sha_update(sha, hmac_buf, 64+32);
897 av_sha_final(sha, dst);
904 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
907 int i, digest_pos = 0;
909 for (i = 0; i < 4; i++)
910 digest_pos += buf[i + off];
911 digest_pos = digest_pos % mod_val + add_val;
917 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
918 * will be stored) into that packet.
920 * @param buf handshake data (1536 bytes)
921 * @param encrypted use an encrypted connection (RTMPE)
922 * @return offset to the digest inside input data
924 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
929 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
931 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
933 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
934 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
943 * Verify that the received server response has the expected digest value.
945 * @param buf handshake data received from the server (1536 bytes)
946 * @param off position to search digest offset from
947 * @return 0 if digest is valid, digest position otherwise
949 static int rtmp_validate_digest(uint8_t *buf, int off)
954 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
956 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
957 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
962 if (!memcmp(digest, buf + digest_pos, 32))
967 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
973 if (rt->swfhash_len != 32) {
974 av_log(s, AV_LOG_ERROR,
975 "Hash of the decompressed SWF file is not 32 bytes long.\n");
976 return AVERROR(EINVAL);
979 p = &rt->swfverification[0];
980 bytestream_put_byte(&p, 1);
981 bytestream_put_byte(&p, 1);
982 bytestream_put_be32(&p, rt->swfsize);
983 bytestream_put_be32(&p, rt->swfsize);
985 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
992 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
993 uint8_t **out_data, int64_t *out_size)
1000 zs.avail_in = in_size;
1001 zs.next_in = in_data;
1002 ret = inflateInit(&zs);
1004 return AVERROR_UNKNOWN;
1007 uint8_t tmp_buf[16384];
1009 zs.avail_out = sizeof(tmp_buf);
1010 zs.next_out = tmp_buf;
1012 ret = inflate(&zs, Z_NO_FLUSH);
1013 if (ret != Z_OK && ret != Z_STREAM_END) {
1014 ret = AVERROR_UNKNOWN;
1018 size = sizeof(tmp_buf) - zs.avail_out;
1019 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1020 ret = AVERROR(ENOMEM);
1025 memcpy(*out_data + *out_size, tmp_buf, size);
1027 } while (zs.avail_out == 0);
1035 static int rtmp_calc_swfhash(URLContext *s)
1037 RTMPContext *rt = s->priv_data;
1038 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1039 int64_t in_size, out_size;
1045 /* Get the SWF player file. */
1046 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1047 &s->interrupt_callback, NULL)) < 0) {
1048 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1052 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1057 if (!(in_data = av_malloc(in_size))) {
1058 ret = AVERROR(ENOMEM);
1062 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1066 ret = AVERROR_INVALIDDATA;
1070 if (!memcmp(in_data, "CWS", 3)) {
1071 /* Decompress the SWF player file using Zlib. */
1072 if (!(out_data = av_malloc(8))) {
1073 ret = AVERROR(ENOMEM);
1076 *in_data = 'F'; // magic stuff
1077 memcpy(out_data, in_data, 8);
1081 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1082 &out_data, &out_size)) < 0)
1085 av_log(s, AV_LOG_ERROR,
1086 "Zlib is required for decompressing the SWF player file.\n");
1087 ret = AVERROR(EINVAL);
1097 /* Compute the SHA256 hash of the SWF player file. */
1098 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1099 "Genuine Adobe Flash Player 001", 30,
1103 /* Set SWFVerification parameters. */
1104 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1105 rt->swfsize = swfsize;
1109 av_freep(&out_data);
1110 ffurl_close(stream);
1115 * Perform handshake with the server by means of exchanging pseudorandom data
1116 * signed with HMAC-SHA2 digest.
1118 * @return 0 if handshake succeeds, negative value otherwise
1120 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1123 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1124 3, // unencrypted data
1125 0, 0, 0, 0, // client uptime
1131 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1132 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1134 int server_pos, client_pos;
1135 uint8_t digest[32], signature[32];
1138 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1140 av_lfg_init(&rnd, 0xDEADC0DE);
1141 // generate handshake packet - 1536 bytes of pseudorandom data
1142 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1143 tosend[i] = av_lfg_get(&rnd) >> 24;
1145 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1146 /* When the client wants to use RTMPE, we have to change the command
1147 * byte to 0x06 which means to use encrypted data and we have to set
1148 * the flash version to at least 9.0.115.0. */
1155 /* Initialize the Diffie-Hellmann context and generate the public key
1156 * to send to the server. */
1157 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1161 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1165 if ((ret = ffurl_write(rt->stream, tosend,
1166 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1167 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1171 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1172 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1173 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1177 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1178 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1179 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1183 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1184 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1185 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1187 if (rt->is_input && serverdata[5] >= 3) {
1188 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1194 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1199 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1200 return AVERROR(EIO);
1204 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1205 * key are the last 32 bytes of the server handshake. */
1207 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1208 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1212 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1213 rtmp_server_key, sizeof(rtmp_server_key),
1218 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1219 0, digest, 32, signature);
1223 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1224 /* Compute the shared secret key sent by the server and initialize
1225 * the RC4 encryption. */
1226 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1227 tosend + 1, type)) < 0)
1230 /* Encrypt the signature received by the server. */
1231 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1234 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1235 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1236 return AVERROR(EIO);
1239 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1240 tosend[i] = av_lfg_get(&rnd) >> 24;
1241 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1242 rtmp_player_key, sizeof(rtmp_player_key),
1247 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1249 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1253 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1254 /* Encrypt the signature to be send to the server. */
1255 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1256 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1260 // write reply back to the server
1261 if ((ret = ffurl_write(rt->stream, tosend,
1262 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1265 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1266 /* Set RC4 keys for encryption and update the keystreams. */
1267 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1271 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1272 /* Compute the shared secret key sent by the server and initialize
1273 * the RC4 encryption. */
1274 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1275 tosend + 1, 1)) < 0)
1278 if (serverdata[0] == 9) {
1279 /* Encrypt the signature received by the server. */
1280 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1285 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1286 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1289 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1290 /* Set RC4 keys for encryption and update the keystreams. */
1291 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1299 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1300 uint32_t *second_int, char *arraydata,
1305 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1306 RTMP_HANDSHAKE_PACKET_SIZE);
1308 return AVERROR(EIO);
1309 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1310 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1311 " not following standard\n", (int)inoutsize);
1312 return AVERROR(EINVAL);
1315 *first_int = AV_RB32(arraydata);
1316 *second_int = AV_RB32(arraydata + 4);
1320 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1321 uint32_t second_int, char *arraydata, int size)
1325 AV_WB32(arraydata, first_int);
1326 AV_WB32(arraydata + 4, first_int);
1327 inoutsize = ffurl_write(rt->stream, arraydata,
1328 RTMP_HANDSHAKE_PACKET_SIZE);
1329 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1330 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1331 return AVERROR(EIO);
1338 * rtmp handshake server side
1340 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1342 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1344 uint32_t hs_my_epoch;
1345 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1346 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1353 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1354 if (inoutsize <= 0) {
1355 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1356 return AVERROR(EIO);
1359 if (buffer[0] != 3) {
1360 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1361 return AVERROR(EIO);
1363 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1364 av_log(s, AV_LOG_ERROR,
1365 "Unable to write answer - RTMP S0\n");
1366 return AVERROR(EIO);
1369 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1370 RTMP_HANDSHAKE_PACKET_SIZE);
1372 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1376 av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1378 /* By now same epoch will be sent */
1379 hs_my_epoch = hs_epoch;
1380 /* Generate random */
1381 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1383 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1385 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1386 RTMP_HANDSHAKE_PACKET_SIZE);
1388 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1392 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1393 RTMP_HANDSHAKE_PACKET_SIZE);
1395 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1399 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1400 RTMP_HANDSHAKE_PACKET_SIZE);
1402 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1405 if (temp != hs_my_epoch)
1406 av_log(s, AV_LOG_WARNING,
1407 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1408 if (memcmp(buffer + 8, hs_s1 + 8,
1409 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1410 av_log(s, AV_LOG_WARNING,
1411 "Erroneous C2 Message random does not match up\n");
1416 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1418 RTMPContext *rt = s->priv_data;
1421 if (pkt->data_size < 4) {
1422 av_log(s, AV_LOG_ERROR,
1423 "Too short chunk size change packet (%d)\n",
1425 return AVERROR_INVALIDDATA;
1428 if (!rt->is_input) {
1429 /* Send the same chunk size change packet back to the server,
1430 * setting the outgoing chunk size to the same as the incoming one. */
1431 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1432 rt->prev_pkt[1])) < 0)
1434 rt->out_chunk_size = AV_RB32(pkt->data);
1437 rt->in_chunk_size = AV_RB32(pkt->data);
1438 if (rt->in_chunk_size <= 0) {
1439 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1441 return AVERROR_INVALIDDATA;
1443 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1449 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1451 RTMPContext *rt = s->priv_data;
1454 if (pkt->data_size < 2) {
1455 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1457 return AVERROR_INVALIDDATA;
1460 t = AV_RB16(pkt->data);
1462 if ((ret = gen_pong(s, rt, pkt)) < 0)
1464 } else if (t == 26) {
1466 if ((ret = gen_swf_verification(s, rt)) < 0)
1469 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1476 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1478 RTMPContext *rt = s->priv_data;
1480 if (pkt->data_size < 4) {
1481 av_log(s, AV_LOG_ERROR,
1482 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1484 return AVERROR_INVALIDDATA;
1487 rt->client_report_size = AV_RB32(pkt->data);
1488 if (rt->client_report_size <= 0) {
1489 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1490 rt->client_report_size);
1491 return AVERROR_INVALIDDATA;
1494 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1495 rt->client_report_size >>= 1;
1500 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1502 RTMPContext *rt = s->priv_data;
1504 if (pkt->data_size < 4) {
1505 av_log(s, AV_LOG_ERROR,
1506 "Too short server bandwidth report packet (%d)\n",
1508 return AVERROR_INVALIDDATA;
1511 rt->server_bw = AV_RB32(pkt->data);
1512 if (rt->server_bw <= 0) {
1513 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1515 return AVERROR_INVALIDDATA;
1517 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1522 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1523 const char *opaque, const char *challenge)
1526 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1527 struct AVMD5 *md5 = av_md5_alloc();
1529 return AVERROR(ENOMEM);
1531 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1534 av_md5_update(md5, user, strlen(user));
1535 av_md5_update(md5, salt, strlen(salt));
1536 av_md5_update(md5, rt->password, strlen(rt->password));
1537 av_md5_final(md5, hash);
1538 av_base64_encode(hashstr, sizeof(hashstr), hash,
1541 av_md5_update(md5, hashstr, strlen(hashstr));
1543 av_md5_update(md5, opaque, strlen(opaque));
1545 av_md5_update(md5, challenge, strlen(challenge));
1546 av_md5_update(md5, challenge2, strlen(challenge2));
1547 av_md5_final(md5, hash);
1548 av_base64_encode(hashstr, sizeof(hashstr), hash,
1550 snprintf(rt->auth_params, sizeof(rt->auth_params),
1551 "?authmod=%s&user=%s&challenge=%s&response=%s",
1552 "adobe", user, challenge2, hashstr);
1554 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1555 "&opaque=%s", opaque);
1561 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1564 char hashstr1[33], hashstr2[33];
1565 const char *realm = "live";
1566 const char *method = "publish";
1567 const char *qop = "auth";
1568 const char *nc = "00000001";
1570 struct AVMD5 *md5 = av_md5_alloc();
1572 return AVERROR(ENOMEM);
1574 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1577 av_md5_update(md5, user, strlen(user));
1578 av_md5_update(md5, ":", 1);
1579 av_md5_update(md5, realm, strlen(realm));
1580 av_md5_update(md5, ":", 1);
1581 av_md5_update(md5, rt->password, strlen(rt->password));
1582 av_md5_final(md5, hash);
1583 ff_data_to_hex(hashstr1, hash, 16, 1);
1584 hashstr1[32] = '\0';
1587 av_md5_update(md5, method, strlen(method));
1588 av_md5_update(md5, ":/", 2);
1589 av_md5_update(md5, rt->app, strlen(rt->app));
1590 av_md5_final(md5, hash);
1591 ff_data_to_hex(hashstr2, hash, 16, 1);
1592 hashstr2[32] = '\0';
1595 av_md5_update(md5, hashstr1, strlen(hashstr1));
1596 av_md5_update(md5, ":", 1);
1598 av_md5_update(md5, nonce, strlen(nonce));
1599 av_md5_update(md5, ":", 1);
1600 av_md5_update(md5, nc, strlen(nc));
1601 av_md5_update(md5, ":", 1);
1602 av_md5_update(md5, cnonce, strlen(cnonce));
1603 av_md5_update(md5, ":", 1);
1604 av_md5_update(md5, qop, strlen(qop));
1605 av_md5_update(md5, ":", 1);
1606 av_md5_update(md5, hashstr2, strlen(hashstr2));
1607 av_md5_final(md5, hash);
1608 ff_data_to_hex(hashstr1, hash, 16, 1);
1610 snprintf(rt->auth_params, sizeof(rt->auth_params),
1611 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1612 "llnw", user, nonce, cnonce, nc, hashstr1);
1618 static int handle_connect_error(URLContext *s, const char *desc)
1620 RTMPContext *rt = s->priv_data;
1621 char buf[300], *ptr, authmod[15];
1623 const char *user = "", *salt = "", *opaque = NULL,
1624 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1626 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1627 !(cptr = strstr(desc, "authmod=llnw"))) {
1628 av_log(s, AV_LOG_ERROR,
1629 "Unknown connect error (unsupported authentication method?)\n");
1630 return AVERROR_UNKNOWN;
1632 cptr += strlen("authmod=");
1633 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1634 authmod[i++] = *cptr++;
1637 if (!rt->username[0] || !rt->password[0]) {
1638 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1639 return AVERROR_UNKNOWN;
1642 if (strstr(desc, "?reason=authfailed")) {
1643 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1644 return AVERROR_UNKNOWN;
1645 } else if (strstr(desc, "?reason=nosuchuser")) {
1646 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1647 return AVERROR_UNKNOWN;
1650 if (rt->auth_tried) {
1651 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1652 return AVERROR_UNKNOWN;
1655 rt->auth_params[0] = '\0';
1657 if (strstr(desc, "code=403 need auth")) {
1658 snprintf(rt->auth_params, sizeof(rt->auth_params),
1659 "?authmod=%s&user=%s", authmod, rt->username);
1663 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1664 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1665 return AVERROR_UNKNOWN;
1668 av_strlcpy(buf, cptr + 1, sizeof(buf));
1672 char *next = strchr(ptr, '&');
1673 char *value = strchr(ptr, '=');
1678 if (!strcmp(ptr, "user")) {
1680 } else if (!strcmp(ptr, "salt")) {
1682 } else if (!strcmp(ptr, "opaque")) {
1684 } else if (!strcmp(ptr, "challenge")) {
1686 } else if (!strcmp(ptr, "nonce")) {
1692 if (!strcmp(authmod, "adobe")) {
1693 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1696 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1704 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1706 RTMPContext *rt = s->priv_data;
1707 const uint8_t *data_end = pkt->data + pkt->data_size;
1708 char *tracked_method = NULL;
1709 int level = AV_LOG_ERROR;
1710 uint8_t tmpstr[256];
1713 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1716 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1717 "description", tmpstr, sizeof(tmpstr))) {
1718 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1719 !strcmp(tracked_method, "releaseStream") ||
1720 !strcmp(tracked_method, "FCSubscribe") ||
1721 !strcmp(tracked_method, "FCPublish"))) {
1722 /* Gracefully ignore Adobe-specific historical artifact errors. */
1723 level = AV_LOG_WARNING;
1725 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1726 ret = handle_connect_error(s, tmpstr);
1728 rt->do_reconnect = 1;
1729 level = AV_LOG_VERBOSE;
1732 ret = AVERROR_UNKNOWN;
1733 av_log(s, level, "Server error: %s\n", tmpstr);
1736 av_free(tracked_method);
1740 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1742 RTMPContext *rt = s->priv_data;
1746 char statusmsg[128];
1749 const uint8_t *p = pkt->data;
1751 RTMPPacket spkt = { 0 };
1755 bytestream2_init(&gbc, p, pkt->data_size);
1756 if (ff_amf_read_string(&gbc, command, sizeof(command),
1758 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1759 return AVERROR_INVALIDDATA;
1762 ret = ff_amf_read_number(&gbc, &seqnum);
1765 ret = ff_amf_read_null(&gbc);
1768 if (!strcmp(command, "FCPublish") ||
1769 !strcmp(command, "publish")) {
1770 ret = ff_amf_read_string(&gbc, filename,
1771 sizeof(filename), &stringlen);
1774 pchar = strrchr(s->filename, '/');
1776 av_log(s, AV_LOG_WARNING,
1777 "Unable to find / in url %s, bad format\n",
1779 pchar = s->filename;
1782 if (strcmp(pchar, filename))
1783 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1784 " %s\n", filename, pchar);
1786 rt->state = STATE_RECEIVING;
1789 if (!strcmp(command, "FCPublish")) {
1790 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1792 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1793 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1797 ff_amf_write_string(&pp, "onFCPublish");
1798 } else if (!strcmp(command, "publish")) {
1800 // Send Stream Begin 1
1801 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1802 RTMP_PT_PING, 0, 6)) < 0) {
1803 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1807 bytestream2_init_writer(&pbc, pp, spkt.data_size);
1808 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1809 bytestream2_put_be32(&pbc, rt->nb_streamid);
1810 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1812 ff_rtmp_packet_destroy(&spkt);
1816 // Send onStatus(NetStream.Publish.Start)
1817 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1819 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1820 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1823 spkt.extra = pkt->extra;
1825 ff_amf_write_string(&pp, "onStatus");
1826 ff_amf_write_number(&pp, 0);
1827 ff_amf_write_null(&pp);
1829 ff_amf_write_object_start(&pp);
1830 ff_amf_write_field_name(&pp, "level");
1831 ff_amf_write_string(&pp, "status");
1832 ff_amf_write_field_name(&pp, "code");
1833 ff_amf_write_string(&pp, "NetStream.Publish.Start");
1834 ff_amf_write_field_name(&pp, "description");
1835 snprintf(statusmsg, sizeof(statusmsg),
1836 "%s is now published", filename);
1837 ff_amf_write_string(&pp, statusmsg);
1838 ff_amf_write_field_name(&pp, "details");
1839 ff_amf_write_string(&pp, filename);
1840 ff_amf_write_field_name(&pp, "clientid");
1841 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1842 ff_amf_write_string(&pp, statusmsg);
1843 ff_amf_write_object_end(&pp);
1846 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1848 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1849 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1853 ff_amf_write_string(&pp, "_result");
1854 ff_amf_write_number(&pp, seqnum);
1855 ff_amf_write_null(&pp);
1856 if (!strcmp(command, "createStream")) {
1858 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1859 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1860 ff_amf_write_number(&pp, rt->nb_streamid);
1861 /* By now we don't control which streams are removed in
1862 * deleteStream. There is no stream creation control
1863 * if a client creates more than 2^32 - 2 streams. */
1866 spkt.data_size = pp - spkt.data;
1867 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1869 ff_rtmp_packet_destroy(&spkt);
1873 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1875 RTMPContext *rt = s->priv_data;
1876 char *tracked_method = NULL;
1879 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1882 if (!tracked_method) {
1883 /* Ignore this reply when the current method is not tracked. */
1887 if (!memcmp(tracked_method, "connect", 7)) {
1888 if (!rt->is_input) {
1889 if ((ret = gen_release_stream(s, rt)) < 0)
1892 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1895 if ((ret = gen_server_bw(s, rt)) < 0)
1899 if ((ret = gen_create_stream(s, rt)) < 0)
1903 /* Send the FCSubscribe command when the name of live
1904 * stream is defined by the user or if it's a live stream. */
1905 if (rt->subscribe) {
1906 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1908 } else if (rt->live == -1) {
1909 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1913 } else if (!memcmp(tracked_method, "createStream", 12)) {
1914 //extract a number from the result
1915 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1916 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1918 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1921 if (!rt->is_input) {
1922 if ((ret = gen_publish(s, rt)) < 0)
1925 if ((ret = gen_play(s, rt)) < 0)
1927 if ((ret = gen_buffer_time(s, rt)) < 0)
1933 av_free(tracked_method);
1937 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1939 RTMPContext *rt = s->priv_data;
1940 const uint8_t *data_end = pkt->data + pkt->data_size;
1941 const uint8_t *ptr = pkt->data + 11;
1942 uint8_t tmpstr[256];
1945 for (i = 0; i < 2; i++) {
1946 t = ff_amf_tag_size(ptr, data_end);
1952 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1953 if (!t && !strcmp(tmpstr, "error")) {
1954 if (!ff_amf_get_field_value(ptr, data_end,
1955 "description", tmpstr, sizeof(tmpstr)))
1956 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1960 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1961 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1962 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1963 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1964 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1969 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1971 RTMPContext *rt = s->priv_data;
1974 //TODO: check for the messages sent for wrong state?
1975 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1976 if ((ret = handle_invoke_error(s, pkt)) < 0)
1978 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1979 if ((ret = handle_invoke_result(s, pkt)) < 0)
1981 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1982 if ((ret = handle_invoke_status(s, pkt)) < 0)
1984 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1985 if ((ret = gen_check_bw(s, rt)) < 0)
1987 } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1988 !memcmp(pkt->data, "\002\000\011FCPublish", 12) ||
1989 !memcmp(pkt->data, "\002\000\007publish", 10) ||
1990 !memcmp(pkt->data, "\002\000\010_checkbw", 11) ||
1991 !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1992 if ((ret = send_invoke_response(s, pkt)) < 0)
1999 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2000 RTMPContext *rt = s->priv_data;
2001 const uint8_t *p = NULL;
2003 uint8_t commandbuffer[64];
2004 char statusmsg[128];
2010 const uint8_t *datatowrite;
2011 unsigned datatowritelength;
2014 bytestream2_init(&gbc, p, pkt->data_size);
2015 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2017 return AVERROR_INVALIDDATA;
2018 if (!strcmp(commandbuffer, "@setDataFrame")) {
2019 datatowrite = gbc.buffer;
2020 datatowritelength = bytestream2_get_bytes_left(&gbc);
2021 if (ff_amf_read_string(&gbc, statusmsg,
2022 sizeof(statusmsg), &stringlen))
2023 return AVERROR_INVALIDDATA;
2024 if (strcmp(statusmsg, "onMetaData")) {
2025 av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
2030 /* Provide ECMAArray to flv */
2031 ts = pkt->timestamp;
2033 // generate packet header and put data into buffer for FLV demuxer
2034 if (rt->flv_off < rt->flv_size) {
2035 old_flv_size = rt->flv_size;
2036 rt->flv_size += datatowritelength + 15;
2039 rt->flv_size = datatowritelength + 15;
2043 cp = av_realloc(rt->flv_data, rt->flv_size);
2045 return AVERROR(ENOMEM);
2047 bytestream2_init_writer(&pbc, cp, rt->flv_size);
2048 bytestream2_skip_p(&pbc, old_flv_size);
2049 bytestream2_put_byte(&pbc, pkt->type);
2050 bytestream2_put_be24(&pbc, datatowritelength);
2051 bytestream2_put_be24(&pbc, ts);
2052 bytestream2_put_byte(&pbc, ts >> 24);
2053 bytestream2_put_be24(&pbc, 0);
2054 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2055 bytestream2_put_be32(&pbc, 0);
2061 * Parse received packet and possibly perform some action depending on
2062 * the packet contents.
2063 * @return 0 for no errors, negative values for serious errors which prevent
2064 * further communications, positive values for uncritical errors
2066 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2071 ff_rtmp_packet_dump(s, pkt);
2074 switch (pkt->type) {
2075 case RTMP_PT_BYTES_READ:
2076 av_dlog(s, "received bytes read report\n");
2078 case RTMP_PT_CHUNK_SIZE:
2079 if ((ret = handle_chunk_size(s, pkt)) < 0)
2083 if ((ret = handle_ping(s, pkt)) < 0)
2086 case RTMP_PT_CLIENT_BW:
2087 if ((ret = handle_client_bw(s, pkt)) < 0)
2090 case RTMP_PT_SERVER_BW:
2091 if ((ret = handle_server_bw(s, pkt)) < 0)
2094 case RTMP_PT_INVOKE:
2095 if ((ret = handle_invoke(s, pkt)) < 0)
2100 case RTMP_PT_METADATA:
2101 case RTMP_PT_NOTIFY:
2102 /* Audio, Video and Metadata packets are parsed in get_packet() */
2105 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2112 * Interact with the server by receiving and sending RTMP packets until
2113 * there is some significant data (media data or expected status notification).
2115 * @param s reading context
2116 * @param for_header non-zero value tells function to work until it
2117 * gets notification from the server that playing has been started,
2118 * otherwise function will work until some media data is received (or
2120 * @return 0 for successful operation, negative value in case of error
2122 static int get_packet(URLContext *s, int for_header)
2124 RTMPContext *rt = s->priv_data;
2127 const uint8_t *next;
2129 uint32_t ts, cts, pts=0;
2131 if (rt->state == STATE_STOPPED)
2135 RTMPPacket rpkt = { 0 };
2136 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2137 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2139 return AVERROR(EAGAIN);
2141 return AVERROR(EIO);
2144 rt->bytes_read += ret;
2145 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2146 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2147 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2149 rt->last_bytes_read = rt->bytes_read;
2152 ret = rtmp_parse_result(s, rt, &rpkt);
2153 if (ret < 0) {//serious error in current packet
2154 ff_rtmp_packet_destroy(&rpkt);
2157 if (rt->do_reconnect && for_header) {
2158 ff_rtmp_packet_destroy(&rpkt);
2161 if (rt->state == STATE_STOPPED) {
2162 ff_rtmp_packet_destroy(&rpkt);
2165 if (for_header && (rt->state == STATE_PLAYING ||
2166 rt->state == STATE_PUBLISHING ||
2167 rt->state == STATE_RECEIVING)) {
2168 ff_rtmp_packet_destroy(&rpkt);
2171 if (!rpkt.data_size || !rt->is_input) {
2172 ff_rtmp_packet_destroy(&rpkt);
2175 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2176 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2177 ts = rpkt.timestamp;
2179 // generate packet header and put data into buffer for FLV demuxer
2181 rt->flv_size = rpkt.data_size + 15;
2182 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2183 bytestream_put_byte(&p, rpkt.type);
2184 bytestream_put_be24(&p, rpkt.data_size);
2185 bytestream_put_be24(&p, ts);
2186 bytestream_put_byte(&p, ts >> 24);
2187 bytestream_put_be24(&p, 0);
2188 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2189 bytestream_put_be32(&p, 0);
2190 ff_rtmp_packet_destroy(&rpkt);
2192 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2193 ret = handle_notify(s, &rpkt);
2194 ff_rtmp_packet_destroy(&rpkt);
2196 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2200 } else if (rpkt.type == RTMP_PT_METADATA) {
2201 // we got raw FLV data, make it available for FLV demuxer
2203 rt->flv_size = rpkt.data_size;
2204 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2205 /* rewrite timestamps */
2207 ts = rpkt.timestamp;
2208 while (next - rpkt.data < rpkt.data_size - 11) {
2210 data_size = bytestream_get_be24(&next);
2212 cts = bytestream_get_be24(&next);
2213 cts |= bytestream_get_byte(&next) << 24;
2218 bytestream_put_be24(&p, ts);
2219 bytestream_put_byte(&p, ts >> 24);
2220 next += data_size + 3 + 4;
2222 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2223 ff_rtmp_packet_destroy(&rpkt);
2226 ff_rtmp_packet_destroy(&rpkt);
2230 static int rtmp_close(URLContext *h)
2232 RTMPContext *rt = h->priv_data;
2235 if (!rt->is_input) {
2236 rt->flv_data = NULL;
2237 if (rt->out_pkt.data_size)
2238 ff_rtmp_packet_destroy(&rt->out_pkt);
2239 if (rt->state > STATE_FCPUBLISH)
2240 ret = gen_fcunpublish_stream(h, rt);
2242 if (rt->state > STATE_HANDSHAKED)
2243 ret = gen_delete_stream(h, rt);
2245 free_tracked_methods(rt);
2246 av_freep(&rt->flv_data);
2247 ffurl_close(rt->stream);
2252 * Open RTMP connection and verify that the stream can be played.
2254 * URL syntax: rtmp://server[:port][/app][/playpath]
2255 * where 'app' is first one or two directories in the path
2256 * (e.g. /ondemand/, /flash/live/, etc.)
2257 * and 'playpath' is a file name (the rest of the path,
2258 * may be prefixed with "mp4:")
2260 static int rtmp_open(URLContext *s, const char *uri, int flags)
2262 RTMPContext *rt = s->priv_data;
2263 char proto[8], hostname[256], path[1024], auth[100], *fname;
2267 AVDictionary *opts = NULL;
2270 if (rt->listen_timeout > 0)
2273 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2275 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2276 hostname, sizeof(hostname), &port,
2277 path, sizeof(path), s->filename);
2280 char *ptr = strchr(auth, ':');
2283 av_strlcpy(rt->username, auth, sizeof(rt->username));
2284 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2288 if (rt->listen && strcmp(proto, "rtmp")) {
2289 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2291 return AVERROR(EINVAL);
2293 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2294 if (!strcmp(proto, "rtmpts"))
2295 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2297 /* open the http tunneling connection */
2298 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2299 } else if (!strcmp(proto, "rtmps")) {
2300 /* open the tls connection */
2302 port = RTMPS_DEFAULT_PORT;
2303 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2304 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2305 if (!strcmp(proto, "rtmpte"))
2306 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2308 /* open the encrypted connection */
2309 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2312 /* open the tcp connection */
2314 port = RTMP_DEFAULT_PORT;
2316 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2317 "?listen&listen_timeout=%d",
2318 rt->listen_timeout * 1000);
2320 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2324 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2325 &s->interrupt_callback, &opts)) < 0) {
2326 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2330 if (rt->swfverify) {
2331 if ((ret = rtmp_calc_swfhash(s)) < 0)
2335 rt->state = STATE_START;
2336 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2338 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2341 rt->out_chunk_size = 128;
2342 rt->in_chunk_size = 128; // Probably overwritten later
2343 rt->state = STATE_HANDSHAKED;
2345 // Keep the application name when it has been defined by the user.
2348 rt->app = av_malloc(APP_MAX_LENGTH);
2350 ret = AVERROR(ENOMEM);
2354 //extract "app" part from path
2355 if (!strncmp(path, "/ondemand/", 10)) {
2357 memcpy(rt->app, "ondemand", 9);
2359 char *next = *path ? path + 1 : path;
2360 char *p = strchr(next, '/');
2365 // make sure we do not mismatch a playpath for an application instance
2366 char *c = strchr(p + 1, ':');
2367 fname = strchr(p + 1, '/');
2368 if (!fname || (c && c < fname)) {
2370 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2373 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2379 // The name of application has been defined by the user, override it.
2380 if (strlen(old_app) >= APP_MAX_LENGTH) {
2381 ret = AVERROR(EINVAL);
2388 if (!rt->playpath) {
2389 int len = strlen(fname);
2391 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2392 if (!rt->playpath) {
2393 ret = AVERROR(ENOMEM);
2397 if (!strchr(fname, ':') && len >= 4 &&
2398 (!strcmp(fname + len - 4, ".f4v") ||
2399 !strcmp(fname + len - 4, ".mp4"))) {
2400 memcpy(rt->playpath, "mp4:", 5);
2401 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2402 fname[len - 4] = '\0';
2404 rt->playpath[0] = 0;
2406 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2410 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2412 ret = AVERROR(ENOMEM);
2415 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2416 port, "/%s", rt->app);
2419 if (!rt->flashver) {
2420 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2421 if (!rt->flashver) {
2422 ret = AVERROR(ENOMEM);
2426 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2427 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2428 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2430 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2431 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2435 rt->client_report_size = 1048576;
2437 rt->last_bytes_read = 0;
2438 rt->server_bw = 2500000;
2440 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2441 proto, path, rt->app, rt->playpath);
2443 if ((ret = gen_connect(s, rt)) < 0)
2446 if (read_connect(s, s->priv_data) < 0)
2452 ret = get_packet(s, 1);
2453 } while (ret == EAGAIN);
2457 if (rt->do_reconnect) {
2458 ffurl_close(rt->stream);
2460 rt->do_reconnect = 0;
2462 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2463 free_tracked_methods(rt);
2468 // generate FLV header for demuxer
2470 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2472 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2475 rt->flv_data = NULL;
2477 rt->skip_bytes = 13;
2480 s->max_packet_size = rt->stream->max_packet_size;
2485 av_dict_free(&opts);
2490 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2492 RTMPContext *rt = s->priv_data;
2493 int orig_size = size;
2497 int data_left = rt->flv_size - rt->flv_off;
2499 if (data_left >= size) {
2500 memcpy(buf, rt->flv_data + rt->flv_off, size);
2501 rt->flv_off += size;
2504 if (data_left > 0) {
2505 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2508 rt->flv_off = rt->flv_size;
2511 if ((ret = get_packet(s, 0)) < 0)
2517 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2519 RTMPContext *rt = s->priv_data;
2520 int size_temp = size;
2521 int pktsize, pkttype;
2523 const uint8_t *buf_temp = buf;
2528 if (rt->skip_bytes) {
2529 int skip = FFMIN(rt->skip_bytes, size_temp);
2532 rt->skip_bytes -= skip;
2536 if (rt->flv_header_bytes < 11) {
2537 const uint8_t *header = rt->flv_header;
2538 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2539 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2540 rt->flv_header_bytes += copy;
2542 if (rt->flv_header_bytes < 11)
2545 pkttype = bytestream_get_byte(&header);
2546 pktsize = bytestream_get_be24(&header);
2547 ts = bytestream_get_be24(&header);
2548 ts |= bytestream_get_byte(&header) << 24;
2549 bytestream_get_be24(&header);
2550 rt->flv_size = pktsize;
2552 //force 12bytes header
2553 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2554 pkttype == RTMP_PT_NOTIFY) {
2555 if (pkttype == RTMP_PT_NOTIFY)
2557 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2560 //this can be a big packet, it's better to send it right here
2561 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2562 pkttype, ts, pktsize)) < 0)
2565 rt->out_pkt.extra = rt->main_channel_id;
2566 rt->flv_data = rt->out_pkt.data;
2568 if (pkttype == RTMP_PT_NOTIFY)
2569 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2572 if (rt->flv_size - rt->flv_off > size_temp) {
2573 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2574 rt->flv_off += size_temp;
2577 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2578 size_temp -= rt->flv_size - rt->flv_off;
2579 rt->flv_off += rt->flv_size - rt->flv_off;
2582 if (rt->flv_off == rt->flv_size) {
2585 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2589 rt->flv_header_bytes = 0;
2590 rt->flv_nb_packets++;
2592 } while (buf_temp - buf < size);
2594 if (rt->flv_nb_packets < rt->flush_interval)
2596 rt->flv_nb_packets = 0;
2598 /* set stream into nonblocking mode */
2599 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2601 /* try to read one byte from the stream */
2602 ret = ffurl_read(rt->stream, &c, 1);
2604 /* switch the stream back into blocking mode */
2605 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2607 if (ret == AVERROR(EAGAIN)) {
2608 /* no incoming data to handle */
2610 } else if (ret < 0) {
2612 } else if (ret == 1) {
2613 RTMPPacket rpkt = { 0 };
2615 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2617 rt->prev_pkt[0], c)) <= 0)
2620 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2623 ff_rtmp_packet_destroy(&rpkt);
2629 #define OFFSET(x) offsetof(RTMPContext, x)
2630 #define DEC AV_OPT_FLAG_DECODING_PARAM
2631 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2633 static const AVOption rtmp_options[] = {
2634 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2635 {"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},
2636 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2637 {"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},
2638 {"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},
2639 {"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"},
2640 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2641 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2642 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2643 {"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},
2644 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2645 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2646 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2647 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2648 {"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},
2649 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2650 {"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},
2651 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2652 {"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" },
2656 #define RTMP_PROTOCOL(flavor) \
2657 static const AVClass flavor##_class = { \
2658 .class_name = #flavor, \
2659 .item_name = av_default_item_name, \
2660 .option = rtmp_options, \
2661 .version = LIBAVUTIL_VERSION_INT, \
2664 URLProtocol ff_##flavor##_protocol = { \
2666 .url_open = rtmp_open, \
2667 .url_read = rtmp_read, \
2668 .url_write = rtmp_write, \
2669 .url_close = rtmp_close, \
2670 .priv_data_size = sizeof(RTMPContext), \
2671 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2672 .priv_data_class= &flavor##_class, \
2677 RTMP_PROTOCOL(rtmpe)
2678 RTMP_PROTOCOL(rtmps)
2679 RTMP_PROTOCOL(rtmpt)
2680 RTMP_PROTOCOL(rtmpte)
2681 RTMP_PROTOCOL(rtmpts)