2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 1024
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56 #define RTMP_HEADER 11
58 /** RTMP protocol handler state */
60 STATE_START, ///< client has not done anything yet
61 STATE_HANDSHAKED, ///< client has performed handshake
62 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
63 STATE_PLAYING, ///< client has started receiving multimedia data from server
64 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66 STATE_RECEIVING, ///< received a publish command (for input)
67 STATE_SENDING, ///< received a play command (for output)
68 STATE_STOPPED, ///< the broadcast has been stopped
71 typedef struct TrackedMethod {
76 /** protocol handler context */
77 typedef struct RTMPContext {
79 URLContext* stream; ///< TCP stream used in interactions with RTMP server
80 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
82 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
83 int is_input; ///< input/output flag
84 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
85 int live; ///< 0: recorded, -1: live, -2: both
86 char *app; ///< name of application
87 char *conn; ///< append arbitrary AMF data to the Connect message
88 ClientState state; ///< current state
89 int stream_id; ///< ID assigned by the server for the stream
90 uint8_t* flv_data; ///< buffer with data for demuxer
91 int flv_size; ///< current buffer size
92 int flv_off; ///< number of bytes read from current buffer
93 int flv_nb_packets; ///< number of flv packets published
94 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
95 uint32_t client_report_size; ///< number of bytes after which client should report to server
96 uint32_t bytes_read; ///< number of bytes read from server
97 uint32_t last_bytes_read; ///< number of bytes read last reported to server
98 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
99 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
100 int flv_header_bytes; ///< number of initialized bytes in flv_header
101 int nb_invokes; ///< keeps track of invoke messages
102 char* tcurl; ///< url of the target stream
103 char* flashver; ///< version of the flash plugin
104 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
105 int swfhash_len; ///< length of the SHA256 hash
106 int swfsize; ///< size of the decompressed SWF file
107 char* swfurl; ///< url of the swf player
108 char* swfverify; ///< URL to player swf file, compute hash/size automatically
109 char swfverification[42]; ///< hash of the SWF verification
110 char* pageurl; ///< url of the web page
111 char* subscribe; ///< name of live stream to subscribe
112 int server_bw; ///< server bandwidth
113 int client_buffer_time; ///< client buffer time in ms
114 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
115 int encrypted; ///< use an encrypted connection (RTMPE only)
116 TrackedMethod*tracked_methods; ///< tracked methods buffer
117 int nb_tracked_methods; ///< number of tracked methods
118 int tracked_methods_size; ///< size of the tracked methods buffer
119 int listen; ///< listen mode flag
120 int listen_timeout; ///< listen timeout to wait for new connections
121 int nb_streamid; ///< The next stream id to return on createStream calls
124 char auth_params[500];
129 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
130 /** Client key used for digest signing */
131 static const uint8_t rtmp_player_key[] = {
132 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
133 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
135 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
136 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
137 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
140 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
141 /** Key used for RTMP server digest signing */
142 static const uint8_t rtmp_server_key[] = {
143 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
144 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
145 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
147 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
148 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
149 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
152 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
156 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
157 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
158 if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
159 sizeof(*rt->tracked_methods))) < 0) {
160 rt->nb_tracked_methods = 0;
161 rt->tracked_methods_size = 0;
166 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
167 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
168 return AVERROR(ENOMEM);
169 rt->tracked_methods[rt->nb_tracked_methods].id = id;
170 rt->nb_tracked_methods++;
175 static void del_tracked_method(RTMPContext *rt, int index)
177 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
178 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
179 rt->nb_tracked_methods--;
182 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
183 char **tracked_method)
185 RTMPContext *rt = s->priv_data;
191 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
192 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
195 for (i = 0; i < rt->nb_tracked_methods; i++) {
196 if (rt->tracked_methods[i].id != pkt_id)
199 *tracked_method = rt->tracked_methods[i].name;
200 del_tracked_method(rt, i);
207 static void free_tracked_methods(RTMPContext *rt)
211 for (i = 0; i < rt->nb_tracked_methods; i ++)
212 av_free(rt->tracked_methods[i].name);
213 av_free(rt->tracked_methods);
214 rt->tracked_methods = NULL;
215 rt->tracked_methods_size = 0;
216 rt->nb_tracked_methods = 0;
219 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
223 if (pkt->type == RTMP_PT_INVOKE && track) {
229 bytestream2_init(&gbc, pkt->data, pkt->size);
230 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
233 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
236 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
240 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
243 ff_rtmp_packet_destroy(pkt);
247 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
252 /* The type must be B for Boolean, N for number, S for string, O for
253 * object, or Z for null. For Booleans the data must be either 0 or 1 for
254 * FALSE or TRUE, respectively. Likewise for Objects the data must be
255 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
256 * may be named, by prefixing the type with 'N' and specifying the name
257 * before the value (ie. NB:myFlag:1). This option may be used multiple times
258 * to construct arbitrary AMF sequences. */
259 if (param[0] && param[1] == ':') {
262 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
265 value = strchr(field, ':');
271 ff_amf_write_field_name(p, field);
278 ff_amf_write_bool(p, value[0] != '0');
281 ff_amf_write_string(p, value);
284 ff_amf_write_number(p, strtod(value, NULL));
287 ff_amf_write_null(p);
291 ff_amf_write_object_start(p);
293 ff_amf_write_object_end(p);
303 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
304 return AVERROR(EINVAL);
308 * Generate 'connect' call and send it to the server.
310 static int gen_connect(URLContext *s, RTMPContext *rt)
316 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
317 0, 4096 + APP_MAX_LENGTH)) < 0)
322 ff_amf_write_string(&p, "connect");
323 ff_amf_write_number(&p, ++rt->nb_invokes);
324 ff_amf_write_object_start(&p);
325 ff_amf_write_field_name(&p, "app");
326 ff_amf_write_string2(&p, rt->app, rt->auth_params);
329 ff_amf_write_field_name(&p, "type");
330 ff_amf_write_string(&p, "nonprivate");
332 ff_amf_write_field_name(&p, "flashVer");
333 ff_amf_write_string(&p, rt->flashver);
336 ff_amf_write_field_name(&p, "swfUrl");
337 ff_amf_write_string(&p, rt->swfurl);
340 ff_amf_write_field_name(&p, "tcUrl");
341 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
343 ff_amf_write_field_name(&p, "fpad");
344 ff_amf_write_bool(&p, 0);
345 ff_amf_write_field_name(&p, "capabilities");
346 ff_amf_write_number(&p, 15.0);
348 /* Tell the server we support all the audio codecs except
349 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
350 * which are unused in the RTMP protocol implementation. */
351 ff_amf_write_field_name(&p, "audioCodecs");
352 ff_amf_write_number(&p, 4071.0);
353 ff_amf_write_field_name(&p, "videoCodecs");
354 ff_amf_write_number(&p, 252.0);
355 ff_amf_write_field_name(&p, "videoFunction");
356 ff_amf_write_number(&p, 1.0);
359 ff_amf_write_field_name(&p, "pageUrl");
360 ff_amf_write_string(&p, rt->pageurl);
363 ff_amf_write_object_end(&p);
366 char *param = rt->conn;
368 // Write arbitrary AMF data to the Connect message.
369 while (param != NULL) {
371 param += strspn(param, " ");
374 sep = strchr(param, ' ');
377 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
378 // Invalid AMF parameter.
379 ff_rtmp_packet_destroy(&pkt);
390 pkt.size = p - pkt.data;
392 return rtmp_send_packet(rt, &pkt, 1);
395 static int read_connect(URLContext *s, RTMPContext *rt)
397 RTMPPacket pkt = { 0 };
407 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
408 rt->prev_pkt[0])) < 0)
411 bytestream2_init(&gbc, cp, pkt.size);
412 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
413 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
414 ff_rtmp_packet_destroy(&pkt);
415 return AVERROR_INVALIDDATA;
417 if (strcmp(command, "connect")) {
418 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
419 ff_rtmp_packet_destroy(&pkt);
420 return AVERROR_INVALIDDATA;
422 ret = ff_amf_read_number(&gbc, &seqnum);
424 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
425 /* Here one could parse an AMF Object with data as flashVers and others. */
426 ret = ff_amf_get_field_value(gbc.buffer,
427 gbc.buffer + bytestream2_get_bytes_left(&gbc),
428 "app", tmpstr, sizeof(tmpstr));
430 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
431 if (!ret && strcmp(tmpstr, rt->app))
432 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
434 ff_rtmp_packet_destroy(&pkt);
436 // Send Window Acknowledgement Size (as defined in speficication)
437 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
438 RTMP_PT_SERVER_BW, 0, 4)) < 0)
441 bytestream_put_be32(&p, rt->server_bw);
442 pkt.size = p - pkt.data;
443 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
445 ff_rtmp_packet_destroy(&pkt);
448 // Send Peer Bandwidth
449 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
450 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
453 bytestream_put_be32(&p, rt->server_bw);
454 bytestream_put_byte(&p, 2); // dynamic
455 pkt.size = p - pkt.data;
456 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
458 ff_rtmp_packet_destroy(&pkt);
463 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
464 RTMP_PT_PING, 0, 6)) < 0)
468 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
469 bytestream_put_be32(&p, 0);
470 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
472 ff_rtmp_packet_destroy(&pkt);
477 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
478 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
482 bytestream_put_be32(&p, rt->out_chunk_size);
483 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
485 ff_rtmp_packet_destroy(&pkt);
489 // Send result_ NetConnection.Connect.Success to connect
490 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
492 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
496 ff_amf_write_string(&p, "_result");
497 ff_amf_write_number(&p, seqnum);
499 ff_amf_write_object_start(&p);
500 ff_amf_write_field_name(&p, "fmsVer");
501 ff_amf_write_string(&p, "FMS/3,0,1,123");
502 ff_amf_write_field_name(&p, "capabilities");
503 ff_amf_write_number(&p, 31);
504 ff_amf_write_object_end(&p);
506 ff_amf_write_object_start(&p);
507 ff_amf_write_field_name(&p, "level");
508 ff_amf_write_string(&p, "status");
509 ff_amf_write_field_name(&p, "code");
510 ff_amf_write_string(&p, "NetConnection.Connect.Success");
511 ff_amf_write_field_name(&p, "description");
512 ff_amf_write_string(&p, "Connection succeeded.");
513 ff_amf_write_field_name(&p, "objectEncoding");
514 ff_amf_write_number(&p, 0);
515 ff_amf_write_object_end(&p);
517 pkt.size = p - pkt.data;
518 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
520 ff_rtmp_packet_destroy(&pkt);
524 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
525 RTMP_PT_INVOKE, 0, 30)) < 0)
528 ff_amf_write_string(&p, "onBWDone");
529 ff_amf_write_number(&p, 0);
530 ff_amf_write_null(&p);
531 ff_amf_write_number(&p, 8192);
532 pkt.size = p - pkt.data;
533 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
535 ff_rtmp_packet_destroy(&pkt);
541 * Generate 'releaseStream' call and send it to the server. It should make
542 * the server release some channel for media streams.
544 static int gen_release_stream(URLContext *s, RTMPContext *rt)
550 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
551 0, 29 + strlen(rt->playpath))) < 0)
554 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
556 ff_amf_write_string(&p, "releaseStream");
557 ff_amf_write_number(&p, ++rt->nb_invokes);
558 ff_amf_write_null(&p);
559 ff_amf_write_string(&p, rt->playpath);
561 return rtmp_send_packet(rt, &pkt, 1);
565 * Generate 'FCPublish' call and send it to the server. It should make
566 * the server preapare for receiving media streams.
568 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
574 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
575 0, 25 + strlen(rt->playpath))) < 0)
578 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
580 ff_amf_write_string(&p, "FCPublish");
581 ff_amf_write_number(&p, ++rt->nb_invokes);
582 ff_amf_write_null(&p);
583 ff_amf_write_string(&p, rt->playpath);
585 return rtmp_send_packet(rt, &pkt, 1);
589 * Generate 'FCUnpublish' call and send it to the server. It should make
590 * the server destroy stream.
592 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
598 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
599 0, 27 + strlen(rt->playpath))) < 0)
602 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
604 ff_amf_write_string(&p, "FCUnpublish");
605 ff_amf_write_number(&p, ++rt->nb_invokes);
606 ff_amf_write_null(&p);
607 ff_amf_write_string(&p, rt->playpath);
609 return rtmp_send_packet(rt, &pkt, 0);
613 * Generate 'createStream' call and send it to the server. It should make
614 * the server allocate some channel for media streams.
616 static int gen_create_stream(URLContext *s, RTMPContext *rt)
622 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
624 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
629 ff_amf_write_string(&p, "createStream");
630 ff_amf_write_number(&p, ++rt->nb_invokes);
631 ff_amf_write_null(&p);
633 return rtmp_send_packet(rt, &pkt, 1);
638 * Generate 'deleteStream' call and send it to the server. It should make
639 * the server remove some channel for media streams.
641 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
647 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
649 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
654 ff_amf_write_string(&p, "deleteStream");
655 ff_amf_write_number(&p, ++rt->nb_invokes);
656 ff_amf_write_null(&p);
657 ff_amf_write_number(&p, rt->stream_id);
659 return rtmp_send_packet(rt, &pkt, 0);
663 * Generate client buffer time and send it to the server.
665 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
671 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
676 bytestream_put_be16(&p, 3);
677 bytestream_put_be32(&p, rt->stream_id);
678 bytestream_put_be32(&p, rt->client_buffer_time);
680 return rtmp_send_packet(rt, &pkt, 0);
684 * Generate 'play' call and send it to the server, then ping the server
685 * to start actual playing.
687 static int gen_play(URLContext *s, RTMPContext *rt)
693 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
695 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
696 0, 29 + strlen(rt->playpath))) < 0)
699 pkt.extra = rt->stream_id;
702 ff_amf_write_string(&p, "play");
703 ff_amf_write_number(&p, ++rt->nb_invokes);
704 ff_amf_write_null(&p);
705 ff_amf_write_string(&p, rt->playpath);
706 ff_amf_write_number(&p, rt->live);
708 return rtmp_send_packet(rt, &pkt, 1);
711 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
717 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
720 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
723 pkt.extra = rt->stream_id;
726 ff_amf_write_string(&p, "seek");
727 ff_amf_write_number(&p, 0); //no tracking back responses
728 ff_amf_write_null(&p); //as usual, the first null param
729 ff_amf_write_number(&p, timestamp); //where we want to jump
731 return rtmp_send_packet(rt, &pkt, 1);
735 * Generate 'publish' call and send it to the server.
737 static int gen_publish(URLContext *s, RTMPContext *rt)
743 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
745 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
746 0, 30 + strlen(rt->playpath))) < 0)
749 pkt.extra = rt->stream_id;
752 ff_amf_write_string(&p, "publish");
753 ff_amf_write_number(&p, ++rt->nb_invokes);
754 ff_amf_write_null(&p);
755 ff_amf_write_string(&p, rt->playpath);
756 ff_amf_write_string(&p, "live");
758 return rtmp_send_packet(rt, &pkt, 1);
762 * Generate ping reply and send it to the server.
764 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
770 if (ppkt->size < 6) {
771 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
773 return AVERROR_INVALIDDATA;
776 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
777 ppkt->timestamp + 1, 6)) < 0)
781 bytestream_put_be16(&p, 7);
782 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
784 return rtmp_send_packet(rt, &pkt, 0);
788 * Generate SWF verification message and send it to the server.
790 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
796 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
797 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
802 bytestream_put_be16(&p, 27);
803 memcpy(p, rt->swfverification, 42);
805 return rtmp_send_packet(rt, &pkt, 0);
809 * Generate server bandwidth message and send it to the server.
811 static int gen_server_bw(URLContext *s, RTMPContext *rt)
817 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
822 bytestream_put_be32(&p, rt->server_bw);
824 return rtmp_send_packet(rt, &pkt, 0);
828 * Generate check bandwidth message and send it to the server.
830 static int gen_check_bw(URLContext *s, RTMPContext *rt)
836 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
841 ff_amf_write_string(&p, "_checkbw");
842 ff_amf_write_number(&p, ++rt->nb_invokes);
843 ff_amf_write_null(&p);
845 return rtmp_send_packet(rt, &pkt, 1);
849 * Generate report on bytes read so far and send it to the server.
851 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
857 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
862 bytestream_put_be32(&p, rt->bytes_read);
864 return rtmp_send_packet(rt, &pkt, 0);
867 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
868 const char *subscribe)
874 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
875 0, 27 + strlen(subscribe))) < 0)
879 ff_amf_write_string(&p, "FCSubscribe");
880 ff_amf_write_number(&p, ++rt->nb_invokes);
881 ff_amf_write_null(&p);
882 ff_amf_write_string(&p, subscribe);
884 return rtmp_send_packet(rt, &pkt, 1);
887 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
888 const uint8_t *key, int keylen, uint8_t *dst)
891 uint8_t hmac_buf[64+32] = {0};
894 sha = av_sha_alloc();
896 return AVERROR(ENOMEM);
899 memcpy(hmac_buf, key, keylen);
901 av_sha_init(sha, 256);
902 av_sha_update(sha,key, keylen);
903 av_sha_final(sha, hmac_buf);
905 for (i = 0; i < 64; i++)
906 hmac_buf[i] ^= HMAC_IPAD_VAL;
908 av_sha_init(sha, 256);
909 av_sha_update(sha, hmac_buf, 64);
911 av_sha_update(sha, src, len);
912 } else { //skip 32 bytes used for storing digest
913 av_sha_update(sha, src, gap);
914 av_sha_update(sha, src + gap + 32, len - gap - 32);
916 av_sha_final(sha, hmac_buf + 64);
918 for (i = 0; i < 64; i++)
919 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
920 av_sha_init(sha, 256);
921 av_sha_update(sha, hmac_buf, 64+32);
922 av_sha_final(sha, dst);
929 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
932 int i, digest_pos = 0;
934 for (i = 0; i < 4; i++)
935 digest_pos += buf[i + off];
936 digest_pos = digest_pos % mod_val + add_val;
942 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
943 * will be stored) into that packet.
945 * @param buf handshake data (1536 bytes)
946 * @param encrypted use an encrypted connection (RTMPE)
947 * @return offset to the digest inside input data
949 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
954 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
956 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
958 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
959 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
968 * Verify that the received server response has the expected digest value.
970 * @param buf handshake data received from the server (1536 bytes)
971 * @param off position to search digest offset from
972 * @return 0 if digest is valid, digest position otherwise
974 static int rtmp_validate_digest(uint8_t *buf, int off)
979 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
981 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
982 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
987 if (!memcmp(digest, buf + digest_pos, 32))
992 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
998 if (rt->swfhash_len != 32) {
999 av_log(s, AV_LOG_ERROR,
1000 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1001 return AVERROR(EINVAL);
1004 p = &rt->swfverification[0];
1005 bytestream_put_byte(&p, 1);
1006 bytestream_put_byte(&p, 1);
1007 bytestream_put_be32(&p, rt->swfsize);
1008 bytestream_put_be32(&p, rt->swfsize);
1010 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1017 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1018 uint8_t **out_data, int64_t *out_size)
1020 z_stream zs = { 0 };
1025 zs.avail_in = in_size;
1026 zs.next_in = in_data;
1027 ret = inflateInit(&zs);
1029 return AVERROR_UNKNOWN;
1032 uint8_t tmp_buf[16384];
1034 zs.avail_out = sizeof(tmp_buf);
1035 zs.next_out = tmp_buf;
1037 ret = inflate(&zs, Z_NO_FLUSH);
1038 if (ret != Z_OK && ret != Z_STREAM_END) {
1039 ret = AVERROR_UNKNOWN;
1043 size = sizeof(tmp_buf) - zs.avail_out;
1044 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1045 ret = AVERROR(ENOMEM);
1050 memcpy(*out_data + *out_size, tmp_buf, size);
1052 } while (zs.avail_out == 0);
1060 static int rtmp_calc_swfhash(URLContext *s)
1062 RTMPContext *rt = s->priv_data;
1063 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1064 int64_t in_size, out_size;
1070 /* Get the SWF player file. */
1071 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1072 &s->interrupt_callback, NULL)) < 0) {
1073 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1077 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1082 if (!(in_data = av_malloc(in_size))) {
1083 ret = AVERROR(ENOMEM);
1087 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1091 ret = AVERROR_INVALIDDATA;
1095 if (!memcmp(in_data, "CWS", 3)) {
1096 /* Decompress the SWF player file using Zlib. */
1097 if (!(out_data = av_malloc(8))) {
1098 ret = AVERROR(ENOMEM);
1101 *in_data = 'F'; // magic stuff
1102 memcpy(out_data, in_data, 8);
1106 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1107 &out_data, &out_size)) < 0)
1110 av_log(s, AV_LOG_ERROR,
1111 "Zlib is required for decompressing the SWF player file.\n");
1112 ret = AVERROR(EINVAL);
1122 /* Compute the SHA256 hash of the SWF player file. */
1123 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1124 "Genuine Adobe Flash Player 001", 30,
1128 /* Set SWFVerification parameters. */
1129 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1130 rt->swfsize = swfsize;
1134 av_freep(&out_data);
1135 ffurl_close(stream);
1140 * Perform handshake with the server by means of exchanging pseudorandom data
1141 * signed with HMAC-SHA2 digest.
1143 * @return 0 if handshake succeeds, negative value otherwise
1145 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1148 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1149 3, // unencrypted data
1150 0, 0, 0, 0, // client uptime
1156 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1157 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1159 int server_pos, client_pos;
1160 uint8_t digest[32], signature[32];
1163 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1165 av_lfg_init(&rnd, 0xDEADC0DE);
1166 // generate handshake packet - 1536 bytes of pseudorandom data
1167 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1168 tosend[i] = av_lfg_get(&rnd) >> 24;
1170 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1171 /* When the client wants to use RTMPE, we have to change the command
1172 * byte to 0x06 which means to use encrypted data and we have to set
1173 * the flash version to at least 9.0.115.0. */
1180 /* Initialize the Diffie-Hellmann context and generate the public key
1181 * to send to the server. */
1182 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1186 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1190 if ((ret = ffurl_write(rt->stream, tosend,
1191 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1192 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1196 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1197 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1198 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1202 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1203 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1204 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1208 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1209 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1210 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1212 if (rt->is_input && serverdata[5] >= 3) {
1213 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1219 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1224 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1225 return AVERROR(EIO);
1229 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1230 * key are the last 32 bytes of the server handshake. */
1232 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1233 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1237 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1238 rtmp_server_key, sizeof(rtmp_server_key),
1243 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1244 0, digest, 32, signature);
1248 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1249 /* Compute the shared secret key sent by the server and initialize
1250 * the RC4 encryption. */
1251 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1252 tosend + 1, type)) < 0)
1255 /* Encrypt the signature received by the server. */
1256 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1259 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1260 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1261 return AVERROR(EIO);
1264 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1265 tosend[i] = av_lfg_get(&rnd) >> 24;
1266 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1267 rtmp_player_key, sizeof(rtmp_player_key),
1272 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1274 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1278 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1279 /* Encrypt the signature to be send to the server. */
1280 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1281 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1285 // write reply back to the server
1286 if ((ret = ffurl_write(rt->stream, tosend,
1287 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1290 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1291 /* Set RC4 keys for encryption and update the keystreams. */
1292 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1296 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1297 /* Compute the shared secret key sent by the server and initialize
1298 * the RC4 encryption. */
1299 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1300 tosend + 1, 1)) < 0)
1303 if (serverdata[0] == 9) {
1304 /* Encrypt the signature received by the server. */
1305 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1310 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1311 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1314 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1315 /* Set RC4 keys for encryption and update the keystreams. */
1316 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1324 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1325 uint32_t *second_int, char *arraydata,
1330 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1331 RTMP_HANDSHAKE_PACKET_SIZE);
1333 return AVERROR(EIO);
1334 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1335 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1336 " not following standard\n", (int)inoutsize);
1337 return AVERROR(EINVAL);
1340 *first_int = AV_RB32(arraydata);
1341 *second_int = AV_RB32(arraydata + 4);
1345 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1346 uint32_t second_int, char *arraydata, int size)
1350 AV_WB32(arraydata, first_int);
1351 AV_WB32(arraydata + 4, second_int);
1352 inoutsize = ffurl_write(rt->stream, arraydata,
1353 RTMP_HANDSHAKE_PACKET_SIZE);
1354 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1355 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1356 return AVERROR(EIO);
1363 * rtmp handshake server side
1365 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1367 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1369 uint32_t hs_my_epoch;
1370 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1371 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1378 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1379 if (inoutsize <= 0) {
1380 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1381 return AVERROR(EIO);
1384 if (buffer[0] != 3) {
1385 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1386 return AVERROR(EIO);
1388 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1389 av_log(s, AV_LOG_ERROR,
1390 "Unable to write answer - RTMP S0\n");
1391 return AVERROR(EIO);
1394 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1395 RTMP_HANDSHAKE_PACKET_SIZE);
1397 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1401 /* By now same epoch will be sent */
1402 hs_my_epoch = hs_epoch;
1403 /* Generate random */
1404 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1406 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1408 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1409 RTMP_HANDSHAKE_PACKET_SIZE);
1411 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1415 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1416 RTMP_HANDSHAKE_PACKET_SIZE);
1418 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1422 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1423 RTMP_HANDSHAKE_PACKET_SIZE);
1425 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1428 if (temp != hs_my_epoch)
1429 av_log(s, AV_LOG_WARNING,
1430 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1431 if (memcmp(buffer + 8, hs_s1 + 8,
1432 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1433 av_log(s, AV_LOG_WARNING,
1434 "Erroneous C2 Message random does not match up\n");
1439 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1441 RTMPContext *rt = s->priv_data;
1444 if (pkt->size < 4) {
1445 av_log(s, AV_LOG_ERROR,
1446 "Too short chunk size change packet (%d)\n",
1448 return AVERROR_INVALIDDATA;
1451 if (!rt->is_input) {
1452 /* Send the same chunk size change packet back to the server,
1453 * setting the outgoing chunk size to the same as the incoming one. */
1454 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1455 rt->prev_pkt[1])) < 0)
1457 rt->out_chunk_size = AV_RB32(pkt->data);
1460 rt->in_chunk_size = AV_RB32(pkt->data);
1461 if (rt->in_chunk_size <= 0) {
1462 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1464 return AVERROR_INVALIDDATA;
1466 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1472 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1474 RTMPContext *rt = s->priv_data;
1477 if (pkt->size < 2) {
1478 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1480 return AVERROR_INVALIDDATA;
1483 t = AV_RB16(pkt->data);
1485 if ((ret = gen_pong(s, rt, pkt)) < 0)
1487 } else if (t == 26) {
1489 if ((ret = gen_swf_verification(s, rt)) < 0)
1492 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1499 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1501 RTMPContext *rt = s->priv_data;
1503 if (pkt->size < 4) {
1504 av_log(s, AV_LOG_ERROR,
1505 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1507 return AVERROR_INVALIDDATA;
1510 rt->client_report_size = AV_RB32(pkt->data);
1511 if (rt->client_report_size <= 0) {
1512 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1513 rt->client_report_size);
1514 return AVERROR_INVALIDDATA;
1517 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1518 rt->client_report_size >>= 1;
1523 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1525 RTMPContext *rt = s->priv_data;
1527 if (pkt->size < 4) {
1528 av_log(s, AV_LOG_ERROR,
1529 "Too short server bandwidth report packet (%d)\n",
1531 return AVERROR_INVALIDDATA;
1534 rt->server_bw = AV_RB32(pkt->data);
1535 if (rt->server_bw <= 0) {
1536 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1538 return AVERROR_INVALIDDATA;
1540 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1545 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1546 const char *opaque, const char *challenge)
1549 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1550 struct AVMD5 *md5 = av_md5_alloc();
1552 return AVERROR(ENOMEM);
1554 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1557 av_md5_update(md5, user, strlen(user));
1558 av_md5_update(md5, salt, strlen(salt));
1559 av_md5_update(md5, rt->password, strlen(rt->password));
1560 av_md5_final(md5, hash);
1561 av_base64_encode(hashstr, sizeof(hashstr), hash,
1564 av_md5_update(md5, hashstr, strlen(hashstr));
1566 av_md5_update(md5, opaque, strlen(opaque));
1568 av_md5_update(md5, challenge, strlen(challenge));
1569 av_md5_update(md5, challenge2, strlen(challenge2));
1570 av_md5_final(md5, hash);
1571 av_base64_encode(hashstr, sizeof(hashstr), hash,
1573 snprintf(rt->auth_params, sizeof(rt->auth_params),
1574 "?authmod=%s&user=%s&challenge=%s&response=%s",
1575 "adobe", user, challenge2, hashstr);
1577 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1578 "&opaque=%s", opaque);
1584 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1587 char hashstr1[33], hashstr2[33];
1588 const char *realm = "live";
1589 const char *method = "publish";
1590 const char *qop = "auth";
1591 const char *nc = "00000001";
1593 struct AVMD5 *md5 = av_md5_alloc();
1595 return AVERROR(ENOMEM);
1597 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1600 av_md5_update(md5, user, strlen(user));
1601 av_md5_update(md5, ":", 1);
1602 av_md5_update(md5, realm, strlen(realm));
1603 av_md5_update(md5, ":", 1);
1604 av_md5_update(md5, rt->password, strlen(rt->password));
1605 av_md5_final(md5, hash);
1606 ff_data_to_hex(hashstr1, hash, 16, 1);
1607 hashstr1[32] = '\0';
1610 av_md5_update(md5, method, strlen(method));
1611 av_md5_update(md5, ":/", 2);
1612 av_md5_update(md5, rt->app, strlen(rt->app));
1613 if (!strchr(rt->app, '/'))
1614 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1615 av_md5_final(md5, hash);
1616 ff_data_to_hex(hashstr2, hash, 16, 1);
1617 hashstr2[32] = '\0';
1620 av_md5_update(md5, hashstr1, strlen(hashstr1));
1621 av_md5_update(md5, ":", 1);
1623 av_md5_update(md5, nonce, strlen(nonce));
1624 av_md5_update(md5, ":", 1);
1625 av_md5_update(md5, nc, strlen(nc));
1626 av_md5_update(md5, ":", 1);
1627 av_md5_update(md5, cnonce, strlen(cnonce));
1628 av_md5_update(md5, ":", 1);
1629 av_md5_update(md5, qop, strlen(qop));
1630 av_md5_update(md5, ":", 1);
1631 av_md5_update(md5, hashstr2, strlen(hashstr2));
1632 av_md5_final(md5, hash);
1633 ff_data_to_hex(hashstr1, hash, 16, 1);
1635 snprintf(rt->auth_params, sizeof(rt->auth_params),
1636 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1637 "llnw", user, nonce, cnonce, nc, hashstr1);
1643 static int handle_connect_error(URLContext *s, const char *desc)
1645 RTMPContext *rt = s->priv_data;
1646 char buf[300], *ptr, authmod[15];
1648 const char *user = "", *salt = "", *opaque = NULL,
1649 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1651 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1652 !(cptr = strstr(desc, "authmod=llnw"))) {
1653 av_log(s, AV_LOG_ERROR,
1654 "Unknown connect error (unsupported authentication method?)\n");
1655 return AVERROR_UNKNOWN;
1657 cptr += strlen("authmod=");
1658 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1659 authmod[i++] = *cptr++;
1662 if (!rt->username[0] || !rt->password[0]) {
1663 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1664 return AVERROR_UNKNOWN;
1667 if (strstr(desc, "?reason=authfailed")) {
1668 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1669 return AVERROR_UNKNOWN;
1670 } else if (strstr(desc, "?reason=nosuchuser")) {
1671 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1672 return AVERROR_UNKNOWN;
1675 if (rt->auth_tried) {
1676 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1677 return AVERROR_UNKNOWN;
1680 rt->auth_params[0] = '\0';
1682 if (strstr(desc, "code=403 need auth")) {
1683 snprintf(rt->auth_params, sizeof(rt->auth_params),
1684 "?authmod=%s&user=%s", authmod, rt->username);
1688 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1689 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1690 return AVERROR_UNKNOWN;
1693 av_strlcpy(buf, cptr + 1, sizeof(buf));
1697 char *next = strchr(ptr, '&');
1698 char *value = strchr(ptr, '=');
1703 if (!strcmp(ptr, "user")) {
1705 } else if (!strcmp(ptr, "salt")) {
1707 } else if (!strcmp(ptr, "opaque")) {
1709 } else if (!strcmp(ptr, "challenge")) {
1711 } else if (!strcmp(ptr, "nonce")) {
1717 if (!strcmp(authmod, "adobe")) {
1718 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1721 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1729 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1731 RTMPContext *rt = s->priv_data;
1732 const uint8_t *data_end = pkt->data + pkt->size;
1733 char *tracked_method = NULL;
1734 int level = AV_LOG_ERROR;
1735 uint8_t tmpstr[256];
1738 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1741 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1742 "description", tmpstr, sizeof(tmpstr))) {
1743 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1744 !strcmp(tracked_method, "releaseStream") ||
1745 !strcmp(tracked_method, "FCSubscribe") ||
1746 !strcmp(tracked_method, "FCPublish"))) {
1747 /* Gracefully ignore Adobe-specific historical artifact errors. */
1748 level = AV_LOG_WARNING;
1750 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1751 ret = handle_connect_error(s, tmpstr);
1753 rt->do_reconnect = 1;
1754 level = AV_LOG_VERBOSE;
1757 ret = AVERROR_UNKNOWN;
1758 av_log(s, level, "Server error: %s\n", tmpstr);
1761 av_free(tracked_method);
1765 static int write_begin(URLContext *s)
1767 RTMPContext *rt = s->priv_data;
1769 RTMPPacket spkt = { 0 };
1772 // Send Stream Begin 1
1773 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1774 RTMP_PT_PING, 0, 6)) < 0) {
1775 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1779 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1780 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1781 bytestream2_put_be32(&pbc, rt->nb_streamid);
1783 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1786 ff_rtmp_packet_destroy(&spkt);
1791 static int write_status(URLContext *s, RTMPPacket *pkt,
1792 const char *status, const char *filename)
1794 RTMPContext *rt = s->priv_data;
1795 RTMPPacket spkt = { 0 };
1796 char statusmsg[128];
1800 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1802 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1803 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1808 spkt.extra = pkt->extra;
1809 ff_amf_write_string(&pp, "onStatus");
1810 ff_amf_write_number(&pp, 0);
1811 ff_amf_write_null(&pp);
1813 ff_amf_write_object_start(&pp);
1814 ff_amf_write_field_name(&pp, "level");
1815 ff_amf_write_string(&pp, "status");
1816 ff_amf_write_field_name(&pp, "code");
1817 ff_amf_write_string(&pp, status);
1818 ff_amf_write_field_name(&pp, "description");
1819 snprintf(statusmsg, sizeof(statusmsg),
1820 "%s is now published", filename);
1821 ff_amf_write_string(&pp, statusmsg);
1822 ff_amf_write_field_name(&pp, "details");
1823 ff_amf_write_string(&pp, filename);
1824 ff_amf_write_field_name(&pp, "clientid");
1825 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1826 ff_amf_write_string(&pp, statusmsg);
1827 ff_amf_write_object_end(&pp);
1829 spkt.size = pp - spkt.data;
1830 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1832 ff_rtmp_packet_destroy(&spkt);
1837 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1839 RTMPContext *rt = s->priv_data;
1845 const uint8_t *p = pkt->data;
1847 RTMPPacket spkt = { 0 };
1851 bytestream2_init(&gbc, p, pkt->size);
1852 if (ff_amf_read_string(&gbc, command, sizeof(command),
1854 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1855 return AVERROR_INVALIDDATA;
1858 ret = ff_amf_read_number(&gbc, &seqnum);
1861 ret = ff_amf_read_null(&gbc);
1864 if (!strcmp(command, "FCPublish") ||
1865 !strcmp(command, "publish")) {
1866 ret = ff_amf_read_string(&gbc, filename,
1867 sizeof(filename), &stringlen);
1870 pchar = strrchr(s->filename, '/');
1872 av_log(s, AV_LOG_WARNING,
1873 "Unable to find / in url %s, bad format\n",
1875 pchar = s->filename;
1878 if (strcmp(pchar, filename))
1879 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1880 " %s\n", filename, pchar);
1882 rt->state = STATE_RECEIVING;
1885 if (!strcmp(command, "FCPublish")) {
1886 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1888 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1889 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1893 ff_amf_write_string(&pp, "onFCPublish");
1894 } else if (!strcmp(command, "publish")) {
1895 ret = write_begin(s);
1899 // Send onStatus(NetStream.Publish.Start)
1900 return write_status(s, pkt, "NetStream.Publish.Start",
1902 } else if (!strcmp(command, "play")) {
1903 ret = write_begin(s);
1906 rt->state = STATE_SENDING;
1907 return write_status(s, pkt, "NetStream.Play.Start",
1910 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1912 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1913 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1917 ff_amf_write_string(&pp, "_result");
1918 ff_amf_write_number(&pp, seqnum);
1919 ff_amf_write_null(&pp);
1920 if (!strcmp(command, "createStream")) {
1922 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1923 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1924 ff_amf_write_number(&pp, rt->nb_streamid);
1925 /* By now we don't control which streams are removed in
1926 * deleteStream. There is no stream creation control
1927 * if a client creates more than 2^32 - 2 streams. */
1930 spkt.size = pp - spkt.data;
1931 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1933 ff_rtmp_packet_destroy(&spkt);
1937 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1939 RTMPContext *rt = s->priv_data;
1940 char *tracked_method = NULL;
1943 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1946 if (!tracked_method) {
1947 /* Ignore this reply when the current method is not tracked. */
1951 if (!strcmp(tracked_method, "connect")) {
1952 if (!rt->is_input) {
1953 if ((ret = gen_release_stream(s, rt)) < 0)
1956 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1959 if ((ret = gen_server_bw(s, rt)) < 0)
1963 if ((ret = gen_create_stream(s, rt)) < 0)
1967 /* Send the FCSubscribe command when the name of live
1968 * stream is defined by the user or if it's a live stream. */
1969 if (rt->subscribe) {
1970 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1972 } else if (rt->live == -1) {
1973 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1977 } else if (!strcmp(tracked_method, "createStream")) {
1978 //extract a number from the result
1979 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1980 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1982 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1985 if (!rt->is_input) {
1986 if ((ret = gen_publish(s, rt)) < 0)
1989 if ((ret = gen_play(s, rt)) < 0)
1991 if ((ret = gen_buffer_time(s, rt)) < 0)
1997 av_free(tracked_method);
2001 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2003 RTMPContext *rt = s->priv_data;
2004 const uint8_t *data_end = pkt->data + pkt->size;
2005 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2006 uint8_t tmpstr[256];
2009 for (i = 0; i < 2; i++) {
2010 t = ff_amf_tag_size(ptr, data_end);
2016 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2017 if (!t && !strcmp(tmpstr, "error")) {
2018 if (!ff_amf_get_field_value(ptr, data_end,
2019 "description", tmpstr, sizeof(tmpstr)))
2020 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2024 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2025 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2026 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2027 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2028 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2029 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2034 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2036 RTMPContext *rt = s->priv_data;
2039 //TODO: check for the messages sent for wrong state?
2040 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2041 if ((ret = handle_invoke_error(s, pkt)) < 0)
2043 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2044 if ((ret = handle_invoke_result(s, pkt)) < 0)
2046 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2047 if ((ret = handle_invoke_status(s, pkt)) < 0)
2049 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2050 if ((ret = gen_check_bw(s, rt)) < 0)
2052 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2053 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2054 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2055 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2056 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2057 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2058 if ((ret = send_invoke_response(s, pkt)) < 0)
2065 static int update_offset(RTMPContext *rt, int size)
2069 // generate packet header and put data into buffer for FLV demuxer
2070 if (rt->flv_off < rt->flv_size) {
2071 // There is old unread data in the buffer, thus append at the end
2072 old_flv_size = rt->flv_size;
2073 rt->flv_size += size + 15;
2075 // All data has been read, write the new data at the start of the buffer
2077 rt->flv_size = size + 15;
2081 return old_flv_size;
2084 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2086 int old_flv_size, ret;
2088 const uint8_t *data = pkt->data + skip;
2089 const int size = pkt->size - skip;
2090 uint32_t ts = pkt->timestamp;
2092 old_flv_size = update_offset(rt, size);
2094 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2096 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2097 bytestream2_skip_p(&pbc, old_flv_size);
2098 bytestream2_put_byte(&pbc, pkt->type);
2099 bytestream2_put_be24(&pbc, size);
2100 bytestream2_put_be24(&pbc, ts);
2101 bytestream2_put_byte(&pbc, ts >> 24);
2102 bytestream2_put_be24(&pbc, 0);
2103 bytestream2_put_buffer(&pbc, data, size);
2104 bytestream2_put_be32(&pbc, 0);
2109 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2111 RTMPContext *rt = s->priv_data;
2112 uint8_t commandbuffer[64];
2113 char statusmsg[128];
2114 int stringlen, ret, skip = 0;
2117 bytestream2_init(&gbc, pkt->data, pkt->size);
2118 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2120 return AVERROR_INVALIDDATA;
2122 // Skip the @setDataFrame string and validate it is a notification
2123 if (!strcmp(commandbuffer, "@setDataFrame")) {
2124 skip = gbc.buffer - pkt->data;
2125 ret = ff_amf_read_string(&gbc, statusmsg,
2126 sizeof(statusmsg), &stringlen);
2128 return AVERROR_INVALIDDATA;
2131 return append_flv_data(rt, pkt, skip);
2135 * Parse received packet and possibly perform some action depending on
2136 * the packet contents.
2137 * @return 0 for no errors, negative values for serious errors which prevent
2138 * further communications, positive values for uncritical errors
2140 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2145 ff_rtmp_packet_dump(s, pkt);
2148 switch (pkt->type) {
2149 case RTMP_PT_BYTES_READ:
2150 av_dlog(s, "received bytes read report\n");
2152 case RTMP_PT_CHUNK_SIZE:
2153 if ((ret = handle_chunk_size(s, pkt)) < 0)
2157 if ((ret = handle_ping(s, pkt)) < 0)
2160 case RTMP_PT_CLIENT_BW:
2161 if ((ret = handle_client_bw(s, pkt)) < 0)
2164 case RTMP_PT_SERVER_BW:
2165 if ((ret = handle_server_bw(s, pkt)) < 0)
2168 case RTMP_PT_INVOKE:
2169 if ((ret = handle_invoke(s, pkt)) < 0)
2174 case RTMP_PT_METADATA:
2175 case RTMP_PT_NOTIFY:
2176 /* Audio, Video and Metadata packets are parsed in get_packet() */
2179 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2185 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2187 int ret, old_flv_size, type;
2188 const uint8_t *next;
2191 uint32_t ts, cts, pts = 0;
2193 old_flv_size = update_offset(rt, pkt->size);
2195 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2199 p = rt->flv_data + old_flv_size;
2201 /* copy data while rewriting timestamps */
2202 ts = pkt->timestamp;
2204 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2205 type = bytestream_get_byte(&next);
2206 size = bytestream_get_be24(&next);
2207 cts = bytestream_get_be24(&next);
2208 cts |= bytestream_get_byte(&next) << 24;
2213 bytestream_put_byte(&p, type);
2214 bytestream_put_be24(&p, size);
2215 bytestream_put_be24(&p, ts);
2216 bytestream_put_byte(&p, ts >> 24);
2217 memcpy(p, next, size + 3 + 4);
2218 next += size + 3 + 4;
2221 memcpy(p, next, RTMP_HEADER);
2227 * Interact with the server by receiving and sending RTMP packets until
2228 * there is some significant data (media data or expected status notification).
2230 * @param s reading context
2231 * @param for_header non-zero value tells function to work until it
2232 * gets notification from the server that playing has been started,
2233 * otherwise function will work until some media data is received (or
2235 * @return 0 for successful operation, negative value in case of error
2237 static int get_packet(URLContext *s, int for_header)
2239 RTMPContext *rt = s->priv_data;
2242 if (rt->state == STATE_STOPPED)
2246 RTMPPacket rpkt = { 0 };
2247 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2248 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2250 return AVERROR(EAGAIN);
2252 return AVERROR(EIO);
2255 rt->bytes_read += ret;
2256 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2257 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2258 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2260 rt->last_bytes_read = rt->bytes_read;
2263 ret = rtmp_parse_result(s, rt, &rpkt);
2265 // At this point we must check if we are in the seek state and continue
2266 // with the next packet. handle_invoke will get us out of this state
2267 // when the right message is encountered
2268 if (rt->state == STATE_SEEKING) {
2269 ff_rtmp_packet_destroy(&rpkt);
2270 // We continue, let the natural flow of things happen:
2271 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2275 if (ret < 0) {//serious error in current packet
2276 ff_rtmp_packet_destroy(&rpkt);
2279 if (rt->do_reconnect && for_header) {
2280 ff_rtmp_packet_destroy(&rpkt);
2283 if (rt->state == STATE_STOPPED) {
2284 ff_rtmp_packet_destroy(&rpkt);
2287 if (for_header && (rt->state == STATE_PLAYING ||
2288 rt->state == STATE_PUBLISHING ||
2289 rt->state == STATE_SENDING ||
2290 rt->state == STATE_RECEIVING)) {
2291 ff_rtmp_packet_destroy(&rpkt);
2294 if (!rpkt.size || !rt->is_input) {
2295 ff_rtmp_packet_destroy(&rpkt);
2298 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2299 ret = append_flv_data(rt, &rpkt, 0);
2300 ff_rtmp_packet_destroy(&rpkt);
2302 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2303 ret = handle_notify(s, &rpkt);
2304 ff_rtmp_packet_destroy(&rpkt);
2306 } else if (rpkt.type == RTMP_PT_METADATA) {
2307 ret = handle_metadata(rt, &rpkt);
2308 ff_rtmp_packet_destroy(&rpkt);
2311 ff_rtmp_packet_destroy(&rpkt);
2315 static int rtmp_close(URLContext *h)
2317 RTMPContext *rt = h->priv_data;
2320 if (!rt->is_input) {
2321 rt->flv_data = NULL;
2322 if (rt->out_pkt.size)
2323 ff_rtmp_packet_destroy(&rt->out_pkt);
2324 if (rt->state > STATE_FCPUBLISH)
2325 ret = gen_fcunpublish_stream(h, rt);
2327 if (rt->state > STATE_HANDSHAKED)
2328 ret = gen_delete_stream(h, rt);
2329 for (i = 0; i < 2; i++)
2330 for (j = 0; j < RTMP_CHANNELS; j++)
2331 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2333 free_tracked_methods(rt);
2334 av_freep(&rt->flv_data);
2335 ffurl_close(rt->stream);
2340 * Open RTMP connection and verify that the stream can be played.
2342 * URL syntax: rtmp://server[:port][/app][/playpath]
2343 * where 'app' is first one or two directories in the path
2344 * (e.g. /ondemand/, /flash/live/, etc.)
2345 * and 'playpath' is a file name (the rest of the path,
2346 * may be prefixed with "mp4:")
2348 static int rtmp_open(URLContext *s, const char *uri, int flags)
2350 RTMPContext *rt = s->priv_data;
2351 char proto[8], hostname[256], path[1024], auth[100], *fname;
2355 AVDictionary *opts = NULL;
2358 if (rt->listen_timeout > 0)
2361 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2363 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2364 hostname, sizeof(hostname), &port,
2365 path, sizeof(path), s->filename);
2367 if (strchr(path, ' ')) {
2368 av_log(s, AV_LOG_WARNING,
2369 "Detected librtmp style URL parameters, these aren't supported "
2370 "by the libavformat internal RTMP handler currently enabled. "
2371 "See the documentation for the correct way to pass parameters.\n");
2375 char *ptr = strchr(auth, ':');
2378 av_strlcpy(rt->username, auth, sizeof(rt->username));
2379 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2383 if (rt->listen && strcmp(proto, "rtmp")) {
2384 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2386 return AVERROR(EINVAL);
2388 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2389 if (!strcmp(proto, "rtmpts"))
2390 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2392 /* open the http tunneling connection */
2393 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2394 } else if (!strcmp(proto, "rtmps")) {
2395 /* open the tls connection */
2397 port = RTMPS_DEFAULT_PORT;
2398 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2399 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2400 if (!strcmp(proto, "rtmpte"))
2401 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2403 /* open the encrypted connection */
2404 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2407 /* open the tcp connection */
2409 port = RTMP_DEFAULT_PORT;
2411 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2412 "?listen&listen_timeout=%d",
2413 rt->listen_timeout * 1000);
2415 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2419 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2420 &s->interrupt_callback, &opts)) < 0) {
2421 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2425 if (rt->swfverify) {
2426 if ((ret = rtmp_calc_swfhash(s)) < 0)
2430 rt->state = STATE_START;
2431 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2433 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2436 rt->out_chunk_size = 128;
2437 rt->in_chunk_size = 128; // Probably overwritten later
2438 rt->state = STATE_HANDSHAKED;
2440 // Keep the application name when it has been defined by the user.
2443 rt->app = av_malloc(APP_MAX_LENGTH);
2445 ret = AVERROR(ENOMEM);
2449 //extract "app" part from path
2450 if (!strncmp(path, "/ondemand/", 10)) {
2452 memcpy(rt->app, "ondemand", 9);
2454 char *next = *path ? path + 1 : path;
2455 char *p = strchr(next, '/');
2460 // make sure we do not mismatch a playpath for an application instance
2461 char *c = strchr(p + 1, ':');
2462 fname = strchr(p + 1, '/');
2463 if (!fname || (c && c < fname)) {
2465 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2468 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2474 // The name of application has been defined by the user, override it.
2475 if (strlen(old_app) >= APP_MAX_LENGTH) {
2476 ret = AVERROR(EINVAL);
2483 if (!rt->playpath) {
2484 int len = strlen(fname);
2486 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2487 if (!rt->playpath) {
2488 ret = AVERROR(ENOMEM);
2492 if (!strchr(fname, ':') && len >= 4 &&
2493 (!strcmp(fname + len - 4, ".f4v") ||
2494 !strcmp(fname + len - 4, ".mp4"))) {
2495 memcpy(rt->playpath, "mp4:", 5);
2496 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2497 fname[len - 4] = '\0';
2499 rt->playpath[0] = 0;
2501 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2505 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2507 ret = AVERROR(ENOMEM);
2510 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2511 port, "/%s", rt->app);
2514 if (!rt->flashver) {
2515 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2516 if (!rt->flashver) {
2517 ret = AVERROR(ENOMEM);
2521 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2522 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2523 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2525 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2526 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2530 rt->client_report_size = 1048576;
2532 rt->last_bytes_read = 0;
2533 rt->server_bw = 2500000;
2535 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2536 proto, path, rt->app, rt->playpath);
2538 if ((ret = gen_connect(s, rt)) < 0)
2541 if (read_connect(s, s->priv_data) < 0)
2546 ret = get_packet(s, 1);
2547 } while (ret == AVERROR(EAGAIN));
2551 if (rt->do_reconnect) {
2552 ffurl_close(rt->stream);
2554 rt->do_reconnect = 0;
2556 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2557 free_tracked_methods(rt);
2563 // generate FLV header for demuxer
2565 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2568 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2571 rt->flv_data = NULL;
2573 rt->skip_bytes = 13;
2576 s->max_packet_size = rt->stream->max_packet_size;
2581 av_dict_free(&opts);
2586 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2588 RTMPContext *rt = s->priv_data;
2589 int orig_size = size;
2593 int data_left = rt->flv_size - rt->flv_off;
2595 if (data_left >= size) {
2596 memcpy(buf, rt->flv_data + rt->flv_off, size);
2597 rt->flv_off += size;
2600 if (data_left > 0) {
2601 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2604 rt->flv_off = rt->flv_size;
2607 if ((ret = get_packet(s, 0)) < 0)
2613 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2616 RTMPContext *rt = s->priv_data;
2618 av_log(s, AV_LOG_DEBUG,
2619 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2620 stream_index, timestamp, flags);
2621 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2622 av_log(s, AV_LOG_ERROR,
2623 "Unable to send seek command on stream index %d at timestamp "
2624 "%"PRId64" with flags %08x\n",
2625 stream_index, timestamp, flags);
2628 rt->flv_off = rt->flv_size;
2629 rt->state = STATE_SEEKING;
2633 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2635 RTMPContext *rt = s->priv_data;
2636 int size_temp = size;
2637 int pktsize, pkttype;
2639 const uint8_t *buf_temp = buf;
2644 if (rt->skip_bytes) {
2645 int skip = FFMIN(rt->skip_bytes, size_temp);
2648 rt->skip_bytes -= skip;
2652 if (rt->flv_header_bytes < RTMP_HEADER) {
2653 const uint8_t *header = rt->flv_header;
2654 int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2655 int channel = RTMP_AUDIO_CHANNEL;
2656 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2657 rt->flv_header_bytes += copy;
2659 if (rt->flv_header_bytes < RTMP_HEADER)
2662 pkttype = bytestream_get_byte(&header);
2663 pktsize = bytestream_get_be24(&header);
2664 ts = bytestream_get_be24(&header);
2665 ts |= bytestream_get_byte(&header) << 24;
2666 bytestream_get_be24(&header);
2667 rt->flv_size = pktsize;
2669 if (pkttype == RTMP_PT_VIDEO)
2670 channel = RTMP_VIDEO_CHANNEL;
2672 //force 12bytes header
2673 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2674 pkttype == RTMP_PT_NOTIFY) {
2675 if (pkttype == RTMP_PT_NOTIFY)
2677 rt->prev_pkt[1][channel].channel_id = 0;
2680 //this can be a big packet, it's better to send it right here
2681 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2682 pkttype, ts, pktsize)) < 0)
2685 rt->out_pkt.extra = rt->stream_id;
2686 rt->flv_data = rt->out_pkt.data;
2688 if (pkttype == RTMP_PT_NOTIFY)
2689 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2692 if (rt->flv_size - rt->flv_off > size_temp) {
2693 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2694 rt->flv_off += size_temp;
2697 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2698 size_temp -= rt->flv_size - rt->flv_off;
2699 rt->flv_off += rt->flv_size - rt->flv_off;
2702 if (rt->flv_off == rt->flv_size) {
2705 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2709 rt->flv_header_bytes = 0;
2710 rt->flv_nb_packets++;
2712 } while (buf_temp - buf < size);
2714 if (rt->flv_nb_packets < rt->flush_interval)
2716 rt->flv_nb_packets = 0;
2718 /* set stream into nonblocking mode */
2719 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2721 /* try to read one byte from the stream */
2722 ret = ffurl_read(rt->stream, &c, 1);
2724 /* switch the stream back into blocking mode */
2725 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2727 if (ret == AVERROR(EAGAIN)) {
2728 /* no incoming data to handle */
2730 } else if (ret < 0) {
2732 } else if (ret == 1) {
2733 RTMPPacket rpkt = { 0 };
2735 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2737 rt->prev_pkt[0], c)) <= 0)
2740 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2743 ff_rtmp_packet_destroy(&rpkt);
2749 #define OFFSET(x) offsetof(RTMPContext, x)
2750 #define DEC AV_OPT_FLAG_DECODING_PARAM
2751 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2753 static const AVOption rtmp_options[] = {
2754 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2755 {"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},
2756 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2757 {"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},
2758 {"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},
2759 {"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"},
2760 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2761 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2762 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2763 {"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},
2764 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2765 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2766 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2767 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2768 {"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},
2769 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2770 {"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},
2771 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2772 {"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" },
2776 #define RTMP_PROTOCOL(flavor) \
2777 static const AVClass flavor##_class = { \
2778 .class_name = #flavor, \
2779 .item_name = av_default_item_name, \
2780 .option = rtmp_options, \
2781 .version = LIBAVUTIL_VERSION_INT, \
2784 URLProtocol ff_##flavor##_protocol = { \
2786 .url_open = rtmp_open, \
2787 .url_read = rtmp_read, \
2788 .url_read_seek = rtmp_seek, \
2789 .url_write = rtmp_write, \
2790 .url_close = rtmp_close, \
2791 .priv_data_size = sizeof(RTMPContext), \
2792 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2793 .priv_data_class= &flavor##_class, \
2798 RTMP_PROTOCOL(rtmpe)
2799 RTMP_PROTOCOL(rtmps)
2800 RTMP_PROTOCOL(rtmpt)
2801 RTMP_PROTOCOL(rtmpte)
2802 RTMP_PROTOCOL(rtmpts)