Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtmpproto.c @ 57b5555c

History | View | Annotate | Download (33.8 KB)

1
/*
2
 * RTMP network protocol
3
 * Copyright (c) 2009 Kostya Shishkov
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
/**
23
 * @file libavformat/rtmpproto.c
24
 * RTMP protocol
25
 */
26

    
27
#include "libavcodec/bytestream.h"
28
#include "libavutil/avstring.h"
29
#include "libavutil/lfg.h"
30
#include "libavutil/sha.h"
31
#include "avformat.h"
32

    
33
#include "network.h"
34

    
35
#include "flv.h"
36
#include "rtmp.h"
37
#include "rtmppkt.h"
38

    
39
/* we can't use av_log() with URLContext yet... */
40
#if LIBAVFORMAT_VERSION_MAJOR < 53
41
#define LOG_CONTEXT NULL
42
#else
43
#define LOG_CONTEXT s
44
#endif
45

    
46
//#define DEBUG
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
    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[128];                   ///< 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
} RTMPContext;
79

    
80
#define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
81
/** Client key used for digest signing */
82
static const uint8_t rtmp_player_key[] = {
83
    'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
84
    'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
85

    
86
    0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
87
    0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
88
    0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
89
};
90

    
91
#define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
92
/** Key used for RTMP server digest signing */
93
static const uint8_t rtmp_server_key[] = {
94
    'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
95
    'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
96
    'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
97

    
98
    0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
99
    0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
100
    0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
101
};
102

    
103
/**
104
 * Generates 'connect' call and sends it to the server.
105
 */
106
static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto,
107
                        const char *host, int port)
108
{
109
    RTMPPacket pkt;
110
    uint8_t ver[64], *p;
111
    char tcurl[512];
112

    
113
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
114
    p = pkt.data;
115

    
116
    ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
117
    ff_amf_write_string(&p, "connect");
118
    ff_amf_write_number(&p, 1.0);
119
    ff_amf_write_object_start(&p);
120
    ff_amf_write_field_name(&p, "app");
121
    ff_amf_write_string(&p, rt->app);
122

    
123
    if (rt->is_input) {
124
        snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
125
                 RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
126
    } else {
127
        snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
128
        ff_amf_write_field_name(&p, "type");
129
        ff_amf_write_string(&p, "nonprivate");
130
    }
131
    ff_amf_write_field_name(&p, "flashVer");
132
    ff_amf_write_string(&p, ver);
133
    ff_amf_write_field_name(&p, "tcUrl");
134
    ff_amf_write_string(&p, tcurl);
135
    if (rt->is_input) {
136
        ff_amf_write_field_name(&p, "fpad");
137
        ff_amf_write_bool(&p, 0);
138
        ff_amf_write_field_name(&p, "capabilities");
139
        ff_amf_write_number(&p, 15.0);
140
        ff_amf_write_field_name(&p, "audioCodecs");
141
        ff_amf_write_number(&p, 1639.0);
142
        ff_amf_write_field_name(&p, "videoCodecs");
143
        ff_amf_write_number(&p, 252.0);
144
        ff_amf_write_field_name(&p, "videoFunction");
145
        ff_amf_write_number(&p, 1.0);
146
    }
147
    ff_amf_write_object_end(&p);
148

    
149
    pkt.data_size = p - pkt.data;
150

    
151
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
152
    ff_rtmp_packet_destroy(&pkt);
153
}
154

    
155
/**
156
 * Generates 'releaseStream' call and sends it to the server. It should make
157
 * the server release some channel for media streams.
158
 */
159
static void gen_release_stream(URLContext *s, RTMPContext *rt)
160
{
161
    RTMPPacket pkt;
162
    uint8_t *p;
163

    
164
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
165
                          29 + strlen(rt->playpath));
166

    
167
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Releasing stream...\n");
168
    p = pkt.data;
169
    ff_amf_write_string(&p, "releaseStream");
170
    ff_amf_write_number(&p, 2.0);
