]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
Merge commit '0097cbea695e534fce39958ccd103af2fbf65831'
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Konstantin Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * RTMP protocol
25  */
26
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/base64.h"
30 #include "libavutil/intfloat.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/md5.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/random_seed.h"
35 #include "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             } else {
1728                 av_log(s, AV_LOG_INFO, "Ignoring unsupported var %s\n", ptr);
1729             }
1730         } else {
1731             av_log(s, AV_LOG_WARNING, "Variable %s has NULL value\n", ptr);
1732         }
1733         ptr = next;
1734     }
1735
1736     if (!strcmp(authmod, "adobe")) {
1737         if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1738             return ret;
1739     } else {
1740         if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1741             return ret;
1742     }
1743
1744     rt->auth_tried = 1;
1745     return 0;
1746 }
1747
1748 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1749 {
1750     RTMPContext *rt = s->priv_data;
1751     const uint8_t *data_end = pkt->data + pkt->size;
1752     char *tracked_method = NULL;
1753     int level = AV_LOG_ERROR;
1754     uint8_t tmpstr[256];
1755     int ret;
1756
1757     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1758         return ret;
1759
1760     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1761                                 "description", tmpstr, sizeof(tmpstr))) {
1762         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1763                                !strcmp(tracked_method, "releaseStream") ||
1764                                !strcmp(tracked_method, "FCSubscribe")   ||
1765                                !strcmp(tracked_method, "FCPublish"))) {
1766             /* Gracefully ignore Adobe-specific historical artifact errors. */
1767             level = AV_LOG_WARNING;
1768             ret = 0;
1769         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1770             ret = handle_connect_error(s, tmpstr);
1771             if (!ret) {
1772                 rt->do_reconnect = 1;
1773                 level = AV_LOG_VERBOSE;
1774             }
1775         } else
1776             ret = AVERROR_UNKNOWN;
1777         av_log(s, level, "Server error: %s\n", tmpstr);
1778     }
1779
1780     av_free(tracked_method);
1781     return ret;
1782 }
1783
1784 static int write_begin(URLContext *s)
1785 {
1786     RTMPContext *rt = s->priv_data;
1787     PutByteContext pbc;
1788     RTMPPacket spkt = { 0 };
1789     int ret;
1790
1791     // Send Stream Begin 1
1792     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1793                                      RTMP_PT_PING, 0, 6)) < 0) {
1794         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1795         return ret;
1796     }
1797
1798     bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1799     bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1800     bytestream2_put_be32(&pbc, rt->nb_streamid);
1801
1802     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1803                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1804
1805     ff_rtmp_packet_destroy(&spkt);
1806
1807     return ret;
1808 }
1809
1810 static int write_status(URLContext *s, RTMPPacket *pkt,
1811                         const char *status, const char *filename)
1812 {
1813     RTMPContext *rt = s->priv_data;
1814     RTMPPacket spkt = { 0 };
1815     char statusmsg[128];
1816     uint8_t *pp;
1817     int ret;
1818
1819     if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1820                                      RTMP_PT_INVOKE, 0,
1821                                      RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1822         av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1823         return ret;
1824     }
1825
1826     pp = spkt.data;
1827     spkt.extra = pkt->extra;
1828     ff_amf_write_string(&pp, "onStatus");
1829     ff_amf_write_number(&pp, 0);
1830     ff_amf_write_null(&pp);
1831
1832     ff_amf_write_object_start(&pp);
1833     ff_amf_write_field_name(&pp, "level");
1834     ff_amf_write_string(&pp, "status");
1835     ff_amf_write_field_name(&pp, "code");
1836     ff_amf_write_string(&pp, status);
1837     ff_amf_write_field_name(&pp, "description");
1838     snprintf(statusmsg, sizeof(statusmsg),
1839              "%s is now published", filename);
1840     ff_amf_write_string(&pp, statusmsg);
1841     ff_amf_write_field_name(&pp, "details");
1842     ff_amf_write_string(&pp, filename);
1843     ff_amf_write_field_name(&pp, "clientid");
1844     snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1845     ff_amf_write_string(&pp, statusmsg);
1846     ff_amf_write_object_end(&pp);
1847
1848     spkt.size = pp - spkt.data;
1849     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1850                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1851     ff_rtmp_packet_destroy(&spkt);
1852
1853     return ret;
1854 }
1855
1856 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1857 {
1858     RTMPContext *rt = s->priv_data;
1859     double seqnum;
1860     char filename[64];
1861     char command[64];
1862     int stringlen;
1863     char *pchar;
1864     const uint8_t *p = pkt->data;
1865     uint8_t *pp      = NULL;
1866     RTMPPacket spkt  = { 0 };
1867     GetByteContext gbc;
1868     int ret;
1869
1870     bytestream2_init(&gbc, p, pkt->size);
1871     if (ff_amf_read_string(&gbc, command, sizeof(command),
1872                            &stringlen)) {
1873         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1874         return AVERROR_INVALIDDATA;
1875     }
1876
1877     ret = ff_amf_read_number(&gbc, &seqnum);
1878     if (ret)
1879         return ret;
1880     ret = ff_amf_read_null(&gbc);
1881     if (ret)
1882         return ret;
1883     if (!strcmp(command, "FCPublish") ||
1884         !strcmp(command, "publish")) {
1885         ret = ff_amf_read_string(&gbc, filename,
1886                                  sizeof(filename), &stringlen);
1887         // check with url
1888         if (s->filename) {
1889             pchar = strrchr(s->filename, '/');
1890             if (!pchar) {
1891                 av_log(s, AV_LOG_WARNING,
1892                        "Unable to find / in url %s, bad format\n",
1893                        s->filename);
1894                 pchar = s->filename;
1895             }
1896             pchar++;
1897             if (strcmp(pchar, filename))
1898                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1899                        " %s\n", filename, pchar);
1900         }
1901         rt->state = STATE_RECEIVING;
1902     }
1903
1904     if (!strcmp(command, "FCPublish")) {
1905         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1906                                          RTMP_PT_INVOKE, 0,
1907                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1908             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1909             return ret;
1910         }
1911         pp = spkt.data;
1912         ff_amf_write_string(&pp, "onFCPublish");
1913     } else if (!strcmp(command, "publish")) {
1914         ret = write_begin(s);
1915         if (ret < 0)
1916             return ret;
1917
1918         // Send onStatus(NetStream.Publish.Start)
1919         return write_status(s, pkt, "NetStream.Publish.Start",
1920                            filename);
1921     } else if (!strcmp(command, "play")) {
1922         ret = write_begin(s);
1923         if (ret < 0)
1924             return ret;
1925         rt->state = STATE_SENDING;
1926         return write_status(s, pkt, "NetStream.Play.Start",
1927                             filename);
1928     } else {
1929         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1930                                          RTMP_PT_INVOKE, 0,
1931                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1932             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1933             return ret;
1934         }
1935         pp = spkt.data;
1936         ff_amf_write_string(&pp, "_result");
1937         ff_amf_write_number(&pp, seqnum);
1938         ff_amf_write_null(&pp);
1939         if (!strcmp(command, "createStream")) {
1940             rt->nb_streamid++;
1941             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1942                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1943             ff_amf_write_number(&pp, rt->nb_streamid);
1944             /* By now we don't control which streams are removed in
1945              * deleteStream. There is no stream creation control
1946              * if a client creates more than 2^32 - 2 streams. */
1947         }
1948     }
1949     spkt.size = pp - spkt.data;
1950     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1951                                &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1952     ff_rtmp_packet_destroy(&spkt);
1953     return ret;
1954 }
1955
1956 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1957 {
1958     RTMPContext *rt = s->priv_data;
1959     char *tracked_method = NULL;
1960     int ret = 0;
1961
1962     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1963         return ret;
1964
1965     if (!tracked_method) {
1966         /* Ignore this reply when the current method is not tracked. */
1967         return ret;
1968     }
1969
1970     if (!strcmp(tracked_method, "connect")) {
1971         if (!rt->is_input) {
1972             if ((ret = gen_release_stream(s, rt)) < 0)
1973                 goto fail;
1974
1975             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1976                 goto fail;
1977         } else {
1978             if ((ret = gen_server_bw(s, rt)) < 0)
1979                 goto fail;
1980         }
1981
1982         if ((ret = gen_create_stream(s, rt)) < 0)
1983             goto fail;
1984
1985         if (rt->is_input) {
1986             /* Send the FCSubscribe command when the name of live
1987              * stream is defined by the user or if it's a live stream. */
1988             if (rt->subscribe) {
1989                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1990                     goto fail;
1991             } else if (rt->live == -1) {
1992                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1993                     goto fail;
1994             }
1995         }
1996     } else if (!strcmp(tracked_method, "createStream")) {
1997         //extract a number from the result
1998         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1999             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
2000         } else {
2001             rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
2002         }
2003
2004         if (!rt->is_input) {
2005             if ((ret = gen_publish(s, rt)) < 0)
2006                 goto fail;
2007         } else {
2008             if ((ret = gen_play(s, rt)) < 0)
2009                 goto fail;
2010             if ((ret = gen_buffer_time(s, rt)) < 0)
2011                 goto fail;
2012         }
2013     }
2014
2015 fail:
2016     av_free(tracked_method);
2017     return ret;
2018 }
2019
2020 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2021 {
2022     RTMPContext *rt = s->priv_data;
2023     const uint8_t *data_end = pkt->data + pkt->size;
2024     const uint8_t *ptr = pkt->data + RTMP_HEADER;
2025     uint8_t tmpstr[256];
2026     int i, t;
2027
2028     for (i = 0; i < 2; i++) {
2029         t = ff_amf_tag_size(ptr, data_end);
2030         if (t < 0)
2031             return 1;
2032         ptr += t;
2033     }
2034
2035     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2036     if (!t && !strcmp(tmpstr, "error")) {
2037         t = ff_amf_get_field_value(ptr, data_end,
2038                                    "description", tmpstr, sizeof(tmpstr));
2039         if (t || !tmpstr[0])
2040             t = ff_amf_get_field_value(ptr, data_end, "code",
2041                                        tmpstr, sizeof(tmpstr));
2042         if (!t)
2043             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2044         return -1;
2045     }
2046
2047     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2048     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2049     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2050     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2051     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2052     if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2053
2054     return 0;
2055 }
2056
2057 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2058 {
2059     RTMPContext *rt = s->priv_data;
2060     int ret = 0;
2061
2062     //TODO: check for the messages sent for wrong state?
2063     if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2064         if ((ret = handle_invoke_error(s, pkt)) < 0)
2065             return ret;
2066     } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2067         if ((ret = handle_invoke_result(s, pkt)) < 0)
2068             return ret;
2069     } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2070         if ((ret = handle_invoke_status(s, pkt)) < 0)
2071             return ret;
2072     } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2073         if ((ret = gen_check_bw(s, rt)) < 0)
2074             return ret;
2075     } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2076                ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
2077                ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
2078                ff_amf_match_string(pkt->data, pkt->size, "play")          ||
2079                ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
2080                ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2081         if ((ret = send_invoke_response(s, pkt)) < 0)
2082             return ret;
2083     }
2084
2085     return ret;
2086 }
2087
2088 static int update_offset(RTMPContext *rt, int size)
2089 {
2090     int old_flv_size;
2091
2092     // generate packet header and put data into buffer for FLV demuxer
2093     if (rt->flv_off < rt->flv_size) {
2094         // There is old unread data in the buffer, thus append at the end
2095         old_flv_size  = rt->flv_size;
2096         rt->flv_size += size;
2097     } else {
2098         // All data has been read, write the new data at the start of the buffer
2099         old_flv_size = 0;
2100         rt->flv_size = size;
2101         rt->flv_off  = 0;
2102     }
2103
2104     return old_flv_size;
2105 }
2106
2107 static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2108 {
2109     int old_flv_size, ret;
2110     PutByteContext pbc;
2111     const uint8_t *data = pkt->data + skip;
2112     const int size      = pkt->size - skip;
2113     uint32_t ts         = pkt->timestamp;
2114
2115     old_flv_size = update_offset(rt, size + 15);
2116
2117     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2118         rt->flv_size = rt->flv_off = 0;
2119         return ret;
2120     }
2121     bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2122     bytestream2_skip_p(&pbc, old_flv_size);
2123     bytestream2_put_byte(&pbc, pkt->type);
2124     bytestream2_put_be24(&pbc, size);
2125     bytestream2_put_be24(&pbc, ts);
2126     bytestream2_put_byte(&pbc, ts >> 24);
2127     bytestream2_put_be24(&pbc, 0);
2128     bytestream2_put_buffer(&pbc, data, size);
2129     bytestream2_put_be32(&pbc, 0);
2130
2131     return 0;
2132 }
2133
2134 static int handle_notify(URLContext *s, RTMPPacket *pkt)
2135 {
2136     RTMPContext *rt  = s->priv_data;
2137     uint8_t commandbuffer[64];
2138     char statusmsg[128];
2139     int stringlen, ret, skip = 0;
2140     GetByteContext gbc;
2141
2142     bytestream2_init(&gbc, pkt->data, pkt->size);
2143     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2144                            &stringlen))
2145         return AVERROR_INVALIDDATA;
2146
2147     // Skip the @setDataFrame string and validate it is a notification
2148     if (!strcmp(commandbuffer, "@setDataFrame")) {
2149         skip = gbc.buffer - pkt->data;
2150         ret = ff_amf_read_string(&gbc, statusmsg,
2151                                  sizeof(statusmsg), &stringlen);
2152         if (ret < 0)
2153             return AVERROR_INVALIDDATA;
2154     }
2155
2156     return append_flv_data(rt, pkt, skip);
2157 }
2158
2159 /**
2160  * Parse received packet and possibly perform some action depending on
2161  * the packet contents.
2162  * @return 0 for no errors, negative values for serious errors which prevent
2163  *         further communications, positive values for uncritical errors
2164  */
2165 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2166 {
2167     int ret;
2168
2169 #ifdef DEBUG
2170     ff_rtmp_packet_dump(s, pkt);
2171 #endif
2172
2173     switch (pkt->type) {
2174     case RTMP_PT_BYTES_READ:
2175         av_dlog(s, "received bytes read report\n");
2176         break;
2177     case RTMP_PT_CHUNK_SIZE:
2178         if ((ret = handle_chunk_size(s, pkt)) < 0)
2179             return ret;
2180         break;
2181     case RTMP_PT_PING:
2182         if ((ret = handle_ping(s, pkt)) < 0)
2183             return ret;
2184         break;
2185     case RTMP_PT_CLIENT_BW:
2186         if ((ret = handle_client_bw(s, pkt)) < 0)
2187             return ret;
2188         break;
2189     case RTMP_PT_SERVER_BW:
2190         if ((ret = handle_server_bw(s, pkt)) < 0)
2191             return ret;
2192         break;
2193     case RTMP_PT_INVOKE:
2194         if ((ret = handle_invoke(s, pkt)) < 0)
2195             return ret;
2196         break;
2197     case RTMP_PT_VIDEO:
2198     case RTMP_PT_AUDIO:
2199     case RTMP_PT_METADATA:
2200     case RTMP_PT_NOTIFY:
2201         /* Audio, Video and Metadata packets are parsed in get_packet() */
2202         break;
2203     default:
2204         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2205         break;
2206     }
2207     return 0;
2208 }
2209
2210 static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2211 {
2212     int ret, old_flv_size, type;
2213     const uint8_t *next;
2214     uint8_t *p;
2215     uint32_t size;
2216     uint32_t ts, cts, pts = 0;
2217
2218     old_flv_size = update_offset(rt, pkt->size);
2219
2220     if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2221         rt->flv_size = rt->flv_off = 0;
2222         return ret;
2223     }
2224
2225     next = pkt->data;
2226     p    = rt->flv_data + old_flv_size;
2227
2228     /* copy data while rewriting timestamps */
2229     ts = pkt->timestamp;
2230
2231     while (next - pkt->data < pkt->size - RTMP_HEADER) {
2232         type = bytestream_get_byte(&next);
2233         size = bytestream_get_be24(&next);
2234         cts  = bytestream_get_be24(&next);
2235         cts |= bytestream_get_byte(&next) << 24;
2236         if (!pts)
2237             pts = cts;
2238         ts += cts - pts;
2239         pts = cts;
2240         if (size + 3 + 4 > pkt->data + pkt->size - next)
2241             break;
2242         bytestream_put_byte(&p, type);
2243         bytestream_put_be24(&p, size);
2244         bytestream_put_be24(&p, ts);
2245         bytestream_put_byte(&p, ts >> 24);
2246         memcpy(p, next, size + 3 + 4);
2247         next += size + 3 + 4;
2248         p    += size + 3 + 4;
2249     }
2250     if (p != rt->flv_data + rt->flv_size) {
2251         av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2252                                      "RTMP_PT_METADATA packet\n");
2253         rt->flv_size = p - rt->flv_data;
2254     }
2255
2256     return 0;
2257 }
2258
2259 /**
2260  * Interact with the server by receiving and sending RTMP packets until
2261  * there is some significant data (media data or expected status notification).
2262  *
2263  * @param s          reading context
2264  * @param for_header non-zero value tells function to work until it
2265  * gets notification from the server that playing has been started,
2266  * otherwise function will work until some media data is received (or
2267  * an error happens)
2268  * @return 0 for successful operation, negative value in case of error
2269  */
2270 static int get_packet(URLContext *s, int for_header)
2271 {
2272     RTMPContext *rt = s->priv_data;
2273     int ret;
2274
2275     if (rt->state == STATE_STOPPED)
2276         return AVERROR_EOF;
2277
2278     for (;;) {
2279         RTMPPacket rpkt = { 0 };
2280         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2281                                        rt->in_chunk_size, &rt->prev_pkt[0],
2282                                        &rt->nb_prev_pkt[0])) <= 0) {
2283             if (ret == 0) {
2284                 return AVERROR(EAGAIN);
2285             } else {
2286                 return AVERROR(EIO);
2287             }
2288         }
2289         rt->bytes_read += ret;
2290         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2291             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2292             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2293                 return ret;
2294             rt->last_bytes_read = rt->bytes_read;
2295         }
2296
2297         ret = rtmp_parse_result(s, rt, &rpkt);
2298
2299         // At this point we must check if we are in the seek state and continue
2300         // with the next packet. handle_invoke will get us out of this state
2301         // when the right message is encountered
2302         if (rt->state == STATE_SEEKING) {
2303             ff_rtmp_packet_destroy(&rpkt);
2304             // We continue, let the natural flow of things happen:
2305             // AVERROR(EAGAIN) or handle_invoke gets us out of here
2306             continue;
2307         }
2308
2309         if (ret < 0) {//serious error in current packet
2310             ff_rtmp_packet_destroy(&rpkt);
2311             return ret;
2312         }
2313         if (rt->do_reconnect && for_header) {
2314             ff_rtmp_packet_destroy(&rpkt);
2315             return 0;
2316         }
2317         if (rt->state == STATE_STOPPED) {
2318             ff_rtmp_packet_destroy(&rpkt);
2319             return AVERROR_EOF;
2320         }
2321         if (for_header && (rt->state == STATE_PLAYING    ||
2322                            rt->state == STATE_PUBLISHING ||
2323                            rt->state == STATE_SENDING    ||
2324                            rt->state == STATE_RECEIVING)) {
2325             ff_rtmp_packet_destroy(&rpkt);
2326             return 0;
2327         }
2328         if (!rpkt.size || !rt->is_input) {
2329             ff_rtmp_packet_destroy(&rpkt);
2330             continue;
2331         }
2332         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2333             ret = append_flv_data(rt, &rpkt, 0);
2334             ff_rtmp_packet_destroy(&rpkt);
2335             return ret;
2336         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2337             ret = handle_notify(s, &rpkt);
2338             ff_rtmp_packet_destroy(&rpkt);
2339             return ret;
2340         } else if (rpkt.type == RTMP_PT_METADATA) {
2341             ret = handle_metadata(rt, &rpkt);
2342             ff_rtmp_packet_destroy(&rpkt);
2343             return 0;
2344         }
2345         ff_rtmp_packet_destroy(&rpkt);
2346     }
2347 }
2348
2349 static int rtmp_close(URLContext *h)
2350 {
2351     RTMPContext *rt = h->priv_data;
2352     int ret = 0, i, j;
2353
2354     if (!rt->is_input) {
2355         rt->flv_data = NULL;
2356         if (rt->out_pkt.size)
2357             ff_rtmp_packet_destroy(&rt->out_pkt);
2358         if (rt->state > STATE_FCPUBLISH)
2359             ret = gen_fcunpublish_stream(h, rt);
2360     }
2361     if (rt->state > STATE_HANDSHAKED)
2362         ret = gen_delete_stream(h, rt);
2363     for (i = 0; i < 2; i++) {
2364         for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2365             ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2366         av_freep(&rt->prev_pkt[i]);
2367     }
2368
2369     free_tracked_methods(rt);
2370     av_freep(&rt->flv_data);
2371     ffurl_close(rt->stream);
2372     return ret;
2373 }
2374
2375 /**
2376  * Open RTMP connection and verify that the stream can be played.
2377  *
2378  * URL syntax: rtmp://server[:port][/app][/playpath]
2379  *             where 'app' is first one or two directories in the path
2380  *             (e.g. /ondemand/, /flash/live/, etc.)
2381  *             and 'playpath' is a file name (the rest of the path,
2382  *             may be prefixed with "mp4:")
2383  */
2384 static int rtmp_open(URLContext *s, const char *uri, int flags)
2385 {
2386     RTMPContext *rt = s->priv_data;
2387     char proto[8], hostname[256], path[1024], auth[100], *fname;
2388     char *old_app, *qmark, fname_buffer[1024];
2389     uint8_t buf[2048];
2390     int port;
2391     AVDictionary *opts = NULL;
2392     int ret;
2393
2394     if (rt->listen_timeout > 0)
2395         rt->listen = 1;
2396
2397     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2398
2399     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2400                  hostname, sizeof(hostname), &port,
2401                  path, sizeof(path), s->filename);
2402
2403     if (strchr(path, ' ')) {
2404         av_log(s, AV_LOG_WARNING,
2405                "Detected librtmp style URL parameters, these aren't supported "
2406                "by the libavformat internal RTMP handler currently enabled. "
2407                "See the documentation for the correct way to pass parameters.\n");
2408     }
2409
2410     if (auth[0]) {
2411         char *ptr = strchr(auth, ':');
2412         if (ptr) {
2413             *ptr = '\0';
2414             av_strlcpy(rt->username, auth, sizeof(rt->username));
2415             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2416         }
2417     }
2418
2419     if (rt->listen && strcmp(proto, "rtmp")) {
2420         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2421                proto);
2422         return AVERROR(EINVAL);
2423     }
2424     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2425         if (!strcmp(proto, "rtmpts"))
2426             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2427
2428         /* open the http tunneling connection */
2429         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2430     } else if (!strcmp(proto, "rtmps")) {
2431         /* open the tls connection */
2432         if (port < 0)
2433             port = RTMPS_DEFAULT_PORT;
2434         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2435     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2436         if (!strcmp(proto, "rtmpte"))
2437             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2438
2439         /* open the encrypted connection */
2440         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2441         rt->encrypted = 1;
2442     } else {
2443         /* open the tcp connection */
2444         if (port < 0)
2445             port = RTMP_DEFAULT_PORT;
2446         if (rt->listen)
2447             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2448                         "?listen&listen_timeout=%d",
2449                         rt->listen_timeout * 1000);
2450         else
2451             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2452     }
2453
2454 reconnect:
2455     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2456                           &s->interrupt_callback, &opts)) < 0) {
2457         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2458         goto fail;
2459     }
2460
2461     if (rt->swfverify) {
2462         if ((ret = rtmp_calc_swfhash(s)) < 0)
2463             goto fail;
2464     }
2465
2466     rt->state = STATE_START;
2467     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2468         goto fail;
2469     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2470         goto fail;
2471
2472     rt->out_chunk_size = 128;
2473     rt->in_chunk_size  = 128; // Probably overwritten later
2474     rt->state = STATE_HANDSHAKED;
2475
2476     // Keep the application name when it has been defined by the user.
2477     old_app = rt->app;
2478
2479     rt->app = av_malloc(APP_MAX_LENGTH);
2480     if (!rt->app) {
2481         ret = AVERROR(ENOMEM);
2482         goto fail;
2483     }
2484
2485     //extract "app" part from path
2486     qmark = strchr(path, '?');
2487     if (qmark && strstr(qmark, "slist=")) {
2488         char* amp;
2489         // After slist we have the playpath, before the params, the app
2490         av_strlcpy(rt->app, path + 1, FFMIN(qmark - path, APP_MAX_LENGTH));
2491         fname = strstr(path, "slist=") + 6;
2492         // Strip any further query parameters from fname
2493         amp = strchr(fname, '&');
2494         if (amp) {
2495             av_strlcpy(fname_buffer, fname, FFMIN(amp - fname + 1,
2496                                                   sizeof(fname_buffer)));
2497             fname = fname_buffer;
2498         }
2499     } else if (!strncmp(path, "/ondemand/", 10)) {
2500         fname = path + 10;
2501         memcpy(rt->app, "ondemand", 9);
2502     } else {
2503         char *next = *path ? path + 1 : path;
2504         char *p = strchr(next, '/');
2505         if (!p) {
2506             fname = next;
2507             rt->app[0] = '\0';
2508         } else {
2509             // make sure we do not mismatch a playpath for an application instance
2510             char *c = strchr(p + 1, ':');
2511             fname = strchr(p + 1, '/');
2512             if (!fname || (c && c < fname)) {
2513                 fname = p + 1;
2514                 av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2515             } else {
2516                 fname++;
2517                 av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2518             }
2519         }
2520     }
2521
2522     if (old_app) {
2523         // The name of application has been defined by the user, override it.
2524         if (strlen(old_app) >= APP_MAX_LENGTH) {
2525             ret = AVERROR(EINVAL);
2526             goto fail;
2527         }
2528         av_free(rt->app);
2529         rt->app = old_app;
2530     }
2531
2532     if (!rt->playpath) {
2533         int len = strlen(fname);
2534
2535         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2536         if (!rt->playpath) {
2537             ret = AVERROR(ENOMEM);
2538             goto fail;
2539         }
2540
2541         if (!strchr(fname, ':') && len >= 4 &&
2542             (!strcmp(fname + len - 4, ".f4v") ||
2543              !strcmp(fname + len - 4, ".mp4"))) {
2544             memcpy(rt->playpath, "mp4:", 5);
2545         } else {
2546             if (len >= 4 && !strcmp(fname + len - 4, ".flv"))
2547                 fname[len - 4] = '\0';
2548             rt->playpath[0] = 0;
2549         }
2550         av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2551     }
2552
2553     if (!rt->tcurl) {
2554         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2555         if (!rt->tcurl) {
2556             ret = AVERROR(ENOMEM);
2557             goto fail;
2558         }
2559         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2560                     port, "/%s", rt->app);
2561     }
2562
2563     if (!rt->flashver) {
2564         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2565         if (!rt->flashver) {
2566             ret = AVERROR(ENOMEM);
2567             goto fail;
2568         }
2569         if (rt->is_input) {
2570             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2571                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2572                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2573         } else {
2574             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2575                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2576         }
2577     }
2578
2579     rt->client_report_size = 1048576;
2580     rt->bytes_read = 0;
2581     rt->last_bytes_read = 0;
2582     rt->server_bw = 2500000;
2583
2584     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2585            proto, path, rt->app, rt->playpath);
2586     if (!rt->listen) {
2587         if ((ret = gen_connect(s, rt)) < 0)
2588             goto fail;
2589     } else {
2590         if ((ret = read_connect(s, s->priv_data)) < 0)
2591             goto fail;
2592     }
2593
2594     do {
2595         ret = get_packet(s, 1);
2596     } while (ret == AVERROR(EAGAIN));
2597     if (ret < 0)
2598         goto fail;
2599
2600     if (rt->do_reconnect) {
2601         int i;
2602         ffurl_close(rt->stream);
2603         rt->stream       = NULL;
2604         rt->do_reconnect = 0;
2605         rt->nb_invokes   = 0;
2606         for (i = 0; i < 2; i++)
2607             memset(rt->prev_pkt[i], 0,
2608                    sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2609         free_tracked_methods(rt);
2610         goto reconnect;
2611     }
2612
2613     if (rt->is_input) {
2614         int err;
2615         // generate FLV header for demuxer
2616         rt->flv_size = 13;
2617         if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2618             return err;
2619         rt->flv_off  = 0;
2620         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2621     } else {
2622         rt->flv_size = 0;
2623         rt->flv_data = NULL;
2624         rt->flv_off  = 0;
2625         rt->skip_bytes = 13;
2626     }
2627
2628     s->max_packet_size = rt->stream->max_packet_size;
2629     s->is_streamed     = 1;
2630     return 0;
2631
2632 fail:
2633     av_dict_free(&opts);
2634     rtmp_close(s);
2635     return ret;
2636 }
2637
2638 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2639 {
2640     RTMPContext *rt = s->priv_data;
2641     int orig_size = size;
2642     int ret;
2643
2644     while (size > 0) {
2645         int data_left = rt->flv_size - rt->flv_off;
2646
2647         if (data_left >= size) {
2648             memcpy(buf, rt->flv_data + rt->flv_off, size);
2649             rt->flv_off += size;
2650             return orig_size;
2651         }
2652         if (data_left > 0) {
2653             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2654             buf  += data_left;
2655             size -= data_left;
2656             rt->flv_off = rt->flv_size;
2657             return data_left;
2658         }
2659         if ((ret = get_packet(s, 0)) < 0)
2660            return ret;
2661     }
2662     return orig_size;
2663 }
2664
2665 static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2666                          int flags)
2667 {
2668     RTMPContext *rt = s->priv_data;
2669     int ret;
2670     av_log(s, AV_LOG_DEBUG,
2671            "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2672            stream_index, timestamp, flags);
2673     if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2674         av_log(s, AV_LOG_ERROR,
2675                "Unable to send seek command on stream index %d at timestamp "
2676                "%"PRId64" with flags %08x\n",
2677                stream_index, timestamp, flags);
2678         return ret;
2679     }
2680     rt->flv_off = rt->flv_size;
2681     rt->state = STATE_SEEKING;
2682     return timestamp;
2683 }
2684
2685 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2686 {
2687     RTMPContext *rt = s->priv_data;
2688     int size_temp = size;
2689     int pktsize, pkttype;
2690     uint32_t ts;
2691     const uint8_t *buf_temp = buf;
2692     uint8_t c;
2693     int ret;
2694
2695     do {
2696         if (rt->skip_bytes) {
2697             int skip = FFMIN(rt->skip_bytes, size_temp);
2698             buf_temp       += skip;
2699             size_temp      -= skip;
2700             rt->skip_bytes -= skip;
2701             continue;
2702         }
2703
2704         if (rt->flv_header_bytes < RTMP_HEADER) {
2705             const uint8_t *header = rt->flv_header;
2706             int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2707             int channel = RTMP_AUDIO_CHANNEL;
2708             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2709             rt->flv_header_bytes += copy;
2710             size_temp            -= copy;
2711             if (rt->flv_header_bytes < RTMP_HEADER)
2712                 break;
2713
2714             pkttype = bytestream_get_byte(&header);
2715             pktsize = bytestream_get_be24(&header);
2716             ts = bytestream_get_be24(&header);
2717             ts |= bytestream_get_byte(&header) << 24;
2718             bytestream_get_be24(&header);
2719             rt->flv_size = pktsize;
2720
2721             if (pkttype == RTMP_PT_VIDEO)
2722                 channel = RTMP_VIDEO_CHANNEL;
2723
2724             //force 12bytes header
2725             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2726                 pkttype == RTMP_PT_NOTIFY) {
2727                 if (pkttype == RTMP_PT_NOTIFY)
2728                     pktsize += 16;
2729                 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2730                                                      &rt->nb_prev_pkt[1],
2731                                                      channel)) < 0)
2732                     return ret;
2733                 rt->prev_pkt[1][channel].channel_id = 0;
2734             }
2735
2736             //this can be a big packet, it's better to send it right here
2737             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2738                                              pkttype, ts, pktsize)) < 0)
2739                 return ret;
2740
2741             rt->out_pkt.extra = rt->stream_id;
2742             rt->flv_data = rt->out_pkt.data;
2743
2744             if (pkttype == RTMP_PT_NOTIFY)
2745                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2746         }
2747
2748         if (rt->flv_size - rt->flv_off > size_temp) {
2749             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2750             rt->flv_off += size_temp;
2751             size_temp = 0;
2752         } else {
2753             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2754             size_temp   -= rt->flv_size - rt->flv_off;
2755             rt->flv_off += rt->flv_size - rt->flv_off;
2756         }
2757
2758         if (rt->flv_off == rt->flv_size) {
2759             rt->skip_bytes = 4;
2760
2761             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2762                 return ret;
2763             rt->flv_size = 0;
2764             rt->flv_off = 0;
2765             rt->flv_header_bytes = 0;
2766             rt->flv_nb_packets++;
2767         }
2768     } while (buf_temp - buf < size);
2769
2770     if (rt->flv_nb_packets < rt->flush_interval)
2771         return size;
2772     rt->flv_nb_packets = 0;
2773
2774     /* set stream into nonblocking mode */
2775     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2776
2777     /* try to read one byte from the stream */
2778     ret = ffurl_read(rt->stream, &c, 1);
2779
2780     /* switch the stream back into blocking mode */
2781     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2782
2783     if (ret == AVERROR(EAGAIN)) {
2784         /* no incoming data to handle */
2785         return size;
2786     } else if (ret < 0) {
2787         return ret;
2788     } else if (ret == 1) {
2789         RTMPPacket rpkt = { 0 };
2790
2791         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2792                                                 rt->in_chunk_size,
2793                                                 &rt->prev_pkt[0],
2794                                                 &rt->nb_prev_pkt[0], c)) <= 0)
2795              return ret;
2796
2797         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2798             return ret;
2799
2800         ff_rtmp_packet_destroy(&rpkt);
2801     }
2802
2803     return size;
2804 }
2805
2806 #define OFFSET(x) offsetof(RTMPContext, x)
2807 #define DEC AV_OPT_FLAG_DECODING_PARAM
2808 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2809
2810 static const AVOption rtmp_options[] = {
2811     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2812     {"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},
2813     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2814     {"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},
2815     {"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},
2816     {"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"},
2817     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2818     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2819     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2820     {"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},
2821     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2822     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2823     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2824     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2825     {"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},
2826     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2827     {"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},
2828     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2829     {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2830     {"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" },
2831     { NULL },
2832 };
2833
2834 #define RTMP_PROTOCOL(flavor)                    \
2835 static const AVClass flavor##_class = {          \
2836     .class_name = #flavor,                       \
2837     .item_name  = av_default_item_name,          \
2838     .option     = rtmp_options,                  \
2839     .version    = LIBAVUTIL_VERSION_INT,         \
2840 };                                               \
2841                                                  \
2842 URLProtocol ff_##flavor##_protocol = {           \
2843     .name           = #flavor,                   \
2844     .url_open       = rtmp_open,                 \
2845     .url_read       = rtmp_read,                 \
2846     .url_read_seek  = rtmp_seek,                 \
2847     .url_write      = rtmp_write,                \
2848     .url_close      = rtmp_close,                \
2849     .priv_data_size = sizeof(RTMPContext),       \
2850     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2851     .priv_data_class= &flavor##_class,           \
2852 };
2853
2854
2855 RTMP_PROTOCOL(rtmp)
2856 RTMP_PROTOCOL(rtmpe)
2857 RTMP_PROTOCOL(rtmps)
2858 RTMP_PROTOCOL(rtmpt)
2859 RTMP_PROTOCOL(rtmpte)
2860 RTMP_PROTOCOL(rtmpts)