rtmpproto.c 37 KB
Newer Older
1 2 3 4
/*
 * RTMP network protocol
 * Copyright (c) 2009 Kostya Shishkov
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8 9 10 11
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
12
 * Libav is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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 20 21 22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
23
 * @file
24 25 26 27 28
 * RTMP protocol
 */

#include "libavcodec/bytestream.h"
#include "libavutil/avstring.h"
29
#include "libavutil/intfloat.h"
30
#include "libavutil/lfg.h"
31
#include "libavutil/opt.h"
32 33
#include "libavutil/sha.h"
#include "avformat.h"
34
#include "internal.h"
35 36 37 38 39 40

#include "network.h"

#include "flv.h"
#include "rtmp.h"
#include "rtmppkt.h"
41
#include "url.h"
42

43 44
//#define DEBUG

45
#define APP_MAX_LENGTH 128
46
#define PLAYPATH_MAX_LENGTH 256
47

48 49 50 51
/** RTMP protocol handler state */
typedef enum {
    STATE_START,      ///< client has not done anything yet
    STATE_HANDSHAKED, ///< client has performed handshake
52 53
    STATE_RELEASING,  ///< client releasing stream before publish it (for output)
    STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
54 55 56
    STATE_CONNECTING, ///< client connected to server successfully
    STATE_READY,      ///< client has sent all needed commands and waits for server reply
    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 60 61 62
} ClientState;

/** protocol handler context */
typedef struct RTMPContext {
63
    const AVClass *class;
64 65 66
    URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
    RTMPPacket    prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets
    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
    int           live;                       ///< 0: recorded, -1: live, -2: both
70
    char          *app;                       ///< name of application
71 72 73 74 75
    ClientState   state;                      ///< current state
    int           main_channel_id;            ///< an additional channel ID which is used for some invocations
    uint8_t*      flv_data;                   ///< buffer with data for demuxer
    int           flv_size;                   ///< current buffer size
    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 78 79
    uint32_t      client_report_size;         ///< number of bytes after which client should report to server
    uint32_t      bytes_read;                 ///< number of bytes read from server
    uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
80
    int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
81 82
    uint8_t       flv_header[11];             ///< partial incoming flv packet header
    int           flv_header_bytes;           ///< number of initialized bytes in flv_header
83
    int           nb_invokes;                 ///< keeps track of invoke messages
84
    int           create_stream_invoke;       ///< invoke id for the create stream command
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
} RTMPContext;

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

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

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

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

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

120
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
121 122
    p = pkt.data;

123
    ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
124
    ff_amf_write_string(&p, "connect");
125
    ff_amf_write_number(&p, ++rt->nb_invokes);
126 127
    ff_amf_write_object_start(&p);
    ff_amf_write_field_name(&p, "app");
128
    ff_amf_write_string(&p, rt->app);
129

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

        /* Tell the server we support all the audio codecs except
         * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
         * which are unused in the RTMP protocol implementation. */
151
        ff_amf_write_field_name(&p, "audioCodecs");
152
        ff_amf_write_number(&p, 4071.0);
153 154 155 156
        ff_amf_write_field_name(&p, "videoCodecs");
        ff_amf_write_number(&p, 252.0);
        ff_amf_write_field_name(&p, "videoFunction");
        ff_amf_write_number(&p, 1.0);
157
    }
158 159 160 161 162
    ff_amf_write_object_end(&p);

    pkt.data_size = p - pkt.data;

    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
163
    ff_rtmp_packet_destroy(&pkt);
164 165
}

166
/**
167
 * Generate 'releaseStream' call and send it to the server. It should make
168 169 170 171 172 173 174 175 176 177
 * the server release some channel for media streams.
 */