171
    ff_amf_write_null(&p);
172
    ff_amf_write_string(&p, rt->playpath);
173

    
174
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
175
    ff_rtmp_packet_destroy(&pkt);
176
}
177

    
178
/**
179
 * Generates 'FCPublish' call and sends it to the server. It should make
180
 * the server preapare for receiving media streams.
181
 */
182
static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
183
{
184
    RTMPPacket pkt;
185
    uint8_t *p;
186

    
187
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
188
                          25 + strlen(rt->playpath));
189

    
190
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FCPublish stream...\n");
191
    p = pkt.data;
192
    ff_amf_write_string(&p, "FCPublish");
193
    ff_amf_write_number(&p, 3.0);
194
    ff_amf_write_null(&p);
195
    ff_amf_write_string(&p, rt->playpath);
196

    
197
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
198
    ff_rtmp_packet_destroy(&pkt);
199
}
200

    
201
/**
202
 * Generates 'FCUnpublish' call and sends it to the server. It should make
203
 * the server destroy stream.
204
 */
205
static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
206
{
207
    RTMPPacket pkt;
208
    uint8_t *p;
209

    
210
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0,
211
                          27 + strlen(rt->playpath));
212

    
213
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "UnPublishing stream...\n");
214
    p = pkt.data;
215
    ff_amf_write_string(&p, "FCUnpublish");
216
    ff_amf_write_number(&p, 5.0);
217
    ff_amf_write_null(&p);
218
    ff_amf_write_string(&p, rt->playpath);
219

    
220
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
221
    ff_rtmp_packet_destroy(&pkt);
222
}
223

    
224
/**
225
 * Generates 'createStream' call and sends it to the server. It should make
226
 * the server allocate some channel for media streams.
227
 */
228
static void gen_create_stream(URLContext *s, RTMPContext *rt)
229
{
230
    RTMPPacket pkt;
231
    uint8_t *p;
232

    
233
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Creating stream...\n");
234
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
235

    
236
    p = pkt.data;
237
    ff_amf_write_string(&p, "createStream");
238
    ff_amf_write_number(&p, rt->is_input ? 3.0 : 4.0);
239
    ff_amf_write_null(&p);
240

    
241
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
242
    ff_rtmp_packet_destroy(&pkt);
243
}
244

    
245

    
246
/**
247
 * Generates 'deleteStream' call and sends it to the server. It should make
248
 * the server remove some channel for media streams.
249
 */
250
static void gen_delete_stream(URLContext *s, RTMPContext *rt)
251
{
252
    RTMPPacket pkt;
253
    uint8_t *p;
254

    
255
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Deleting stream...\n");
256
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);
257

    
258
    p = pkt.data;
259
    ff_amf_write_string(&p, "deleteStream");
260
    ff_amf_write_number(&p, 0.0);
261
    ff_amf_write_null(&p);
262
    ff_amf_write_number(&p, rt->main_channel_id);
263

    
264
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
265
    ff_rtmp_packet_destroy(&pkt);
266
}
267

    
268
/**
269
 * Generates 'play' call and sends it to the server, then pings the server
270
 * to start actual playing.
271
 */
272
static void gen_play(URLContext *s, RTMPContext *rt)
273
{
274
    RTMPPacket pkt;
275
    uint8_t *p;
276

    
277
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
278
    ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
279
                          20 + strlen(rt->playpath));
280
    pkt.extra = rt->main_channel_id;
281

    
282
    p = pkt.data;
283
    ff_amf_write_string(&p, "play");
284
    ff_amf_write_number(&p, 0.0);
285
    ff_amf_write_null(&p);
286
    ff_amf_write_string(&p, rt->playpath);
287

    
288
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
289
    ff_rtmp_packet_destroy(&pkt);
290

    
291
    // set client buffer time disguised in ping packet
292
    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, 1, 10);
293

    
294
    p = pkt.data;
295
    bytestream_put_be16(&p, 3);
296
    bytestream_put_be32(&p, 1);
