2 * RTMP network protocol
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "libavutil/sha.h"
43 #include "rtmpcrypt.h"
51 #define APP_MAX_LENGTH 128
52 #define PLAYPATH_MAX_LENGTH 256
53 #define TCURL_MAX_LENGTH 512
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
57 /** RTMP protocol handler state */
59 STATE_START, ///< client has not done anything yet
60 STATE_HANDSHAKED, ///< client has performed handshake
61 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
62 STATE_PLAYING, ///< client has started receiving multimedia data from server
63 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
64 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
65 STATE_RECEIVING, ///< received a publish command (for input)
66 STATE_SENDING, ///< received a play command (for output)
67 STATE_STOPPED, ///< the broadcast has been stopped
70 typedef struct TrackedMethod {
75 /** protocol handler context */
76 typedef struct RTMPContext {
78 URLContext* stream; ///< TCP stream used in interactions with RTMP server
79 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
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 stream_id; ///< ID assigned by the server for the stream
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 if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
158 sizeof(*rt->tracked_methods))) < 0)
162 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
163 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
164 return AVERROR(ENOMEM);
165 rt->tracked_methods[rt->nb_tracked_methods].id = id;
166 rt->nb_tracked_methods++;
171 static void del_tracked_method(RTMPContext *rt, int index)
173 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
174 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
175 rt->nb_tracked_methods--;
178 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
179 char **tracked_method)
181 RTMPContext *rt = s->priv_data;
187 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
188 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
191 for (i = 0; i < rt->nb_tracked_methods; i++) {
192 if (rt->tracked_methods[i].id != pkt_id)
195 *tracked_method = rt->tracked_methods[i].name;
196 del_tracked_method(rt, i);
203 static void free_tracked_methods(RTMPContext *rt)
207 for (i = 0; i < rt->nb_tracked_methods; i ++)
208 av_free(rt->tracked_methods[i].name);
209 av_free(rt->tracked_methods);
210 rt->tracked_methods = NULL;
211 rt->tracked_methods_size = 0;
212 rt->nb_tracked_methods = 0;
215 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
219 if (pkt->type == RTMP_PT_INVOKE && track) {
225 bytestream2_init(&gbc, pkt->data, pkt->size);
226 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
229 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
232 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
236 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
239 ff_rtmp_packet_destroy(pkt);
243 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
248 /* The type must be B for Boolean, N for number, S for string, O for
249 * object, or Z for null. For Booleans the data must be either 0 or 1 for
250 * FALSE or TRUE, respectively. Likewise for Objects the data must be
251 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
252 * may be named, by prefixing the type with 'N' and specifying the name
253 * before the value (ie. NB:myFlag:1). This option may be used multiple times
254 * to construct arbitrary AMF sequences. */
255 if (param[0] && param[1] == ':') {
258 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
261 value = strchr(field, ':');
267 if (!field || !value)
270 ff_amf_write_field_name(p, field);
277 ff_amf_write_bool(p, value[0] != '0');
280 ff_amf_write_string(p, value);
283 ff_amf_write_number(p, strtod(value, NULL));
286 ff_amf_write_null(p);
290 ff_amf_write_object_start(p);
292 ff_amf_write_object_end(p);
302 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
303 return AVERROR(EINVAL);
307 * Generate 'connect' call and send it to the server.
309 static int gen_connect(URLContext *s, RTMPContext *rt)
315 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
321 ff_amf_write_string(&p, "connect");
322 ff_amf_write_number(&p, ++rt->nb_invokes);
323 ff_amf_write_object_start(&p);
324 ff_amf_write_field_name(&p, "app");
325 ff_amf_write_string2(&p, rt->app, rt->auth_params);
328 ff_amf_write_field_name(&p, "type");
329 ff_amf_write_string(&p, "nonprivate");
331 ff_amf_write_field_name(&p, "flashVer");
332 ff_amf_write_string(&p, rt->flashver);
335 ff_amf_write_field_name(&p, "swfUrl");
336 ff_amf_write_string(&p, rt->swfurl);
339 ff_amf_write_field_name(&p, "tcUrl");
340 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
342 ff_amf_write_field_name(&p, "fpad");
343 ff_amf_write_bool(&p, 0);
344 ff_amf_write_field_name(&p, "capabilities");
345 ff_amf_write_number(&p, 15.0);
347 /* Tell the server we support all the audio codecs except
348 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
349 * which are unused in the RTMP protocol implementation. */
350 ff_amf_write_field_name(&p, "audioCodecs");
351 ff_amf_write_number(&p, 4071.0);
352 ff_amf_write_field_name(&p, "videoCodecs");
353 ff_amf_write_number(&p, 252.0);
354 ff_amf_write_field_name(&p, "videoFunction");
355 ff_amf_write_number(&p, 1.0);
358 ff_amf_write_field_name(&p, "pageUrl");
359 ff_amf_write_string(&p, rt->pageurl);
362 ff_amf_write_object_end(&p);
365 char *param = rt->conn;
367 // Write arbitrary AMF data to the Connect message.
368 while (param != NULL) {
370 param += strspn(param, " ");
373 sep = strchr(param, ' ');
376 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
377 // Invalid AMF parameter.
378 ff_rtmp_packet_destroy(&pkt);
389 pkt.size = p - pkt.data;
391 return rtmp_send_packet(rt, &pkt, 1);
394 static int read_connect(URLContext *s, RTMPContext *rt)
396 RTMPPacket pkt = { 0 };
406 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
407 rt->prev_pkt[0])) < 0)
410 bytestream2_init(&gbc, cp, pkt.size);
411 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
412 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
413 ff_rtmp_packet_destroy(&pkt);
414 return AVERROR_INVALIDDATA;
416 if (strcmp(command, "connect")) {
417 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
418 ff_rtmp_packet_destroy(&pkt);
419 return AVERROR_INVALIDDATA;
421 ret = ff_amf_read_number(&gbc, &seqnum);
423 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
424 /* Here one could parse an AMF Object with data as flashVers and others. */
425 ret = ff_amf_get_field_value(gbc.buffer,
426 gbc.buffer + bytestream2_get_bytes_left(&gbc),
427 "app", tmpstr, sizeof(tmpstr));
429 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
430 if (!ret && strcmp(tmpstr, rt->app))
431 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
433 ff_rtmp_packet_destroy(&pkt);
435 // Send Window Acknowledgement Size (as defined in speficication)
436 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
437 RTMP_PT_SERVER_BW, 0, 4)) < 0)
440 bytestream_put_be32(&p, rt->server_bw);
441 pkt.size = p - pkt.data;
442 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
444 ff_rtmp_packet_destroy(&pkt);
447 // Send Peer Bandwidth
448 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
449 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
452 bytestream_put_be32(&p, rt->server_bw);
453 bytestream_put_byte(&p, 2); // dynamic
454 pkt.size = p - pkt.data;
455 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
457 ff_rtmp_packet_destroy(&pkt);
462 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
463 RTMP_PT_PING, 0, 6)) < 0)
467 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
468 bytestream_put_be32(&p, 0);
469 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
471 ff_rtmp_packet_destroy(&pkt);
476 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
477 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
481 bytestream_put_be32(&p, rt->out_chunk_size);
482 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
484 ff_rtmp_packet_destroy(&pkt);
488 // Send result_ NetConnection.Connect.Success to connect
489 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
491 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
495 ff_amf_write_string(&p, "_result");
496 ff_amf_write_number(&p, seqnum);
498 ff_amf_write_object_start(&p);
499 ff_amf_write_field_name(&p, "fmsVer");
500 ff_amf_write_string(&p, "FMS/3,0,1,123");
501 ff_amf_write_field_name(&p, "capabilities");
502 ff_amf_write_number(&p, 31);
503 ff_amf_write_object_end(&p);
505 ff_amf_write_object_start(&p);
506 ff_amf_write_field_name(&p, "level");
507 ff_amf_write_string(&p, "status");
508 ff_amf_write_field_name(&p, "code");
509 ff_amf_write_string(&p, "NetConnection.Connect.Success");
510 ff_amf_write_field_name(&p, "description");
511 ff_amf_write_string(&p, "Connection succeeded.");
512 ff_amf_write_field_name(&p, "objectEncoding");
513 ff_amf_write_number(&p, 0);
514 ff_amf_write_object_end(&p);
516 pkt.size = p - pkt.data;
517 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
519 ff_rtmp_packet_destroy(&pkt);
523 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
524 RTMP_PT_INVOKE, 0, 30)) < 0)
527 ff_amf_write_string(&p, "onBWDone");
528 ff_amf_write_number(&p, 0);
529 ff_amf_write_null(&p);
530 ff_amf_write_number(&p, 8192);
531 pkt.size = p - pkt.data;
532 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
534 ff_rtmp_packet_destroy(&pkt);
540 * Generate 'releaseStream' call and send it to the server. It should make
541 * the server release some channel for media streams.
543 static int gen_release_stream(URLContext *s, RTMPContext *rt)
549 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
550 0, 29 + strlen(rt->playpath))) < 0)
553 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
555 ff_amf_write_string(&p, "releaseStream");
556 ff_amf_write_number(&p, ++rt->nb_invokes);
557 ff_amf_write_null(&p);
558 ff_amf_write_string(&p, rt->playpath);
560 return rtmp_send_packet(rt, &pkt, 1);
564 * Generate 'FCPublish' call and send it to the server. It should make
565 * the server preapare for receiving media streams.
567 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
573 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
574 0, 25 + strlen(rt->playpath))) < 0)
577 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
579 ff_amf_write_string(&p, "FCPublish");
580 ff_amf_write_number(&p, ++rt->nb_invokes);
581 ff_amf_write_null(&p);
582 ff_amf_write_string(&p, rt->playpath);
584 return rtmp_send_packet(rt, &pkt, 1);
588 * Generate 'FCUnpublish' call and send it to the server. It should make
589 * the server destroy stream.
591 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
597 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
598 0, 27 + strlen(rt->playpath))) < 0)
601 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
603 ff_amf_write_string(&p, "FCUnpublish");
604 ff_amf_write_number(&p, ++rt->nb_invokes);
605 ff_amf_write_null(&p);
606 ff_amf_write_string(&p, rt->playpath);
608 return rtmp_send_packet(rt, &pkt, 0);
612 * Generate 'createStream' call and send it to the server. It should make
613 * the server allocate some channel for media streams.
615 static int gen_create_stream(URLContext *s, RTMPContext *rt)
621 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
623 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
628 ff_amf_write_string(&p, "createStream");
629 ff_amf_write_number(&p, ++rt->nb_invokes);
630 ff_amf_write_null(&p);
632 return rtmp_send_packet(rt, &pkt, 1);
637 * Generate 'deleteStream' call and send it to the server. It should make
638 * the server remove some channel for media streams.
640 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
646 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
648 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
653 ff_amf_write_string(&p, "deleteStream");
654 ff_amf_write_number(&p, ++rt->nb_invokes);
655 ff_amf_write_null(&p);
656 ff_amf_write_number(&p, rt->stream_id);
658 return rtmp_send_packet(rt, &pkt, 0);
662 * Generate client buffer time and send it to the server.
664 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
670 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
675 bytestream_put_be16(&p, 3);
676 bytestream_put_be32(&p, rt->stream_id);
677 bytestream_put_be32(&p, rt->client_buffer_time);
679 return rtmp_send_packet(rt, &pkt, 0);
683 * Generate 'play' call and send it to the server, then ping the server
684 * to start actual playing.
686 static int gen_play(URLContext *s, RTMPContext *rt)
692 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
694 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
695 0, 29 + strlen(rt->playpath))) < 0)
698 pkt.extra = rt->stream_id;
701 ff_amf_write_string(&p, "play");
702 ff_amf_write_number(&p, ++rt->nb_invokes);
703 ff_amf_write_null(&p);
704 ff_amf_write_string(&p, rt->playpath);
705 ff_amf_write_number(&p, rt->live);
707 return rtmp_send_packet(rt, &pkt, 1);
710 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
716 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
719 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
722 pkt.extra = rt->stream_id;
725 ff_amf_write_string(&p, "seek");
726 ff_amf_write_number(&p, 0); //no tracking back responses
727 ff_amf_write_null(&p); //as usual, the first null param
728 ff_amf_write_number(&p, timestamp); //where we want to jump
730 return rtmp_send_packet(rt, &pkt, 1);
734 * Generate 'publish' call and send it to the server.
736 static int gen_publish(URLContext *s, RTMPContext *rt)
742 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
744 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
745 0, 30 + strlen(rt->playpath))) < 0)
748 pkt.extra = rt->stream_id;
751 ff_amf_write_string(&p, "publish");
752 ff_amf_write_number(&p, ++rt->nb_invokes);
753 ff_amf_write_null(&p);
754 ff_amf_write_string(&p, rt->playpath);
755 ff_amf_write_string(&p, "live");
757 return rtmp_send_packet(rt, &pkt, 1);
761 * Generate ping reply and send it to the server.
763 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
769 if (ppkt->size < 6) {
770 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
772 return AVERROR_INVALIDDATA;
775 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
776 ppkt->timestamp + 1, 6)) < 0)
780 bytestream_put_be16(&p, 7);
781 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
783 return rtmp_send_packet(rt, &pkt, 0);
787 * Generate SWF verification message and send it to the server.
789 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
795 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
796 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
801 bytestream_put_be16(&p, 27);
802 memcpy(p, rt->swfverification, 42);
804 return rtmp_send_packet(rt, &pkt, 0);
808 * Generate server bandwidth message and send it to the server.
810 static int gen_server_bw(URLContext *s, RTMPContext *rt)
816 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
821 bytestream_put_be32(&p, rt->server_bw);
823 return rtmp_send_packet(rt, &pkt, 0);
827 * Generate check bandwidth message and send it to the server.
829 static int gen_check_bw(URLContext *s, RTMPContext *rt)
835 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
840 ff_amf_write_string(&p, "_checkbw");
841 ff_amf_write_number(&p, ++rt->nb_invokes);
842 ff_amf_write_null(&p);
844 return rtmp_send_packet(rt, &pkt, 1);
848 * Generate report on bytes read so far and send it to the server.
850 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
856 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
861 bytestream_put_be32(&p, rt->bytes_read);
863 return rtmp_send_packet(rt, &pkt, 0);
866 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
867 const char *subscribe)
873 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
874 0, 27 + strlen(subscribe))) < 0)
878 ff_amf_write_string(&p, "FCSubscribe");
879 ff_amf_write_number(&p, ++rt->nb_invokes);
880 ff_amf_write_null(&p);
881 ff_amf_write_string(&p, subscribe);
883 return rtmp_send_packet(rt, &pkt, 1);
886 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
887 const uint8_t *key, int keylen, uint8_t *dst)
890 uint8_t hmac_buf[64+32] = {0};
893 sha = av_sha_alloc();
895 return AVERROR(ENOMEM);
898 memcpy(hmac_buf, key, keylen);
900 av_sha_init(sha, 256);
901 av_sha_update(sha,key, keylen);
902 av_sha_final(sha, hmac_buf);
904 for (i = 0; i < 64; i++)
905 hmac_buf[i] ^= HMAC_IPAD_VAL;
907 av_sha_init(sha, 256);
908 av_sha_update(sha, hmac_buf, 64);
910 av_sha_update(sha, src, len);
911 } else { //skip 32 bytes used for storing digest
912 av_sha_update(sha, src, gap);
913 av_sha_update(sha, src + gap + 32, len - gap - 32);
915 av_sha_final(sha, hmac_buf + 64);
917 for (i = 0; i < 64; i++)
918 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
919 av_sha_init(sha, 256);
920 av_sha_update(sha, hmac_buf, 64+32);
921 av_sha_final(sha, dst);
928 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
931 int i, digest_pos = 0;
933 for (i = 0; i < 4; i++)
934 digest_pos += buf[i + off];
935 digest_pos = digest_pos % mod_val + add_val;
941 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
942 * will be stored) into that packet.
944 * @param buf handshake data (1536 bytes)
945 * @param encrypted use an encrypted connection (RTMPE)
946 * @return offset to the digest inside input data
948 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
953 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
955 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
957 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
958 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
967 * Verify that the received server response has the expected digest value.
969 * @param buf handshake data received from the server (1536 bytes)
970 * @param off position to search digest offset from
971 * @return 0 if digest is valid, digest position otherwise
973 static int rtmp_validate_digest(uint8_t *buf, int off)
978 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
980 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
981 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
986 if (!memcmp(digest, buf + digest_pos, 32))
991 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
997 if (rt->swfhash_len != 32) {
998 av_log(s, AV_LOG_ERROR,
999 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1000 return AVERROR(EINVAL);
1003 p = &rt->swfverification[0];
1004 bytestream_put_byte(&p, 1);
1005 bytestream_put_byte(&p, 1);
1006 bytestream_put_be32(&p, rt->swfsize);
1007 bytestream_put_be32(&p, rt->swfsize);
1009 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1016 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1017 uint8_t **out_data, int64_t *out_size)
1019 z_stream zs = { 0 };
1024 zs.avail_in = in_size;
1025 zs.next_in = in_data;
1026 ret = inflateInit(&zs);
1028 return AVERROR_UNKNOWN;
1031 uint8_t tmp_buf[16384];
1033 zs.avail_out = sizeof(tmp_buf);
1034 zs.next_out = tmp_buf;
1036 ret = inflate(&zs, Z_NO_FLUSH);
1037 if (ret != Z_OK && ret != Z_STREAM_END) {
1038 ret = AVERROR_UNKNOWN;
1042 size = sizeof(tmp_buf) - zs.avail_out;
1043 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1044 ret = AVERROR(ENOMEM);
1049 memcpy(*out_data + *out_size, tmp_buf, size);
1051 } while (zs.avail_out == 0);
1059 static int rtmp_calc_swfhash(URLContext *s)
1061 RTMPContext *rt = s->priv_data;
1062 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1063 int64_t in_size, out_size;
1069 /* Get the SWF player file. */
1070 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1071 &s->interrupt_callback, NULL)) < 0) {
1072 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1076 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1081 if (!(in_data = av_malloc(in_size))) {
1082 ret = AVERROR(ENOMEM);
1086 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1090 ret = AVERROR_INVALIDDATA;
1094 if (!memcmp(in_data, "CWS", 3)) {
1095 /* Decompress the SWF player file using Zlib. */
1096 if (!(out_data = av_malloc(8))) {
1097 ret = AVERROR(ENOMEM);
1100 *in_data = 'F'; // magic stuff
1101 memcpy(out_data, in_data, 8);
1105 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1106 &out_data, &out_size)) < 0)
1109 av_log(s, AV_LOG_ERROR,
1110 "Zlib is required for decompressing the SWF player file.\n");
1111 ret = AVERROR(EINVAL);
1121 /* Compute the SHA256 hash of the SWF player file. */
1122 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1123 "Genuine Adobe Flash Player 001", 30,
1127 /* Set SWFVerification parameters. */
1128 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1129 rt->swfsize = swfsize;
1133 av_freep(&out_data);
1134 ffurl_close(stream);
1139 * Perform handshake with the server by means of exchanging pseudorandom data
1140 * signed with HMAC-SHA2 digest.
1142 * @return 0 if handshake succeeds, negative value otherwise
1144 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1147 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1148 3, // unencrypted data
1149 0, 0, 0, 0, // client uptime
1155 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1156 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1158 int server_pos, client_pos;
1159 uint8_t digest[32], signature[32];
1162 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1164 av_lfg_init(&rnd, 0xDEADC0DE);
1165 // generate handshake packet - 1536 bytes of pseudorandom data
1166 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1167 tosend[i] = av_lfg_get(&rnd) >> 24;
1169 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1170 /* When the client wants to use RTMPE, we have to change the command
1171 * byte to 0x06 which means to use encrypted data and we have to set
1172 * the flash version to at least 9.0.115.0. */
1179 /* Initialize the Diffie-Hellmann context and generate the public key
1180 * to send to the server. */
1181 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1185 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1189 if ((ret = ffurl_write(rt->stream, tosend,
1190 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1191 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1195 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1196 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1197 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1201 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1202 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1203 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1207 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1208 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1209 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1211 if (rt->is_input && serverdata[5] >= 3) {
1212 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1218 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1223 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1224 return AVERROR(EIO);
1228 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1229 * key are the last 32 bytes of the server handshake. */
1231 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1232 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1236 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1237 rtmp_server_key, sizeof(rtmp_server_key),
1242 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1243 0, digest, 32, signature);
1247 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1248 /* Compute the shared secret key sent by the server and initialize
1249 * the RC4 encryption. */
1250 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1251 tosend + 1, type)) < 0)
1254 /* Encrypt the signature received by the server. */
1255 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1258 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1259 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1260 return AVERROR(EIO);
1263 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1264 tosend[i] = av_lfg_get(&rnd) >> 24;
1265 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1266 rtmp_player_key, sizeof(rtmp_player_key),
1271 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1273 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1277 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1278 /* Encrypt the signature to be send to the server. */
1279 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1280 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1284 // write reply back to the server
1285 if ((ret = ffurl_write(rt->stream, tosend,
1286 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1289 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1290 /* Set RC4 keys for encryption and update the keystreams. */
1291 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1295 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1296 /* Compute the shared secret key sent by the server and initialize
1297 * the RC4 encryption. */
1298 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1299 tosend + 1, 1)) < 0)
1302 if (serverdata[0] == 9) {
1303 /* Encrypt the signature received by the server. */
1304 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1309 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1310 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1313 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1314 /* Set RC4 keys for encryption and update the keystreams. */
1315 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1323 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1324 uint32_t *second_int, char *arraydata,
1329 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1330 RTMP_HANDSHAKE_PACKET_SIZE);
1332 return AVERROR(EIO);
1333 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1334 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1335 " not following standard\n", (int)inoutsize);
1336 return AVERROR(EINVAL);
1339 *first_int = AV_RB32(arraydata);
1340 *second_int = AV_RB32(arraydata + 4);
1344 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1345 uint32_t second_int, char *arraydata, int size)
1349 AV_WB32(arraydata, first_int);
1350 AV_WB32(arraydata + 4, second_int);
1351 inoutsize = ffurl_write(rt->stream, arraydata,
1352 RTMP_HANDSHAKE_PACKET_SIZE);
1353 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1354 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1355 return AVERROR(EIO);
1362 * rtmp handshake server side
1364 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1366 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1368 uint32_t hs_my_epoch;
1369 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1370 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1377 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1378 if (inoutsize <= 0) {
1379 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1380 return AVERROR(EIO);
1383 if (buffer[0] != 3) {
1384 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1385 return AVERROR(EIO);
1387 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1388 av_log(s, AV_LOG_ERROR,
1389 "Unable to write answer - RTMP S0\n");
1390 return AVERROR(EIO);
1393 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1394 RTMP_HANDSHAKE_PACKET_SIZE);
1396 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1400 /* By now same epoch will be sent */
1401 hs_my_epoch = hs_epoch;
1402 /* Generate random */
1403 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1405 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1407 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1408 RTMP_HANDSHAKE_PACKET_SIZE);
1410 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1414 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1415 RTMP_HANDSHAKE_PACKET_SIZE);
1417 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1421 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1422 RTMP_HANDSHAKE_PACKET_SIZE);
1424 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1427 if (temp != hs_my_epoch)
1428 av_log(s, AV_LOG_WARNING,
1429 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1430 if (memcmp(buffer + 8, hs_s1 + 8,
1431 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1432 av_log(s, AV_LOG_WARNING,
1433 "Erroneous C2 Message random does not match up\n");
1438 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1440 RTMPContext *rt = s->priv_data;
1443 if (pkt->size < 4) {
1444 av_log(s, AV_LOG_ERROR,
1445 "Too short chunk size change packet (%d)\n",
1447 return AVERROR_INVALIDDATA;
1450 if (!rt->is_input) {
1451 /* Send the same chunk size change packet back to the server,
1452 * setting the outgoing chunk size to the same as the incoming one. */
1453 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1454 rt->prev_pkt[1])) < 0)
1456 rt->out_chunk_size = AV_RB32(pkt->data);
1459 rt->in_chunk_size = AV_RB32(pkt->data);
1460 if (rt->in_chunk_size <= 0) {
1461 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1463 return AVERROR_INVALIDDATA;
1465 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1471 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1473 RTMPContext *rt = s->priv_data;
1476 if (pkt->size < 2) {
1477 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1479 return AVERROR_INVALIDDATA;
1482 t = AV_RB16(pkt->data);
1484 if ((ret = gen_pong(s, rt, pkt)) < 0)
1486 } else if (t == 26) {
1488 if ((ret = gen_swf_verification(s, rt)) < 0)
1491 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1498 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1500 RTMPContext *rt = s->priv_data;
1502 if (pkt->size < 4) {
1503 av_log(s, AV_LOG_ERROR,
1504 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1506 return AVERROR_INVALIDDATA;
1509 rt->client_report_size = AV_RB32(pkt->data);
1510 if (rt->client_report_size <= 0) {
1511 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1512 rt->client_report_size);
1513 return AVERROR_INVALIDDATA;
1516 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1517 rt->client_report_size >>= 1;
1522 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1524 RTMPContext *rt = s->priv_data;
1526 if (pkt->size < 4) {
1527 av_log(s, AV_LOG_ERROR,
1528 "Too short server bandwidth report packet (%d)\n",
1530 return AVERROR_INVALIDDATA;
1533 rt->server_bw = AV_RB32(pkt->data);
1534 if (rt->server_bw <= 0) {
1535 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1537 return AVERROR_INVALIDDATA;
1539 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1544 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1545 const char *opaque, const char *challenge)
1548 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1549 struct AVMD5 *md5 = av_md5_alloc();
1551 return AVERROR(ENOMEM);
1553 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1556 av_md5_update(md5, user, strlen(user));
1557 av_md5_update(md5, salt, strlen(salt));
1558 av_md5_update(md5, rt->password, strlen(rt->password));
1559 av_md5_final(md5, hash);
1560 av_base64_encode(hashstr, sizeof(hashstr), hash,
1563 av_md5_update(md5, hashstr, strlen(hashstr));
1565 av_md5_update(md5, opaque, strlen(opaque));
1567 av_md5_update(md5, challenge, strlen(challenge));
1568 av_md5_update(md5, challenge2, strlen(challenge2));
1569 av_md5_final(md5, hash);
1570 av_base64_encode(hashstr, sizeof(hashstr), hash,
1572 snprintf(rt->auth_params, sizeof(rt->auth_params),
1573 "?authmod=%s&user=%s&challenge=%s&response=%s",
1574 "adobe", user, challenge2, hashstr);
1576 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1577 "&opaque=%s", opaque);
1583 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1586 char hashstr1[33], hashstr2[33];
1587 const char *realm = "live";
1588 const char *method = "publish";
1589 const char *qop = "auth";
1590 const char *nc = "00000001";
1592 struct AVMD5 *md5 = av_md5_alloc();
1594 return AVERROR(ENOMEM);
1596 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1599 av_md5_update(md5, user, strlen(user));
1600 av_md5_update(md5, ":", 1);
1601 av_md5_update(md5, realm, strlen(realm));
1602 av_md5_update(md5, ":", 1);
1603 av_md5_update(md5, rt->password, strlen(rt->password));
1604 av_md5_final(md5, hash);
1605 ff_data_to_hex(hashstr1, hash, 16, 1);
1606 hashstr1[32] = '\0';
1609 av_md5_update(md5, method, strlen(method));
1610 av_md5_update(md5, ":/", 2);
1611 av_md5_update(md5, rt->app, strlen(rt->app));
1612 if (!strchr(rt->app, '/'))
1613 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1614 av_md5_final(md5, hash);
1615 ff_data_to_hex(hashstr2, hash, 16, 1);
1616 hashstr2[32] = '\0';
1619 av_md5_update(md5, hashstr1, strlen(hashstr1));
1620 av_md5_update(md5, ":", 1);
1622 av_md5_update(md5, nonce, strlen(nonce));
1623 av_md5_update(md5, ":", 1);
1624 av_md5_update(md5, nc, strlen(nc));
1625 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, cnonce, strlen(cnonce));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, qop, strlen(qop));
1629 av_md5_update(md5, ":", 1);
1630 av_md5_update(md5, hashstr2, strlen(hashstr2));
1631 av_md5_final(md5, hash);
1632 ff_data_to_hex(hashstr1, hash, 16, 1);
1634 snprintf(rt->auth_params, sizeof(rt->auth_params),
1635 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1636 "llnw", user, nonce, cnonce, nc, hashstr1);
1642 static int handle_connect_error(URLContext *s, const char *desc)
1644 RTMPContext *rt = s->priv_data;
1645 char buf[300], *ptr, authmod[15];
1647 const char *user = "", *salt = "", *opaque = NULL,
1648 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1650 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1651 !(cptr = strstr(desc, "authmod=llnw"))) {
1652 av_log(s, AV_LOG_ERROR,
1653 "Unknown connect error (unsupported authentication method?)\n");
1654 return AVERROR_UNKNOWN;
1656 cptr += strlen("authmod=");
1657 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1658 authmod[i++] = *cptr++;
1661 if (!rt->username[0] || !rt->password[0]) {
1662 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1663 return AVERROR_UNKNOWN;
1666 if (strstr(desc, "?reason=authfailed")) {
1667 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1668 return AVERROR_UNKNOWN;
1669 } else if (strstr(desc, "?reason=nosuchuser")) {
1670 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1671 return AVERROR_UNKNOWN;
1674 if (rt->auth_tried) {
1675 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1676 return AVERROR_UNKNOWN;
1679 rt->auth_params[0] = '\0';
1681 if (strstr(desc, "code=403 need auth")) {
1682 snprintf(rt->auth_params, sizeof(rt->auth_params),
1683 "?authmod=%s&user=%s", authmod, rt->username);
1687 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1688 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1689 return AVERROR_UNKNOWN;
1692 av_strlcpy(buf, cptr + 1, sizeof(buf));
1696 char *next = strchr(ptr, '&');
1697 char *value = strchr(ptr, '=');
1702 if (!strcmp(ptr, "user")) {
1704 } else if (!strcmp(ptr, "salt")) {
1706 } else if (!strcmp(ptr, "opaque")) {
1708 } else if (!strcmp(ptr, "challenge")) {
1710 } else if (!strcmp(ptr, "nonce")) {
1716 if (!strcmp(authmod, "adobe")) {
1717 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1720 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1728 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1730 RTMPContext *rt = s->priv_data;
1731 const uint8_t *data_end = pkt->data + pkt->size;
1732 char *tracked_method = NULL;
1733 int level = AV_LOG_ERROR;
1734 uint8_t tmpstr[256];
1737 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1740 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1741 "description", tmpstr, sizeof(tmpstr))) {
1742 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1743 !strcmp(tracked_method, "releaseStream") ||
1744 !strcmp(tracked_method, "FCSubscribe") ||
1745 !strcmp(tracked_method, "FCPublish"))) {
1746 /* Gracefully ignore Adobe-specific historical artifact errors. */
1747 level = AV_LOG_WARNING;
1749 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1750 ret = handle_connect_error(s, tmpstr);
1752 rt->do_reconnect = 1;
1753 level = AV_LOG_VERBOSE;
1756 ret = AVERROR_UNKNOWN;
1757 av_log(s, level, "Server error: %s\n", tmpstr);
1760 av_free(tracked_method);
1764 static int write_begin(URLContext *s)
1766 RTMPContext *rt = s->priv_data;
1768 RTMPPacket spkt = { 0 };
1771 // Send Stream Begin 1
1772 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1773 RTMP_PT_PING, 0, 6)) < 0) {
1774 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1778 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1779 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1780 bytestream2_put_be32(&pbc, rt->nb_streamid);
1782 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1785 ff_rtmp_packet_destroy(&spkt);
1790 static int write_status(URLContext *s, RTMPPacket *pkt,
1791 const char *status, const char *filename)
1793 RTMPContext *rt = s->priv_data;
1794 RTMPPacket spkt = { 0 };
1795 char statusmsg[128];
1799 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1801 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1802 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1807 spkt.extra = pkt->extra;
1808 ff_amf_write_string(&pp, "onStatus");
1809 ff_amf_write_number(&pp, 0);
1810 ff_amf_write_null(&pp);
1812 ff_amf_write_object_start(&pp);
1813 ff_amf_write_field_name(&pp, "level");
1814 ff_amf_write_string(&pp, "status");
1815 ff_amf_write_field_name(&pp, "code");
1816 ff_amf_write_string(&pp, status);
1817 ff_amf_write_field_name(&pp, "description");
1818 snprintf(statusmsg, sizeof(statusmsg),
1819 "%s is now published", filename);
1820 ff_amf_write_string(&pp, statusmsg);
1821 ff_amf_write_field_name(&pp, "details");
1822 ff_amf_write_string(&pp, filename);
1823 ff_amf_write_field_name(&pp, "clientid");
1824 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1825 ff_amf_write_string(&pp, statusmsg);
1826 ff_amf_write_object_end(&pp);
1828 spkt.size = pp - spkt.data;
1829 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1831 ff_rtmp_packet_destroy(&spkt);
1836 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1838 RTMPContext *rt = s->priv_data;
1844 const uint8_t *p = pkt->data;
1846 RTMPPacket spkt = { 0 };
1850 bytestream2_init(&gbc, p, pkt->size);
1851 if (ff_amf_read_string(&gbc, command, sizeof(command),
1853 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1854 return AVERROR_INVALIDDATA;
1857 ret = ff_amf_read_number(&gbc, &seqnum);
1860 ret = ff_amf_read_null(&gbc);
1863 if (!strcmp(command, "FCPublish") ||
1864 !strcmp(command, "publish")) {
1865 ret = ff_amf_read_string(&gbc, filename,
1866 sizeof(filename), &stringlen);
1869 pchar = strrchr(s->filename, '/');
1871 av_log(s, AV_LOG_WARNING,
1872 "Unable to find / in url %s, bad format\n",
1874 pchar = s->filename;
1877 if (strcmp(pchar, filename))
1878 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1879 " %s\n", filename, pchar);
1881 rt->state = STATE_RECEIVING;
1884 if (!strcmp(command, "FCPublish")) {
1885 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1887 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1888 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1892 ff_amf_write_string(&pp, "onFCPublish");
1893 } else if (!strcmp(command, "publish")) {
1894 ret = write_begin(s);
1898 // Send onStatus(NetStream.Publish.Start)
1899 return write_status(s, pkt, "NetStream.Publish.Start",
1901 } else if (!strcmp(command, "play")) {
1902 ret = write_begin(s);
1905 rt->state = STATE_SENDING;
1906 return write_status(s, pkt, "NetStream.Play.Start",
1909 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1911 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1912 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1916 ff_amf_write_string(&pp, "_result");
1917 ff_amf_write_number(&pp, seqnum);
1918 ff_amf_write_null(&pp);
1919 if (!strcmp(command, "createStream")) {
1921 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1922 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1923 ff_amf_write_number(&pp, rt->nb_streamid);
1924 /* By now we don't control which streams are removed in
1925 * deleteStream. There is no stream creation control
1926 * if a client creates more than 2^32 - 2 streams. */
1929 spkt.size = pp - spkt.data;
1930 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1932 ff_rtmp_packet_destroy(&spkt);
1936 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1938 RTMPContext *rt = s->priv_data;
1939 char *tracked_method = NULL;
1942 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1945 if (!tracked_method) {
1946 /* Ignore this reply when the current method is not tracked. */
1950 if (!strcmp(tracked_method, "connect")) {
1951 if (!rt->is_input) {
1952 if ((ret = gen_release_stream(s, rt)) < 0)
1955 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1958 if ((ret = gen_server_bw(s, rt)) < 0)
1962 if ((ret = gen_create_stream(s, rt)) < 0)
1966 /* Send the FCSubscribe command when the name of live
1967 * stream is defined by the user or if it's a live stream. */
1968 if (rt->subscribe) {
1969 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1971 } else if (rt->live == -1) {
1972 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1976 } else if (!strcmp(tracked_method, "createStream")) {
1977 //extract a number from the result
1978 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1979 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1981 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1984 if (!rt->is_input) {
1985 if ((ret = gen_publish(s, rt)) < 0)
1988 if ((ret = gen_play(s, rt)) < 0)
1990 if ((ret = gen_buffer_time(s, rt)) < 0)
1996 av_free(tracked_method);
2000 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2002 RTMPContext *rt = s->priv_data;
2003 const uint8_t *data_end = pkt->data + pkt->size;
2004 const uint8_t *ptr = pkt->data + 11;
2005 uint8_t tmpstr[256];
2008 for (i = 0; i < 2; i++) {
2009 t = ff_amf_tag_size(ptr, data_end);
2015 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2016 if (!t && !strcmp(tmpstr, "error")) {
2017 if (!ff_amf_get_field_value(ptr, data_end,
2018 "description", tmpstr, sizeof(tmpstr)))
2019 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2023 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2024 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2025 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2026 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2027 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2028 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2033 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2035 RTMPContext *rt = s->priv_data;
2038 //TODO: check for the messages sent for wrong state?
2039 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2040 if ((ret = handle_invoke_error(s, pkt)) < 0)
2042 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2043 if ((ret = handle_invoke_result(s, pkt)) < 0)
2045 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2046 if ((ret = handle_invoke_status(s, pkt)) < 0)
2048 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2049 if ((ret = gen_check_bw(s, rt)) < 0)
2051 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2052 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2053 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2054 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2055 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2056 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2057 if ((ret = send_invoke_response(s, pkt)) < 0)
2064 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
2065 RTMPContext *rt = s->priv_data;
2066 const uint8_t *p = NULL;
2067 uint8_t commandbuffer[64];
2068 char statusmsg[128];
2073 int old_flv_size, err;
2074 const uint8_t *datatowrite;
2075 unsigned datatowritelength;
2078 bytestream2_init(&gbc, p, pkt->size);
2079 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2081 return AVERROR_INVALIDDATA;
2082 if (!strcmp(commandbuffer, "@setDataFrame")) {
2083 datatowrite = gbc.buffer;
2084 datatowritelength = bytestream2_get_bytes_left(&gbc);
2085 if (ff_amf_read_string(&gbc, statusmsg,
2086 sizeof(statusmsg), &stringlen))
2087 return AVERROR_INVALIDDATA;
2089 datatowrite = pkt->data;
2090 datatowritelength = pkt->size;
2093 /* Provide ECMAArray to flv */
2094 ts = pkt->timestamp;
2096 // generate packet header and put data into buffer for FLV demuxer
2097 if (rt->flv_off < rt->flv_size) {
2098 // There is old unread data in the buffer, thus append at the end
2099 old_flv_size = rt->flv_size;
2100 rt->flv_size += datatowritelength + 15;
2102 // All data has been read, write the new data at the start of the buffer
2104 rt->flv_size = datatowritelength + 15;
2108 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2110 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2111 bytestream2_skip_p(&pbc, old_flv_size);
2112 bytestream2_put_byte(&pbc, pkt->type);
2113 bytestream2_put_be24(&pbc, datatowritelength);
2114 bytestream2_put_be24(&pbc, ts);
2115 bytestream2_put_byte(&pbc, ts >> 24);
2116 bytestream2_put_be24(&pbc, 0);
2117 bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
2118 bytestream2_put_be32(&pbc, 0);
2124 * Parse received packet and possibly perform some action depending on
2125 * the packet contents.
2126 * @return 0 for no errors, negative values for serious errors which prevent
2127 * further communications, positive values for uncritical errors
2129 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2134 ff_rtmp_packet_dump(s, pkt);
2137 switch (pkt->type) {
2138 case RTMP_PT_BYTES_READ:
2139 av_dlog(s, "received bytes read report\n");
2141 case RTMP_PT_CHUNK_SIZE:
2142 if ((ret = handle_chunk_size(s, pkt)) < 0)
2146 if ((ret = handle_ping(s, pkt)) < 0)
2149 case RTMP_PT_CLIENT_BW:
2150 if ((ret = handle_client_bw(s, pkt)) < 0)
2153 case RTMP_PT_SERVER_BW:
2154 if ((ret = handle_server_bw(s, pkt)) < 0)
2157 case RTMP_PT_INVOKE:
2158 if ((ret = handle_invoke(s, pkt)) < 0)
2163 case RTMP_PT_METADATA:
2164 case RTMP_PT_NOTIFY:
2165 /* Audio, Video and Metadata packets are parsed in get_packet() */
2168 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2175 * Interact with the server by receiving and sending RTMP packets until
2176 * there is some significant data (media data or expected status notification).
2178 * @param s reading context
2179 * @param for_header non-zero value tells function to work until it
2180 * gets notification from the server that playing has been started,
2181 * otherwise function will work until some media data is received (or
2183 * @return 0 for successful operation, negative value in case of error
2185 static int get_packet(URLContext *s, int for_header)
2187 RTMPContext *rt = s->priv_data;
2190 const uint8_t *next;
2192 uint32_t ts, cts, pts=0;
2194 if (rt->state == STATE_STOPPED)
2198 RTMPPacket rpkt = { 0 };
2199 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2200 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2202 return AVERROR(EAGAIN);
2204 return AVERROR(EIO);
2207 rt->bytes_read += ret;
2208 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2209 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2210 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2212 rt->last_bytes_read = rt->bytes_read;
2215 ret = rtmp_parse_result(s, rt, &rpkt);
2217 // At this point we must check if we are in the seek state and continue
2218 // with the next packet. handle_invoke will get us out of this state
2219 // when the right message is encountered
2220 if (rt->state == STATE_SEEKING) {
2221 ff_rtmp_packet_destroy(&rpkt);
2222 // We continue, let the natural flow of things happen:
2223 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2227 if (ret < 0) {//serious error in current packet
2228 ff_rtmp_packet_destroy(&rpkt);
2231 if (rt->do_reconnect && for_header) {
2232 ff_rtmp_packet_destroy(&rpkt);
2235 if (rt->state == STATE_STOPPED) {
2236 ff_rtmp_packet_destroy(&rpkt);
2239 if (for_header && (rt->state == STATE_PLAYING ||
2240 rt->state == STATE_PUBLISHING ||
2241 rt->state == STATE_SENDING ||
2242 rt->state == STATE_RECEIVING)) {
2243 ff_rtmp_packet_destroy(&rpkt);
2246 if (!rpkt.size || !rt->is_input) {
2247 ff_rtmp_packet_destroy(&rpkt);
2250 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2251 (rpkt.type == RTMP_PT_NOTIFY &&
2252 ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
2254 ts = rpkt.timestamp;
2256 // generate packet header and put data into buffer for FLV demuxer
2258 rt->flv_size = rpkt.size + 15;
2259 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2262 bytestream_put_byte(&p, rpkt.type);
2263 bytestream_put_be24(&p, rpkt.size);
2264 bytestream_put_be24(&p, ts);
2265 bytestream_put_byte(&p, ts >> 24);
2266 bytestream_put_be24(&p, 0);
2267 bytestream_put_buffer(&p, rpkt.data, rpkt.size);
2268 bytestream_put_be32(&p, 0);
2269 ff_rtmp_packet_destroy(&rpkt);
2271 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2272 ret = handle_notify(s, &rpkt);
2273 ff_rtmp_packet_destroy(&rpkt);
2275 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2279 } else if (rpkt.type == RTMP_PT_METADATA) {
2281 // we got raw FLV data, make it available for FLV demuxer
2283 rt->flv_size = rpkt.size;
2284 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2286 /* rewrite timestamps */
2288 ts = rpkt.timestamp;
2289 while (next - rpkt.data < rpkt.size - 11) {
2291 size = bytestream_get_be24(&next);
2293 cts = bytestream_get_be24(&next);
2294 cts |= bytestream_get_byte(&next) << 24;
2299 bytestream_put_be24(&p, ts);
2300 bytestream_put_byte(&p, ts >> 24);
2301 next += size + 3 + 4;
2303 memcpy(rt->flv_data, rpkt.data, rpkt.size);
2304 ff_rtmp_packet_destroy(&rpkt);
2307 ff_rtmp_packet_destroy(&rpkt);
2311 static int rtmp_close(URLContext *h)
2313 RTMPContext *rt = h->priv_data;
2316 if (!rt->is_input) {
2317 rt->flv_data = NULL;
2318 if (rt->out_pkt.size)
2319 ff_rtmp_packet_destroy(&rt->out_pkt);
2320 if (rt->state > STATE_FCPUBLISH)
2321 ret = gen_fcunpublish_stream(h, rt);
2323 if (rt->state > STATE_HANDSHAKED)
2324 ret = gen_delete_stream(h, rt);
2325 for (i = 0; i < 2; i++)
2326 for (j = 0; j < RTMP_CHANNELS; j++)
2327 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2329 free_tracked_methods(rt);
2330 av_freep(&rt->flv_data);
2331 ffurl_close(rt->stream);
2336 * Open RTMP connection and verify that the stream can be played.
2338 * URL syntax: rtmp://server[:port][/app][/playpath]
2339 * where 'app' is first one or two directories in the path
2340 * (e.g. /ondemand/, /flash/live/, etc.)
2341 * and 'playpath' is a file name (the rest of the path,
2342 * may be prefixed with "mp4:")
2344 static int rtmp_open(URLContext *s, const char *uri, int flags)
2346 RTMPContext *rt = s->priv_data;
2347 char proto[8], hostname[256], path[1024], auth[100], *fname;
2351 AVDictionary *opts = NULL;
2354 if (rt->listen_timeout > 0)
2357 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2359 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2360 hostname, sizeof(hostname), &port,
2361 path, sizeof(path), s->filename);
2363 if (strchr(path, ' ')) {
2364 av_log(s, AV_LOG_WARNING,
2365 "Detected librtmp style URL parameters, these aren't supported "
2366 "by the libavformat internal RTMP handler currently enabled. "
2367 "See the documentation for the correct way to pass parameters.\n");
2371 char *ptr = strchr(auth, ':');
2374 av_strlcpy(rt->username, auth, sizeof(rt->username));
2375 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2379 if (rt->listen && strcmp(proto, "rtmp")) {
2380 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2382 return AVERROR(EINVAL);
2384 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2385 if (!strcmp(proto, "rtmpts"))
2386 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2388 /* open the http tunneling connection */
2389 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2390 } else if (!strcmp(proto, "rtmps")) {
2391 /* open the tls connection */
2393 port = RTMPS_DEFAULT_PORT;
2394 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2395 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2396 if (!strcmp(proto, "rtmpte"))
2397 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2399 /* open the encrypted connection */
2400 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2403 /* open the tcp connection */
2405 port = RTMP_DEFAULT_PORT;
2407 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2408 "?listen&listen_timeout=%d",
2409 rt->listen_timeout * 1000);
2411 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2415 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2416 &s->interrupt_callback, &opts)) < 0) {
2417 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2421 if (rt->swfverify) {
2422 if ((ret = rtmp_calc_swfhash(s)) < 0)
2426 rt->state = STATE_START;
2427 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2429 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2432 rt->out_chunk_size = 128;
2433 rt->in_chunk_size = 128; // Probably overwritten later
2434 rt->state = STATE_HANDSHAKED;
2436 // Keep the application name when it has been defined by the user.
2439 rt->app = av_malloc(APP_MAX_LENGTH);
2441 ret = AVERROR(ENOMEM);
2445 //extract "app" part from path
2446 if (!strncmp(path, "/ondemand/", 10)) {
2448 memcpy(rt->app, "ondemand", 9);
2450 char *next = *path ? path + 1 : path;
2451 char *p = strchr(next, '/');
2456 // make sure we do not mismatch a playpath for an application instance
2457 char *c = strchr(p + 1, ':');
2458 fname = strchr(p + 1, '/');
2459 if (!fname || (c && c < fname)) {
2461 av_strlcpy(rt->app, path + 1, p - path);
2464 av_strlcpy(rt->app, path + 1, fname - path - 1);
2470 // The name of application has been defined by the user, override it.
2475 if (!rt->playpath) {
2476 int len = strlen(fname);
2478 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2479 if (!rt->playpath) {
2480 ret = AVERROR(ENOMEM);
2484 if (!strchr(fname, ':') && len >= 4 &&
2485 (!strcmp(fname + len - 4, ".f4v") ||
2486 !strcmp(fname + len - 4, ".mp4"))) {
2487 memcpy(rt->playpath, "mp4:", 5);
2488 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2489 fname[len - 4] = '\0';
2491 rt->playpath[0] = 0;
2493 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2497 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2499 ret = AVERROR(ENOMEM);
2502 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2503 port, "/%s", rt->app);
2506 if (!rt->flashver) {
2507 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2508 if (!rt->flashver) {
2509 ret = AVERROR(ENOMEM);
2513 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2514 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2515 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2517 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2518 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2522 rt->client_report_size = 1048576;
2524 rt->last_bytes_read = 0;
2525 rt->server_bw = 2500000;
2527 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2528 proto, path, rt->app, rt->playpath);
2530 if ((ret = gen_connect(s, rt)) < 0)
2533 if (read_connect(s, s->priv_data) < 0)
2538 ret = get_packet(s, 1);
2539 } while (ret == AVERROR(EAGAIN));
2543 if (rt->do_reconnect) {
2544 ffurl_close(rt->stream);
2546 rt->do_reconnect = 0;
2548 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2549 free_tracked_methods(rt);
2555 // generate FLV header for demuxer
2557 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2560 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2563 rt->flv_data = NULL;
2565 rt->skip_bytes = 13;
2568 s->max_packet_size = rt->stream->max_packet_size;
2573 av_dict_free(&opts);
2578 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2580 RTMPContext *rt = s->priv_data;
2581 int orig_size = size;
2585 int data_left = rt->flv_size - rt->flv_off;
2587 if (data_left >= size) {
2588 memcpy(buf, rt->flv_data + rt->flv_off, size);
2589 rt->flv_off += size;
2592 if (data_left > 0) {
2593 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2596 rt->flv_off = rt->flv_size;
2599 if ((ret = get_packet(s, 0)) < 0)
2605 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2608 RTMPContext *rt = s->priv_data;
2610 av_log(s, AV_LOG_DEBUG,
2611 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2612 stream_index, timestamp, flags);
2613 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2614 av_log(s, AV_LOG_ERROR,
2615 "Unable to send seek command on stream index %d at timestamp "
2616 "%"PRId64" with flags %08x\n",
2617 stream_index, timestamp, flags);
2620 rt->flv_off = rt->flv_size;
2621 rt->state = STATE_SEEKING;
2625 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2627 RTMPContext *rt = s->priv_data;
2628 int size_temp = size;
2629 int pktsize, pkttype;
2631 const uint8_t *buf_temp = buf;
2636 if (rt->skip_bytes) {
2637 int skip = FFMIN(rt->skip_bytes, size_temp);
2640 rt->skip_bytes -= skip;
2644 if (rt->flv_header_bytes < 11) {
2645 const uint8_t *header = rt->flv_header;
2646 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2647 int channel = RTMP_AUDIO_CHANNEL;
2648 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2649 rt->flv_header_bytes += copy;
2651 if (rt->flv_header_bytes < 11)
2654 pkttype = bytestream_get_byte(&header);
2655 pktsize = bytestream_get_be24(&header);
2656 ts = bytestream_get_be24(&header);
2657 ts |= bytestream_get_byte(&header) << 24;
2658 bytestream_get_be24(&header);
2659 rt->flv_size = pktsize;
2661 if (pkttype == RTMP_PT_VIDEO)
2662 channel = RTMP_VIDEO_CHANNEL;
2664 //force 12bytes header
2665 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2666 pkttype == RTMP_PT_NOTIFY) {
2667 if (pkttype == RTMP_PT_NOTIFY)
2669 rt->prev_pkt[1][channel].channel_id = 0;
2672 //this can be a big packet, it's better to send it right here
2673 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2674 pkttype, ts, pktsize)) < 0)
2677 rt->out_pkt.extra = rt->stream_id;
2678 rt->flv_data = rt->out_pkt.data;
2680 if (pkttype == RTMP_PT_NOTIFY)
2681 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2684 if (rt->flv_size - rt->flv_off > size_temp) {
2685 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2686 rt->flv_off += size_temp;
2689 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2690 size_temp -= rt->flv_size - rt->flv_off;
2691 rt->flv_off += rt->flv_size - rt->flv_off;
2694 if (rt->flv_off == rt->flv_size) {
2697 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2701 rt->flv_header_bytes = 0;
2702 rt->flv_nb_packets++;
2704 } while (buf_temp - buf < size);
2706 if (rt->flv_nb_packets < rt->flush_interval)
2708 rt->flv_nb_packets = 0;
2710 /* set stream into nonblocking mode */
2711 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2713 /* try to read one byte from the stream */
2714 ret = ffurl_read(rt->stream, &c, 1);
2716 /* switch the stream back into blocking mode */
2717 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2719 if (ret == AVERROR(EAGAIN)) {
2720 /* no incoming data to handle */
2722 } else if (ret < 0) {
2724 } else if (ret == 1) {
2725 RTMPPacket rpkt = { 0 };
2727 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2729 rt->prev_pkt[0], c)) <= 0)
2732 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2735 ff_rtmp_packet_destroy(&rpkt);
2741 #define OFFSET(x) offsetof(RTMPContext, x)
2742 #define DEC AV_OPT_FLAG_DECODING_PARAM
2743 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2745 static const AVOption rtmp_options[] = {
2746 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2747 {"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},
2748 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2749 {"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},
2750 {"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},
2751 {"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"},
2752 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2753 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2754 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2755 {"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},
2756 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2757 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2758 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2759 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2760 {"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},
2761 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2762 {"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},
2763 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2764 {"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" },
2768 #define RTMP_PROTOCOL(flavor) \
2769 static const AVClass flavor##_class = { \
2770 .class_name = #flavor, \
2771 .item_name = av_default_item_name, \
2772 .option = rtmp_options, \
2773 .version = LIBAVUTIL_VERSION_INT, \
2776 URLProtocol ff_##flavor##_protocol = { \
2778 .url_open = rtmp_open, \
2779 .url_read = rtmp_read, \
2780 .url_read_seek = rtmp_seek, \
2781 .url_write = rtmp_write, \
2782 .url_close = rtmp_close, \
2783 .priv_data_size = sizeof(RTMPContext), \
2784 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2785 .priv_data_class= &flavor##_class, \
2790 RTMP_PROTOCOL(rtmpe)
2791 RTMP_PROTOCOL(rtmps)
2792 RTMP_PROTOCOL(rtmpt)
2793 RTMP_PROTOCOL(rtmpte)
2794 RTMP_PROTOCOL(rtmpts)