static void gen_release_stream(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

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

178
    av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
179 180
    p = pkt.data;
    ff_amf_write_string(&p, "releaseStream");
181
    ff_amf_write_number(&p, ++rt->nb_invokes);
182 183 184 185 186 187 188 189
    ff_amf_write_null(&p);
    ff_amf_write_string(&p, rt->playpath);

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

/**
190
 * Generate 'FCPublish' call and send it to the server. It should make
191 192 193 194 195 196 197 198 199 200
 * the server preapare for receiving media streams.
 */
static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

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

201
    av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
202 203
    p = pkt.data;
    ff_amf_write_string(&p, "FCPublish");
204
    ff_amf_write_number(&p, ++rt->nb_invokes);
205 206 207 208 209 210 211 212
    ff_amf_write_null(&p);
    ff_amf_write_string(&p, rt->playpath);

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

/**
213
 * Generate 'FCUnpublish' call and send it to the server. It should make
214 215 216 217 218 219 220 221 222 223
 * the server destroy stream.
 */
static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

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

224
    av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
225 226
    p = pkt.data;
    ff_amf_write_string(&p, "FCUnpublish");
227
    ff_amf_write_number(&p, ++rt->nb_invokes);
228 229 230 231 232 233 234
    ff_amf_write_null(&p);
    ff_amf_write_string(&p, rt->playpath);

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

235
/**
236
 * Generate 'createStream' call and send it to the server. It should make
237 238 239 240 241 242 243
 * the server allocate some channel for media streams.
 */
static void gen_create_stream(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

244
    av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
245
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 25);
246 247 248

    p = pkt.data;
    ff_amf_write_string(&p, "createStream");
249
    ff_amf_write_number(&p, ++rt->nb_invokes);
250
    ff_amf_write_null(&p);
251
    rt->create_stream_invoke = rt->nb_invokes;
252 253 254 255 256 257 258

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


/**
259
 * Generate 'deleteStream' call and send it to the server. It should make
260 261 262 263 264 265 266
 * the server remove some channel for media streams.
 */
static void gen_delete_stream(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

267
    av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
268 269 270 271
    ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 34);

    p = pkt.data;
    ff_amf_write_string(&p, "deleteStream");
272
    ff_amf_write_number(&p, ++rt->nb_invokes);
273
    ff_amf_write_null(&p);
274
    ff_amf_write_number(&p, rt->main_channel_id);
275 276 277 278 279 280

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

/**
281
 * Generate 'play' call and send it to the server, then ping the server
282 283 284 285 286 287 288
 * to start actual playing.
 */
static void gen_play(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

289
    av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
290
    ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0,
291
                          29 + strlen(rt->playpath));
292 293 294 295
    pkt.extra = rt->main_channel_id;

    p = pkt.data;
    ff_amf_write_string(&p, "play");
296
    ff_amf_write_number(&p, ++rt->nb_invokes);
297 298
    ff_amf_write_null(&p);
    ff_amf_write_string(&p, rt->playpath);
299
    ff_amf_write_number(&p, rt->live);
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

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

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

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

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

316
/**
317
 * Generate 'publish' call and send it to the server.
318 319 320 321 322 323
 */
static void gen_publish(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

324
    av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
325 326 327 328 329 330
    ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE, 0,
                          30 + strlen(rt->playpath));
    pkt.extra = rt->main_channel_id;

    p = pkt.data;
    ff_amf_write_string(&p, "publish");
331
    ff_amf_write_number(&p, ++rt->nb_invokes);
332 333 334 335 336 337 338 339
    ff_amf_write_null(&p);
    ff_amf_write_string(&p, rt->playpath);
    ff_amf_write_string(&p, "live");

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

340
/**
341
 * Generate ping reply and send it to the server.
342 343 344 345 346 347 348 349 350
 */
static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
{
    RTMPPacket pkt;
    uint8_t *p;

    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING, ppkt->timestamp + 1, 6);
    p = pkt.data;
    bytestream_put_be16(&p, 7);
351
    bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
352 353 354 355
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
    ff_rtmp_packet_destroy(&pkt);
}

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
/**
 * Generate server bandwidth message and send it to the server.
 */