297
    bytestream_put_be32(&p, 256); //TODO: what is a good value here?
298

    
299
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
300
    ff_rtmp_packet_destroy(&pkt);
301
}
302

    
303
/**
304
 * Generates 'publish' call and sends it to the server.
305
 */
306
static void gen_publish(URLContext *s, RTMPContext *rt)
307
{
308
    RTMPPacket pkt;
309
    uint8_t *p;
310

    
311
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
312
    ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
313
                          30 + strlen(rt->playpath));
314
    pkt.extra = rt->main_channel_id;
315

    
316
    p = pkt.data;
317
    ff_amf_write_string(&p, "publish");
318
    ff_amf_write_number(&p, 0.0);
319
    ff_amf_write_null(&p);
320
    ff_amf_write_string(&p, rt->playpath);
321
    ff_amf_write_string(&p, "live");
322

    
323
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
324
    ff_rtmp_packet_destroy(&pkt);
325
}
326

    
327
/**
328
 * Generates ping reply and sends it to the server.
329
 */
330
static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
331
{
332
    RTMPPacket pkt;
333
    uint8_t *p;
334

    
335
    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
336
    p = pkt.data;
337
    bytestream_put_be16(&p, 7);
338
    bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
339
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
340
    ff_rtmp_packet_destroy(&pkt);
341
}
342

    
343
/**
344
 * Generates report on bytes read so far and sends it to the server.
345
 */
346
static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
347
{
348
    RTMPPacket pkt;
349
    uint8_t *p;
350

    
351
    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
352
    p = pkt.data;
353
    bytestream_put_be32(&p, rt->bytes_read);
354
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
355
    ff_rtmp_packet_destroy(&pkt);
356
}
357

    
358
//TODO: Move HMAC code somewhere. Eventually.
359
#define HMAC_IPAD_VAL 0x36
360
#define HMAC_OPAD_VAL 0x5C
361

    
362
/**
363
 * Calculates HMAC-SHA2 digest for RTMP handshake packets.
364
 *
365
 * @param src    input buffer
366
 * @param len    input buffer length (should be 1536)
367
 * @param gap    offset in buffer where 32 bytes should not be taken into account
368
 *               when calculating digest (since it will be used to store that digest)
369
 * @param key    digest key
370
 * @param keylen digest key length
371
 * @param dst    buffer where calculated digest will be stored (32 bytes)
372
 */
373
static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
374
                             const uint8_t *key, int keylen, uint8_t *dst)
375
{
376
    struct AVSHA *sha;
377
    uint8_t hmac_buf[64+32] = {0};
378
    int i;
379

    
380
    sha = av_mallocz(av_sha_size);
381

    
382
    if (keylen < 64) {
383
        memcpy(hmac_buf, key, keylen);
384
    } else {
385
        av_sha_init(sha, 256);
386
        av_sha_update(sha,key, keylen);
387
        av_sha_final(sha, hmac_buf);
388
    }
389
    for (i = 0; i < 64; i++)
390
        hmac_buf[i] ^= HMAC_IPAD_VAL;
391

    
392
    av_sha_init(sha, 256);
393
    av_sha_update(sha, hmac_buf, 64);
394
    if (gap <= 0) {
395
        av_sha_update(sha, src, len);
396
    } else { //skip 32 bytes used for storing digest
397
        av_sha_update(sha, src, gap);
398
        av_sha_update(sha, src + gap + 32, len - gap - 32);
399
    }
400
    av_sha_final(sha, hmac_buf + 64);
401

    
402
    for (i = 0; i < 64; i++)
403
        hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
404
    av_sha_init(sha, 256);
405
    av_sha_update(sha, hmac_buf, 64+32);
406
    av_sha_final(sha, dst);
407

    
408
    av_free(sha);
409
}
410

    
411
/**
412
 * Puts HMAC-SHA2 digest of packet data (except for the bytes where this digest
413
 * will be stored) into that packet.
414
 *
415
 * @param buf handshake data (1536 bytes)
416
 * @return offset to the digest inside input data
417
 */
