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