static void gen_server_bw(URLContext *s, RTMPContext *rt)
{
    RTMPPacket pkt;
    uint8_t *p;

    ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW, 0, 4);
    p = pkt.data;
    bytestream_put_be32(&p, 2500000);
    ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
    ff_rtmp_packet_destroy(&pkt);
}

371
/**
372
 * Generate report on bytes read so far and send it to the server.
373 374 375 376 377 378 379 380 381 382 383 384 385
 */
static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
{
    RTMPPacket pkt;
    uint8_t *p;

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

386 387 388 389 390
//TODO: Move HMAC code somewhere. Eventually.
#define HMAC_IPAD_VAL 0x36
#define HMAC_OPAD_VAL 0x5C

/**
391
 * Calculate HMAC-SHA2 digest for RTMP handshake packets.
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
 *
 * @param src    input buffer
 * @param len    input buffer length (should be 1536)
 * @param gap    offset in buffer where 32 bytes should not be taken into account
 *               when calculating digest (since it will be used to store that digest)
 * @param key    digest key
 * @param keylen digest key length
 * @param dst    buffer where calculated digest will be stored (32 bytes)
 */
static void rtmp_calc_digest(const uint8_t *src, int len, int gap,
                             const uint8_t *key, int keylen, uint8_t *dst)
{
    struct AVSHA *sha;
    uint8_t hmac_buf[64+32] = {0};
    int i;

    sha = av_mallocz(av_sha_size);

    if (keylen < 64) {
        memcpy(hmac_buf, key, keylen);
    } else {
        av_sha_init(sha, 256);
        av_sha_update(sha,key, keylen);
        av_sha_final(sha, hmac_buf);
    }
    for (i = 0; i < 64; i++)
        hmac_buf[i] ^= HMAC_IPAD_VAL;

    av_sha_init(sha, 256);
    av_sha_update(sha, hmac_buf, 64);
    if (gap <= 0) {
        av_sha_update(sha, src, len);
    } else { //skip 32 bytes used for storing digest
        av_sha_update(sha, src, gap);
        av_sha_update(sha, src + gap + 32, len - gap - 32);
    }
    av_sha_final(sha, hmac_buf + 64);

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

    av_free(sha);
}

/**
440
 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
 * will be stored) into that packet.
 *
 * @param buf handshake data (1536 bytes)
 * @return offset to the digest inside input data
 */
static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
{
    int i, digest_pos = 0;

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

    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
                     rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
                     buf + digest_pos);
    return digest_pos;
}

/**
461
 * Verify that the received server response has the expected digest value.
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
 *
 * @param buf handshake data received from the server (1536 bytes)
 * @param off position to search digest offset from
 * @return 0 if digest is valid, digest position otherwise
 */
static int rtmp_validate_digest(uint8_t *buf, int off)
{
    int i, digest_pos = 0;
    uint8_t digest[32];

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

    rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
                     rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
                     digest);
    if (!memcmp(digest, buf + digest_pos, 32))
        return digest_pos;
    return 0;
}

/**
485
 * Perform handshake with the server by means of exchanging pseudorandom data
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
 * signed with HMAC-SHA2 digest.
 *
 * @return 0 if handshake succeeds, negative value otherwise
 */
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
{
    AVLFG rnd;
    uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
        3,                // unencrypted data
        0, 0, 0, 0,       // client uptime
        RTMP_CLIENT_VER1,
        RTMP_CLIENT_VER2,
        RTMP_CLIENT_VER3,
        RTMP_CLIENT_VER4,
    };
    uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
    uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
    int i;
    int server_pos, client_pos;
    uint8_t digest[32];

507
    av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
508 509 510 511 512 513 514

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

515
    ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
516
    i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
517
    if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
518
        av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
519 520
        return -1;
    }
