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