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