521
    i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
522
    if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
523
        av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
524 525 526
        return -1;
    }

527
    av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
528 529
           serverdata[5], serverdata[6], serverdata[7], serverdata[8]);

530
    if (rt->is_input && serverdata[5] >= 3) {
531
        server_pos = rtmp_validate_digest(serverdata + 1, 772);
532
        if (!server_pos) {
533 534
            server_pos = rtmp_validate_digest(serverdata + 1, 8);
            if (!server_pos) {
535
                av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
536 537
                return -1;
            }
538 539
        }

540 541 542 543 544 545 546
        rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
                         rtmp_server_key, sizeof(rtmp_server_key),
                         digest);
        rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE-32, 0,
                         digest, 32,
                         digest);
        if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
547
            av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
548 549
            return -1;
        }
550

551 552 553 554 555 556 557 558 559 560
        for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
            tosend[i] = av_lfg_get(&rnd) >> 24;
        rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
                         rtmp_player_key, sizeof(rtmp_player_key),
                         digest);
        rtmp_calc_digest(tosend,  RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
                         digest, 32,
                         tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);

        // write reply back to the server
561
        ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
562
    } else {
563
        ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
564 565
    }

566 567 568 569
    return 0;
}

/**
570
 * Parse received packet and possibly perform some action depending on
571 572 573 574 575 576 577 578 579
 * the packet contents.
 * @return 0 for no errors, negative values for serious errors which prevent
 *         further communications, positive values for uncritical errors
 */
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
{
    int i, t;
    const uint8_t *data_end = pkt->data + pkt->data_size;

580
#ifdef DEBUG
581
    ff_rtmp_packet_dump(s, pkt);
582 583
#endif

584 585 586
    switch (pkt->type) {
    case RTMP_PT_CHUNK_SIZE:
        if (pkt->data_size != 4) {
587
            av_log(s, AV_LOG_ERROR,
588 589 590
                   "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
            return -1;
        }
591 592
        if (!rt->is_input)
            ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
593 594
        rt->chunk_size = AV_RB32(pkt->data);
        if (rt->chunk_size <= 0) {
595
            av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
596 597
            return -1;
        }
598
        av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
599 600 601 602 603 604
        break;
    case RTMP_PT_PING:
        t = AV_RB16(pkt->data);
        if (t == 6)
            gen_pong(s, rt, pkt);
        break;
605 606
    case RTMP_PT_CLIENT_BW:
        if (pkt->data_size < 4) {
607
            av_log(s, AV_LOG_ERROR,
608 609 610 611
                   "Client bandwidth report packet is less than 4 bytes long (%d)\n",
                   pkt->data_size);
            return -1;
        }
612
        av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
613 614
        rt->client_report_size = AV_RB32(pkt->data) >> 1;
        break;
615 616 617 618 619 620 621
    case RTMP_PT_INVOKE:
        //TODO: check for the messages sent for wrong state?
        if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
            uint8_t tmpstr[256];

            if (!ff_amf_get_field_value(pkt->data + 9, data_end,
                                        "description", tmpstr, sizeof(tmpstr)))
622
                av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
623 624 625 626
            return -1;
        } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
            switch (rt->state) {
            case STATE_HANDSHAKED:
627 628 629 630 631
                if (!rt->is_input) {
                    gen_release_stream(s, rt);
                    gen_fcpublish_stream(s, rt);
                    rt->state = STATE_RELEASING;
                } else {
632
                    gen_server_bw(s, rt);
633 634
                    rt->state = STATE_CONNECTING;
                }
635
                gen_create_stream(s, rt);
636 637
                break;
            case STATE_FCPUBLISH:
638 639
                rt->state = STATE_CONNECTING;
                break;
640 641 642 643 644
            case STATE_RELEASING:
                rt->state = STATE_FCPUBLISH;
                /* hack for Wowza Media Server, it does not send result for
                 * releaseStream and FCPublish calls */
                if (!pkt->data[10]) {
645
                    int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
646
                    if (pkt_id == rt->create_stream_invoke)
647 648
                        rt->state = STATE_CONNECTING;
                }
649
                if (rt->state != STATE_CONNECTING)
650
                    break;
651 652 653
            case STATE_CONNECTING:
                //extract a number from the result
                if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
654
                    av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
655
                } else {
656
                    rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
657
                }
658
                if (rt->is_input) {
659
                    gen_play(s, rt);
660 661 662
                } else {
                    gen_publish(s, rt);
                }
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
                rt->state = STATE_READY;
                break;
            }
        } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
            const uint8_t* ptr = pkt->data + 11;
            uint8_t tmpstr[256];

            for (i = 0; i < 2; i++) {
                t = ff_amf_tag_size(ptr, data_end);
                if (t < 0)
                    return 1;
                ptr += t;
            }
            t = ff_amf_get_field_value(ptr, data_end,
                                       "level", tmpstr, sizeof(tmpstr));
            if (!t && !strcmp(tmpstr, "error")) {
                if (!ff_amf_get_field_value(ptr, data_end,
                                            "description", tmpstr, sizeof(tmpstr)))
681
                    av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
682 683 684 685
                return -1;
            }
            t = ff_amf_get_field_value(ptr, data_end,
                                       "code", tmpstr, sizeof(tmpstr));
