]> git.sesse.net Git - ffmpeg/blob - libavformat/rtmpproto.c
rtmp: Support 'rtmp_app', an option which overrides the name of application
[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 "rtmppkt.h"
41 #include "url.h"
42
43 //#define DEBUG
44
45 #define APP_MAX_LENGTH 128
46
47 /** RTMP protocol handler state */
48 typedef enum {
49     STATE_START,      ///< client has not done anything yet
50     STATE_HANDSHAKED, ///< client has performed handshake
51     STATE_RELEASING,  ///< client releasing stream before publish it (for output)
52     STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
53     STATE_CONNECTING, ///< client connected to server successfully
54     STATE_READY,      ///< client has sent all needed commands and waits for server reply
55     STATE_PLAYING,    ///< client has started receiving multimedia data from server
56     STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
57     STATE_STOPPED,    ///< the broadcast has been stopped
58 } ClientState;
59
60 /** protocol handler context */
61 typedef struct RTMPContext {
62     const AVClass *class;
63     URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
64     RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
65     int           chunk_size;                 ///< size of the chunks RTMP packets are divided into
66     int           is_input;                   ///< input/output flag
67     char          playpath[256];              ///< path to filename to play (with possible "mp4:" prefix)
68     char          *app;                       ///< name of application
69     ClientState   state;                      ///< current state
70     int           main_channel_id;            ///< an additional channel ID which is used for some invocations
71     uint8_t*      flv_data;                   ///< buffer with data for demuxer
72     int           flv_size;                   ///< current buffer size
73     int           flv_off;                    ///< number of bytes read from current buffer
74     RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
75     uint32_t      client_report_size;         ///< number of bytes after which client should report to server
76     uint32_t      bytes_read;                 ///< number of bytes read from server
77     uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
78     int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
79     uint8_t       flv_header[11];             ///< partial incoming flv packet header
80     int           flv_header_bytes;           ///< number of initialized bytes in flv_header
81     int           nb_invokes;                 ///< keeps track of invoke messages
82     int           create_stream_invoke;       ///< invoke id for the create stream command
83 } RTMPContext;
84
85 #define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
86 /** Client key used for digest signing */
87 static const uint8_t rtmp_player_key[] = {
88     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
89     'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
90
91     0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
92     0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
93     0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
94 };
95
96 #define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
97 /** Key used for RTMP server digest signing */
98 static const uint8_t rtmp_server_key[] = {
99     'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
100     'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
101     'S', 'e', 'r', 'v', '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 /**
109  * Generate 'connect' call and send it to the server.
110  */
111 static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto,
112                         const char *host, int port)
113 {
114     RTMPPacket pkt;
115     uint8_t ver[64], *p;
116     char tcurl[512];
117
118     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
119     p = pkt.data;
120
121     ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
122     ff_amf_write_string(&p, "connect");
123     ff_amf_write_number(&p, ++rt->nb_invokes);
124     ff_amf_write_object_start(&p);
125     ff_amf_write_field_name(&p, "app");
126     ff_amf_write_string(&p, rt->app);
127
128     if (rt->is_input) {
129         snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
130                  RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
131     } else {
132         snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
133         ff_amf_write_field_name(&p, "type");
134         ff_amf_write_string(&p, "nonprivate");
135     }
136     ff_amf_write_field_name(&p, "flashVer");
137     ff_amf_write_string(&p, ver);
138     ff_amf_write_field_name(&p, "tcUrl");
139     ff_amf_write_string(&p, tcurl);
140     if (rt->is_input) {
141         ff_amf_write_field_name(&p, "fpad");
142         ff_amf_write_bool(&p, 0);
143         ff_amf_write_field_name(&p, "capabilities");
144         ff_amf_write_number(&p, 15.0);
145
146         /* Tell the server we support all the audio codecs except
147          * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
148          * which are unused in the RTMP protocol implementation. */
149         ff_amf_write_field_name(&p, "audioCodecs");
150         ff_amf_write_number(&p, 4071.0);
151         ff_amf_write_field_name(&p, "videoCodecs");
152         ff_amf_write_number(&p, 252.0);
153         ff_amf_write_field_name(&p, "videoFunction");
154         ff_amf_write_number(&p, 1.0);
155     }
156     ff_amf_write_object_end(&p);
157
158     pkt.data_size = p - pkt.data;
159
160     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
161     ff_rtmp_packet_destroy(&pkt);
162 }
163
164 /**
165  * Generate 'releaseStream' call and send it to the server. It should make
166  * the server release some channel for media streams.
167  */
168 static void gen_release_stream(URLContext *s, RTMPContext *rt)
169 {
170     RTMPPacket pkt;
171     uint8_t *p;
172
173     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
174                           29 + strlen(rt->playpath));
175
176     av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
177     p = pkt.data;
178     ff_amf_write_string(&p, "releaseStream");
179     ff_amf_write_number(&p, ++rt->nb_invokes);
180     ff_amf_write_null(&p);
181     ff_amf_write_string(&p, rt->playpath);
182
183     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
184     ff_rtmp_packet_destroy(&pkt);
185 }
186
187 /**
188  * Generate 'FCPublish' call and send it to the server. It should make
189  * the server preapare for receiving media streams.
190  */
191 static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
192 {
193     RTMPPacket pkt;
194     uint8_t *p;
195
196     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
197                           25 + strlen(rt->playpath));
198
199     av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
200     p = pkt.data;
201     ff_amf_write_string(&p, "FCPublish");
202     ff_amf_write_number(&p, ++rt->nb_invokes);
203     ff_amf_write_null(&p);
204     ff_amf_write_string(&p, rt->playpath);
205
206     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
207     ff_rtmp_packet_destroy(&pkt);
208 }
209
210 /**
211  * Generate 'FCUnpublish' call and send it to the server. It should make
212  * the server destroy stream.
213  */
214 static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
215 {
216     RTMPPacket pkt;
217     uint8_t *p;
218
219     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
220                           27 + strlen(rt->playpath));
221
222     av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
223     p = pkt.data;
224     ff_amf_write_string(&p, "FCUnpublish");
225     ff_amf_write_number(&p, ++rt->nb_invokes);
226     ff_amf_write_null(&p);
227     ff_amf_write_string(&p, rt->playpath);
228
229     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
230     ff_rtmp_packet_destroy(&pkt);
231 }
232
233 /**
234  * Generate 'createStream' call and send it to the server. It should make
235  * the server allocate some channel for media streams.
236  */
237 static void gen_create_stream(URLContext *s, RTMPContext *rt)
238 {
239     RTMPPacket pkt;
240     uint8_t *p;
241
242     av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
243     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
244
245     p = pkt.data;
246     ff_amf_write_string(&p, "createStream");
247     ff_amf_write_number(&p, ++rt->nb_invokes);
248     ff_amf_write_null(&p);
249     rt->create_stream_invoke = rt->nb_invokes;
250
251     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
252     ff_rtmp_packet_destroy(&pkt);
253 }
254
255
256 /**
257  * Generate 'deleteStream' call and send it to the server. It should make
258  * the server remove some channel for media streams.
259  */
260 static void gen_delete_stream(URLContext *s, RTMPContext *rt)
261 {
262     RTMPPacket pkt;
263     uint8_t *p;
264
265     av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
266     ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
267
268     p = pkt.data;
269     ff_amf_write_string(&p, "deleteStream");
270     ff_amf_write_number(&p, ++rt->nb_invokes);
271     ff_amf_write_null(&p);
272     ff_amf_write_number(&p, rt->main_channel_id);
273
274     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
275     ff_rtmp_packet_destroy(&pkt);
276 }
277
278 /**
279  * Generate 'play' call and send it to the server, then ping the server
280  * to start actual playing.
281  */
282 static void gen_play(URLContext *s, RTMPContext *rt)
283 {
284     RTMPPacket pkt;
285     uint8_t *p;
286
287     av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
288     ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
289                           20 + strlen(rt->playpath));
290     pkt.extra = rt->main_channel_id;
291
292     p = pkt.data;
293     ff_amf_write_string(&p, "play");
294     ff_amf_write_number(&p, ++rt->nb_invokes);
295     ff_amf_write_null(&p);
296     ff_amf_write_string(&p, rt->playpath);
297
298     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
299     ff_rtmp_packet_destroy(&pkt);
300
301     // set client buffer time disguised in ping packet
302     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
303
304     p = pkt.data;
305     bytestream_put_be16(&p, 3);
306     bytestream_put_be32(&p, 1);
307     bytestream_put_be32(&p, 256); //TODO: what is a good value here?
308
309     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
310     ff_rtmp_packet_destroy(&pkt);
311 }
312
313 /**
314  * Generate 'publish' call and send it to the server.
315  */
316 static void gen_publish(URLContext *s, RTMPContext *rt)
317 {
318     RTMPPacket pkt;
319     uint8_t *p;
320
321     av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
322     ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
323                           30 + strlen(rt->playpath));
324     pkt.extra = rt->main_channel_id;
325
326     p = pkt.data;
327     ff_amf_write_string(&p, "publish");
328     ff_amf_write_number(&p, ++rt->nb_invokes);
329     ff_amf_write_null(&p);
330     ff_amf_write_string(&p, rt->playpath);
331     ff_amf_write_string(&p, "live");
332
333     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
334     ff_rtmp_packet_destroy(&pkt);
335 }
336
337 /**
338  * Generate ping reply and send it to the server.
339  */
340 static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
341 {
342     RTMPPacket pkt;
343     uint8_t *p;
344
345     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
346     p = pkt.data;
347     bytestream_put_be16(&p, 7);
348     bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
349     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
350     ff_rtmp_packet_destroy(&pkt);
351 }
352
353 /**
354  * Generate server bandwidth message and send it to the server.
355  */
356 static void gen_server_bw(URLContext *s, RTMPContext *rt)
357 {
358     RTMPPacket pkt;
359     uint8_t *p;
360
361     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4);
362     p = pkt.data;
363     bytestream_put_be32(&p, 2500000);
364     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
365     ff_rtmp_packet_destroy(&pkt);
366 }
367
368 /**
369  * Generate report on bytes read so far and send it to the server.
370  */
371 static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
372 {
373     RTMPPacket pkt;
374     uint8_t *p;
375
376     ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
377     p = pkt.data;
378     bytestream_put_be32(&p, rt->bytes_read);
379     ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
380     ff_rtmp_packet_destroy(&pkt);
381 }
382
383 //TODO: Move HMAC code somewhere. Eventually.
384 #define HMAC_IPAD_VAL 0x36
385 #define HMAC_OPAD_VAL 0x5C
386
387 /**
388  * Calculate HMAC-SHA2 digest for RTMP handshake packets.
389  *
390  * @param src    input buffer
391  * @param len    input buffer length (should be 1536)
392  * @param gap    offset in buffer where 32 bytes should not be taken into account
393  *               when calculating digest (since it will be used to store that digest)
394  * @param key    digest key
395  * @param keylen digest key length
396  * @param dst    buffer where calculated digest will be stored (32 bytes)
397  */
398 static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
399                              const uint8_t *key, int keylen, uint8_t *dst)
400 {
401     struct AVSHA *sha;
402     uint8_t hmac_buf[64+32] = {0};
403     int i;
404
405     sha = av_mallocz(av_sha_size);
406
407     if (keylen < 64) {
408         memcpy(hmac_buf, key, keylen);
409     } else {
410         av_sha_init(sha, 256);
411         av_sha_update(sha,key, keylen);
412         av_sha_final(sha, hmac_buf);
413     }
414     for (i = 0; i < 64; i++)
415         hmac_buf[i] ^= HMAC_IPAD_VAL;
416
417     av_sha_init(sha, 256);
418     av_sha_update(sha, hmac_buf, 64);
419     if (gap <= 0) {
420         av_sha_update(sha, src, len);
421     } else { //skip 32 bytes used for storing digest
422         av_sha_update(sha, src, gap);
423         av_sha_update(sha, src + gap + 32, len - gap - 32);
424     }
425     av_sha_final(sha, hmac_buf + 64);
426
427     for (i = 0; i < 64; i++)
428         hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
429     av_sha_init(sha, 256);
430     av_sha_update(sha, hmac_buf, 64+32);
431     av_sha_final(sha, dst);
432
433     av_free(sha);
434 }
435
436 /**
437  * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
438  * will be stored) into that packet.
439  *
440  * @param buf handshake data (1536 bytes)
441  * @return offset to the digest inside input data
442  */
443 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
444 {
445     int i, digest_pos = 0;
446
447     for (i = 8; i < 12; i++)
448         digest_pos += buf[i];
449     digest_pos = (digest_pos % 728) + 12;
450
451     rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
452                      rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
453                      buf + digest_pos);
454     return digest_pos;
455 }
456
457 /**
458  * Verify that the received server response has the expected digest value.
459  *
460  * @param buf handshake data received from the server (1536 bytes)
461  * @param off position to search digest offset from
462  * @return 0 if digest is valid, digest position otherwise
463  */
464 static int rtmp_validate_digest(uint8_t *buf, int off)
465 {
466     int i, digest_pos = 0;
467     uint8_t digest[32];
468
469     for (i = 0; i < 4; i++)
470         digest_pos += buf[i + off];
471     digest_pos = (digest_pos % 728) + off + 4;
472
473     rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
474                      rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
475                      digest);
476     if (!memcmp(digest, buf + digest_pos, 32))
477         return digest_pos;
478     return 0;
479 }
480
481 /**
482  * Perform handshake with the server by means of exchanging pseudorandom data
483  * signed with HMAC-SHA2 digest.
484  *
485  * @return 0 if handshake succeeds, negative value otherwise
486  */
487 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
488 {
489     AVLFG rnd;
490     uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
491         3,                // unencrypted data
492         0, 0, 0, 0,       // client uptime
493         RTMP_CLIENT_VER1,
494         RTMP_CLIENT_VER2,
495         RTMP_CLIENT_VER3,
496         RTMP_CLIENT_VER4,
497     };
498     uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
499     uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
500     int i;
501     int server_pos, client_pos;
502     uint8_t digest[32];
503
504     av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
505
506     av_lfg_init(&rnd, 0xDEADC0DE);
507     // generate handshake packet - 1536 bytes of pseudorandom data
508     for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
509         tosend[i] = av_lfg_get(&rnd) >> 24;
510     client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
511
512     ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
513     i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
514     if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
515         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
516         return -1;
517     }
518     i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
519     if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
520         av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
521         return -1;
522     }
523
524     av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
525            serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
526
527     if (rt->is_input && serverdata[5] >= 3) {
528         server_pos = rtmp_validate_digest(serverdata + 1, 772);
529         if (!server_pos) {
530             server_pos = rtmp_validate_digest(serverdata + 1, 8);
531             if (!server_pos) {
532                 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
533                 return -1;
534             }
535         }
536
537         rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
538                          rtmp_server_key, sizeof(rtmp_server_key),
539                          digest);
540         rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
541                          digest, 32,
542                          digest);
543         if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
544             av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
545             return -1;
546         }
547
548         for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
549             tosend[i] = av_lfg_get(&rnd) >> 24;
550         rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
551                          rtmp_player_key, sizeof(rtmp_player_key),
552                          digest);
553         rtmp_calc_digest(tosend,  RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
554                          digest, 32,
555                          tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
556
557         // write reply back to the server
558         ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
559     } else {
560         ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
561     }
562
563     return 0;
564 }
565
566 /**
567  * Parse received packet and possibly perform some action depending on
568  * the packet contents.
569  * @return 0 for no errors, negative values for serious errors which prevent
570  *         further communications, positive values for uncritical errors
571  */
572 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
573 {
574     int i, t;
575     const uint8_t *data_end = pkt->data + pkt->data_size;
576
577 #ifdef DEBUG
578     ff_rtmp_packet_dump(s, pkt);
579 #endif
580
581     switch (pkt->type) {
582     case RTMP_PT_CHUNK_SIZE:
583         if (pkt->data_size != 4) {
584             av_log(s, AV_LOG_ERROR,
585                    "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
586             return -1;
587         }
588         if (!rt->is_input)
589             ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
590         rt->chunk_size = AV_RB32(pkt->data);
591         if (rt->chunk_size <= 0) {
592             av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
593             return -1;
594         }
595         av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
596         break;
597     case RTMP_PT_PING:
598         t = AV_RB16(pkt->data);
599         if (t == 6)
600             gen_pong(s, rt, pkt);
601         break;
602     case RTMP_PT_CLIENT_BW:
603         if (pkt->data_size < 4) {
604             av_log(s, AV_LOG_ERROR,
605                    "Client bandwidth report packet is less than 4 bytes long (%d)\n",
606                    pkt->data_size);
607             return -1;
608         }
609         av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
610         rt->client_report_size = AV_RB32(pkt->data) >> 1;
611         break;
612     case RTMP_PT_INVOKE:
613         //TODO: check for the messages sent for wrong state?
614         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
615             uint8_t tmpstr[256];
616
617             if (!ff_amf_get_field_value(pkt->data + 9, data_end,
618                                         "description", tmpstr, sizeof(tmpstr)))
619                 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
620             return -1;
621         } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
622             switch (rt->state) {
623             case STATE_HANDSHAKED:
624                 if (!rt->is_input) {
625                     gen_release_stream(s, rt);
626                     gen_fcpublish_stream(s, rt);
627                     rt->state = STATE_RELEASING;
628                 } else {
629                     gen_server_bw(s, rt);
630                     rt->state = STATE_CONNECTING;
631                 }
632                 gen_create_stream(s, rt);
633                 break;
634             case STATE_FCPUBLISH:
635                 rt->state = STATE_CONNECTING;
636                 break;
637             case STATE_RELEASING:
638                 rt->state = STATE_FCPUBLISH;
639                 /* hack for Wowza Media Server, it does not send result for
640                  * releaseStream and FCPublish calls */
641                 if (!pkt->data[10]) {
642                     int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
643                     if (pkt_id == rt->create_stream_invoke)
644                         rt->state = STATE_CONNECTING;
645                 }
646                 if (rt->state != STATE_CONNECTING)
647                     break;
648             case STATE_CONNECTING:
649                 //extract a number from the result
650                 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
651                     av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
652                 } else {
653                     rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
654                 }
655                 if (rt->is_input) {
656                     gen_play(s, rt);
657                 } else {
658                     gen_publish(s, rt);
659                 }
660                 rt->state = STATE_READY;
661                 break;
662             }
663         } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
664             const uint8_t* ptr = pkt->data + 11;
665             uint8_t tmpstr[256];
666
667             for (i = 0; i < 2; i++) {
668                 t = ff_amf_tag_size(ptr, data_end);
669                 if (t < 0)
670                     return 1;
671                 ptr += t;
672             }
673             t = ff_amf_get_field_value(ptr, data_end,
674                                        "level", tmpstr, sizeof(tmpstr));
675             if (!t && !strcmp(tmpstr, "error")) {
676                 if (!ff_amf_get_field_value(ptr, data_end,
677                                             "description", tmpstr, sizeof(tmpstr)))
678                     av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
679                 return -1;
680             }
681             t = ff_amf_get_field_value(ptr, data_end,
682                                        "code", tmpstr, sizeof(tmpstr));
683             if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
684             if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
685             if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
686             if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
687         }
688         break;
689     }
690     return 0;
691 }
692
693 /**
694  * Interact with the server by receiving and sending RTMP packets until
695  * there is some significant data (media data or expected status notification).
696  *
697  * @param s          reading context
698  * @param for_header non-zero value tells function to work until it
699  * gets notification from the server that playing has been started,
700  * otherwise function will work until some media data is received (or
701  * an error happens)
702  * @return 0 for successful operation, negative value in case of error
703  */
704 static int get_packet(URLContext *s, int for_header)
705 {
706     RTMPContext *rt = s->priv_data;
707     int ret;
708     uint8_t *p;
709     const uint8_t *next;
710     uint32_t data_size;
711     uint32_t ts, cts, pts=0;
712
713     if (rt->state == STATE_STOPPED)
714         return AVERROR_EOF;
715
716     for (;;) {
717         RTMPPacket rpkt = { 0 };
718         if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
719                                        rt->chunk_size, rt->prev_pkt[0])) <= 0) {
720             if (ret == 0) {
721                 return AVERROR(EAGAIN);
722             } else {
723                 return AVERROR(EIO);
724             }
725         }
726         rt->bytes_read += ret;
727         if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
728             av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
729             gen_bytes_read(s, rt, rpkt.timestamp + 1);
730             rt->last_bytes_read = rt->bytes_read;
731         }
732
733         ret = rtmp_parse_result(s, rt, &rpkt);
734         if (ret < 0) {//serious error in current packet
735             ff_rtmp_packet_destroy(&rpkt);
736             return -1;
737         }
738         if (rt->state == STATE_STOPPED) {
739             ff_rtmp_packet_destroy(&rpkt);
740             return AVERROR_EOF;
741         }
742         if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
743             ff_rtmp_packet_destroy(&rpkt);
744             return 0;
745         }
746         if (!rpkt.data_size || !rt->is_input) {
747             ff_rtmp_packet_destroy(&rpkt);
748             continue;
749         }
750         if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
751            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
752             ts = rpkt.timestamp;
753
754             // generate packet header and put data into buffer for FLV demuxer
755             rt->flv_off  = 0;
756             rt->flv_size = rpkt.data_size + 15;
757             rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
758             bytestream_put_byte(&p, rpkt.type);
759             bytestream_put_be24(&p, rpkt.data_size);
760             bytestream_put_be24(&p, ts);
761             bytestream_put_byte(&p, ts >> 24);
762             bytestream_put_be24(&p, 0);
763             bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
764             bytestream_put_be32(&p, 0);
765             ff_rtmp_packet_destroy(&rpkt);
766             return 0;
767         } else if (rpkt.type == RTMP_PT_METADATA) {
768             // we got raw FLV data, make it available for FLV demuxer
769             rt->flv_off  = 0;
770             rt->flv_size = rpkt.data_size;
771             rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
772             /* rewrite timestamps */
773             next = rpkt.data;
774             ts = rpkt.timestamp;
775             while (next - rpkt.data < rpkt.data_size - 11) {
776                 next++;
777                 data_size = bytestream_get_be24(&next);
778                 p=next;
779                 cts = bytestream_get_be24(&next);
780                 cts |= bytestream_get_byte(&next) << 24;
781                 if (pts==0)
782                     pts=cts;
783                 ts += cts - pts;
784                 pts = cts;
785                 bytestream_put_be24(&p, ts);
786                 bytestream_put_byte(&p, ts >> 24);
787                 next += data_size + 3 + 4;
788             }
789             memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
790             ff_rtmp_packet_destroy(&rpkt);
791             return 0;
792         }
793         ff_rtmp_packet_destroy(&rpkt);
794     }
795 }
796
797 static int rtmp_close(URLContext *h)
798 {
799     RTMPContext *rt = h->priv_data;
800
801     if (!rt->is_input) {
802         rt->flv_data = NULL;
803         if (rt->out_pkt.data_size)
804             ff_rtmp_packet_destroy(&rt->out_pkt);
805         if (rt->state > STATE_FCPUBLISH)
806             gen_fcunpublish_stream(h, rt);
807     }
808     if (rt->state > STATE_HANDSHAKED)
809         gen_delete_stream(h, rt);
810
811     av_freep(&rt->flv_data);
812     ffurl_close(rt->stream);
813     return 0;
814 }
815
816 /**
817  * Open RTMP connection and verify that the stream can be played.
818  *
819  * URL syntax: rtmp://server[:port][/app][/playpath]
820  *             where 'app' is first one or two directories in the path
821  *             (e.g. /ondemand/, /flash/live/, etc.)
822  *             and 'playpath' is a file name (the rest of the path,
823  *             may be prefixed with "mp4:")
824  */
825 static int rtmp_open(URLContext *s, const char *uri, int flags)
826 {
827     RTMPContext *rt = s->priv_data;
828     char proto[8], hostname[256], path[1024], *fname;
829     char *old_app;
830     uint8_t buf[2048];
831     int port;
832     int ret;
833
834     rt->is_input = !(flags & AVIO_FLAG_WRITE);
835
836     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
837                  path, sizeof(path), s->filename);
838
839     if (port < 0)
840         port = RTMP_DEFAULT_PORT;
841     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
842
843     if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
844                    &s->interrupt_callback, NULL) < 0) {
845         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
846         goto fail;
847     }
848
849     rt->state = STATE_START;
850     if (rtmp_handshake(s, rt))
851         goto fail;
852
853     rt->chunk_size = 128;
854     rt->state = STATE_HANDSHAKED;
855
856     // Keep the application name when it has been defined by the user.
857     old_app = rt->app;
858
859     rt->app = av_malloc(APP_MAX_LENGTH);
860     if (!rt->app) {
861         rtmp_close(s);
862         return AVERROR(ENOMEM);
863     }
864
865     //extract "app" part from path
866     if (!strncmp(path, "/ondemand/", 10)) {
867         fname = path + 10;
868         memcpy(rt->app, "ondemand", 9);
869     } else {
870         char *p = strchr(path + 1, '/');
871         if (!p) {
872             fname = path + 1;
873             rt->app[0] = '\0';
874         } else {
875             char *c = strchr(p + 1, ':');
876             fname = strchr(p + 1, '/');
877             if (!fname || c < fname) {
878                 fname = p + 1;
879                 av_strlcpy(rt->app, path + 1, p - path);
880             } else {
881                 fname++;
882                 av_strlcpy(rt->app, path + 1, fname - path - 1);
883             }
884         }
885     }
886
887     if (old_app) {
888         // The name of application has been defined by the user, override it.
889         av_free(rt->app);
890         rt->app = old_app;
891     }
892
893     if (!strchr(fname, ':') &&
894         (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
895          !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
896         memcpy(rt->playpath, "mp4:", 5);
897     } else {
898         rt->playpath[0] = 0;
899     }
900     strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
901
902     rt->client_report_size = 1048576;
903     rt->bytes_read = 0;
904     rt->last_bytes_read = 0;
905
906     av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
907            proto, path, rt->app, rt->playpath);
908     gen_connect(s, rt, proto, hostname, port);
909
910     do {
911         ret = get_packet(s, 1);
912     } while (ret == EAGAIN);
913     if (ret < 0)
914         goto fail;
915
916     if (rt->is_input) {
917         // generate FLV header for demuxer
918         rt->flv_size = 13;
919         rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
920         rt->flv_off  = 0;
921         memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
922     } else {
923         rt->flv_size = 0;
924         rt->flv_data = NULL;
925         rt->flv_off  = 0;
926         rt->skip_bytes = 13;
927     }
928
929     s->max_packet_size = rt->stream->max_packet_size;
930     s->is_streamed     = 1;
931     return 0;
932
933 fail:
934     rtmp_close(s);
935     return AVERROR(EIO);
936 }
937
938 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
939 {
940     RTMPContext *rt = s->priv_data;
941     int orig_size = size;
942     int ret;
943
944     while (size > 0) {
945         int data_left = rt->flv_size - rt->flv_off;
946
947         if (data_left >= size) {
948             memcpy(buf, rt->flv_data + rt->flv_off, size);
949             rt->flv_off += size;
950             return orig_size;
951         }
952         if (data_left > 0) {
953             memcpy(buf, rt->flv_data + rt->flv_off, data_left);
954             buf  += data_left;
955             size -= data_left;
956             rt->flv_off = rt->flv_size;
957             return data_left;
958         }
959         if ((ret = get_packet(s, 0)) < 0)
960            return ret;
961     }
962     return orig_size;
963 }
964
965 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
966 {
967     RTMPContext *rt = s->priv_data;
968     int size_temp = size;
969     int pktsize, pkttype;
970     uint32_t ts;
971     const uint8_t *buf_temp = buf;
972
973     do {
974         if (rt->skip_bytes) {
975             int skip = FFMIN(rt->skip_bytes, size_temp);
976             buf_temp       += skip;
977             size_temp      -= skip;
978             rt->skip_bytes -= skip;
979             continue;
980         }
981
982         if (rt->flv_header_bytes < 11) {
983             const uint8_t *header = rt->flv_header;
984             int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
985             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
986             rt->flv_header_bytes += copy;
987             size_temp            -= copy;
988             if (rt->flv_header_bytes < 11)
989                 break;
990
991             pkttype = bytestream_get_byte(&header);
992             pktsize = bytestream_get_be24(&header);
993             ts = bytestream_get_be24(&header);
994             ts |= bytestream_get_byte(&header) << 24;
995             bytestream_get_be24(&header);
996             rt->flv_size = pktsize;
997
998             //force 12bytes header
999             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
1000                 pkttype == RTMP_PT_NOTIFY) {
1001                 if (pkttype == RTMP_PT_NOTIFY)
1002                     pktsize += 16;
1003                 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
1004             }
1005
1006             //this can be a big packet, it's better to send it right here
1007             ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
1008             rt->out_pkt.extra = rt->main_channel_id;
1009             rt->flv_data = rt->out_pkt.data;
1010
1011             if (pkttype == RTMP_PT_NOTIFY)
1012                 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
1013         }
1014
1015         if (rt->flv_size - rt->flv_off > size_temp) {
1016             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
1017             rt->flv_off += size_temp;
1018             size_temp = 0;
1019         } else {
1020             bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
1021             size_temp   -= rt->flv_size - rt->flv_off;
1022             rt->flv_off += rt->flv_size - rt->flv_off;
1023         }
1024
1025         if (rt->flv_off == rt->flv_size) {
1026             rt->skip_bytes = 4;
1027
1028             ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
1029             ff_rtmp_packet_destroy(&rt->out_pkt);
1030             rt->flv_size = 0;
1031             rt->flv_off = 0;
1032             rt->flv_header_bytes = 0;
1033         }
1034     } while (buf_temp - buf < size);
1035     return size;
1036 }
1037
1038 #define OFFSET(x) offsetof(RTMPContext, x)
1039 #define DEC AV_OPT_FLAG_DECODING_PARAM
1040 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1041
1042 static const AVOption rtmp_options[] = {
1043     {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
1044     { NULL },
1045 };
1046
1047 static const AVClass rtmp_class = {
1048     .class_name = "rtmp",
1049     .item_name  = av_default_item_name,
1050     .option     = rtmp_options,
1051     .version    = LIBAVUTIL_VERSION_INT,
1052 };
1053
1054 URLProtocol ff_rtmp_protocol = {
1055     .name           = "rtmp",
1056     .url_open       = rtmp_open,
1057     .url_read       = rtmp_read,
1058     .url_write      = rtmp_write,
1059     .url_close      = rtmp_close,
1060     .priv_data_size = sizeof(RTMPContext),
1061     .flags          = URL_PROTOCOL_FLAG_NETWORK,
1062     .priv_data_class= &rtmp_class,
1063 };