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