686
            if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
687 688
            if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
            if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
689
            if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
690 691 692 693 694 695 696
        }
        break;
    }
    return 0;
}

/**
697
 * Interact with the server by receiving and sending RTMP packets until
698 699 700
 * there is some significant data (media data or expected status notification).
 *
 * @param s          reading context
701 702 703 704
 * @param for_header non-zero value tells function to work until it
 * gets notification from the server that playing has been started,
 * otherwise function will work until some media data is received (or
 * an error happens)
705 706 707 708 709 710
 * @return 0 for successful operation, negative value in case of error
 */
static int get_packet(URLContext *s, int for_header)
{
    RTMPContext *rt = s->priv_data;
    int ret;
711 712 713 714
    uint8_t *p;
    const uint8_t *next;
    uint32_t data_size;
    uint32_t ts, cts, pts=0;
715

716 717 718
    if (rt->state == STATE_STOPPED)
        return AVERROR_EOF;

719
    for (;;) {
720
        RTMPPacket rpkt = { 0 };
721
        if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
722
                                       rt->chunk_size, rt->prev_pkt[0])) <= 0) {
723
            if (ret == 0) {
724 725 726 727 728
                return AVERROR(EAGAIN);
            } else {
                return AVERROR(EIO);
            }
        }
729 730
        rt->bytes_read += ret;
        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
731
            av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
732 733 734
            gen_bytes_read(s, rt, rpkt.timestamp + 1);
            rt->last_bytes_read = rt->bytes_read;
        }
735 736 737 738 739 740

        ret = rtmp_parse_result(s, rt, &rpkt);
        if (ret < 0) {//serious error in current packet
            ff_rtmp_packet_destroy(&rpkt);
            return -1;
        }
741 742 743 744
        if (rt->state == STATE_STOPPED) {
            ff_rtmp_packet_destroy(&rpkt);
            return AVERROR_EOF;
        }
745
        if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
746 747 748
            ff_rtmp_packet_destroy(&rpkt);
            return 0;
        }
749
        if (!rpkt.data_size || !rt->is_input) {
750 751 752 753
            ff_rtmp_packet_destroy(&rpkt);
            continue;
        }
        if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
