]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
Merge commit '0ce3761c781f2c2de40a5a8a99563878804f47cc'
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Konstantin Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * RTMP protocol
25  */
26
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/hmac.h"
31 #include "libavutil/intfloat.h"
32 #include "libavutil/lfg.h"
33 #include "libavutil/md5.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/random_seed.h"
36 #include "avformat.h"
37 #include "internal.h"
38
39 #include "network.h"
40
41 #include "flv.h"
42 #include "rtmp.h"
43 #include "rtmpcrypt.h"
44 #include "rtmppkt.h"
45 #include "url.h"
46
47 #if CONFIG_ZLIB
48 #include <zlib.h>
49 #endif
50
51 #define APP_MAX_LENGTH 1024
52 #define PLAYPATH_MAX_LENGTH 512
53 #define TCURL_MAX_LENGTH 1024
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56 #define RTMP_HEADER 11
57
58 /** RTMP protocol handler state */
59 typedef enum {
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
69 } ClientState;
70
71 typedef struct TrackedMethod {
72     char *name;
73     int id;
74 } TrackedMethod;
75
76 /** protocol handler context */
77 typedef struct RTMPContext {
78     const AVClass *class;
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      receive_report_size;        ///< number of bytes after which we should report the number of received bytes to the peer
97     uint64_t      bytes_read;                 ///< number of bytes read from server
98     uint64_t      last_bytes_read;            ///< number of bytes read last reported to server
99     uint32_t      last_timestamp;             ///< last timestamp received in a packet
100     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
101     int           has_audio;                  ///< presence of audio data
102     int           has_video;                  ///< presence of video data
103     int           received_metadata;          ///< Indicates if we have received metadata about the streams
104     uint8_t       flv_header[RTMP_HEADER];    ///< partial incoming flv packet header
105     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
106     int           nb_invokes;                 ///< keeps track of invoke messages
107     char*         tcurl;                      ///< url of the target stream
108     char*         flashver;                   ///< version of the flash plugin
109     char*         swfhash;                    ///< SHA256 hash of the decompressed SWF file (32 bytes)
110     int           swfhash_len;                ///< length of the SHA256 hash
111     int           swfsize;                    ///< size of the decompressed SWF file
112     char*         swfurl;                     ///< url of the swf player
113     char*         swfverify;                  ///< URL to player swf file, compute hash/size automatically
114     char          swfverification[42];        ///< hash of the SWF verification
115     char*         pageurl;                    ///< url of the web page
116     char*         subscribe;                  ///< name of live stream to subscribe
117     int           max_sent_unacked;           ///< max unacked sent bytes
118     int           client_buffer_time;         ///< client buffer time in ms
119     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
120     int           encrypted;                  ///< use an encrypted connection (RTMPE only)
121     TrackedMethod*tracked_methods;            ///< tracked methods buffer
122     int           nb_tracked_methods;         ///< number of tracked methods
123     int           tracked_methods_size;       ///< size of the tracked methods buffer
124     int           listen;                     ///< listen mode flag
125     int           listen_timeout;             ///< listen timeout to wait for new connections
126     int           nb_streamid;                ///< The next stream id to return on createStream calls
127     double        duration;                   ///< Duration of the stream in seconds as returned by the server (only valid if non-zero)
128     char          username[50];
129     char          password[50];
130     char          auth_params[500];
131     int           do_reconnect;
132     int           auth_tried;
133 } RTMPContext;
134
135 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
136 /** Client key used for digest signing */
137 static const uint8_t rtmp_player_key[] = {
138     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
139     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
140
141     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
142     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
143     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
144 };
145
146 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
147 /** Key used for RTMP server digest signing */
148 static const uint8_t rtmp_server_key[] = {
149     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
150     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
151     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
152
153     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
154     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
155     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
156 };
157
158 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
159 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt);
160 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt);
161
162 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
163 {
164     int err;
165
166     if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
167         rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
168         if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
169                                sizeof(*rt->tracked_methods))) < 0) {
170             rt->nb_tracked_methods = 0;
171             rt->tracked_methods_size = 0;
172             return err;
173         }
174     }
175
176     rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
177     if (!rt->tracked_methods[rt->nb_tracked_methods].name)
178         return AVERROR(ENOMEM);
179     rt->tracked_methods[rt->nb_tracked_methods].id = id;
180     rt->nb_tracked_methods++;
181
182     return 0;
183 }
184
185 static void del_tracked_method(RTMPContext *rt, int index)
186 {
187     memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
188             sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
189     rt->nb_tracked_methods--;
190 }
191
192 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
193                                char **tracked_method)
194 {
195     RTMPContext *rt = s->priv_data;
196     GetByteContext gbc;
197     double pkt_id;
198     int ret;
199     int i;
200
201     bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
202     if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
203         return ret;
204
205     for (i = 0; i < rt->nb_tracked_methods; i++) {
206         if (rt->tracked_methods[i].id != pkt_id)
207             continue;
208
209         *tracked_method = rt->tracked_methods[i].name;
210         del_tracked_method(rt, i);
211         break;
212     }
213
214     return 0;
215 }
216
217 static void free_tracked_methods(RTMPContext *rt)
218 {
219     int i;
220
221     for (i = 0; i < rt->nb_tracked_methods; i ++)
222         av_freep(&rt->tracked_methods[i].name);
223     av_freep(&rt->tracked_methods);
224     rt->tracked_methods_size = 0;
225     rt->nb_tracked_methods   = 0;
226 }
227
228 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
229 {
230     int ret;
231
232     if (pkt->type == RTMP_PT_INVOKE && track) {
233         GetByteContext gbc;
234         char name[128];
235         double pkt_id;
236         int len;
237
238         bytestream2_init(&gbc, pkt->data, pkt->size);
239         if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
240             goto fail;
241
242         if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
243             goto fail;
244
245         if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
246             goto fail;
247     }
248
249     ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
250                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
251 fail:
252     ff_rtmp_packet_destroy(pkt);
253     return ret;
254 }
255
256 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
257 {
258     char *field, *value;
259     char type;
260
261     /* The type must be B for Boolean, N for number, S for string, O for
262      * object, or Z for null. For Booleans the data must be either 0 or 1 for
263      * FALSE or TRUE, respectively. Likewise for Objects the data must be
264      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
265      * may be named, by prefixing the type with 'N' and specifying the name
266      * before the value (ie. NB:myFlag:1). This option may be used multiple times
267      * to construct arbitrary AMF sequences. */
268     if (param[0] && param[1] == ':') {
269         type = param[0];
270         value = param + 2;
271     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
272         type = param[1];
273         field = param + 3;
274         value = strchr(field, ':');
275         if (!value)
276             goto fail;
277         *value = '\0';
278         value++;
279
280         ff_amf_write_field_name(p, field);
281     } else {
282         goto fail;
283     }
284
285     switch (type) {
286     case 'B':
287         ff_amf_write_bool(p, value[0] != '0');
288         break;
289     case 'S':
290         ff_amf_write_string(p, value);
291         break;
292     case 'N':
293         ff_amf_write_number(p, strtod(value, NULL));
294         break;
295     case 'Z':
296         ff_amf_write_null(p);
297         break;
298     case 'O':
299         if (value[0] != '0')
300             ff_amf_write_object_start(p);
301         else
302             ff_amf_write_object_end(p);
303         break;
304     default:
305         goto fail;
306         break;
307     }
308
309     return 0;
310
311 fail:
312     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
313     return AVERROR(EINVAL);
314 }
315
316 /**
317  * Generate 'connect' call and send it to the server.
318  */
319 static int gen_connect(URLContext *s, RTMPContext *rt)
320 {
321     RTMPPacket pkt;
322     uint8_t *p;
323     int ret;
324
325     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
326                                      0, 4096 + APP_MAX_LENGTH)) < 0)
327         return ret;
328
329     p = pkt.data;
330
331     ff_amf_write_string(&p, "connect");
332     ff_amf_write_number(&p, ++rt->nb_invokes);
333     ff_amf_write_object_start(&p);
334     ff_amf_write_field_name(&p, "app");
335     ff_amf_write_string2(&p, rt->app, rt->auth_params);
336
337     if (!rt->is_input) {
338         ff_amf_write_field_name(&p, "type");
339         ff_amf_write_string(&p, "nonprivate");
340     }
341     ff_amf_write_field_name(&p, "flashVer");
342     ff_amf_write_string(&p, rt->flashver);
343
344     if (rt->swfurl || rt->swfverify) {
345         ff_amf_write_field_name(&p, "swfUrl");
346         if (rt->swfurl)
347             ff_amf_write_string(&p, rt->swfurl);
348         else
349             ff_amf_write_string(&p, rt->swfverify);
350     }
351
352     ff_amf_write_field_name(&p, "tcUrl");
353     ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
354     if (rt->is_input) {
355         ff_amf_write_field_name(&p, "fpad");
356         ff_amf_write_bool(&p, 0);
357         ff_amf_write_field_name(&p, "capabilities");
358         ff_amf_write_number(&p, 15.0);
359
360         /* Tell the server we support all the audio codecs except
361          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
362          * which are unused in the RTMP protocol implementation. */
363         ff_amf_write_field_name(&p, "audioCodecs");
364         ff_amf_write_number(&p, 4071.0);
365         ff_amf_write_field_name(&p, "videoCodecs");
366         ff_amf_write_number(&p, 252.0);
367         ff_amf_write_field_name(&p, "videoFunction");
368         ff_amf_write_number(&p, 1.0);
369
370         if (rt->pageurl) {
371             ff_amf_write_field_name(&p, "pageUrl");
372             ff_amf_write_string(&p, rt->pageurl);
373         }
374     }
375     ff_amf_write_object_end(&p);
376
377     if (rt->conn) {
378         char *param = rt->conn;
379
380         // Write arbitrary AMF data to the Connect message.
381         while (param) {
382             char *sep;
383             param += strspn(param, " ");
384             if (!*param)
385                 break;
386             sep = strchr(param, ' ');
387             if (sep)
388                 *sep = '\0';
389             if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
390                 // Invalid AMF parameter.
391                 ff_rtmp_packet_destroy(&pkt);
392                 return ret;
393             }
394
395             if (sep)
396                 param = sep + 1;
397             else
398                 break;
399         }
400     }
401
402     pkt.size = p - pkt.data;
403
404     return rtmp_send_packet(rt, &pkt, 1);
405 }
406
407
408 #define RTMP_CTRL_ABORT_MESSAGE  (2)
409
410 static int read_connect(URLContext *s, RTMPContext *rt)
411 {
412     RTMPPacket pkt = { 0 };
413     uint8_t *p;
414     const uint8_t *cp;
415     int ret;
416     char command[64];
417     int stringlen;
418     double seqnum;
419     uint8_t tmpstr[256];
420     GetByteContext gbc;
421
422     // handle RTMP Protocol Control Messages
423     for (;;) {
424         if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
425                                        &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
426             return ret;
427 #ifdef DEBUG
428         ff_rtmp_packet_dump(s, &pkt);
429 #endif
430         if (pkt.type == RTMP_PT_CHUNK_SIZE) {
431             if ((ret = handle_chunk_size(s, &pkt)) < 0) {
432                 ff_rtmp_packet_destroy(&pkt);
433                 return ret;
434             }
435         } else if (pkt.type == RTMP_CTRL_ABORT_MESSAGE) {
436             av_log(s, AV_LOG_ERROR, "received abort message\n");
437             ff_rtmp_packet_destroy(&pkt);
438             return AVERROR_UNKNOWN;
439         } else if (pkt.type == RTMP_PT_BYTES_READ) {
440             av_log(s, AV_LOG_TRACE, "received acknowledgement\n");
441         } else if (pkt.type == RTMP_PT_WINDOW_ACK_SIZE) {
442             if ((ret = handle_window_ack_size(s, &pkt)) < 0) {
443                 ff_rtmp_packet_destroy(&pkt);
444                 return ret;
445             }
446         } else if (pkt.type == RTMP_PT_SET_PEER_BW) {
447             if ((ret = handle_set_peer_bw(s, &pkt)) < 0) {
448                 ff_rtmp_packet_destroy(&pkt);
449                 return ret;
450             }
451         } else if (pkt.type == RTMP_PT_INVOKE) {
452             // received RTMP Command Message
453             break;
454         } else {
455             av_log(s, AV_LOG_ERROR, "Unknown control message type (%d)\n", pkt.type);
456         }
457         ff_rtmp_packet_destroy(&pkt);
458     }
459
460     cp = pkt.data;
461     bytestream2_init(&gbc, cp, pkt.size);
462     if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
463         av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
464         ff_rtmp_packet_destroy(&pkt);
465         return AVERROR_INVALIDDATA;
466     }
467     if (strcmp(command, "connect")) {
468         av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
469         ff_rtmp_packet_destroy(&pkt);
470         return AVERROR_INVALIDDATA;
471     }
472     ret = ff_amf_read_number(&gbc, &seqnum);
473     if (ret)
474         av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
475     /* Here one could parse an AMF Object with data as flashVers and others. */
476     ret = ff_amf_get_field_value(gbc.buffer,
477                                  gbc.buffer + bytestream2_get_bytes_left(&gbc),
478                                  "app", tmpstr, sizeof(tmpstr));
479     if (ret)
480         av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
481     if (!ret && strcmp(tmpstr, rt->app))
482         av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
483                tmpstr, rt->app);
484     ff_rtmp_packet_destroy(&pkt);
485
486     // Send Window Acknowledgement Size (as defined in specification)
487     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
488                                      RTMP_PT_WINDOW_ACK_SIZE, 0, 4)) < 0)
489         return ret;
490     p = pkt.data;
491     // Inform the peer about how often we want acknowledgements about what
492     // we send. (We don't check for the acknowledgements currently.)
493     bytestream_put_be32(&p, rt->max_sent_unacked);
494     pkt.size = p - pkt.data;
495     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
496                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
497     ff_rtmp_packet_destroy(&pkt);
498     if (ret < 0)
499         return ret;
500     // Set Peer Bandwidth
501     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
502                                      RTMP_PT_SET_PEER_BW, 0, 5)) < 0)
503         return ret;
504     p = pkt.data;
505     // Tell the peer to only send this many bytes unless it gets acknowledgements.
506     // This could be any arbitrary value we want here.
507     bytestream_put_be32(&p, rt->max_sent_unacked);
508     bytestream_put_byte(&p, 2); // dynamic
509     pkt.size = p - pkt.data;
510     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
511                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
512     ff_rtmp_packet_destroy(&pkt);
513     if (ret < 0)
514         return ret;
515
516     // User control
517     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
518                                      RTMP_PT_USER_CONTROL, 0, 6)) < 0)
519         return ret;
520
521     p = pkt.data;
522     bytestream_put_be16(&p, 0); // 0 -> Stream Begin
523     bytestream_put_be32(&p, 0); // Stream 0
524     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
525                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
526     ff_rtmp_packet_destroy(&pkt);
527     if (ret < 0)
528         return ret;
529
530     // Chunk size
531     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
532                                      RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
533         return ret;
534
535     p = pkt.data;
536     bytestream_put_be32(&p, rt->out_chunk_size);
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);
540     if (ret < 0)
541         return ret;
542
543     // Send _result NetConnection.Connect.Success to connect
544     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
545                                      RTMP_PT_INVOKE, 0,
546                                      RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
547         return ret;
548
549     p = pkt.data;
550     ff_amf_write_string(&p, "_result");
551     ff_amf_write_number(&p, seqnum);
552
553     ff_amf_write_object_start(&p);
554     ff_amf_write_field_name(&p, "fmsVer");
555     ff_amf_write_string(&p, "FMS/3,0,1,123");
556     ff_amf_write_field_name(&p, "capabilities");
557     ff_amf_write_number(&p, 31);
558     ff_amf_write_object_end(&p);
559
560     ff_amf_write_object_start(&p);
561     ff_amf_write_field_name(&p, "level");
562     ff_amf_write_string(&p, "status");
563     ff_amf_write_field_name(&p, "code");
564     ff_amf_write_string(&p, "NetConnection.Connect.Success");
565     ff_amf_write_field_name(&p, "description");
566     ff_amf_write_string(&p, "Connection succeeded.");
567     ff_amf_write_field_name(&p, "objectEncoding");
568     ff_amf_write_number(&p, 0);
569     ff_amf_write_object_end(&p);
570
571     pkt.size = p - pkt.data;
572     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
573                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
574     ff_rtmp_packet_destroy(&pkt);
575     if (ret < 0)
576         return ret;
577
578     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
579                                      RTMP_PT_INVOKE, 0, 30)) < 0)
580         return ret;
581     p = pkt.data;
582     ff_amf_write_string(&p, "onBWDone");
583     ff_amf_write_number(&p, 0);
584     ff_amf_write_null(&p);
585     ff_amf_write_number(&p, 8192);
586     pkt.size = p - pkt.data;
587     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
588                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
589     ff_rtmp_packet_destroy(&pkt);
590
591     return ret;
592 }
593
594 /**
595  * Generate 'releaseStream' call and send it to the server. It should make
596  * the server release some channel for media streams.
597  */
598 static int gen_release_stream(URLContext *s, RTMPContext *rt)
599 {
600     RTMPPacket pkt;
601     uint8_t *p;
602     int ret;
603
604     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
605                                      0, 29 + strlen(rt->playpath))) < 0)
606         return ret;
607
608     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
609     p = pkt.data;
610     ff_amf_write_string(&p, "releaseStream");
611     ff_amf_write_number(&p, ++rt->nb_invokes);
612     ff_amf_write_null(&p);
613     ff_amf_write_string(&p, rt->playpath);
614
615     return rtmp_send_packet(rt, &pkt, 1);
616 }
617
618 /**
619  * Generate 'FCPublish' call and send it to the server. It should make
620  * the server prepare for receiving media streams.
621  */
622 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
623 {
624     RTMPPacket pkt;
625     uint8_t *p;
626     int ret;
627
628     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
629                                      0, 25 + strlen(rt->playpath))) < 0)
630         return ret;
631
632     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
633     p = pkt.data;
634     ff_amf_write_string(&p, "FCPublish");
635     ff_amf_write_number(&p, ++rt->nb_invokes);
636     ff_amf_write_null(&p);
637     ff_amf_write_string(&p, rt->playpath);
638
639     return rtmp_send_packet(rt, &pkt, 1);
640 }
641
642 /**
643  * Generate 'FCUnpublish' call and send it to the server. It should make
644  * the server destroy stream.
645  */
646 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
647 {
648     RTMPPacket pkt;
649     uint8_t *p;
650     int ret;
651
652     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
653                                      0, 27 + strlen(rt->playpath))) < 0)
654         return ret;
655
656     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
657     p = pkt.data;
658     ff_amf_write_string(&p, "FCUnpublish");
659     ff_amf_write_number(&p, ++rt->nb_invokes);
660     ff_amf_write_null(&p);
661     ff_amf_write_string(&p, rt->playpath);
662
663     return rtmp_send_packet(rt, &pkt, 0);
664 }
665
666 /**
667  * Generate 'createStream' call and send it to the server. It should make
668  * the server allocate some channel for media streams.
669  */
670 static int gen_create_stream(URLContext *s, RTMPContext *rt)
671 {
672     RTMPPacket pkt;
673     uint8_t *p;
674     int ret;
675
676     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
677
678     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
679                                      0, 25)) < 0)
680         return ret;
681
682     p = pkt.data;
683     ff_amf_write_string(&p, "createStream");
684     ff_amf_write_number(&p, ++rt->nb_invokes);
685     ff_amf_write_null(&p);
686
687     return rtmp_send_packet(rt, &pkt, 1);
688 }
689
690
691 /**
692  * Generate 'deleteStream' call and send it to the server. It should make
693  * the server remove some channel for media streams.
694  */
695 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
696 {
697     RTMPPacket pkt;
698     uint8_t *p;
699     int ret;
700
701     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
702
703     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
704                                      0, 34)) < 0)
705         return ret;
706
707     p = pkt.data;
708     ff_amf_write_string(&p, "deleteStream");
709     ff_amf_write_number(&p, ++rt->nb_invokes);
710     ff_amf_write_null(&p);
711     ff_amf_write_number(&p, rt->stream_id);
712
713     return rtmp_send_packet(rt, &pkt, 0);
714 }
715
716 /**
717  * Generate 'getStreamLength' call and send it to the server. If the server
718  * knows the duration of the selected stream, it will reply with the duration
719  * in seconds.
720  */
721 static int gen_get_stream_length(URLContext *s, RTMPContext *rt)
722 {
723     RTMPPacket pkt;
724     uint8_t *p;
725     int ret;
726
727     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
728                                      0, 31 + strlen(rt->playpath))) < 0)
729         return ret;
730
731     p = pkt.data;
732     ff_amf_write_string(&p, "getStreamLength");
733     ff_amf_write_number(&p, ++rt->nb_invokes);
734     ff_amf_write_null(&p);
735     ff_amf_write_string(&p, rt->playpath);
736
737     return rtmp_send_packet(rt, &pkt, 1);
738 }
739
740 /**
741  * Generate client buffer time and send it to the server.
742  */
743 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
744 {
745     RTMPPacket pkt;
746     uint8_t *p;
747     int ret;
748
749     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
750                                      1, 10)) < 0)
751         return ret;
752
753     p = pkt.data;
754     bytestream_put_be16(&p, 3); // SetBuffer Length
755     bytestream_put_be32(&p, rt->stream_id);
756     bytestream_put_be32(&p, rt->client_buffer_time);
757
758     return rtmp_send_packet(rt, &pkt, 0);
759 }
760
761 /**
762  * Generate 'play' call and send it to the server, then ping the server
763  * to start actual playing.
764  */
765 static int gen_play(URLContext *s, RTMPContext *rt)
766 {
767     RTMPPacket pkt;
768     uint8_t *p;
769     int ret;
770
771     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
772
773     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
774                                      0, 29 + strlen(rt->playpath))) < 0)
775         return ret;
776
777     pkt.extra = rt->stream_id;
778
779     p = pkt.data;
780     ff_amf_write_string(&p, "play");
781     ff_amf_write_number(&p, ++rt->nb_invokes);
782     ff_amf_write_null(&p);
783     ff_amf_write_string(&p, rt->playpath);
784     ff_amf_write_number(&p, rt->live * 1000);
785
786     return rtmp_send_packet(rt, &pkt, 1);
787 }
788
789 static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
790 {
791     RTMPPacket pkt;
792     uint8_t *p;
793     int ret;
794
795     av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
796            timestamp);
797
798     if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
799         return ret;
800
801     pkt.extra = rt->stream_id;
802
803     p = pkt.data;
804     ff_amf_write_string(&p, "seek");
805     ff_amf_write_number(&p, 0); //no tracking back responses
806     ff_amf_write_null(&p); //as usual, the first null param
807     ff_amf_write_number(&p, timestamp); //where we want to jump
808
809     return rtmp_send_packet(rt, &pkt, 1);
810 }
811
812 /**
813  * Generate a pause packet that either pauses or unpauses the current stream.
814  */
815 static int gen_pause(URLContext *s, RTMPContext *rt, int pause, uint32_t timestamp)
816 {
817     RTMPPacket pkt;
818     uint8_t *p;
819     int ret;
820
821     av_log(s, AV_LOG_DEBUG, "Sending pause command for timestamp %d\n",
822            timestamp);
823
824     if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 29)) < 0)
825         return ret;
826
827     pkt.extra = rt->stream_id;
828
829     p = pkt.data;
830     ff_amf_write_string(&p, "pause");
831     ff_amf_write_number(&p, 0); //no tracking back responses
832     ff_amf_write_null(&p); //as usual, the first null param
833     ff_amf_write_bool(&p, pause); // pause or unpause
834     ff_amf_write_number(&p, timestamp); //where we pause the stream
835
836     return rtmp_send_packet(rt, &pkt, 1);
837 }
838
839 /**
840  * Generate 'publish' call and send it to the server.
841  */
842 static int gen_publish(URLContext *s, RTMPContext *rt)
843 {
844     RTMPPacket pkt;
845     uint8_t *p;
846     int ret;
847
848     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
849
850     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
851                                      0, 30 + strlen(rt->playpath))) < 0)
852         return ret;
853
854     pkt.extra = rt->stream_id;
855
856     p = pkt.data;
857     ff_amf_write_string(&p, "publish");
858     ff_amf_write_number(&p, ++rt->nb_invokes);
859     ff_amf_write_null(&p);
860     ff_amf_write_string(&p, rt->playpath);
861     ff_amf_write_string(&p, "live");
862
863     return rtmp_send_packet(rt, &pkt, 1);
864 }
865
866 /**
867  * Generate ping reply and send it to the server.
868  */
869 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
870 {
871     RTMPPacket pkt;
872     uint8_t *p;
873     int ret;
874
875     if (ppkt->size < 6) {
876         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
877                ppkt->size);
878         return AVERROR_INVALIDDATA;
879     }
880
881     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,RTMP_PT_USER_CONTROL,
882                                      ppkt->timestamp + 1, 6)) < 0)
883         return ret;
884
885     p = pkt.data;
886     bytestream_put_be16(&p, 7); // PingResponse
887     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
888
889     return rtmp_send_packet(rt, &pkt, 0);
890 }
891
892 /**
893  * Generate SWF verification message and send it to the server.
894  */
895 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
896 {
897     RTMPPacket pkt;
898     uint8_t *p;
899     int ret;
900
901     av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
902     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_USER_CONTROL,
903                                      0, 44)) < 0)
904         return ret;
905
906     p = pkt.data;
907     bytestream_put_be16(&p, 27);
908     memcpy(p, rt->swfverification, 42);
909
910     return rtmp_send_packet(rt, &pkt, 0);
911 }
912
913 /**
914  * Generate window acknowledgement size message and send it to the server.
915  */
916 static int gen_window_ack_size(URLContext *s, RTMPContext *rt)
917 {
918     RTMPPacket pkt;
919     uint8_t *p;
920     int ret;
921
922     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_WINDOW_ACK_SIZE,
923                                      0, 4)) < 0)
924         return ret;
925
926     p = pkt.data;
927     bytestream_put_be32(&p, rt->max_sent_unacked);
928
929     return rtmp_send_packet(rt, &pkt, 0);
930 }
931
932 /**
933  * Generate check bandwidth message and send it to the server.
934  */
935 static int gen_check_bw(URLContext *s, RTMPContext *rt)
936 {
937     RTMPPacket pkt;
938     uint8_t *p;
939     int ret;
940
941     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
942                                      0, 21)) < 0)
943         return ret;
944
945     p = pkt.data;
946     ff_amf_write_string(&p, "_checkbw");
947     ff_amf_write_number(&p, ++rt->nb_invokes);
948     ff_amf_write_null(&p);
949
950     return rtmp_send_packet(rt, &pkt, 1);
951 }
952
953 /**
954  * Generate report on bytes read so far and send it to the server.
955  */
956 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
957 {
958     RTMPPacket pkt;
959     uint8_t *p;
960     int ret;
961
962     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
963                                      ts, 4)) < 0)
964         return ret;
965
966     p = pkt.data;
967     bytestream_put_be32(&p, rt->bytes_read);
968
969     return rtmp_send_packet(rt, &pkt, 0);
970 }
971
972 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
973                                   const char *subscribe)
974 {
975     RTMPPacket pkt;
976     uint8_t *p;
977     int ret;
978
979     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
980                                      0, 27 + strlen(subscribe))) < 0)
981         return ret;
982
983     p = pkt.data;
984     ff_amf_write_string(&p, "FCSubscribe");
985     ff_amf_write_number(&p, ++rt->nb_invokes);
986     ff_amf_write_null(&p);
987     ff_amf_write_string(&p, subscribe);
988
989     return rtmp_send_packet(rt, &pkt, 1);
990 }
991
992 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
993                         const uint8_t *key, int keylen, uint8_t *dst)
994 {
995     AVHMAC *hmac;
996
997     hmac = av_hmac_alloc(AV_HMAC_SHA256);
998     if (!hmac)
999         return AVERROR(ENOMEM);
1000
1001     av_hmac_init(hmac, key, keylen);
1002     if (gap <= 0) {
1003         av_hmac_update(hmac, src, len);
1004     } else { //skip 32 bytes used for storing digest
1005         av_hmac_update(hmac, src, gap);
1006         av_hmac_update(hmac, src + gap + 32, len - gap - 32);
1007     }
1008     av_hmac_final(hmac, dst, 32);
1009
1010     av_hmac_free(hmac);
1011
1012     return 0;
1013 }
1014
1015 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
1016                             int add_val)
1017 {
1018     int i, digest_pos = 0;
1019
1020     for (i = 0; i < 4; i++)
1021         digest_pos += buf[i + off];
1022     digest_pos = digest_pos % mod_val + add_val;
1023
1024     return digest_pos;
1025 }
1026
1027 /**
1028  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
1029  * will be stored) into that packet.
1030  *
1031  * @param buf handshake data (1536 bytes)
1032  * @param encrypted use an encrypted connection (RTMPE)
1033  * @return offset to the digest inside input data
1034  */
1035 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
1036 {
1037     int ret, digest_pos;
1038
1039     if (encrypted)
1040         digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
1041     else
1042         digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
1043
1044     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1045                               rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
1046                               buf + digest_pos);
1047     if (ret < 0)
1048         return ret;
1049
1050     return digest_pos;
1051 }
1052
1053 /**
1054  * Verify that the received server response has the expected digest value.
1055  *
1056  * @param buf handshake data received from the server (1536 bytes)
1057  * @param off position to search digest offset from
1058  * @return 0 if digest is valid, digest position otherwise
1059  */
1060 static int rtmp_validate_digest(uint8_t *buf, int off)
1061 {
1062     uint8_t digest[32];
1063     int ret, digest_pos;
1064
1065     digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
1066
1067     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
1068                               rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
1069                               digest);
1070     if (ret < 0)
1071         return ret;
1072
1073     if (!memcmp(digest, buf + digest_pos, 32))
1074         return digest_pos;
1075     return 0;
1076 }
1077
1078 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
1079                                       uint8_t *buf)
1080 {
1081     uint8_t *p;
1082     int ret;
1083
1084     if (rt->swfhash_len != 32) {
1085         av_log(s, AV_LOG_ERROR,
1086                "Hash of the decompressed SWF file is not 32 bytes long.\n");
1087         return AVERROR(EINVAL);
1088     }
1089
1090     p = &rt->swfverification[0];
1091     bytestream_put_byte(&p, 1);
1092     bytestream_put_byte(&p, 1);
1093     bytestream_put_be32(&p, rt->swfsize);
1094     bytestream_put_be32(&p, rt->swfsize);
1095
1096     if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1097         return ret;
1098
1099     return 0;
1100 }
1101
1102 #if CONFIG_ZLIB
1103 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1104                                      uint8_t **out_data, int64_t *out_size)
1105 {
1106     z_stream zs = { 0 };
1107     void *ptr;
1108     int size;
1109     int ret = 0;
1110
1111     zs.avail_in = in_size;
1112     zs.next_in  = in_data;
1113     ret = inflateInit(&zs);
1114     if (ret != Z_OK)
1115         return AVERROR_UNKNOWN;
1116
1117     do {
1118         uint8_t tmp_buf[16384];
1119
1120         zs.avail_out = sizeof(tmp_buf);
1121         zs.next_out  = tmp_buf;
1122
1123         ret = inflate(&zs, Z_NO_FLUSH);
1124         if (ret != Z_OK && ret != Z_STREAM_END) {
1125             ret = AVERROR_UNKNOWN;
1126             goto fail;
1127         }
1128
1129         size = sizeof(tmp_buf) - zs.avail_out;
1130         if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1131             ret = AVERROR(ENOMEM);
1132             goto fail;
1133         }
1134         *out_data = ptr;
1135
1136         memcpy(*out_data + *out_size, tmp_buf, size);
1137         *out_size += size;
1138     } while (zs.avail_out == 0);
1139
1140 fail:
1141     inflateEnd(&zs);
1142     return ret;
1143 }
1144 #endif
1145
1146 static int rtmp_calc_swfhash(URLContext *s)
1147 {
1148     RTMPContext *rt = s->priv_data;
1149     uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1150     int64_t in_size;
1151     URLContext *stream;
1152     char swfhash[32];
1153     int swfsize;
1154     int ret = 0;
1155
1156     /* Get the SWF player file. */
1157     if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
1158                                     &s->interrupt_callback, NULL,
1159                                     s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
1160         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1161         goto fail;
1162     }
1163
1164     if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1165         ret = AVERROR(EIO);
1166         goto fail;
1167     }
1168
1169     if (!(in_data = av_malloc(in_size))) {
1170         ret = AVERROR(ENOMEM);
1171         goto fail;
1172     }
1173
1174     if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1175         goto fail;
1176
1177     if (in_size < 3) {
1178         ret = AVERROR_INVALIDDATA;
1179         goto fail;
1180     }
1181
1182     if (!memcmp(in_data, "CWS", 3)) {
1183 #if CONFIG_ZLIB
1184         int64_t out_size;
1185         /* Decompress the SWF player file using Zlib. */
1186         if (!(out_data = av_malloc(8))) {
1187             ret = AVERROR(ENOMEM);
1188             goto fail;
1189         }
1190         *in_data = 'F'; // magic stuff
1191         memcpy(out_data, in_data, 8);
1192         out_size = 8;
1193
1194         if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1195                                              &out_data, &out_size)) < 0)
1196             goto fail;
1197         swfsize = out_size;
1198         swfdata = out_data;
1199 #else
1200         av_log(s, AV_LOG_ERROR,
1201                "Zlib is required for decompressing the SWF player file.\n");
1202         ret = AVERROR(EINVAL);
1203         goto fail;
1204 #endif
1205     } else {
1206         swfsize = in_size;
1207         swfdata = in_data;
1208     }
1209
1210     /* Compute the SHA256 hash of the SWF player file. */
1211     if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1212                                    "Genuine Adobe Flash Player 001", 30,
1213                                    swfhash)) < 0)
1214         goto fail;
1215
1216     /* Set SWFVerification parameters. */
1217     av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1218     rt->swfsize = swfsize;
1219
1220 fail:
1221     av_freep(&in_data);
1222     av_freep(&out_data);
1223     ffurl_close(stream);
1224     return ret;
1225 }
1226
1227 /**
1228  * Perform handshake with the server by means of exchanging pseudorandom data
1229  * signed with HMAC-SHA2 digest.
1230  *
1231  * @return 0 if handshake succeeds, negative value otherwise
1232  */
1233 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1234 {
1235     AVLFG rnd;
1236     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1237         3,                // unencrypted data
1238         0, 0, 0, 0,       // client uptime
1239         RTMP_CLIENT_VER1,
1240         RTMP_CLIENT_VER2,
1241         RTMP_CLIENT_VER3,
1242         RTMP_CLIENT_VER4,
1243     };
1244     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1245     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1246     int i;
1247     int server_pos, client_pos;
1248     uint8_t digest[32], signature[32];
1249     int ret, type = 0;
1250
1251     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1252
1253     av_lfg_init(&rnd, 0xDEADC0DE);
1254     // generate handshake packet - 1536 bytes of pseudorandom data
1255     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1256         tosend[i] = av_lfg_get(&rnd) >> 24;
1257
1258     if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1259         /* When the client wants to use RTMPE, we have to change the command
1260          * byte to 0x06 which means to use encrypted data and we have to set
1261          * the flash version to at least 9.0.115.0. */
1262         tosend[0] = 6;
1263         tosend[5] = 128;
1264         tosend[6] = 0;
1265         tosend[7] = 3;
1266         tosend[8] = 2;
1267
1268         /* Initialize the Diffie-Hellmann context and generate the public key
1269          * to send to the server. */
1270         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1271             return ret;
1272     }
1273
1274     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1275     if (client_pos < 0)
1276         return client_pos;
1277
1278     if ((ret = ffurl_write(rt->stream, tosend,
1279                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1280         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1281         return ret;
1282     }
1283
1284     if ((ret = ffurl_read_complete(rt->stream, serverdata,
1285                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1286         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1287         return ret;
1288     }
1289
1290     if ((ret = ffurl_read_complete(rt->stream, clientdata,
1291                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1292         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1293         return ret;
1294     }
1295
1296     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1297     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1298            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1299
1300     if (rt->is_input && serverdata[5] >= 3) {
1301         server_pos = rtmp_validate_digest(serverdata + 1, 772);
1302         if (server_pos < 0)
1303             return server_pos;
1304
1305         if (!server_pos) {
1306             type = 1;
1307             server_pos = rtmp_validate_digest(serverdata + 1, 8);
1308             if (server_pos < 0)
1309                 return server_pos;
1310
1311             if (!server_pos) {
1312                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1313                 return AVERROR(EIO);
1314             }
1315         }
1316
1317         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1318          * key are the last 32 bytes of the server handshake. */
1319         if (rt->swfsize) {
1320             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1321                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1322                 return ret;
1323         }
1324
1325         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1326                                   rtmp_server_key, sizeof(rtmp_server_key),
1327                                   digest);
1328         if (ret < 0)
1329             return ret;
1330
1331         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1332                                   0, digest, 32, signature);
1333         if (ret < 0)
1334             return ret;
1335
1336         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1337             /* Compute the shared secret key sent by the server and initialize
1338              * the RC4 encryption. */
1339             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1340                                                    tosend + 1, type)) < 0)
1341                 return ret;
1342
1343             /* Encrypt the signature received by the server. */
1344             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1345         }
1346
1347         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1348             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1349             return AVERROR(EIO);
1350         }
1351
1352         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1353             tosend[i] = av_lfg_get(&rnd) >> 24;
1354         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1355                                   rtmp_player_key, sizeof(rtmp_player_key),
1356                                   digest);
1357         if (ret < 0)
1358             return ret;
1359
1360         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1361                                   digest, 32,
1362                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1363         if (ret < 0)
1364             return ret;
1365
1366         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1367             /* Encrypt the signature to be send to the server. */
1368             ff_rtmpe_encrypt_sig(rt->stream, tosend +
1369                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1370                                  serverdata[0]);
1371         }
1372
1373         // write reply back to the server
1374         if ((ret = ffurl_write(rt->stream, tosend,
1375                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1376             return ret;
1377
1378         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1379             /* Set RC4 keys for encryption and update the keystreams. */
1380             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1381                 return ret;
1382         }
1383     } else {
1384         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1385             /* Compute the shared secret key sent by the server and initialize
1386              * the RC4 encryption. */
1387             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1388                             tosend + 1, 1)) < 0)
1389                 return ret;
1390
1391             if (serverdata[0] == 9) {
1392                 /* Encrypt the signature received by the server. */
1393                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1394                                      serverdata[0]);
1395             }
1396         }
1397
1398         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1399                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1400             return ret;
1401
1402         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1403             /* Set RC4 keys for encryption and update the keystreams. */
1404             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1405                 return ret;
1406         }
1407     }
1408
1409     return 0;
1410 }
1411
1412 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1413                                   uint32_t *second_int, char *arraydata,
1414                                   int size)
1415 {
1416     int inoutsize;
1417
1418     inoutsize = ffurl_read_complete(rt->stream, arraydata,
1419                                     RTMP_HANDSHAKE_PACKET_SIZE);
1420     if (inoutsize <= 0)
1421         return AVERROR(EIO);
1422     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1423         av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1424                " not following standard\n", (int)inoutsize);
1425         return AVERROR(EINVAL);
1426     }
1427
1428     *first_int  = AV_RB32(arraydata);
1429     *second_int = AV_RB32(arraydata + 4);
1430     return 0;
1431 }
1432
1433 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1434                                uint32_t second_int, char *arraydata, int size)
1435 {
1436     int inoutsize;
1437
1438     AV_WB32(arraydata, first_int);
1439     AV_WB32(arraydata + 4, second_int);
1440     inoutsize = ffurl_write(rt->stream, arraydata,
1441                             RTMP_HANDSHAKE_PACKET_SIZE);
1442     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1443         av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1444         return AVERROR(EIO);
1445     }
1446
1447     return 0;
1448 }
1449
1450 /**
1451  * rtmp handshake server side
1452  */
1453 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1454 {
1455     uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1456     uint32_t hs_epoch;
1457     uint32_t hs_my_epoch;
1458     uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1459     uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1460     uint32_t zeroes;
1461     uint32_t temp       = 0;
1462     int randomidx       = 0;
1463     int inoutsize       = 0;
1464     int ret;
1465
1466     inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1467     if (inoutsize <= 0) {
1468         av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1469         return AVERROR(EIO);
1470     }
1471     // Check Version
1472     if (buffer[0] != 3) {
1473         av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1474         return AVERROR(EIO);
1475     }
1476     if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1477         av_log(s, AV_LOG_ERROR,
1478                "Unable to write answer - RTMP S0\n");
1479         return AVERROR(EIO);
1480     }
1481     /* Receive C1 */
1482     ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1483                                  RTMP_HANDSHAKE_PACKET_SIZE);
1484     if (ret) {
1485         av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1486         return ret;
1487     }
1488     /* Send S1 */
1489     /* By now same epoch will be sent */
1490     hs_my_epoch = hs_epoch;
1491     /* Generate random */
1492     for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1493          randomidx += 4)
1494         AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1495
1496     ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1497                               RTMP_HANDSHAKE_PACKET_SIZE);
1498     if (ret) {
1499         av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1500         return ret;
1501     }
1502     /* Send S2 */
1503     ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1504                               RTMP_HANDSHAKE_PACKET_SIZE);
1505     if (ret) {
1506         av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1507         return ret;
1508     }
1509     /* Receive C2 */
1510     ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1511                                  RTMP_HANDSHAKE_PACKET_SIZE);
1512     if (ret) {
1513         av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1514         return ret;
1515     }
1516     if (temp != hs_my_epoch)
1517         av_log(s, AV_LOG_WARNING,
1518                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1519     if (memcmp(buffer + 8, hs_s1 + 8,
1520                RTMP_HANDSHAKE_PACKET_SIZE - 8))
1521         av_log(s, AV_LOG_WARNING,
1522                "Erroneous C2 Message random does not match up\n");
1523
1524     return 0;
1525 }
1526
1527 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1528 {
1529     RTMPContext *rt = s->priv_data;
1530     int ret;
1531
1532     if (pkt->size < 4) {
1533         av_log(s, AV_LOG_ERROR,
1534                "Too short chunk size change packet (%d)\n",
1535                pkt->size);
1536         return AVERROR_INVALIDDATA;
1537     }
1538
1539     if (!rt->is_input) {
1540         /* Send the same chunk size change packet back to the server,
1541          * setting the outgoing chunk size to the same as the incoming one. */
1542         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1543                                         &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1544             return ret;
1545         rt->out_chunk_size = AV_RB32(pkt->data);
1546     }
1547
1548     rt->in_chunk_size = AV_RB32(pkt->data);
1549     if (rt->in_chunk_size <= 0) {
1550         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1551                rt->in_chunk_size);
1552         return AVERROR_INVALIDDATA;
1553     }
1554     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1555            rt->in_chunk_size);
1556
1557     return 0;
1558 }
1559
1560 static int handle_user_control(URLContext *s, RTMPPacket *pkt)
1561 {
1562     RTMPContext *rt = s->priv_data;
1563     int t, ret;
1564
1565     if (pkt->size < 2) {
1566         av_log(s, AV_LOG_ERROR, "Too short user control packet (%d)\n",
1567                pkt->size);
1568         return AVERROR_INVALIDDATA;
1569     }
1570
1571     t = AV_RB16(pkt->data);
1572     if (t == 6) { // PingRequest
1573         if ((ret = gen_pong(s, rt, pkt)) < 0)
1574             return ret;
1575     } else if (t == 26) {
1576         if (rt->swfsize) {
1577             if ((ret = gen_swf_verification(s, rt)) < 0)
1578                 return ret;
1579         } else {
1580             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1581         }
1582     }
1583
1584     return 0;
1585 }
1586
1587 static int handle_set_peer_bw(URLContext *s, RTMPPacket *pkt)
1588 {
1589     RTMPContext *rt = s->priv_data;
1590
1591     if (pkt->size < 4) {
1592         av_log(s, AV_LOG_ERROR,
1593                "Peer bandwidth packet is less than 4 bytes long (%d)\n",
1594                pkt->size);
1595         return AVERROR_INVALIDDATA;
1596     }
1597
1598     // We currently don't check how much the peer has acknowledged of
1599     // what we have sent. To do that properly, we should call
1600     // gen_window_ack_size here, to tell the peer that we want an
1601     // acknowledgement with (at least) that interval.
1602     rt->max_sent_unacked = AV_RB32(pkt->data);
1603     if (rt->max_sent_unacked <= 0) {
1604         av_log(s, AV_LOG_ERROR, "Incorrect set peer bandwidth %d\n",
1605                rt->max_sent_unacked);
1606         return AVERROR_INVALIDDATA;
1607
1608     }
1609     av_log(s, AV_LOG_DEBUG, "Max sent, unacked = %d\n", rt->max_sent_unacked);
1610
1611     return 0;
1612 }
1613
1614 static int handle_window_ack_size(URLContext *s, RTMPPacket *pkt)
1615 {
1616     RTMPContext *rt = s->priv_data;
1617
1618     if (pkt->size < 4) {
1619         av_log(s, AV_LOG_ERROR,
1620                "Too short window acknowledgement size packet (%d)\n",
1621                pkt->size);
1622         return AVERROR_INVALIDDATA;
1623     }
1624
1625     rt->receive_report_size = AV_RB32(pkt->data);
1626     if (rt->receive_report_size <= 0) {
1627         av_log(s, AV_LOG_ERROR, "Incorrect window acknowledgement size %d\n",
1628                rt->receive_report_size);
1629         return AVERROR_INVALIDDATA;
1630     }
1631     av_log(s, AV_LOG_DEBUG, "Window acknowledgement size = %d\n", rt->receive_report_size);
1632     // Send an Acknowledgement packet after receiving half the maximum
1633     // size, to make sure the peer can keep on sending without waiting
1634     // for acknowledgements.
1635     rt->receive_report_size >>= 1;
1636
1637     return 0;
1638 }
1639
1640 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1641                          const char *opaque, const char *challenge)
1642 {
1643     uint8_t hash[16];
1644     char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1645     struct AVMD5 *md5 = av_md5_alloc();
1646     if (!md5)
1647         return AVERROR(ENOMEM);
1648
1649     snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1650
1651     av_md5_init(md5);
1652     av_md5_update(md5, user, strlen(user));
1653     av_md5_update(md5, salt, strlen(salt));
1654     av_md5_update(md5, rt->password, strlen(rt->password));
1655     av_md5_final(md5, hash);
1656     av_base64_encode(hashstr, sizeof(hashstr), hash,
1657                      sizeof(hash));
1658     av_md5_init(md5);
1659     av_md5_update(md5, hashstr, strlen(hashstr));
1660     if (opaque)
1661         av_md5_update(md5, opaque, strlen(opaque));
1662     else if (challenge)
1663         av_md5_update(md5, challenge, strlen(challenge));
1664     av_md5_update(md5, challenge2, strlen(challenge2));
1665     av_md5_final(md5, hash);
1666     av_base64_encode(hashstr, sizeof(hashstr), hash,
1667                      sizeof(hash));
1668     snprintf(rt->auth_params, sizeof(rt->auth_params),
1669              "?authmod=%s&user=%s&challenge=%s&response=%s",
1670              "adobe", user, challenge2, hashstr);
1671     if (opaque)
1672         av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1673                     "&opaque=%s", opaque);
1674
1675     av_free(md5);
1676     return 0;
1677 }
1678
1679 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1680 {
1681     uint8_t hash[16];
1682     char hashstr1[33], hashstr2[33];
1683     const char *realm = "live";
1684     const char *method = "publish";
1685     const char *qop = "auth";
1686     const char *nc = "00000001";
1687     char cnonce[10];
1688     struct AVMD5 *md5 = av_md5_alloc();
1689     if (!md5)
1690         return AVERROR(ENOMEM);
1691
1692     snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1693
1694     av_md5_init(md5);
1695     av_md5_update(md5, user, strlen(user));
1696     av_md5_update(md5, ":", 1);
1697     av_md5_update(md5, realm, strlen(realm));
1698     av_md5_update(md5, ":", 1);
1699     av_md5_update(md5, rt->password, strlen(rt->password));
1700     av_md5_final(md5, hash);
1701     ff_data_to_hex(hashstr1, hash, 16, 1);
1702     hashstr1[32] = '\0';
1703
1704     av_md5_init(md5);
1705     av_md5_update(md5, method, strlen(method));
1706     av_md5_update(md5, ":/", 2);
1707     av_md5_update(md5, rt->app, strlen(rt->app));
1708     if (!strchr(rt->app, '/'))
1709         av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1710     av_md5_final(md5, hash);
1711     ff_data_to_hex(hashstr2, hash, 16, 1);
1712     hashstr2[32] = '\0';
1713
1714     av_md5_init(md5);
1715     av_md5_update(md5, hashstr1, strlen(hashstr1));
1716     av_md5_update(md5, ":", 1);
1717     if (nonce)
1718         av_md5_update(md5, nonce, strlen(nonce));
1719     av_md5_update(md5, ":", 1);
1720     av_md5_update(md5, nc, strlen(nc));
1721     av_md5_update(md5, ":", 1);
1722     av_md5_update(md5, cnonce, strlen(cnonce));
1723     av_md5_update(md5, ":", 1);
1724     av_md5_update(md5, qop, strlen(qop));
1725     av_md5_update(md5, ":", 1);
1726     av_md5_update(md5, hashstr2, strlen(hashstr2));
1727     av_md5_final(md5, hash);
1728     ff_data_to_hex(hashstr1, hash, 16, 1);
1729
1730     snprintf(rt->auth_params, sizeof(rt->auth_params),
1731              "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1732              "llnw", user, nonce, cnonce, nc, hashstr1);
1733
1734     av_free(md5);
1735     return 0;
1736 }
1737
1738 static int handle_connect_error(URLContext *s, const char *desc)
1739 {
1740     RTMPContext *rt = s->priv_data;
1741     char buf[300], *ptr, authmod[15];
1742     int i = 0, ret = 0;
1743     const char *user = "", *salt = "", *opaque = NULL,
1744                *challenge = NULL, *cptr = NULL, *nonce = NULL;
1745
1746     if (!(cptr = strstr(desc, "authmod=adobe")) &&
1747         !(cptr = strstr(desc, "authmod=llnw"))) {
1748         av_log(s, AV_LOG_ERROR,
1749                "Unknown connect error (unsupported authentication method?)\n");
1750         return AVERROR_UNKNOWN;
1751     }
1752     cptr += strlen("authmod=");
1753     while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1754         authmod[i++] = *cptr++;
1755     authmod[i] = '\0';
1756
1757     if (!rt->username[0] || !rt->password[0]) {
1758         av_log(s, AV_LOG_ERROR, "No credentials set\n");
1759         return AVERROR_UNKNOWN;
1760     }
1761
1762     if (strstr(desc, "?reason=authfailed")) {
1763         av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1764         return AVERROR_UNKNOWN;
1765     } else if (strstr(desc, "?reason=nosuchuser")) {
1766         av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1767         return AVERROR_UNKNOWN;
1768     }
1769
1770     if (rt->auth_tried) {
1771         av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1772         return AVERROR_UNKNOWN;
1773     }
1774
1775     rt->auth_params[0] = '\0';
1776
1777     if (strstr(desc, "code=403 need auth")) {
1778         snprintf(rt->auth_params, sizeof(rt->auth_params),
1779                  "?authmod=%s&user=%s", authmod, rt->username);
1780         return 0;
1781     }
1782
1783     if (!(cptr = strstr(desc, "?reason=needauth"))) {
1784         av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1785         return AVERROR_UNKNOWN;
1786     }
1787
1788     av_strlcpy(buf, cptr + 1, sizeof(buf));
1789     ptr = buf;
1790
1791     while (ptr) {
1792         char *next  = strchr(ptr, '&');
1793         char *value = strchr(ptr, '=');
1794         if (next)
1795             *next++ = '\0';
1796         if (value) {
1797             *value++ = '\0';
1798             if (!strcmp(ptr, "user")) {
1799                 user = value;
1800             } else if (!strcmp(ptr, "salt")) {
1801                 salt = value;
1802             } else if (!strcmp(ptr, "opaque")) {
1803                 opaque = value;
1804             } else if (!strcmp(ptr, "challenge")) {
1805                 challenge = value;
1806             } else if (!strcmp(ptr, "nonce")) {
1807                 nonce = value;
1808             } else {
1809                 av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1810             }
1811         } else {
1812             av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1813         }
1814         ptr = next;
1815     }
1816
1817     if (!strcmp(authmod, "adobe")) {
1818         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1819             return ret;
1820     } else {
1821         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1822             return ret;
1823     }
1824
1825     rt->auth_tried = 1;
1826     return 0;
1827 }
1828
1829 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1830 {
1831     RTMPContext *rt = s->priv_data;
1832     const uint8_t *data_end = pkt->data + pkt->size;
1833     char *tracked_method = NULL;
1834     int level = AV_LOG_ERROR;
1835     uint8_t tmpstr[256];
1836     int ret;
1837
1838     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1839         return ret;
1840
1841     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1842                                 "description", tmpstr, sizeof(tmpstr))) {
1843         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1844                                !strcmp(tracked_method, "releaseStream") ||
1845                                !strcmp(tracked_method, "FCSubscribe")   ||
1846                                !strcmp(tracked_method, "FCPublish"))) {
1847             /* Gracefully ignore Adobe-specific historical artifact errors. */
1848             level = AV_LOG_WARNING;
1849             ret = 0;
1850         } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
1851             level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
1852             ret = 0;
1853         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1854             ret = handle_connect_error(s, tmpstr);
1855             if (!ret) {
1856                 rt->do_reconnect = 1;
1857                 level = AV_LOG_VERBOSE;
1858             }
1859         } else
1860             ret = AVERROR_UNKNOWN;
1861         av_log(s, level, "Server error: %s\n", tmpstr);
1862     }
1863
1864     av_free(tracked_method);
1865     return ret;
1866 }
1867
1868 static int write_begin(URLContext *s)
1869 {
1870     RTMPContext *rt = s->priv_data;
1871     PutByteContext pbc;
1872     RTMPPacket spkt = { 0 };
1873     int ret;
1874
1875     // Send Stream Begin 1
1876     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1877                                      RTMP_PT_USER_CONTROL, 0, 6)) < 0) {
1878         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1879         return ret;
1880     }
1881
1882     bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1883     bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1884     bytestream2_put_be32(&pbc, rt->nb_streamid);
1885
1886     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1887                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1888
1889     ff_rtmp_packet_destroy(&spkt);
1890
1891     return ret;
1892 }
1893
1894 static int write_status(URLContext *s, RTMPPacket *pkt,
1895                         const char *status, const char *filename)
1896 {
1897     RTMPContext *rt = s->priv_data;
1898     RTMPPacket spkt = { 0 };
1899     char statusmsg[128];
1900     uint8_t *pp;
1901     int ret;
1902
1903     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1904                                      RTMP_PT_INVOKE, 0,
1905                                      RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1906         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1907         return ret;
1908     }
1909
1910     pp = spkt.data;
1911     spkt.extra = pkt->extra;
1912     ff_amf_write_string(&pp, "onStatus");
1913     ff_amf_write_number(&pp, 0);
1914     ff_amf_write_null(&pp);
1915
1916     ff_amf_write_object_start(&pp);
1917     ff_amf_write_field_name(&pp, "level");
1918     ff_amf_write_string(&pp, "status");
1919     ff_amf_write_field_name(&pp, "code");
1920     ff_amf_write_string(&pp, status);
1921     ff_amf_write_field_name(&pp, "description");
1922     snprintf(statusmsg, sizeof(statusmsg),
1923              "%s is now published", filename);
1924     ff_amf_write_string(&pp, statusmsg);
1925     ff_amf_write_field_name(&pp, "details");
1926     ff_amf_write_string(&pp, filename);
1927     ff_amf_write_object_end(&pp);
1928
1929     spkt.size = pp - spkt.data;
1930     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1931                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1932     ff_rtmp_packet_destroy(&spkt);
1933
1934     return ret;
1935 }
1936
1937 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1938 {
1939     RTMPContext *rt = s->priv_data;
1940     double seqnum;
1941     char filename[128];
1942     char command[64];
1943     int stringlen;
1944     char *pchar;
1945     const uint8_t *p = pkt->data;
1946     uint8_t *pp      = NULL;
1947     RTMPPacket spkt  = { 0 };
1948     GetByteContext gbc;
1949     int ret;
1950
1951     bytestream2_init(&gbc, p, pkt->size);
1952     if (ff_amf_read_string(&gbc, command, sizeof(command),
1953                            &stringlen)) {
1954         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1955         return AVERROR_INVALIDDATA;
1956     }
1957
1958     ret = ff_amf_read_number(&gbc, &seqnum);
1959     if (ret)
1960         return ret;
1961     ret = ff_amf_read_null(&gbc);
1962     if (ret)
1963         return ret;
1964     if (!strcmp(command, "FCPublish") ||
1965         !strcmp(command, "publish")) {
1966         ret = ff_amf_read_string(&gbc, filename,
1967                                  sizeof(filename), &stringlen);
1968         if (ret) {
1969             if (ret == AVERROR(EINVAL))
1970                 av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n");
1971             else
1972                 av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n");
1973             return ret;
1974         }
1975         // check with url
1976         if (s->filename) {
1977             pchar = strrchr(s->filename, '/');
1978             if (!pchar) {
1979                 av_log(s, AV_LOG_WARNING,
1980                        "Unable to find / in url %s, bad format\n",
1981                        s->filename);
1982                 pchar = s->filename;
1983             }
1984             pchar++;
1985             if (strcmp(pchar, filename))
1986                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1987                        " %s\n", filename, pchar);
1988         }
1989         rt->state = STATE_RECEIVING;
1990     }
1991
1992     if (!strcmp(command, "FCPublish")) {
1993         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1994                                          RTMP_PT_INVOKE, 0,
1995                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1996             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1997             return ret;
1998         }
1999         pp = spkt.data;
2000         ff_amf_write_string(&pp, "onFCPublish");
2001     } else if (!strcmp(command, "publish")) {
2002         ret = write_begin(s);
2003         if (ret < 0)
2004             return ret;
2005
2006         // Send onStatus(NetStream.Publish.Start)
2007         return write_status(s, pkt, "NetStream.Publish.Start",
2008                            filename);
2009     } else if (!strcmp(command, "play")) {
2010         ret = write_begin(s);
2011         if (ret < 0)
2012             return ret;
2013         rt->state = STATE_SENDING;
2014         return write_status(s, pkt, "NetStream.Play.Start",
2015                             filename);
2016     } else {
2017         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2018                                          RTMP_PT_INVOKE, 0,
2019                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2020             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2021             return ret;
2022         }
2023         pp = spkt.data;
2024         ff_amf_write_string(&pp, "_result");
2025         ff_amf_write_number(&pp, seqnum);
2026         ff_amf_write_null(&pp);
2027         if (!strcmp(command, "createStream")) {
2028             rt->nb_streamid++;
2029             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
2030                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
2031             ff_amf_write_number(&pp, rt->nb_streamid);
2032             /* By now we don't control which streams are removed in
2033              * deleteStream. There is no stream creation control
2034              * if a client creates more than 2^32 - 2 streams. */
2035         }
2036     }
2037     spkt.size = pp - spkt.data;
2038     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
2039                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
2040     ff_rtmp_packet_destroy(&spkt);
2041     return ret;
2042 }
2043
2044 /**
2045  * Read the AMF_NUMBER response ("_result") to a function call
2046  * (e.g. createStream()). This response should be made up of the AMF_STRING
2047  * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
2048  * successful response, we will return set the value to number (otherwise number
2049  * will not be changed).
2050  *
2051  * @return 0 if reading the value succeeds, negative value otherwise
2052  */
2053 static int read_number_result(RTMPPacket *pkt, double *number)
2054 {
2055     // We only need to fit "_result" in this.
2056     uint8_t strbuffer[8];
2057     int stringlen;
2058     double numbuffer;
2059     GetByteContext gbc;
2060
2061     bytestream2_init(&gbc, pkt->data, pkt->size);
2062
2063     // Value 1/4: "_result" as AMF_STRING
2064     if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
2065         return AVERROR_INVALIDDATA;
2066     if (strcmp(strbuffer, "_result"))
2067         return AVERROR_INVALIDDATA;
2068     // Value 2/4: The callee reference number
2069     if (ff_amf_read_number(&gbc, &numbuffer))
2070         return AVERROR_INVALIDDATA;
2071     // Value 3/4: Null
2072     if (ff_amf_read_null(&gbc))
2073         return AVERROR_INVALIDDATA;
2074     // Value 4/4: The response as AMF_NUMBER
2075     if (ff_amf_read_number(&gbc, &numbuffer))
2076         return AVERROR_INVALIDDATA;
2077     else
2078         *number = numbuffer;
2079
2080     return 0;
2081 }
2082
2083 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
2084 {
2085     RTMPContext *rt = s->priv_data;
2086     char *tracked_method = NULL;
2087     int ret = 0;
2088
2089     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
2090         return ret;
2091
2092     if (!tracked_method) {
2093         /* Ignore this reply when the current method is not tracked. */
2094         return ret;
2095     }
2096
2097     if (!strcmp(tracked_method, "connect")) {
2098         if (!rt->is_input) {
2099             if ((ret = gen_release_stream(s, rt)) < 0)
2100                 goto fail;
2101
2102             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
2103                 goto fail;
2104         } else {
2105             if ((ret = gen_window_ack_size(s, rt)) < 0)
2106                 goto fail;
2107         }
2108
2109         if ((ret = gen_create_stream(s, rt)) < 0)
2110             goto fail;
2111
2112         if (rt->is_input) {
2113             /* Send the FCSubscribe command when the name of live
2114              * stream is defined by the user or if it's a live stream. */
2115             if (rt->subscribe) {
2116                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
2117                     goto fail;
2118             } else if (rt->live == -1) {
2119                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2120                     goto fail;
2121             }
2122         }
2123     } else if (!strcmp(tracked_method, "createStream")) {
2124         double stream_id;
2125         if (read_number_result(pkt, &stream_id)) {
2126             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2127         } else {
2128             rt->stream_id = stream_id;
2129         }
2130
2131         if (!rt->is_input) {
2132             if ((ret = gen_publish(s, rt)) < 0)
2133                 goto fail;
2134         } else {
2135             if (rt->live != -1) {
2136                 if ((ret = gen_get_stream_length(s, rt)) < 0)
2137                     goto fail;
2138             }
2139             if ((ret = gen_play(s, rt)) < 0)
2140                 goto fail;
2141             if ((ret = gen_buffer_time(s, rt)) < 0)
2142                 goto fail;
2143         }
2144     } else if (!strcmp(tracked_method, "getStreamLength")) {
2145         if (read_number_result(pkt, &rt->duration)) {
2146             av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n");
2147         }
2148     }
2149
2150 fail:
2151     av_free(tracked_method);
2152     return ret;
2153 }
2154
2155 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2156 {
2157     RTMPContext *rt = s->priv_data;
2158     const uint8_t *data_end = pkt->data + pkt->size;
2159     const uint8_t *ptr = pkt->data + RTMP_HEADER;
2160     uint8_t tmpstr[256];
2161     int i, t;
2162
2163     for (i = 0; i < 2; i++) {
2164         t = ff_amf_tag_size(ptr, data_end);
2165         if (t < 0)
2166             return 1;
2167         ptr += t;
2168     }
2169
2170     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2171     if (!t && !strcmp(tmpstr, "error")) {
2172         t = ff_amf_get_field_value(ptr, data_end,
2173                                    "description", tmpstr, sizeof(tmpstr));
2174         if (t || !tmpstr[0])
2175             t = ff_amf_get_field_value(ptr, data_end, "code",
2176                                        tmpstr, sizeof(tmpstr));
2177         if (!t)
2178             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2179         return -1;
2180     }
2181
2182     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2183     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2184     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2185     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2186     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2187     if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2188
2189     return 0;
2190 }
2191
2192 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2193 {
2194     RTMPContext *rt = s->priv_data;
2195     int ret = 0;
2196
2197     //TODO: check for the messages sent for wrong state?
2198     if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2199         if ((ret = handle_invoke_error(s, pkt)) < 0)
2200             return ret;
2201     } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2202         if ((ret = handle_invoke_result(s, pkt)) < 0)
2203             return ret;
2204     } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2205         if ((ret = handle_invoke_status(s, pkt)) < 0)
2206             return ret;
2207     } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2208         if ((ret = gen_check_bw(s, rt)) < 0)
2209             return ret;
2210     } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2211                ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
2212                ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
2213                ff_amf_match_string(pkt->data, pkt->size, "play")          ||
2214                ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
2215                ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2216         if ((ret = send_invoke_response(s, pkt)) < 0)
2217             return ret;
2218     }
2219
2220     return ret;
2221 }
2222
2223 static int update_offset(RTMPContext *rt, int size)
2224 {
2225     int old_flv_size;
2226
2227     // generate packet header and put data into buffer for FLV demuxer
2228     if (rt->flv_off < rt->flv_size) {
2229         // There is old unread data in the buffer, thus append at the end
2230         old_flv_size  = rt->flv_size;
2231         rt->flv_size += size;
2232     } else {
2233         // All data has been read, write the new data at the start of the buffer
2234         old_flv_size = 0;
2235         rt->flv_size = size;
2236         rt->flv_off  = 0;
2237     }
2238
2239     return old_flv_size;
2240 }
2241
2242 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2243 {
2244     int old_flv_size, ret;
2245     PutByteContext pbc;
2246     const uint8_t *data = pkt->data + skip;
2247     const int size      = pkt->size - skip;
2248     uint32_t ts         = pkt->timestamp;
2249
2250     if (pkt->type == RTMP_PT_AUDIO) {
2251         rt->has_audio = 1;
2252     } else if (pkt->type == RTMP_PT_VIDEO) {
2253         rt->has_video = 1;
2254     }
2255
2256     old_flv_size = update_offset(rt, size + 15);
2257
2258     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2259         rt->flv_size = rt->flv_off = 0;
2260         return ret;
2261     }
2262     bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2263     bytestream2_skip_p(&pbc, old_flv_size);
2264     bytestream2_put_byte(&pbc, pkt->type);
2265     bytestream2_put_be24(&pbc, size);
2266     bytestream2_put_be24(&pbc, ts);
2267     bytestream2_put_byte(&pbc, ts >> 24);
2268     bytestream2_put_be24(&pbc, 0);
2269     bytestream2_put_buffer(&pbc, data, size);
2270     bytestream2_put_be32(&pbc, size + RTMP_HEADER);
2271
2272     return 0;
2273 }
2274
2275 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2276 {
2277     RTMPContext *rt  = s->priv_data;
2278     uint8_t commandbuffer[64];
2279     char statusmsg[128];
2280     int stringlen, ret, skip = 0;
2281     GetByteContext gbc;
2282
2283     bytestream2_init(&gbc, pkt->data, pkt->size);
2284     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2285                            &stringlen))
2286         return AVERROR_INVALIDDATA;
2287
2288     if (!strcmp(commandbuffer, "onMetaData")) {
2289         // metadata properties should be stored in a mixed array
2290         if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2291             // We have found a metaData Array so flv can determine the streams
2292             // from this.
2293             rt->received_metadata = 1;
2294             // skip 32-bit max array index
2295             bytestream2_skip(&gbc, 4);
2296             while (bytestream2_get_bytes_left(&gbc) > 3) {
2297                 if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2298                                       &stringlen))
2299                     return AVERROR_INVALIDDATA;
2300                 // We do not care about the content of the property (yet).
2301                 stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2302                 if (stringlen < 0)
2303                     return AVERROR_INVALIDDATA;
2304                 bytestream2_skip(&gbc, stringlen);
2305
2306                 // The presence of the following properties indicates that the
2307                 // respective streams are present.
2308                 if (!strcmp(statusmsg, "videocodecid")) {
2309                     rt->has_video = 1;
2310                 }
2311                 if (!strcmp(statusmsg, "audiocodecid")) {
2312                     rt->has_audio = 1;
2313                 }
2314             }
2315             if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2316                 return AVERROR_INVALIDDATA;
2317         }
2318     }
2319
2320     // Skip the @setDataFrame string and validate it is a notification
2321     if (!strcmp(commandbuffer, "@setDataFrame")) {
2322         skip = gbc.buffer - pkt->data;
2323         ret = ff_amf_read_string(&gbc, statusmsg,
2324                                  sizeof(statusmsg), &stringlen);
2325         if (ret < 0)
2326             return AVERROR_INVALIDDATA;
2327     }
2328
2329     return append_flv_data(rt, pkt, skip);
2330 }
2331
2332 /**
2333  * Parse received packet and possibly perform some action depending on
2334  * the packet contents.
2335  * @return 0 for no errors, negative values for serious errors which prevent
2336  *         further communications, positive values for uncritical errors
2337  */
2338 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2339 {
2340     int ret;
2341
2342 #ifdef DEBUG
2343     ff_rtmp_packet_dump(s, pkt);
2344 #endif
2345
2346     switch (pkt->type) {
2347     case RTMP_PT_BYTES_READ:
2348         av_log(s, AV_LOG_TRACE, "received bytes read report\n");
2349         break;
2350     case RTMP_PT_CHUNK_SIZE:
2351         if ((ret = handle_chunk_size(s, pkt)) < 0)
2352             return ret;
2353         break;
2354     case RTMP_PT_USER_CONTROL:
2355         if ((ret = handle_user_control(s, pkt)) < 0)
2356             return ret;
2357         break;
2358     case RTMP_PT_SET_PEER_BW:
2359         if ((ret = handle_set_peer_bw(s, pkt)) < 0)
2360             return ret;
2361         break;
2362     case RTMP_PT_WINDOW_ACK_SIZE:
2363         if ((ret = handle_window_ack_size(s, pkt)) < 0)
2364             return ret;
2365         break;
2366     case RTMP_PT_INVOKE:
2367         if ((ret = handle_invoke(s, pkt)) < 0)
2368             return ret;
2369         break;
2370     case RTMP_PT_VIDEO:
2371     case RTMP_PT_AUDIO:
2372     case RTMP_PT_METADATA:
2373     case RTMP_PT_NOTIFY:
2374         /* Audio, Video and Metadata packets are parsed in get_packet() */
2375         break;
2376     default:
2377         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2378         break;
2379     }
2380     return 0;
2381 }
2382
2383 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2384 {
2385     int ret, old_flv_size, type;
2386     const uint8_t *next;
2387     uint8_t *p;
2388     uint32_t size;
2389     uint32_t ts, cts, pts = 0;
2390
2391     old_flv_size = update_offset(rt, pkt->size);
2392
2393     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2394         rt->flv_size = rt->flv_off = 0;
2395         return ret;
2396     }
2397
2398     next = pkt->data;
2399     p    = rt->flv_data + old_flv_size;
2400
2401     /* copy data while rewriting timestamps */
2402     ts = pkt->timestamp;
2403
2404     while (next - pkt->data < pkt->size - RTMP_HEADER) {
2405         type = bytestream_get_byte(&next);
2406         size = bytestream_get_be24(&next);
2407         cts  = bytestream_get_be24(&next);
2408         cts |= bytestream_get_byte(&next) << 24;
2409         if (!pts)
2410             pts = cts;
2411         ts += cts - pts;
2412         pts = cts;
2413         if (size + 3 + 4 > pkt->data + pkt->size - next)
2414             break;
2415         bytestream_put_byte(&p, type);
2416         bytestream_put_be24(&p, size);
2417         bytestream_put_be24(&p, ts);
2418         bytestream_put_byte(&p, ts >> 24);
2419         memcpy(p, next, size + 3 + 4);
2420         p    += size + 3;
2421         bytestream_put_be32(&p, size + RTMP_HEADER);
2422         next += size + 3 + 4;
2423     }
2424     if (p != rt->flv_data + rt->flv_size) {
2425         av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2426                                      "RTMP_PT_METADATA packet\n");
2427         rt->flv_size = p - rt->flv_data;
2428     }
2429
2430     return 0;
2431 }
2432
2433 /**
2434  * Interact with the server by receiving and sending RTMP packets until
2435  * there is some significant data (media data or expected status notification).
2436  *
2437  * @param s          reading context
2438  * @param for_header non-zero value tells function to work until it
2439  * gets notification from the server that playing has been started,
2440  * otherwise function will work until some media data is received (or
2441  * an error happens)
2442  * @return 0 for successful operation, negative value in case of error
2443  */
2444 static int get_packet(URLContext *s, int for_header)
2445 {
2446     RTMPContext *rt = s->priv_data;
2447     int ret;
2448
2449     if (rt->state == STATE_STOPPED)
2450         return AVERROR_EOF;
2451
2452     for (;;) {
2453         RTMPPacket rpkt = { 0 };
2454         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2455                                        rt->in_chunk_size, &rt->prev_pkt[0],
2456                                        &rt->nb_prev_pkt[0])) <= 0) {
2457             if (ret == 0) {
2458                 return AVERROR(EAGAIN);
2459             } else {
2460                 return AVERROR(EIO);
2461             }
2462         }
2463
2464         // Track timestamp for later use
2465         rt->last_timestamp = rpkt.timestamp;
2466
2467         rt->bytes_read += ret;
2468         if (rt->bytes_read - rt->last_bytes_read > rt->receive_report_size) {
2469             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2470             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2471                 return ret;
2472             rt->last_bytes_read = rt->bytes_read;
2473         }
2474
2475         ret = rtmp_parse_result(s, rt, &rpkt);
2476
2477         // At this point we must check if we are in the seek state and continue
2478         // with the next packet. handle_invoke will get us out of this state
2479         // when the right message is encountered
2480         if (rt->state == STATE_SEEKING) {
2481             ff_rtmp_packet_destroy(&rpkt);
2482             // We continue, let the natural flow of things happen:
2483             // AVERROR(EAGAIN) or handle_invoke gets us out of here
2484             continue;
2485         }
2486
2487         if (ret < 0) {//serious error in current packet
2488             ff_rtmp_packet_destroy(&rpkt);
2489             return ret;
2490         }
2491         if (rt->do_reconnect && for_header) {
2492             ff_rtmp_packet_destroy(&rpkt);
2493             return 0;
2494         }
2495         if (rt->state == STATE_STOPPED) {
2496             ff_rtmp_packet_destroy(&rpkt);
2497             return AVERROR_EOF;
2498         }
2499         if (for_header && (rt->state == STATE_PLAYING    ||
2500                            rt->state == STATE_PUBLISHING ||
2501                            rt->state == STATE_SENDING    ||
2502                            rt->state == STATE_RECEIVING)) {
2503             ff_rtmp_packet_destroy(&rpkt);
2504             return 0;
2505         }
2506         if (!rpkt.size || !rt->is_input) {
2507             ff_rtmp_packet_destroy(&rpkt);
2508             continue;
2509         }
2510         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2511             ret = append_flv_data(rt, &rpkt, 0);
2512             ff_rtmp_packet_destroy(&rpkt);
2513             return ret;
2514         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2515             ret = handle_notify(s, &rpkt);
2516             ff_rtmp_packet_destroy(&rpkt);
2517             return ret;
2518         } else if (rpkt.type == RTMP_PT_METADATA) {
2519             ret = handle_metadata(rt, &rpkt);
2520             ff_rtmp_packet_destroy(&rpkt);
2521             return ret;
2522         }
2523         ff_rtmp_packet_destroy(&rpkt);
2524     }
2525 }
2526
2527 static int rtmp_close(URLContext *h)
2528 {
2529     RTMPContext *rt = h->priv_data;
2530     int ret = 0, i, j;
2531
2532     if (!rt->is_input) {
2533         rt->flv_data = NULL;
2534         if (rt->out_pkt.size)
2535             ff_rtmp_packet_destroy(&rt->out_pkt);
2536         if (rt->state > STATE_FCPUBLISH)
2537             ret = gen_fcunpublish_stream(h, rt);
2538     }
2539     if (rt->state > STATE_HANDSHAKED)
2540         ret = gen_delete_stream(h, rt);
2541     for (i = 0; i < 2; i++) {
2542         for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2543             ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2544         av_freep(&rt->prev_pkt[i]);
2545     }
2546
2547     free_tracked_methods(rt);
2548     av_freep(&rt->flv_data);
2549     ffurl_close(rt->stream);
2550     return ret;
2551 }
2552
2553 /**
2554  * Insert a fake onMetadata packet into the FLV stream to notify the FLV
2555  * demuxer about the duration of the stream.
2556  *
2557  * This should only be done if there was no real onMetadata packet sent by the
2558  * server at the start of the stream and if we were able to retrieve a valid
2559  * duration via a getStreamLength call.
2560  *
2561  * @return 0 for successful operation, negative value in case of error
2562  */
2563 static int inject_fake_duration_metadata(RTMPContext *rt)
2564 {
2565     // We need to insert the metadata packet directly after the FLV
2566     // header, i.e. we need to move all other already read data by the
2567     // size of our fake metadata packet.
2568
2569     uint8_t* p;
2570     // Keep old flv_data pointer
2571     uint8_t* old_flv_data = rt->flv_data;
2572     // Allocate a new flv_data pointer with enough space for the additional package
2573     if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) {
2574         rt->flv_data = old_flv_data;
2575         return AVERROR(ENOMEM);
2576     }
2577
2578     // Copy FLV header
2579     memcpy(rt->flv_data, old_flv_data, 13);
2580     // Copy remaining packets
2581     memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13);
2582     // Increase the size by the injected packet
2583     rt->flv_size += 55;
2584     // Delete the old FLV data
2585     av_freep(&old_flv_data);
2586
2587     p = rt->flv_data + 13;
2588     bytestream_put_byte(&p, FLV_TAG_TYPE_META);
2589     bytestream_put_be24(&p, 40); // size of data part (sum of all parts below)
2590     bytestream_put_be24(&p, 0);  // timestamp
2591     bytestream_put_be32(&p, 0);  // reserved
2592
2593     // first event name as a string
2594     bytestream_put_byte(&p, AMF_DATA_TYPE_STRING);
2595     // "onMetaData" as AMF string
2596     bytestream_put_be16(&p, 10);
2597     bytestream_put_buffer(&p, "onMetaData", 10);
2598
2599     // mixed array (hash) with size and string/type/data tuples
2600     bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY);
2601     bytestream_put_be32(&p, 1); // metadata_count
2602
2603     // "duration" as AMF string
2604     bytestream_put_be16(&p, 8);
2605     bytestream_put_buffer(&p, "duration", 8);
2606     bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER);
2607     bytestream_put_be64(&p, av_double2int(rt->duration));
2608
2609     // Finalise object
2610     bytestream_put_be16(&p, 0); // Empty string
2611     bytestream_put_byte(&p, AMF_END_OF_OBJECT);
2612     bytestream_put_be32(&p, 40 + RTMP_HEADER); // size of data part (sum of all parts above)
2613
2614     return 0;
2615 }
2616
2617 /**
2618  * Open RTMP connection and verify that the stream can be played.
2619  *
2620  * URL syntax: rtmp://server[:port][/app][/playpath]
2621  *             where 'app' is first one or two directories in the path
2622  *             (e.g. /ondemand/, /flash/live/, etc.)
2623  *             and 'playpath' is a file name (the rest of the path,
2624  *             may be prefixed with "mp4:")
2625  */
2626 static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
2627 {
2628     RTMPContext *rt = s->priv_data;
2629     char proto[8], hostname[256], path[1024], auth[100], *fname;
2630     char *old_app, *qmark, *n, fname_buffer[1024];
2631     uint8_t buf[2048];
2632     int port;
2633     int ret;
2634
2635     if (rt->listen_timeout > 0)
2636         rt->listen = 1;
2637
2638     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2639
2640     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2641                  hostname, sizeof(hostname), &port,
2642                  path, sizeof(path), s->filename);
2643
2644     n = strchr(path, ' ');
2645     if (n) {
2646         av_log(s, AV_LOG_WARNING,
2647                "Detected librtmp style URL parameters, these aren't supported "
2648                "by the libavformat internal RTMP handler currently enabled. "
2649                "See the documentation for the correct way to pass parameters.\n");
2650         *n = '\0'; // Trim not supported part
2651     }
2652
2653     if (auth[0]) {
2654         char *ptr = strchr(auth, ':');
2655         if (ptr) {
2656             *ptr = '\0';
2657             av_strlcpy(rt->username, auth, sizeof(rt->username));
2658             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2659         }
2660     }
2661
2662     if (rt->listen && strcmp(proto, "rtmp")) {
2663         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2664                proto);
2665         return AVERROR(EINVAL);
2666     }
2667     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2668         if (!strcmp(proto, "rtmpts"))
2669             av_dict_set(opts, "ffrtmphttp_tls", "1", 1);
2670
2671         /* open the http tunneling connection */
2672         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2673     } else if (!strcmp(proto, "rtmps")) {
2674         /* open the tls connection */
2675         if (port < 0)
2676             port = RTMPS_DEFAULT_PORT;
2677         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2678     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2679         if (!strcmp(proto, "rtmpte"))
2680             av_dict_set(opts, "ffrtmpcrypt_tunneling", "1", 1);
2681
2682         /* open the encrypted connection */
2683         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2684         rt->encrypted = 1;
2685     } else {
2686         /* open the tcp connection */
2687         if (port < 0)
2688             port = RTMP_DEFAULT_PORT;
2689         if (rt->listen)
2690             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2691                         "?listen&listen_timeout=%d",
2692                         rt->listen_timeout * 1000);
2693         else
2694             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2695     }
2696
2697 reconnect:
2698     if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2699                                     &s->interrupt_callback, opts,
2700                                     s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
2701         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2702         goto fail;
2703     }
2704
2705     if (rt->swfverify) {
2706         if ((ret = rtmp_calc_swfhash(s)) < 0)
2707             goto fail;
2708     }
2709
2710     rt->state = STATE_START;
2711     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2712         goto fail;
2713     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2714         goto fail;
2715
2716     rt->out_chunk_size = 128;
2717     rt->in_chunk_size  = 128; // Probably overwritten later
2718     rt->state = STATE_HANDSHAKED;
2719
2720     // Keep the application name when it has been defined by the user.
2721     old_app = rt->app;
2722
2723     rt->app = av_malloc(APP_MAX_LENGTH);
2724     if (!rt->app) {
2725         ret = AVERROR(ENOMEM);
2726         goto fail;
2727     }
2728
2729     //extract "app" part from path
2730     qmark = strchr(path, '?');
2731     if (qmark && strstr(qmark, "slist=")) {
2732         char* amp;
2733         // After slist we have the playpath, the full path is used as app
2734         av_strlcpy(rt->app, path + 1, APP_MAX_LENGTH);
2735         fname = strstr(path, "slist=") + 6;
2736         // Strip any further query parameters from fname
2737         amp = strchr(fname, '&');
2738         if (amp) {
2739             av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2740                                                   sizeof(fname_buffer)));
2741             fname = fname_buffer;
2742         }
2743     } else if (!strncmp(path, "/ondemand/", 10)) {
2744         fname = path + 10;
2745         memcpy(rt->app, "ondemand", 9);
2746     } else {
2747         char *next = *path ? path + 1 : path;
2748         char *p = strchr(next, '/');
2749         if (!p) {
2750             if (old_app) {
2751                 // If name of application has been defined by the user, assume that
2752                 // playpath is provided in the URL
2753                 fname = next;
2754             } else {
2755                 fname = NULL;
2756                 av_strlcpy(rt->app, next, APP_MAX_LENGTH);
2757             }
2758         } else {
2759             // make sure we do not mismatch a playpath for an application instance
2760             char *c = strchr(p + 1, ':');
2761             fname = strchr(p + 1, '/');
2762             if (!fname || (c && c < fname)) {
2763                 fname = p + 1;
2764                 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2765             } else {
2766                 fname++;
2767                 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2768             }
2769         }
2770     }
2771
2772     if (old_app) {
2773         // The name of application has been defined by the user, override it.
2774         if (strlen(old_app) >= APP_MAX_LENGTH) {
2775             ret = AVERROR(EINVAL);
2776             goto fail;
2777         }
2778         av_free(rt->app);
2779         rt->app = old_app;
2780     }
2781
2782     if (!rt->playpath) {
2783         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2784         if (!rt->playpath) {
2785             ret = AVERROR(ENOMEM);
2786             goto fail;
2787         }
2788
2789         if (fname) {
2790             int len = strlen(fname);
2791             if (!strchr(fname, ':') && len >= 4 &&
2792                 (!strcmp(fname + len - 4, ".f4v") ||
2793                  !strcmp(fname + len - 4, ".mp4"))) {
2794                 memcpy(rt->playpath, "mp4:", 5);
2795             } else {
2796                 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2797                     fname[len - 4] = '\0';
2798                 rt->playpath[0] = 0;
2799             }
2800             av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2801         } else {
2802             rt->playpath[0] = '\0';
2803         }
2804     }
2805
2806     if (!rt->tcurl) {
2807         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2808         if (!rt->tcurl) {
2809             ret = AVERROR(ENOMEM);
2810             goto fail;
2811         }
2812         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2813                     port, "/%s", rt->app);
2814     }
2815
2816     if (!rt->flashver) {
2817         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2818         if (!rt->flashver) {
2819             ret = AVERROR(ENOMEM);
2820             goto fail;
2821         }
2822         if (rt->is_input) {
2823             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2824                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2825                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2826         } else {
2827             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2828                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2829         }
2830     }
2831
2832     rt->receive_report_size = 1048576;
2833     rt->bytes_read = 0;
2834     rt->has_audio = 0;
2835     rt->has_video = 0;
2836     rt->received_metadata = 0;
2837     rt->last_bytes_read = 0;
2838     rt->max_sent_unacked = 2500000;
2839     rt->duration = 0;
2840
2841     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2842            proto, path, rt->app, rt->playpath);
2843     if (!rt->listen) {
2844         if ((ret = gen_connect(s, rt)) < 0)
2845             goto fail;
2846     } else {
2847         if ((ret = read_connect(s, s->priv_data)) < 0)
2848             goto fail;
2849     }
2850
2851     do {
2852         ret = get_packet(s, 1);
2853     } while (ret == AVERROR(EAGAIN));
2854     if (ret < 0)
2855         goto fail;
2856
2857     if (rt->do_reconnect) {
2858         int i;
2859         ffurl_close(rt->stream);
2860         rt->stream       = NULL;
2861         rt->do_reconnect = 0;
2862         rt->nb_invokes   = 0;
2863         for (i = 0; i < 2; i++)
2864             memset(rt->prev_pkt[i], 0,
2865                    sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2866         free_tracked_methods(rt);
2867         goto reconnect;
2868     }
2869
2870     if (rt->is_input) {
2871         // generate FLV header for demuxer
2872         rt->flv_size = 13;
2873         if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2874             goto fail;
2875         rt->flv_off  = 0;
2876         memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2877
2878         // Read packets until we reach the first A/V packet or read metadata.
2879         // If there was a metadata package in front of the A/V packets, we can
2880         // build the FLV header from this. If we do not receive any metadata,
2881         // the FLV decoder will allocate the needed streams when their first
2882         // audio or video packet arrives.
2883         while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2884             if ((ret = get_packet(s, 0)) < 0)
2885                goto fail;
2886         }
2887
2888         // Either after we have read the metadata or (if there is none) the
2889         // first packet of an A/V stream, we have a better knowledge about the
2890         // streams, so set the FLV header accordingly.
2891         if (rt->has_audio) {
2892             rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO;
2893         }
2894         if (rt->has_video) {
2895             rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO;
2896         }
2897
2898         // If we received the first packet of an A/V stream and no metadata but
2899         // the server returned a valid duration, create a fake metadata packet
2900         // to inform the FLV decoder about the duration.
2901         if (!rt->received_metadata && rt->duration > 0) {
2902             if ((ret = inject_fake_duration_metadata(rt)) < 0)
2903                 goto fail;
2904         }
2905     } else {
2906         rt->flv_size = 0;
2907         rt->flv_data = NULL;
2908         rt->flv_off  = 0;
2909         rt->skip_bytes = 13;
2910     }
2911
2912     s->max_packet_size = rt->stream->max_packet_size;
2913     s->is_streamed     = 1;
2914     return 0;
2915
2916 fail:
2917     av_dict_free(opts);
2918     rtmp_close(s);
2919     return ret;
2920 }
2921
2922 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2923 {
2924     RTMPContext *rt = s->priv_data;
2925     int orig_size = size;
2926     int ret;
2927
2928     while (size > 0) {
2929         int data_left = rt->flv_size - rt->flv_off;
2930
2931         if (data_left >= size) {
2932             memcpy(buf, rt->flv_data + rt->flv_off, size);
2933             rt->flv_off += size;
2934             return orig_size;
2935         }
2936         if (data_left > 0) {
2937             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2938             buf  += data_left;
2939             size -= data_left;
2940             rt->flv_off = rt->flv_size;
2941             return data_left;
2942         }
2943         if ((ret = get_packet(s, 0)) < 0)
2944            return ret;
2945     }
2946     return orig_size;
2947 }
2948
2949 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2950                          int flags)
2951 {
2952     RTMPContext *rt = s->priv_data;
2953     int ret;
2954     av_log(s, AV_LOG_DEBUG,
2955            "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2956            stream_index, timestamp, flags);
2957     if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2958         av_log(s, AV_LOG_ERROR,
2959                "Unable to send seek command on stream index %d at timestamp "
2960                "%"PRId64" with flags %08x\n",
2961                stream_index, timestamp, flags);
2962         return ret;
2963     }
2964     rt->flv_off = rt->flv_size;
2965     rt->state = STATE_SEEKING;
2966     return timestamp;
2967 }
2968
2969 static int rtmp_pause(URLContext *s, int pause)
2970 {
2971     RTMPContext *rt = s->priv_data;
2972     int ret;
2973     av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n",
2974            rt->last_timestamp);
2975     if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) {
2976         av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n",
2977                rt->last_timestamp);
2978         return ret;
2979     }
2980     return 0;
2981 }
2982
2983 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2984 {
2985     RTMPContext *rt = s->priv_data;
2986     int size_temp = size;
2987     int pktsize, pkttype, copy;
2988     uint32_t ts;
2989     const uint8_t *buf_temp = buf;
2990     uint8_t c;
2991     int ret;
2992
2993     do {
2994         if (rt->skip_bytes) {
2995             int skip = FFMIN(rt->skip_bytes, size_temp);
2996             buf_temp       += skip;
2997             size_temp      -= skip;
2998             rt->skip_bytes -= skip;
2999             continue;
3000         }
3001
3002         if (rt->flv_header_bytes < RTMP_HEADER) {
3003             const uint8_t *header = rt->flv_header;
3004             int channel = RTMP_AUDIO_CHANNEL;
3005
3006             copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
3007             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
3008             rt->flv_header_bytes += copy;
3009             size_temp            -= copy;
3010             if (rt->flv_header_bytes < RTMP_HEADER)
3011                 break;
3012
3013             pkttype = bytestream_get_byte(&header);
3014             pktsize = bytestream_get_be24(&header);
3015             ts = bytestream_get_be24(&header);
3016             ts |= bytestream_get_byte(&header) << 24;
3017             bytestream_get_be24(&header);
3018             rt->flv_size = pktsize;
3019
3020             if (pkttype == RTMP_PT_VIDEO)
3021                 channel = RTMP_VIDEO_CHANNEL;
3022
3023             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
3024                 pkttype == RTMP_PT_NOTIFY) {
3025                 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
3026                                                      &rt->nb_prev_pkt[1],
3027                                                      channel)) < 0)
3028                     return ret;
3029                 // Force sending a full 12 bytes header by clearing the
3030                 // channel id, to make it not match a potential earlier
3031                 // packet in the same channel.
3032                 rt->prev_pkt[1][channel].channel_id = 0;
3033             }
3034
3035             //this can be a big packet, it's better to send it right here
3036             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
3037                                              pkttype, ts, pktsize)) < 0)
3038                 return ret;
3039
3040             rt->out_pkt.extra = rt->stream_id;
3041             rt->flv_data = rt->out_pkt.data;
3042         }
3043
3044         copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
3045         bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
3046         rt->flv_off += copy;
3047         size_temp   -= copy;
3048
3049         if (rt->flv_off == rt->flv_size) {
3050             rt->skip_bytes = 4;
3051
3052             if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
3053                 // For onMetaData and |RtmpSampleAccess packets, we want
3054                 // @setDataFrame prepended to the packet before it gets sent.
3055                 // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
3056                 // and onCuePoint).
3057                 uint8_t commandbuffer[64];
3058                 int stringlen = 0;
3059                 GetByteContext gbc;
3060
3061                 bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
3062                 if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
3063                                         &stringlen)) {
3064                     if (!strcmp(commandbuffer, "onMetaData") ||
3065                         !strcmp(commandbuffer, "|RtmpSampleAccess")) {
3066                         uint8_t *ptr;
3067                         if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
3068                             rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
3069                             return ret;
3070                         }
3071                         memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
3072                         rt->out_pkt.size += 16;
3073                         ptr = rt->out_pkt.data;
3074                         ff_amf_write_string(&ptr, "@setDataFrame");
3075                     }
3076                 }
3077             }
3078
3079             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
3080                 return ret;
3081             rt->flv_size = 0;
3082             rt->flv_off = 0;
3083             rt->flv_header_bytes = 0;
3084             rt->flv_nb_packets++;
3085         }
3086     } while (buf_temp - buf < size);
3087
3088     if (rt->flv_nb_packets < rt->flush_interval)
3089         return size;
3090     rt->flv_nb_packets = 0;
3091
3092     /* set stream into nonblocking mode */
3093     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
3094
3095     /* try to read one byte from the stream */
3096     ret = ffurl_read(rt->stream, &c, 1);
3097
3098     /* switch the stream back into blocking mode */
3099     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
3100
3101     if (ret == AVERROR(EAGAIN)) {
3102         /* no incoming data to handle */
3103         return size;
3104     } else if (ret < 0) {
3105         return ret;
3106     } else if (ret == 1) {
3107         RTMPPacket rpkt = { 0 };
3108
3109         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
3110                                                 rt->in_chunk_size,
3111                                                 &rt->prev_pkt[0],
3112                                                 &rt->nb_prev_pkt[0], c)) <= 0)
3113              return ret;
3114
3115         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
3116             return ret;
3117
3118         ff_rtmp_packet_destroy(&rpkt);
3119     }
3120
3121     return size;
3122 }
3123
3124 #define OFFSET(x) offsetof(RTMPContext, x)
3125 #define DEC AV_OPT_FLAG_DECODING_PARAM
3126 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3127
3128 static const AVOption rtmp_options[] = {
3129     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3130     {"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},
3131     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3132     {"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},
3133     {"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},
3134     {"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"},
3135     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
3136     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
3137     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
3138     {"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},
3139     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3140     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3141     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
3142     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
3143     {"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},
3144     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3145     {"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},
3146     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3147     {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3148     {"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" },
3149     { NULL },
3150 };
3151
3152 #define RTMP_PROTOCOL(flavor)                    \
3153 static const AVClass flavor##_class = {          \
3154     .class_name = #flavor,                       \
3155     .item_name  = av_default_item_name,          \
3156     .option     = rtmp_options,                  \
3157     .version    = LIBAVUTIL_VERSION_INT,         \
3158 };                                               \
3159                                                  \
3160 const URLProtocol ff_##flavor##_protocol = {     \
3161     .name           = #flavor,                   \
3162     .url_open2      = rtmp_open,                 \
3163     .url_read       = rtmp_read,                 \
3164     .url_read_seek  = rtmp_seek,                 \
3165     .url_read_pause = rtmp_pause,                \
3166     .url_write      = rtmp_write,                \
3167     .url_close      = rtmp_close,                \
3168     .priv_data_size = sizeof(RTMPContext),       \
3169     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
3170     .priv_data_class= &flavor##_class,           \
3171 };
3172
3173
3174 RTMP_PROTOCOL(rtmp)
3175 RTMP_PROTOCOL(rtmpe)
3176 RTMP_PROTOCOL(rtmps)
3177 RTMP_PROTOCOL(rtmpt)
3178 RTMP_PROTOCOL(rtmpte)
3179 RTMP_PROTOCOL(rtmpts)