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