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