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