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