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