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