418
static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
419
{
420
    int i, digest_pos = 0;
421

    
422
    for (i = 8; i < 12; i++)
423
        digest_pos += buf[i];
424
    digest_pos = (digest_pos % 728) + 12;
425

    
426
    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
427
                     rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
428
                     buf + digest_pos);
429
    return digest_pos;
430
}
431

    
432
/**
433
 * Verifies that the received server response has the expected digest value.
434
 *
435
 * @param buf handshake data received from the server (1536 bytes)
436
 * @param off position to search digest offset from
437
 * @return 0 if digest is valid, digest position otherwise
438
 */
439
static int rtmp_validate_digest(uint8_t *buf, int off)
440
{
441
    int i, digest_pos = 0;
442
    uint8_t digest[32];
443

    
444
    for (i = 0; i < 4; i++)
445
        digest_pos += buf[i + off];
446
    digest_pos = (digest_pos % 728) + off + 4;
447

    
448
    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
449
                     rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
450
                     digest);
451
    if (!memcmp(digest, buf + digest_pos, 32))
452
        return digest_pos;
453
    return 0;
454
}
455

    
456
/**
457
 * Performs handshake with the server by means of exchanging pseudorandom data
458
 * signed with HMAC-SHA2 digest.
459
 *
460
 * @return 0 if handshake succeeds, negative value otherwise
461
 */
462
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
463
{
464
    AVLFG rnd;
465
    uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
466
        3,                // unencrypted data
467
        0, 0, 0, 0,       // client uptime
468
        RTMP_CLIENT_VER1,
469
        RTMP_CLIENT_VER2,
470
        RTMP_CLIENT_VER3,
471
        RTMP_CLIENT_VER4,
472
    };
473
    uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
474
    uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
475
    int i;
476
    int server_pos, client_pos;
477
    uint8_t digest[32];
478

    
479
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Handshaking...\n");
480

    
481
    av_lfg_init(&rnd, 0xDEADC0DE);
482
    // generate handshake packet - 1536 bytes of pseudorandom data
483
    for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
484
        tosend[i] = av_lfg_get(&rnd) >> 24;
485
    client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
486

    
487
    url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
488
    i = url_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
489
    if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
490
        av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
491
        return -1;
492
    }
493
    i = url_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
494
    if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
495
        av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
496
        return -1;
497
    }
498

    
499
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
500
           serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
501

    
502
    if (rt->is_input && serverdata[5] >= 3) {
503
        server_pos = rtmp_validate_digest(serverdata + 1, 772);
504
        if (!server_pos) {
505
            server_pos = rtmp_validate_digest(serverdata + 1, 8);
506
            if (!server_pos) {
507
                av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server response validating failed\n");
508
                return -1;
509
            }
510
        }
511

    
512
        rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
513
                         rtmp_server_key, sizeof(rtmp_server_key),
514
                         digest);
515
        rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
516
                         digest, 32,
517
                         digest);
518
        if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
519
            av_log(LOG_CONTEXT, AV_LOG_ERROR, "Signature mismatch\n");
520
            return -1;
521
        }
522

    
523
        for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
524
            tosend[i] = av_lfg_get(&rnd) >> 24;
525
        rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
526
                         rtmp_player_key, sizeof(rtmp_player_key),
527
                         digest);
528
        rtmp_calc_digest(tosend,  RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
529
                         digest, 32,
530
                         tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
531

    
532
        // write reply back to the server
533
        url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
534
    } else {
535
        url_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
536
    }
537

    
538
    return 0;
539
}
540

    
541
/**
542
 * Parses received packet and may perform some action depending on
543
 * the packet contents.
544
 * @return 0 for no errors, negative values for serious errors which prevent
545
 *         further communications, positive values for uncritical errors
546
 */
