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