Merge commit 'd6ded94036e43a04889f4ff2813a7f7dd60b82fe'
[ffmpeg.git] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Konstantin Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * RTMP protocol
25  */
26
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/hmac.h"
31 #include "libavutil/intfloat.h"
32 #include "libavutil/lfg.h"
33 #include "libavutil/md5.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/random_seed.h"
36 #include "avformat.h"
37 #include "internal.h"
38
39 #include "network.h"
40
41 #include "flv.h"
42 #include "rtmp.h"
43 #include "rtmpcrypt.h"
44 #include "rtmppkt.h"
45 #include "url.h"
46
47 #if CONFIG_ZLIB
48 #include <zlib.h>
49 #endif
50
51 #define APP_MAX_LENGTH 1024
52 #define PLAYPATH_MAX_LENGTH 512
53 #define TCURL_MAX_LENGTH 1024
54 #define FLASHVER_MAX_LENGTH 64
55 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
56 #define RTMP_HEADER 11
57
58 /** RTMP protocol handler state */
59 typedef enum {
60     STATE_START,      ///< client has not done anything yet
61     STATE_HANDSHAKED, ///< client has performed handshake
62     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
63     STATE_PLAYING,    ///< client has started receiving multimedia data from server
64     STATE_SEEKING,    ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66     STATE_RECEIVING,  ///< received a publish command (for input)
67     STATE_SENDING,    ///< received a play command (for output)
68     STATE_STOPPED,    ///< the broadcast has been stopped
69 } ClientState;
70
71 typedef struct TrackedMethod {
72     char *name;
73     int id;
74 } TrackedMethod;
75
76 /** protocol handler context */
77 typedef struct RTMPContext {
78     const AVClass *class;
79     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
80     RTMPPacket    *prev_pkt[2];               ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81     int           nb_prev_pkt[2];             ///< number of elements in prev_pkt
82     int           in_chunk_size;              ///< size of the chunks incoming RTMP packets are divided into
83     int           out_chunk_size;             ///< size of the chunks outgoing RTMP packets are divided into
84     int           is_input;                   ///< input/output flag
85     char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
86     int           live;                       ///< 0: recorded, -1: live, -2: both
87     char          *app;                       ///< name of application
88     char          *conn;                      ///< append arbitrary AMF data to the Connect message
89     ClientState   state;                      ///< current state
90     int           stream_id;                  ///< ID assigned by the server for the stream
91     uint8_t*      flv_data;                   ///< buffer with data for demuxer
92     int           flv_size;                   ///< current buffer size
93     int           flv_off;                    ///< number of bytes read from current buffer
94     int           flv_nb_packets;             ///< number of flv packets published
95     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
96     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
97     uint64_t      bytes_read;                 ///< number of bytes read from server
98     uint64_t      last_bytes_read;            ///< number of bytes read last reported to server
99     uint32_t      last_timestamp;             ///< last timestamp received in a packet
100     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
101     int           has_audio;                  ///< presence of audio data
102     int           has_video;                  ///< presence of video data
103     int           received_metadata;          ///< Indicates if we have received metadata about the streams
104     uint8_t       flv_header[RTMP_HEADER];    ///< partial incoming flv packet header
105     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
106     int           nb_invokes;                 ///< keeps track of invoke messages
107     char*         tcurl;                      ///< url of the target stream
108     char*         flashver;                   ///< version of the flash plugin
109     char*         swfhash;                    ///< SHA256 hash of the decompressed SWF file (32 bytes)
110     int           swfhash_len;                ///< length of the SHA256 hash
111     int           swfsize;                    ///< size of the decompressed SWF file
112     char*         swfurl;                     ///< url of the swf player
113     char*         swfverify;                  ///< URL to player swf file, compute hash/size automatically
114     char          swfverification[42];        ///< hash of the SWF verification
115     char*         pageurl;                    ///< url of the web page
116     char*         subscribe;                  ///< name of live stream to subscribe
117     int           server_bw;                  ///< server bandwidth
118     int           client_buffer_time;         ///< client buffer time in ms
119     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
120     int           encrypted;                  ///< use an encrypted connection (RTMPE only)
121     TrackedMethod*tracked_methods;            ///< tracked methods buffer
122     int           nb_tracked_methods;         ///< number of tracked methods
123     int           tracked_methods_size;       ///< size of the tracked methods buffer
124     int           listen;                     ///< listen mode flag
125     int           listen_timeout;             ///< listen timeout to wait for new connections
126     int           nb_streamid;                ///< The next stream id to return on createStream calls
127     double        duration;                   ///< Duration of the stream in seconds as returned by the server (only valid if non-zero)
128     char          username[50];
129     char          password[50];
130     char          auth_params[500];
131     int           do_reconnect;
132     int           auth_tried;
133 } RTMPContext;
134
135 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
136 /** Client key used for digest signing */
137 static const uint8_t rtmp_player_key[] = {
138     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
139     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
140
141     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
142     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
143     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
144 };
145
146 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
147 /** Key used for RTMP server digest signing */
148 static const uint8_t rtmp_server_key[] = {
149     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
150     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
151     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
152
153     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
154     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
155     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
156 };
157
158 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt);
159 static int handle_server_bw(URLContext *s, RTMPPacket *pkt);
160 static int handle_client_bw(URLContext *s, RTMPPacket *pkt);
161
162 static int add_tracked_method(RTMPContext *rt, const char *name, int id)
163 {
164     int err;
165
166     if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
167         rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
168         if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
169                                sizeof(*rt->tracked_methods))) < 0) {
170             rt->nb_tracked_methods = 0;
171             rt->tracked_methods_size = 0;
172             return err;
173         }
174     }
175
176     rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
177     if (!rt->tracked_methods[rt->nb_tracked_methods].name)
178         return AVERROR(ENOMEM);
179     rt->tracked_methods[rt->nb_tracked_methods].id = id;
180     rt->nb_tracked_methods++;
181
182     return 0;
183 }
184
185 static void del_tracked_method(RTMPContext *rt, int index)
186 {
187     memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
188             sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
189     rt->nb_tracked_methods--;
190 }
191
192 static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
193                                char **tracked_method)
194 {
195     RTMPContext *rt = s->priv_data;
196     GetByteContext gbc;
197     double pkt_id;
198     int ret;
199     int i;
200
201     bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
202     if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
203         return ret;
204
205     for (i = 0; i < rt->nb_tracked_methods; i++) {
206         if (rt->tracked_methods[i].id != pkt_id)
207             continue;
208
209         *tracked_method = rt->tracked_methods[i].name;
210         del_tracked_method(rt, i);
211         break;
212     }
213
214     return 0;
215 }
216
217 static void free_tracked_methods(RTMPContext *rt)
218 {
219     int i;
220
221     for (i = 0; i < rt->nb_tracked_methods; i ++)
222         av_freep(&rt->tracked_methods[i].name);
223     av_freep(&rt->tracked_methods);
224     rt->tracked_methods_size = 0;
225     rt->nb_tracked_methods   = 0;
226 }
227
228 static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
229 {
230     int ret;
231
232     if (pkt->type == RTMP_PT_INVOKE && track) {
233         GetByteContext gbc;
234         char name[128];
235         double pkt_id;
236         int len;
237
238         bytestream2_init(&gbc, pkt->data, pkt->size);
239         if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
240             goto fail;
241
242         if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
243             goto fail;
244
245         if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
246             goto fail;
247     }
248
249     ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
250                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
251 fail:
252     ff_rtmp_packet_destroy(pkt);
253     return ret;
254 }
255
256 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
257 {
258     char *field, *value;
259     char type;
260
261     /* The type must be B for Boolean, N for number, S for string, O for
262      * object, or Z for null. For Booleans the data must be either 0 or 1 for
263      * FALSE or TRUE, respectively. Likewise for Objects the data must be
264      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
265      * may be named, by prefixing the type with 'N' and specifying the name
266      * before the value (ie. NB:myFlag:1). This option may be used multiple times
267      * to construct arbitrary AMF sequences. */
268     if (param[0] && param[1] == ':') {
269         type = param[0];
270         value = param + 2;
271     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
272         type = param[1];
273         field = param + 3;
274         value = strchr(field, ':');
275         if (!value)
276             goto fail;
277         *value = '\0';
278         value++;
279
280         ff_amf_write_field_name(p, field);
281     } else {
282         goto fail;
283     }
284
285     switch (type) {
286     case 'B':
287         ff_amf_write_bool(p, value[0] != '0');
288         break;
289     case 'S':
290         ff_amf_write_string(p, value);
291         break;
292     case 'N':
293         ff_amf_write_number(p, strtod(value, NULL));
294         break;
295     case 'Z':
296         ff_amf_write_null(p);
297         break;
298     case 'O':
299         if (value[0] != '0')
300             ff_amf_write_object_start(p);
301         else
302             ff_amf_write_object_end(p);
303         break;
304     default:
305         goto fail;
306         break;
307     }
308
309     return 0;
310
311 fail:
312     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
313     return AVERROR(EINVAL);
314 }
315
316 /**
317  * Generate 'connect' call and send it to the server.
318  */
319 static int gen_connect(URLContext *s, RTMPContext *rt)
320 {
321     RTMPPacket pkt;
322     uint8_t *p;
323     int ret;
324
325     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
326                                      0, 4096 + APP_MAX_LENGTH)) < 0)
327         return ret;
328
329     p = pkt.data;
330
331     ff_amf_write_string(&p, "connect");
332     ff_amf_write_number(&p, ++rt->nb_invokes);
333     ff_amf_write_object_start(&p);
334     ff_amf_write_field_name(&p, "app");
335     ff_amf_write_string2(&p, rt->app, rt->auth_params);
336
337     if (!rt->is_input) {
338         ff_amf_write_field_name(&p, "type");
339         ff_amf_write_string(&p, "nonprivate");
340     }
341     ff_amf_write_field_name(&p, "flashVer");
342     ff_amf_write_string(&p, rt->flashver);
343
344     if (rt->swfurl) {
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_SYSTEM_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         RTMP_CLIENT_VER1,
1232         RTMP_CLIENT_VER2,
1233         RTMP_CLIENT_VER3,
1234         RTMP_CLIENT_VER4,
1235     };
1236     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1237     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1238     int i;
1239     int server_pos, client_pos;
1240     uint8_t digest[32], signature[32];
1241     int ret, type = 0;
1242
1243     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1244
1245     av_lfg_init(&rnd, 0xDEADC0DE);
1246     // generate handshake packet - 1536 bytes of pseudorandom data
1247     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1248         tosend[i] = av_lfg_get(&rnd) >> 24;
1249
1250     if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1251         /* When the client wants to use RTMPE, we have to change the command
1252          * byte to 0x06 which means to use encrypted data and we have to set
1253          * the flash version to at least 9.0.115.0. */
1254         tosend[0] = 6;
1255         tosend[5] = 128;
1256         tosend[6] = 0;
1257         tosend[7] = 3;
1258         tosend[8] = 2;
1259
1260         /* Initialize the Diffie-Hellmann context and generate the public key
1261          * to send to the server. */
1262         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1263             return ret;
1264     }
1265
1266     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1267     if (client_pos < 0)
1268         return client_pos;
1269
1270     if ((ret = ffurl_write(rt->stream, tosend,
1271                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1272         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1273         return ret;
1274     }
1275
1276     if ((ret = ffurl_read_complete(rt->stream, serverdata,
1277                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1278         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1279         return ret;
1280     }
1281
1282     if ((ret = ffurl_read_complete(rt->stream, clientdata,
1283                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1284         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1285         return ret;
1286     }
1287
1288     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1289     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1290            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1291
1292     if (rt->is_input && serverdata[5] >= 3) {
1293         server_pos = rtmp_validate_digest(serverdata + 1, 772);
1294         if (server_pos < 0)
1295             return server_pos;
1296
1297         if (!server_pos) {
1298             type = 1;
1299             server_pos = rtmp_validate_digest(serverdata + 1, 8);
1300             if (server_pos < 0)
1301                 return server_pos;
1302
1303             if (!server_pos) {
1304                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1305                 return AVERROR(EIO);
1306             }
1307         }
1308
1309         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1310          * key are the last 32 bytes of the server handshake. */
1311         if (rt->swfsize) {
1312             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1313                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1314                 return ret;
1315         }
1316
1317         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1318                                   rtmp_server_key, sizeof(rtmp_server_key),
1319                                   digest);
1320         if (ret < 0)
1321             return ret;
1322
1323         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1324                                   0, digest, 32, signature);
1325         if (ret < 0)
1326             return ret;
1327
1328         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1329             /* Compute the shared secret key sent by the server and initialize
1330              * the RC4 encryption. */
1331             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1332                                                    tosend + 1, type)) < 0)
1333                 return ret;
1334
1335             /* Encrypt the signature received by the server. */
1336             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1337         }
1338
1339         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1340             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1341             return AVERROR(EIO);
1342         }
1343
1344         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1345             tosend[i] = av_lfg_get(&rnd) >> 24;
1346         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1347                                   rtmp_player_key, sizeof(rtmp_player_key),
1348                                   digest);
1349         if (ret < 0)
1350             return ret;
1351
1352         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1353                                   digest, 32,
1354                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1355         if (ret < 0)
1356             return ret;
1357
1358         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1359             /* Encrypt the signature to be send to the server. */
1360             ff_rtmpe_encrypt_sig(rt->stream, tosend +
1361                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1362                                  serverdata[0]);
1363         }
1364
1365         // write reply back to the server
1366         if ((ret = ffurl_write(rt->stream, tosend,
1367                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1368             return ret;
1369
1370         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1371             /* Set RC4 keys for encryption and update the keystreams. */
1372             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1373                 return ret;
1374         }
1375     } else {
1376         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1377             /* Compute the shared secret key sent by the server and initialize
1378              * the RC4 encryption. */
1379             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1380                             tosend + 1, 1)) < 0)
1381                 return ret;
1382
1383             if (serverdata[0] == 9) {
1384                 /* Encrypt the signature received by the server. */
1385                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1386                                      serverdata[0]);
1387             }
1388         }
1389
1390         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1391                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1392             return ret;
1393
1394         if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1395             /* Set RC4 keys for encryption and update the keystreams. */
1396             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1397                 return ret;
1398         }
1399     }
1400
1401     return 0;
1402 }
1403
1404 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1405                                   uint32_t *second_int, char *arraydata,
1406                                   int size)
1407 {
1408     int inoutsize;
1409
1410     inoutsize = ffurl_read_complete(rt->stream, arraydata,
1411                                     RTMP_HANDSHAKE_PACKET_SIZE);
1412     if (inoutsize <= 0)
1413         return AVERROR(EIO);
1414     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1415         av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1416                " not following standard\n", (int)inoutsize);
1417         return AVERROR(EINVAL);
1418     }
1419
1420     *first_int  = AV_RB32(arraydata);
1421     *second_int = AV_RB32(arraydata + 4);
1422     return 0;
1423 }
1424
1425 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1426                                uint32_t second_int, char *arraydata, int size)
1427 {
1428     int inoutsize;
1429
1430     AV_WB32(arraydata, first_int);
1431     AV_WB32(arraydata + 4, second_int);
1432     inoutsize = ffurl_write(rt->stream, arraydata,
1433                             RTMP_HANDSHAKE_PACKET_SIZE);
1434     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1435         av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1436         return AVERROR(EIO);
1437     }
1438
1439     return 0;
1440 }
1441
1442 /**
1443  * rtmp handshake server side
1444  */
1445 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1446 {
1447     uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1448     uint32_t hs_epoch;
1449     uint32_t hs_my_epoch;
1450     uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1451     uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1452     uint32_t zeroes;
1453     uint32_t temp       = 0;
1454     int randomidx       = 0;
1455     int inoutsize       = 0;
1456     int ret;
1457
1458     inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1459     if (inoutsize <= 0) {
1460         av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1461         return AVERROR(EIO);
1462     }
1463     // Check Version
1464     if (buffer[0] != 3) {
1465         av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1466         return AVERROR(EIO);
1467     }
1468     if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1469         av_log(s, AV_LOG_ERROR,
1470                "Unable to write answer - RTMP S0\n");
1471         return AVERROR(EIO);
1472     }
1473     /* Receive C1 */
1474     ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1475                                  RTMP_HANDSHAKE_PACKET_SIZE);
1476     if (ret) {
1477         av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1478         return ret;
1479     }
1480     /* Send S1 */
1481     /* By now same epoch will be sent */
1482     hs_my_epoch = hs_epoch;
1483     /* Generate random */
1484     for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1485          randomidx += 4)
1486         AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1487
1488     ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1489                               RTMP_HANDSHAKE_PACKET_SIZE);
1490     if (ret) {
1491         av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1492         return ret;
1493     }
1494     /* Send S2 */
1495     ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1496                               RTMP_HANDSHAKE_PACKET_SIZE);
1497     if (ret) {
1498         av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1499         return ret;
1500     }
1501     /* Receive C2 */
1502     ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1503                                  RTMP_HANDSHAKE_PACKET_SIZE);
1504     if (ret) {
1505         av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1506         return ret;
1507     }
1508     if (temp != hs_my_epoch)
1509         av_log(s, AV_LOG_WARNING,
1510                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1511     if (memcmp(buffer + 8, hs_s1 + 8,
1512                RTMP_HANDSHAKE_PACKET_SIZE - 8))
1513         av_log(s, AV_LOG_WARNING,
1514                "Erroneous C2 Message random does not match up\n");
1515
1516     return 0;
1517 }
1518
1519 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1520 {
1521     RTMPContext *rt = s->priv_data;
1522     int ret;
1523
1524     if (pkt->size < 4) {
1525         av_log(s, AV_LOG_ERROR,
1526                "Too short chunk size change packet (%d)\n",
1527                pkt->size);
1528         return AVERROR_INVALIDDATA;
1529     }
1530
1531     if (!rt->is_input) {
1532         /* Send the same chunk size change packet back to the server,
1533          * setting the outgoing chunk size to the same as the incoming one. */
1534         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1535                                         &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1536             return ret;
1537         rt->out_chunk_size = AV_RB32(pkt->data);
1538     }
1539
1540     rt->in_chunk_size = AV_RB32(pkt->data);
1541     if (rt->in_chunk_size <= 0) {
1542         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1543                rt->in_chunk_size);
1544         return AVERROR_INVALIDDATA;
1545     }
1546     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1547            rt->in_chunk_size);
1548
1549     return 0;
1550 }
1551
1552 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1553 {
1554     RTMPContext *rt = s->priv_data;
1555     int t, ret;
1556
1557     if (pkt->size < 2) {
1558         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1559                pkt->size);
1560         return AVERROR_INVALIDDATA;
1561     }
1562
1563     t = AV_RB16(pkt->data);
1564     if (t == 6) {
1565         if ((ret = gen_pong(s, rt, pkt)) < 0)
1566             return ret;
1567     } else if (t == 26) {
1568         if (rt->swfsize) {
1569             if ((ret = gen_swf_verification(s, rt)) < 0)
1570                 return ret;
1571         } else {
1572             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1573         }
1574     }
1575
1576     return 0;
1577 }
1578
1579 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1580 {
1581     RTMPContext *rt = s->priv_data;
1582
1583     if (pkt->size < 4) {
1584         av_log(s, AV_LOG_ERROR,
1585                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1586                pkt->size);
1587         return AVERROR_INVALIDDATA;
1588     }
1589
1590     rt->client_report_size = AV_RB32(pkt->data);
1591     if (rt->client_report_size <= 0) {
1592         av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1593                 rt->client_report_size);
1594         return AVERROR_INVALIDDATA;
1595
1596     }
1597     av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1598     rt->client_report_size >>= 1;
1599
1600     return 0;
1601 }
1602
1603 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1604 {
1605     RTMPContext *rt = s->priv_data;
1606
1607     if (pkt->size < 4) {
1608         av_log(s, AV_LOG_ERROR,
1609                "Too short server bandwidth report packet (%d)\n",
1610                pkt->size);
1611         return AVERROR_INVALIDDATA;
1612     }
1613
1614     rt->server_bw = AV_RB32(pkt->data);
1615     if (rt->server_bw <= 0) {
1616         av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1617                rt->server_bw);
1618         return AVERROR_INVALIDDATA;
1619     }
1620     av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1621
1622     return 0;
1623 }
1624
1625 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1626                          const char *opaque, const char *challenge)
1627 {
1628     uint8_t hash[16];
1629     char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1630     struct AVMD5 *md5 = av_md5_alloc();
1631     if (!md5)
1632         return AVERROR(ENOMEM);
1633
1634     snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1635
1636     av_md5_init(md5);
1637     av_md5_update(md5, user, strlen(user));
1638     av_md5_update(md5, salt, strlen(salt));
1639     av_md5_update(md5, rt->password, strlen(rt->password));
1640     av_md5_final(md5, hash);
1641     av_base64_encode(hashstr, sizeof(hashstr), hash,
1642                      sizeof(hash));
1643     av_md5_init(md5);
1644     av_md5_update(md5, hashstr, strlen(hashstr));
1645     if (opaque)
1646         av_md5_update(md5, opaque, strlen(opaque));
1647     else if (challenge)
1648         av_md5_update(md5, challenge, strlen(challenge));
1649     av_md5_update(md5, challenge2, strlen(challenge2));
1650     av_md5_final(md5, hash);
1651     av_base64_encode(hashstr, sizeof(hashstr), hash,
1652                      sizeof(hash));
1653     snprintf(rt->auth_params, sizeof(rt->auth_params),
1654              "?authmod=%s&user=%s&challenge=%s&response=%s",
1655              "adobe", user, challenge2, hashstr);
1656     if (opaque)
1657         av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1658                     "&opaque=%s", opaque);
1659
1660     av_free(md5);
1661     return 0;
1662 }
1663
1664 static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1665 {
1666     uint8_t hash[16];
1667     char hashstr1[33], hashstr2[33];
1668     const char *realm = "live";
1669     const char *method = "publish";
1670     const char *qop = "auth";
1671     const char *nc = "00000001";
1672     char cnonce[10];
1673     struct AVMD5 *md5 = av_md5_alloc();
1674     if (!md5)
1675         return AVERROR(ENOMEM);
1676
1677     snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1678
1679     av_md5_init(md5);
1680     av_md5_update(md5, user, strlen(user));
1681     av_md5_update(md5, ":", 1);
1682     av_md5_update(md5, realm, strlen(realm));
1683     av_md5_update(md5, ":", 1);
1684     av_md5_update(md5, rt->password, strlen(rt->password));
1685     av_md5_final(md5, hash);
1686     ff_data_to_hex(hashstr1, hash, 16, 1);
1687     hashstr1[32] = '\0';
1688
1689     av_md5_init(md5);
1690     av_md5_update(md5, method, strlen(method));
1691     av_md5_update(md5, ":/", 2);
1692     av_md5_update(md5, rt->app, strlen(rt->app));
1693     if (!strchr(rt->app, '/'))
1694         av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1695     av_md5_final(md5, hash);
1696     ff_data_to_hex(hashstr2, hash, 16, 1);
1697     hashstr2[32] = '\0';
1698
1699     av_md5_init(md5);
1700     av_md5_update(md5, hashstr1, strlen(hashstr1));
1701     av_md5_update(md5, ":", 1);
1702     if (nonce)
1703         av_md5_update(md5, nonce, strlen(nonce));
1704     av_md5_update(md5, ":", 1);
1705     av_md5_update(md5, nc, strlen(nc));
1706     av_md5_update(md5, ":", 1);
1707     av_md5_update(md5, cnonce, strlen(cnonce));
1708     av_md5_update(md5, ":", 1);
1709     av_md5_update(md5, qop, strlen(qop));
1710     av_md5_update(md5, ":", 1);
1711     av_md5_update(md5, hashstr2, strlen(hashstr2));
1712     av_md5_final(md5, hash);
1713     ff_data_to_hex(hashstr1, hash, 16, 1);
1714
1715     snprintf(rt->auth_params, sizeof(rt->auth_params),
1716              "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1717              "llnw", user, nonce, cnonce, nc, hashstr1);
1718
1719     av_free(md5);
1720     return 0;
1721 }
1722
1723 static int handle_connect_error(URLContext *s, const char *desc)
1724 {
1725     RTMPContext *rt = s->priv_data;
1726     char buf[300], *ptr, authmod[15];
1727     int i = 0, ret = 0;
1728     const char *user = "", *salt = "", *opaque = NULL,
1729                *challenge = NULL, *cptr = NULL, *nonce = NULL;
1730
1731     if (!(cptr = strstr(desc, "authmod=adobe")) &&
1732         !(cptr = strstr(desc, "authmod=llnw"))) {
1733         av_log(s, AV_LOG_ERROR,
1734                "Unknown connect error (unsupported authentication method?)\n");
1735         return AVERROR_UNKNOWN;
1736     }
1737     cptr += strlen("authmod=");
1738     while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1739         authmod[i++] = *cptr++;
1740     authmod[i] = '\0';
1741
1742     if (!rt->username[0] || !rt->password[0]) {
1743         av_log(s, AV_LOG_ERROR, "No credentials set\n");
1744         return AVERROR_UNKNOWN;
1745     }
1746
1747     if (strstr(desc, "?reason=authfailed")) {
1748         av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1749         return AVERROR_UNKNOWN;
1750     } else if (strstr(desc, "?reason=nosuchuser")) {
1751         av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1752         return AVERROR_UNKNOWN;
1753     }
1754
1755     if (rt->auth_tried) {
1756         av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1757         return AVERROR_UNKNOWN;
1758     }
1759
1760     rt->auth_params[0] = '\0';
1761
1762     if (strstr(desc, "code=403 need auth")) {
1763         snprintf(rt->auth_params, sizeof(rt->auth_params),
1764                  "?authmod=%s&user=%s", authmod, rt->username);
1765         return 0;
1766     }
1767
1768     if (!(cptr = strstr(desc, "?reason=needauth"))) {
1769         av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1770         return AVERROR_UNKNOWN;
1771     }
1772
1773     av_strlcpy(buf, cptr + 1, sizeof(buf));
1774     ptr = buf;
1775
1776     while (ptr) {
1777         char *next  = strchr(ptr, '&');
1778         char *value = strchr(ptr, '=');
1779         if (next)
1780             *next++ = '\0';
1781         if (value) {
1782             *value++ = '\0';
1783             if (!strcmp(ptr, "user")) {
1784                 user = value;
1785             } else if (!strcmp(ptr, "salt")) {
1786                 salt = value;
1787             } else if (!strcmp(ptr, "opaque")) {
1788                 opaque = value;
1789             } else if (!strcmp(ptr, "challenge")) {
1790                 challenge = value;
1791             } else if (!strcmp(ptr, "nonce")) {
1792                 nonce = value;
1793             } else {
1794                 av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1795             }
1796         } else {
1797             av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1798         }
1799         ptr = next;
1800     }
1801
1802     if (!strcmp(authmod, "adobe")) {
1803         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1804             return ret;
1805     } else {
1806         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1807             return ret;
1808     }
1809
1810     rt->auth_tried = 1;
1811     return 0;
1812 }
1813
1814 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1815 {
1816     RTMPContext *rt = s->priv_data;
1817     const uint8_t *data_end = pkt->data + pkt->size;
1818     char *tracked_method = NULL;
1819     int level = AV_LOG_ERROR;
1820     uint8_t tmpstr[256];
1821     int ret;
1822
1823     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1824         return ret;
1825
1826     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1827                                 "description", tmpstr, sizeof(tmpstr))) {
1828         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1829                                !strcmp(tracked_method, "releaseStream") ||
1830                                !strcmp(tracked_method, "FCSubscribe")   ||
1831                                !strcmp(tracked_method, "FCPublish"))) {
1832             /* Gracefully ignore Adobe-specific historical artifact errors. */
1833             level = AV_LOG_WARNING;
1834             ret = 0;
1835         } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
1836             level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
1837             ret = 0;
1838         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1839             ret = handle_connect_error(s, tmpstr);
1840             if (!ret) {
1841                 rt->do_reconnect = 1;
1842                 level = AV_LOG_VERBOSE;
1843             }
1844         } else
1845             ret = AVERROR_UNKNOWN;
1846         av_log(s, level, "Server error: %s\n", tmpstr);
1847     }
1848
1849     av_free(tracked_method);
1850     return ret;
1851 }
1852
1853 static int write_begin(URLContext *s)
1854 {
1855     RTMPContext *rt = s->priv_data;
1856     PutByteContext pbc;
1857     RTMPPacket spkt = { 0 };
1858     int ret;
1859
1860     // Send Stream Begin 1
1861     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1862                                      RTMP_PT_PING, 0, 6)) < 0) {
1863         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1864         return ret;
1865     }
1866
1867     bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1868     bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1869     bytestream2_put_be32(&pbc, rt->nb_streamid);
1870
1871     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1872                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1873
1874     ff_rtmp_packet_destroy(&spkt);
1875
1876     return ret;
1877 }
1878
1879 static int write_status(URLContext *s, RTMPPacket *pkt,
1880                         const char *status, const char *filename)
1881 {
1882     RTMPContext *rt = s->priv_data;
1883     RTMPPacket spkt = { 0 };
1884     char statusmsg[128];
1885     uint8_t *pp;
1886     int ret;
1887
1888     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1889                                      RTMP_PT_INVOKE, 0,
1890                                      RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1891         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1892         return ret;
1893     }
1894
1895     pp = spkt.data;
1896     spkt.extra = pkt->extra;
1897     ff_amf_write_string(&pp, "onStatus");
1898     ff_amf_write_number(&pp, 0);
1899     ff_amf_write_null(&pp);
1900
1901     ff_amf_write_object_start(&pp);
1902     ff_amf_write_field_name(&pp, "level");
1903     ff_amf_write_string(&pp, "status");
1904     ff_amf_write_field_name(&pp, "code");
1905     ff_amf_write_string(&pp, status);
1906     ff_amf_write_field_name(&pp, "description");
1907     snprintf(statusmsg, sizeof(statusmsg),
1908              "%s is now published", filename);
1909     ff_amf_write_string(&pp, statusmsg);
1910     ff_amf_write_field_name(&pp, "details");
1911     ff_amf_write_string(&pp, filename);
1912     ff_amf_write_field_name(&pp, "clientid");
1913     snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1914     ff_amf_write_string(&pp, statusmsg);
1915     ff_amf_write_object_end(&pp);
1916
1917     spkt.size = pp - spkt.data;
1918     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1919                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1920     ff_rtmp_packet_destroy(&spkt);
1921
1922     return ret;
1923 }
1924
1925 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1926 {
1927     RTMPContext *rt = s->priv_data;
1928     double seqnum;
1929     char filename[128];
1930     char command[64];
1931     int stringlen;
1932     char *pchar;
1933     const uint8_t *p = pkt->data;
1934     uint8_t *pp      = NULL;
1935     RTMPPacket spkt  = { 0 };
1936     GetByteContext gbc;
1937     int ret;
1938
1939     bytestream2_init(&gbc, p, pkt->size);
1940     if (ff_amf_read_string(&gbc, command, sizeof(command),
1941                            &stringlen)) {
1942         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1943         return AVERROR_INVALIDDATA;
1944     }
1945
1946     ret = ff_amf_read_number(&gbc, &seqnum);
1947     if (ret)
1948         return ret;
1949     ret = ff_amf_read_null(&gbc);
1950     if (ret)
1951         return ret;
1952     if (!strcmp(command, "FCPublish") ||
1953         !strcmp(command, "publish")) {
1954         ret = ff_amf_read_string(&gbc, filename,
1955                                  sizeof(filename), &stringlen);
1956         if (ret) {
1957             if (ret == AVERROR(EINVAL))
1958                 av_log(s, AV_LOG_ERROR, "Unable to parse stream name - name too long?\n");
1959             else
1960                 av_log(s, AV_LOG_ERROR, "Unable to parse stream name\n");
1961             return ret;
1962         }
1963         // check with url
1964         if (s->filename) {
1965             pchar = strrchr(s->filename, '/');
1966             if (!pchar) {
1967                 av_log(s, AV_LOG_WARNING,
1968                        "Unable to find / in url %s, bad format\n",
1969                        s->filename);
1970                 pchar = s->filename;
1971             }
1972             pchar++;
1973             if (strcmp(pchar, filename))
1974                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1975                        " %s\n", filename, pchar);
1976         }
1977         rt->state = STATE_RECEIVING;
1978     }
1979
1980     if (!strcmp(command, "FCPublish")) {
1981         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1982                                          RTMP_PT_INVOKE, 0,
1983                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1984             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1985             return ret;
1986         }
1987         pp = spkt.data;
1988         ff_amf_write_string(&pp, "onFCPublish");
1989     } else if (!strcmp(command, "publish")) {
1990         ret = write_begin(s);
1991         if (ret < 0)
1992             return ret;
1993
1994         // Send onStatus(NetStream.Publish.Start)
1995         return write_status(s, pkt, "NetStream.Publish.Start",
1996                            filename);
1997     } else if (!strcmp(command, "play")) {
1998         ret = write_begin(s);
1999         if (ret < 0)
2000             return ret;
2001         rt->state = STATE_SENDING;
2002         return write_status(s, pkt, "NetStream.Play.Start",
2003                             filename);
2004     } else {
2005         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
2006                                          RTMP_PT_INVOKE, 0,
2007                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
2008             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
2009             return ret;
2010         }
2011         pp = spkt.data;
2012         ff_amf_write_string(&pp, "_result");
2013         ff_amf_write_number(&pp, seqnum);
2014         ff_amf_write_null(&pp);
2015         if (!strcmp(command, "createStream")) {
2016             rt->nb_streamid++;
2017             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
2018                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
2019             ff_amf_write_number(&pp, rt->nb_streamid);
2020             /* By now we don't control which streams are removed in
2021              * deleteStream. There is no stream creation control
2022              * if a client creates more than 2^32 - 2 streams. */
2023         }
2024     }
2025     spkt.size = pp - spkt.data;
2026     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
2027                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
2028     ff_rtmp_packet_destroy(&spkt);
2029     return ret;
2030 }
2031
2032 /**
2033  * Read the AMF_NUMBER response ("_result") to a function call
2034  * (e.g. createStream()). This response should be made up of the AMF_STRING
2035  * "result", a NULL object and then the response encoded as AMF_NUMBER. On a
2036  * successful response, we will return set the value to number (otherwise number
2037  * will not be changed).
2038  *
2039  * @return 0 if reading the value succeeds, negative value otherwise
2040  */
2041 static int read_number_result(RTMPPacket *pkt, double *number)
2042 {
2043     // We only need to fit "_result" in this.
2044     uint8_t strbuffer[8];
2045     int stringlen;
2046     double numbuffer;
2047     GetByteContext gbc;
2048
2049     bytestream2_init(&gbc, pkt->data, pkt->size);
2050
2051     // Value 1/4: "_result" as AMF_STRING
2052     if (ff_amf_read_string(&gbc, strbuffer, sizeof(strbuffer), &stringlen))
2053         return AVERROR_INVALIDDATA;
2054     if (strcmp(strbuffer, "_result"))
2055         return AVERROR_INVALIDDATA;
2056     // Value 2/4: The callee reference number
2057     if (ff_amf_read_number(&gbc, &numbuffer))
2058         return AVERROR_INVALIDDATA;
2059     // Value 3/4: Null
2060     if (ff_amf_read_null(&gbc))
2061         return AVERROR_INVALIDDATA;
2062     // Value 4/4: The response as AMF_NUMBER
2063     if (ff_amf_read_number(&gbc, &numbuffer))
2064         return AVERROR_INVALIDDATA;
2065     else
2066         *number = numbuffer;
2067
2068     return 0;
2069 }
2070
2071 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
2072 {
2073     RTMPContext *rt = s->priv_data;
2074     char *tracked_method = NULL;
2075     int ret = 0;
2076
2077     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
2078         return ret;
2079
2080     if (!tracked_method) {
2081         /* Ignore this reply when the current method is not tracked. */
2082         return ret;
2083     }
2084
2085     if (!strcmp(tracked_method, "connect")) {
2086         if (!rt->is_input) {
2087             if ((ret = gen_release_stream(s, rt)) < 0)
2088                 goto fail;
2089
2090             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
2091                 goto fail;
2092         } else {
2093             if ((ret = gen_server_bw(s, rt)) < 0)
2094                 goto fail;
2095         }
2096
2097         if ((ret = gen_create_stream(s, rt)) < 0)
2098             goto fail;
2099
2100         if (rt->is_input) {
2101             /* Send the FCSubscribe command when the name of live
2102              * stream is defined by the user or if it's a live stream. */
2103             if (rt->subscribe) {
2104                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
2105                     goto fail;
2106             } else if (rt->live == -1) {
2107                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
2108                     goto fail;
2109             }
2110         }
2111     } else if (!strcmp(tracked_method, "createStream")) {
2112         double stream_id;
2113         if (read_number_result(pkt, &stream_id)) {
2114             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2115         } else {
2116             rt->stream_id = stream_id;
2117         }
2118
2119         if (!rt->is_input) {
2120             if ((ret = gen_publish(s, rt)) < 0)
2121                 goto fail;
2122         } else {
2123             if (rt->live != -1) {
2124                 if ((ret = gen_get_stream_length(s, rt)) < 0)
2125                     goto fail;
2126             }
2127             if ((ret = gen_play(s, rt)) < 0)
2128                 goto fail;
2129             if ((ret = gen_buffer_time(s, rt)) < 0)
2130                 goto fail;
2131         }
2132     } else if (!strcmp(tracked_method, "getStreamLength")) {
2133         if (read_number_result(pkt, &rt->duration)) {
2134             av_log(s, AV_LOG_WARNING, "Unexpected reply on getStreamLength()\n");
2135         }
2136     }
2137
2138 fail:
2139     av_free(tracked_method);
2140     return ret;
2141 }
2142
2143 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2144 {
2145     RTMPContext *rt = s->priv_data;
2146     const uint8_t *data_end = pkt->data + pkt->size;
2147     const uint8_t *ptr = pkt->data + RTMP_HEADER;
2148     uint8_t tmpstr[256];
2149     int i, t;
2150
2151     for (i = 0; i < 2; i++) {
2152         t = ff_amf_tag_size(ptr, data_end);
2153         if (t < 0)
2154             return 1;
2155         ptr += t;
2156     }
2157
2158     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2159     if (!t && !strcmp(tmpstr, "error")) {
2160         t = ff_amf_get_field_value(ptr, data_end,
2161                                    "description", tmpstr, sizeof(tmpstr));
2162         if (t || !tmpstr[0])
2163             t = ff_amf_get_field_value(ptr, data_end, "code",
2164                                        tmpstr, sizeof(tmpstr));
2165         if (!t)
2166             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2167         return -1;
2168     }
2169
2170     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2171     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2172     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2173     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2174     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2175     if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2176
2177     return 0;
2178 }
2179
2180 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2181 {
2182     RTMPContext *rt = s->priv_data;
2183     int ret = 0;
2184
2185     //TODO: check for the messages sent for wrong state?
2186     if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2187         if ((ret = handle_invoke_error(s, pkt)) < 0)
2188             return ret;
2189     } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2190         if ((ret = handle_invoke_result(s, pkt)) < 0)
2191             return ret;
2192     } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2193         if ((ret = handle_invoke_status(s, pkt)) < 0)
2194             return ret;
2195     } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2196         if ((ret = gen_check_bw(s, rt)) < 0)
2197             return ret;
2198     } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2199                ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
2200                ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
2201                ff_amf_match_string(pkt->data, pkt->size, "play")          ||
2202                ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
2203                ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2204         if ((ret = send_invoke_response(s, pkt)) < 0)
2205             return ret;
2206     }
2207
2208     return ret;
2209 }
2210
2211 static int update_offset(RTMPContext *rt, int size)
2212 {
2213     int old_flv_size;
2214
2215     // generate packet header and put data into buffer for FLV demuxer
2216     if (rt->flv_off < rt->flv_size) {
2217         // There is old unread data in the buffer, thus append at the end
2218         old_flv_size  = rt->flv_size;
2219         rt->flv_size += size;
2220     } else {
2221         // All data has been read, write the new data at the start of the buffer
2222         old_flv_size = 0;
2223         rt->flv_size = size;
2224         rt->flv_off  = 0;
2225     }
2226
2227     return old_flv_size;
2228 }
2229
2230 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2231 {
2232     int old_flv_size, ret;
2233     PutByteContext pbc;
2234     const uint8_t *data = pkt->data + skip;
2235     const int size      = pkt->size - skip;
2236     uint32_t ts         = pkt->timestamp;
2237
2238     if (pkt->type == RTMP_PT_AUDIO) {
2239         rt->has_audio = 1;
2240     } else if (pkt->type == RTMP_PT_VIDEO) {
2241         rt->has_video = 1;
2242     }
2243
2244     old_flv_size = update_offset(rt, size + 15);
2245
2246     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2247         rt->flv_size = rt->flv_off = 0;
2248         return ret;
2249     }
2250     bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2251     bytestream2_skip_p(&pbc, old_flv_size);
2252     bytestream2_put_byte(&pbc, pkt->type);
2253     bytestream2_put_be24(&pbc, size);
2254     bytestream2_put_be24(&pbc, ts);
2255     bytestream2_put_byte(&pbc, ts >> 24);
2256     bytestream2_put_be24(&pbc, 0);
2257     bytestream2_put_buffer(&pbc, data, size);
2258     bytestream2_put_be32(&pbc, size + RTMP_HEADER);
2259
2260     return 0;
2261 }
2262
2263 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2264 {
2265     RTMPContext *rt  = s->priv_data;
2266     uint8_t commandbuffer[64];
2267     char statusmsg[128];
2268     int stringlen, ret, skip = 0;
2269     GetByteContext gbc;
2270
2271     bytestream2_init(&gbc, pkt->data, pkt->size);
2272     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2273                            &stringlen))
2274         return AVERROR_INVALIDDATA;
2275
2276     if (!strcmp(commandbuffer, "onMetaData")) {
2277         // metadata properties should be stored in a mixed array
2278         if (bytestream2_get_byte(&gbc) == AMF_DATA_TYPE_MIXEDARRAY) {
2279             // We have found a metaData Array so flv can determine the streams
2280             // from this.
2281             rt->received_metadata = 1;
2282             // skip 32-bit max array index
2283             bytestream2_skip(&gbc, 4);
2284             while (bytestream2_get_bytes_left(&gbc) > 3) {
2285                 if (ff_amf_get_string(&gbc, statusmsg, sizeof(statusmsg),
2286                                       &stringlen))
2287                     return AVERROR_INVALIDDATA;
2288                 // We do not care about the content of the property (yet).
2289                 stringlen = ff_amf_tag_size(gbc.buffer, gbc.buffer_end);
2290                 if (stringlen < 0)
2291                     return AVERROR_INVALIDDATA;
2292                 bytestream2_skip(&gbc, stringlen);
2293
2294                 // The presence of the following properties indicates that the
2295                 // respective streams are present.
2296                 if (!strcmp(statusmsg, "videocodecid")) {
2297                     rt->has_video = 1;
2298                 }
2299                 if (!strcmp(statusmsg, "audiocodecid")) {
2300                     rt->has_audio = 1;
2301                 }
2302             }
2303             if (bytestream2_get_be24(&gbc) != AMF_END_OF_OBJECT)
2304                 return AVERROR_INVALIDDATA;
2305         }
2306     }
2307
2308     // Skip the @setDataFrame string and validate it is a notification
2309     if (!strcmp(commandbuffer, "@setDataFrame")) {
2310         skip = gbc.buffer - pkt->data;
2311         ret = ff_amf_read_string(&gbc, statusmsg,
2312                                  sizeof(statusmsg), &stringlen);
2313         if (ret < 0)
2314             return AVERROR_INVALIDDATA;
2315     }
2316
2317     return append_flv_data(rt, pkt, skip);
2318 }
2319
2320 /**
2321  * Parse received packet and possibly perform some action depending on
2322  * the packet contents.
2323  * @return 0 for no errors, negative values for serious errors which prevent
2324  *         further communications, positive values for uncritical errors
2325  */
2326 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2327 {
2328     int ret;
2329
2330 #ifdef DEBUG
2331     ff_rtmp_packet_dump(s, pkt);
2332 #endif
2333
2334     switch (pkt->type) {
2335     case RTMP_PT_BYTES_READ:
2336         av_log(s, AV_LOG_TRACE, "received bytes read report\n");
2337         break;
2338     case RTMP_PT_CHUNK_SIZE:
2339         if ((ret = handle_chunk_size(s, pkt)) < 0)
2340             return ret;
2341         break;
2342     case RTMP_PT_PING:
2343         if ((ret = handle_ping(s, pkt)) < 0)
2344             return ret;
2345         break;
2346     case RTMP_PT_CLIENT_BW:
2347         if ((ret = handle_client_bw(s, pkt)) < 0)
2348             return ret;
2349         break;
2350     case RTMP_PT_SERVER_BW:
2351         if ((ret = handle_server_bw(s, pkt)) < 0)
2352             return ret;
2353         break;
2354     case RTMP_PT_INVOKE:
2355         if ((ret = handle_invoke(s, pkt)) < 0)
2356             return ret;
2357         break;
2358     case RTMP_PT_VIDEO:
2359     case RTMP_PT_AUDIO:
2360     case RTMP_PT_METADATA:
2361     case RTMP_PT_NOTIFY:
2362         /* Audio, Video and Metadata packets are parsed in get_packet() */
2363         break;
2364     default:
2365         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2366         break;
2367     }
2368     return 0;
2369 }
2370
2371 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2372 {
2373     int ret, old_flv_size, type;
2374     const uint8_t *next;
2375     uint8_t *p;
2376     uint32_t size;
2377     uint32_t ts, cts, pts = 0;
2378
2379     old_flv_size = update_offset(rt, pkt->size);
2380
2381     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2382         rt->flv_size = rt->flv_off = 0;
2383         return ret;
2384     }
2385
2386     next = pkt->data;
2387     p    = rt->flv_data + old_flv_size;
2388
2389     /* copy data while rewriting timestamps */
2390     ts = pkt->timestamp;
2391
2392     while (next - pkt->data < pkt->size - RTMP_HEADER) {
2393         type = bytestream_get_byte(&next);
2394         size = bytestream_get_be24(&next);
2395         cts  = bytestream_get_be24(&next);
2396         cts |= bytestream_get_byte(&next) << 24;
2397         if (!pts)
2398             pts = cts;
2399         ts += cts - pts;
2400         pts = cts;
2401         if (size + 3 + 4 > pkt->data + pkt->size - next)
2402             break;
2403         bytestream_put_byte(&p, type);
2404         bytestream_put_be24(&p, size);
2405         bytestream_put_be24(&p, ts);
2406         bytestream_put_byte(&p, ts >> 24);
2407         memcpy(p, next, size + 3 + 4);
2408         p    += size + 3;
2409         bytestream_put_be32(&p, size + RTMP_HEADER);
2410         next += size + 3 + 4;
2411     }
2412     if (p != rt->flv_data + rt->flv_size) {
2413         av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2414                                      "RTMP_PT_METADATA packet\n");
2415         rt->flv_size = p - rt->flv_data;
2416     }
2417
2418     return 0;
2419 }
2420
2421 /**
2422  * Interact with the server by receiving and sending RTMP packets until
2423  * there is some significant data (media data or expected status notification).
2424  *
2425  * @param s          reading context
2426  * @param for_header non-zero value tells function to work until it
2427  * gets notification from the server that playing has been started,
2428  * otherwise function will work until some media data is received (or
2429  * an error happens)
2430  * @return 0 for successful operation, negative value in case of error
2431  */
2432 static int get_packet(URLContext *s, int for_header)
2433 {
2434     RTMPContext *rt = s->priv_data;
2435     int ret;
2436
2437     if (rt->state == STATE_STOPPED)
2438         return AVERROR_EOF;
2439
2440     for (;;) {
2441         RTMPPacket rpkt = { 0 };
2442         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2443                                        rt->in_chunk_size, &rt->prev_pkt[0],
2444                                        &rt->nb_prev_pkt[0])) <= 0) {
2445             if (ret == 0) {
2446                 return AVERROR(EAGAIN);
2447             } else {
2448                 return AVERROR(EIO);
2449             }
2450         }
2451
2452         // Track timestamp for later use
2453         rt->last_timestamp = rpkt.timestamp;
2454
2455         rt->bytes_read += ret;
2456         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2457             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2458             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2459                 return ret;
2460             rt->last_bytes_read = rt->bytes_read;
2461         }
2462
2463         ret = rtmp_parse_result(s, rt, &rpkt);
2464
2465         // At this point we must check if we are in the seek state and continue
2466         // with the next packet. handle_invoke will get us out of this state
2467         // when the right message is encountered
2468         if (rt->state == STATE_SEEKING) {
2469             ff_rtmp_packet_destroy(&rpkt);
2470             // We continue, let the natural flow of things happen:
2471             // AVERROR(EAGAIN) or handle_invoke gets us out of here
2472             continue;
2473         }
2474
2475         if (ret < 0) {//serious error in current packet
2476             ff_rtmp_packet_destroy(&rpkt);
2477             return ret;
2478         }
2479         if (rt->do_reconnect && for_header) {
2480             ff_rtmp_packet_destroy(&rpkt);
2481             return 0;
2482         }
2483         if (rt->state == STATE_STOPPED) {
2484             ff_rtmp_packet_destroy(&rpkt);
2485             return AVERROR_EOF;
2486         }
2487         if (for_header && (rt->state == STATE_PLAYING    ||
2488                            rt->state == STATE_PUBLISHING ||
2489                            rt->state == STATE_SENDING    ||
2490                            rt->state == STATE_RECEIVING)) {
2491             ff_rtmp_packet_destroy(&rpkt);
2492             return 0;
2493         }
2494         if (!rpkt.size || !rt->is_input) {
2495             ff_rtmp_packet_destroy(&rpkt);
2496             continue;
2497         }
2498         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2499             ret = append_flv_data(rt, &rpkt, 0);
2500             ff_rtmp_packet_destroy(&rpkt);
2501             return ret;
2502         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2503             ret = handle_notify(s, &rpkt);
2504             ff_rtmp_packet_destroy(&rpkt);
2505             return ret;
2506         } else if (rpkt.type == RTMP_PT_METADATA) {
2507             ret = handle_metadata(rt, &rpkt);
2508             ff_rtmp_packet_destroy(&rpkt);
2509             return 0;
2510         }
2511         ff_rtmp_packet_destroy(&rpkt);
2512     }
2513 }
2514
2515 static int rtmp_close(URLContext *h)
2516 {
2517     RTMPContext *rt = h->priv_data;
2518     int ret = 0, i, j;
2519
2520     if (!rt->is_input) {
2521         rt->flv_data = NULL;
2522         if (rt->out_pkt.size)
2523             ff_rtmp_packet_destroy(&rt->out_pkt);
2524         if (rt->state > STATE_FCPUBLISH)
2525             ret = gen_fcunpublish_stream(h, rt);
2526     }
2527     if (rt->state > STATE_HANDSHAKED)
2528         ret = gen_delete_stream(h, rt);
2529     for (i = 0; i < 2; i++) {
2530         for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2531             ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2532         av_freep(&rt->prev_pkt[i]);
2533     }
2534
2535     free_tracked_methods(rt);
2536     av_freep(&rt->flv_data);
2537     ffurl_close(rt->stream);
2538     return ret;
2539 }
2540
2541 /**
2542  * Insert a fake onMetadata packet into the FLV stream to notify the FLV
2543  * demuxer about the duration of the stream.
2544  *
2545  * This should only be done if there was no real onMetadata packet sent by the
2546  * server at the start of the stream and if we were able to retrieve a valid
2547  * duration via a getStreamLength call.
2548  *
2549  * @return 0 for successful operation, negative value in case of error
2550  */
2551 static int inject_fake_duration_metadata(RTMPContext *rt)
2552 {
2553     // We need to insert the metadata packet directly after the FLV
2554     // header, i.e. we need to move all other already read data by the
2555     // size of our fake metadata packet.
2556
2557     uint8_t* p;
2558     // Keep old flv_data pointer
2559     uint8_t* old_flv_data = rt->flv_data;
2560     // Allocate a new flv_data pointer with enough space for the additional package
2561     if (!(rt->flv_data = av_malloc(rt->flv_size + 55))) {
2562         rt->flv_data = old_flv_data;
2563         return AVERROR(ENOMEM);
2564     }
2565
2566     // Copy FLV header
2567     memcpy(rt->flv_data, old_flv_data, 13);
2568     // Copy remaining packets
2569     memcpy(rt->flv_data + 13 + 55, old_flv_data + 13, rt->flv_size - 13);
2570     // Increase the size by the injected packet
2571     rt->flv_size += 55;
2572     // Delete the old FLV data
2573     av_freep(&old_flv_data);
2574
2575     p = rt->flv_data + 13;
2576     bytestream_put_byte(&p, FLV_TAG_TYPE_META);
2577     bytestream_put_be24(&p, 40); // size of data part (sum of all parts below)
2578     bytestream_put_be24(&p, 0);  // timestamp
2579     bytestream_put_be32(&p, 0);  // reserved
2580
2581     // first event name as a string
2582     bytestream_put_byte(&p, AMF_DATA_TYPE_STRING);
2583     // "onMetaData" as AMF string
2584     bytestream_put_be16(&p, 10);
2585     bytestream_put_buffer(&p, "onMetaData", 10);
2586
2587     // mixed array (hash) with size and string/type/data tuples
2588     bytestream_put_byte(&p, AMF_DATA_TYPE_MIXEDARRAY);
2589     bytestream_put_be32(&p, 1); // metadata_count
2590
2591     // "duration" as AMF string
2592     bytestream_put_be16(&p, 8);
2593     bytestream_put_buffer(&p, "duration", 8);
2594     bytestream_put_byte(&p, AMF_DATA_TYPE_NUMBER);
2595     bytestream_put_be64(&p, av_double2int(rt->duration));
2596
2597     // Finalise object
2598     bytestream_put_be16(&p, 0); // Empty string
2599     bytestream_put_byte(&p, AMF_END_OF_OBJECT);
2600     bytestream_put_be32(&p, 40 + RTMP_HEADER); // size of data part (sum of all parts above)
2601
2602     return 0;
2603 }
2604
2605 /**
2606  * Open RTMP connection and verify that the stream can be played.
2607  *
2608  * URL syntax: rtmp://server[:port][/app][/playpath]
2609  *             where 'app' is first one or two directories in the path
2610  *             (e.g. /ondemand/, /flash/live/, etc.)
2611  *             and 'playpath' is a file name (the rest of the path,
2612  *             may be prefixed with "mp4:")
2613  */
2614 static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
2615 {
2616     RTMPContext *rt = s->priv_data;
2617     char proto[8], hostname[256], path[1024], auth[100], *fname;
2618     char *old_app, *qmark, *n, fname_buffer[1024];
2619     uint8_t buf[2048];
2620     int port;
2621     int ret;
2622
2623     if (rt->listen_timeout > 0)
2624         rt->listen = 1;
2625
2626     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2627
2628     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2629                  hostname, sizeof(hostname), &port,
2630                  path, sizeof(path), s->filename);
2631
2632     n = strchr(path, ' ');
2633     if (n) {
2634         av_log(s, AV_LOG_WARNING,
2635                "Detected librtmp style URL parameters, these aren't supported "
2636                "by the libavformat internal RTMP handler currently enabled. "
2637                "See the documentation for the correct way to pass parameters.\n");
2638         *n = '\0'; // Trim not supported part
2639     }
2640
2641     if (auth[0]) {
2642         char *ptr = strchr(auth, ':');
2643         if (ptr) {
2644             *ptr = '\0';
2645             av_strlcpy(rt->username, auth, sizeof(rt->username));
2646             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2647         }
2648     }
2649
2650     if (rt->listen && strcmp(proto, "rtmp")) {
2651         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2652                proto);
2653         return AVERROR(EINVAL);
2654     }
2655     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2656         if (!strcmp(proto, "rtmpts"))
2657             av_dict_set(opts, "ffrtmphttp_tls", "1", 1);
2658
2659         /* open the http tunneling connection */
2660         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2661     } else if (!strcmp(proto, "rtmps")) {
2662         /* open the tls connection */
2663         if (port < 0)
2664             port = RTMPS_DEFAULT_PORT;
2665         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2666     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2667         if (!strcmp(proto, "rtmpte"))
2668             av_dict_set(opts, "ffrtmpcrypt_tunneling", "1", 1);
2669
2670         /* open the encrypted connection */
2671         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2672         rt->encrypted = 1;
2673     } else {
2674         /* open the tcp connection */
2675         if (port < 0)
2676             port = RTMP_DEFAULT_PORT;
2677         if (rt->listen)
2678             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2679                         "?listen&listen_timeout=%d",
2680                         rt->listen_timeout * 1000);
2681         else
2682             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2683     }
2684
2685 reconnect:
2686     if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2687                                     &s->interrupt_callback, opts,
2688                                     s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
2689         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2690         goto fail;
2691     }
2692
2693     if (rt->swfverify) {
2694         if ((ret = rtmp_calc_swfhash(s)) < 0)
2695             goto fail;
2696     }
2697
2698     rt->state = STATE_START;
2699     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2700         goto fail;
2701     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2702         goto fail;
2703
2704     rt->out_chunk_size = 128;
2705     rt->in_chunk_size  = 128; // Probably overwritten later
2706     rt->state = STATE_HANDSHAKED;
2707
2708     // Keep the application name when it has been defined by the user.
2709     old_app = rt->app;
2710
2711     rt->app = av_malloc(APP_MAX_LENGTH);
2712     if (!rt->app) {
2713         ret = AVERROR(ENOMEM);
2714         goto fail;
2715     }
2716
2717     //extract "app" part from path
2718     qmark = strchr(path, '?');
2719     if (qmark && strstr(qmark, "slist=")) {
2720         char* amp;
2721         // After slist we have the playpath, the full path is used as app
2722         av_strlcpy(rt->app, path + 1, APP_MAX_LENGTH);
2723         fname = strstr(path, "slist=") + 6;
2724         // Strip any further query parameters from fname
2725         amp = strchr(fname, '&');
2726         if (amp) {
2727             av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2728                                                   sizeof(fname_buffer)));
2729             fname = fname_buffer;
2730         }
2731     } else if (!strncmp(path, "/ondemand/", 10)) {
2732         fname = path + 10;
2733         memcpy(rt->app, "ondemand", 9);
2734     } else {
2735         char *next = *path ? path + 1 : path;
2736         char *p = strchr(next, '/');
2737         if (!p) {
2738             if (old_app) {
2739                 // If name of application has been defined by the user, assume that
2740                 // playpath is provided in the URL
2741                 fname = next;
2742             } else {
2743                 fname = NULL;
2744                 av_strlcpy(rt->app, next, APP_MAX_LENGTH);
2745             }
2746         } else {
2747             // make sure we do not mismatch a playpath for an application instance
2748             char *c = strchr(p + 1, ':');
2749             fname = strchr(p + 1, '/');
2750             if (!fname || (c && c < fname)) {
2751                 fname = p + 1;
2752                 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2753             } else {
2754                 fname++;
2755                 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2756             }
2757         }
2758     }
2759
2760     if (old_app) {
2761         // The name of application has been defined by the user, override it.
2762         if (strlen(old_app) >= APP_MAX_LENGTH) {
2763             ret = AVERROR(EINVAL);
2764             goto fail;
2765         }
2766         av_free(rt->app);
2767         rt->app = old_app;
2768     }
2769
2770     if (!rt->playpath) {
2771         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2772         if (!rt->playpath) {
2773             ret = AVERROR(ENOMEM);
2774             goto fail;
2775         }
2776
2777         if (fname) {
2778             int len = strlen(fname);
2779             if (!strchr(fname, ':') && len >= 4 &&
2780                 (!strcmp(fname + len - 4, ".f4v") ||
2781                  !strcmp(fname + len - 4, ".mp4"))) {
2782                 memcpy(rt->playpath, "mp4:", 5);
2783             } else {
2784                 if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2785                     fname[len - 4] = '\0';
2786                 rt->playpath[0] = 0;
2787             }
2788             av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2789         } else {
2790             rt->playpath[0] = '\0';
2791         }
2792     }
2793
2794     if (!rt->tcurl) {
2795         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2796         if (!rt->tcurl) {
2797             ret = AVERROR(ENOMEM);
2798             goto fail;
2799         }
2800         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2801                     port, "/%s", rt->app);
2802     }
2803
2804     if (!rt->flashver) {
2805         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2806         if (!rt->flashver) {
2807             ret = AVERROR(ENOMEM);
2808             goto fail;
2809         }
2810         if (rt->is_input) {
2811             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2812                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2813                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2814         } else {
2815             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2816                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2817         }
2818     }
2819
2820     rt->client_report_size = 1048576;
2821     rt->bytes_read = 0;
2822     rt->has_audio = 0;
2823     rt->has_video = 0;
2824     rt->received_metadata = 0;
2825     rt->last_bytes_read = 0;
2826     rt->server_bw = 2500000;
2827     rt->duration = 0;
2828
2829     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2830            proto, path, rt->app, rt->playpath);
2831     if (!rt->listen) {
2832         if ((ret = gen_connect(s, rt)) < 0)
2833             goto fail;
2834     } else {
2835         if ((ret = read_connect(s, s->priv_data)) < 0)
2836             goto fail;
2837     }
2838
2839     do {
2840         ret = get_packet(s, 1);
2841     } while (ret == AVERROR(EAGAIN));
2842     if (ret < 0)
2843         goto fail;
2844
2845     if (rt->do_reconnect) {
2846         int i;
2847         ffurl_close(rt->stream);
2848         rt->stream       = NULL;
2849         rt->do_reconnect = 0;
2850         rt->nb_invokes   = 0;
2851         for (i = 0; i < 2; i++)
2852             memset(rt->prev_pkt[i], 0,
2853                    sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2854         free_tracked_methods(rt);
2855         goto reconnect;
2856     }
2857
2858     if (rt->is_input) {
2859         // generate FLV header for demuxer
2860         rt->flv_size = 13;
2861         if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2862             goto fail;
2863         rt->flv_off  = 0;
2864         memcpy(rt->flv_data, "FLV\1\0\0\0\0\011\0\0\0\0", rt->flv_size);
2865
2866         // Read packets until we reach the first A/V packet or read metadata.
2867         // If there was a metadata package in front of the A/V packets, we can
2868         // build the FLV header from this. If we do not receive any metadata,
2869         // the FLV decoder will allocate the needed streams when their first
2870         // audio or video packet arrives.
2871         while (!rt->has_audio && !rt->has_video && !rt->received_metadata) {
2872             if ((ret = get_packet(s, 0)) < 0)
2873                goto fail;
2874         }
2875
2876         // Either after we have read the metadata or (if there is none) the
2877         // first packet of an A/V stream, we have a better knowledge about the
2878         // streams, so set the FLV header accordingly.
2879         if (rt->has_audio) {
2880             rt->flv_data[4] |= FLV_HEADER_FLAG_HASAUDIO;
2881         }
2882         if (rt->has_video) {
2883             rt->flv_data[4] |= FLV_HEADER_FLAG_HASVIDEO;
2884         }
2885
2886         // If we received the first packet of an A/V stream and no metadata but
2887         // the server returned a valid duration, create a fake metadata packet
2888         // to inform the FLV decoder about the duration.
2889         if (!rt->received_metadata && rt->duration > 0) {
2890             if ((ret = inject_fake_duration_metadata(rt)) < 0)
2891                 goto fail;
2892         }
2893     } else {
2894         rt->flv_size = 0;
2895         rt->flv_data = NULL;
2896         rt->flv_off  = 0;
2897         rt->skip_bytes = 13;
2898     }
2899
2900     s->max_packet_size = rt->stream->max_packet_size;
2901     s->is_streamed     = 1;
2902     return 0;
2903
2904 fail:
2905     av_dict_free(opts);
2906     rtmp_close(s);
2907     return ret;
2908 }
2909
2910 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2911 {
2912     RTMPContext *rt = s->priv_data;
2913     int orig_size = size;
2914     int ret;
2915
2916     while (size > 0) {
2917         int data_left = rt->flv_size - rt->flv_off;
2918
2919         if (data_left >= size) {
2920             memcpy(buf, rt->flv_data + rt->flv_off, size);
2921             rt->flv_off += size;
2922             return orig_size;
2923         }
2924         if (data_left > 0) {
2925             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2926             buf  += data_left;
2927             size -= data_left;
2928             rt->flv_off = rt->flv_size;
2929             return data_left;
2930         }
2931         if ((ret = get_packet(s, 0)) < 0)
2932            return ret;
2933     }
2934     return orig_size;
2935 }
2936
2937 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2938                          int flags)
2939 {
2940     RTMPContext *rt = s->priv_data;
2941     int ret;
2942     av_log(s, AV_LOG_DEBUG,
2943            "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2944            stream_index, timestamp, flags);
2945     if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2946         av_log(s, AV_LOG_ERROR,
2947                "Unable to send seek command on stream index %d at timestamp "
2948                "%"PRId64" with flags %08x\n",
2949                stream_index, timestamp, flags);
2950         return ret;
2951     }
2952     rt->flv_off = rt->flv_size;
2953     rt->state = STATE_SEEKING;
2954     return timestamp;
2955 }
2956
2957 static int rtmp_pause(URLContext *s, int pause)
2958 {
2959     RTMPContext *rt = s->priv_data;
2960     int ret;
2961     av_log(s, AV_LOG_DEBUG, "Pause at timestamp %d\n",
2962            rt->last_timestamp);
2963     if ((ret = gen_pause(s, rt, pause, rt->last_timestamp)) < 0) {
2964         av_log(s, AV_LOG_ERROR, "Unable to send pause command at timestamp %d\n",
2965                rt->last_timestamp);
2966         return ret;
2967     }
2968     return 0;
2969 }
2970
2971 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2972 {
2973     RTMPContext *rt = s->priv_data;
2974     int size_temp = size;
2975     int pktsize, pkttype, copy;
2976     uint32_t ts;
2977     const uint8_t *buf_temp = buf;
2978     uint8_t c;
2979     int ret;
2980
2981     do {
2982         if (rt->skip_bytes) {
2983             int skip = FFMIN(rt->skip_bytes, size_temp);
2984             buf_temp       += skip;
2985             size_temp      -= skip;
2986             rt->skip_bytes -= skip;
2987             continue;
2988         }
2989
2990         if (rt->flv_header_bytes < RTMP_HEADER) {
2991             const uint8_t *header = rt->flv_header;
2992             int channel = RTMP_AUDIO_CHANNEL;
2993
2994             copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2995             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2996             rt->flv_header_bytes += copy;
2997             size_temp            -= copy;
2998             if (rt->flv_header_bytes < RTMP_HEADER)
2999                 break;
3000
3001             pkttype = bytestream_get_byte(&header);
3002             pktsize = bytestream_get_be24(&header);
3003             ts = bytestream_get_be24(&header);
3004             ts |= bytestream_get_byte(&header) << 24;
3005             bytestream_get_be24(&header);
3006             rt->flv_size = pktsize;
3007
3008             if (pkttype == RTMP_PT_VIDEO)
3009                 channel = RTMP_VIDEO_CHANNEL;
3010
3011             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
3012                 pkttype == RTMP_PT_NOTIFY) {
3013                 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
3014                                                      &rt->nb_prev_pkt[1],
3015                                                      channel)) < 0)
3016                     return ret;
3017                 // Force sending a full 12 bytes header by clearing the
3018                 // channel id, to make it not match a potential earlier
3019                 // packet in the same channel.
3020                 rt->prev_pkt[1][channel].channel_id = 0;
3021             }
3022
3023             //this can be a big packet, it's better to send it right here
3024             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
3025                                              pkttype, ts, pktsize)) < 0)
3026                 return ret;
3027
3028             rt->out_pkt.extra = rt->stream_id;
3029             rt->flv_data = rt->out_pkt.data;
3030         }
3031
3032         copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
3033         bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
3034         rt->flv_off += copy;
3035         size_temp   -= copy;
3036
3037         if (rt->flv_off == rt->flv_size) {
3038             rt->skip_bytes = 4;
3039
3040             if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
3041                 // For onMetaData and |RtmpSampleAccess packets, we want
3042                 // @setDataFrame prepended to the packet before it gets sent.
3043                 // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
3044                 // and onCuePoint).
3045                 uint8_t commandbuffer[64];
3046                 int stringlen = 0;
3047                 GetByteContext gbc;
3048
3049                 bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
3050                 if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
3051                                         &stringlen)) {
3052                     if (!strcmp(commandbuffer, "onMetaData") ||
3053                         !strcmp(commandbuffer, "|RtmpSampleAccess")) {
3054                         uint8_t *ptr;
3055                         if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
3056                             rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
3057                             return ret;
3058                         }
3059                         memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
3060                         rt->out_pkt.size += 16;
3061                         ptr = rt->out_pkt.data;
3062                         ff_amf_write_string(&ptr, "@setDataFrame");
3063                     }
3064                 }
3065             }
3066
3067             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
3068                 return ret;
3069             rt->flv_size = 0;
3070             rt->flv_off = 0;
3071             rt->flv_header_bytes = 0;
3072             rt->flv_nb_packets++;
3073         }
3074     } while (buf_temp - buf < size);
3075
3076     if (rt->flv_nb_packets < rt->flush_interval)
3077         return size;
3078     rt->flv_nb_packets = 0;
3079
3080     /* set stream into nonblocking mode */
3081     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
3082
3083     /* try to read one byte from the stream */
3084     ret = ffurl_read(rt->stream, &c, 1);
3085
3086     /* switch the stream back into blocking mode */
3087     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
3088
3089     if (ret == AVERROR(EAGAIN)) {
3090         /* no incoming data to handle */
3091         return size;
3092     } else if (ret < 0) {
3093         return ret;
3094     } else if (ret == 1) {
3095         RTMPPacket rpkt = { 0 };
3096
3097         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
3098                                                 rt->in_chunk_size,
3099                                                 &rt->prev_pkt[0],
3100                                                 &rt->nb_prev_pkt[0], c)) <= 0)
3101              return ret;
3102
3103         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
3104             return ret;
3105
3106         ff_rtmp_packet_destroy(&rpkt);
3107     }
3108
3109     return size;
3110 }
3111
3112 #define OFFSET(x) offsetof(RTMPContext, x)
3113 #define DEC AV_OPT_FLAG_DECODING_PARAM
3114 #define ENC AV_OPT_FLAG_ENCODING_PARAM
3115
3116 static const AVOption rtmp_options[] = {
3117     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3118     {"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},
3119     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3120     {"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},
3121     {"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},
3122     {"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"},
3123     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
3124     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
3125     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
3126     {"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},
3127     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
3128     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3129     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
3130     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
3131     {"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},
3132     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
3133     {"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},
3134     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3135     {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
3136     {"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" },
3137     { NULL },
3138 };
3139
3140 #define RTMP_PROTOCOL(flavor)                    \
3141 static const AVClass flavor##_class = {          \
3142     .class_name = #flavor,                       \
3143     .item_name  = av_default_item_name,          \
3144     .option     = rtmp_options,                  \
3145     .version    = LIBAVUTIL_VERSION_INT,         \
3146 };                                               \
3147                                                  \
3148 const URLProtocol ff_##flavor##_protocol = {     \
3149     .name           = #flavor,                   \
3150     .url_open2      = rtmp_open,                 \
3151     .url_read       = rtmp_read,                 \
3152     .url_read_seek  = rtmp_seek,                 \
3153     .url_read_pause = rtmp_pause,                \
3154     .url_write      = rtmp_write,                \
3155     .url_close      = rtmp_close,                \
3156     .priv_data_size = sizeof(RTMPContext),       \
3157     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
3158     .priv_data_class= &flavor##_class,           \
3159 };
3160
3161
3162 RTMP_PROTOCOL(rtmp)
3163 RTMP_PROTOCOL(rtmpe)
3164 RTMP_PROTOCOL(rtmps)
3165 RTMP_PROTOCOL(rtmpt)
3166 RTMP_PROTOCOL(rtmpte)
3167 RTMP_PROTOCOL(rtmpts)