547
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
548
{
549
    int i, t;
550
    const uint8_t *data_end = pkt->data + pkt->data_size;
551

    
552
#ifdef DEBUG
553
    ff_rtmp_packet_dump(LOG_CONTEXT, pkt);
554
#endif
555

    
556
    switch (pkt->type) {
557
    case RTMP_PT_CHUNK_SIZE:
558
        if (pkt->data_size != 4) {
559
            av_log(LOG_CONTEXT, AV_LOG_ERROR,
560
                   "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
561
            return -1;
562
        }
563
        if (!rt->is_input)
564
            ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
565
        rt->chunk_size = AV_RB32(pkt->data);
566
        if (rt->chunk_size <= 0) {
567
            av_log(LOG_CONTEXT, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
568
            return -1;
569
        }
570
        av_log(LOG_CONTEXT, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
571
        break;
572
    case RTMP_PT_PING:
573
        t = AV_RB16(pkt->data);
574
        if (t == 6)
575
            gen_pong(s, rt, pkt);
576
        break;
577
    case RTMP_PT_CLIENT_BW:
578
        if (pkt->data_size < 4) {
579
            av_log(LOG_CONTEXT, AV_LOG_ERROR,
580
                   "Client bandwidth report packet is less than 4 bytes long (%d)\n",
581
                   pkt->data_size);
582
            return -1;
583
        }
584
        av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
585
        rt->client_report_size = AV_RB32(pkt->data) >> 1;
586
        break;
587
    case RTMP_PT_INVOKE:
588
        //TODO: check for the messages sent for wrong state?
589
        if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
590
            uint8_t tmpstr[256];
591

    
592
            if (!ff_amf_get_field_value(pkt->data + 9, data_end,
593
                                        "description", tmpstr, sizeof(tmpstr)))
594
                av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
595
            return -1;
596
        } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
597
            switch (rt->state) {
598
            case STATE_HANDSHAKED:
599
                if (!rt->is_input) {
600
                    gen_release_stream(s, rt);
601
                    gen_fcpublish_stream(s, rt);
602
                    rt->state = STATE_RELEASING;
603
                } else {
604
                    rt->state = STATE_CONNECTING;
605
                }
606
                gen_create_stream(s, rt);
607
                break;
608
            case STATE_FCPUBLISH:
609
                rt->state = STATE_CONNECTING;
610
                break;
611
            case STATE_RELEASING:
612
                rt->state = STATE_FCPUBLISH;
613
                /* hack for Wowza Media Server, it does not send result for
614
                 * releaseStream and FCPublish calls */
615
                if (!pkt->data[10]) {
616
                    int pkt_id = (int) av_int2dbl(AV_RB64(pkt->data + 11));
617
                    if (pkt_id == 4)
618
                        rt->state = STATE_CONNECTING;
619
                }
620
                if (rt->state != STATE_CONNECTING)
621
                    break;
622
            case STATE_CONNECTING:
623
                //extract a number from the result
624
                if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
625
                    av_log(LOG_CONTEXT, AV_LOG_WARNING, "Unexpected reply on connect()\n");
626
                } else {
627
                    rt->main_channel_id = (int) av_int2dbl(AV_RB64(pkt->data + 21));
628
                }
629
                if (rt->is_input) {
630
                    gen_play(s, rt);
631
                } else {
632
                    gen_publish(s, rt);
633
                }
634
                rt->state = STATE_READY;
635
                break;
636
            }
637
        } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
638
            const uint8_t* ptr = pkt->data + 11;
639
            uint8_t tmpstr[256];
640

    
641
            for (i = 0; i < 2; i++) {
642
                t = ff_amf_tag_size(ptr, data_end);
643
                if (t < 0)
644
                    return 1;
645
                ptr += t;
646
            }
647
            t = ff_amf_get_field_value(ptr, data_end,
648
                                       "level", tmpstr, sizeof(tmpstr));
649
            if (!t && !strcmp(tmpstr, "error")) {
650
                if (!ff_amf_get_field_value(ptr, data_end,
651
                                            "description", tmpstr, sizeof(tmpstr)))
652
                    av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
653
                return -1;
654
            }
655
            t = ff_amf_get_field_value(ptr, data_end,
656
                                       "code", tmpstr, sizeof(tmpstr));
657
            if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
658
            if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
659
            if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
660
            if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
661
        }
662
        break;
663
    }