754
           (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
755
            ts = rpkt.timestamp;
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774

            // generate packet header and put data into buffer for FLV demuxer
            rt->flv_off  = 0;
            rt->flv_size = rpkt.data_size + 15;
            rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
            bytestream_put_byte(&p, rpkt.type);
            bytestream_put_be24(&p, rpkt.data_size);
            bytestream_put_be24(&p, ts);
            bytestream_put_byte(&p, ts >> 24);
            bytestream_put_be24(&p, 0);
            bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
            bytestream_put_be32(&p, 0);
            ff_rtmp_packet_destroy(&rpkt);
            return 0;
        } else if (rpkt.type == RTMP_PT_METADATA) {
            // we got raw FLV data, make it available for FLV demuxer
            rt->flv_off  = 0;
            rt->flv_size = rpkt.data_size;
            rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
775 776 777 778 779 780 781 782
            /* rewrite timestamps */
            next = rpkt.data;
            ts = rpkt.timestamp;
            while (next - rpkt.data < rpkt.data_size - 11) {
                next++;
                data_size = bytestream_get_be24(&next);
                p=next;
                cts = bytestream_get_be24(&next);
783
                cts |= bytestream_get_byte(&next) << 24;
784 785 786 787 788 789 790 791
                if (pts==0)
                    pts=cts;
                ts += cts - pts;
                pts = cts;
                bytestream_put_be24(&p, ts);
                bytestream_put_byte(&p, ts >> 24);
                next += data_size + 3 + 4;
            }
792 793 794 795 796 797 798 799 800 801 802 803
            memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
            ff_rtmp_packet_destroy(&rpkt);
            return 0;
        }
        ff_rtmp_packet_destroy(&rpkt);
    }
}

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

804
    if (!rt->is_input) {
805 806 807
        rt->flv_data = NULL;
        if (rt->out_pkt.data_size)
            ff_rtmp_packet_destroy(&rt->out_pkt);
808 809
        if (rt->state > STATE_FCPUBLISH)
            gen_fcunpublish_stream(h, rt);
810
    }
811 812
    if (rt->state > STATE_HANDSHAKED)
        gen_delete_stream(h, rt);
813

814
    av_freep(&rt->flv_data);
815
    ffurl_close(rt->stream);
816 817 818 819
    return 0;
}

/**
820
 * Open RTMP connection and verify that the stream can be played.
821 822 823 824 825 826 827 828 829
 *
 * URL syntax: rtmp://server[:port][/app][/playpath]
 *             where 'app' is first one or two directories in the path
 *             (e.g. /ondemand/, /flash/live/, etc.)
 *             and 'playpath' is a file name (the rest of the path,
 *             may be prefixed with "mp4:")
 */
static int rtmp_open(URLContext *s, const char *uri, int flags)
{
830
    RTMPContext *rt = s->priv_data;
831
    char proto[8], hostname[256], path[1024], *fname;
832
    char *old_app;
833
    uint8_t buf[2048];
834
    int port;
835 836
    int ret;

837
    rt->is_input = !(flags & AVIO_FLAG_WRITE);
838

Måns Rullgård's avatar
Måns Rullgård committed
839
    av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
Martin Storsjö's avatar
Martin Storsjö committed
840
                 path, sizeof(path), s->filename);
841 842 843

    if (port < 0)
        port = RTMP_DEFAULT_PORT;
844
    ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
845

846
    if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
847
                   &s->interrupt_callback, NULL) < 0) {
848
        av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
849
        goto fail;
850
    }
851

852 853
    rt->state = STATE_START;
    if (rtmp_handshake(s, rt))
854
        goto fail;
855

856 857
    rt->chunk_size = 128;
    rt->state = STATE_HANDSHAKED;
858 859 860 861 862 863 864 865 866 867

    // Keep the application name when it has been defined by the user.
    old_app = rt->app;

    rt->app = av_malloc(APP_MAX_LENGTH);
    if (!rt->app) {
        rtmp_close(s);
        return AVERROR(ENOMEM);
    }

