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]; ///< 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 if (!field || !value)
275 ff_amf_write_field_name(p, field);
282 ff_amf_write_bool(p, value[0] != '0');
285 ff_amf_write_string(p, value);
288 ff_amf_write_number(p, strtod(value, NULL));
291 ff_amf_write_null(p);
295 ff_amf_write_object_start(p);
297 ff_amf_write_object_end(p);
307 av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
308 return AVERROR(EINVAL);
312 * Generate 'connect' call and send it to the server.
314 static int gen_connect(URLContext *s, RTMPContext *rt)
320 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
326 ff_amf_write_string(&p, "connect");
327 ff_amf_write_number(&p, ++rt->nb_invokes);
328 ff_amf_write_object_start(&p);
329 ff_amf_write_field_name(&p, "app");
330 ff_amf_write_string2(&p, rt->app, rt->auth_params);
333 ff_amf_write_field_name(&p, "type");
334 ff_amf_write_string(&p, "nonprivate");
336 ff_amf_write_field_name(&p, "flashVer");
337 ff_amf_write_string(&p, rt->flashver);
340 ff_amf_write_field_name(&p, "swfUrl");
341 ff_amf_write_string(&p, rt->swfurl);
344 ff_amf_write_field_name(&p, "tcUrl");
345 ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
347 ff_amf_write_field_name(&p, "fpad");
348 ff_amf_write_bool(&p, 0);
349 ff_amf_write_field_name(&p, "capabilities");
350 ff_amf_write_number(&p, 15.0);
352 /* Tell the server we support all the audio codecs except
353 * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
354 * which are unused in the RTMP protocol implementation. */
355 ff_amf_write_field_name(&p, "audioCodecs");
356 ff_amf_write_number(&p, 4071.0);
357 ff_amf_write_field_name(&p, "videoCodecs");
358 ff_amf_write_number(&p, 252.0);
359 ff_amf_write_field_name(&p, "videoFunction");
360 ff_amf_write_number(&p, 1.0);
363 ff_amf_write_field_name(&p, "pageUrl");
364 ff_amf_write_string(&p, rt->pageurl);
367 ff_amf_write_object_end(&p);
370 char *param = rt->conn;
372 // Write arbitrary AMF data to the Connect message.
373 while (param != NULL) {
375 param += strspn(param, " ");
378 sep = strchr(param, ' ');
381 if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
382 // Invalid AMF parameter.
383 ff_rtmp_packet_destroy(&pkt);
394 pkt.size = p - pkt.data;
396 return rtmp_send_packet(rt, &pkt, 1);
399 static int read_connect(URLContext *s, RTMPContext *rt)
401 RTMPPacket pkt = { 0 };
411 if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
412 &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
415 bytestream2_init(&gbc, cp, pkt.size);
416 if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
417 av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
418 ff_rtmp_packet_destroy(&pkt);
419 return AVERROR_INVALIDDATA;
421 if (strcmp(command, "connect")) {
422 av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
423 ff_rtmp_packet_destroy(&pkt);
424 return AVERROR_INVALIDDATA;
426 ret = ff_amf_read_number(&gbc, &seqnum);
428 av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
429 /* Here one could parse an AMF Object with data as flashVers and others. */
430 ret = ff_amf_get_field_value(gbc.buffer,
431 gbc.buffer + bytestream2_get_bytes_left(&gbc),
432 "app", tmpstr, sizeof(tmpstr));
434 av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
435 if (!ret && strcmp(tmpstr, rt->app))
436 av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
438 ff_rtmp_packet_destroy(&pkt);
440 // Send Window Acknowledgement Size (as defined in speficication)
441 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
442 RTMP_PT_SERVER_BW, 0, 4)) < 0)
445 bytestream_put_be32(&p, rt->server_bw);
446 pkt.size = p - pkt.data;
447 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
448 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
449 ff_rtmp_packet_destroy(&pkt);
452 // Send Peer Bandwidth
453 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
454 RTMP_PT_CLIENT_BW, 0, 5)) < 0)
457 bytestream_put_be32(&p, rt->server_bw);
458 bytestream_put_byte(&p, 2); // dynamic
459 pkt.size = p - pkt.data;
460 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
461 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
462 ff_rtmp_packet_destroy(&pkt);
467 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
468 RTMP_PT_PING, 0, 6)) < 0)
472 bytestream_put_be16(&p, 0); // 0 -> Stream Begin
473 bytestream_put_be32(&p, 0);
474 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
475 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
476 ff_rtmp_packet_destroy(&pkt);
481 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
482 RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
486 bytestream_put_be32(&p, rt->out_chunk_size);
487 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
488 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
489 ff_rtmp_packet_destroy(&pkt);
493 // Send result_ NetConnection.Connect.Success to connect
494 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
496 RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
500 ff_amf_write_string(&p, "_result");
501 ff_amf_write_number(&p, seqnum);
503 ff_amf_write_object_start(&p);
504 ff_amf_write_field_name(&p, "fmsVer");
505 ff_amf_write_string(&p, "FMS/3,0,1,123");
506 ff_amf_write_field_name(&p, "capabilities");
507 ff_amf_write_number(&p, 31);
508 ff_amf_write_object_end(&p);
510 ff_amf_write_object_start(&p);
511 ff_amf_write_field_name(&p, "level");
512 ff_amf_write_string(&p, "status");
513 ff_amf_write_field_name(&p, "code");
514 ff_amf_write_string(&p, "NetConnection.Connect.Success");
515 ff_amf_write_field_name(&p, "description");
516 ff_amf_write_string(&p, "Connection succeeded.");
517 ff_amf_write_field_name(&p, "objectEncoding");
518 ff_amf_write_number(&p, 0);
519 ff_amf_write_object_end(&p);
521 pkt.size = p - pkt.data;
522 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
523 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
524 ff_rtmp_packet_destroy(&pkt);
528 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
529 RTMP_PT_INVOKE, 0, 30)) < 0)
532 ff_amf_write_string(&p, "onBWDone");
533 ff_amf_write_number(&p, 0);
534 ff_amf_write_null(&p);
535 ff_amf_write_number(&p, 8192);
536 pkt.size = p - pkt.data;
537 ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
538 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
539 ff_rtmp_packet_destroy(&pkt);
545 * Generate 'releaseStream' call and send it to the server. It should make
546 * the server release some channel for media streams.
548 static int gen_release_stream(URLContext *s, RTMPContext *rt)
554 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
555 0, 29 + strlen(rt->playpath))) < 0)
558 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
560 ff_amf_write_string(&p, "releaseStream");
561 ff_amf_write_number(&p, ++rt->nb_invokes);
562 ff_amf_write_null(&p);
563 ff_amf_write_string(&p, rt->playpath);
565 return rtmp_send_packet(rt, &pkt, 1);
569 * Generate 'FCPublish' call and send it to the server. It should make
570 * the server preapare for receiving media streams.
572 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
578 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
579 0, 25 + strlen(rt->playpath))) < 0)
582 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
584 ff_amf_write_string(&p, "FCPublish");
585 ff_amf_write_number(&p, ++rt->nb_invokes);
586 ff_amf_write_null(&p);
587 ff_amf_write_string(&p, rt->playpath);
589 return rtmp_send_packet(rt, &pkt, 1);
593 * Generate 'FCUnpublish' call and send it to the server. It should make
594 * the server destroy stream.
596 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
602 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
603 0, 27 + strlen(rt->playpath))) < 0)
606 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
608 ff_amf_write_string(&p, "FCUnpublish");
609 ff_amf_write_number(&p, ++rt->nb_invokes);
610 ff_amf_write_null(&p);
611 ff_amf_write_string(&p, rt->playpath);
613 return rtmp_send_packet(rt, &pkt, 0);
617 * Generate 'createStream' call and send it to the server. It should make
618 * the server allocate some channel for media streams.
620 static int gen_create_stream(URLContext *s, RTMPContext *rt)
626 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
628 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
633 ff_amf_write_string(&p, "createStream");
634 ff_amf_write_number(&p, ++rt->nb_invokes);
635 ff_amf_write_null(&p);
637 return rtmp_send_packet(rt, &pkt, 1);
642 * Generate 'deleteStream' call and send it to the server. It should make
643 * the server remove some channel for media streams.
645 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
651 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
653 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
658 ff_amf_write_string(&p, "deleteStream");
659 ff_amf_write_number(&p, ++rt->nb_invokes);
660 ff_amf_write_null(&p);
661 ff_amf_write_number(&p, rt->stream_id);
663 return rtmp_send_packet(rt, &pkt, 0);
667 * Generate client buffer time and send it to the server.
669 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
675 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
680 bytestream_put_be16(&p, 3);
681 bytestream_put_be32(&p, rt->stream_id);
682 bytestream_put_be32(&p, rt->client_buffer_time);
684 return rtmp_send_packet(rt, &pkt, 0);
688 * Generate 'play' call and send it to the server, then ping the server
689 * to start actual playing.
691 static int gen_play(URLContext *s, RTMPContext *rt)
697 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
699 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
700 0, 29 + strlen(rt->playpath))) < 0)
703 pkt.extra = rt->stream_id;
706 ff_amf_write_string(&p, "play");
707 ff_amf_write_number(&p, ++rt->nb_invokes);
708 ff_amf_write_null(&p);
709 ff_amf_write_string(&p, rt->playpath);
710 ff_amf_write_number(&p, rt->live * 1000);
712 return rtmp_send_packet(rt, &pkt, 1);
715 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
721 av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
724 if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
727 pkt.extra = rt->stream_id;
730 ff_amf_write_string(&p, "seek");
731 ff_amf_write_number(&p, 0); //no tracking back responses
732 ff_amf_write_null(&p); //as usual, the first null param
733 ff_amf_write_number(&p, timestamp); //where we want to jump
735 return rtmp_send_packet(rt, &pkt, 1);
739 * Generate 'publish' call and send it to the server.
741 static int gen_publish(URLContext *s, RTMPContext *rt)
747 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
749 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
750 0, 30 + strlen(rt->playpath))) < 0)
753 pkt.extra = rt->stream_id;
756 ff_amf_write_string(&p, "publish");
757 ff_amf_write_number(&p, ++rt->nb_invokes);
758 ff_amf_write_null(&p);
759 ff_amf_write_string(&p, rt->playpath);
760 ff_amf_write_string(&p, "live");
762 return rtmp_send_packet(rt, &pkt, 1);
766 * Generate ping reply and send it to the server.
768 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
774 if (ppkt->size < 6) {
775 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
777 return AVERROR_INVALIDDATA;
780 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
781 ppkt->timestamp + 1, 6)) < 0)
785 bytestream_put_be16(&p, 7);
786 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
788 return rtmp_send_packet(rt, &pkt, 0);
792 * Generate SWF verification message and send it to the server.
794 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
800 av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
801 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
806 bytestream_put_be16(&p, 27);
807 memcpy(p, rt->swfverification, 42);
809 return rtmp_send_packet(rt, &pkt, 0);
813 * Generate server bandwidth message and send it to the server.
815 static int gen_server_bw(URLContext *s, RTMPContext *rt)
821 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
826 bytestream_put_be32(&p, rt->server_bw);
828 return rtmp_send_packet(rt, &pkt, 0);
832 * Generate check bandwidth message and send it to the server.
834 static int gen_check_bw(URLContext *s, RTMPContext *rt)
840 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
845 ff_amf_write_string(&p, "_checkbw");
846 ff_amf_write_number(&p, ++rt->nb_invokes);
847 ff_amf_write_null(&p);
849 return rtmp_send_packet(rt, &pkt, 1);
853 * Generate report on bytes read so far and send it to the server.
855 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
861 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
866 bytestream_put_be32(&p, rt->bytes_read);
868 return rtmp_send_packet(rt, &pkt, 0);
871 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
872 const char *subscribe)
878 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
879 0, 27 + strlen(subscribe))) < 0)
883 ff_amf_write_string(&p, "FCSubscribe");
884 ff_amf_write_number(&p, ++rt->nb_invokes);
885 ff_amf_write_null(&p);
886 ff_amf_write_string(&p, subscribe);
888 return rtmp_send_packet(rt, &pkt, 1);
891 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
892 const uint8_t *key, int keylen, uint8_t *dst)
895 uint8_t hmac_buf[64+32] = {0};
898 sha = av_sha_alloc();
900 return AVERROR(ENOMEM);
903 memcpy(hmac_buf, key, keylen);
905 av_sha_init(sha, 256);
906 av_sha_update(sha,key, keylen);
907 av_sha_final(sha, hmac_buf);
909 for (i = 0; i < 64; i++)
910 hmac_buf[i] ^= HMAC_IPAD_VAL;
912 av_sha_init(sha, 256);
913 av_sha_update(sha, hmac_buf, 64);
915 av_sha_update(sha, src, len);
916 } else { //skip 32 bytes used for storing digest
917 av_sha_update(sha, src, gap);
918 av_sha_update(sha, src + gap + 32, len - gap - 32);
920 av_sha_final(sha, hmac_buf + 64);
922 for (i = 0; i < 64; i++)
923 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
924 av_sha_init(sha, 256);
925 av_sha_update(sha, hmac_buf, 64+32);
926 av_sha_final(sha, dst);
933 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
936 int i, digest_pos = 0;
938 for (i = 0; i < 4; i++)
939 digest_pos += buf[i + off];
940 digest_pos = digest_pos % mod_val + add_val;
946 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
947 * will be stored) into that packet.
949 * @param buf handshake data (1536 bytes)
950 * @param encrypted use an encrypted connection (RTMPE)
951 * @return offset to the digest inside input data
953 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
958 digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
960 digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
962 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
963 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
972 * Verify that the received server response has the expected digest value.
974 * @param buf handshake data received from the server (1536 bytes)
975 * @param off position to search digest offset from
976 * @return 0 if digest is valid, digest position otherwise
978 static int rtmp_validate_digest(uint8_t *buf, int off)
983 digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
985 ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
986 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
991 if (!memcmp(digest, buf + digest_pos, 32))
996 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1002 if (rt->swfhash_len != 32) {
1003 av_log(s, AV_LOG_ERROR,
1004 "Hash of the decompressed SWF file is not 32 bytes long.\n");
1005 return AVERROR(EINVAL);
1008 p = &rt->swfverification[0];
1009 bytestream_put_byte(&p, 1);
1010 bytestream_put_byte(&p, 1);
1011 bytestream_put_be32(&p, rt->swfsize);
1012 bytestream_put_be32(&p, rt->swfsize);
1014 if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1021 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1022 uint8_t **out_data, int64_t *out_size)
1024 z_stream zs = { 0 };
1029 zs.avail_in = in_size;
1030 zs.next_in = in_data;
1031 ret = inflateInit(&zs);
1033 return AVERROR_UNKNOWN;
1036 uint8_t tmp_buf[16384];
1038 zs.avail_out = sizeof(tmp_buf);
1039 zs.next_out = tmp_buf;
1041 ret = inflate(&zs, Z_NO_FLUSH);
1042 if (ret != Z_OK && ret != Z_STREAM_END) {
1043 ret = AVERROR_UNKNOWN;
1047 size = sizeof(tmp_buf) - zs.avail_out;
1048 if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1049 ret = AVERROR(ENOMEM);
1054 memcpy(*out_data + *out_size, tmp_buf, size);
1056 } while (zs.avail_out == 0);
1064 static int rtmp_calc_swfhash(URLContext *s)
1066 RTMPContext *rt = s->priv_data;
1067 uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1068 int64_t in_size, out_size;
1074 /* Get the SWF player file. */
1075 if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1076 &s->interrupt_callback, NULL)) < 0) {
1077 av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1081 if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1086 if (!(in_data = av_malloc(in_size))) {
1087 ret = AVERROR(ENOMEM);
1091 if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1095 ret = AVERROR_INVALIDDATA;
1099 if (!memcmp(in_data, "CWS", 3)) {
1100 /* Decompress the SWF player file using Zlib. */
1101 if (!(out_data = av_malloc(8))) {
1102 ret = AVERROR(ENOMEM);
1105 *in_data = 'F'; // magic stuff
1106 memcpy(out_data, in_data, 8);
1110 if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1111 &out_data, &out_size)) < 0)
1114 av_log(s, AV_LOG_ERROR,
1115 "Zlib is required for decompressing the SWF player file.\n");
1116 ret = AVERROR(EINVAL);
1126 /* Compute the SHA256 hash of the SWF player file. */
1127 if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1128 "Genuine Adobe Flash Player 001", 30,
1132 /* Set SWFVerification parameters. */
1133 av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1134 rt->swfsize = swfsize;
1138 av_freep(&out_data);
1139 ffurl_close(stream);
1144 * Perform handshake with the server by means of exchanging pseudorandom data
1145 * signed with HMAC-SHA2 digest.
1147 * @return 0 if handshake succeeds, negative value otherwise
1149 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1152 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1153 3, // unencrypted data
1154 0, 0, 0, 0, // client uptime
1160 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1161 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1163 int server_pos, client_pos;
1164 uint8_t digest[32], signature[32];
1167 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1169 av_lfg_init(&rnd, 0xDEADC0DE);
1170 // generate handshake packet - 1536 bytes of pseudorandom data
1171 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1172 tosend[i] = av_lfg_get(&rnd) >> 24;
1174 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1175 /* When the client wants to use RTMPE, we have to change the command
1176 * byte to 0x06 which means to use encrypted data and we have to set
1177 * the flash version to at least 9.0.115.0. */
1184 /* Initialize the Diffie-Hellmann context and generate the public key
1185 * to send to the server. */
1186 if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1190 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1194 if ((ret = ffurl_write(rt->stream, tosend,
1195 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1196 av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1200 if ((ret = ffurl_read_complete(rt->stream, serverdata,
1201 RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1202 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1206 if ((ret = ffurl_read_complete(rt->stream, clientdata,
1207 RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1208 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1212 av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1213 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1214 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1216 if (rt->is_input && serverdata[5] >= 3) {
1217 server_pos = rtmp_validate_digest(serverdata + 1, 772);
1223 server_pos = rtmp_validate_digest(serverdata + 1, 8);
1228 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1229 return AVERROR(EIO);
1233 /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1234 * key are the last 32 bytes of the server handshake. */
1236 if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1237 RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1241 ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1242 rtmp_server_key, sizeof(rtmp_server_key),
1247 ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1248 0, digest, 32, signature);
1252 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1253 /* Compute the shared secret key sent by the server and initialize
1254 * the RC4 encryption. */
1255 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1256 tosend + 1, type)) < 0)
1259 /* Encrypt the signature received by the server. */
1260 ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1263 if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1264 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1265 return AVERROR(EIO);
1268 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1269 tosend[i] = av_lfg_get(&rnd) >> 24;
1270 ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1271 rtmp_player_key, sizeof(rtmp_player_key),
1276 ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1278 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1282 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1283 /* Encrypt the signature to be send to the server. */
1284 ff_rtmpe_encrypt_sig(rt->stream, tosend +
1285 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1289 // write reply back to the server
1290 if ((ret = ffurl_write(rt->stream, tosend,
1291 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1294 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1295 /* Set RC4 keys for encryption and update the keystreams. */
1296 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1300 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1301 /* Compute the shared secret key sent by the server and initialize
1302 * the RC4 encryption. */
1303 if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1304 tosend + 1, 1)) < 0)
1307 if (serverdata[0] == 9) {
1308 /* Encrypt the signature received by the server. */
1309 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1314 if ((ret = ffurl_write(rt->stream, serverdata + 1,
1315 RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1318 if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1319 /* Set RC4 keys for encryption and update the keystreams. */
1320 if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1328 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1329 uint32_t *second_int, char *arraydata,
1334 inoutsize = ffurl_read_complete(rt->stream, arraydata,
1335 RTMP_HANDSHAKE_PACKET_SIZE);
1337 return AVERROR(EIO);
1338 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1339 av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1340 " not following standard\n", (int)inoutsize);
1341 return AVERROR(EINVAL);
1344 *first_int = AV_RB32(arraydata);
1345 *second_int = AV_RB32(arraydata + 4);
1349 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1350 uint32_t second_int, char *arraydata, int size)
1354 AV_WB32(arraydata, first_int);
1355 AV_WB32(arraydata + 4, second_int);
1356 inoutsize = ffurl_write(rt->stream, arraydata,
1357 RTMP_HANDSHAKE_PACKET_SIZE);
1358 if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1359 av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1360 return AVERROR(EIO);
1367 * rtmp handshake server side
1369 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1371 uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1373 uint32_t hs_my_epoch;
1374 uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1375 uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1382 inoutsize = ffurl_read_complete(rt->stream, buffer, 1); // Receive C0
1383 if (inoutsize <= 0) {
1384 av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1385 return AVERROR(EIO);
1388 if (buffer[0] != 3) {
1389 av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1390 return AVERROR(EIO);
1392 if (ffurl_write(rt->stream, buffer, 1) <= 0) { // Send S0
1393 av_log(s, AV_LOG_ERROR,
1394 "Unable to write answer - RTMP S0\n");
1395 return AVERROR(EIO);
1398 ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1399 RTMP_HANDSHAKE_PACKET_SIZE);
1401 av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1405 /* By now same epoch will be sent */
1406 hs_my_epoch = hs_epoch;
1407 /* Generate random */
1408 for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1410 AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1412 ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1413 RTMP_HANDSHAKE_PACKET_SIZE);
1415 av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1419 ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1420 RTMP_HANDSHAKE_PACKET_SIZE);
1422 av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1426 ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1427 RTMP_HANDSHAKE_PACKET_SIZE);
1429 av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1432 if (temp != hs_my_epoch)
1433 av_log(s, AV_LOG_WARNING,
1434 "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1435 if (memcmp(buffer + 8, hs_s1 + 8,
1436 RTMP_HANDSHAKE_PACKET_SIZE - 8))
1437 av_log(s, AV_LOG_WARNING,
1438 "Erroneous C2 Message random does not match up\n");
1443 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1445 RTMPContext *rt = s->priv_data;
1448 if (pkt->size < 4) {
1449 av_log(s, AV_LOG_ERROR,
1450 "Too short chunk size change packet (%d)\n",
1452 return AVERROR_INVALIDDATA;
1455 if (!rt->is_input) {
1456 /* Send the same chunk size change packet back to the server,
1457 * setting the outgoing chunk size to the same as the incoming one. */
1458 if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1459 &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1461 rt->out_chunk_size = AV_RB32(pkt->data);
1464 rt->in_chunk_size = AV_RB32(pkt->data);
1465 if (rt->in_chunk_size <= 0) {
1466 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1468 return AVERROR_INVALIDDATA;
1470 av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1476 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1478 RTMPContext *rt = s->priv_data;
1481 if (pkt->size < 2) {
1482 av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1484 return AVERROR_INVALIDDATA;
1487 t = AV_RB16(pkt->data);
1489 if ((ret = gen_pong(s, rt, pkt)) < 0)
1491 } else if (t == 26) {
1493 if ((ret = gen_swf_verification(s, rt)) < 0)
1496 av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1503 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1505 RTMPContext *rt = s->priv_data;
1507 if (pkt->size < 4) {
1508 av_log(s, AV_LOG_ERROR,
1509 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1511 return AVERROR_INVALIDDATA;
1514 rt->client_report_size = AV_RB32(pkt->data);
1515 if (rt->client_report_size <= 0) {
1516 av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1517 rt->client_report_size);
1518 return AVERROR_INVALIDDATA;
1521 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1522 rt->client_report_size >>= 1;
1527 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1529 RTMPContext *rt = s->priv_data;
1531 if (pkt->size < 4) {
1532 av_log(s, AV_LOG_ERROR,
1533 "Too short server bandwidth report packet (%d)\n",
1535 return AVERROR_INVALIDDATA;
1538 rt->server_bw = AV_RB32(pkt->data);
1539 if (rt->server_bw <= 0) {
1540 av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1542 return AVERROR_INVALIDDATA;
1544 av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1549 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1550 const char *opaque, const char *challenge)
1553 char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1554 struct AVMD5 *md5 = av_md5_alloc();
1556 return AVERROR(ENOMEM);
1558 snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1561 av_md5_update(md5, user, strlen(user));
1562 av_md5_update(md5, salt, strlen(salt));
1563 av_md5_update(md5, rt->password, strlen(rt->password));
1564 av_md5_final(md5, hash);
1565 av_base64_encode(hashstr, sizeof(hashstr), hash,
1568 av_md5_update(md5, hashstr, strlen(hashstr));
1570 av_md5_update(md5, opaque, strlen(opaque));
1572 av_md5_update(md5, challenge, strlen(challenge));
1573 av_md5_update(md5, challenge2, strlen(challenge2));
1574 av_md5_final(md5, hash);
1575 av_base64_encode(hashstr, sizeof(hashstr), hash,
1577 snprintf(rt->auth_params, sizeof(rt->auth_params),
1578 "?authmod=%s&user=%s&challenge=%s&response=%s",
1579 "adobe", user, challenge2, hashstr);
1581 av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1582 "&opaque=%s", opaque);
1588 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1591 char hashstr1[33], hashstr2[33];
1592 const char *realm = "live";
1593 const char *method = "publish";
1594 const char *qop = "auth";
1595 const char *nc = "00000001";
1597 struct AVMD5 *md5 = av_md5_alloc();
1599 return AVERROR(ENOMEM);
1601 snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1604 av_md5_update(md5, user, strlen(user));
1605 av_md5_update(md5, ":", 1);
1606 av_md5_update(md5, realm, strlen(realm));
1607 av_md5_update(md5, ":", 1);
1608 av_md5_update(md5, rt->password, strlen(rt->password));
1609 av_md5_final(md5, hash);
1610 ff_data_to_hex(hashstr1, hash, 16, 1);
1611 hashstr1[32] = '\0';
1614 av_md5_update(md5, method, strlen(method));
1615 av_md5_update(md5, ":/", 2);
1616 av_md5_update(md5, rt->app, strlen(rt->app));
1617 if (!strchr(rt->app, '/'))
1618 av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1619 av_md5_final(md5, hash);
1620 ff_data_to_hex(hashstr2, hash, 16, 1);
1621 hashstr2[32] = '\0';
1624 av_md5_update(md5, hashstr1, strlen(hashstr1));
1625 av_md5_update(md5, ":", 1);
1627 av_md5_update(md5, nonce, strlen(nonce));
1628 av_md5_update(md5, ":", 1);
1629 av_md5_update(md5, nc, strlen(nc));
1630 av_md5_update(md5, ":", 1);
1631 av_md5_update(md5, cnonce, strlen(cnonce));
1632 av_md5_update(md5, ":", 1);
1633 av_md5_update(md5, qop, strlen(qop));
1634 av_md5_update(md5, ":", 1);
1635 av_md5_update(md5, hashstr2, strlen(hashstr2));
1636 av_md5_final(md5, hash);
1637 ff_data_to_hex(hashstr1, hash, 16, 1);
1639 snprintf(rt->auth_params, sizeof(rt->auth_params),
1640 "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1641 "llnw", user, nonce, cnonce, nc, hashstr1);
1647 static int handle_connect_error(URLContext *s, const char *desc)
1649 RTMPContext *rt = s->priv_data;
1650 char buf[300], *ptr, authmod[15];
1652 const char *user = "", *salt = "", *opaque = NULL,
1653 *challenge = NULL, *cptr = NULL, *nonce = NULL;
1655 if (!(cptr = strstr(desc, "authmod=adobe")) &&
1656 !(cptr = strstr(desc, "authmod=llnw"))) {
1657 av_log(s, AV_LOG_ERROR,
1658 "Unknown connect error (unsupported authentication method?)\n");
1659 return AVERROR_UNKNOWN;
1661 cptr += strlen("authmod=");
1662 while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1663 authmod[i++] = *cptr++;
1666 if (!rt->username[0] || !rt->password[0]) {
1667 av_log(s, AV_LOG_ERROR, "No credentials set\n");
1668 return AVERROR_UNKNOWN;
1671 if (strstr(desc, "?reason=authfailed")) {
1672 av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1673 return AVERROR_UNKNOWN;
1674 } else if (strstr(desc, "?reason=nosuchuser")) {
1675 av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1676 return AVERROR_UNKNOWN;
1679 if (rt->auth_tried) {
1680 av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1681 return AVERROR_UNKNOWN;
1684 rt->auth_params[0] = '\0';
1686 if (strstr(desc, "code=403 need auth")) {
1687 snprintf(rt->auth_params, sizeof(rt->auth_params),
1688 "?authmod=%s&user=%s", authmod, rt->username);
1692 if (!(cptr = strstr(desc, "?reason=needauth"))) {
1693 av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1694 return AVERROR_UNKNOWN;
1697 av_strlcpy(buf, cptr + 1, sizeof(buf));
1701 char *next = strchr(ptr, '&');
1702 char *value = strchr(ptr, '=');
1707 if (!strcmp(ptr, "user")) {
1709 } else if (!strcmp(ptr, "salt")) {
1711 } else if (!strcmp(ptr, "opaque")) {
1713 } else if (!strcmp(ptr, "challenge")) {
1715 } else if (!strcmp(ptr, "nonce")) {
1721 if (!strcmp(authmod, "adobe")) {
1722 if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1725 if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1733 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1735 RTMPContext *rt = s->priv_data;
1736 const uint8_t *data_end = pkt->data + pkt->size;
1737 char *tracked_method = NULL;
1738 int level = AV_LOG_ERROR;
1739 uint8_t tmpstr[256];
1742 if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1745 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1746 "description", tmpstr, sizeof(tmpstr))) {
1747 if (tracked_method && (!strcmp(tracked_method, "_checkbw") ||
1748 !strcmp(tracked_method, "releaseStream") ||
1749 !strcmp(tracked_method, "FCSubscribe") ||
1750 !strcmp(tracked_method, "FCPublish"))) {
1751 /* Gracefully ignore Adobe-specific historical artifact errors. */
1752 level = AV_LOG_WARNING;
1754 } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1755 ret = handle_connect_error(s, tmpstr);
1757 rt->do_reconnect = 1;
1758 level = AV_LOG_VERBOSE;
1761 ret = AVERROR_UNKNOWN;
1762 av_log(s, level, "Server error: %s\n", tmpstr);
1765 av_free(tracked_method);
1769 static int write_begin(URLContext *s)
1771 RTMPContext *rt = s->priv_data;
1773 RTMPPacket spkt = { 0 };
1776 // Send Stream Begin 1
1777 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1778 RTMP_PT_PING, 0, 6)) < 0) {
1779 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1783 bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1784 bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin
1785 bytestream2_put_be32(&pbc, rt->nb_streamid);
1787 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1788 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1790 ff_rtmp_packet_destroy(&spkt);
1795 static int write_status(URLContext *s, RTMPPacket *pkt,
1796 const char *status, const char *filename)
1798 RTMPContext *rt = s->priv_data;
1799 RTMPPacket spkt = { 0 };
1800 char statusmsg[128];
1804 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1806 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1807 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1812 spkt.extra = pkt->extra;
1813 ff_amf_write_string(&pp, "onStatus");
1814 ff_amf_write_number(&pp, 0);
1815 ff_amf_write_null(&pp);
1817 ff_amf_write_object_start(&pp);
1818 ff_amf_write_field_name(&pp, "level");
1819 ff_amf_write_string(&pp, "status");
1820 ff_amf_write_field_name(&pp, "code");
1821 ff_amf_write_string(&pp, status);
1822 ff_amf_write_field_name(&pp, "description");
1823 snprintf(statusmsg, sizeof(statusmsg),
1824 "%s is now published", filename);
1825 ff_amf_write_string(&pp, statusmsg);
1826 ff_amf_write_field_name(&pp, "details");
1827 ff_amf_write_string(&pp, filename);
1828 ff_amf_write_field_name(&pp, "clientid");
1829 snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1830 ff_amf_write_string(&pp, statusmsg);
1831 ff_amf_write_object_end(&pp);
1833 spkt.size = pp - spkt.data;
1834 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1835 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1836 ff_rtmp_packet_destroy(&spkt);
1841 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1843 RTMPContext *rt = s->priv_data;
1849 const uint8_t *p = pkt->data;
1851 RTMPPacket spkt = { 0 };
1855 bytestream2_init(&gbc, p, pkt->size);
1856 if (ff_amf_read_string(&gbc, command, sizeof(command),
1858 av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1859 return AVERROR_INVALIDDATA;
1862 ret = ff_amf_read_number(&gbc, &seqnum);
1865 ret = ff_amf_read_null(&gbc);
1868 if (!strcmp(command, "FCPublish") ||
1869 !strcmp(command, "publish")) {
1870 ret = ff_amf_read_string(&gbc, filename,
1871 sizeof(filename), &stringlen);
1874 pchar = strrchr(s->filename, '/');
1876 av_log(s, AV_LOG_WARNING,
1877 "Unable to find / in url %s, bad format\n",
1879 pchar = s->filename;
1882 if (strcmp(pchar, filename))
1883 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1884 " %s\n", filename, pchar);
1886 rt->state = STATE_RECEIVING;
1889 if (!strcmp(command, "FCPublish")) {
1890 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1892 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1893 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1897 ff_amf_write_string(&pp, "onFCPublish");
1898 } else if (!strcmp(command, "publish")) {
1899 ret = write_begin(s);
1903 // Send onStatus(NetStream.Publish.Start)
1904 return write_status(s, pkt, "NetStream.Publish.Start",
1906 } else if (!strcmp(command, "play")) {
1907 ret = write_begin(s);
1910 rt->state = STATE_SENDING;
1911 return write_status(s, pkt, "NetStream.Play.Start",
1914 if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1916 RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1917 av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1921 ff_amf_write_string(&pp, "_result");
1922 ff_amf_write_number(&pp, seqnum);
1923 ff_amf_write_null(&pp);
1924 if (!strcmp(command, "createStream")) {
1926 if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1927 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1928 ff_amf_write_number(&pp, rt->nb_streamid);
1929 /* By now we don't control which streams are removed in
1930 * deleteStream. There is no stream creation control
1931 * if a client creates more than 2^32 - 2 streams. */
1934 spkt.size = pp - spkt.data;
1935 ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1936 &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1937 ff_rtmp_packet_destroy(&spkt);
1941 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1943 RTMPContext *rt = s->priv_data;
1944 char *tracked_method = NULL;
1947 if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1950 if (!tracked_method) {
1951 /* Ignore this reply when the current method is not tracked. */
1955 if (!strcmp(tracked_method, "connect")) {
1956 if (!rt->is_input) {
1957 if ((ret = gen_release_stream(s, rt)) < 0)
1960 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1963 if ((ret = gen_server_bw(s, rt)) < 0)
1967 if ((ret = gen_create_stream(s, rt)) < 0)
1971 /* Send the FCSubscribe command when the name of live
1972 * stream is defined by the user or if it's a live stream. */
1973 if (rt->subscribe) {
1974 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1976 } else if (rt->live == -1) {
1977 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1981 } else if (!strcmp(tracked_method, "createStream")) {
1982 //extract a number from the result
1983 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1984 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1986 rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1989 if (!rt->is_input) {
1990 if ((ret = gen_publish(s, rt)) < 0)
1993 if ((ret = gen_play(s, rt)) < 0)
1995 if ((ret = gen_buffer_time(s, rt)) < 0)
2001 av_free(tracked_method);
2005 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2007 RTMPContext *rt = s->priv_data;
2008 const uint8_t *data_end = pkt->data + pkt->size;
2009 const uint8_t *ptr = pkt->data + RTMP_HEADER;
2010 uint8_t tmpstr[256];
2013 for (i = 0; i < 2; i++) {
2014 t = ff_amf_tag_size(ptr, data_end);
2020 t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2021 if (!t && !strcmp(tmpstr, "error")) {
2022 t = ff_amf_get_field_value(ptr, data_end,
2023 "description", tmpstr, sizeof(tmpstr));
2024 if (t || !tmpstr[0])
2025 t = ff_amf_get_field_value(ptr, data_end, "code",
2026 tmpstr, sizeof(tmpstr));
2028 av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2032 t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2033 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2034 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2035 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2036 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2037 if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2042 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2044 RTMPContext *rt = s->priv_data;
2047 //TODO: check for the messages sent for wrong state?
2048 if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2049 if ((ret = handle_invoke_error(s, pkt)) < 0)
2051 } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2052 if ((ret = handle_invoke_result(s, pkt)) < 0)
2054 } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2055 if ((ret = handle_invoke_status(s, pkt)) < 0)
2057 } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2058 if ((ret = gen_check_bw(s, rt)) < 0)
2060 } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2061 ff_amf_match_string(pkt->data, pkt->size, "FCPublish") ||
2062 ff_amf_match_string(pkt->data, pkt->size, "publish") ||
2063 ff_amf_match_string(pkt->data, pkt->size, "play") ||
2064 ff_amf_match_string(pkt->data, pkt->size, "_checkbw") ||
2065 ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2066 if ((ret = send_invoke_response(s, pkt)) < 0)
2073 static int update_offset(RTMPContext *rt, int size)
2077 // generate packet header and put data into buffer for FLV demuxer
2078 if (rt->flv_off < rt->flv_size) {
2079 // There is old unread data in the buffer, thus append at the end
2080 old_flv_size = rt->flv_size;
2081 rt->flv_size += size;
2083 // All data has been read, write the new data at the start of the buffer
2085 rt->flv_size = size;
2089 return old_flv_size;
2092 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2094 int old_flv_size, ret;
2096 const uint8_t *data = pkt->data + skip;
2097 const int size = pkt->size - skip;
2098 uint32_t ts = pkt->timestamp;
2100 old_flv_size = update_offset(rt, size + 15);
2102 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2103 rt->flv_size = rt->flv_off = 0;
2106 bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2107 bytestream2_skip_p(&pbc, old_flv_size);
2108 bytestream2_put_byte(&pbc, pkt->type);
2109 bytestream2_put_be24(&pbc, size);
2110 bytestream2_put_be24(&pbc, ts);
2111 bytestream2_put_byte(&pbc, ts >> 24);
2112 bytestream2_put_be24(&pbc, 0);
2113 bytestream2_put_buffer(&pbc, data, size);
2114 bytestream2_put_be32(&pbc, 0);
2119 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2121 RTMPContext *rt = s->priv_data;
2122 uint8_t commandbuffer[64];
2123 char statusmsg[128];
2124 int stringlen, ret, skip = 0;
2127 bytestream2_init(&gbc, pkt->data, pkt->size);
2128 if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2130 return AVERROR_INVALIDDATA;
2132 // Skip the @setDataFrame string and validate it is a notification
2133 if (!strcmp(commandbuffer, "@setDataFrame")) {
2134 skip = gbc.buffer - pkt->data;
2135 ret = ff_amf_read_string(&gbc, statusmsg,
2136 sizeof(statusmsg), &stringlen);
2138 return AVERROR_INVALIDDATA;
2141 return append_flv_data(rt, pkt, skip);
2145 * Parse received packet and possibly perform some action depending on
2146 * the packet contents.
2147 * @return 0 for no errors, negative values for serious errors which prevent
2148 * further communications, positive values for uncritical errors
2150 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2155 ff_rtmp_packet_dump(s, pkt);
2158 switch (pkt->type) {
2159 case RTMP_PT_BYTES_READ:
2160 av_dlog(s, "received bytes read report\n");
2162 case RTMP_PT_CHUNK_SIZE:
2163 if ((ret = handle_chunk_size(s, pkt)) < 0)
2167 if ((ret = handle_ping(s, pkt)) < 0)
2170 case RTMP_PT_CLIENT_BW:
2171 if ((ret = handle_client_bw(s, pkt)) < 0)
2174 case RTMP_PT_SERVER_BW:
2175 if ((ret = handle_server_bw(s, pkt)) < 0)
2178 case RTMP_PT_INVOKE:
2179 if ((ret = handle_invoke(s, pkt)) < 0)
2184 case RTMP_PT_METADATA:
2185 case RTMP_PT_NOTIFY:
2186 /* Audio, Video and Metadata packets are parsed in get_packet() */
2189 av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2195 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2197 int ret, old_flv_size, type;
2198 const uint8_t *next;
2201 uint32_t ts, cts, pts = 0;
2203 old_flv_size = update_offset(rt, pkt->size);
2205 if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2206 rt->flv_size = rt->flv_off = 0;
2211 p = rt->flv_data + old_flv_size;
2213 /* copy data while rewriting timestamps */
2214 ts = pkt->timestamp;
2216 while (next - pkt->data < pkt->size - RTMP_HEADER) {
2217 type = bytestream_get_byte(&next);
2218 size = bytestream_get_be24(&next);
2219 cts = bytestream_get_be24(&next);
2220 cts |= bytestream_get_byte(&next) << 24;
2225 if (size + 3 + 4 > pkt->data + pkt->size - next)
2227 bytestream_put_byte(&p, type);
2228 bytestream_put_be24(&p, size);
2229 bytestream_put_be24(&p, ts);
2230 bytestream_put_byte(&p, ts >> 24);
2231 memcpy(p, next, size + 3 + 4);
2232 next += size + 3 + 4;
2235 if (p != rt->flv_data + rt->flv_size) {
2236 av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2237 "RTMP_PT_METADATA packet\n");
2238 rt->flv_size = p - rt->flv_data;
2245 * Interact with the server by receiving and sending RTMP packets until
2246 * there is some significant data (media data or expected status notification).
2248 * @param s reading context
2249 * @param for_header non-zero value tells function to work until it
2250 * gets notification from the server that playing has been started,
2251 * otherwise function will work until some media data is received (or
2253 * @return 0 for successful operation, negative value in case of error
2255 static int get_packet(URLContext *s, int for_header)
2257 RTMPContext *rt = s->priv_data;
2260 if (rt->state == STATE_STOPPED)
2264 RTMPPacket rpkt = { 0 };
2265 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2266 rt->in_chunk_size, &rt->prev_pkt[0],
2267 &rt->nb_prev_pkt[0])) <= 0) {
2269 return AVERROR(EAGAIN);
2271 return AVERROR(EIO);
2274 rt->bytes_read += ret;
2275 if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2276 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2277 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2279 rt->last_bytes_read = rt->bytes_read;
2282 ret = rtmp_parse_result(s, rt, &rpkt);
2284 // At this point we must check if we are in the seek state and continue
2285 // with the next packet. handle_invoke will get us out of this state
2286 // when the right message is encountered
2287 if (rt->state == STATE_SEEKING) {
2288 ff_rtmp_packet_destroy(&rpkt);
2289 // We continue, let the natural flow of things happen:
2290 // AVERROR(EAGAIN) or handle_invoke gets us out of here
2294 if (ret < 0) {//serious error in current packet
2295 ff_rtmp_packet_destroy(&rpkt);
2298 if (rt->do_reconnect && for_header) {
2299 ff_rtmp_packet_destroy(&rpkt);
2302 if (rt->state == STATE_STOPPED) {
2303 ff_rtmp_packet_destroy(&rpkt);
2306 if (for_header && (rt->state == STATE_PLAYING ||
2307 rt->state == STATE_PUBLISHING ||
2308 rt->state == STATE_SENDING ||
2309 rt->state == STATE_RECEIVING)) {
2310 ff_rtmp_packet_destroy(&rpkt);
2313 if (!rpkt.size || !rt->is_input) {
2314 ff_rtmp_packet_destroy(&rpkt);
2317 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2318 ret = append_flv_data(rt, &rpkt, 0);
2319 ff_rtmp_packet_destroy(&rpkt);
2321 } else if (rpkt.type == RTMP_PT_NOTIFY) {
2322 ret = handle_notify(s, &rpkt);
2323 ff_rtmp_packet_destroy(&rpkt);
2325 } else if (rpkt.type == RTMP_PT_METADATA) {
2326 ret = handle_metadata(rt, &rpkt);
2327 ff_rtmp_packet_destroy(&rpkt);
2330 ff_rtmp_packet_destroy(&rpkt);
2334 static int rtmp_close(URLContext *h)
2336 RTMPContext *rt = h->priv_data;
2339 if (!rt->is_input) {
2340 rt->flv_data = NULL;
2341 if (rt->out_pkt.size)
2342 ff_rtmp_packet_destroy(&rt->out_pkt);
2343 if (rt->state > STATE_FCPUBLISH)
2344 ret = gen_fcunpublish_stream(h, rt);
2346 if (rt->state > STATE_HANDSHAKED)
2347 ret = gen_delete_stream(h, rt);
2348 for (i = 0; i < 2; i++) {
2349 for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2350 ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2351 av_freep(&rt->prev_pkt[i]);
2354 free_tracked_methods(rt);
2355 av_freep(&rt->flv_data);
2356 ffurl_close(rt->stream);
2361 * Open RTMP connection and verify that the stream can be played.
2363 * URL syntax: rtmp://server[:port][/app][/playpath]
2364 * where 'app' is first one or two directories in the path
2365 * (e.g. /ondemand/, /flash/live/, etc.)
2366 * and 'playpath' is a file name (the rest of the path,
2367 * may be prefixed with "mp4:")
2369 static int rtmp_open(URLContext *s, const char *uri, int flags)
2371 RTMPContext *rt = s->priv_data;
2372 char proto[8], hostname[256], path[1024], auth[100], *fname;
2376 AVDictionary *opts = NULL;
2379 if (rt->listen_timeout > 0)
2382 rt->is_input = !(flags & AVIO_FLAG_WRITE);
2384 av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2385 hostname, sizeof(hostname), &port,
2386 path, sizeof(path), s->filename);
2388 if (strchr(path, ' ')) {
2389 av_log(s, AV_LOG_WARNING,
2390 "Detected librtmp style URL parameters, these aren't supported "
2391 "by the libavformat internal RTMP handler currently enabled. "
2392 "See the documentation for the correct way to pass parameters.\n");
2396 char *ptr = strchr(auth, ':');
2399 av_strlcpy(rt->username, auth, sizeof(rt->username));
2400 av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2404 if (rt->listen && strcmp(proto, "rtmp")) {
2405 av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2407 return AVERROR(EINVAL);
2409 if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2410 if (!strcmp(proto, "rtmpts"))
2411 av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2413 /* open the http tunneling connection */
2414 ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2415 } else if (!strcmp(proto, "rtmps")) {
2416 /* open the tls connection */
2418 port = RTMPS_DEFAULT_PORT;
2419 ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2420 } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2421 if (!strcmp(proto, "rtmpte"))
2422 av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2424 /* open the encrypted connection */
2425 ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2428 /* open the tcp connection */
2430 port = RTMP_DEFAULT_PORT;
2432 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2433 "?listen&listen_timeout=%d",
2434 rt->listen_timeout * 1000);
2436 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2440 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2441 &s->interrupt_callback, &opts)) < 0) {
2442 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2446 if (rt->swfverify) {
2447 if ((ret = rtmp_calc_swfhash(s)) < 0)
2451 rt->state = STATE_START;
2452 if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2454 if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2457 rt->out_chunk_size = 128;
2458 rt->in_chunk_size = 128; // Probably overwritten later
2459 rt->state = STATE_HANDSHAKED;
2461 // Keep the application name when it has been defined by the user.
2464 rt->app = av_malloc(APP_MAX_LENGTH);
2466 ret = AVERROR(ENOMEM);
2470 //extract "app" part from path
2471 if (!strncmp(path, "/ondemand/", 10)) {
2473 memcpy(rt->app, "ondemand", 9);
2475 char *next = *path ? path + 1 : path;
2476 char *p = strchr(next, '/');
2481 // make sure we do not mismatch a playpath for an application instance
2482 char *c = strchr(p + 1, ':');
2483 fname = strchr(p + 1, '/');
2484 if (!fname || (c && c < fname)) {
2486 av_strlcpy(rt->app, path + 1, p - path);
2489 av_strlcpy(rt->app, path + 1, fname - path - 1);
2495 // The name of application has been defined by the user, override it.
2500 if (!rt->playpath) {
2501 int len = strlen(fname);
2503 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2504 if (!rt->playpath) {
2505 ret = AVERROR(ENOMEM);
2509 if (!strchr(fname, ':') && len >= 4 &&
2510 (!strcmp(fname + len - 4, ".f4v") ||
2511 !strcmp(fname + len - 4, ".mp4"))) {
2512 memcpy(rt->playpath, "mp4:", 5);
2513 } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2514 fname[len - 4] = '\0';
2516 rt->playpath[0] = 0;
2518 av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2522 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2524 ret = AVERROR(ENOMEM);
2527 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2528 port, "/%s", rt->app);
2531 if (!rt->flashver) {
2532 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2533 if (!rt->flashver) {
2534 ret = AVERROR(ENOMEM);
2538 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2539 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2540 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2542 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2543 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2547 rt->client_report_size = 1048576;
2549 rt->last_bytes_read = 0;
2550 rt->server_bw = 2500000;
2552 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2553 proto, path, rt->app, rt->playpath);
2555 if ((ret = gen_connect(s, rt)) < 0)
2558 if (read_connect(s, s->priv_data) < 0)
2563 ret = get_packet(s, 1);
2564 } while (ret == AVERROR(EAGAIN));
2568 if (rt->do_reconnect) {
2570 ffurl_close(rt->stream);
2572 rt->do_reconnect = 0;
2574 for (i = 0; i < 2; i++)
2575 memset(rt->prev_pkt[i], 0,
2576 sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2577 free_tracked_methods(rt);
2583 // generate FLV header for demuxer
2585 if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2588 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2591 rt->flv_data = NULL;
2593 rt->skip_bytes = 13;
2596 s->max_packet_size = rt->stream->max_packet_size;
2601 av_dict_free(&opts);
2606 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2608 RTMPContext *rt = s->priv_data;
2609 int orig_size = size;
2613 int data_left = rt->flv_size - rt->flv_off;
2615 if (data_left >= size) {
2616 memcpy(buf, rt->flv_data + rt->flv_off, size);
2617 rt->flv_off += size;
2620 if (data_left > 0) {
2621 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2624 rt->flv_off = rt->flv_size;
2627 if ((ret = get_packet(s, 0)) < 0)
2633 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2636 RTMPContext *rt = s->priv_data;
2638 av_log(s, AV_LOG_DEBUG,
2639 "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2640 stream_index, timestamp, flags);
2641 if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2642 av_log(s, AV_LOG_ERROR,
2643 "Unable to send seek command on stream index %d at timestamp "
2644 "%"PRId64" with flags %08x\n",
2645 stream_index, timestamp, flags);
2648 rt->flv_off = rt->flv_size;
2649 rt->state = STATE_SEEKING;
2653 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2655 RTMPContext *rt = s->priv_data;
2656 int size_temp = size;
2657 int pktsize, pkttype;
2659 const uint8_t *buf_temp = buf;
2664 if (rt->skip_bytes) {
2665 int skip = FFMIN(rt->skip_bytes, size_temp);
2668 rt->skip_bytes -= skip;
2672 if (rt->flv_header_bytes < RTMP_HEADER) {
2673 const uint8_t *header = rt->flv_header;
2674 int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2675 int channel = RTMP_AUDIO_CHANNEL;
2676 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2677 rt->flv_header_bytes += copy;
2679 if (rt->flv_header_bytes < RTMP_HEADER)
2682 pkttype = bytestream_get_byte(&header);
2683 pktsize = bytestream_get_be24(&header);
2684 ts = bytestream_get_be24(&header);
2685 ts |= bytestream_get_byte(&header) << 24;
2686 bytestream_get_be24(&header);
2687 rt->flv_size = pktsize;
2689 if (pkttype == RTMP_PT_VIDEO)
2690 channel = RTMP_VIDEO_CHANNEL;
2692 //force 12bytes header
2693 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2694 pkttype == RTMP_PT_NOTIFY) {
2695 if (pkttype == RTMP_PT_NOTIFY)
2697 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2698 &rt->nb_prev_pkt[1],
2701 rt->prev_pkt[1][channel].channel_id = 0;
2704 //this can be a big packet, it's better to send it right here
2705 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2706 pkttype, ts, pktsize)) < 0)
2709 rt->out_pkt.extra = rt->stream_id;
2710 rt->flv_data = rt->out_pkt.data;
2712 if (pkttype == RTMP_PT_NOTIFY)
2713 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2716 if (rt->flv_size - rt->flv_off > size_temp) {
2717 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2718 rt->flv_off += size_temp;
2721 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2722 size_temp -= rt->flv_size - rt->flv_off;
2723 rt->flv_off += rt->flv_size - rt->flv_off;
2726 if (rt->flv_off == rt->flv_size) {
2729 if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2733 rt->flv_header_bytes = 0;
2734 rt->flv_nb_packets++;
2736 } while (buf_temp - buf < size);
2738 if (rt->flv_nb_packets < rt->flush_interval)
2740 rt->flv_nb_packets = 0;
2742 /* set stream into nonblocking mode */
2743 rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2745 /* try to read one byte from the stream */
2746 ret = ffurl_read(rt->stream, &c, 1);
2748 /* switch the stream back into blocking mode */
2749 rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2751 if (ret == AVERROR(EAGAIN)) {
2752 /* no incoming data to handle */
2754 } else if (ret < 0) {
2756 } else if (ret == 1) {
2757 RTMPPacket rpkt = { 0 };
2759 if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2762 &rt->nb_prev_pkt[0], c)) <= 0)
2765 if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2768 ff_rtmp_packet_destroy(&rpkt);
2774 #define OFFSET(x) offsetof(RTMPContext, x)
2775 #define DEC AV_OPT_FLAG_DECODING_PARAM
2776 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2778 static const AVOption rtmp_options[] = {
2779 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2780 {"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},
2781 {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2782 {"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},
2783 {"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},
2784 {"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"},
2785 {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2786 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2787 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2788 {"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},
2789 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2790 {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2791 {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2792 {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2793 {"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},
2794 {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2795 {"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},
2796 {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2797 {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2798 {"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" },
2802 #define RTMP_PROTOCOL(flavor) \
2803 static const AVClass flavor##_class = { \
2804 .class_name = #flavor, \
2805 .item_name = av_default_item_name, \
2806 .option = rtmp_options, \
2807 .version = LIBAVUTIL_VERSION_INT, \
2810 URLProtocol ff_##flavor##_protocol = { \
2812 .url_open = rtmp_open, \
2813 .url_read = rtmp_read, \
2814 .url_read_seek = rtmp_seek, \
2815 .url_write = rtmp_write, \
2816 .url_close = rtmp_close, \
2817 .priv_data_size = sizeof(RTMPContext), \
2818 .flags = URL_PROTOCOL_FLAG_NETWORK, \
2819 .priv_data_class= &flavor##_class, \
2824 RTMP_PROTOCOL(rtmpe)
2825 RTMP_PROTOCOL(rtmps)
2826 RTMP_PROTOCOL(rtmpt)
2827 RTMP_PROTOCOL(rtmpte)
2828 RTMP_PROTOCOL(rtmpts)