]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / rtmpproto.c
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2009 Kostya Shishkov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * RTMP protocol
25  */
26
27 #include "libavcodec/bytestream.h"
28 #include "libavutil/avstring.h"
29 #include "libavutil/intfloat.h"
30 #include "libavutil/lfg.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/sha.h"
33 #include "avformat.h"
34 #include "internal.h"
35
36 #include "network.h"
37
38 #include "flv.h"
39 #include "rtmp.h"
40 #include "rtmppkt.h"
41 #include "url.h"
42
43 //#define DEBUG
44
45 #define APP_MAX_LENGTH 128
46 #define PLAYPATH_MAX_LENGTH 256
47 #define TCURL_MAX_LENGTH 512
48 #define FLASHVER_MAX_LENGTH 64
49
50 /** RTMP protocol handler state */
51 typedef enum {
52     STATE_START,      ///< client has not done anything yet
53     STATE_HANDSHAKED, ///< client has performed handshake
54     STATE_RELEASING,  ///< client releasing stream before publish it (for output)
55     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
56     STATE_CONNECTING, ///< client connected to server successfully
57     STATE_READY,      ///< client has sent all needed commands and waits for server reply
58     STATE_PLAYING,    ///< client has started receiving multimedia data from server
59     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
60     STATE_STOPPED,    ///< the broadcast has been stopped
61 } ClientState;
62
63 /** protocol handler context */
64 typedef struct RTMPContext {
65     const AVClass *class;
66     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
67     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
68     int           chunk_size;                 ///< size of the chunks RTMP packets are divided into
69     int           is_input;                   ///< input/output flag
70     char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
71     int           live;                       ///< 0: recorded, -1: live, -2: both
72     char          *app;                       ///< name of application
73     char          *conn;                      ///< append arbitrary AMF data to the Connect message
74     ClientState   state;                      ///< current state
75     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
76     uint8_t*      flv_data;                   ///< buffer with data for demuxer
77     int           flv_size;                   ///< current buffer size
78     int           flv_off;                    ///< number of bytes read from current buffer
79     int           flv_nb_packets;             ///< number of flv packets published
80     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
81     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
82     uint32_t      bytes_read;                 ///< number of bytes read from server
83     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
84     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
85     uint8_t       flv_header[11];             ///< partial incoming flv packet header
86     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
87     int           nb_invokes;                 ///< keeps track of invoke messages
88     int           create_stream_invoke;       ///< invoke id for the create stream command
89     char*         tcurl;                      ///< url of the target stream
90     char*         flashver;                   ///< version of the flash plugin
91     char*         swfurl;                     ///< url of the swf player
92     int           server_bw;                  ///< server bandwidth
93     int           client_buffer_time;         ///< client buffer time in ms
94     int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
95 } RTMPContext;
96
97 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
98 /** Client key used for digest signing */
99 static const uint8_t rtmp_player_key[] = {
100     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
101     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
102
103     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
104     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
105     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
106 };
107
108 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
109 /** Key used for RTMP server digest signing */
110 static const uint8_t rtmp_server_key[] = {
111     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
112     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
113     'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
114
115     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
116     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
117     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
118 };
119
120 static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
121 {
122     char *field, *value;
123     char type;
124
125     /* The type must be B for Boolean, N for number, S for string, O for
126      * object, or Z for null. For Booleans the data must be either 0 or 1 for
127      * FALSE or TRUE, respectively. Likewise for Objects the data must be
128      * 0 or 1 to end or begin an object, respectively. Data items in subobjects
129      * may be named, by prefixing the type with 'N' and specifying the name
130      * before the value (ie. NB:myFlag:1). This option may be used multiple times
131      * to construct arbitrary AMF sequences. */
132     if (param[0] && param[1] == ':') {
133         type = param[0];
134         value = param + 2;
135     } else if (param[0] == 'N' && param[1] && param[2] == ':') {
136         type = param[1];
137         field = param + 3;
138         value = strchr(field, ':');
139         if (!value)
140             goto fail;
141         *value = '\0';
142         value++;
143
144         if (!field || !value)
145             goto fail;
146
147         ff_amf_write_field_name(p, field);
148     } else {
149         goto fail;
150     }
151
152     switch (type) {
153     case 'B':
154         ff_amf_write_bool(p, value[0] != '0');
155         break;
156     case 'S':
157         ff_amf_write_string(p, value);
158         break;
159     case 'N':
160         ff_amf_write_number(p, strtod(value, NULL));
161         break;
162     case 'Z':
163         ff_amf_write_null(p);
164         break;
165     case 'O':
166         if (value[0] != '0')
167             ff_amf_write_object_start(p);
168         else
169             ff_amf_write_object_end(p);
170         break;
171     default:
172         goto fail;
173         break;
174     }
175
176     return 0;
177
178 fail:
179     av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
180     return AVERROR(EINVAL);
181 }
182
183 /**
184  * Generate 'connect' call and send it to the server.
185  */
186 static int gen_connect(URLContext *s, RTMPContext *rt)
187 {
188     RTMPPacket pkt;
189     uint8_t *p;
190     int ret;
191
192     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
193                                      0, 4096)) < 0)
194         return ret;
195
196     p = pkt.data;
197
198     ff_amf_write_string(&p, "connect");
199     ff_amf_write_number(&p, ++rt->nb_invokes);
200     ff_amf_write_object_start(&p);
201     ff_amf_write_field_name(&p, "app");
202     ff_amf_write_string(&p, rt->app);
203
204     if (!rt->is_input) {
205         ff_amf_write_field_name(&p, "type");
206         ff_amf_write_string(&p, "nonprivate");
207     }
208     ff_amf_write_field_name(&p, "flashVer");
209     ff_amf_write_string(&p, rt->flashver);
210
211     if (rt->swfurl) {
212         ff_amf_write_field_name(&p, "swfUrl");
213         ff_amf_write_string(&p, rt->swfurl);
214     }
215
216     ff_amf_write_field_name(&p, "tcUrl");
217     ff_amf_write_string(&p, rt->tcurl);
218     if (rt->is_input) {
219         ff_amf_write_field_name(&p, "fpad");
220         ff_amf_write_bool(&p, 0);
221         ff_amf_write_field_name(&p, "capabilities");
222         ff_amf_write_number(&p, 15.0);
223
224         /* Tell the server we support all the audio codecs except
225          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
226          * which are unused in the RTMP protocol implementation. */
227         ff_amf_write_field_name(&p, "audioCodecs");
228         ff_amf_write_number(&p, 4071.0);
229         ff_amf_write_field_name(&p, "videoCodecs");
230         ff_amf_write_number(&p, 252.0);
231         ff_amf_write_field_name(&p, "videoFunction");
232         ff_amf_write_number(&p, 1.0);
233     }
234     ff_amf_write_object_end(&p);
235
236     if (rt->conn) {
237         char *param = rt->conn;
238
239         // Write arbitrary AMF data to the Connect message.
240         while (param != NULL) {
241             char *sep;
242             param += strspn(param, " ");
243             if (!*param)
244                 break;
245             sep = strchr(param, ' ');
246             if (sep)
247                 *sep = '\0';
248             if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
249                 // Invalid AMF parameter.
250                 ff_rtmp_packet_destroy(&pkt);
251                 return ret;
252             }
253
254             if (sep)
255                 param = sep + 1;
256             else
257                 break;
258         }
259     }
260
261     pkt.data_size = p - pkt.data;
262
263     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
264                                rt->prev_pkt[1]);
265     ff_rtmp_packet_destroy(&pkt);
266
267     return ret;
268 }
269
270 /**
271  * Generate 'releaseStream' call and send it to the server. It should make
272  * the server release some channel for media streams.
273  */
274 static int gen_release_stream(URLContext *s, RTMPContext *rt)
275 {
276     RTMPPacket pkt;
277     uint8_t *p;
278     int ret;
279
280     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
281                                      0, 29 + strlen(rt->playpath))) < 0)
282         return ret;
283
284     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
285     p = pkt.data;
286     ff_amf_write_string(&p, "releaseStream");
287     ff_amf_write_number(&p, ++rt->nb_invokes);
288     ff_amf_write_null(&p);
289     ff_amf_write_string(&p, rt->playpath);
290
291     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
292                                rt->prev_pkt[1]);
293     ff_rtmp_packet_destroy(&pkt);
294
295     return ret;
296 }
297
298 /**
299  * Generate 'FCPublish' call and send it to the server. It should make
300  * the server preapare for receiving media streams.
301  */
302 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
303 {
304     RTMPPacket pkt;
305     uint8_t *p;
306     int ret;
307
308     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
309                                      0, 25 + strlen(rt->playpath))) < 0)
310         return ret;
311
312     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
313     p = pkt.data;
314     ff_amf_write_string(&p, "FCPublish");
315     ff_amf_write_number(&p, ++rt->nb_invokes);
316     ff_amf_write_null(&p);
317     ff_amf_write_string(&p, rt->playpath);
318
319     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
320                                rt->prev_pkt[1]);
321     ff_rtmp_packet_destroy(&pkt);
322
323     return ret;
324 }
325
326 /**
327  * Generate 'FCUnpublish' call and send it to the server. It should make
328  * the server destroy stream.
329  */
330 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
331 {
332     RTMPPacket pkt;
333     uint8_t *p;
334     int ret;
335
336     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
337                                      0, 27 + strlen(rt->playpath))) < 0)
338         return ret;
339
340     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
341     p = pkt.data;
342     ff_amf_write_string(&p, "FCUnpublish");
343     ff_amf_write_number(&p, ++rt->nb_invokes);
344     ff_amf_write_null(&p);
345     ff_amf_write_string(&p, rt->playpath);
346
347     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
348                                rt->prev_pkt[1]);
349     ff_rtmp_packet_destroy(&pkt);
350
351     return ret;
352 }
353
354 /**
355  * Generate 'createStream' call and send it to the server. It should make
356  * the server allocate some channel for media streams.
357  */
358 static int gen_create_stream(URLContext *s, RTMPContext *rt)
359 {
360     RTMPPacket pkt;
361     uint8_t *p;
362     int ret;
363
364     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
365
366     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
367                                      0, 25)) < 0)
368         return ret;
369
370     p = pkt.data;
371     ff_amf_write_string(&p, "createStream");
372     ff_amf_write_number(&p, ++rt->nb_invokes);
373     ff_amf_write_null(&p);
374     rt->create_stream_invoke = rt->nb_invokes;
375
376     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
377                                rt->prev_pkt[1]);
378     ff_rtmp_packet_destroy(&pkt);
379
380     return ret;
381 }
382
383
384 /**
385  * Generate 'deleteStream' call and send it to the server. It should make
386  * the server remove some channel for media streams.
387  */
388 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
389 {
390     RTMPPacket pkt;
391     uint8_t *p;
392     int ret;
393
394     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
395
396     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
397                                      0, 34)) < 0)
398         return ret;
399
400     p = pkt.data;
401     ff_amf_write_string(&p, "deleteStream");
402     ff_amf_write_number(&p, ++rt->nb_invokes);
403     ff_amf_write_null(&p);
404     ff_amf_write_number(&p, rt->main_channel_id);
405
406     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
407                                rt->prev_pkt[1]);
408     ff_rtmp_packet_destroy(&pkt);
409
410     return ret;
411 }
412
413 /**
414  * Generate client buffer time and send it to the server.
415  */
416 static int gen_buffer_time(URLContext *s, RTMPContext *rt)
417 {
418     RTMPPacket pkt;
419     uint8_t *p;
420     int ret;
421
422     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
423                                      1, 10)) < 0)
424         return ret;
425
426     p = pkt.data;
427     bytestream_put_be16(&p, 3);
428     bytestream_put_be32(&p, rt->main_channel_id);
429     bytestream_put_be32(&p, rt->client_buffer_time);
430
431     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
432                                rt->prev_pkt[1]);
433     ff_rtmp_packet_destroy(&pkt);
434
435     return ret;
436 }
437
438 /**
439  * Generate 'play' call and send it to the server, then ping the server
440  * to start actual playing.
441  */
442 static int gen_play(URLContext *s, RTMPContext *rt)
443 {
444     RTMPPacket pkt;
445     uint8_t *p;
446     int ret;
447
448     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
449
450     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
451                                      0, 29 + strlen(rt->playpath))) < 0)
452         return ret;
453
454     pkt.extra = rt->main_channel_id;
455
456     p = pkt.data;
457     ff_amf_write_string(&p, "play");
458     ff_amf_write_number(&p, ++rt->nb_invokes);
459     ff_amf_write_null(&p);
460     ff_amf_write_string(&p, rt->playpath);
461     ff_amf_write_number(&p, rt->live);
462
463     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
464                                rt->prev_pkt[1]);
465     ff_rtmp_packet_destroy(&pkt);
466
467     return ret;
468 }
469
470 /**
471  * Generate 'publish' call and send it to the server.
472  */
473 static int gen_publish(URLContext *s, RTMPContext *rt)
474 {
475     RTMPPacket pkt;
476     uint8_t *p;
477     int ret;
478
479     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
480
481     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
482                                      0, 30 + strlen(rt->playpath))) < 0)
483         return ret;
484
485     pkt.extra = rt->main_channel_id;
486
487     p = pkt.data;
488     ff_amf_write_string(&p, "publish");
489     ff_amf_write_number(&p, ++rt->nb_invokes);
490     ff_amf_write_null(&p);
491     ff_amf_write_string(&p, rt->playpath);
492     ff_amf_write_string(&p, "live");
493
494     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
495                                rt->prev_pkt[1]);
496     ff_rtmp_packet_destroy(&pkt);
497
498     return ret;
499 }
500
501 /**
502  * Generate ping reply and send it to the server.
503  */
504 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
505 {
506     RTMPPacket pkt;
507     uint8_t *p;
508     int ret;
509
510     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
511                                      ppkt->timestamp + 1, 6)) < 0)
512         return ret;
513
514     p = pkt.data;
515     bytestream_put_be16(&p, 7);
516     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
517     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
518                                rt->prev_pkt[1]);
519     ff_rtmp_packet_destroy(&pkt);
520
521     return ret;
522 }
523
524 /**
525  * Generate server bandwidth message and send it to the server.
526  */
527 static int gen_server_bw(URLContext *s, RTMPContext *rt)
528 {
529     RTMPPacket pkt;
530     uint8_t *p;
531     int ret;
532
533     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
534                                      0, 4)) < 0)
535         return ret;
536
537     p = pkt.data;
538     bytestream_put_be32(&p, rt->server_bw);
539     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
540                                rt->prev_pkt[1]);
541     ff_rtmp_packet_destroy(&pkt);
542
543     return ret;
544 }
545
546 /**
547  * Generate check bandwidth message and send it to the server.
548  */
549 static int gen_check_bw(URLContext *s, RTMPContext *rt)
550 {
551     RTMPPacket pkt;
552     uint8_t *p;
553     int ret;
554
555     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
556                                      0, 21)) < 0)
557         return ret;
558
559     p = pkt.data;
560     ff_amf_write_string(&p, "_checkbw");
561     ff_amf_write_number(&p, ++rt->nb_invokes);
562     ff_amf_write_null(&p);
563
564     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
565                                rt->prev_pkt[1]);
566     ff_rtmp_packet_destroy(&pkt);
567
568     return ret;
569 }
570
571 /**
572  * Generate report on bytes read so far and send it to the server.
573  */
574 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
575 {
576     RTMPPacket pkt;
577     uint8_t *p;
578     int ret;
579
580     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
581                                      ts, 4)) < 0)
582         return ret;
583
584     p = pkt.data;
585     bytestream_put_be32(&p, rt->bytes_read);
586     ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size,
587                                rt->prev_pkt[1]);
588     ff_rtmp_packet_destroy(&pkt);
589
590     return ret;
591 }
592
593 //TODO: Move HMAC code somewhere. Eventually.
594 #define HMAC_IPAD_VAL 0x36
595 #define HMAC_OPAD_VAL 0x5C
596
597 /**
598  * Calculate HMAC-SHA2 digest for RTMP handshake packets.
599  *
600  * @param src    input buffer
601  * @param len    input buffer length (should be 1536)
602  * @param gap    offset in buffer where 32 bytes should not be taken into account
603  *               when calculating digest (since it will be used to store that digest)
604  * @param key    digest key
605  * @param keylen digest key length
606  * @param dst    buffer where calculated digest will be stored (32 bytes)
607  */
608 static int rtmp_calc_digest(const uint8_t *src, int len, int gap,
609                             const uint8_t *key, int keylen, uint8_t *dst)
610 {
611     struct AVSHA *sha;
612     uint8_t hmac_buf[64+32] = {0};
613     int i;
614
615     sha = av_mallocz(av_sha_size);
616     if (!sha)
617         return AVERROR(ENOMEM);
618
619     if (keylen < 64) {
620         memcpy(hmac_buf, key, keylen);
621     } else {
622         av_sha_init(sha, 256);
623         av_sha_update(sha,key, keylen);
624         av_sha_final(sha, hmac_buf);
625     }
626     for (i = 0; i < 64; i++)
627         hmac_buf[i] ^= HMAC_IPAD_VAL;
628
629     av_sha_init(sha, 256);
630     av_sha_update(sha, hmac_buf, 64);
631     if (gap <= 0) {
632         av_sha_update(sha, src, len);
633     } else { //skip 32 bytes used for storing digest
634         av_sha_update(sha, src, gap);
635         av_sha_update(sha, src + gap + 32, len - gap - 32);
636     }
637     av_sha_final(sha, hmac_buf + 64);
638
639     for (i = 0; i < 64; i++)
640         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
641     av_sha_init(sha, 256);
642     av_sha_update(sha, hmac_buf, 64+32);
643     av_sha_final(sha, dst);
644
645     av_free(sha);
646
647     return 0;
648 }
649
650 /**
651  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
652  * will be stored) into that packet.
653  *
654  * @param buf handshake data (1536 bytes)
655  * @return offset to the digest inside input data
656  */
657 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
658 {
659     int i, digest_pos = 0;
660     int ret;
661
662     for (i = 8; i < 12; i++)
663         digest_pos += buf[i];
664     digest_pos = (digest_pos % 728) + 12;
665
666     ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
667                            rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
668                            buf + digest_pos);
669     if (ret < 0)
670         return ret;
671
672     return digest_pos;
673 }
674
675 /**
676  * Verify that the received server response has the expected digest value.
677  *
678  * @param buf handshake data received from the server (1536 bytes)
679  * @param off position to search digest offset from
680  * @return 0 if digest is valid, digest position otherwise
681  */
682 static int rtmp_validate_digest(uint8_t *buf, int off)
683 {
684     int i, digest_pos = 0;
685     uint8_t digest[32];
686     int ret;
687
688     for (i = 0; i < 4; i++)
689         digest_pos += buf[i + off];
690     digest_pos = (digest_pos % 728) + off + 4;
691
692     ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
693                            rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
694                            digest);
695     if (ret < 0)
696         return ret;
697
698     if (!memcmp(digest, buf + digest_pos, 32))
699         return digest_pos;
700     return 0;
701 }
702
703 /**
704  * Perform handshake with the server by means of exchanging pseudorandom data
705  * signed with HMAC-SHA2 digest.
706  *
707  * @return 0 if handshake succeeds, negative value otherwise
708  */
709 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
710 {
711     AVLFG rnd;
712     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
713         3,                // unencrypted data
714         0, 0, 0, 0,       // client uptime
715         RTMP_CLIENT_VER1,
716         RTMP_CLIENT_VER2,
717         RTMP_CLIENT_VER3,
718         RTMP_CLIENT_VER4,
719     };
720     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
721     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
722     int i;
723     int server_pos, client_pos;
724     uint8_t digest[32];
725     int ret;
726
727     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
728
729     av_lfg_init(&rnd, 0xDEADC0DE);
730     // generate handshake packet - 1536 bytes of pseudorandom data
731     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
732         tosend[i] = av_lfg_get(&rnd) >> 24;
733     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
734     if (client_pos < 0)
735         return client_pos;
736
737     if ((ret = ffurl_write(rt->stream, tosend,
738                            RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
739         av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
740         return ret;
741     }
742
743     if ((ret = ffurl_read_complete(rt->stream, serverdata,
744                                    RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
745         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
746         return ret;
747     }
748
749     if ((ret = ffurl_read_complete(rt->stream, clientdata,
750                                    RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
751         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
752         return ret;
753     }
754
755     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
756            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
757
758     if (rt->is_input && serverdata[5] >= 3) {
759         server_pos = rtmp_validate_digest(serverdata + 1, 772);
760         if (server_pos < 0)
761             return server_pos;
762
763         if (!server_pos) {
764             server_pos = rtmp_validate_digest(serverdata + 1, 8);
765             if (server_pos < 0)
766                 return server_pos;
767
768             if (!server_pos) {
769                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
770                 return AVERROR(EIO);
771             }
772         }
773
774         ret = rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key,
775                                sizeof(rtmp_server_key), digest);
776         if (ret < 0)
777             return ret;
778
779         ret = rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
780                                digest, 32, digest);
781         if (ret < 0)
782             return ret;
783
784         if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
785             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
786             return AVERROR(EIO);
787         }
788
789         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
790             tosend[i] = av_lfg_get(&rnd) >> 24;
791         ret = rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
792                                rtmp_player_key, sizeof(rtmp_player_key),
793                                digest);
794         if (ret < 0)
795             return ret;
796
797         ret = rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
798                                digest, 32,
799                                tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
800         if (ret < 0)
801             return ret;
802
803         // write reply back to the server
804         if ((ret = ffurl_write(rt->stream, tosend,
805                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
806             return ret;
807     } else {
808         if ((ret = ffurl_write(rt->stream, serverdata + 1,
809                                RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
810             return ret;
811     }
812
813     return 0;
814 }
815
816 /**
817  * Parse received packet and possibly perform some action depending on
818  * the packet contents.
819  * @return 0 for no errors, negative values for serious errors which prevent
820  *         further communications, positive values for uncritical errors
821  */
822 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
823 {
824     int i, t;
825     const uint8_t *data_end = pkt->data + pkt->data_size;
826     int ret;
827
828 #ifdef DEBUG
829     ff_rtmp_packet_dump(s, pkt);
830 #endif
831
832     switch (pkt->type) {
833     case RTMP_PT_CHUNK_SIZE:
834         if (pkt->data_size != 4) {
835             av_log(s, AV_LOG_ERROR,
836                    "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
837             return -1;
838         }
839         if (!rt->is_input)
840             if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size,
841                                             rt->prev_pkt[1])) < 0)
842                 return ret;
843         rt->chunk_size = AV_RB32(pkt->data);
844         if (rt->chunk_size <= 0) {
845             av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
846             return -1;
847         }
848         av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
849         break;
850     case RTMP_PT_PING:
851         t = AV_RB16(pkt->data);
852         if (t == 6)
853             if ((ret = gen_pong(s, rt, pkt)) < 0)
854                 return ret;
855         break;
856     case RTMP_PT_CLIENT_BW:
857         if (pkt->data_size < 4) {
858             av_log(s, AV_LOG_ERROR,
859                    "Client bandwidth report packet is less than 4 bytes long (%d)\n",
860                    pkt->data_size);
861             return -1;
862         }
863         av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
864         rt->client_report_size = AV_RB32(pkt->data) >> 1;
865         break;
866     case RTMP_PT_SERVER_BW:
867         rt->server_bw = AV_RB32(pkt->data);
868         if (rt->server_bw <= 0) {
869             av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n", rt->server_bw);
870             return AVERROR(EINVAL);
871         }
872         av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
873         break;
874     case RTMP_PT_INVOKE:
875         //TODO: check for the messages sent for wrong state?
876         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
877             uint8_t tmpstr[256];
878
879             if (!ff_amf_get_field_value(pkt->data + 9, data_end,
880                                         "description", tmpstr, sizeof(tmpstr)))
881                 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
882             return -1;
883         } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
884             switch (rt->state) {
885             case STATE_HANDSHAKED:
886                 if (!rt->is_input) {
887                     if ((ret = gen_release_stream(s, rt)) < 0)
888                         return ret;
889                     if ((ret = gen_fcpublish_stream(s, rt)) < 0)
890                         return ret;
891                     rt->state = STATE_RELEASING;
892                 } else {
893                     if ((ret = gen_server_bw(s, rt)) < 0)
894                         return ret;
895                     rt->state = STATE_CONNECTING;
896                 }
897                 if ((ret = gen_create_stream(s, rt)) < 0)
898                     return ret;
899                 break;
900             case STATE_FCPUBLISH:
901                 rt->state = STATE_CONNECTING;
902                 break;
903             case STATE_RELEASING:
904                 rt->state = STATE_FCPUBLISH;
905                 /* hack for Wowza Media Server, it does not send result for
906                  * releaseStream and FCPublish calls */
907                 if (!pkt->data[10]) {
908                     int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
909                     if (pkt_id == rt->create_stream_invoke)
910                         rt->state = STATE_CONNECTING;
911                 }
912                 if (rt->state != STATE_CONNECTING)
913                     break;
914             case STATE_CONNECTING:
915                 //extract a number from the result
916                 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
917                     av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
918                 } else {
919                     rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
920                 }
921                 if (rt->is_input) {
922                     if ((ret = gen_play(s, rt)) < 0)
923                         return ret;
924                     if ((ret = gen_buffer_time(s, rt)) < 0)
925                         return ret;
926                 } else {
927                     if ((ret = gen_publish(s, rt)) < 0)
928                         return ret;
929                 }
930                 rt->state = STATE_READY;
931                 break;
932             }
933         } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
934             const uint8_t* ptr = pkt->data + 11;
935             uint8_t tmpstr[256];
936
937             for (i = 0; i < 2; i++) {
938                 t = ff_amf_tag_size(ptr, data_end);
939                 if (t < 0)
940                     return 1;
941                 ptr += t;
942             }
943             t = ff_amf_get_field_value(ptr, data_end,
944                                        "level", tmpstr, sizeof(tmpstr));
945             if (!t && !strcmp(tmpstr, "error")) {
946                 if (!ff_amf_get_field_value(ptr, data_end,
947                                             "description", tmpstr, sizeof(tmpstr)))
948                     av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
949                 return -1;
950             }
951             t = ff_amf_get_field_value(ptr, data_end,
952                                        "code", tmpstr, sizeof(tmpstr));
953             if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
954             if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
955             if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
956             if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
957         } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
958             if ((ret = gen_check_bw(s, rt)) < 0)
959                 return ret;
960         }
961         break;
962     case RTMP_PT_VIDEO:
963     case RTMP_PT_AUDIO:
964         /* Audio and Video packets are parsed in get_packet() */
965         break;
966     default:
967         av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
968         break;
969     }
970     return 0;
971 }
972
973 /**
974  * Interact with the server by receiving and sending RTMP packets until
975  * there is some significant data (media data or expected status notification).
976  *
977  * @param s          reading context
978  * @param for_header non-zero value tells function to work until it
979  * gets notification from the server that playing has been started,
980  * otherwise function will work until some media data is received (or
981  * an error happens)
982  * @return 0 for successful operation, negative value in case of error
983  */
984 static int get_packet(URLContext *s, int for_header)
985 {
986     RTMPContext *rt = s->priv_data;
987     int ret;
988     uint8_t *p;
989     const uint8_t *next;
990     uint32_t data_size;
991     uint32_t ts, cts, pts=0;
992
993     if (rt->state == STATE_STOPPED)
994         return AVERROR_EOF;
995
996     for (;;) {
997         RTMPPacket rpkt = { 0 };
998         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
999                                        rt->chunk_size, rt->prev_pkt[0])) <= 0) {
1000             if (ret == 0) {
1001                 return AVERROR(EAGAIN);
1002             } else {
1003                 return AVERROR(EIO);
1004             }
1005         }
1006         rt->bytes_read += ret;
1007         if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
1008             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
1009             if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
1010                 return ret;
1011             rt->last_bytes_read = rt->bytes_read;
1012         }
1013
1014         ret = rtmp_parse_result(s, rt, &rpkt);
1015         if (ret < 0) {//serious error in current packet
1016             ff_rtmp_packet_destroy(&rpkt);
1017             return ret;
1018         }
1019         if (rt->state == STATE_STOPPED) {
1020             ff_rtmp_packet_destroy(&rpkt);
1021             return AVERROR_EOF;
1022         }
1023         if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
1024             ff_rtmp_packet_destroy(&rpkt);
1025             return 0;
1026         }
1027         if (!rpkt.data_size || !rt->is_input) {
1028             ff_rtmp_packet_destroy(&rpkt);
1029             continue;
1030         }
1031         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
1032            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
1033             ts = rpkt.timestamp;
1034
1035             // generate packet header and put data into buffer for FLV demuxer
1036             rt->flv_off  = 0;
1037             rt->flv_size = rpkt.data_size + 15;
1038             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
1039             bytestream_put_byte(&p, rpkt.type);
1040             bytestream_put_be24(&p, rpkt.data_size);
1041             bytestream_put_be24(&p, ts);
1042             bytestream_put_byte(&p, ts >> 24);
1043             bytestream_put_be24(&p, 0);
1044             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
1045             bytestream_put_be32(&p, 0);
1046             ff_rtmp_packet_destroy(&rpkt);
1047             return 0;
1048         } else if (rpkt.type == RTMP_PT_METADATA) {
1049             // we got raw FLV data, make it available for FLV demuxer
1050             rt->flv_off  = 0;
1051             rt->flv_size = rpkt.data_size;
1052             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1053             /* rewrite timestamps */
1054             next = rpkt.data;
1055             ts = rpkt.timestamp;
1056             while (next - rpkt.data < rpkt.data_size - 11) {
1057                 next++;
1058                 data_size = bytestream_get_be24(&next);
1059                 p=next;
1060                 cts = bytestream_get_be24(&next);
1061                 cts |= bytestream_get_byte(&next) << 24;
1062                 if (pts==0)
1063                     pts=cts;
1064                 ts += cts - pts;
1065                 pts = cts;
1066                 bytestream_put_be24(&p, ts);
1067                 bytestream_put_byte(&p, ts >> 24);
1068                 next += data_size + 3 + 4;
1069             }
1070             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
1071             ff_rtmp_packet_destroy(&rpkt);
1072             return 0;
1073         }
1074         ff_rtmp_packet_destroy(&rpkt);
1075     }
1076 }
1077
1078 static int rtmp_close(URLContext *h)
1079 {
1080     RTMPContext *rt = h->priv_data;
1081     int ret = 0;
1082
1083     if (!rt->is_input) {
1084         rt->flv_data = NULL;
1085         if (rt->out_pkt.data_size)
1086             ff_rtmp_packet_destroy(&rt->out_pkt);
1087         if (rt->state > STATE_FCPUBLISH)
1088             ret = gen_fcunpublish_stream(h, rt);
1089     }
1090     if (rt->state > STATE_HANDSHAKED)
1091         ret = gen_delete_stream(h, rt);
1092
1093     av_freep(&rt->flv_data);
1094     ffurl_close(rt->stream);
1095     return ret;
1096 }
1097
1098 /**
1099  * Open RTMP connection and verify that the stream can be played.
1100  *
1101  * URL syntax: rtmp://server[:port][/app][/playpath]
1102  *             where 'app' is first one or two directories in the path
1103  *             (e.g. /ondemand/, /flash/live/, etc.)
1104  *             and 'playpath' is a file name (the rest of the path,
1105  *             may be prefixed with "mp4:")
1106  */
1107 static int rtmp_open(URLContext *s, const char *uri, int flags)
1108 {
1109     RTMPContext *rt = s->priv_data;
1110     char proto[8], hostname[256], path[1024], *fname;
1111     char *old_app;
1112     uint8_t buf[2048];
1113     int port;
1114     AVDictionary *opts = NULL;
1115     int ret;
1116
1117     rt->is_input = !(flags & AVIO_FLAG_WRITE);
1118
1119     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
1120                  path, sizeof(path), s->filename);
1121
1122     if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
1123         if (!strcmp(proto, "rtmpts"))
1124             av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
1125
1126         /* open the http tunneling connection */
1127         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
1128     } else if (!strcmp(proto, "rtmps")) {
1129         /* open the tls connection */
1130         if (port < 0)
1131             port = RTMPS_DEFAULT_PORT;
1132         ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
1133     } else {
1134         /* open the tcp connection */
1135         if (port < 0)
1136             port = RTMP_DEFAULT_PORT;
1137         ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
1138     }
1139
1140     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
1141                           &s->interrupt_callback, &opts)) < 0) {
1142         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
1143         goto fail;
1144     }
1145
1146     rt->state = STATE_START;
1147     if ((ret = rtmp_handshake(s, rt)) < 0)
1148         goto fail;
1149
1150     rt->chunk_size = 128;
1151     rt->state = STATE_HANDSHAKED;
1152
1153     // Keep the application name when it has been defined by the user.
1154     old_app = rt->app;
1155
1156     rt->app = av_malloc(APP_MAX_LENGTH);
1157     if (!rt->app) {
1158         ret = AVERROR(ENOMEM);
1159         goto fail;
1160     }
1161
1162     //extract "app" part from path
1163     if (!strncmp(path, "/ondemand/", 10)) {
1164         fname = path + 10;
1165         memcpy(rt->app, "ondemand", 9);
1166     } else {
1167         char *next = *path ? path + 1 : path;
1168         char *p = strchr(next, '/');
1169         if (!p) {
1170             fname = next;
1171             rt->app[0] = '\0';
1172         } else {
1173             // make sure we do not mismatch a playpath for an application instance
1174             char *c = strchr(p + 1, ':');
1175             fname = strchr(p + 1, '/');
1176             if (!fname || (c && c < fname)) {
1177                 fname = p + 1;
1178                 av_strlcpy(rt->app, path + 1, p - path);
1179             } else {
1180                 fname++;
1181                 av_strlcpy(rt->app, path + 1, fname - path - 1);
1182             }
1183         }
1184     }
1185
1186     if (old_app) {
1187         // The name of application has been defined by the user, override it.
1188         av_free(rt->app);
1189         rt->app = old_app;
1190     }
1191
1192     if (!rt->playpath) {
1193         int len = strlen(fname);
1194
1195         rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
1196         if (!rt->playpath) {
1197             ret = AVERROR(ENOMEM);
1198             goto fail;
1199         }
1200
1201         if (!strchr(fname, ':') && len >= 4 &&
1202             (!strcmp(fname + len - 4, ".f4v") ||
1203              !strcmp(fname + len - 4, ".mp4"))) {
1204             memcpy(rt->playpath, "mp4:", 5);
1205         } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
1206             fname[len - 4] = '\0';
1207         } else {
1208             rt->playpath[0] = 0;
1209         }
1210         strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
1211     }
1212
1213     if (!rt->tcurl) {
1214         rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
1215         if (!rt->tcurl) {
1216             ret = AVERROR(ENOMEM);
1217             goto fail;
1218         }
1219         ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
1220                     port, "/%s", rt->app);
1221     }
1222
1223     if (!rt->flashver) {
1224         rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
1225         if (!rt->flashver) {
1226             ret = AVERROR(ENOMEM);
1227             goto fail;
1228         }
1229         if (rt->is_input) {
1230             snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
1231                     RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
1232                     RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
1233         } else {
1234             snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
1235                     "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
1236         }
1237     }
1238
1239     rt->client_report_size = 1048576;
1240     rt->bytes_read = 0;
1241     rt->last_bytes_read = 0;
1242     rt->server_bw = 2500000;
1243
1244     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
1245            proto, path, rt->app, rt->playpath);
1246     if ((ret = gen_connect(s, rt)) < 0)
1247         goto fail;
1248
1249     do {
1250         ret = get_packet(s, 1);
1251     } while (ret == EAGAIN);
1252     if (ret < 0)
1253         goto fail;
1254
1255     if (rt->is_input) {
1256         // generate FLV header for demuxer
1257         rt->flv_size = 13;
1258         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
1259         rt->flv_off  = 0;
1260         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
1261     } else {
1262         rt->flv_size = 0;
1263         rt->flv_data = NULL;
1264         rt->flv_off  = 0;
1265         rt->skip_bytes = 13;
1266     }
1267
1268     s->max_packet_size = rt->stream->max_packet_size;
1269     s->is_streamed     = 1;
1270     return 0;
1271
1272 fail:
1273     av_dict_free(&opts);
1274     rtmp_close(s);
1275     return ret;
1276 }
1277
1278 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
1279 {
1280     RTMPContext *rt = s->priv_data;
1281     int orig_size = size;
1282     int ret;
1283
1284     while (size > 0) {
1285         int data_left = rt->flv_size - rt->flv_off;
1286
1287         if (data_left >= size) {
1288             memcpy(buf, rt->flv_data + rt->flv_off, size);
1289             rt->flv_off += size;
1290             return orig_size;
1291         }
1292         if (data_left > 0) {
1293             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
1294             buf  += data_left;
1295             size -= data_left;
1296             rt->flv_off = rt->flv_size;
1297             return data_left;
1298         }
1299         if ((ret = get_packet(s, 0)) < 0)
1300            return ret;
1301     }
1302     return orig_size;
1303 }
1304
1305 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
1306 {
1307     RTMPContext *rt = s->priv_data;
1308     int size_temp = size;
1309     int pktsize, pkttype;
1310     uint32_t ts;
1311     const uint8_t *buf_temp = buf;
1312     uint8_t c;
1313     int ret;
1314
1315     do {
1316         if (rt->skip_bytes) {
1317             int skip = FFMIN(rt->skip_bytes, size_temp);
1318             buf_temp       += skip;
1319             size_temp      -= skip;
1320             rt->skip_bytes -= skip;
1321             continue;
1322         }
1323
1324         if (rt->flv_header_bytes < 11) {
1325             const uint8_t *header = rt->flv_header;
1326             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
1327             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
1328             rt->flv_header_bytes += copy;
1329             size_temp            -= copy;
1330             if (rt->flv_header_bytes < 11)
1331                 break;
1332
1333             pkttype = bytestream_get_byte(&header);
1334             pktsize = bytestream_get_be24(&header);
1335             ts = bytestream_get_be24(&header);
1336             ts |= bytestream_get_byte(&header) << 24;
1337             bytestream_get_be24(&header);
1338             rt->flv_size = pktsize;
1339
1340             //force 12bytes header
1341             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1342                 pkttype == RTMP_PT_NOTIFY) {
1343                 if (pkttype == RTMP_PT_NOTIFY)
1344                     pktsize += 16;
1345                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1346             }
1347
1348             //this can be a big packet, it's better to send it right here
1349             if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
1350                                              pkttype, ts, pktsize)) < 0)
1351                 return ret;
1352
1353             rt->out_pkt.extra = rt->main_channel_id;
1354             rt->flv_data = rt->out_pkt.data;
1355
1356             if (pkttype == RTMP_PT_NOTIFY)
1357                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1358         }
1359
1360         if (rt->flv_size - rt->flv_off > size_temp) {
1361             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1362             rt->flv_off += size_temp;
1363             size_temp = 0;
1364         } else {
1365             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1366             size_temp   -= rt->flv_size - rt->flv_off;
1367             rt->flv_off += rt->flv_size - rt->flv_off;
1368         }
1369
1370         if (rt->flv_off == rt->flv_size) {
1371             rt->skip_bytes = 4;
1372
1373             if ((ret = ff_rtmp_packet_write(rt->stream, &rt->out_pkt,
1374                                             rt->chunk_size, rt->prev_pkt[1])) < 0)
1375                 return ret;
1376             ff_rtmp_packet_destroy(&rt->out_pkt);
1377             rt->flv_size = 0;
1378             rt->flv_off = 0;
1379             rt->flv_header_bytes = 0;
1380             rt->flv_nb_packets++;
1381         }
1382     } while (buf_temp - buf < size);
1383
1384     if (rt->flv_nb_packets < rt->flush_interval)
1385         return size;
1386     rt->flv_nb_packets = 0;
1387
1388     /* set stream into nonblocking mode */
1389     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
1390
1391     /* try to read one byte from the stream */
1392     ret = ffurl_read(rt->stream, &c, 1);
1393
1394     /* switch the stream back into blocking mode */
1395     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
1396
1397     if (ret == AVERROR(EAGAIN)) {
1398         /* no incoming data to handle */
1399         return size;
1400     } else if (ret < 0) {
1401         return ret;
1402     } else if (ret == 1) {
1403         RTMPPacket rpkt = { 0 };
1404
1405         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
1406                                                 rt->chunk_size,
1407                                                 rt->prev_pkt[0], c)) <= 0)
1408              return ret;
1409
1410         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
1411             return ret;
1412
1413         ff_rtmp_packet_destroy(&rpkt);
1414     }
1415
1416     return size;
1417 }
1418
1419 #define OFFSET(x) offsetof(RTMPContext, x)
1420 #define DEC AV_OPT_FLAG_DECODING_PARAM
1421 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1422
1423 static const AVOption rtmp_options[] = {
1424     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1425     {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
1426     {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1427     {"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},
1428     {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
1429     {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
1430     {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
1431     {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
1432     {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
1433     {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1434     {"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},
1435     {"rtmp_tcurl", "URL of the target stream. Defaults to rtmp://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1436     { NULL },
1437 };
1438
1439 static const AVClass rtmp_class = {
1440     .class_name = "rtmp",
1441     .item_name  = av_default_item_name,
1442     .option     = rtmp_options,
1443     .version    = LIBAVUTIL_VERSION_INT,
1444 };
1445
1446 URLProtocol ff_rtmp_protocol = {
1447     .name           = "rtmp",
1448     .url_open       = rtmp_open,
1449     .url_read       = rtmp_read,
1450     .url_write      = rtmp_write,
1451     .url_close      = rtmp_close,
1452     .priv_data_size = sizeof(RTMPContext),
1453     .flags          = URL_PROTOCOL_FLAG_NETWORK,
1454     .priv_data_class= &rtmp_class,
1455 };
1456
1457 static const AVClass rtmps_class = {
1458     .class_name = "rtmps",
1459     .item_name  = av_default_item_name,
1460     .option     = rtmp_options,
1461     .version    = LIBAVUTIL_VERSION_INT,
1462 };
1463
1464 URLProtocol ff_rtmps_protocol = {
1465     .name            = "rtmps",
1466     .url_open        = rtmp_open,
1467     .url_read        = rtmp_read,
1468     .url_write       = rtmp_write,
1469     .url_close       = rtmp_close,
1470     .priv_data_size  = sizeof(RTMPContext),
1471     .flags           = URL_PROTOCOL_FLAG_NETWORK,
1472     .priv_data_class = &rtmps_class,
1473 };
1474
1475 static const AVClass rtmpt_class = {
1476     .class_name = "rtmpt",
1477     .item_name  = av_default_item_name,
1478     .option     = rtmp_options,
1479     .version    = LIBAVUTIL_VERSION_INT,
1480 };
1481
1482 URLProtocol ff_rtmpt_protocol = {
1483     .name            = "rtmpt",
1484     .url_open        = rtmp_open,
1485     .url_read        = rtmp_read,
1486     .url_write       = rtmp_write,
1487     .url_close       = rtmp_close,
1488     .priv_data_size  = sizeof(RTMPContext),
1489     .flags           = URL_PROTOCOL_FLAG_NETWORK,
1490     .priv_data_class = &rtmpt_class,
1491 };
1492
1493 static const AVClass rtmpts_class = {
1494     .class_name = "rtmpts",
1495     .item_name  = av_default_item_name,
1496     .option     = rtmp_options,
1497     .version    = LIBAVUTIL_VERSION_INT,
1498 };
1499
1500 URLProtocol ff_rtmpts_protocol = {
1501     .name            = "rtmpts",
1502     .url_open        = rtmp_open,
1503     .url_read        = rtmp_read,
1504     .url_write       = rtmp_write,
1505     .url_close       = rtmp_close,
1506     .priv_data_size  = sizeof(RTMPContext),
1507     .flags           = URL_PROTOCOL_FLAG_NETWORK,
1508     .priv_data_class = &rtmpts_class,
1509 };