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