OSDN Git Service

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