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
56 #define RTMP_HEADER 11
58 /** RTMP protocol handler state */
60 STATE_START, ///< client has not done anything yet
61 STATE_HANDSHAKED, ///< client has performed handshake
62 STATE_FCPUBLISH, ///< client FCPublishing stream (for output)
63 STATE_PLAYING, ///< client has started receiving multimedia data from server
64 STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65 STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66 STATE_RECEIVING, ///< received a publish command (for input)
67 STATE_SENDING, ///< received a play command (for output)
68 STATE_STOPPED, ///< the broadcast has been stopped
71 typedef struct TrackedMethod {
76 /** protocol handler context */
77 typedef struct RTMPContext {
79 URLContext* stream; ///< TCP stream used in interactions with RTMP server
80 RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81 int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
82 int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
83 int is_input; ///< input/output flag
84 char *playpath; ///< stream identifier to play (with possible "mp4:" prefix)
85 int live; ///< 0: recorded, -1: live, -2: both
86 char *app; ///< name of application
87 char *conn; ///< append arbitrary AMF data to the Connect message
88 ClientState state; ///< current state
89 int stream_id; ///< ID assigned by the server for the stream
90 uint8_t* flv_data; ///< buffer with data for demuxer
91 int flv_size; ///< current buffer size
92 int flv_off; ///< number of bytes read from current buffer
93 int flv_nb_packets; ///< number of flv packets published
94 RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
95 uint32_t client_report_size; ///< number of bytes after which client should report to server
96 uint32_t bytes_read; ///< number of bytes read from server
97 uint32_t last_bytes_read; ///< number of bytes read last reported to server
98 int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
99 uint8_t flv_header[RTMP_HEADER]; ///< partial incoming flv packet header
100 int flv_header_bytes; ///< number of initialized bytes in flv_header
101 int nb_invokes; ///< keeps track of invoke messages
102 char* tcurl; ///< url of the target stream
103 char* flashver; ///< version of the flash plugin
104 char* swfhash; ///< SHA256 hash of the decompressed SWF file (32 bytes)
105 int swfhash_len; ///< length of the SHA256 hash
106 int swfsize; ///< size of the decompressed SWF file
107 char* swfurl; ///< url of the swf player
108 char* swfverify; ///< URL to player swf file, compute hash/size automatically
109 char swfverification[42]; ///< hash of the SWF verification
110 char* pageurl; ///< url of the web page
111 char* subscribe; ///< name of live stream to subscribe
112 int server_bw; ///< server bandwidth
113 int client_buffer_time; ///< client buffer time in ms
114 int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
115 int encrypted; ///< use an encrypted connection (RTMPE only)
116 TrackedMethod*tracked_methods; ///< tracked methods buffer
117 int nb_tracked_methods; ///< number of tracked methods
118 int tracked_methods_size; ///< size of the tracked methods buffer
119 int listen; ///< listen mode flag
120 int listen_timeout; ///< listen timeout to wait for new connections
121 int nb_streamid; ///< The next stream id to return on createStream calls
124 char auth_params[500];
129 #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
130 /** Client key used for digest signing */
131 static const uint8_t rtmp_player_key[] = {
132 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
133 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
135 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
136 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
137 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
140 #define SERVER_KEY_OPEN_PART_LEN 36 ///< length of partial key used for first server digest signing
141 /** Key used for RTMP server digest signing */
142 static const uint8_t rtmp_server_key[] = {
143 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
144 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
145 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
147 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
148 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
149 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
152 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
156 if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
157 rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
158 if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
159 sizeof(*rt->tracked_methods))) < 0) {
160 rt->nb_tracked_methods = 0;
161 rt->tracked_methods_size = 0;
166 rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
167 if (!rt->tracked_methods[rt->nb_tracked_methods].name)
168 return AVERROR(ENOMEM);
169 rt->tracked_methods[rt->nb_tracked_methods].id = id;
170 rt->nb_tracked_methods++;
175 static void del_tracked_method(RTMPContext *rt, int index)
177 memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
178 sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
179 rt->nb_tracked_methods--;
182 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
183 char **tracked_method)
185 RTMPContext *rt = s->priv_data;
191 bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
192 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
195 for (i = 0; i < rt->nb_tracked_methods; i++) {
196 if (rt->tracked_methods[i].id != pkt_id)
199 *tracked_method = rt->tracked_methods[i].name;
200 del_tracked_method(rt, i);
207 static void free_tracked_methods(RTMPContext *rt)
211 for (i = 0; i < rt->nb_tracked_methods; i ++)
212 av_free(rt->tracked_methods[i].name);
213 av_free(rt->tracked_methods);
214 rt->tracked_methods = NULL;
215 rt->tracked_methods_size = 0;
216 rt->nb_tracked_methods = 0;
219 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
223 if (pkt->type == RTMP_PT_INVOKE && track) {
229 bytestream2_init(&gbc, pkt->data, pkt->size);
230 if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
233 if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
236 if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
240 ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
243 ff_rtmp_packet_destroy(pkt);
247 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
252 /* The type must be B for Boolean, N for number, S for string, O for
253 * object, or Z for null. For Booleans the data must be either 0 or 1 for
254 * FALSE or TRUE, respectively. Likewise for Objects the data must be
255 * 0 or 1 to end or begin an object, respectively. Data items in subobjects
256 * may be named, by prefixing the type with 'N' and specifying the name
257 * before the value (ie. NB:myFlag:1). This option may be used multiple times
258 * to construct arbitrary AMF sequences. */
259 if (param[0] && param[1] == ':') {
262 } else if (param[0] == 'N' && param[1] && param[2] == ':') {
265 value = strchr(field, ':');
271 if (!field || !value)
274 ff_amf_write_field_name(p, field);
281 ff_amf_write_bool(p, value[0] != '0');
284 ff_amf_write_string(p, value);
287 ff_amf_write_number(p, strtod(value, NULL));
290 ff_amf_write_null(p);
294 ff_amf_write_object_start(p);
296 ff_amf_write_object_end(p);
306 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
307 return AVERROR(EINVAL);
311 * Generate 'connect' call and send it to the server.
313 static int gen_connect(URLContext *s, RTMPContext *rt)
319 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
325 ff_amf_write_string(&p, "connect");
326 ff_amf_write_number(&p, ++rt->nb_invokes);
327 ff_amf_write_object_start(&p);
328 ff_amf_write_field_name(&p, "app");
329 ff_amf_write_string2(&p, rt->app, rt->auth_params);
332 ff_amf_write_field_name(&p, "type");
333 ff_amf_write_string(&p, "nonprivate");
335 ff_amf_write_field_name(&p, "flashVer");
336 ff_amf_write_string(&p, rt->flashver);
339 ff_amf_write_field_name(&p, "swfUrl");
340 ff_amf_write_string(&p, rt->swfurl);
343 ff_amf_write_field_name(&p, "tcUrl");
344 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
346 ff_amf_write_field_name(&p, "fpad");
347 ff_amf_write_bool(&p, 0);
348 ff_amf_write_field_name(&p, "capabilities");
349 ff_amf_write_number(&p, 15.0);
351 /* Tell the server we support all the audio codecs except
352 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
353 * which are unused in the RTMP protocol implementation. */
354 ff_amf_write_field_name(&p, "audioCodecs");
355 ff_amf_write_number(&p, 4071.0);
356 ff_amf_write_field_name(&p, "videoCodecs");
357 ff_amf_write_number(&p, 252.0);
358 ff_amf_write_field_name(&p, "videoFunction");
359 ff_amf_write_number(&p, 1.0);
362 ff_amf_write_field_name(&p, "pageUrl");
363 ff_amf_write_string(&p, rt->pageurl);
366 ff_amf_write_object_end(&p);
369 char *param = rt->conn;
371 // Write arbitrary AMF data to the Connect message.
372 while (param != NULL) {
374 param += strspn(param, " ");
377 sep = strchr(param, ' ');
380 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
381 // Invalid AMF parameter.
382 ff_rtmp_packet_destroy(&pkt);
393 pkt.size = p - pkt.data;
395 return rtmp_send_packet(rt, &pkt, 1);
398 static int read_connect(URLContext *s, RTMPContext *rt)
400 RTMPPacket pkt = { 0 };
410 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
411 rt->prev_pkt[0])) < 0)
414 bytestream2_init(&gbc, cp, pkt.size);
415 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
416 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
417 ff_rtmp_packet_destroy(&pkt);
418 return AVERROR_INVALIDDATA;
420 if (strcmp(command, "connect")) {
421 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
422 ff_rtmp_packet_destroy(&pkt);
423 return AVERROR_INVALIDDATA;
425 ret = ff_amf_read_number(&gbc, &seqnum);
427 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
428 /* Here one could parse an AMF Object with data as flashVers and others. */
429 ret = ff_amf_get_field_value(gbc.buffer,
430 gbc.buffer + bytestream2_get_bytes_left(&gbc),
431 "app", tmpstr, sizeof(tmpstr));
433 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
434 if (!ret && strcmp(tmpstr, rt->app))
435 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
437 ff_rtmp_packet_destroy(&pkt);
439 // Send Window Acknowledgement Size (as defined in speficication)
440 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
441 RTMP_PT_SERVER_BW, 0, 4)) < 0)
444 bytestream_put_be32(&p, rt->server_bw);
445 pkt.size = p - pkt.data;
446 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
448 ff_rtmp_packet_destroy(&pkt);
451 // Send Peer Bandwidth
452 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
453 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
456 bytestream_put_be32(&p, rt->server_bw);
457 bytestream_put_byte(&p, 2); // dynamic
458 pkt.size = p - pkt.data;
459 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
461 ff_rtmp_packet_destroy(&pkt);
466 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
467 RTMP_PT_PING, 0, 6)) < 0)
471 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
472 bytestream_put_be32(&p, 0);
473 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
475 ff_rtmp_packet_destroy(&pkt);
480 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
481 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
485 bytestream_put_be32(&p, rt->out_chunk_size);
486 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
488 ff_rtmp_packet_destroy(&pkt);
492 // Send result_ NetConnection.Connect.Success to connect
493 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
495 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
499 ff_amf_write_string(&p, "_result");
500 ff_amf_write_number(&p, seqnum);
502 ff_amf_write_object_start(&p);
503 ff_amf_write_field_name(&p, "fmsVer");
504 ff_amf_write_string(&p, "FMS/3,0,1,123");
505 ff_amf_write_field_name(&p, "capabilities");
506 ff_amf_write_number(&p, 31);
507 ff_amf_write_object_end(&p);
509 ff_amf_write_object_start(&p);
510 ff_amf_write_field_name(&p, "level");
511 ff_amf_write_string(&p, "status");
512 ff_amf_write_field_name(&p, "code");
513 ff_amf_write_string(&p, "NetConnection.Connect.Success");
514 ff_amf_write_field_name(&p, "description");
515 ff_amf_write_string(&p, "Connection succeeded.");
516 ff_amf_write_field_name(&p, "objectEncoding");
517 ff_amf_write_number(&p, 0);
518 ff_amf_write_object_end(&p);
520 pkt.size = p - pkt.data;
521 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
523 ff_rtmp_packet_destroy(&pkt);
527 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
528 RTMP_PT_INVOKE, 0, 30)) < 0)
531 ff_amf_write_string(&p, "onBWDone");
532 ff_amf_write_number(&p, 0);
533 ff_amf_write_null(&p);
534 ff_amf_write_number(&p, 8192);
535 pkt.size = p - pkt.data;
536 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
538 ff_rtmp_packet_destroy(&pkt);
544 * Generate 'releaseStream' call and send it to the server. It should make
545 * the server release some channel for media streams.
547 static int gen_release_stream(URLContext *s, RTMPContext *rt)
553 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
554 0, 29 + strlen(rt->playpath))) < 0)
557 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
559 ff_amf_write_string(&p, "releaseStream");
560 ff_amf_write_number(&p, ++rt->nb_invokes);
561 ff_amf_write_null(&p);
562 ff_amf_write_string(&p, rt->playpath);
564 return rtmp_send_packet(rt, &pkt, 1);
568 * Generate 'FCPublish' call and send it to the server. It should make
569 * the server preapare for receiving media streams.
571 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
577 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
578 0, 25 + strlen(rt->playpath))) < 0)
581 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
583 ff_amf_write_string(&p, "FCPublish");
584 ff_amf_write_number(&p, ++rt->nb_invokes);
585 ff_amf_write_null(&p);
586 ff_amf_write_string(&p, rt->playpath);
588 return rtmp_send_packet(rt, &pkt, 1);
592 * Generate 'FCUnpublish' call and send it to the server. It should make
593 * the server destroy stream.
595 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
601 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
602 0, 27 + strlen(rt->playpath))) < 0)
605 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
607 ff_amf_write_string(&p, "FCUnpublish");
608 ff_amf_write_number(&p, ++rt->nb_invokes);
609 ff_amf_write_null(&p);
610 ff_amf_write_string(&p, rt->playpath);
612 return rtmp_send_packet(rt, &pkt, 0);
616 * Generate 'createStream' call and send it to the server. It should make
617 * the server allocate some channel for media streams.
619 static int gen_create_stream(URLContext *s, RTMPContext *rt)
625 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
627 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
632 ff_amf_write_string(&p, "createStream");
633 ff_amf_write_number(&p, ++rt->nb_invokes);
634 ff_amf_write_null(&p);
636 return rtmp_send_packet(rt, &pkt, 1);
641 * Generate 'deleteStream' call and send it to the server. It should make
642 * the server remove some channel for media streams.
644 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
650 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
652 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
657 ff_amf_write_string(&p, "deleteStream");
658 ff_amf_write_number(&p, ++rt->nb_invokes);
659 ff_amf_write_null(&p);
660 ff_amf_write_number(&p, rt->stream_id);
662 return rtmp_send_packet(rt, &pkt, 0);
666 * Generate client buffer time and send it to the server.
668 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
674 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
679 bytestream_put_be16(&p, 3);
680 bytestream_put_be32(&p, rt->stream_id);
681 bytestream_put_be32(&p, rt->client_buffer_time);
683 return rtmp_send_packet(rt, &pkt, 0);
687 * Generate 'play' call and send it to the server, then ping the server
688 * to start actual playing.
690 static int gen_play(URLContext *s, RTMPContext *rt)
696 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
698 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
699 0, 29 + strlen(rt->playpath))) < 0)
702 pkt.extra = rt->stream_id;
705 ff_amf_write_string(&p, "play");
706 ff_amf_write_number(&p, ++rt->nb_invokes);
707 ff_amf_write_null(&p);
708 ff_amf_write_string(&p, rt->playpath);
709 ff_amf_write_number(&p, rt->live);
711 return rtmp_send_packet(rt, &pkt, 1);
714 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
720 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
723 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
726 pkt.extra = rt->stream_id;
729 ff_amf_write_string(&p, "seek");
730 ff_amf_write_number(&p, 0); //no tracking back responses
731 ff_amf_write_null(&p); //as usual, the first null param
732 ff_amf_write_number(&p, timestamp); //where we want to jump
734 return rtmp_send_packet(rt, &pkt, 1);
738 * Generate 'publish' call and send it to the server.
740 static int gen_publish(URLContext *s, RTMPContext *rt)
746 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
748 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
749 0, 30 + strlen(rt->playpath))) < 0)
752 pkt.extra = rt->stream_id;
755 ff_amf_write_string(&p, "publish");
756 ff_amf_write_number(&p, ++rt->nb_invokes);
757 ff_amf_write_null(&p);
758 ff_amf_write_string(&p, rt->playpath);
759 ff_amf_write_string(&p, "live");
761 return rtmp_send_packet(rt, &pkt, 1);
765 * Generate ping reply and send it to the server.
767 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
773 if (ppkt->size < 6) {
774 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
776 return AVERROR_INVALIDDATA;
779 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
780 ppkt->timestamp + 1, 6)) < 0)
784 bytestream_put_be16(&p, 7);
785 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
787 return rtmp_send_packet(rt, &pkt, 0);
791 * Generate SWF verification message and send it to the server.
793 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
799 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
800 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
805 bytestream_put_be16(&p, 27);
806 memcpy(p, rt->swfverification, 42);
808 return rtmp_send_packet(rt, &pkt, 0);
812 * Generate server bandwidth message and send it to the server.
814 static int gen_server_bw(URLContext *s, RTMPContext *rt)
820 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
825 bytestream_put_be32(&p, rt->server_bw);
827 return rtmp_send_packet(rt, &pkt, 0);
831 * Generate check bandwidth message and send it to the server.
833 static int gen_check_bw(URLContext *s, RTMPContext *rt)
839 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
844 ff_amf_write_string(&p, "_checkbw");
845 ff_amf_write_number(&p, ++rt->nb_invokes);
846 ff_amf_write_null(&p);
848 return rtmp_send_packet(rt, &pkt, 1);
852 * Generate report on bytes read so far and send it to the server.
854 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
860 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
865 bytestream_put_be32(&p, rt->bytes_read);
867 return rtmp_send_packet(rt, &pkt, 0);
870 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
871 const char *subscribe)
877 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
878 0, 27 + strlen(subscribe))) < 0)
882 ff_amf_write_string(&p, "FCSubscribe");
883 ff_amf_write_number(&p, ++rt->nb_invokes);
884 ff_amf_write_null(&p);
885 ff_amf_write_string(&p, subscribe);
887 return rtmp_send_packet(rt, &pkt, 1);
890 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
891 const uint8_t *key, int keylen, uint8_t *dst)
894 uint8_t hmac_buf[64+32] = {0};
897 sha = av_sha_alloc();
899 return AVERROR(ENOMEM);
902 memcpy(hmac_buf, key, keylen);
904 av_sha_init(sha, 256);
905 av_sha_update(sha,key, keylen);
906 av_sha_final(sha, hmac_buf);
908 for (i = 0; i < 64; i++)
909 hmac_buf[i] ^= HMAC_IPAD_VAL;
911 av_sha_init(sha, 256);
912 av_sha_update(sha, hmac_buf, 64);
914 av_sha_update(sha, src, len);
915 } else { //skip 32 bytes used for storing digest
916 av_sha_update(sha, src, gap);
917 av_sha_update(sha, src + gap + 32, len - gap - 32);
919 av_sha_final(sha, hmac_buf + 64);
921 for (i = 0; i < 64; i++)
922 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
923 av_sha_init(sha, 256);
924 av_sha_update(sha, hmac_buf, 64+32);
925 av_sha_final(sha, dst);
932 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
935 int i, digest_pos = 0;
937 for (i = 0; i < 4; i++)
938 digest_pos += buf[i + off];
939 digest_pos = digest_pos % mod_val + add_val;
945 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
946 * will be stored) into that packet.
948 * @param buf handshake data (1536 bytes)
949 * @param encrypted use an encrypted connection (RTMPE)
950 * @return offset to the digest inside input data
952 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
957 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
959 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
961 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
962 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
971 * Verify that the received server response has the expected digest value.
973 * @param buf handshake data received from the server (1536 bytes)
974 * @param off position to search digest offset from
975 * @return 0 if digest is valid, digest position otherwise
977 static int rtmp_validate_digest(uint8_t *buf, int off)
982 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
984 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
985 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
990 if (!memcmp(digest, buf + digest_pos, 32))
995 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1001 if (rt->swfhash_len != 32) {
1002 av_log(s, AV_LOG_ERROR,
1003 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1004 return AVERROR(EINVAL);
1007 p = &rt->swfverification[0];
1008 bytestream_put_byte(&p, 1);
1009 bytestream_put_byte(&p, 1);
1010 bytestream_put_be32(&p, rt->swfsize);
1011 bytestream_put_be32(&p, rt->swfsize);
1013 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1020 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1021 uint8_t **out_data, int64_t *out_size)
1023 z_stream zs = { 0 };
1028 zs.avail_in = in_size;
1029 zs.next_in = in_data;
1030 ret = inflateInit(&zs);
1032 return AVERROR_UNKNOWN;
1035 uint8_t tmp_buf[16384];
1037 zs.avail_out = sizeof(tmp_buf);
1038 zs.next_out = tmp_buf;
1040 ret = inflate(&zs, Z_NO_FLUSH);
1041 if (ret != Z_OK && ret != Z_STREAM_END) {
1042 ret = AVERROR_UNKNOWN;
1046 size = sizeof(tmp_buf) - zs.avail_out;
1047 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1048 ret = AVERROR(ENOMEM);
1053 memcpy(*out_data + *out_size, tmp_buf, size);
1055 } while (zs.avail_out == 0);
1063 static int rtmp_calc_swfhash(URLContext *s)
1065 RTMPContext *rt = s->priv_data;
1066 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1067 int64_t in_size, out_size;
1073 /* Get the SWF player file. */
1074 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1075 &s->interrupt_callback, NULL)) < 0) {
1076 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1080 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1085 if (!(in_data = av_malloc(in_size))) {
1086 ret = AVERROR(ENOMEM);
1090 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1094 ret = AVERROR_INVALIDDATA;
1098 if (!memcmp(in_data, "CWS", 3)) {
1099 /* Decompress the SWF player file using Zlib. */
1100 if (!(out_data = av_malloc(8))) {
1101 ret = AVERROR(ENOMEM);
1104 *in_data = 'F'; // magic stuff
1105 memcpy(out_data, in_data, 8);
1109 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1110 &out_data, &out_size)) < 0)
1113 av_log(s, AV_LOG_ERROR,
1114 "Zlib is required for decompressing the SWF player file.\n");
1115 ret = AVERROR(EINVAL);
1125 /* Compute the SHA256 hash of the SWF player file. */
1126 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1127 "Genuine Adobe Flash Player 001", 30,
1131 /* Set SWFVerification parameters. */
1132 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1133 rt->swfsize = swfsize;
1137 av_freep(&out_data);
1138 ffurl_close(stream);
1143 * Perform handshake with the server by means of exchanging pseudorandom data
1144 * signed with HMAC-SHA2 digest.
1146 * @return 0 if handshake succeeds, negative value otherwise
1148 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1151 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1152 3, // unencrypted data
1153 0, 0, 0, 0, // client uptime
1159 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1160 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1162 int server_pos, client_pos;
1163 uint8_t digest[32], signature[32];
1166 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1168 av_lfg_init(&rnd, 0xDEADC0DE);
1169 // generate handshake packet - 1536 bytes of pseudorandom data
1170 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1171 tosend[i] = av_lfg_get(&rnd) >> 24;
1173 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1174 /* When the client wants to use RTMPE, we have to change the command
1175 * byte to 0x06 which means to use encrypted data and we have to set
1176 * the flash version to at least 9.0.115.0. */
1183 /* Initialize the Diffie-Hellmann context and generate the public key
1184 * to send to the server. */
1185 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1189 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1193 if ((ret = ffurl_write(rt->stream, tosend,
1194 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1195 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1199 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1200 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1201 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1205 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1206 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1207 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1211 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1212 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1213 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1215 if (rt->is_input && serverdata[5] >= 3) {
1216 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1222 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1227 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1228 return AVERROR(EIO);
1232 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1233 * key are the last 32 bytes of the server handshake. */
1235 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1236 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1240 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1241 rtmp_server_key, sizeof(rtmp_server_key),
1246 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1247 0, digest, 32, signature);
1251 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1252 /* Compute the shared secret key sent by the server and initialize
1253 * the RC4 encryption. */
1254 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1255 tosend + 1, type)) < 0)
1258 /* Encrypt the signature received by the server. */
1259 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1262 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1263 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1264 return AVERROR(EIO);
1267 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1268 tosend[i] = av_lfg_get(&rnd) >> 24;
1269 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1270 rtmp_player_key, sizeof(rtmp_player_key),
1275 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1277 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1281 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1282 /* Encrypt the signature to be send to the server. */
1283 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1284 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1288 // write reply back to the server
1289 if ((ret = ffurl_write(rt->stream, tosend,
1290 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1293 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1294 /* Set RC4 keys for encryption and update the keystreams. */
1295 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1299 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1300 /* Compute the shared secret key sent by the server and initialize
1301 * the RC4 encryption. */
1302 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1303 tosend + 1, 1)) < 0)
1306 if (serverdata[0] == 9) {
1307 /* Encrypt the signature received by the server. */
1308 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1313 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1314 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1317 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1318 /* Set RC4 keys for encryption and update the keystreams. */
1319 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1327 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1328 uint32_t *second_int, char *arraydata,
1333 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1334 RTMP_HANDSHAKE_PACKET_SIZE);
1336 return AVERROR(EIO);
1337 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1338 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1339 " not following standard\n", (int)inoutsize);
1340 return AVERROR(EINVAL);
1343 *first_int = AV_RB32(arraydata);
1344 *second_int = AV_RB32(arraydata + 4);
1348 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1349 uint32_t second_int, char *arraydata, int size)
1353 AV_WB32(arraydata, first_int);
1354 AV_WB32(arraydata + 4, second_int);
1355 inoutsize = ffurl_write(rt->stream, arraydata,
1356 RTMP_HANDSHAKE_PACKET_SIZE);
1357 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1358 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1359 return AVERROR(EIO);
1366 * rtmp handshake server side
1368 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1370 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1372 uint32_t hs_my_epoch;
1373 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1374 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1381 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1382 if (inoutsize <= 0) {
1383 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1384 return AVERROR(EIO);
1387 if (buffer[0] != 3) {
1388 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1389 return AVERROR(EIO);
1391 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1392 av_log(s, AV_LOG_ERROR,
1393 "Unable to write answer - RTMP S0\n");
1394 return AVERROR(EIO);
1397 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1398 RTMP_HANDSHAKE_PACKET_SIZE);
1400 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1404 /* By now same epoch will be sent */
1405 hs_my_epoch = hs_epoch;
1406 /* Generate random */
1407 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1409 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1411 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1412 RTMP_HANDSHAKE_PACKET_SIZE);
1414 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1418 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1419 RTMP_HANDSHAKE_PACKET_SIZE);
1421 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1425 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1426 RTMP_HANDSHAKE_PACKET_SIZE);
1428 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1431 if (temp != hs_my_epoch)
1432 av_log(s, AV_LOG_WARNING,
1433 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1434 if (memcmp(buffer + 8, hs_s1 + 8,
1435 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1436 av_log(s, AV_LOG_WARNING,
1437 "Erroneous C2 Message random does not match up\n");
1442 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1444 RTMPContext *rt = s->priv_data;
1447 if (pkt->size < 4) {
1448 av_log(s, AV_LOG_ERROR,
1449 "Too short chunk size change packet (%d)\n",
1451 return AVERROR_INVALIDDATA;
1454 if (!rt->is_input) {
1455 /* Send the same chunk size change packet back to the server,
1456 * setting the outgoing chunk size to the same as the incoming one. */
1457 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1458 rt->prev_pkt[1])) < 0)
1460 rt->out_chunk_size = AV_RB32(pkt->data);
1463 rt->in_chunk_size = AV_RB32(pkt->data);
1464 if (rt->in_chunk_size <= 0) {
1465 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1467 return AVERROR_INVALIDDATA;
1469 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1475 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1477 RTMPContext *rt = s->priv_data;
1480 if (pkt->size < 2) {
1481 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1483 return AVERROR_INVALIDDATA;
1486 t = AV_RB16(pkt->data);
1488 if ((ret = gen_pong(s, rt, pkt)) < 0)
1490 } else if (t == 26) {
1492 if ((ret = gen_swf_verification(s, rt)) < 0)
1495 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1502 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1504 RTMPContext *rt = s->priv_data;
1506 if (pkt->size < 4) {
1507 av_log(s, AV_LOG_ERROR,
1508 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1510 return AVERROR_INVALIDDATA;
1513 rt->client_report_size = AV_RB32(pkt->data);
1514 if (rt->client_report_size <= 0) {
1515 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1516 rt->client_report_size);
1517 return AVERROR_INVALIDDATA;
1520 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1521 rt->client_report_size >>= 1;
1526 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1528 RTMPContext *rt = s->priv_data;
1530 if (pkt->size < 4) {
1531 av_log(s, AV_LOG_ERROR,
1532 "Too short server bandwidth report packet (%d)\n",
1534 return AVERROR_INVALIDDATA;
1537 rt->server_bw = AV_RB32(pkt->data);
1538 if (rt->server_bw <= 0) {
1539 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1541 return AVERROR_INVALIDDATA;
1543 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1548 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1549 const char *opaque, const char *challenge)
1552 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1553 struct AVMD5 *md5 = av_md5_alloc();
1555 return AVERROR(ENOMEM);
1557 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1560 av_md5_update(md5, user, strlen(user));
1561 av_md5_update(md5, salt, strlen(salt));
1562 av_md5_update(md5, rt->password, strlen(rt->password));
1563 av_md5_final(md5, hash);
1564 av_base64_encode(hashstr, sizeof(hashstr), hash,
1567 av_md5_update(md5, hashstr, strlen(hashstr));
1569 av_md5_update(md5, opaque, strlen(opaque));
1571 av_md5_update(md5, challenge, strlen(challenge));
1572 av_md5_update(md5, challenge2, strlen(challenge2));
1573 av_md5_final(md5, hash);
1574 av_base64_encode(hashstr, sizeof(hashstr), hash,
1576 snprintf(rt->auth_params, sizeof(rt->auth_params),
1577 "?authmod=%s&user=%s&challenge=%s&response=%s",
1578 "adobe", user, challenge2, hashstr);
1580 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1581 "&opaque=%s", opaque);
1587 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1590 char hashstr1[33], hashstr2[33];
1591 const char *realm = "live";
1592 const char *method = "publish";
1593 const char *qop = "auth";
1594 const char *nc = "00000001";
1596 struct AVMD5 *md5 = av_md5_alloc();
1598 return AVERROR(ENOMEM);
1600 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1603 av_md5_update(md5, user, strlen(user));
1604 av_md5_update(md5, ":", 1);
1605 av_md5_update(md5, realm, strlen(realm));
1606 av_md5_update(md5, ":", 1);
1607 av_md5_update(md5, rt->password, strlen(rt->password));
1608 av_md5_final(md5, hash);
1609 ff_data_to_hex(hashstr1, hash, 16, 1);
1610 hashstr1[32] = '\0';
1613 av_md5_update(md5, method, strlen(method));
1614 av_md5_update(md5, ":/", 2);
1615 av_md5_update(md5, rt->app, strlen(rt->app));
1616 if (!strchr(rt->app, '/'))
1617 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1618 av_md5_final(md5, hash);
1619 ff_data_to_hex(hashstr2, hash, 16, 1);
1620 hashstr2[32] = '\0';
1623 av_md5_update(md5, hashstr1, strlen(hashstr1));
1624 av_md5_update(md5, ":", 1);
1626 av_md5_update(md5, nonce, strlen(nonce));
1627 av_md5_update(md5, ":", 1);
1628 av_md5_update(md5, nc, strlen(nc));
1629 av_md5_update(md5, ":", 1);
1630 av_md5_update(md5, cnonce, strlen(cnonce));
1631 av_md5_update(md5, ":", 1);
1632 av_md5_update(md5, qop, strlen(qop));
1633 av_md5_update(md5, ":", 1);
1634 av_md5_update(md5, hashstr2, strlen(hashstr2));
1635 av_md5_final(md5, hash);
1636 ff_data_to_hex(hashstr1, hash, 16, 1);
1638 snprintf(rt->auth_params, sizeof(rt->auth_params),
1639 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1640 "llnw", user, nonce, cnonce, nc, hashstr1);
1646 static int handle_connect_error(URLContext *s, const char *desc)
1648 RTMPContext *rt = s->priv_data;
1649 char buf[300], *ptr, authmod[15];
1651 const char *user = "", *salt = "", *opaque = NULL,
1652 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1654 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1655 !(cptr = strstr(desc, "authmod=llnw"))) {
1656 av_log(s, AV_LOG_ERROR,
1657 "Unknown connect error (unsupported authentication method?)\n");
1658 return AVERROR_UNKNOWN;
1660 cptr += strlen("authmod=");
1661 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1662 authmod[i++] = *cptr++;
1665 if (!rt->username[0] || !rt->password[0]) {
1666 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1667 return AVERROR_UNKNOWN;
1670 if (strstr(desc, "?reason=authfailed")) {
1671 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1672 return AVERROR_UNKNOWN;
1673 } else if (strstr(desc, "?reason=nosuchuser")) {
1674 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1675 return AVERROR_UNKNOWN;
1678 if (rt->auth_tried) {
1679 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1680 return AVERROR_UNKNOWN;
1683 rt->auth_params[0] = '\0';
1685 if (strstr(desc, "code=403 need auth")) {
1686 snprintf(rt->auth_params, sizeof(rt->auth_params),
1687 "?authmod=%s&user=%s", authmod, rt->username);
1691 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1692 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1693 return AVERROR_UNKNOWN;
1696 av_strlcpy(buf, cptr + 1, sizeof(buf));
1700 char *next = strchr(ptr, '&');
1701 char *value = strchr(ptr, '=');
1706 if (!strcmp(ptr, "user")) {
1708 } else if (!strcmp(ptr, "salt")) {
1710 } else if (!strcmp(ptr, "opaque")) {
1712 } else if (!strcmp(ptr, "challenge")) {
1714 } else if (!strcmp(ptr, "nonce")) {
1720 if (!strcmp(authmod, "adobe")) {
1721 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1724 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1732 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1734 RTMPContext *rt = s->priv_data;
1735 const uint8_t *data_end = pkt->data + pkt->size;
1736 char *tracked_method = NULL;
1737 int level = AV_LOG_ERROR;
1738 uint8_t tmpstr[256];
1741 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1744 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1745 "description", tmpstr, sizeof(tmpstr))) {
1746 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1747 !strcmp(tracked_method, "releaseStream") ||
1748 !strcmp(tracked_method, "FCSubscribe") ||
1749 !strcmp(tracked_method, "FCPublish"))) {
1750 /* Gracefully ignore Adobe-specific historical artifact errors. */
1751 level = AV_LOG_WARNING;
1753 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1754 ret = handle_connect_error(s, tmpstr);
1756 rt->do_reconnect = 1;
1757 level = AV_LOG_VERBOSE;
1760 ret = AVERROR_UNKNOWN;
1761 av_log(s, level, "Server error: %s\n", tmpstr);
1764 av_free(tracked_method);
1768 static int write_begin(URLContext *s)
1770 RTMPContext *rt = s->priv_data;
1772 RTMPPacket spkt = { 0 };
1775 // Send Stream Begin 1
1776 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1777 RTMP_PT_PING, 0, 6)) < 0) {
1778 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1782 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1783 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1784 bytestream2_put_be32(&pbc, rt->nb_streamid);
1786 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1789 ff_rtmp_packet_destroy(&spkt);
1794 static int write_status(URLContext *s, RTMPPacket *pkt,
1795 const char *status, const char *filename)
1797 RTMPContext *rt = s->priv_data;
1798 RTMPPacket spkt = { 0 };
1799 char statusmsg[128];
1803 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1805 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1806 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1811 spkt.extra = pkt->extra;
1812 ff_amf_write_string(&pp, "onStatus");
1813 ff_amf_write_number(&pp, 0);
1814 ff_amf_write_null(&pp);
1816 ff_amf_write_object_start(&pp);
1817 ff_amf_write_field_name(&pp, "level");
1818 ff_amf_write_string(&pp, "status");
1819 ff_amf_write_field_name(&pp, "code");
1820 ff_amf_write_string(&pp, status);
1821 ff_amf_write_field_name(&pp, "description");
1822 snprintf(statusmsg, sizeof(statusmsg),
1823 "%s is now published", filename);
1824 ff_amf_write_string(&pp, statusmsg);
1825 ff_amf_write_field_name(&pp, "details");
1826 ff_amf_write_string(&pp, filename);
1827 ff_amf_write_field_name(&pp, "clientid");
1828 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1829 ff_amf_write_string(&pp, statusmsg);
1830 ff_amf_write_object_end(&pp);
1832 spkt.size = pp - spkt.data;
1833 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1835 ff_rtmp_packet_destroy(&spkt);
1840 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1842 RTMPContext *rt = s->priv_data;
1848 const uint8_t *p = pkt->data;
1850 RTMPPacket spkt = { 0 };
1854 bytestream2_init(&gbc, p, pkt->size);
1855 if (ff_amf_read_string(&gbc, command, sizeof(command),
1857 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1858 return AVERROR_INVALIDDATA;
1861 ret = ff_amf_read_number(&gbc, &seqnum);
1864 ret = ff_amf_read_null(&gbc);
1867 if (!strcmp(command, "FCPublish") ||
1868 !strcmp(command, "publish")) {
1869 ret = ff_amf_read_string(&gbc, filename,
1870 sizeof(filename), &stringlen);
1873 pchar = strrchr(s->filename, '/');
1875 av_log(s, AV_LOG_WARNING,
1876 "Unable to find / in url %s, bad format\n",
1878 pchar = s->filename;
1881 if (strcmp(pchar, filename))
1882 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1883 " %s\n", filename, pchar);
1885 rt->state = STATE_RECEIVING;
1888 if (!strcmp(command, "FCPublish")) {
1889 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1891 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1892 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1896 ff_amf_write_string(&pp, "onFCPublish");
1897 } else if (!strcmp(command, "publish")) {
1898 ret = write_begin(s);
1902 // Send onStatus(NetStream.Publish.Start)
1903 return write_status(s, pkt, "NetStream.Publish.Start",
1905 } else if (!strcmp(command, "play")) {
1906 ret = write_begin(s);
1909 rt->state = STATE_SENDING;
1910 return write_status(s, pkt, "NetStream.Play.Start",
1913 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1915 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1916 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1920 ff_amf_write_string(&pp, "_result");
1921 ff_amf_write_number(&pp, seqnum);
1922 ff_amf_write_null(&pp);
1923 if (!strcmp(command, "createStream")) {
1925 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1926 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1927 ff_amf_write_number(&pp, rt->nb_streamid);
1928 /* By now we don't control which streams are removed in
1929 * deleteStream. There is no stream creation control
1930 * if a client creates more than 2^32 - 2 streams. */
1933 spkt.size = pp - spkt.data;
1934 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1936 ff_rtmp_packet_destroy(&spkt);
1940 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1942 RTMPContext *rt = s->priv_data;
1943 char *tracked_method = NULL;
1946 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1949 if (!tracked_method) {
1950 /* Ignore this reply when the current method is not tracked. */
1954 if (!strcmp(tracked_method, "connect")) {
1955 if (!rt->is_input) {
1956 if ((ret = gen_release_stream(s, rt)) < 0)
1959 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1962 if ((ret = gen_server_bw(s, rt)) < 0)
1966 if ((ret = gen_create_stream(s, rt)) < 0)
1970 /* Send the FCSubscribe command when the name of live
1971 * stream is defined by the user or if it's a live stream. */
1972 if (rt->subscribe) {
1973 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1975 } else if (rt->live == -1) {
1976 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1980 } else if (!strcmp(tracked_method, "createStream")) {
1981 //extract a number from the result
1982 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1983 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1985 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1988 if (!rt->is_input) {
1989 if ((ret = gen_publish(s, rt)) < 0)
1992 if ((ret = gen_play(s, rt)) < 0)
1994 if ((ret = gen_buffer_time(s, rt)) < 0)
2000 av_free(tracked_method);
2004 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2006 RTMPContext *rt = s->priv_data;
2007 const uint8_t *data_end = pkt->data + pkt->size;
2008 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2009 uint8_t tmpstr[256];
2012 for (i = 0; i < 2; i++) {
2013 t = ff_amf_tag_size(ptr, data_end);
2019 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2020 if (!t && !strcmp(tmpstr, "error")) {
2021 if (!ff_amf_get_field_value(ptr, data_end,
2022 "description", tmpstr, sizeof(tmpstr)))
2023 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2027 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2028 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2029 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2030 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2031 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2032 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2037 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2039 RTMPContext *rt = s->priv_data;
2042 //TODO: check for the messages sent for wrong state?
2043 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2044 if ((ret = handle_invoke_error(s, pkt)) < 0)
2046 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2047 if ((ret = handle_invoke_result(s, pkt)) < 0)
2049 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2050 if ((ret = handle_invoke_status(s, pkt)) < 0)
2052 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2053 if ((ret = gen_check_bw(s, rt)) < 0)
2055 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2056 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2057 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2058 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2059 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2060 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2061 if ((ret = send_invoke_response(s, pkt)) < 0)
2068 static int update_offset(RTMPContext *rt, int size)
2072 // generate packet header and put data into buffer for FLV demuxer
2073 if (rt->flv_off < rt->flv_size) {
2074 // There is old unread data in the buffer, thus append at the end
2075 old_flv_size = rt->flv_size;
2076 rt->flv_size += size + 15;
2078 // All data has been read, write the new data at the start of the buffer
2080 rt->flv_size = size + 15;
2084 return old_flv_size;
2087 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2089 int old_flv_size, ret;
2091 const uint8_t *data = pkt->data + skip;
2092 const int size = pkt->size - skip;
2093 uint32_t ts = pkt->timestamp;
2095 old_flv_size = update_offset(rt, size);
2097 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2099 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2100 bytestream2_skip_p(&pbc, old_flv_size);
2101 bytestream2_put_byte(&pbc, pkt->type);
2102 bytestream2_put_be24(&pbc, size);
2103 bytestream2_put_be24(&pbc, ts);
2104 bytestream2_put_byte(&pbc, ts >> 24);
2105 bytestream2_put_be24(&pbc, 0);
2106 bytestream2_put_buffer(&pbc, data, size);
2107 bytestream2_put_be32(&pbc, 0);
2112 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2114 RTMPContext *rt = s->priv_data;
2115 uint8_t commandbuffer[64];
2116 char statusmsg[128];
2117 int stringlen, ret, skip = 0;
2120 bytestream2_init(&gbc, pkt->data, pkt->size);
2121 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2123 return AVERROR_INVALIDDATA;
2125 // Skip the @setDataFrame string and validate it is a notification
2126 if (!strcmp(commandbuffer, "@setDataFrame")) {
2127 skip = gbc.buffer - pkt->data;
2128 ret = ff_amf_read_string(&gbc, statusmsg,
2129 sizeof(statusmsg), &stringlen);
2131 return AVERROR_INVALIDDATA;
2134 return append_flv_data(rt, pkt, skip);
2138 * Parse received packet and possibly perform some action depending on
2139 * the packet contents.
2140 * @return 0 for no errors, negative values for serious errors which prevent
2141 * further communications, positive values for uncritical errors
2143 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2148 ff_rtmp_packet_dump(s, pkt);
2151 switch (pkt->type) {
2152 case RTMP_PT_BYTES_READ:
2153 av_dlog(s, "received bytes read report\n");
2155 case RTMP_PT_CHUNK_SIZE:
2156 if ((ret = handle_chunk_size(s, pkt)) < 0)
2160 if ((ret = handle_ping(s, pkt)) < 0)
2163 case RTMP_PT_CLIENT_BW:
2164 if ((ret = handle_client_bw(s, pkt)) < 0)
2167 case RTMP_PT_SERVER_BW:
2168 if ((ret = handle_server_bw(s, pkt)) < 0)
2171 case RTMP_PT_INVOKE:
2172 if ((ret = handle_invoke(s, pkt)) < 0)
2177 case RTMP_PT_METADATA:
2178 case RTMP_PT_NOTIFY:
2179 /* Audio, Video and Metadata packets are parsed in get_packet() */
2182 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2188 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2190 int ret, old_flv_size, type;
2191 const uint8_t *next;
2194 uint32_t ts, cts, pts = 0;
2196 old_flv_size = update_offset(rt, pkt->size);
2198 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2202 p = rt->flv_data + old_flv_size;
2204 /* copy data while rewriting timestamps */
2205 ts = pkt->timestamp;
2207 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2208 type = bytestream_get_byte(&next);
2209 size = bytestream_get_be24(&next);
2210 cts = bytestream_get_be24(&next);
2211 cts |= bytestream_get_byte(&next) << 24;
2216 bytestream_put_byte(&p, type);
2217 bytestream_put_be24(&p, size);
2218 bytestream_put_be24(&p, ts);
2219 bytestream_put_byte(&p, ts >> 24);
2220 memcpy(p, next, size + 3 + 4);
2221 next += size + 3 + 4;
2224 memcpy(p, next, RTMP_HEADER);
2230 * Interact with the server by receiving and sending RTMP packets until
2231 * there is some significant data (media data or expected status notification).
2233 * @param s reading context
2234 * @param for_header non-zero value tells function to work until it
2235 * gets notification from the server that playing has been started,
2236 * otherwise function will work until some media data is received (or
2238 * @return 0 for successful operation, negative value in case of error
2240 static int get_packet(URLContext *s, int for_header)
2242 RTMPContext *rt = s->priv_data;
2245 if (rt->state == STATE_STOPPED)
2249 RTMPPacket rpkt = { 0 };
2250 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2251 rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2253 return AVERROR(EAGAIN);
2255 return AVERROR(EIO);
2258 rt->bytes_read += ret;
2259 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2260 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2261 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2263 rt->last_bytes_read = rt->bytes_read;
2266 ret = rtmp_parse_result(s, rt, &rpkt);
2268 // At this point we must check if we are in the seek state and continue
2269 // with the next packet. handle_invoke will get us out of this state
2270 // when the right message is encountered
2271 if (rt->state == STATE_SEEKING) {
2272 ff_rtmp_packet_destroy(&rpkt);
2273 // We continue, let the natural flow of things happen:
2274 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2278 if (ret < 0) {//serious error in current packet
2279 ff_rtmp_packet_destroy(&rpkt);
2282 if (rt->do_reconnect && for_header) {
2283 ff_rtmp_packet_destroy(&rpkt);
2286 if (rt->state == STATE_STOPPED) {
2287 ff_rtmp_packet_destroy(&rpkt);
2290 if (for_header && (rt->state == STATE_PLAYING ||
2291 rt->state == STATE_PUBLISHING ||
2292 rt->state == STATE_SENDING ||
2293 rt->state == STATE_RECEIVING)) {
2294 ff_rtmp_packet_destroy(&rpkt);
2297 if (!rpkt.size || !rt->is_input) {
2298 ff_rtmp_packet_destroy(&rpkt);
2301 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2302 ret = append_flv_data(rt, &rpkt, 0);
2303 ff_rtmp_packet_destroy(&rpkt);
2305 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2306 ret = handle_notify(s, &rpkt);
2307 ff_rtmp_packet_destroy(&rpkt);
2309 } else if (rpkt.type == RTMP_PT_METADATA) {
2310 ret = handle_metadata(rt, &rpkt);
2311 ff_rtmp_packet_destroy(&rpkt);
2314 ff_rtmp_packet_destroy(&rpkt);
2318 static int rtmp_close(URLContext *h)
2320 RTMPContext *rt = h->priv_data;
2323 if (!rt->is_input) {
2324 rt->flv_data = NULL;
2325 if (rt->out_pkt.size)
2326 ff_rtmp_packet_destroy(&rt->out_pkt);
2327 if (rt->state > STATE_FCPUBLISH)
2328 ret = gen_fcunpublish_stream(h, rt);
2330 if (rt->state > STATE_HANDSHAKED)
2331 ret = gen_delete_stream(h, rt);
2332 for (i = 0; i < 2; i++)
2333 for (j = 0; j < RTMP_CHANNELS; j++)
2334 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2336 free_tracked_methods(rt);
2337 av_freep(&rt->flv_data);
2338 ffurl_close(rt->stream);
2343 * Open RTMP connection and verify that the stream can be played.
2345 * URL syntax: rtmp://server[:port][/app][/playpath]
2346 * where 'app' is first one or two directories in the path
2347 * (e.g. /ondemand/, /flash/live/, etc.)
2348 * and 'playpath' is a file name (the rest of the path,
2349 * may be prefixed with "mp4:")
2351 static int rtmp_open(URLContext *s, const char *uri, int flags)
2353 RTMPContext *rt = s->priv_data;
2354 char proto[8], hostname[256], path[1024], auth[100], *fname;
2358 AVDictionary *opts = NULL;
2361 if (rt->listen_timeout > 0)
2364 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2366 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2367 hostname, sizeof(hostname), &port,
2368 path, sizeof(path), s->filename);
2370 if (strchr(path, ' ')) {
2371 av_log(s, AV_LOG_WARNING,
2372 "Detected librtmp style URL parameters, these aren't supported "
2373 "by the libavformat internal RTMP handler currently enabled. "
2374 "See the documentation for the correct way to pass parameters.\n");
2378 char *ptr = strchr(auth, ':');
2381 av_strlcpy(rt->username, auth, sizeof(rt->username));
2382 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2386 if (rt->listen && strcmp(proto, "rtmp")) {
2387 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2389 return AVERROR(EINVAL);
2391 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2392 if (!strcmp(proto, "rtmpts"))
2393 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2395 /* open the http tunneling connection */
2396 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2397 } else if (!strcmp(proto, "rtmps")) {
2398 /* open the tls connection */
2400 port = RTMPS_DEFAULT_PORT;
2401 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2402 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2403 if (!strcmp(proto, "rtmpte"))
2404 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2406 /* open the encrypted connection */
2407 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2410 /* open the tcp connection */
2412 port = RTMP_DEFAULT_PORT;
2414 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2415 "?listen&listen_timeout=%d",
2416 rt->listen_timeout * 1000);
2418 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2422 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2423 &s->interrupt_callback, &opts)) < 0) {
2424 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2428 if (rt->swfverify) {
2429 if ((ret = rtmp_calc_swfhash(s)) < 0)
2433 rt->state = STATE_START;
2434 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2436 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2439 rt->out_chunk_size = 128;
2440 rt->in_chunk_size = 128; // Probably overwritten later
2441 rt->state = STATE_HANDSHAKED;
2443 // Keep the application name when it has been defined by the user.
2446 rt->app = av_malloc(APP_MAX_LENGTH);
2448 ret = AVERROR(ENOMEM);
2452 //extract "app" part from path
2453 if (!strncmp(path, "/ondemand/", 10)) {
2455 memcpy(rt->app, "ondemand", 9);
2457 char *next = *path ? path + 1 : path;
2458 char *p = strchr(next, '/');
2463 // make sure we do not mismatch a playpath for an application instance
2464 char *c = strchr(p + 1, ':');
2465 fname = strchr(p + 1, '/');
2466 if (!fname || (c && c < fname)) {
2468 av_strlcpy(rt->app, path + 1, p - path);
2471 av_strlcpy(rt->app, path + 1, fname - path - 1);
2477 // The name of application has been defined by the user, override it.
2482 if (!rt->playpath) {
2483 int len = strlen(fname);
2485 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2486 if (!rt->playpath) {
2487 ret = AVERROR(ENOMEM);
2491 if (!strchr(fname, ':') && len >= 4 &&
2492 (!strcmp(fname + len - 4, ".f4v") ||
2493 !strcmp(fname + len - 4, ".mp4"))) {
2494 memcpy(rt->playpath, "mp4:", 5);
2495 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2496 fname[len - 4] = '\0';
2498 rt->playpath[0] = 0;
2500 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2504 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2506 ret = AVERROR(ENOMEM);
2509 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2510 port, "/%s", rt->app);
2513 if (!rt->flashver) {
2514 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2515 if (!rt->flashver) {
2516 ret = AVERROR(ENOMEM);
2520 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2521 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2522 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2524 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2525 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2529 rt->client_report_size = 1048576;
2531 rt->last_bytes_read = 0;
2532 rt->server_bw = 2500000;
2534 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2535 proto, path, rt->app, rt->playpath);
2537 if ((ret = gen_connect(s, rt)) < 0)
2540 if (read_connect(s, s->priv_data) < 0)
2545 ret = get_packet(s, 1);
2546 } while (ret == AVERROR(EAGAIN));
2550 if (rt->do_reconnect) {
2551 ffurl_close(rt->stream);
2553 rt->do_reconnect = 0;
2555 memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2556 free_tracked_methods(rt);
2562 // generate FLV header for demuxer
2564 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2567 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2570 rt->flv_data = NULL;
2572 rt->skip_bytes = 13;
2575 s->max_packet_size = rt->stream->max_packet_size;
2580 av_dict_free(&opts);
2585 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2587 RTMPContext *rt = s->priv_data;
2588 int orig_size = size;
2592 int data_left = rt->flv_size - rt->flv_off;
2594 if (data_left >= size) {
2595 memcpy(buf, rt->flv_data + rt->flv_off, size);
2596 rt->flv_off += size;
2599 if (data_left > 0) {
2600 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2603 rt->flv_off = rt->flv_size;
2606 if ((ret = get_packet(s, 0)) < 0)
2612 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2615 RTMPContext *rt = s->priv_data;
2617 av_log(s, AV_LOG_DEBUG,
2618 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2619 stream_index, timestamp, flags);
2620 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2621 av_log(s, AV_LOG_ERROR,
2622 "Unable to send seek command on stream index %d at timestamp "
2623 "%"PRId64" with flags %08x\n",
2624 stream_index, timestamp, flags);
2627 rt->flv_off = rt->flv_size;
2628 rt->state = STATE_SEEKING;
2632 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2634 RTMPContext *rt = s->priv_data;
2635 int size_temp = size;
2636 int pktsize, pkttype;
2638 const uint8_t *buf_temp = buf;
2643 if (rt->skip_bytes) {
2644 int skip = FFMIN(rt->skip_bytes, size_temp);
2647 rt->skip_bytes -= skip;
2651 if (rt->flv_header_bytes < RTMP_HEADER) {
2652 const uint8_t *header = rt->flv_header;
2653 int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2654 int channel = RTMP_AUDIO_CHANNEL;
2655 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2656 rt->flv_header_bytes += copy;
2658 if (rt->flv_header_bytes < RTMP_HEADER)
2661 pkttype = bytestream_get_byte(&header);
2662 pktsize = bytestream_get_be24(&header);
2663 ts = bytestream_get_be24(&header);
2664 ts |= bytestream_get_byte(&header) << 24;
2665 bytestream_get_be24(&header);
2666 rt->flv_size = pktsize;
2668 if (pkttype == RTMP_PT_VIDEO)
2669 channel = RTMP_VIDEO_CHANNEL;
2671 //force 12bytes header
2672 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2673 pkttype == RTMP_PT_NOTIFY) {
2674 if (pkttype == RTMP_PT_NOTIFY)
2676 rt->prev_pkt[1][channel].channel_id = 0;
2679 //this can be a big packet, it's better to send it right here
2680 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2681 pkttype, ts, pktsize)) < 0)
2684 rt->out_pkt.extra = rt->stream_id;
2685 rt->flv_data = rt->out_pkt.data;
2687 if (pkttype == RTMP_PT_NOTIFY)
2688 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2691 if (rt->flv_size - rt->flv_off > size_temp) {
2692 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2693 rt->flv_off += size_temp;
2696 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2697 size_temp -= rt->flv_size - rt->flv_off;
2698 rt->flv_off += rt->flv_size - rt->flv_off;
2701 if (rt->flv_off == rt->flv_size) {
2704 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2708 rt->flv_header_bytes = 0;
2709 rt->flv_nb_packets++;
2711 } while (buf_temp - buf < size);
2713 if (rt->flv_nb_packets < rt->flush_interval)
2715 rt->flv_nb_packets = 0;
2717 /* set stream into nonblocking mode */
2718 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2720 /* try to read one byte from the stream */
2721 ret = ffurl_read(rt->stream, &c, 1);
2723 /* switch the stream back into blocking mode */
2724 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2726 if (ret == AVERROR(EAGAIN)) {
2727 /* no incoming data to handle */
2729 } else if (ret < 0) {
2731 } else if (ret == 1) {
2732 RTMPPacket rpkt = { 0 };
2734 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2736 rt->prev_pkt[0], c)) <= 0)
2739 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2742 ff_rtmp_packet_destroy(&rpkt);
2748 #define OFFSET(x) offsetof(RTMPContext, x)
2749 #define DEC AV_OPT_FLAG_DECODING_PARAM
2750 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2752 static const AVOption rtmp_options[] = {
2753 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2754 {"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},
2755 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2756 {"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},
2757 {"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},
2758 {"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"},
2759 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2760 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2761 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2762 {"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},
2763 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2764 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2765 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2766 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2767 {"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},
2768 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2769 {"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},
2770 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2771 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2772 {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2776 #define RTMP_PROTOCOL(flavor) \
2777 static const AVClass flavor##_class = { \
2778 .class_name = #flavor, \
2779 .item_name = av_default_item_name, \
2780 .option = rtmp_options, \
2781 .version = LIBAVUTIL_VERSION_INT, \
2784 URLProtocol ff_##flavor##_protocol = { \
2786 .url_open = rtmp_open, \
2787 .url_read = rtmp_read, \
2788 .url_read_seek = rtmp_seek, \
2789 .url_write = rtmp_write, \
2790 .url_close = rtmp_close, \
2791 .priv_data_size = sizeof(RTMPContext), \
2792 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2793 .priv_data_class= &flavor##_class, \
2798 RTMP_PROTOCOL(rtmpe)
2799 RTMP_PROTOCOL(rtmps)
2800 RTMP_PROTOCOL(rtmpt)
2801 RTMP_PROTOCOL(rtmpte)
2802 RTMP_PROTOCOL(rtmpts)