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