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