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