Statistics
| Branch: | Revision:

ffmpeg / libavformat / rtmpproto.c @ f35ff97f

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 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/lfg.h"
30
#include "libavutil/sha.h"
31
#include "avformat.h"
32
#include "internal.h"
33

    
34
#include "network.h"
35

    
36
#include "flv.h"
37
#include "rtmp.h"
38
#include "rtmppkt.h"
39
#include "url.h"
40

    
41
/* we can't use av_log() with URLContext yet... */
42
#if FF_API_URL_CLASS
43
#define LOG_CONTEXT s
44
#else
45
#define LOG_CONTEXT NULL
46
#endif
47

    
48
//#define DEBUG
49

    
50
/** RTMP protocol handler state */
51
typedef enum {
52
    STATE_START,      ///< client has not done anything yet
53
    STATE_HANDSHAKED, ///< client has performed handshake
54
    STATE_RELEASING,  ///< client releasing stream before publish it (for output)
55
    STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
56
    STATE_CONNECTING, ///< client connected to server successfully
57
    STATE_READY,      ///< client has sent all needed commands and waits for server reply
58
    STATE_PLAYING,    ///< client has started receiving multimedia data from server
59
    STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
60
    STATE_STOPPED,    ///< the broadcast has been stopped
61
} ClientState;
62

    
63
/** protocol handler context */
64
typedef struct RTMPContext {
65
    URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
66
    RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
67
    int           chunk_size;                 ///< size of the chunks RTMP packets are divided into
68
    int           is_input;                   ///< input/output flag
69
    char          playpath[256];              ///< path to filename to play (with possible "mp4:" prefix)
70
    char          app[128];                   ///< application
71
    ClientState   state;                      ///< current state
72
    int           main_channel_id;            ///< an additional channel ID which is used for some invocations
73
    uint8_t*      flv_data;                   ///< buffer with data for demuxer
74
    int           flv_size;                   ///< current buffer size
75
    int           flv_off;                    ///< number of bytes read from current buffer
76
    RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
77
    uint32_t      client_report_size;         ///< number of bytes after which client should report to server
78
    uint32_t      bytes_read;                 ///< number of bytes read from server
79
    uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
80
} RTMPContext;
81

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

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

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

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

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

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

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

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

    
151
    pkt.data_size = p - pkt.data;
152

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
247

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

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

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

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

    
270
/**
271
 * Generate 'play' call and send it to the server, then ping the server
272
 * to start actual playing.
273
 */
274
static void gen_play(URLContext *s, RTMPContext *rt)
275
{
276
    RTMPPacket pkt;
277
    uint8_t *p;
278

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
382
    sha = av_mallocz(av_sha_size);
383

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

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

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

    
410
    av_free(sha);
411
}
412

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

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

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

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

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

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

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

    
481
    av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Handshaking...\n");
482

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

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

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

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

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

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

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

    
540
    return 0;
541
}
542

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

    
554
#ifdef DEBUG
555
    ff_rtmp_packet_dump(LOG_CONTEXT, pkt);
556
#endif
557

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

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

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

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

    
689
    if (rt->state == STATE_STOPPED)
690
        return AVERROR_EOF;
691

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

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

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

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

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

    
788
    av_freep(&rt->flv_data);
789
    ffurl_close(rt->stream);
790
    av_free(rt);
791
    return 0;
792
}
793

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

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

    
817
    av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
818
                 path, sizeof(path), s->filename);
819

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

    
824
    if (ffurl_open(&rt->stream, buf, AVIO_RDWR) < 0) {
825
        av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf);
826
        goto fail;
827
    }
828

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

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

    
865
    rt->client_report_size = 1048576;
866
    rt->bytes_read = 0;
867
    rt->last_bytes_read = 0;
868

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

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

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

    
891
    s->max_packet_size = rt->stream->max_packet_size;
892
    s->is_streamed     = 1;
893
    return 0;
894

    
895
fail:
896
    rtmp_close(s);
897
    return AVERROR(EIO);
898
}
899

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

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

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

    
927
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
928
{
929
    RTMPContext *rt = s->priv_data;
930
    int size_temp = size;
931
    int pktsize, pkttype;
932
    uint32_t ts;
933
    const uint8_t *buf_temp = buf;
934

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

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

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

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

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

    
969
            if (pkttype == RTMP_PT_NOTIFY)
970
                ff_amf_write_string(&rt->flv_data, "@setDataFrame");
971
        }
972

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

    
981
        if (rt->flv_off == rt->flv_size) {
982
            bytestream_get_be32(&buf_temp);
983

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

    
993
URLProtocol ff_rtmp_protocol = {
994
    .name      = "rtmp",
995
    .url_open  = rtmp_open,
996
    .url_read  = rtmp_read,
997
    .url_write = rtmp_write,
998
    .url_close = rtmp_close,
999
};