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