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]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81 int nb_prev_pkt[2]; ///< number of elements in prev_pkt
82 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
83 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
84 int is_input; ///< input/output flag
85 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
86 int live; ///< 0: recorded, -1: live, -2: both
87 char *app; ///< name of application
88 char *conn; ///< append arbitrary AMF data to the Connect message
89 ClientState state; ///< current state
90 int stream_id; ///< ID assigned by the server for the stream
91 uint8_t* flv_data; ///< buffer with data for demuxer
92 int flv_size; ///< current buffer size
93 int flv_off; ///< number of bytes read from current buffer
94 int flv_nb_packets; ///< number of flv packets published
95 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
96 uint32_t client_report_size; ///< number of bytes after which client should report to server
97 uint32_t bytes_read; ///< number of bytes read from server
98 uint32_t last_bytes_read; ///< number of bytes read last reported to server
99 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
100 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
101 int flv_header_bytes; ///< number of initialized bytes in flv_header
102 int nb_invokes; ///< keeps track of invoke messages
103 char* tcurl; ///< url of the target stream
104 char* flashver; ///< version of the flash plugin
105 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
106 int swfhash_len; ///< length of the SHA256 hash
107 int swfsize; ///< size of the decompressed SWF file
108 char* swfurl; ///< url of the swf player
109 char* swfverify; ///< URL to player swf file, compute hash/size automatically
110 char swfverification[42]; ///< hash of the SWF verification
111 char* pageurl; ///< url of the web page
112 char* subscribe; ///< name of live stream to subscribe
113 int server_bw; ///< server bandwidth
114 int client_buffer_time; ///< client buffer time in ms
115 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
116 int encrypted; ///< use an encrypted connection (RTMPE only)
117 TrackedMethod*tracked_methods; ///< tracked methods buffer
118 int nb_tracked_methods; ///< number of tracked methods
119 int tracked_methods_size; ///< size of the tracked methods buffer
120 int listen; ///< listen mode flag
121 int listen_timeout; ///< listen timeout to wait for new connections
122 int nb_streamid; ///< The next stream id to return on createStream calls
125 char auth_params[500];
130 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
131 /** Client key used for digest signing */
132 static const uint8_t rtmp_player_key[] = {
133 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
134 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
136 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
137 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
138 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
141 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
142 /** Key used for RTMP server digest signing */
143 static const uint8_t rtmp_server_key[] = {
144 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
145 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
146 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
148 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
149 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
150 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
153 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
157 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
158 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
159 if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
160 sizeof(*rt->tracked_methods))) < 0) {
161 rt->nb_tracked_methods = 0;
162 rt->tracked_methods_size = 0;
167 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
168 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
169 return AVERROR(ENOMEM);
170 rt->tracked_methods[rt->nb_tracked_methods].id = id;
171 rt->nb_tracked_methods++;
176 static void del_tracked_method(RTMPContext *rt, int index)
178 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
179 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
180 rt->nb_tracked_methods--;
183 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
184 char **tracked_method)
186 RTMPContext *rt = s->priv_data;
192 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
193 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
196 for (i = 0; i < rt->nb_tracked_methods; i++) {
197 if (rt->tracked_methods[i].id != pkt_id)
200 *tracked_method = rt->tracked_methods[i].name;
201 del_tracked_method(rt, i);
208 static void free_tracked_methods(RTMPContext *rt)
212 for (i = 0; i < rt->nb_tracked_methods; i ++)
213 av_free(rt->tracked_methods[i].name);
214 av_free(rt->tracked_methods);
215 rt->tracked_methods = NULL;
216 rt->tracked_methods_size = 0;
217 rt->nb_tracked_methods = 0;
220 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
224 if (pkt->type == RTMP_PT_INVOKE && track) {
230 bytestream2_init(&gbc, pkt->data, pkt->size);
231 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
234 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
237 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
241 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
242 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
244 ff_rtmp_packet_destroy(pkt);
248 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
253 /* The type must be B for Boolean, N for number, S for string, O for
254 * object, or Z for null. For Booleans the data must be either 0 or 1 for
255 * FALSE or TRUE, respectively. Likewise for Objects the data must be
256 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
257 * may be named, by prefixing the type with 'N' and specifying the name
258 * before the value (ie. NB:myFlag:1). This option may be used multiple times
259 * to construct arbitrary AMF sequences. */
260 if (param[0] && param[1] == ':') {
263 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
266 value = strchr(field, ':');
272 ff_amf_write_field_name(p, field);
279 ff_amf_write_bool(p, value[0] != '0');
282 ff_amf_write_string(p, value);
285 ff_amf_write_number(p, strtod(value, NULL));
288 ff_amf_write_null(p);
292 ff_amf_write_object_start(p);
294 ff_amf_write_object_end(p);
304 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
305 return AVERROR(EINVAL);
309 * Generate 'connect' call and send it to the server.
311 static int gen_connect(URLContext *s, RTMPContext *rt)
317 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
318 0, 4096 + APP_MAX_LENGTH)) < 0)
323 ff_amf_write_string(&p, "connect");
324 ff_amf_write_number(&p, ++rt->nb_invokes);
325 ff_amf_write_object_start(&p);
326 ff_amf_write_field_name(&p, "app");
327 ff_amf_write_string2(&p, rt->app, rt->auth_params);
330 ff_amf_write_field_name(&p, "type");
331 ff_amf_write_string(&p, "nonprivate");
333 ff_amf_write_field_name(&p, "flashVer");
334 ff_amf_write_string(&p, rt->flashver);
337 ff_amf_write_field_name(&p, "swfUrl");
338 ff_amf_write_string(&p, rt->swfurl);
341 ff_amf_write_field_name(&p, "tcUrl");
342 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
344 ff_amf_write_field_name(&p, "fpad");
345 ff_amf_write_bool(&p, 0);
346 ff_amf_write_field_name(&p, "capabilities");
347 ff_amf_write_number(&p, 15.0);
349 /* Tell the server we support all the audio codecs except
350 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
351 * which are unused in the RTMP protocol implementation. */
352 ff_amf_write_field_name(&p, "audioCodecs");
353 ff_amf_write_number(&p, 4071.0);
354 ff_amf_write_field_name(&p, "videoCodecs");
355 ff_amf_write_number(&p, 252.0);
356 ff_amf_write_field_name(&p, "videoFunction");
357 ff_amf_write_number(&p, 1.0);
360 ff_amf_write_field_name(&p, "pageUrl");
361 ff_amf_write_string(&p, rt->pageurl);
364 ff_amf_write_object_end(&p);
367 char *param = rt->conn;
369 // Write arbitrary AMF data to the Connect message.
370 while (param != NULL) {
372 param += strspn(param, " ");
375 sep = strchr(param, ' ');
378 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
379 // Invalid AMF parameter.
380 ff_rtmp_packet_destroy(&pkt);
391 pkt.size = p - pkt.data;
393 return rtmp_send_packet(rt, &pkt, 1);
396 static int read_connect(URLContext *s, RTMPContext *rt)
398 RTMPPacket pkt = { 0 };
408 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
409 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
412 bytestream2_init(&gbc, cp, pkt.size);
413 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
414 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
415 ff_rtmp_packet_destroy(&pkt);
416 return AVERROR_INVALIDDATA;
418 if (strcmp(command, "connect")) {
419 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
420 ff_rtmp_packet_destroy(&pkt);
421 return AVERROR_INVALIDDATA;
423 ret = ff_amf_read_number(&gbc, &seqnum);
425 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
426 /* Here one could parse an AMF Object with data as flashVers and others. */
427 ret = ff_amf_get_field_value(gbc.buffer,
428 gbc.buffer + bytestream2_get_bytes_left(&gbc),
429 "app", tmpstr, sizeof(tmpstr));
431 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
432 if (!ret && strcmp(tmpstr, rt->app))
433 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
435 ff_rtmp_packet_destroy(&pkt);
437 // Send Window Acknowledgement Size (as defined in speficication)
438 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
439 RTMP_PT_SERVER_BW, 0, 4)) < 0)
442 bytestream_put_be32(&p, rt->server_bw);
443 pkt.size = p - pkt.data;
444 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
445 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
446 ff_rtmp_packet_destroy(&pkt);
449 // Send Peer Bandwidth
450 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
451 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
454 bytestream_put_be32(&p, rt->server_bw);
455 bytestream_put_byte(&p, 2); // dynamic
456 pkt.size = p - pkt.data;
457 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
458 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
459 ff_rtmp_packet_destroy(&pkt);
464 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
465 RTMP_PT_PING, 0, 6)) < 0)
469 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
470 bytestream_put_be32(&p, 0);
471 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
472 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
473 ff_rtmp_packet_destroy(&pkt);
478 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
479 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
483 bytestream_put_be32(&p, rt->out_chunk_size);
484 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
485 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
486 ff_rtmp_packet_destroy(&pkt);
490 // Send result_ NetConnection.Connect.Success to connect
491 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
493 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
497 ff_amf_write_string(&p, "_result");
498 ff_amf_write_number(&p, seqnum);
500 ff_amf_write_object_start(&p);
501 ff_amf_write_field_name(&p, "fmsVer");
502 ff_amf_write_string(&p, "FMS/3,0,1,123");
503 ff_amf_write_field_name(&p, "capabilities");
504 ff_amf_write_number(&p, 31);
505 ff_amf_write_object_end(&p);
507 ff_amf_write_object_start(&p);
508 ff_amf_write_field_name(&p, "level");
509 ff_amf_write_string(&p, "status");
510 ff_amf_write_field_name(&p, "code");
511 ff_amf_write_string(&p, "NetConnection.Connect.Success");
512 ff_amf_write_field_name(&p, "description");
513 ff_amf_write_string(&p, "Connection succeeded.");
514 ff_amf_write_field_name(&p, "objectEncoding");
515 ff_amf_write_number(&p, 0);
516 ff_amf_write_object_end(&p);
518 pkt.size = p - pkt.data;
519 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
520 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
521 ff_rtmp_packet_destroy(&pkt);
525 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
526 RTMP_PT_INVOKE, 0, 30)) < 0)
529 ff_amf_write_string(&p, "onBWDone");
530 ff_amf_write_number(&p, 0);
531 ff_amf_write_null(&p);
532 ff_amf_write_number(&p, 8192);
533 pkt.size = p - pkt.data;
534 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
535 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
536 ff_rtmp_packet_destroy(&pkt);
542 * Generate 'releaseStream' call and send it to the server. It should make
543 * the server release some channel for media streams.
545 static int gen_release_stream(URLContext *s, RTMPContext *rt)
551 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
552 0, 29 + strlen(rt->playpath))) < 0)
555 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
557 ff_amf_write_string(&p, "releaseStream");
558 ff_amf_write_number(&p, ++rt->nb_invokes);
559 ff_amf_write_null(&p);
560 ff_amf_write_string(&p, rt->playpath);
562 return rtmp_send_packet(rt, &pkt, 1);
566 * Generate 'FCPublish' call and send it to the server. It should make
567 * the server preapare for receiving media streams.
569 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
575 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
576 0, 25 + strlen(rt->playpath))) < 0)
579 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
581 ff_amf_write_string(&p, "FCPublish");
582 ff_amf_write_number(&p, ++rt->nb_invokes);
583 ff_amf_write_null(&p);
584 ff_amf_write_string(&p, rt->playpath);
586 return rtmp_send_packet(rt, &pkt, 1);
590 * Generate 'FCUnpublish' call and send it to the server. It should make
591 * the server destroy stream.
593 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
599 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
600 0, 27 + strlen(rt->playpath))) < 0)
603 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
605 ff_amf_write_string(&p, "FCUnpublish");
606 ff_amf_write_number(&p, ++rt->nb_invokes);
607 ff_amf_write_null(&p);
608 ff_amf_write_string(&p, rt->playpath);
610 return rtmp_send_packet(rt, &pkt, 0);
614 * Generate 'createStream' call and send it to the server. It should make
615 * the server allocate some channel for media streams.
617 static int gen_create_stream(URLContext *s, RTMPContext *rt)
623 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
625 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
630 ff_amf_write_string(&p, "createStream");
631 ff_amf_write_number(&p, ++rt->nb_invokes);
632 ff_amf_write_null(&p);
634 return rtmp_send_packet(rt, &pkt, 1);
639 * Generate 'deleteStream' call and send it to the server. It should make
640 * the server remove some channel for media streams.
642 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
648 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
650 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
655 ff_amf_write_string(&p, "deleteStream");
656 ff_amf_write_number(&p, ++rt->nb_invokes);
657 ff_amf_write_null(&p);
658 ff_amf_write_number(&p, rt->stream_id);
660 return rtmp_send_packet(rt, &pkt, 0);
664 * Generate client buffer time and send it to the server.
666 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
672 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
677 bytestream_put_be16(&p, 3);
678 bytestream_put_be32(&p, rt->stream_id);
679 bytestream_put_be32(&p, rt->client_buffer_time);
681 return rtmp_send_packet(rt, &pkt, 0);
685 * Generate 'play' call and send it to the server, then ping the server
686 * to start actual playing.
688 static int gen_play(URLContext *s, RTMPContext *rt)
694 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
696 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
697 0, 29 + strlen(rt->playpath))) < 0)
700 pkt.extra = rt->stream_id;
703 ff_amf_write_string(&p, "play");
704 ff_amf_write_number(&p, ++rt->nb_invokes);
705 ff_amf_write_null(&p);
706 ff_amf_write_string(&p, rt->playpath);
707 ff_amf_write_number(&p, rt->live * 1000);
709 return rtmp_send_packet(rt, &pkt, 1);
712 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
718 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
721 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
724 pkt.extra = rt->stream_id;
727 ff_amf_write_string(&p, "seek");
728 ff_amf_write_number(&p, 0); //no tracking back responses
729 ff_amf_write_null(&p); //as usual, the first null param
730 ff_amf_write_number(&p, timestamp); //where we want to jump
732 return rtmp_send_packet(rt, &pkt, 1);
736 * Generate 'publish' call and send it to the server.
738 static int gen_publish(URLContext *s, RTMPContext *rt)
744 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
746 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
747 0, 30 + strlen(rt->playpath))) < 0)
750 pkt.extra = rt->stream_id;
753 ff_amf_write_string(&p, "publish");
754 ff_amf_write_number(&p, ++rt->nb_invokes);
755 ff_amf_write_null(&p);
756 ff_amf_write_string(&p, rt->playpath);
757 ff_amf_write_string(&p, "live");
759 return rtmp_send_packet(rt, &pkt, 1);
763 * Generate ping reply and send it to the server.
765 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
771 if (ppkt->size < 6) {
772 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
774 return AVERROR_INVALIDDATA;
777 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
778 ppkt->timestamp + 1, 6)) < 0)
782 bytestream_put_be16(&p, 7);
783 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
785 return rtmp_send_packet(rt, &pkt, 0);
789 * Generate SWF verification message and send it to the server.
791 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
797 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
798 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
803 bytestream_put_be16(&p, 27);
804 memcpy(p, rt->swfverification, 42);
806 return rtmp_send_packet(rt, &pkt, 0);
810 * Generate server bandwidth message and send it to the server.
812 static int gen_server_bw(URLContext *s, RTMPContext *rt)
818 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
823 bytestream_put_be32(&p, rt->server_bw);
825 return rtmp_send_packet(rt, &pkt, 0);
829 * Generate check bandwidth message and send it to the server.
831 static int gen_check_bw(URLContext *s, RTMPContext *rt)
837 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
842 ff_amf_write_string(&p, "_checkbw");
843 ff_amf_write_number(&p, ++rt->nb_invokes);
844 ff_amf_write_null(&p);
846 return rtmp_send_packet(rt, &pkt, 1);
850 * Generate report on bytes read so far and send it to the server.
852 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
858 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
863 bytestream_put_be32(&p, rt->bytes_read);
865 return rtmp_send_packet(rt, &pkt, 0);
868 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
869 const char *subscribe)
875 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
876 0, 27 + strlen(subscribe))) < 0)
880 ff_amf_write_string(&p, "FCSubscribe");
881 ff_amf_write_number(&p, ++rt->nb_invokes);
882 ff_amf_write_null(&p);
883 ff_amf_write_string(&p, subscribe);
885 return rtmp_send_packet(rt, &pkt, 1);
888 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
889 const uint8_t *key, int keylen, uint8_t *dst)
892 uint8_t hmac_buf[64+32] = {0};
895 sha = av_sha_alloc();
897 return AVERROR(ENOMEM);
900 memcpy(hmac_buf, key, keylen);
902 av_sha_init(sha, 256);
903 av_sha_update(sha,key, keylen);
904 av_sha_final(sha, hmac_buf);
906 for (i = 0; i < 64; i++)
907 hmac_buf[i] ^= HMAC_IPAD_VAL;
909 av_sha_init(sha, 256);
910 av_sha_update(sha, hmac_buf, 64);
912 av_sha_update(sha, src, len);
913 } else { //skip 32 bytes used for storing digest
914 av_sha_update(sha, src, gap);
915 av_sha_update(sha, src + gap + 32, len - gap - 32);
917 av_sha_final(sha, hmac_buf + 64);
919 for (i = 0; i < 64; i++)
920 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
921 av_sha_init(sha, 256);
922 av_sha_update(sha, hmac_buf, 64+32);
923 av_sha_final(sha, dst);
930 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
933 int i, digest_pos = 0;
935 for (i = 0; i < 4; i++)
936 digest_pos += buf[i + off];
937 digest_pos = digest_pos % mod_val + add_val;
943 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
944 * will be stored) into that packet.
946 * @param buf handshake data (1536 bytes)
947 * @param encrypted use an encrypted connection (RTMPE)
948 * @return offset to the digest inside input data
950 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
955 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
957 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
959 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
960 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
969 * Verify that the received server response has the expected digest value.
971 * @param buf handshake data received from the server (1536 bytes)
972 * @param off position to search digest offset from
973 * @return 0 if digest is valid, digest position otherwise
975 static int rtmp_validate_digest(uint8_t *buf, int off)
980 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
982 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
983 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
988 if (!memcmp(digest, buf + digest_pos, 32))
993 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
999 if (rt->swfhash_len != 32) {
1000 av_log(s, AV_LOG_ERROR,
1001 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1002 return AVERROR(EINVAL);
1005 p = &rt->swfverification[0];
1006 bytestream_put_byte(&p, 1);
1007 bytestream_put_byte(&p, 1);
1008 bytestream_put_be32(&p, rt->swfsize);
1009 bytestream_put_be32(&p, rt->swfsize);
1011 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1018 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1019 uint8_t **out_data, int64_t *out_size)
1021 z_stream zs = { 0 };
1026 zs.avail_in = in_size;
1027 zs.next_in = in_data;
1028 ret = inflateInit(&zs);
1030 return AVERROR_UNKNOWN;
1033 uint8_t tmp_buf[16384];
1035 zs.avail_out = sizeof(tmp_buf);
1036 zs.next_out = tmp_buf;
1038 ret = inflate(&zs, Z_NO_FLUSH);
1039 if (ret != Z_OK && ret != Z_STREAM_END) {
1040 ret = AVERROR_UNKNOWN;
1044 size = sizeof(tmp_buf) - zs.avail_out;
1045 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1046 ret = AVERROR(ENOMEM);
1051 memcpy(*out_data + *out_size, tmp_buf, size);
1053 } while (zs.avail_out == 0);
1061 static int rtmp_calc_swfhash(URLContext *s)
1063 RTMPContext *rt = s->priv_data;
1064 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1065 int64_t in_size, out_size;
1071 /* Get the SWF player file. */
1072 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1073 &s->interrupt_callback, NULL)) < 0) {
1074 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1078 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1083 if (!(in_data = av_malloc(in_size))) {
1084 ret = AVERROR(ENOMEM);
1088 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1092 ret = AVERROR_INVALIDDATA;
1096 if (!memcmp(in_data, "CWS", 3)) {
1097 /* Decompress the SWF player file using Zlib. */
1098 if (!(out_data = av_malloc(8))) {
1099 ret = AVERROR(ENOMEM);
1102 *in_data = 'F'; // magic stuff
1103 memcpy(out_data, in_data, 8);
1107 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1108 &out_data, &out_size)) < 0)
1111 av_log(s, AV_LOG_ERROR,
1112 "Zlib is required for decompressing the SWF player file.\n");
1113 ret = AVERROR(EINVAL);
1123 /* Compute the SHA256 hash of the SWF player file. */
1124 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1125 "Genuine Adobe Flash Player 001", 30,
1129 /* Set SWFVerification parameters. */
1130 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1131 rt->swfsize = swfsize;
1135 av_freep(&out_data);
1136 ffurl_close(stream);
1141 * Perform handshake with the server by means of exchanging pseudorandom data
1142 * signed with HMAC-SHA2 digest.
1144 * @return 0 if handshake succeeds, negative value otherwise
1146 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1149 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1150 3, // unencrypted data
1151 0, 0, 0, 0, // client uptime
1157 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1158 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1160 int server_pos, client_pos;
1161 uint8_t digest[32], signature[32];
1164 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1166 av_lfg_init(&rnd, 0xDEADC0DE);
1167 // generate handshake packet - 1536 bytes of pseudorandom data
1168 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1169 tosend[i] = av_lfg_get(&rnd) >> 24;
1171 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1172 /* When the client wants to use RTMPE, we have to change the command
1173 * byte to 0x06 which means to use encrypted data and we have to set
1174 * the flash version to at least 9.0.115.0. */
1181 /* Initialize the Diffie-Hellmann context and generate the public key
1182 * to send to the server. */
1183 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1187 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1191 if ((ret = ffurl_write(rt->stream, tosend,
1192 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1193 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1197 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1198 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1199 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1203 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1204 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1205 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1209 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1210 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1211 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1213 if (rt->is_input && serverdata[5] >= 3) {
1214 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1220 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1225 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1226 return AVERROR(EIO);
1230 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1231 * key are the last 32 bytes of the server handshake. */
1233 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1234 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1238 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1239 rtmp_server_key, sizeof(rtmp_server_key),
1244 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1245 0, digest, 32, signature);
1249 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1250 /* Compute the shared secret key sent by the server and initialize
1251 * the RC4 encryption. */
1252 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1253 tosend + 1, type)) < 0)
1256 /* Encrypt the signature received by the server. */
1257 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1260 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1261 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1262 return AVERROR(EIO);
1265 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1266 tosend[i] = av_lfg_get(&rnd) >> 24;
1267 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1268 rtmp_player_key, sizeof(rtmp_player_key),
1273 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1275 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1279 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1280 /* Encrypt the signature to be send to the server. */
1281 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1282 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1286 // write reply back to the server
1287 if ((ret = ffurl_write(rt->stream, tosend,
1288 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1291 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1292 /* Set RC4 keys for encryption and update the keystreams. */
1293 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1297 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1298 /* Compute the shared secret key sent by the server and initialize
1299 * the RC4 encryption. */
1300 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1301 tosend + 1, 1)) < 0)
1304 if (serverdata[0] == 9) {
1305 /* Encrypt the signature received by the server. */
1306 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1311 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1312 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1315 if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1316 /* Set RC4 keys for encryption and update the keystreams. */
1317 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1325 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1326 uint32_t *second_int, char *arraydata,
1331 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1332 RTMP_HANDSHAKE_PACKET_SIZE);
1334 return AVERROR(EIO);
1335 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1336 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1337 " not following standard\n", (int)inoutsize);
1338 return AVERROR(EINVAL);
1341 *first_int = AV_RB32(arraydata);
1342 *second_int = AV_RB32(arraydata + 4);
1346 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1347 uint32_t second_int, char *arraydata, int size)
1351 AV_WB32(arraydata, first_int);
1352 AV_WB32(arraydata + 4, second_int);
1353 inoutsize = ffurl_write(rt->stream, arraydata,
1354 RTMP_HANDSHAKE_PACKET_SIZE);
1355 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1356 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1357 return AVERROR(EIO);
1364 * rtmp handshake server side
1366 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1368 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1370 uint32_t hs_my_epoch;
1371 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1372 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1379 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1380 if (inoutsize <= 0) {
1381 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1382 return AVERROR(EIO);
1385 if (buffer[0] != 3) {
1386 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1387 return AVERROR(EIO);
1389 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1390 av_log(s, AV_LOG_ERROR,
1391 "Unable to write answer - RTMP S0\n");
1392 return AVERROR(EIO);
1395 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1396 RTMP_HANDSHAKE_PACKET_SIZE);
1398 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1402 /* By now same epoch will be sent */
1403 hs_my_epoch = hs_epoch;
1404 /* Generate random */
1405 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1407 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1409 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1410 RTMP_HANDSHAKE_PACKET_SIZE);
1412 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1416 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1417 RTMP_HANDSHAKE_PACKET_SIZE);
1419 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1423 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1424 RTMP_HANDSHAKE_PACKET_SIZE);
1426 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1429 if (temp != hs_my_epoch)
1430 av_log(s, AV_LOG_WARNING,
1431 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1432 if (memcmp(buffer + 8, hs_s1 + 8,
1433 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1434 av_log(s, AV_LOG_WARNING,
1435 "Erroneous C2 Message random does not match up\n");
1440 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1442 RTMPContext *rt = s->priv_data;
1445 if (pkt->size < 4) {
1446 av_log(s, AV_LOG_ERROR,
1447 "Too short chunk size change packet (%d)\n",
1449 return AVERROR_INVALIDDATA;
1452 if (!rt->is_input) {
1453 /* Send the same chunk size change packet back to the server,
1454 * setting the outgoing chunk size to the same as the incoming one. */
1455 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1456 &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1458 rt->out_chunk_size = AV_RB32(pkt->data);
1461 rt->in_chunk_size = AV_RB32(pkt->data);
1462 if (rt->in_chunk_size <= 0) {
1463 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1465 return AVERROR_INVALIDDATA;
1467 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1473 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1475 RTMPContext *rt = s->priv_data;
1478 if (pkt->size < 2) {
1479 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1481 return AVERROR_INVALIDDATA;
1484 t = AV_RB16(pkt->data);
1486 if ((ret = gen_pong(s, rt, pkt)) < 0)
1488 } else if (t == 26) {
1490 if ((ret = gen_swf_verification(s, rt)) < 0)
1493 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1500 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1502 RTMPContext *rt = s->priv_data;
1504 if (pkt->size < 4) {
1505 av_log(s, AV_LOG_ERROR,
1506 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1508 return AVERROR_INVALIDDATA;
1511 rt->client_report_size = AV_RB32(pkt->data);
1512 if (rt->client_report_size <= 0) {
1513 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1514 rt->client_report_size);
1515 return AVERROR_INVALIDDATA;
1518 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1519 rt->client_report_size >>= 1;
1524 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1526 RTMPContext *rt = s->priv_data;
1528 if (pkt->size < 4) {
1529 av_log(s, AV_LOG_ERROR,
1530 "Too short server bandwidth report packet (%d)\n",
1532 return AVERROR_INVALIDDATA;
1535 rt->server_bw = AV_RB32(pkt->data);
1536 if (rt->server_bw <= 0) {
1537 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1539 return AVERROR_INVALIDDATA;
1541 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1546 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1547 const char *opaque, const char *challenge)
1550 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1551 struct AVMD5 *md5 = av_md5_alloc();
1553 return AVERROR(ENOMEM);
1555 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1558 av_md5_update(md5, user, strlen(user));
1559 av_md5_update(md5, salt, strlen(salt));
1560 av_md5_update(md5, rt->password, strlen(rt->password));
1561 av_md5_final(md5, hash);
1562 av_base64_encode(hashstr, sizeof(hashstr), hash,
1565 av_md5_update(md5, hashstr, strlen(hashstr));
1567 av_md5_update(md5, opaque, strlen(opaque));
1569 av_md5_update(md5, challenge, strlen(challenge));
1570 av_md5_update(md5, challenge2, strlen(challenge2));
1571 av_md5_final(md5, hash);
1572 av_base64_encode(hashstr, sizeof(hashstr), hash,
1574 snprintf(rt->auth_params, sizeof(rt->auth_params),
1575 "?authmod=%s&user=%s&challenge=%s&response=%s",
1576 "adobe", user, challenge2, hashstr);
1578 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1579 "&opaque=%s", opaque);
1585 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1588 char hashstr1[33], hashstr2[33];
1589 const char *realm = "live";
1590 const char *method = "publish";
1591 const char *qop = "auth";
1592 const char *nc = "00000001";
1594 struct AVMD5 *md5 = av_md5_alloc();
1596 return AVERROR(ENOMEM);
1598 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1601 av_md5_update(md5, user, strlen(user));
1602 av_md5_update(md5, ":", 1);
1603 av_md5_update(md5, realm, strlen(realm));
1604 av_md5_update(md5, ":", 1);
1605 av_md5_update(md5, rt->password, strlen(rt->password));
1606 av_md5_final(md5, hash);
1607 ff_data_to_hex(hashstr1, hash, 16, 1);
1608 hashstr1[32] = '\0';
1611 av_md5_update(md5, method, strlen(method));
1612 av_md5_update(md5, ":/", 2);
1613 av_md5_update(md5, rt->app, strlen(rt->app));
1614 if (!strchr(rt->app, '/'))
1615 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1616 av_md5_final(md5, hash);
1617 ff_data_to_hex(hashstr2, hash, 16, 1);
1618 hashstr2[32] = '\0';
1621 av_md5_update(md5, hashstr1, strlen(hashstr1));
1622 av_md5_update(md5, ":", 1);
1624 av_md5_update(md5, nonce, strlen(nonce));
1625 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, nc, strlen(nc));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, cnonce, strlen(cnonce));
1629 av_md5_update(md5, ":", 1);
1630 av_md5_update(md5, qop, strlen(qop));
1631 av_md5_update(md5, ":", 1);
1632 av_md5_update(md5, hashstr2, strlen(hashstr2));
1633 av_md5_final(md5, hash);
1634 ff_data_to_hex(hashstr1, hash, 16, 1);
1636 snprintf(rt->auth_params, sizeof(rt->auth_params),
1637 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1638 "llnw", user, nonce, cnonce, nc, hashstr1);
1644 static int handle_connect_error(URLContext *s, const char *desc)
1646 RTMPContext *rt = s->priv_data;
1647 char buf[300], *ptr, authmod[15];
1649 const char *user = "", *salt = "", *opaque = NULL,
1650 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1652 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1653 !(cptr = strstr(desc, "authmod=llnw"))) {
1654 av_log(s, AV_LOG_ERROR,
1655 "Unknown connect error (unsupported authentication method?)\n");
1656 return AVERROR_UNKNOWN;
1658 cptr += strlen("authmod=");
1659 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1660 authmod[i++] = *cptr++;
1663 if (!rt->username[0] || !rt->password[0]) {
1664 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1665 return AVERROR_UNKNOWN;
1668 if (strstr(desc, "?reason=authfailed")) {
1669 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1670 return AVERROR_UNKNOWN;
1671 } else if (strstr(desc, "?reason=nosuchuser")) {
1672 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1673 return AVERROR_UNKNOWN;
1676 if (rt->auth_tried) {
1677 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1678 return AVERROR_UNKNOWN;
1681 rt->auth_params[0] = '\0';
1683 if (strstr(desc, "code=403 need auth")) {
1684 snprintf(rt->auth_params, sizeof(rt->auth_params),
1685 "?authmod=%s&user=%s", authmod, rt->username);
1689 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1690 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1691 return AVERROR_UNKNOWN;
1694 av_strlcpy(buf, cptr + 1, sizeof(buf));
1698 char *next = strchr(ptr, '&');
1699 char *value = strchr(ptr, '=');
1704 if (!strcmp(ptr, "user")) {
1706 } else if (!strcmp(ptr, "salt")) {
1708 } else if (!strcmp(ptr, "opaque")) {
1710 } else if (!strcmp(ptr, "challenge")) {
1712 } else if (!strcmp(ptr, "nonce")) {
1718 if (!strcmp(authmod, "adobe")) {
1719 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1722 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1730 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1732 RTMPContext *rt = s->priv_data;
1733 const uint8_t *data_end = pkt->data + pkt->size;
1734 char *tracked_method = NULL;
1735 int level = AV_LOG_ERROR;
1736 uint8_t tmpstr[256];
1739 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1742 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1743 "description", tmpstr, sizeof(tmpstr))) {
1744 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1745 !strcmp(tracked_method, "releaseStream") ||
1746 !strcmp(tracked_method, "FCSubscribe") ||
1747 !strcmp(tracked_method, "FCPublish"))) {
1748 /* Gracefully ignore Adobe-specific historical artifact errors. */
1749 level = AV_LOG_WARNING;
1751 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1752 ret = handle_connect_error(s, tmpstr);
1754 rt->do_reconnect = 1;
1755 level = AV_LOG_VERBOSE;
1758 ret = AVERROR_UNKNOWN;
1759 av_log(s, level, "Server error: %s\n", tmpstr);
1762 av_free(tracked_method);
1766 static int write_begin(URLContext *s)
1768 RTMPContext *rt = s->priv_data;
1770 RTMPPacket spkt = { 0 };
1773 // Send Stream Begin 1
1774 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1775 RTMP_PT_PING, 0, 6)) < 0) {
1776 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1780 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1781 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1782 bytestream2_put_be32(&pbc, rt->nb_streamid);
1784 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1785 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1787 ff_rtmp_packet_destroy(&spkt);
1792 static int write_status(URLContext *s, RTMPPacket *pkt,
1793 const char *status, const char *filename)
1795 RTMPContext *rt = s->priv_data;
1796 RTMPPacket spkt = { 0 };
1797 char statusmsg[128];
1801 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1803 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1804 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1809 spkt.extra = pkt->extra;
1810 ff_amf_write_string(&pp, "onStatus");
1811 ff_amf_write_number(&pp, 0);
1812 ff_amf_write_null(&pp);
1814 ff_amf_write_object_start(&pp);
1815 ff_amf_write_field_name(&pp, "level");
1816 ff_amf_write_string(&pp, "status");
1817 ff_amf_write_field_name(&pp, "code");
1818 ff_amf_write_string(&pp, status);
1819 ff_amf_write_field_name(&pp, "description");
1820 snprintf(statusmsg, sizeof(statusmsg),
1821 "%s is now published", filename);
1822 ff_amf_write_string(&pp, statusmsg);
1823 ff_amf_write_field_name(&pp, "details");
1824 ff_amf_write_string(&pp, filename);
1825 ff_amf_write_field_name(&pp, "clientid");
1826 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1827 ff_amf_write_string(&pp, statusmsg);
1828 ff_amf_write_object_end(&pp);
1830 spkt.size = pp - spkt.data;
1831 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1832 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1833 ff_rtmp_packet_destroy(&spkt);
1838 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1840 RTMPContext *rt = s->priv_data;
1846 const uint8_t *p = pkt->data;
1848 RTMPPacket spkt = { 0 };
1852 bytestream2_init(&gbc, p, pkt->size);
1853 if (ff_amf_read_string(&gbc, command, sizeof(command),
1855 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1856 return AVERROR_INVALIDDATA;
1859 ret = ff_amf_read_number(&gbc, &seqnum);
1862 ret = ff_amf_read_null(&gbc);
1865 if (!strcmp(command, "FCPublish") ||
1866 !strcmp(command, "publish")) {
1867 ret = ff_amf_read_string(&gbc, filename,
1868 sizeof(filename), &stringlen);
1871 pchar = strrchr(s->filename, '/');
1873 av_log(s, AV_LOG_WARNING,
1874 "Unable to find / in url %s, bad format\n",
1876 pchar = s->filename;
1879 if (strcmp(pchar, filename))
1880 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1881 " %s\n", filename, pchar);
1883 rt->state = STATE_RECEIVING;
1886 if (!strcmp(command, "FCPublish")) {
1887 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1889 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1890 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1894 ff_amf_write_string(&pp, "onFCPublish");
1895 } else if (!strcmp(command, "publish")) {
1896 ret = write_begin(s);
1900 // Send onStatus(NetStream.Publish.Start)
1901 return write_status(s, pkt, "NetStream.Publish.Start",
1903 } else if (!strcmp(command, "play")) {
1904 ret = write_begin(s);
1907 rt->state = STATE_SENDING;
1908 return write_status(s, pkt, "NetStream.Play.Start",
1911 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1913 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1914 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1918 ff_amf_write_string(&pp, "_result");
1919 ff_amf_write_number(&pp, seqnum);
1920 ff_amf_write_null(&pp);
1921 if (!strcmp(command, "createStream")) {
1923 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1924 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1925 ff_amf_write_number(&pp, rt->nb_streamid);
1926 /* By now we don't control which streams are removed in
1927 * deleteStream. There is no stream creation control
1928 * if a client creates more than 2^32 - 2 streams. */
1931 spkt.size = pp - spkt.data;
1932 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1933 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1934 ff_rtmp_packet_destroy(&spkt);
1938 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1940 RTMPContext *rt = s->priv_data;
1941 char *tracked_method = NULL;
1944 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1947 if (!tracked_method) {
1948 /* Ignore this reply when the current method is not tracked. */
1952 if (!strcmp(tracked_method, "connect")) {
1953 if (!rt->is_input) {
1954 if ((ret = gen_release_stream(s, rt)) < 0)
1957 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1960 if ((ret = gen_server_bw(s, rt)) < 0)
1964 if ((ret = gen_create_stream(s, rt)) < 0)
1968 /* Send the FCSubscribe command when the name of live
1969 * stream is defined by the user or if it's a live stream. */
1970 if (rt->subscribe) {
1971 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1973 } else if (rt->live == -1) {
1974 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1978 } else if (!strcmp(tracked_method, "createStream")) {
1979 //extract a number from the result
1980 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1981 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1983 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1986 if (!rt->is_input) {
1987 if ((ret = gen_publish(s, rt)) < 0)
1990 if ((ret = gen_play(s, rt)) < 0)
1992 if ((ret = gen_buffer_time(s, rt)) < 0)
1998 av_free(tracked_method);
2002 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2004 RTMPContext *rt = s->priv_data;
2005 const uint8_t *data_end = pkt->data + pkt->size;
2006 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2007 uint8_t tmpstr[256];
2010 for (i = 0; i < 2; i++) {
2011 t = ff_amf_tag_size(ptr, data_end);
2017 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2018 if (!t && !strcmp(tmpstr, "error")) {
2019 t = ff_amf_get_field_value(ptr, data_end,
2020 "description", tmpstr, sizeof(tmpstr));
2021 if (t || !tmpstr[0])
2022 t = ff_amf_get_field_value(ptr, data_end, "code",
2023 tmpstr, sizeof(tmpstr));
2025 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2029 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2030 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2031 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2032 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2033 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2034 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2039 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2041 RTMPContext *rt = s->priv_data;
2044 //TODO: check for the messages sent for wrong state?
2045 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2046 if ((ret = handle_invoke_error(s, pkt)) < 0)
2048 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2049 if ((ret = handle_invoke_result(s, pkt)) < 0)
2051 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2052 if ((ret = handle_invoke_status(s, pkt)) < 0)
2054 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2055 if ((ret = gen_check_bw(s, rt)) < 0)
2057 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2058 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2059 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2060 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2061 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2062 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2063 if ((ret = send_invoke_response(s, pkt)) < 0)
2070 static int update_offset(RTMPContext *rt, int size)
2074 // generate packet header and put data into buffer for FLV demuxer
2075 if (rt->flv_off < rt->flv_size) {
2076 // There is old unread data in the buffer, thus append at the end
2077 old_flv_size = rt->flv_size;
2078 rt->flv_size += size;
2080 // All data has been read, write the new data at the start of the buffer
2082 rt->flv_size = size;
2086 return old_flv_size;
2089 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2091 int old_flv_size, ret;
2093 const uint8_t *data = pkt->data + skip;
2094 const int size = pkt->size - skip;
2095 uint32_t ts = pkt->timestamp;
2097 old_flv_size = update_offset(rt, size + 15);
2099 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2100 rt->flv_size = rt->flv_off = 0;
2103 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2104 bytestream2_skip_p(&pbc, old_flv_size);
2105 bytestream2_put_byte(&pbc, pkt->type);
2106 bytestream2_put_be24(&pbc, size);
2107 bytestream2_put_be24(&pbc, ts);
2108 bytestream2_put_byte(&pbc, ts >> 24);
2109 bytestream2_put_be24(&pbc, 0);
2110 bytestream2_put_buffer(&pbc, data, size);
2111 bytestream2_put_be32(&pbc, 0);
2116 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2118 RTMPContext *rt = s->priv_data;
2119 uint8_t commandbuffer[64];
2120 char statusmsg[128];
2121 int stringlen, ret, skip = 0;
2124 bytestream2_init(&gbc, pkt->data, pkt->size);
2125 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2127 return AVERROR_INVALIDDATA;
2129 // Skip the @setDataFrame string and validate it is a notification
2130 if (!strcmp(commandbuffer, "@setDataFrame")) {
2131 skip = gbc.buffer - pkt->data;
2132 ret = ff_amf_read_string(&gbc, statusmsg,
2133 sizeof(statusmsg), &stringlen);
2135 return AVERROR_INVALIDDATA;
2138 return append_flv_data(rt, pkt, skip);
2142 * Parse received packet and possibly perform some action depending on
2143 * the packet contents.
2144 * @return 0 for no errors, negative values for serious errors which prevent
2145 * further communications, positive values for uncritical errors
2147 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2152 ff_rtmp_packet_dump(s, pkt);
2155 switch (pkt->type) {
2156 case RTMP_PT_BYTES_READ:
2157 av_dlog(s, "received bytes read report\n");
2159 case RTMP_PT_CHUNK_SIZE:
2160 if ((ret = handle_chunk_size(s, pkt)) < 0)
2164 if ((ret = handle_ping(s, pkt)) < 0)
2167 case RTMP_PT_CLIENT_BW:
2168 if ((ret = handle_client_bw(s, pkt)) < 0)
2171 case RTMP_PT_SERVER_BW:
2172 if ((ret = handle_server_bw(s, pkt)) < 0)
2175 case RTMP_PT_INVOKE:
2176 if ((ret = handle_invoke(s, pkt)) < 0)
2181 case RTMP_PT_METADATA:
2182 case RTMP_PT_NOTIFY:
2183 /* Audio, Video and Metadata packets are parsed in get_packet() */
2186 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2192 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2194 int ret, old_flv_size, type;
2195 const uint8_t *next;
2198 uint32_t ts, cts, pts = 0;
2200 old_flv_size = update_offset(rt, pkt->size);
2202 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2203 rt->flv_size = rt->flv_off = 0;
2208 p = rt->flv_data + old_flv_size;
2210 /* copy data while rewriting timestamps */
2211 ts = pkt->timestamp;
2213 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2214 type = bytestream_get_byte(&next);
2215 size = bytestream_get_be24(&next);
2216 cts = bytestream_get_be24(&next);
2217 cts |= bytestream_get_byte(&next) << 24;
2222 if (size + 3 + 4 > pkt->data + pkt->size - next)
2224 bytestream_put_byte(&p, type);
2225 bytestream_put_be24(&p, size);
2226 bytestream_put_be24(&p, ts);
2227 bytestream_put_byte(&p, ts >> 24);
2228 memcpy(p, next, size + 3 + 4);
2229 next += size + 3 + 4;
2232 if (p != rt->flv_data + rt->flv_size) {
2233 av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2234 "RTMP_PT_METADATA packet\n");
2235 rt->flv_size = p - rt->flv_data;
2242 * Interact with the server by receiving and sending RTMP packets until
2243 * there is some significant data (media data or expected status notification).
2245 * @param s reading context
2246 * @param for_header non-zero value tells function to work until it
2247 * gets notification from the server that playing has been started,
2248 * otherwise function will work until some media data is received (or
2250 * @return 0 for successful operation, negative value in case of error
2252 static int get_packet(URLContext *s, int for_header)
2254 RTMPContext *rt = s->priv_data;
2257 if (rt->state == STATE_STOPPED)
2261 RTMPPacket rpkt = { 0 };
2262 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2263 rt->in_chunk_size, &rt->prev_pkt[0],
2264 &rt->nb_prev_pkt[0])) <= 0) {
2266 return AVERROR(EAGAIN);
2268 return AVERROR(EIO);
2271 rt->bytes_read += ret;
2272 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2273 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2274 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2276 rt->last_bytes_read = rt->bytes_read;
2279 ret = rtmp_parse_result(s, rt, &rpkt);
2281 // At this point we must check if we are in the seek state and continue
2282 // with the next packet. handle_invoke will get us out of this state
2283 // when the right message is encountered
2284 if (rt->state == STATE_SEEKING) {
2285 ff_rtmp_packet_destroy(&rpkt);
2286 // We continue, let the natural flow of things happen:
2287 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2291 if (ret < 0) {//serious error in current packet
2292 ff_rtmp_packet_destroy(&rpkt);
2295 if (rt->do_reconnect && for_header) {
2296 ff_rtmp_packet_destroy(&rpkt);
2299 if (rt->state == STATE_STOPPED) {
2300 ff_rtmp_packet_destroy(&rpkt);
2303 if (for_header && (rt->state == STATE_PLAYING ||
2304 rt->state == STATE_PUBLISHING ||
2305 rt->state == STATE_SENDING ||
2306 rt->state == STATE_RECEIVING)) {
2307 ff_rtmp_packet_destroy(&rpkt);
2310 if (!rpkt.size || !rt->is_input) {
2311 ff_rtmp_packet_destroy(&rpkt);
2314 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2315 ret = append_flv_data(rt, &rpkt, 0);
2316 ff_rtmp_packet_destroy(&rpkt);
2318 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2319 ret = handle_notify(s, &rpkt);
2320 ff_rtmp_packet_destroy(&rpkt);
2322 } else if (rpkt.type == RTMP_PT_METADATA) {
2323 ret = handle_metadata(rt, &rpkt);
2324 ff_rtmp_packet_destroy(&rpkt);
2327 ff_rtmp_packet_destroy(&rpkt);
2331 static int rtmp_close(URLContext *h)
2333 RTMPContext *rt = h->priv_data;
2336 if (!rt->is_input) {
2337 rt->flv_data = NULL;
2338 if (rt->out_pkt.size)
2339 ff_rtmp_packet_destroy(&rt->out_pkt);
2340 if (rt->state > STATE_FCPUBLISH)
2341 ret = gen_fcunpublish_stream(h, rt);
2343 if (rt->state > STATE_HANDSHAKED)
2344 ret = gen_delete_stream(h, rt);
2345 for (i = 0; i < 2; i++) {
2346 for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2347 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2348 av_freep(&rt->prev_pkt[i]);
2351 free_tracked_methods(rt);
2352 av_freep(&rt->flv_data);
2353 ffurl_close(rt->stream);
2358 * Open RTMP connection and verify that the stream can be played.
2360 * URL syntax: rtmp://server[:port][/app][/playpath]
2361 * where 'app' is first one or two directories in the path
2362 * (e.g. /ondemand/, /flash/live/, etc.)
2363 * and 'playpath' is a file name (the rest of the path,
2364 * may be prefixed with "mp4:")
2366 static int rtmp_open(URLContext *s, const char *uri, int flags)
2368 RTMPContext *rt = s->priv_data;
2369 char proto[8], hostname[256], path[1024], auth[100], *fname;
2373 AVDictionary *opts = NULL;
2376 if (rt->listen_timeout > 0)
2379 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2381 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2382 hostname, sizeof(hostname), &port,
2383 path, sizeof(path), s->filename);
2385 if (strchr(path, ' ')) {
2386 av_log(s, AV_LOG_WARNING,
2387 "Detected librtmp style URL parameters, these aren't supported "
2388 "by the libavformat internal RTMP handler currently enabled. "
2389 "See the documentation for the correct way to pass parameters.\n");
2393 char *ptr = strchr(auth, ':');
2396 av_strlcpy(rt->username, auth, sizeof(rt->username));
2397 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2401 if (rt->listen && strcmp(proto, "rtmp")) {
2402 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2404 return AVERROR(EINVAL);
2406 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2407 if (!strcmp(proto, "rtmpts"))
2408 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2410 /* open the http tunneling connection */
2411 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2412 } else if (!strcmp(proto, "rtmps")) {
2413 /* open the tls connection */
2415 port = RTMPS_DEFAULT_PORT;
2416 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2417 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2418 if (!strcmp(proto, "rtmpte"))
2419 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2421 /* open the encrypted connection */
2422 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2425 /* open the tcp connection */
2427 port = RTMP_DEFAULT_PORT;
2429 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2430 "?listen&listen_timeout=%d",
2431 rt->listen_timeout * 1000);
2433 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2437 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2438 &s->interrupt_callback, &opts)) < 0) {
2439 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2443 if (rt->swfverify) {
2444 if ((ret = rtmp_calc_swfhash(s)) < 0)
2448 rt->state = STATE_START;
2449 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2451 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2454 rt->out_chunk_size = 128;
2455 rt->in_chunk_size = 128; // Probably overwritten later
2456 rt->state = STATE_HANDSHAKED;
2458 // Keep the application name when it has been defined by the user.
2461 rt->app = av_malloc(APP_MAX_LENGTH);
2463 ret = AVERROR(ENOMEM);
2467 //extract "app" part from path
2468 if (!strncmp(path, "/ondemand/", 10)) {
2470 memcpy(rt->app, "ondemand", 9);
2472 char *next = *path ? path + 1 : path;
2473 char *p = strchr(next, '/');
2478 // make sure we do not mismatch a playpath for an application instance
2479 char *c = strchr(p + 1, ':');
2480 fname = strchr(p + 1, '/');
2481 if (!fname || (c && c < fname)) {
2483 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2486 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2492 // The name of application has been defined by the user, override it.
2493 if (strlen(old_app) >= APP_MAX_LENGTH) {
2494 ret = AVERROR(EINVAL);
2501 if (!rt->playpath) {
2502 int len = strlen(fname);
2504 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2505 if (!rt->playpath) {
2506 ret = AVERROR(ENOMEM);
2510 if (!strchr(fname, ':') && len >= 4 &&
2511 (!strcmp(fname + len - 4, ".f4v") ||
2512 !strcmp(fname + len - 4, ".mp4"))) {
2513 memcpy(rt->playpath, "mp4:", 5);
2515 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2516 fname[len - 4] = '\0';
2517 rt->playpath[0] = 0;
2519 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2523 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2525 ret = AVERROR(ENOMEM);
2528 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2529 port, "/%s", rt->app);
2532 if (!rt->flashver) {
2533 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2534 if (!rt->flashver) {
2535 ret = AVERROR(ENOMEM);
2539 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2540 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2541 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2543 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2544 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2548 rt->client_report_size = 1048576;
2550 rt->last_bytes_read = 0;
2551 rt->server_bw = 2500000;
2553 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2554 proto, path, rt->app, rt->playpath);
2556 if ((ret = gen_connect(s, rt)) < 0)
2559 if (read_connect(s, s->priv_data) < 0)
2564 ret = get_packet(s, 1);
2565 } while (ret == AVERROR(EAGAIN));
2569 if (rt->do_reconnect) {
2571 ffurl_close(rt->stream);
2573 rt->do_reconnect = 0;
2575 for (i = 0; i < 2; i++)
2576 memset(rt->prev_pkt[i], 0,
2577 sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2578 free_tracked_methods(rt);
2584 // generate FLV header for demuxer
2586 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2589 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2592 rt->flv_data = NULL;
2594 rt->skip_bytes = 13;
2597 s->max_packet_size = rt->stream->max_packet_size;
2602 av_dict_free(&opts);
2607 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2609 RTMPContext *rt = s->priv_data;
2610 int orig_size = size;
2614 int data_left = rt->flv_size - rt->flv_off;
2616 if (data_left >= size) {
2617 memcpy(buf, rt->flv_data + rt->flv_off, size);
2618 rt->flv_off += size;
2621 if (data_left > 0) {
2622 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2625 rt->flv_off = rt->flv_size;
2628 if ((ret = get_packet(s, 0)) < 0)
2634 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2637 RTMPContext *rt = s->priv_data;
2639 av_log(s, AV_LOG_DEBUG,
2640 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2641 stream_index, timestamp, flags);
2642 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2643 av_log(s, AV_LOG_ERROR,
2644 "Unable to send seek command on stream index %d at timestamp "
2645 "%"PRId64" with flags %08x\n",
2646 stream_index, timestamp, flags);
2649 rt->flv_off = rt->flv_size;
2650 rt->state = STATE_SEEKING;
2654 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2656 RTMPContext *rt = s->priv_data;
2657 int size_temp = size;
2658 int pktsize, pkttype;
2660 const uint8_t *buf_temp = buf;
2665 if (rt->skip_bytes) {
2666 int skip = FFMIN(rt->skip_bytes, size_temp);
2669 rt->skip_bytes -= skip;
2673 if (rt->flv_header_bytes < RTMP_HEADER) {
2674 const uint8_t *header = rt->flv_header;
2675 int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2676 int channel = RTMP_AUDIO_CHANNEL;
2677 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2678 rt->flv_header_bytes += copy;
2680 if (rt->flv_header_bytes < RTMP_HEADER)
2683 pkttype = bytestream_get_byte(&header);
2684 pktsize = bytestream_get_be24(&header);
2685 ts = bytestream_get_be24(&header);
2686 ts |= bytestream_get_byte(&header) << 24;
2687 bytestream_get_be24(&header);
2688 rt->flv_size = pktsize;
2690 if (pkttype == RTMP_PT_VIDEO)
2691 channel = RTMP_VIDEO_CHANNEL;
2693 //force 12bytes header
2694 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2695 pkttype == RTMP_PT_NOTIFY) {
2696 if (pkttype == RTMP_PT_NOTIFY)
2698 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2699 &rt->nb_prev_pkt[1],
2702 rt->prev_pkt[1][channel].channel_id = 0;
2705 //this can be a big packet, it's better to send it right here
2706 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2707 pkttype, ts, pktsize)) < 0)
2710 rt->out_pkt.extra = rt->stream_id;
2711 rt->flv_data = rt->out_pkt.data;
2713 if (pkttype == RTMP_PT_NOTIFY)
2714 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2717 if (rt->flv_size - rt->flv_off > size_temp) {
2718 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2719 rt->flv_off += size_temp;
2722 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2723 size_temp -= rt->flv_size - rt->flv_off;
2724 rt->flv_off += rt->flv_size - rt->flv_off;
2727 if (rt->flv_off == rt->flv_size) {
2730 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2734 rt->flv_header_bytes = 0;
2735 rt->flv_nb_packets++;
2737 } while (buf_temp - buf < size);
2739 if (rt->flv_nb_packets < rt->flush_interval)
2741 rt->flv_nb_packets = 0;
2743 /* set stream into nonblocking mode */
2744 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2746 /* try to read one byte from the stream */
2747 ret = ffurl_read(rt->stream, &c, 1);
2749 /* switch the stream back into blocking mode */
2750 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2752 if (ret == AVERROR(EAGAIN)) {
2753 /* no incoming data to handle */
2755 } else if (ret < 0) {
2757 } else if (ret == 1) {
2758 RTMPPacket rpkt = { 0 };
2760 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2763 &rt->nb_prev_pkt[0], c)) <= 0)
2766 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2769 ff_rtmp_packet_destroy(&rpkt);
2775 #define OFFSET(x) offsetof(RTMPContext, x)
2776 #define DEC AV_OPT_FLAG_DECODING_PARAM
2777 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2779 static const AVOption rtmp_options[] = {
2780 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2781 {"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},
2782 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2783 {"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},
2784 {"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},
2785 {"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"},
2786 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2787 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2788 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2789 {"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},
2790 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2791 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2792 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2793 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2794 {"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},
2795 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2796 {"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},
2797 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2798 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2799 {"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" },
2803 #define RTMP_PROTOCOL(flavor) \
2804 static const AVClass flavor##_class = { \
2805 .class_name = #flavor, \
2806 .item_name = av_default_item_name, \
2807 .option = rtmp_options, \
2808 .version = LIBAVUTIL_VERSION_INT, \
2811 URLProtocol ff_##flavor##_protocol = { \
2813 .url_open = rtmp_open, \
2814 .url_read = rtmp_read, \
2815 .url_read_seek = rtmp_seek, \
2816 .url_write = rtmp_write, \
2817 .url_close = rtmp_close, \
2818 .priv_data_size = sizeof(RTMPContext), \
2819 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2820 .priv_data_class= &flavor##_class, \
2825 RTMP_PROTOCOL(rtmpe)
2826 RTMP_PROTOCOL(rtmps)
2827 RTMP_PROTOCOL(rtmpt)
2828 RTMP_PROTOCOL(rtmpte)
2829 RTMP_PROTOCOL(rtmpts)