664
    return 0;
665
}
666

    
667
/**
668
 * Interacts with the server by receiving and sending RTMP packets until
669
 * there is some significant data (media data or expected status notification).
670
 *
671
 * @param s          reading context
672
 * @param for_header non-zero value tells function to work until it
673
 * gets notification from the server that playing has been started,
674
 * otherwise function will work until some media data is received (or
675
 * an error happens)
676
 * @return 0 for successful operation, negative value in case of error
677
 */
678
static int get_packet(URLContext *s, int for_header)
679
{
680
    RTMPContext *rt = s->priv_data;
681
    int ret;
682
    uint8_t *p;
683
    const uint8_t *next;
684
    uint32_t data_size;
685
    uint32_t ts, cts, pts=0;
686

    
687
    if (rt->state == STATE_STOPPED)
688
        return AVERROR_EOF;
689

    
690
    for (;;) {
691
        RTMPPacket rpkt;
692
        if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
693
                                       rt->chunk_size, rt->prev_pkt[0])) <= 0) {
694
            if (ret == 0) {
695
                return AVERROR(EAGAIN);
696
            } else {
697
                return AVERROR(EIO);
698
            }
699
        }
700
        rt->bytes_read += ret;
701
        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
702
            av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending bytes read report\n");
703
            gen_bytes_read(s, rt, rpkt.timestamp + 1);
704
            rt->last_bytes_read = rt->bytes_read;
705
        }
706

    
707
        ret = rtmp_parse_result(s, rt, &rpkt);
708
        if (ret < 0) {//serious error in current packet
709
            ff_rtmp_packet_destroy(&rpkt);
710
            return -1;
711
        }
712
        if (rt->state == STATE_STOPPED) {
713
            ff_rtmp_packet_destroy(&rpkt);
714
            return AVERROR_EOF;
715
        }
716
        if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
717
            ff_rtmp_packet_destroy(&rpkt);
718
            return 0;
719
        }
720
        if (!rpkt.data_size || !rt->is_input) {
721
            ff_rtmp_packet_destroy(&rpkt);
722
            continue;
723
        }
724
        if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
725
           (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
726
            ts = rpkt.timestamp;
727

    
728
            // generate packet header and put data into buffer for FLV demuxer
729
            rt->flv_off  = 0;
730
            rt->flv_size = rpkt.data_size + 15;
731
            rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
732
            bytestream_put_byte(&p, rpkt.type);
733
            bytestream_put_be24(&p, rpkt.data_size);
734
            bytestream_put_be24(&p, ts);
735
            bytestream_put_byte(&p, ts >> 24);
736
            bytestream_put_be24(&p, 0);
737
            bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
738
            bytestream_put_be32(&p, 0);
739
            ff_rtmp_packet_destroy(&rpkt);
740
            return 0;
741
        } else if (rpkt.type == RTMP_PT_METADATA) {
742
            // we got raw FLV data, make it available for FLV demuxer
743
            rt->flv_off  = 0;
744
            rt->flv_size = rpkt.data_size;
745
            rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
746
            /* rewrite timestamps */
747
            next = rpkt.data;
748
            ts = rpkt.timestamp;
749
            while (next - rpkt.data < rpkt.data_size - 11) {
750
                next++;
751
                data_size = bytestream_get_be24(&next);
752
                p=next;
753
                cts = bytestream_get_be24(&next);
754
                cts |= bytestream_get_byte(&next);
755
                if (pts==0)
756
                    pts=cts;
757
                ts += cts - pts;
758
                pts = cts;
759
                bytestream_put_be24(&p, ts);
760
                bytestream_put_byte(&p, ts >> 24);
761
                next += data_size + 3 + 4;
762
            }
763
            memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
764
            ff_rtmp_packet_destroy(&rpkt);
765
            return 0;
766
        }
