rtmp: Add support for adobe authentication
[ffmpeg.git] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Kostya 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 DEBUG
52
53 #define APP_MAX_LENGTH 128
54 #define PLAYPATH_MAX_LENGTH 256
55 #define TCURL_MAX_LENGTH 512
56 #define FLASHVER_MAX_LENGTH 64
57 #define RTMP_PKTDATA_DEFAULT_SIZE 4096
58
59 /** RTMP protocol handler state */
60 typedef enum {
61     STATE_START,      ///< client has not done anything yet
62     STATE_HANDSHAKED, ///< client has performed handshake
63     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
64     STATE_PLAYING,    ///< client has started receiving multimedia data from server
65     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66     STATE_RECEIVING,  ///< received a publish command (for input)
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->data_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->data_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.data_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.data_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.data_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.data_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.data_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.data_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 /**
713  * Generate 'publish' call and send it to the server.
714  */
715 static int gen_publish(URLContext *s, RTMPContext *rt)
716 {
717     RTMPPacket pkt;
718     uint8_t *p;
719     int ret;
720
721     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
722
723     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
724                                      0, 30 + strlen(rt->playpath))) < 0)
725         return ret;
726
727     pkt.extra = rt->main_channel_id;
728
729     p = pkt.data;
730     ff_amf_write_string(&p, "publish");
731     ff_amf_write_number(&p, ++rt->nb_invokes);
732     ff_amf_write_null(&p);
733     ff_amf_write_string(&p, rt->playpath);
734     ff_amf_write_string(&p, "live");
735
736     return rtmp_send_packet(rt, &pkt, 1);
737 }
738
739 /**
740  * Generate ping reply and send it to the server.
741  */
742 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
743 {
744     RTMPPacket pkt;
745     uint8_t *p;
746     int ret;
747
748     if (ppkt->data_size < 6) {
749         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
750                ppkt->data_size);
751         return AVERROR_INVALIDDATA;
752     }
753
754     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
755                                      ppkt->timestamp + 1, 6)) < 0)
756         return ret;
757
758     p = pkt.data;
759     bytestream_put_be16(&p, 7);
760     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
761
762     return rtmp_send_packet(rt, &pkt, 0);
763 }
764
765 /**
766  * Generate SWF verification message and send it to the server.
767  */
768 static int gen_swf_verification(URLContext *s, RTMPContext *rt)
769 {
770     RTMPPacket pkt;
771     uint8_t *p;
772     int ret;
773
774     av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
775     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
776                                      0, 44)) < 0)
777         return ret;
778
779     p = pkt.data;
780     bytestream_put_be16(&p, 27);
781     memcpy(p, rt->swfverification, 42);
782
783     return rtmp_send_packet(rt, &pkt, 0);
784 }
785
786 /**
787  * Generate server bandwidth message and send it to the server.
788  */
789 static int gen_server_bw(URLContext *s, RTMPContext *rt)
790 {
791     RTMPPacket pkt;
792     uint8_t *p;
793     int ret;
794
795     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
796                                      0, 4)) < 0)
797         return ret;
798
799     p = pkt.data;
800     bytestream_put_be32(&p, rt->server_bw);
801
802     return rtmp_send_packet(rt, &pkt, 0);
803 }
804
805 /**
806  * Generate check bandwidth message and send it to the server.
807  */
808 static int gen_check_bw(URLContext *s, RTMPContext *rt)
809 {
810     RTMPPacket pkt;
811     uint8_t *p;
812     int ret;
813
814     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
815                                      0, 21)) < 0)
816         return ret;
817
818     p = pkt.data;
819     ff_amf_write_string(&p, "_checkbw");
820     ff_amf_write_number(&p, ++rt->nb_invokes);
821     ff_amf_write_null(&p);
822
823     return rtmp_send_packet(rt, &pkt, 1);
824 }
825
826 /**
827  * Generate report on bytes read so far and send it to the server.
828  */
829 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
830 {
831     RTMPPacket pkt;
832     uint8_t *p;
833     int ret;
834
835     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
836                                      ts, 4)) < 0)
837         return ret;
838
839     p = pkt.data;
840     bytestream_put_be32(&p, rt->bytes_read);
841
842     return rtmp_send_packet(rt, &pkt, 0);
843 }
844
845 static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
846                                   const char *subscribe)
847 {
848     RTMPPacket pkt;
849     uint8_t *p;
850     int ret;
851
852     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
853                                      0, 27 + strlen(subscribe))) < 0)
854         return ret;
855
856     p = pkt.data;
857     ff_amf_write_string(&p, "FCSubscribe");
858     ff_amf_write_number(&p, ++rt->nb_invokes);
859     ff_amf_write_null(&p);
860     ff_amf_write_string(&p, subscribe);
861
862     return rtmp_send_packet(rt, &pkt, 1);
863 }
864
865 int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
866                         const uint8_t *key, int keylen, uint8_t *dst)
867 {
868     struct AVSHA *sha;
869     uint8_t hmac_buf[64+32] = {0};
870     int i;
871
872     sha = av_sha_alloc();
873     if (!sha)
874         return AVERROR(ENOMEM);
875
876     if (keylen < 64) {
877         memcpy(hmac_buf, key, keylen);
878     } else {
879         av_sha_init(sha, 256);
880         av_sha_update(sha,key, keylen);
881         av_sha_final(sha, hmac_buf);
882     }
883     for (i = 0; i < 64; i++)
884         hmac_buf[i] ^= HMAC_IPAD_VAL;
885
886     av_sha_init(sha, 256);
887     av_sha_update(sha, hmac_buf, 64);
888     if (gap <= 0) {
889         av_sha_update(sha, src, len);
890     } else { //skip 32 bytes used for storing digest
891         av_sha_update(sha, src, gap);
892         av_sha_update(sha, src + gap + 32, len - gap - 32);
893     }
894     av_sha_final(sha, hmac_buf + 64);
895
896     for (i = 0; i < 64; i++)
897         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
898     av_sha_init(sha, 256);
899     av_sha_update(sha, hmac_buf, 64+32);
900     av_sha_final(sha, dst);
901
902     av_free(sha);
903
904     return 0;
905 }
906
907 int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
908                             int add_val)
909 {
910     int i, digest_pos = 0;
911
912     for (i = 0; i < 4; i++)
913         digest_pos += buf[i + off];
914     digest_pos = digest_pos % mod_val + add_val;
915
916     return digest_pos;
917 }
918
919 /**
920  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
921  * will be stored) into that packet.
922  *
923  * @param buf handshake data (1536 bytes)
924  * @param encrypted use an encrypted connection (RTMPE)
925  * @return offset to the digest inside input data
926  */
927 static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
928 {
929     int ret, digest_pos;
930
931     if (encrypted)
932         digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
933     else
934         digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
935
936     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
937                               rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
938                               buf + digest_pos);
939     if (ret < 0)
940         return ret;
941
942     return digest_pos;
943 }
944
945 /**
946  * Verify that the received server response has the expected digest value.
947  *
948  * @param buf handshake data received from the server (1536 bytes)
949  * @param off position to search digest offset from
950  * @return 0 if digest is valid, digest position otherwise
951  */
952 static int rtmp_validate_digest(uint8_t *buf, int off)
953 {
954     uint8_t digest[32];
955     int ret, digest_pos;
956
957     digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
958
959     ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
960                               rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
961                               digest);
962     if (ret < 0)
963         return ret;
964
965     if (!memcmp(digest, buf + digest_pos, 32))
966         return digest_pos;
967     return 0;
968 }
969
970 static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
971                                       uint8_t *buf)
972 {
973     uint8_t *p;
974     int ret;
975
976     if (rt->swfhash_len != 32) {
977         av_log(s, AV_LOG_ERROR,
978                "Hash of the decompressed SWF file is not 32 bytes long.\n");
979         return AVERROR(EINVAL);
980     }
981
982     p = &rt->swfverification[0];
983     bytestream_put_byte(&p, 1);
984     bytestream_put_byte(&p, 1);
985     bytestream_put_be32(&p, rt->swfsize);
986     bytestream_put_be32(&p, rt->swfsize);
987
988     if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
989         return ret;
990
991     return 0;
992 }
993
994 #if CONFIG_ZLIB
995 static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
996                                      uint8_t **out_data, int64_t *out_size)
997 {
998     z_stream zs = { 0 };
999     void *ptr;
1000     int size;
1001     int ret = 0;
1002
1003     zs.avail_in = in_size;
1004     zs.next_in  = in_data;
1005     ret = inflateInit(&zs);
1006     if (ret != Z_OK)
1007         return AVERROR_UNKNOWN;
1008
1009     do {
1010         uint8_t tmp_buf[16384];
1011
1012         zs.avail_out = sizeof(tmp_buf);
1013         zs.next_out  = tmp_buf;
1014
1015         ret = inflate(&zs, Z_NO_FLUSH);
1016         if (ret != Z_OK && ret != Z_STREAM_END) {
1017             ret = AVERROR_UNKNOWN;
1018             goto fail;
1019         }
1020
1021         size = sizeof(tmp_buf) - zs.avail_out;
1022         if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1023             ret = AVERROR(ENOMEM);
1024             goto fail;
1025         }
1026         *out_data = ptr;
1027
1028         memcpy(*out_data + *out_size, tmp_buf, size);
1029         *out_size += size;
1030     } while (zs.avail_out == 0);
1031
1032 fail:
1033     inflateEnd(&zs);
1034     return ret;
1035 }
1036 #endif
1037
1038 static int rtmp_calc_swfhash(URLContext *s)
1039 {
1040     RTMPContext *rt = s->priv_data;
1041     uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1042     int64_t in_size, out_size;
1043     URLContext *stream;
1044     char swfhash[32];
1045     int swfsize;
1046     int ret = 0;
1047
1048     /* Get the SWF player file. */
1049     if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1050                           &s->interrupt_callback, NULL)) < 0) {
1051         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1052         goto fail;
1053     }
1054
1055     if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1056         ret = AVERROR(EIO);
1057         goto fail;
1058     }
1059
1060     if (!(in_data = av_malloc(in_size))) {
1061         ret = AVERROR(ENOMEM);
1062         goto fail;
1063     }
1064
1065     if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1066         goto fail;
1067
1068     if (in_size < 3) {
1069         ret = AVERROR_INVALIDDATA;
1070         goto fail;
1071     }
1072
1073     if (!memcmp(in_data, "CWS", 3)) {
1074         /* Decompress the SWF player file using Zlib. */
1075         if (!(out_data = av_malloc(8))) {
1076             ret = AVERROR(ENOMEM);
1077             goto fail;
1078         }
1079         *in_data = 'F'; // magic stuff
1080         memcpy(out_data, in_data, 8);
1081         out_size = 8;
1082
1083 #if CONFIG_ZLIB
1084         if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1085                                              &out_data, &out_size)) < 0)
1086             goto fail;
1087 #else
1088         av_log(s, AV_LOG_ERROR,
1089                "Zlib is required for decompressing the SWF player file.\n");
1090         ret = AVERROR(EINVAL);
1091         goto fail;
1092 #endif
1093         swfsize = out_size;
1094         swfdata = out_data;
1095     } else {
1096         swfsize = in_size;
1097         swfdata = in_data;
1098     }
1099
1100     /* Compute the SHA256 hash of the SWF player file. */
1101     if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1102                                    "Genuine Adobe Flash Player 001", 30,
1103                                    swfhash)) < 0)
1104         goto fail;
1105
1106     /* Set SWFVerification parameters. */
1107     av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1108     rt->swfsize = swfsize;
1109
1110 fail:
1111     av_freep(&in_data);
1112     av_freep(&out_data);
1113     ffurl_close(stream);
1114     return ret;
1115 }
1116
1117 /**
1118  * Perform handshake with the server by means of exchanging pseudorandom data
1119  * signed with HMAC-SHA2 digest.
1120  *
1121  * @return 0 if handshake succeeds, negative value otherwise
1122  */
1123 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1124 {
1125     AVLFG rnd;
1126     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1127         3,                // unencrypted data
1128         0, 0, 0, 0,       // client uptime
1129         RTMP_CLIENT_VER1,
1130         RTMP_CLIENT_VER2,
1131         RTMP_CLIENT_VER3,
1132         RTMP_CLIENT_VER4,
1133     };
1134     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1135     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1136     int i;
1137     int server_pos, client_pos;
1138     uint8_t digest[32], signature[32];
1139     int ret, type = 0;
1140
1141     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1142
1143     av_lfg_init(&rnd, 0xDEADC0DE);
1144     // generate handshake packet - 1536 bytes of pseudorandom data
1145     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1146         tosend[i] = av_lfg_get(&rnd) >> 24;
1147
1148     if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1149         /* When the client wants to use RTMPE, we have to change the command
1150          * byte to 0x06 which means to use encrypted data and we have to set
1151          * the flash version to at least 9.0.115.0. */
1152         tosend[0] = 6;
1153         tosend[5] = 128;
1154         tosend[6] = 0;
1155         tosend[7] = 3;
1156         tosend[8] = 2;
1157
1158         /* Initialize the Diffie-Hellmann context and generate the public key
1159          * to send to the server. */
1160         if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1161             return ret;
1162     }
1163
1164     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1165     if (client_pos < 0)
1166         return client_pos;
1167
1168     if ((ret = ffurl_write(rt->stream, tosend,
1169                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1170         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1171         return ret;
1172     }
1173
1174     if ((ret = ffurl_read_complete(rt->stream, serverdata,
1175                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1176         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1177         return ret;
1178     }
1179
1180     if ((ret = ffurl_read_complete(rt->stream, clientdata,
1181                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1182         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1183         return ret;
1184     }
1185
1186     av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1187     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1188            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1189
1190     if (rt->is_input && serverdata[5] >= 3) {
1191         server_pos = rtmp_validate_digest(serverdata + 1, 772);
1192         if (server_pos < 0)
1193             return server_pos;
1194
1195         if (!server_pos) {
1196             type = 1;
1197             server_pos = rtmp_validate_digest(serverdata + 1, 8);
1198             if (server_pos < 0)
1199                 return server_pos;
1200
1201             if (!server_pos) {
1202                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1203                 return AVERROR(EIO);
1204             }
1205         }
1206
1207         /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1208          * key are the last 32 bytes of the server handshake. */
1209         if (rt->swfsize) {
1210             if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1211                                                   RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1212                 return ret;
1213         }
1214
1215         ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1216                                   rtmp_server_key, sizeof(rtmp_server_key),
1217                                   digest);
1218         if (ret < 0)
1219             return ret;
1220
1221         ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1222                                   0, digest, 32, signature);
1223         if (ret < 0)
1224             return ret;
1225
1226         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1227             /* Compute the shared secret key sent by the server and initialize
1228              * the RC4 encryption. */
1229             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1230                                                    tosend + 1, type)) < 0)
1231                 return ret;
1232
1233             /* Encrypt the signature received by the server. */
1234             ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1235         }
1236
1237         if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1238             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1239             return AVERROR(EIO);
1240         }
1241
1242         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1243             tosend[i] = av_lfg_get(&rnd) >> 24;
1244         ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1245                                   rtmp_player_key, sizeof(rtmp_player_key),
1246                                   digest);
1247         if (ret < 0)
1248             return ret;
1249
1250         ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1251                                   digest, 32,
1252                                   tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1253         if (ret < 0)
1254             return ret;
1255
1256         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1257             /* Encrypt the signature to be send to the server. */
1258             ff_rtmpe_encrypt_sig(rt->stream, tosend +
1259                                  RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1260                                  serverdata[0]);
1261         }
1262
1263         // write reply back to the server
1264         if ((ret = ffurl_write(rt->stream, tosend,
1265                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1266             return ret;
1267
1268         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1269             /* Set RC4 keys for encryption and update the keystreams. */
1270             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1271                 return ret;
1272         }
1273     } else {
1274         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1275             /* Compute the shared secret key sent by the server and initialize
1276              * the RC4 encryption. */
1277             if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1278                             tosend + 1, 1)) < 0)
1279                 return ret;
1280
1281             if (serverdata[0] == 9) {
1282                 /* Encrypt the signature received by the server. */
1283                 ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1284                                      serverdata[0]);
1285             }
1286         }
1287
1288         if ((ret = ffurl_write(rt->stream, serverdata + 1,
1289                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1290             return ret;
1291
1292         if (rt->encrypted && CONFIG_FFRTMPCRYPT_PROTOCOL) {
1293             /* Set RC4 keys for encryption and update the keystreams. */
1294             if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1295                 return ret;
1296         }
1297     }
1298
1299     return 0;
1300 }
1301
1302 static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1303                                   uint32_t *second_int, char *arraydata,
1304                                   int size)
1305 {
1306     int inoutsize;
1307
1308     inoutsize = ffurl_read_complete(rt->stream, arraydata,
1309                                     RTMP_HANDSHAKE_PACKET_SIZE);
1310     if (inoutsize <= 0)
1311         return AVERROR(EIO);
1312     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1313         av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1314                " not following standard\n", (int)inoutsize);
1315         return AVERROR(EINVAL);
1316     }
1317
1318     *first_int  = AV_RB32(arraydata);
1319     *second_int = AV_RB32(arraydata + 4);
1320     return 0;
1321 }
1322
1323 static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1324                                uint32_t second_int, char *arraydata, int size)
1325 {
1326     int inoutsize;
1327
1328     AV_WB32(arraydata, first_int);
1329     AV_WB32(arraydata + 4, first_int);
1330     inoutsize = ffurl_write(rt->stream, arraydata,
1331                             RTMP_HANDSHAKE_PACKET_SIZE);
1332     if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1333         av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1334         return AVERROR(EIO);
1335     }
1336
1337     return 0;
1338 }
1339
1340 /**
1341  * rtmp handshake server side
1342  */
1343 static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1344 {
1345     uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1346     uint32_t hs_epoch;
1347     uint32_t hs_my_epoch;
1348     uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1349     uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1350     uint32_t zeroes;
1351     uint32_t temp       = 0;
1352     int randomidx       = 0;
1353     int inoutsize       = 0;
1354     int ret;
1355
1356     inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1357     if (inoutsize <= 0) {
1358         av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1359         return AVERROR(EIO);
1360     }
1361     // Check Version
1362     if (buffer[0] != 3) {
1363         av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1364         return AVERROR(EIO);
1365     }
1366     if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1367         av_log(s, AV_LOG_ERROR,
1368                "Unable to write answer - RTMP S0\n");
1369         return AVERROR(EIO);
1370     }
1371     /* Receive C1 */
1372     ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1373                                  RTMP_HANDSHAKE_PACKET_SIZE);
1374     if (ret) {
1375         av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1376         return ret;
1377     }
1378     if (zeroes)
1379         av_log(s, AV_LOG_WARNING, "Erroneous C1 Message zero != 0\n");
1380     /* Send S1 */
1381     /* By now same epoch will be sent */
1382     hs_my_epoch = hs_epoch;
1383     /* Generate random */
1384     for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1385          randomidx += 4)
1386         AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1387
1388     ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1389                               RTMP_HANDSHAKE_PACKET_SIZE);
1390     if (ret) {
1391         av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1392         return ret;
1393     }
1394     /* Send S2 */
1395     ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1396                               RTMP_HANDSHAKE_PACKET_SIZE);
1397     if (ret) {
1398         av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1399         return ret;
1400     }
1401     /* Receive C2 */
1402     ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1403                                  RTMP_HANDSHAKE_PACKET_SIZE);
1404     if (ret) {
1405         av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1406         return ret;
1407     }
1408     if (temp != hs_my_epoch)
1409         av_log(s, AV_LOG_WARNING,
1410                "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1411     if (memcmp(buffer + 8, hs_s1 + 8,
1412                RTMP_HANDSHAKE_PACKET_SIZE - 8))
1413         av_log(s, AV_LOG_WARNING,
1414                "Erroneous C2 Message random does not match up\n");
1415
1416     return 0;
1417 }
1418
1419 static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1420 {
1421     RTMPContext *rt = s->priv_data;
1422     int ret;
1423
1424     if (pkt->data_size < 4) {
1425         av_log(s, AV_LOG_ERROR,
1426                "Too short chunk size change packet (%d)\n",
1427                pkt->data_size);
1428         return AVERROR_INVALIDDATA;
1429     }
1430
1431     if (!rt->is_input) {
1432         /* Send the same chunk size change packet back to the server,
1433          * setting the outgoing chunk size to the same as the incoming one. */
1434         if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1435                                         rt->prev_pkt[1])) < 0)
1436             return ret;
1437         rt->out_chunk_size = AV_RB32(pkt->data);
1438     }
1439
1440     rt->in_chunk_size = AV_RB32(pkt->data);
1441     if (rt->in_chunk_size <= 0) {
1442         av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1443                rt->in_chunk_size);
1444         return AVERROR_INVALIDDATA;
1445     }
1446     av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1447            rt->in_chunk_size);
1448
1449     return 0;
1450 }
1451
1452 static int handle_ping(URLContext *s, RTMPPacket *pkt)
1453 {
1454     RTMPContext *rt = s->priv_data;
1455     int t, ret;
1456
1457     if (pkt->data_size < 2) {
1458         av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1459                pkt->data_size);
1460         return AVERROR_INVALIDDATA;
1461     }
1462
1463     t = AV_RB16(pkt->data);
1464     if (t == 6) {
1465         if ((ret = gen_pong(s, rt, pkt)) < 0)
1466             return ret;
1467     } else if (t == 26) {
1468         if (rt->swfsize) {
1469             if ((ret = gen_swf_verification(s, rt)) < 0)
1470                 return ret;
1471         } else {
1472             av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1473         }
1474     }
1475
1476     return 0;
1477 }
1478
1479 static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1480 {
1481     RTMPContext *rt = s->priv_data;
1482
1483     if (pkt->data_size < 4) {
1484         av_log(s, AV_LOG_ERROR,
1485                "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1486                pkt->data_size);
1487         return AVERROR_INVALIDDATA;
1488     }
1489
1490     rt->client_report_size = AV_RB32(pkt->data);
1491     if (rt->client_report_size <= 0) {
1492         av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1493                 rt->client_report_size);
1494         return AVERROR_INVALIDDATA;
1495
1496     }
1497     av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1498     rt->client_report_size >>= 1;
1499
1500     return 0;
1501 }
1502
1503 static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1504 {
1505     RTMPContext *rt = s->priv_data;
1506
1507     if (pkt->data_size < 4) {
1508         av_log(s, AV_LOG_ERROR,
1509                "Too short server bandwidth report packet (%d)\n",
1510                pkt->data_size);
1511         return AVERROR_INVALIDDATA;
1512     }
1513
1514     rt->server_bw = AV_RB32(pkt->data);
1515     if (rt->server_bw <= 0) {
1516         av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1517                rt->server_bw);
1518         return AVERROR_INVALIDDATA;
1519     }
1520     av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1521
1522     return 0;
1523 }
1524
1525 static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1526                          const char *opaque, const char *challenge)
1527 {
1528     uint8_t hash[16];
1529     char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1530     struct AVMD5 *md5 = av_md5_alloc();
1531     if (!md5)
1532         return AVERROR(ENOMEM);
1533
1534     snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1535
1536     av_md5_init(md5);
1537     av_md5_update(md5, user, strlen(user));
1538     av_md5_update(md5, salt, strlen(salt));
1539     av_md5_update(md5, rt->password, strlen(rt->password));
1540     av_md5_final(md5, hash);
1541     av_base64_encode(hashstr, sizeof(hashstr), hash,
1542                      sizeof(hash));
1543     av_md5_init(md5);
1544     av_md5_update(md5, hashstr, strlen(hashstr));
1545     if (opaque)
1546         av_md5_update(md5, opaque, strlen(opaque));
1547     else if (challenge)
1548         av_md5_update(md5, challenge, strlen(challenge));
1549     av_md5_update(md5, challenge2, strlen(challenge2));
1550     av_md5_final(md5, hash);
1551     av_base64_encode(hashstr, sizeof(hashstr), hash,
1552                      sizeof(hash));
1553     snprintf(rt->auth_params, sizeof(rt->auth_params),
1554              "?authmod=%s&user=%s&challenge=%s&response=%s",
1555              "adobe", user, challenge2, hashstr);
1556     if (opaque)
1557         av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1558                     "&opaque=%s", opaque);
1559
1560     av_free(md5);
1561     return 0;
1562 }
1563
1564 static int handle_connect_error(URLContext *s, const char *desc)
1565 {
1566     RTMPContext *rt = s->priv_data;
1567     char buf[300], *ptr;
1568     int i = 0, ret = 0;
1569     const char *user = "", *salt = "", *opaque = NULL,
1570                *challenge = NULL, *cptr = NULL;
1571
1572     if (!(cptr = strstr(desc, "authmod=adobe"))) {
1573         av_log(s, AV_LOG_ERROR,
1574                "Unknown connect error (unsupported authentication method?)\n");
1575         return AVERROR_UNKNOWN;
1576     }
1577
1578     if (!rt->username[0] || !rt->password[0]) {
1579         av_log(s, AV_LOG_ERROR, "No credentials set\n");
1580         return AVERROR_UNKNOWN;
1581     }
1582
1583     if (strstr(desc, "?reason=authfailed")) {
1584         av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1585         return AVERROR_UNKNOWN;
1586     } else if (strstr(desc, "?reason=nosuchuser")) {
1587         av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1588         return AVERROR_UNKNOWN;
1589     }
1590
1591     if (rt->auth_tried) {
1592         av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1593         return AVERROR_UNKNOWN;
1594     }
1595
1596     rt->auth_params[0] = '\0';
1597
1598     if (strstr(desc, "code=403 need auth")) {
1599         snprintf(rt->auth_params, sizeof(rt->auth_params),
1600                  "?authmod=%s&user=%s", "adobe", rt->username);
1601         return 0;
1602     }
1603
1604     if (!(cptr = strstr(desc, "?reason=needauth"))) {
1605         av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1606         return AVERROR_UNKNOWN;
1607     }
1608
1609     av_strlcpy(buf, cptr + 1, sizeof(buf));
1610     ptr = buf;
1611
1612     while (ptr) {
1613         char *next  = strchr(ptr, '&');
1614         char *value = strchr(ptr, '=');
1615         if (next)
1616             *next++ = '\0';
1617         if (value)
1618             *value++ = '\0';
1619         if (!strcmp(ptr, "user")) {
1620             user = value;
1621         } else if (!strcmp(ptr, "salt")) {
1622             salt = value;
1623         } else if (!strcmp(ptr, "opaque")) {
1624             opaque = value;
1625         } else if (!strcmp(ptr, "challenge")) {
1626             challenge = value;
1627         }
1628         ptr = next;
1629     }
1630
1631     if ((ret = do_adobe_auth(rt, user, salt, challenge, opaque)) < 0)
1632         return ret;
1633
1634     rt->auth_tried = 1;
1635     return 0;
1636 }
1637
1638 static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1639 {
1640     RTMPContext *rt = s->priv_data;
1641     const uint8_t *data_end = pkt->data + pkt->data_size;
1642     char *tracked_method = NULL;
1643     int level = AV_LOG_ERROR;
1644     uint8_t tmpstr[256];
1645     int ret;
1646
1647     if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1648         return ret;
1649
1650     if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1651                                 "description", tmpstr, sizeof(tmpstr))) {
1652         if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1653                                !strcmp(tracked_method, "releaseStream") ||
1654                                !strcmp(tracked_method, "FCSubscribe")   ||
1655                                !strcmp(tracked_method, "FCPublish"))) {
1656             /* Gracefully ignore Adobe-specific historical artifact errors. */
1657             level = AV_LOG_WARNING;
1658             ret = 0;
1659         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1660             ret = handle_connect_error(s, tmpstr);
1661             if (!ret) {
1662                 rt->do_reconnect = 1;
1663                 level = AV_LOG_VERBOSE;
1664             }
1665         } else
1666             ret = AVERROR_UNKNOWN;
1667         av_log(s, level, "Server error: %s\n", tmpstr);
1668     }
1669
1670     av_free(tracked_method);
1671     return ret;
1672 }
1673
1674 static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1675 {
1676     RTMPContext *rt = s->priv_data;
1677     double seqnum;
1678     char filename[64];
1679     char command[64];
1680     char statusmsg[128];
1681     int stringlen;
1682     char *pchar;
1683     const uint8_t *p = pkt->data;
1684     uint8_t *pp      = NULL;
1685     RTMPPacket spkt  = { 0 };
1686     GetByteContext gbc;
1687     int ret;
1688
1689     bytestream2_init(&gbc, p, pkt->data_size);
1690     if (ff_amf_read_string(&gbc, command, sizeof(command),
1691                            &stringlen)) {
1692         av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1693         return AVERROR_INVALIDDATA;
1694     }
1695
1696     ret = ff_amf_read_number(&gbc, &seqnum);
1697     if (ret)
1698         return ret;
1699     ret = ff_amf_read_null(&gbc);
1700     if (ret)
1701         return ret;
1702     if (!strcmp(command, "FCPublish") ||
1703         !strcmp(command, "publish")) {
1704         ret = ff_amf_read_string(&gbc, filename,
1705                                  sizeof(filename), &stringlen);
1706         // check with url
1707         if (s->filename) {
1708             pchar = strrchr(s->filename, '/');
1709             if (!pchar) {
1710                 av_log(s, AV_LOG_WARNING,
1711                        "Unable to find / in url %s, bad format\n",
1712                        s->filename);
1713                 pchar = s->filename;
1714             }
1715             pchar++;
1716             if (strcmp(pchar, filename))
1717                 av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1718                        " %s\n", filename, pchar);
1719         }
1720         rt->state = STATE_RECEIVING;
1721     }
1722
1723     if (!strcmp(command, "FCPublish")) {
1724         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1725                                          RTMP_PT_INVOKE, 0,
1726                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1727             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1728             return ret;
1729         }
1730         pp = spkt.data;
1731         ff_amf_write_string(&pp, "onFCPublish");
1732     } else if (!strcmp(command, "publish")) {
1733         PutByteContext pbc;
1734         // Send Stream Begin 1
1735         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1736                                          RTMP_PT_PING, 0, 6)) < 0) {
1737             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1738             return ret;
1739         }
1740         pp = spkt.data;
1741         bytestream2_init_writer(&pbc, pp, spkt.data_size);
1742         bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1743         bytestream2_put_be32(&pbc, rt->nb_streamid);
1744         ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1745                                    rt->prev_pkt[1]);
1746         ff_rtmp_packet_destroy(&spkt);
1747         if (ret < 0)
1748             return ret;
1749
1750         // Send onStatus(NetStream.Publish.Start)
1751         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1752                                          RTMP_PT_INVOKE, 0,
1753                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1754             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1755             return ret;
1756         }
1757         spkt.extra = pkt->extra;
1758         pp = spkt.data;
1759         ff_amf_write_string(&pp, "onStatus");
1760         ff_amf_write_number(&pp, 0);
1761         ff_amf_write_null(&pp);
1762
1763         ff_amf_write_object_start(&pp);
1764         ff_amf_write_field_name(&pp, "level");
1765         ff_amf_write_string(&pp, "status");
1766         ff_amf_write_field_name(&pp, "code");
1767         ff_amf_write_string(&pp, "NetStream.Publish.Start");
1768         ff_amf_write_field_name(&pp, "description");
1769         snprintf(statusmsg, sizeof(statusmsg),
1770                  "%s is now published", filename);
1771         ff_amf_write_string(&pp, statusmsg);
1772         ff_amf_write_field_name(&pp, "details");
1773         ff_amf_write_string(&pp, filename);
1774         ff_amf_write_field_name(&pp, "clientid");
1775         snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1776         ff_amf_write_string(&pp, statusmsg);
1777         ff_amf_write_object_end(&pp);
1778
1779     } else {
1780         if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1781                                          RTMP_PT_INVOKE, 0,
1782                                          RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1783             av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1784             return ret;
1785         }
1786         pp = spkt.data;
1787         ff_amf_write_string(&pp, "_result");
1788         ff_amf_write_number(&pp, seqnum);
1789         ff_amf_write_null(&pp);
1790         if (!strcmp(command, "createStream")) {
1791             rt->nb_streamid++;
1792             if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1793                 rt->nb_streamid++; /* Values 0 and 2 are reserved */
1794             ff_amf_write_number(&pp, rt->nb_streamid);
1795             /* By now we don't control which streams are removed in
1796              * deleteStream. There is no stream creation control
1797              * if a client creates more than 2^32 - 2 streams. */
1798         }
1799     }
1800     spkt.data_size = pp - spkt.data;
1801     ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1802                                rt->prev_pkt[1]);
1803     ff_rtmp_packet_destroy(&spkt);
1804     return ret;
1805 }
1806
1807 static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1808 {
1809     RTMPContext *rt = s->priv_data;
1810     char *tracked_method = NULL;
1811     int ret = 0;
1812
1813     if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1814         return ret;
1815
1816     if (!tracked_method) {
1817         /* Ignore this reply when the current method is not tracked. */
1818         return ret;
1819     }
1820
1821     if (!memcmp(tracked_method, "connect", 7)) {
1822         if (!rt->is_input) {
1823             if ((ret = gen_release_stream(s, rt)) < 0)
1824                 goto fail;
1825
1826             if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1827                 goto fail;
1828         } else {
1829             if ((ret = gen_server_bw(s, rt)) < 0)
1830                 goto fail;
1831         }
1832
1833         if ((ret = gen_create_stream(s, rt)) < 0)
1834             goto fail;
1835
1836         if (rt->is_input) {
1837             /* Send the FCSubscribe command when the name of live
1838              * stream is defined by the user or if it's a live stream. */
1839             if (rt->subscribe) {
1840                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1841                     goto fail;
1842             } else if (rt->live == -1) {
1843                 if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1844                     goto fail;
1845             }
1846         }
1847     } else if (!memcmp(tracked_method, "createStream", 12)) {
1848         //extract a number from the result
1849         if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1850             av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1851         } else {
1852             rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
1853         }
1854
1855         if (!rt->is_input) {
1856             if ((ret = gen_publish(s, rt)) < 0)
1857                 goto fail;
1858         } else {
1859             if ((ret = gen_play(s, rt)) < 0)
1860                 goto fail;
1861             if ((ret = gen_buffer_time(s, rt)) < 0)
1862                 goto fail;
1863         }
1864     }
1865
1866 fail:
1867     av_free(tracked_method);
1868     return ret;
1869 }
1870
1871 static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
1872 {
1873     RTMPContext *rt = s->priv_data;
1874     const uint8_t *data_end = pkt->data + pkt->data_size;
1875     const uint8_t *ptr = pkt->data + 11;
1876     uint8_t tmpstr[256];
1877     int i, t;
1878
1879     for (i = 0; i < 2; i++) {
1880         t = ff_amf_tag_size(ptr, data_end);
1881         if (t < 0)
1882             return 1;
1883         ptr += t;
1884     }
1885
1886     t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
1887     if (!t && !strcmp(tmpstr, "error")) {
1888         if (!ff_amf_get_field_value(ptr, data_end,
1889                                     "description", tmpstr, sizeof(tmpstr)))
1890             av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
1891         return -1;
1892     }
1893
1894     t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
1895     if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
1896     if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
1897     if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
1898     if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
1899
1900     return 0;
1901 }
1902
1903 static int handle_invoke(URLContext *s, RTMPPacket *pkt)
1904 {
1905     RTMPContext *rt = s->priv_data;
1906     int ret = 0;
1907
1908     //TODO: check for the messages sent for wrong state?
1909     if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
1910         if ((ret = handle_invoke_error(s, pkt)) < 0)
1911             return ret;
1912     } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
1913         if ((ret = handle_invoke_result(s, pkt)) < 0)
1914             return ret;
1915     } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
1916         if ((ret = handle_invoke_status(s, pkt)) < 0)
1917             return ret;
1918     } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
1919         if ((ret = gen_check_bw(s, rt)) < 0)
1920             return ret;
1921     } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) ||
1922                !memcmp(pkt->data, "\002\000\011FCPublish", 12)     ||
1923                !memcmp(pkt->data, "\002\000\007publish", 10)       ||
1924                !memcmp(pkt->data, "\002\000\010_checkbw", 11)      ||
1925                !memcmp(pkt->data, "\002\000\014createStream", 15)) {
1926         if (ret = send_invoke_response(s, pkt) < 0)
1927             return ret;
1928     }
1929
1930     return ret;
1931 }
1932
1933 static int handle_notify(URLContext *s, RTMPPacket *pkt) {
1934     RTMPContext *rt  = s->priv_data;
1935     const uint8_t *p = NULL;
1936     uint8_t *cp      = NULL;
1937     uint8_t commandbuffer[64];
1938     char statusmsg[128];
1939     int stringlen;
1940     GetByteContext gbc;
1941     PutByteContext pbc;
1942     uint32_t ts;
1943     int old_flv_size;
1944     const uint8_t *datatowrite;
1945     unsigned datatowritelength;
1946
1947     p = pkt->data;
1948     bytestream2_init(&gbc, p, pkt->data_size);
1949     if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
1950                            &stringlen))
1951         return AVERROR_INVALIDDATA;
1952     if (!strcmp(commandbuffer, "@setDataFrame")) {
1953         datatowrite       = gbc.buffer;
1954         datatowritelength = bytestream2_get_bytes_left(&gbc);
1955         if (ff_amf_read_string(&gbc, statusmsg,
1956                                sizeof(statusmsg), &stringlen))
1957             return AVERROR_INVALIDDATA;
1958         if (strcmp(statusmsg, "onMetaData")) {
1959             av_log(s, AV_LOG_INFO, "Expecting onMetadata but got %s\n",
1960                    statusmsg);
1961             return 0;
1962         }
1963
1964         /* Provide ECMAArray to flv */
1965         ts = pkt->timestamp;
1966
1967         // generate packet header and put data into buffer for FLV demuxer
1968         if (rt->flv_off < rt->flv_size) {
1969             old_flv_size  = rt->flv_size;
1970             rt->flv_size += datatowritelength + 15;
1971         } else {
1972             old_flv_size = 0;
1973             rt->flv_size = datatowritelength + 15;
1974             rt->flv_off  = 0;
1975         }
1976
1977         cp = av_realloc(rt->flv_data, rt->flv_size);
1978         if (!cp)
1979             return AVERROR(ENOMEM);
1980         rt->flv_data = cp;
1981         bytestream2_init_writer(&pbc, cp, rt->flv_size);
1982         bytestream2_skip_p(&pbc, old_flv_size);
1983         bytestream2_put_byte(&pbc, pkt->type);
1984         bytestream2_put_be24(&pbc, datatowritelength);
1985         bytestream2_put_be24(&pbc, ts);
1986         bytestream2_put_byte(&pbc, ts >> 24);
1987         bytestream2_put_be24(&pbc, 0);
1988         bytestream2_put_buffer(&pbc, datatowrite, datatowritelength);
1989         bytestream2_put_be32(&pbc, 0);
1990     }
1991     return 0;
1992 }
1993
1994 /**
1995  * Parse received packet and possibly perform some action depending on
1996  * the packet contents.
1997  * @return 0 for no errors, negative values for serious errors which prevent
1998  *         further communications, positive values for uncritical errors
1999  */
2000 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2001 {
2002     int ret;
2003
2004 #ifdef DEBUG
2005     ff_rtmp_packet_dump(s, pkt);
2006 #endif
2007
2008     switch (pkt->type) {
2009     case RTMP_PT_BYTES_READ:
2010         av_dlog(s, "received bytes read report\n");
2011         break;
2012     case RTMP_PT_CHUNK_SIZE:
2013         if ((ret = handle_chunk_size(s, pkt)) < 0)
2014             return ret;
2015         break;
2016     case RTMP_PT_PING:
2017         if ((ret = handle_ping(s, pkt)) < 0)
2018             return ret;
2019         break;
2020     case RTMP_PT_CLIENT_BW:
2021         if ((ret = handle_client_bw(s, pkt)) < 0)
2022             return ret;
2023         break;
2024     case RTMP_PT_SERVER_BW:
2025         if ((ret = handle_server_bw(s, pkt)) < 0)
2026             return ret;
2027         break;
2028     case RTMP_PT_INVOKE:
2029         if ((ret = handle_invoke(s, pkt)) < 0)
2030             return ret;
2031         break;
2032     case RTMP_PT_VIDEO:
2033     case RTMP_PT_AUDIO:
2034     case RTMP_PT_METADATA:
2035     case RTMP_PT_NOTIFY:
2036         /* Audio, Video and Metadata packets are parsed in get_packet() */
2037         break;
2038     default:
2039         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2040         break;
2041     }
2042     return 0;
2043 }
2044
2045 /**
2046  * Interact with the server by receiving and sending RTMP packets until
2047  * there is some significant data (media data or expected status notification).
2048  *
2049  * @param s          reading context
2050  * @param for_header non-zero value tells function to work until it
2051  * gets notification from the server that playing has been started,
2052  * otherwise function will work until some media data is received (or
2053  * an error happens)
2054  * @return 0 for successful operation, negative value in case of error
2055  */
2056 static int get_packet(URLContext *s, int for_header)
2057 {
2058     RTMPContext *rt = s->priv_data;
2059     int ret;
2060     uint8_t *p;
2061     const uint8_t *next;
2062     uint32_t data_size;
2063     uint32_t ts, cts, pts=0;
2064
2065     if (rt->state == STATE_STOPPED)
2066         return AVERROR_EOF;
2067
2068     for (;;) {
2069         RTMPPacket rpkt = { 0 };
2070         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2071                                        rt->in_chunk_size, rt->prev_pkt[0])) <= 0) {
2072             if (ret == 0) {
2073                 return AVERROR(EAGAIN);
2074             } else {
2075                 return AVERROR(EIO);
2076             }
2077         }
2078         rt->bytes_read += ret;
2079         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
2080             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2081             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2082                 return ret;
2083             rt->last_bytes_read = rt->bytes_read;
2084         }
2085
2086         ret = rtmp_parse_result(s, rt, &rpkt);
2087         if (ret < 0) {//serious error in current packet
2088             ff_rtmp_packet_destroy(&rpkt);
2089             return ret;
2090         }
2091         if (rt->do_reconnect && for_header) {
2092             ff_rtmp_packet_destroy(&rpkt);
2093             return 0;
2094         }
2095         if (rt->state == STATE_STOPPED) {
2096             ff_rtmp_packet_destroy(&rpkt);
2097             return AVERROR_EOF;
2098         }
2099         if (for_header && (rt->state == STATE_PLAYING    ||
2100                            rt->state == STATE_PUBLISHING ||
2101                            rt->state == STATE_RECEIVING)) {
2102             ff_rtmp_packet_destroy(&rpkt);
2103             return 0;
2104         }
2105         if (!rpkt.data_size || !rt->is_input) {
2106             ff_rtmp_packet_destroy(&rpkt);
2107             continue;
2108         }
2109         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
2110            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
2111             ts = rpkt.timestamp;
2112
2113             // generate packet header and put data into buffer for FLV demuxer
2114             rt->flv_off  = 0;
2115             rt->flv_size = rpkt.data_size + 15;
2116             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
2117             bytestream_put_byte(&p, rpkt.type);
2118             bytestream_put_be24(&p, rpkt.data_size);
2119             bytestream_put_be24(&p, ts);
2120             bytestream_put_byte(&p, ts >> 24);
2121             bytestream_put_be24(&p, 0);
2122             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
2123             bytestream_put_be32(&p, 0);
2124             ff_rtmp_packet_destroy(&rpkt);
2125             return 0;
2126         } else if (rpkt.type == RTMP_PT_NOTIFY) {
2127             ret = handle_notify(s, &rpkt);
2128             ff_rtmp_packet_destroy(&rpkt);
2129             if (ret) {
2130                 av_log(s, AV_LOG_ERROR, "Handle notify error\n");
2131                 return ret;
2132             }
2133             return 0;
2134         } else if (rpkt.type == RTMP_PT_METADATA) {
2135             // we got raw FLV data, make it available for FLV demuxer
2136             rt->flv_off  = 0;
2137             rt->flv_size = rpkt.data_size;
2138             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2139             /* rewrite timestamps */
2140             next = rpkt.data;
2141             ts = rpkt.timestamp;
2142             while (next - rpkt.data < rpkt.data_size - 11) {
2143                 next++;
2144                 data_size = bytestream_get_be24(&next);
2145                 p=next;
2146                 cts = bytestream_get_be24(&next);
2147                 cts |= bytestream_get_byte(&next) << 24;
2148                 if (pts==0)
2149                     pts=cts;
2150                 ts += cts - pts;
2151                 pts = cts;
2152                 bytestream_put_be24(&p, ts);
2153                 bytestream_put_byte(&p, ts >> 24);
2154                 next += data_size + 3 + 4;
2155             }
2156             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
2157             ff_rtmp_packet_destroy(&rpkt);
2158             return 0;
2159         }
2160         ff_rtmp_packet_destroy(&rpkt);
2161     }
2162 }
2163
2164 static int rtmp_close(URLContext *h)
2165 {
2166     RTMPContext *rt = h->priv_data;
2167     int ret = 0;
2168
2169     if (!rt->is_input) {
2170         rt->flv_data = NULL;
2171         if (rt->out_pkt.data_size)
2172             ff_rtmp_packet_destroy(&rt->out_pkt);
2173         if (rt->state > STATE_FCPUBLISH)
2174             ret = gen_fcunpublish_stream(h, rt);
2175     }
2176     if (rt->state > STATE_HANDSHAKED)
2177         ret = gen_delete_stream(h, rt);
2178
2179     free_tracked_methods(rt);
2180     av_freep(&rt->flv_data);
2181     ffurl_close(rt->stream);
2182     return ret;
2183 }
2184
2185 /**
2186  * Open RTMP connection and verify that the stream can be played.
2187  *
2188  * URL syntax: rtmp://server[:port][/app][/playpath]
2189  *             where 'app' is first one or two directories in the path
2190  *             (e.g. /ondemand/, /flash/live/, etc.)
2191  *             and 'playpath' is a file name (the rest of the path,
2192  *             may be prefixed with "mp4:")
2193  */
2194 static int rtmp_open(URLContext *s, const char *uri, int flags)
2195 {
2196     RTMPContext *rt = s->priv_data;
2197     char proto[8], hostname[256], path[1024], auth[100], *fname;
2198     char *old_app;
2199     uint8_t buf[2048];
2200     int port;
2201     AVDictionary *opts = NULL;
2202     int ret;
2203
2204     if (rt->listen_timeout > 0)
2205         rt->listen = 1;
2206
2207     rt->is_input = !(flags & AVIO_FLAG_WRITE);
2208
2209     av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2210                  hostname, sizeof(hostname), &port,
2211                  path, sizeof(path), s->filename);
2212
2213     if (auth[0]) {
2214         char *ptr = strchr(auth, ':');
2215         if (ptr) {
2216             *ptr = '\0';
2217             av_strlcpy(rt->username, auth, sizeof(rt->username));
2218             av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2219         }
2220     }
2221
2222     if (rt->listen && strcmp(proto, "rtmp")) {
2223         av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2224                proto);
2225         return AVERROR(EINVAL);
2226     }
2227     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2228         if (!strcmp(proto, "rtmpts"))
2229             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2230
2231         /* open the http tunneling connection */
2232         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2233     } else if (!strcmp(proto, "rtmps")) {
2234         /* open the tls connection */
2235         if (port < 0)
2236             port = RTMPS_DEFAULT_PORT;
2237         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2238     } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2239         if (!strcmp(proto, "rtmpte"))
2240             av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2241
2242         /* open the encrypted connection */
2243         ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2244         rt->encrypted = 1;
2245     } else {
2246         /* open the tcp connection */
2247         if (port < 0)
2248             port = RTMP_DEFAULT_PORT;
2249         if (rt->listen)
2250             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2251                         "?listen&listen_timeout=%d",
2252                         rt->listen_timeout * 1000);
2253         else
2254             ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2255     }
2256
2257 reconnect:
2258     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2259                           &s->interrupt_callback, &opts)) < 0) {
2260         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2261         goto fail;
2262     }
2263
2264     if (rt->swfverify) {
2265         if ((ret = rtmp_calc_swfhash(s)) < 0)
2266             goto fail;
2267     }
2268
2269     rt->state = STATE_START;
2270     if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2271         goto fail;
2272     if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2273         goto fail;
2274
2275     rt->out_chunk_size = 128;
2276     rt->in_chunk_size  = 128; // Probably overwritten later
2277     rt->state = STATE_HANDSHAKED;
2278
2279     // Keep the application name when it has been defined by the user.
2280     old_app = rt->app;
2281
2282     rt->app = av_malloc(APP_MAX_LENGTH);
2283     if (!rt->app) {
2284         ret = AVERROR(ENOMEM);
2285         goto fail;
2286     }
2287
2288     //extract "app" part from path
2289     if (!strncmp(path, "/ondemand/", 10)) {
2290         fname = path + 10;
2291         memcpy(rt->app, "ondemand", 9);
2292     } else {
2293         char *next = *path ? path + 1 : path;
2294         char *p = strchr(next, '/');
2295         if (!p) {
2296             fname = next;
2297             rt->app[0] = '\0';
2298         } else {
2299             // make sure we do not mismatch a playpath for an application instance
2300             char *c = strchr(p + 1, ':');
2301             fname = strchr(p + 1, '/');
2302             if (!fname || (c && c < fname)) {
2303                 fname = p + 1;
2304                 av_strlcpy(rt->app, path + 1, p - path);
2305             } else {
2306                 fname++;
2307                 av_strlcpy(rt->app, path + 1, fname - path - 1);
2308             }
2309         }
2310     }
2311
2312     if (old_app) {
2313         // The name of application has been defined by the user, override it.
2314         av_free(rt->app);
2315         rt->app = old_app;
2316     }
2317
2318     if (!rt->playpath) {
2319         int len = strlen(fname);
2320
2321         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2322         if (!rt->playpath) {
2323             ret = AVERROR(ENOMEM);
2324             goto fail;
2325         }
2326
2327         if (!strchr(fname, ':') && len >= 4 &&
2328             (!strcmp(fname + len - 4, ".f4v") ||
2329              !strcmp(fname + len - 4, ".mp4"))) {
2330             memcpy(rt->playpath, "mp4:", 5);
2331         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2332             fname[len - 4] = '\0';
2333         } else {
2334             rt->playpath[0] = 0;
2335         }
2336         av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2337     }
2338
2339     if (!rt->tcurl) {
2340         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2341         if (!rt->tcurl) {
2342             ret = AVERROR(ENOMEM);
2343             goto fail;
2344         }
2345         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2346                     port, "/%s", rt->app);
2347     }
2348
2349     if (!rt->flashver) {
2350         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2351         if (!rt->flashver) {
2352             ret = AVERROR(ENOMEM);
2353             goto fail;
2354         }
2355         if (rt->is_input) {
2356             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2357                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2358                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2359         } else {
2360             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2361                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2362         }
2363     }
2364
2365     rt->client_report_size = 1048576;
2366     rt->bytes_read = 0;
2367     rt->last_bytes_read = 0;
2368     rt->server_bw = 2500000;
2369
2370     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2371            proto, path, rt->app, rt->playpath);
2372     if (!rt->listen) {
2373         if ((ret = gen_connect(s, rt)) < 0)
2374             goto fail;
2375     } else {
2376         if (read_connect(s, s->priv_data) < 0)
2377             goto fail;
2378         rt->is_input = 1;
2379     }
2380
2381     do {
2382         ret = get_packet(s, 1);
2383     } while (ret == EAGAIN);
2384     if (ret < 0)
2385         goto fail;
2386
2387     if (rt->do_reconnect) {
2388         ffurl_close(rt->stream);
2389         rt->stream       = NULL;
2390         rt->do_reconnect = 0;
2391         rt->nb_invokes   = 0;
2392         memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt));
2393         free_tracked_methods(rt);
2394         goto reconnect;
2395     }
2396
2397     if (rt->is_input) {
2398         // generate FLV header for demuxer
2399         rt->flv_size = 13;
2400         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
2401         rt->flv_off  = 0;
2402         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2403     } else {
2404         rt->flv_size = 0;
2405         rt->flv_data = NULL;
2406         rt->flv_off  = 0;
2407         rt->skip_bytes = 13;
2408     }
2409
2410     s->max_packet_size = rt->stream->max_packet_size;
2411     s->is_streamed     = 1;
2412     return 0;
2413
2414 fail:
2415     av_dict_free(&opts);
2416     rtmp_close(s);
2417     return ret;
2418 }
2419
2420 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2421 {
2422     RTMPContext *rt = s->priv_data;
2423     int orig_size = size;
2424     int ret;
2425
2426     while (size > 0) {
2427         int data_left = rt->flv_size - rt->flv_off;
2428
2429         if (data_left >= size) {
2430             memcpy(buf, rt->flv_data + rt->flv_off, size);
2431             rt->flv_off += size;
2432             return orig_size;
2433         }
2434         if (data_left > 0) {
2435             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2436             buf  += data_left;
2437             size -= data_left;
2438             rt->flv_off = rt->flv_size;
2439             return data_left;
2440         }
2441         if ((ret = get_packet(s, 0)) < 0)
2442            return ret;
2443     }
2444     return orig_size;
2445 }
2446
2447 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2448 {
2449     RTMPContext *rt = s->priv_data;
2450     int size_temp = size;
2451     int pktsize, pkttype;
2452     uint32_t ts;
2453     const uint8_t *buf_temp = buf;
2454     uint8_t c;
2455     int ret;
2456
2457     do {
2458         if (rt->skip_bytes) {
2459             int skip = FFMIN(rt->skip_bytes, size_temp);
2460             buf_temp       += skip;
2461             size_temp      -= skip;
2462             rt->skip_bytes -= skip;
2463             continue;
2464         }
2465
2466         if (rt->flv_header_bytes < 11) {
2467             const uint8_t *header = rt->flv_header;
2468             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
2469             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2470             rt->flv_header_bytes += copy;
2471             size_temp            -= copy;
2472             if (rt->flv_header_bytes < 11)
2473                 break;
2474
2475             pkttype = bytestream_get_byte(&header);
2476             pktsize = bytestream_get_be24(&header);
2477             ts = bytestream_get_be24(&header);
2478             ts |= bytestream_get_byte(&header) << 24;
2479             bytestream_get_be24(&header);
2480             rt->flv_size = pktsize;
2481
2482             //force 12bytes header
2483             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2484                 pkttype == RTMP_PT_NOTIFY) {
2485                 if (pkttype == RTMP_PT_NOTIFY)
2486                     pktsize += 16;
2487                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
2488             }
2489
2490             //this can be a big packet, it's better to send it right here
2491             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
2492                                              pkttype, ts, pktsize)) < 0)
2493                 return ret;
2494
2495             rt->out_pkt.extra = rt->main_channel_id;
2496             rt->flv_data = rt->out_pkt.data;
2497
2498             if (pkttype == RTMP_PT_NOTIFY)
2499                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2500         }
2501
2502         if (rt->flv_size - rt->flv_off > size_temp) {
2503             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2504             rt->flv_off += size_temp;
2505             size_temp = 0;
2506         } else {
2507             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2508             size_temp   -= rt->flv_size - rt->flv_off;
2509             rt->flv_off += rt->flv_size - rt->flv_off;
2510         }
2511
2512         if (rt->flv_off == rt->flv_size) {
2513             rt->skip_bytes = 4;
2514
2515             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2516                 return ret;
2517             rt->flv_size = 0;
2518             rt->flv_off = 0;
2519             rt->flv_header_bytes = 0;
2520             rt->flv_nb_packets++;
2521         }
2522     } while (buf_temp - buf < size);
2523
2524     if (rt->flv_nb_packets < rt->flush_interval)
2525         return size;
2526     rt->flv_nb_packets = 0;
2527
2528     /* set stream into nonblocking mode */
2529     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2530
2531     /* try to read one byte from the stream */
2532     ret = ffurl_read(rt->stream, &c, 1);
2533
2534     /* switch the stream back into blocking mode */
2535     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2536
2537     if (ret == AVERROR(EAGAIN)) {
2538         /* no incoming data to handle */
2539         return size;
2540     } else if (ret < 0) {
2541         return ret;
2542     } else if (ret == 1) {
2543         RTMPPacket rpkt = { 0 };
2544
2545         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2546                                                 rt->in_chunk_size,
2547                                                 rt->prev_pkt[0], c)) <= 0)
2548              return ret;
2549
2550         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2551             return ret;
2552
2553         ff_rtmp_packet_destroy(&rpkt);
2554     }
2555
2556     return size;
2557 }
2558
2559 #define OFFSET(x) offsetof(RTMPContext, x)
2560 #define DEC AV_OPT_FLAG_DECODING_PARAM
2561 #define ENC AV_OPT_FLAG_ENCODING_PARAM
2562
2563 static const AVOption rtmp_options[] = {
2564     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2565     {"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},
2566     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2567     {"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},
2568     {"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},
2569     {"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"},
2570     {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2571     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2572     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2573     {"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},
2574     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2575     {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2576     {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2577     {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2578     {"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},
2579     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2580     {"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},
2581     {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2582     {"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" },
2583     { NULL },
2584 };
2585
2586 #define RTMP_PROTOCOL(flavor)                    \
2587 static const AVClass flavor##_class = {          \
2588     .class_name = #flavor,                       \
2589     .item_name  = av_default_item_name,          \
2590     .option     = rtmp_options,                  \
2591     .version    = LIBAVUTIL_VERSION_INT,         \
2592 };                                               \
2593                                                  \
2594 URLProtocol ff_##flavor##_protocol = {           \
2595     .name           = #flavor,                   \
2596     .url_open       = rtmp_open,                 \
2597     .url_read       = rtmp_read,                 \
2598     .url_write      = rtmp_write,                \
2599     .url_close      = rtmp_close,                \
2600     .priv_data_size = sizeof(RTMPContext),       \
2601     .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2602     .priv_data_class= &flavor##_class,           \
2603 };
2604
2605
2606 RTMP_PROTOCOL(rtmp)
2607 RTMP_PROTOCOL(rtmpe)
2608 RTMP_PROTOCOL(rtmps)
2609 RTMP_PROTOCOL(rtmpt)
2610 RTMP_PROTOCOL(rtmpte)
2611 RTMP_PROTOCOL(rtmpts)