868 869 870 871 872 873 874 875 876
    //extract "app" part from path
    if (!strncmp(path, "/ondemand/", 10)) {
        fname = path + 10;
        memcpy(rt->app, "ondemand", 9);
    } else {
        char *p = strchr(path + 1, '/');
        if (!p) {
            fname = path + 1;
            rt->app[0] = '\0';
877
        } else {
878 879 880 881 882
            char *c = strchr(p + 1, ':');
            fname = strchr(p + 1, '/');
            if (!fname || c < fname) {
                fname = p + 1;
                av_strlcpy(rt->app, path + 1, p - path);
883
            } else {
884 885
                fname++;
                av_strlcpy(rt->app, path + 1, fname - path - 1);
886 887
            }
        }
888
    }
889 890 891 892 893 894 895

    if (old_app) {
        // The name of application has been defined by the user, override it.
        av_free(rt->app);
        rt->app = old_app;
    }

896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
    if (!rt->playpath) {
        rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
        if (!rt->playpath) {
            rtmp_close(s);
            return AVERROR(ENOMEM);
        }

        if (!strchr(fname, ':') &&
            (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
             !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
            memcpy(rt->playpath, "mp4:", 5);
        } else {
            rt->playpath[0] = 0;
        }
        strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
911
    }
912

913 914 915 916
    rt->client_report_size = 1048576;
    rt->bytes_read = 0;
    rt->last_bytes_read = 0;

917
    av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
918 919
           proto, path, rt->app, rt->playpath);
    gen_connect(s, rt, proto, hostname, port);
920

921 922 923 924 925
    do {
        ret = get_packet(s, 1);
    } while (ret == EAGAIN);
    if (ret < 0)
        goto fail;
926 927

    if (rt->is_input) {
928 929 930 931 932
        // generate FLV header for demuxer
        rt->flv_size = 13;
        rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
        rt->flv_off  = 0;
        memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
933 934 935 936
    } else {
        rt->flv_size = 0;
        rt->flv_data = NULL;
        rt->flv_off  = 0;
937
        rt->skip_bytes = 13;
938 939
    }

940
    s->max_packet_size = rt->stream->max_packet_size;
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
    s->is_streamed     = 1;
    return 0;

fail:
    rtmp_close(s);
    return AVERROR(EIO);
}

static int rtmp_read(URLContext *s, uint8_t *buf, int size)
{
    RTMPContext *rt = s->priv_data;
    int orig_size = size;
    int ret;

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

        if (data_left >= size) {
            memcpy(buf, rt->flv_data + rt->flv_off, size);
            rt->flv_off += size;
            return orig_size;
        }
        if (data_left > 0) {
            memcpy(buf, rt->flv_data + rt->flv_off, data_left);
            buf  += data_left;
            size -= data_left;
            rt->flv_off = rt->flv_size;
968
            return data_left;
969 970 971 972 973 974 975
        }
        if ((ret = get_packet(s, 0)) < 0)
           return ret;
    }
    return orig_size;
}

976
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
977
{
978
    RTMPContext *rt = s->priv_data;
979 980 981 982 983 984
    int size_temp = size;
    int pktsize, pkttype;
    uint32_t ts;
    const uint8_t *buf_temp = buf;

    do {
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
        if (rt->skip_bytes) {
            int skip = FFMIN(rt->skip_bytes, size_temp);
            buf_temp       += skip;
            size_temp      -= skip;
            rt->skip_bytes -= skip;
            continue;
        }

        if (rt->flv_header_bytes < 11) {
            const uint8_t *header = rt->flv_header;
            int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
            bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
            rt->flv_header_bytes += copy;
            size_temp            -= copy;
            if (rt->flv_header_bytes < 11)
                break;
1001

1002 1003 1004 1005 1006
            pkttype = bytestream_get_byte(&header);
            pktsize = bytestream_get_be24(&header);
            ts = bytestream_get_be24(&header);
            ts |= bytestream_get_byte(&header) << 24;
            bytestream_get_be24(&header);
1007 1008 1009 1010