767
        ff_rtmp_packet_destroy(&rpkt);
768
    }
769
    return 0;
770
}
771

    
772
static int rtmp_close(URLContext *h)
773
{
774
    RTMPContext *rt = h->priv_data;
775

    
776
    if (!rt->is_input) {
777
        rt->flv_data = NULL;
778
        if (rt->out_pkt.data_size)
779
            ff_rtmp_packet_destroy(&rt->out_pkt);
780
        if (rt->state > STATE_FCPUBLISH)
781
            gen_fcunpublish_stream(h, rt);
782
    }
783
    if (rt->state > STATE_HANDSHAKED)
784
        gen_delete_stream(h, rt);
785

    
786
    av_freep(&rt->flv_data);
787
    url_close(rt->stream);
788
    av_free(rt);
789
    return 0;
790
}
791

    
792
/**
793
 * Opens RTMP connection and verifies that the stream can be played.
794
 *
795
 * URL syntax: rtmp://server[:port][/app][/playpath]
796
 *             where 'app' is first one or two directories in the path
797
 *             (e.g. /ondemand/, /flash/live/, etc.)
798
 *             and 'playpath' is a file name (the rest of the path,
799
 *             may be prefixed with "mp4:")
800
 */
801
static int rtmp_open(URLContext *s, const char *uri, int flags)
802
{
803
    RTMPContext *rt;
804
    char proto[8], hostname[256], path[1024], *fname;
805
    uint8_t buf[2048];
806
    int port;
807
    int ret;
808

    
809
    rt = av_mallocz(sizeof(RTMPContext));
810
    if (!rt)
811
        return AVERROR(ENOMEM);
812
    s->priv_data = rt;
813
    rt->is_input = !(flags & URL_WRONLY);
814

    
815
    url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
816
              path, sizeof(path), s->filename);
817

    
818
    if (port < 0)
819
        port = RTMP_DEFAULT_PORT;
820
    ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
821

    
822
    if (url_open(&rt->stream, buf, URL_RDWR) < 0) {
823
        av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf);
824
        goto fail;
825
    }
826

    
827
    rt->state = STATE_START;
828
    if (rtmp_handshake(s, rt))
829
        return -1;
830

    
831
    rt->chunk_size = 128;
832
    rt->state = STATE_HANDSHAKED;
833
    //extract "app" part from path
834
    if (!strncmp(path, "/ondemand/", 10)) {
835
        fname = path + 10;
836
        memcpy(rt->app, "ondemand", 9);
837
    } else {
838
        char *p = strchr(path + 1, '/');
839
        if (!p) {
840
            fname = path + 1;
841
            rt->app[0] = '\0';
842
        } else {
843
            char *c = strchr(p + 1, ':');
844
            fname = strchr(p + 1, '/');
845
            if (!fname || c < fname) {
846
                fname = p + 1;
847
                av_strlcpy(rt->app, path + 1, p - path);
848
            } else {
849
                fname++;
850
                av_strlcpy(rt->app, path + 1, fname - path - 1);
851
            }
852
        }
853
    }
854
    if (!strchr(fname, ':') &&
855
        (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
856
         !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
857
        memcpy(rt->playpath, "mp4:", 5);
858
    } else {
859
        rt->playpath[0] = 0;
860
    }
861
    strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
862

    
863
    rt->client_report_size = 1048576;
864
    rt->bytes_read = 0;
865
    rt->last_bytes_read = 0;
866

    
867
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
868
           proto, path, rt->app, rt->playpath);
869
    gen_connect(s, rt, proto, hostname, port);
870

    
871
    do {
872
        ret = get_packet(s, 1);
873
    } while (ret == EAGAIN);
874
    if (ret < 0)
875
        goto fail;
