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