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