876

    
877
    if (rt->is_input) {
878
        // generate FLV header for demuxer
879
        rt->flv_size = 13;
880
        rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
881
        rt->flv_off  = 0;
882
        memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
883
    } else {
884
        rt->flv_size = 0;
885
        rt->flv_data = NULL;
886
        rt->flv_off  = 0;
887
    }
888

    
889
    s->max_packet_size = url_get_max_packet_size(rt->stream);
890
    s->is_streamed     = 1;
891
    return 0;
892

    
893
fail:
894
    rtmp_close(s);
895
    return AVERROR(EIO);
896
}
897

    
898
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
899
{
900
    RTMPContext *rt = s->priv_data;
901
    int orig_size = size;
902
    int ret;
903

    
904
    while (size > 0) {
905
        int data_left = rt->flv_size - rt->flv_off;
906

    
907
        if (data_left >= size) {
908
            memcpy(buf, rt->flv_data + rt->flv_off, size);
909
            rt->flv_off += size;
910
            return orig_size;
911
        }
912
        if (data_left > 0) {
913
            memcpy(buf, rt->flv_data + rt->flv_off, data_left);
914
            buf  += data_left;
915
            size -= data_left;
916
            rt->flv_off = rt->flv_size;
917
        }
918
        if ((ret = get_packet(s, 0)) < 0)
919
           return ret;
920
    }
921
    return orig_size;
922
}
923

    
924
static int rtmp_write(URLContext *h, uint8_t *buf, int size)
925
{
926
    RTMPContext *rt = h->priv_data;
927
    int size_temp = size;
928
    int pktsize, pkttype;
929
    uint32_t ts;
930
    const uint8_t *buf_temp = buf;
931

    
932
    if (size < 11) {
933
        av_log(LOG_CONTEXT, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
934
        return 0;
935
    }
936

    
937
    do {
938
        if (!rt->flv_off) {
939
            //skip flv header
940
            if (buf_temp[0] == 'F' && buf_temp[1] == 'L' && buf_temp[2] == 'V') {
941
                buf_temp += 9 + 4;
942
                size_temp -= 9 + 4;
943
            }
944

    
945
            pkttype = bytestream_get_byte(&buf_temp);
946
            pktsize = bytestream_get_be24(&buf_temp);
947
            ts = bytestream_get_be24(&buf_temp);
948
            ts |= bytestream_get_byte(&buf_temp) << 24;
949
            bytestream_get_be24(&buf_temp);
950
            size_temp -= 11;
951
            rt->flv_size = pktsize;
952

    
953
            //force 12bytes header
954
            if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
955
                pkttype == RTMP_PT_NOTIFY) {
956
                if (pkttype == RTMP_PT_NOTIFY)
957
                    pktsize += 16;
958
                rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
959
            }
960

    
961
            //this can be a big packet, it's better to send it right here
962
            ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL, pkttype, ts, pktsize);
963
            rt->out_pkt.extra = rt->main_channel_id;
964
            rt->flv_data = rt->out_pkt.data;
965

    
966
            if (pkttype == RTMP_PT_NOTIFY)
967
                ff_amf_write_string(&rt->flv_data, "@setDataFrame");
968
        }
969

    
970
        if (rt->flv_size - rt->flv_off > size_temp) {
971
            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
972
            rt->flv_off += size_temp;
973
        } else {
974
            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
975
            rt->flv_off += rt->flv_size - rt->flv_off;
976
        }
977

    
978
        if (rt->flv_off == rt->flv_size) {
979
            bytestream_get_be32(&buf_temp);
980

    
981
            ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
982
            ff_rtmp_packet_destroy(&rt->out_pkt);
983
            rt->flv_size = 0;
984
            rt->flv_off = 0;
985
        }
986
    } while (buf_temp - buf < size_temp);
987
    return size;
988
}
989

    
990
URLProtocol rtmp_protocol = {
991
    "rtmp",
992
    rtmp_open,
993
    rtmp_read,
994
    rtmp_write,
995
    NULL, /* seek */
996
    rtmp_close,
997
};