Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * RTMP network protocol
3
 * Copyright (c) 2009 Konstantin 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
24
 * RTMP protocol
25
 */
26
 
27
#include "libavcodec/bytestream.h"
28
#include "libavutil/avstring.h"
29
#include "libavutil/base64.h"
30
#include "libavutil/intfloat.h"
31
#include "libavutil/lfg.h"
32
#include "libavutil/md5.h"
33
#include "libavutil/opt.h"
34
#include "libavutil/random_seed.h"
35
#include "libavutil/sha.h"
36
#include "avformat.h"
37
#include "internal.h"
38
 
39
#include "network.h"
40
 
41
#include "flv.h"
42
#include "rtmp.h"
43
#include "rtmpcrypt.h"
44
#include "rtmppkt.h"
45
#include "url.h"
46
 
47
#if CONFIG_ZLIB
48
#include 
49
#endif
50
 
51
#define APP_MAX_LENGTH 1024
52
#define PLAYPATH_MAX_LENGTH 256
53
#define TCURL_MAX_LENGTH 512
54
#define FLASHVER_MAX_LENGTH 64
55
#define RTMP_PKTDATA_DEFAULT_SIZE 4096
56
#define RTMP_HEADER 11
57
 
58
/** RTMP protocol handler state */
59
typedef enum {
60
    STATE_START,      ///< client has not done anything yet
61
    STATE_HANDSHAKED, ///< client has performed handshake
62
    STATE_FCPUBLISH,  ///< client FCPublishing stream (for output)
63
    STATE_PLAYING,    ///< client has started receiving multimedia data from server
64
    STATE_SEEKING,    ///< client has started the seek operation. Back on STATE_PLAYING when the time comes
65
    STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output)
66
    STATE_RECEIVING,  ///< received a publish command (for input)
67
    STATE_SENDING,    ///< received a play command (for output)
68
    STATE_STOPPED,    ///< the broadcast has been stopped
69
} ClientState;
70
 
71
typedef struct TrackedMethod {
72
    char *name;
73
    int id;
74
} TrackedMethod;
75
 
76
/** protocol handler context */
77
typedef struct RTMPContext {
78
    const AVClass *class;
79
    URLContext*   stream;                     ///< TCP stream used in interactions with RTMP server
80
    RTMPPacket    *prev_pkt[2];               ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
81
    int           nb_prev_pkt[2];             ///< number of elements in prev_pkt
82
    int           in_chunk_size;              ///< size of the chunks incoming RTMP packets are divided into
83
    int           out_chunk_size;             ///< size of the chunks outgoing RTMP packets are divided into
84
    int           is_input;                   ///< input/output flag
85
    char          *playpath;                  ///< stream identifier to play (with possible "mp4:" prefix)
86
    int           live;                       ///< 0: recorded, -1: live, -2: both
87
    char          *app;                       ///< name of application
88
    char          *conn;                      ///< append arbitrary AMF data to the Connect message
89
    ClientState   state;                      ///< current state
90
    int           stream_id;                  ///< ID assigned by the server for the stream
91
    uint8_t*      flv_data;                   ///< buffer with data for demuxer
92
    int           flv_size;                   ///< current buffer size
93
    int           flv_off;                    ///< number of bytes read from current buffer
94
    int           flv_nb_packets;             ///< number of flv packets published
95
    RTMPPacket    out_pkt;                    ///< rtmp packet, created from flv a/v or metadata (for output)
96
    uint32_t      client_report_size;         ///< number of bytes after which client should report to server
97
    uint32_t      bytes_read;                 ///< number of bytes read from server
98
    uint32_t      last_bytes_read;            ///< number of bytes read last reported to server
99
    int           skip_bytes;                 ///< number of bytes to skip from the input FLV stream in the next write call
100
    uint8_t       flv_header[RTMP_HEADER];    ///< partial incoming flv packet header
101
    int           flv_header_bytes;           ///< number of initialized bytes in flv_header
102
    int           nb_invokes;                 ///< keeps track of invoke messages
103
    char*         tcurl;                      ///< url of the target stream
104
    char*         flashver;                   ///< version of the flash plugin
105
    char*         swfhash;                    ///< SHA256 hash of the decompressed SWF file (32 bytes)
106
    int           swfhash_len;                ///< length of the SHA256 hash
107
    int           swfsize;                    ///< size of the decompressed SWF file
108
    char*         swfurl;                     ///< url of the swf player
109
    char*         swfverify;                  ///< URL to player swf file, compute hash/size automatically
110
    char          swfverification[42];        ///< hash of the SWF verification
111
    char*         pageurl;                    ///< url of the web page
112
    char*         subscribe;                  ///< name of live stream to subscribe
113
    int           server_bw;                  ///< server bandwidth
114
    int           client_buffer_time;         ///< client buffer time in ms
115
    int           flush_interval;             ///< number of packets flushed in the same request (RTMPT only)
116
    int           encrypted;                  ///< use an encrypted connection (RTMPE only)
117
    TrackedMethod*tracked_methods;            ///< tracked methods buffer
118
    int           nb_tracked_methods;         ///< number of tracked methods
119
    int           tracked_methods_size;       ///< size of the tracked methods buffer
120
    int           listen;                     ///< listen mode flag
121
    int           listen_timeout;             ///< listen timeout to wait for new connections
122
    int           nb_streamid;                ///< The next stream id to return on createStream calls
123
    char          username[50];
124
    char          password[50];
125
    char          auth_params[500];
126
    int           do_reconnect;
127
    int           auth_tried;
128
} RTMPContext;
129
 
130
#define PLAYER_KEY_OPEN_PART_LEN 30   ///< length of partial key used for first client digest signing
131
/** Client key used for digest signing */
132
static const uint8_t rtmp_player_key[] = {
133
    'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
134
    'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
135
 
136
    0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
137
    0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
138
    0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
139
};
140
 
141
#define SERVER_KEY_OPEN_PART_LEN 36   ///< length of partial key used for first server digest signing
142
/** Key used for RTMP server digest signing */
143
static const uint8_t rtmp_server_key[] = {
144
    'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
145
    'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
146
    'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
147
 
148
    0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
149
    0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
150
    0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
151
};
152
 
153
static int add_tracked_method(RTMPContext *rt, const char *name, int id)
154
{
155
    int err;
156
 
157
    if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) {
158
        rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2;
159
        if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size *
160
                               sizeof(*rt->tracked_methods))) < 0) {
161
            rt->nb_tracked_methods = 0;
162
            rt->tracked_methods_size = 0;
163
            return err;
164
        }
165
    }
166
 
167
    rt->tracked_methods[rt->nb_tracked_methods].name = av_strdup(name);
168
    if (!rt->tracked_methods[rt->nb_tracked_methods].name)
169
        return AVERROR(ENOMEM);
170
    rt->tracked_methods[rt->nb_tracked_methods].id = id;
171
    rt->nb_tracked_methods++;
172
 
173
    return 0;
174
}
175
 
176
static void del_tracked_method(RTMPContext *rt, int index)
177
{
178
    memmove(&rt->tracked_methods[index], &rt->tracked_methods[index + 1],
179
            sizeof(*rt->tracked_methods) * (rt->nb_tracked_methods - index - 1));
180
    rt->nb_tracked_methods--;
181
}
182
 
183
static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset,
184
                               char **tracked_method)
185
{
186
    RTMPContext *rt = s->priv_data;
187
    GetByteContext gbc;
188
    double pkt_id;
189
    int ret;
190
    int i;
191
 
192
    bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset);
193
    if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
194
        return ret;
195
 
196
    for (i = 0; i < rt->nb_tracked_methods; i++) {
197
        if (rt->tracked_methods[i].id != pkt_id)
198
            continue;
199
 
200
        *tracked_method = rt->tracked_methods[i].name;
201
        del_tracked_method(rt, i);
202
        break;
203
    }
204
 
205
    return 0;
206
}
207
 
208
static void free_tracked_methods(RTMPContext *rt)
209
{
210
    int i;
211
 
212
    for (i = 0; i < rt->nb_tracked_methods; i ++)
213
        av_free(rt->tracked_methods[i].name);
214
    av_free(rt->tracked_methods);
215
    rt->tracked_methods      = NULL;
216
    rt->tracked_methods_size = 0;
217
    rt->nb_tracked_methods   = 0;
218
}
219
 
220
static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
221
{
222
    int ret;
223
 
224
    if (pkt->type == RTMP_PT_INVOKE && track) {
225
        GetByteContext gbc;
226
        char name[128];
227
        double pkt_id;
228
        int len;
229
 
230
        bytestream2_init(&gbc, pkt->data, pkt->size);
231
        if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0)
232
            goto fail;
233
 
234
        if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0)
235
            goto fail;
236
 
237
        if ((ret = add_tracked_method(rt, name, pkt_id)) < 0)
238
            goto fail;
239
    }
240
 
241
    ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
242
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
243
fail:
244
    ff_rtmp_packet_destroy(pkt);
245
    return ret;
246
}
247
 
248
static int rtmp_write_amf_data(URLContext *s, char *param, uint8_t **p)
249
{
250
    char *field, *value;
251
    char type;
252
 
253
    /* The type must be B for Boolean, N for number, S for string, O for
254
     * object, or Z for null. For Booleans the data must be either 0 or 1 for
255
     * FALSE or TRUE, respectively. Likewise for Objects the data must be
256
     * 0 or 1 to end or begin an object, respectively. Data items in subobjects
257
     * may be named, by prefixing the type with 'N' and specifying the name
258
     * before the value (ie. NB:myFlag:1). This option may be used multiple times
259
     * to construct arbitrary AMF sequences. */
260
    if (param[0] && param[1] == ':') {
261
        type = param[0];
262
        value = param + 2;
263
    } else if (param[0] == 'N' && param[1] && param[2] == ':') {
264
        type = param[1];
265
        field = param + 3;
266
        value = strchr(field, ':');
267
        if (!value)
268
            goto fail;
269
        *value = '\0';
270
        value++;
271
 
272
        ff_amf_write_field_name(p, field);
273
    } else {
274
        goto fail;
275
    }
276
 
277
    switch (type) {
278
    case 'B':
279
        ff_amf_write_bool(p, value[0] != '0');
280
        break;
281
    case 'S':
282
        ff_amf_write_string(p, value);
283
        break;
284
    case 'N':
285
        ff_amf_write_number(p, strtod(value, NULL));
286
        break;
287
    case 'Z':
288
        ff_amf_write_null(p);
289
        break;
290
    case 'O':
291
        if (value[0] != '0')
292
            ff_amf_write_object_start(p);
293
        else
294
            ff_amf_write_object_end(p);
295
        break;
296
    default:
297
        goto fail;
298
        break;
299
    }
300
 
301
    return 0;
302
 
303
fail:
304
    av_log(s, AV_LOG_ERROR, "Invalid AMF parameter: %s\n", param);
305
    return AVERROR(EINVAL);
306
}
307
 
308
/**
309
 * Generate 'connect' call and send it to the server.
310
 */
311
static int gen_connect(URLContext *s, RTMPContext *rt)
312
{
313
    RTMPPacket pkt;
314
    uint8_t *p;
315
    int ret;
316
 
317
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
318
                                     0, 4096 + APP_MAX_LENGTH)) < 0)
319
        return ret;
320
 
321
    p = pkt.data;
322
 
323
    ff_amf_write_string(&p, "connect");
324
    ff_amf_write_number(&p, ++rt->nb_invokes);
325
    ff_amf_write_object_start(&p);
326
    ff_amf_write_field_name(&p, "app");
327
    ff_amf_write_string2(&p, rt->app, rt->auth_params);
328
 
329
    if (!rt->is_input) {
330
        ff_amf_write_field_name(&p, "type");
331
        ff_amf_write_string(&p, "nonprivate");
332
    }
333
    ff_amf_write_field_name(&p, "flashVer");
334
    ff_amf_write_string(&p, rt->flashver);
335
 
336
    if (rt->swfurl) {
337
        ff_amf_write_field_name(&p, "swfUrl");
338
        ff_amf_write_string(&p, rt->swfurl);
339
    }
340
 
341
    ff_amf_write_field_name(&p, "tcUrl");
342
    ff_amf_write_string2(&p, rt->tcurl, rt->auth_params);
343
    if (rt->is_input) {
344
        ff_amf_write_field_name(&p, "fpad");
345
        ff_amf_write_bool(&p, 0);
346
        ff_amf_write_field_name(&p, "capabilities");
347
        ff_amf_write_number(&p, 15.0);
348
 
349
        /* Tell the server we support all the audio codecs except
350
         * SUPPORT_SND_INTEL (0x0008) and SUPPORT_SND_UNUSED (0x0010)
351
         * which are unused in the RTMP protocol implementation. */
352
        ff_amf_write_field_name(&p, "audioCodecs");
353
        ff_amf_write_number(&p, 4071.0);
354
        ff_amf_write_field_name(&p, "videoCodecs");
355
        ff_amf_write_number(&p, 252.0);
356
        ff_amf_write_field_name(&p, "videoFunction");
357
        ff_amf_write_number(&p, 1.0);
358
 
359
        if (rt->pageurl) {
360
            ff_amf_write_field_name(&p, "pageUrl");
361
            ff_amf_write_string(&p, rt->pageurl);
362
        }
363
    }
364
    ff_amf_write_object_end(&p);
365
 
366
    if (rt->conn) {
367
        char *param = rt->conn;
368
 
369
        // Write arbitrary AMF data to the Connect message.
370
        while (param != NULL) {
371
            char *sep;
372
            param += strspn(param, " ");
373
            if (!*param)
374
                break;
375
            sep = strchr(param, ' ');
376
            if (sep)
377
                *sep = '\0';
378
            if ((ret = rtmp_write_amf_data(s, param, &p)) < 0) {
379
                // Invalid AMF parameter.
380
                ff_rtmp_packet_destroy(&pkt);
381
                return ret;
382
            }
383
 
384
            if (sep)
385
                param = sep + 1;
386
            else
387
                break;
388
        }
389
    }
390
 
391
    pkt.size = p - pkt.data;
392
 
393
    return rtmp_send_packet(rt, &pkt, 1);
394
}
395
 
396
static int read_connect(URLContext *s, RTMPContext *rt)
397
{
398
    RTMPPacket pkt = { 0 };
399
    uint8_t *p;
400
    const uint8_t *cp;
401
    int ret;
402
    char command[64];
403
    int stringlen;
404
    double seqnum;
405
    uint8_t tmpstr[256];
406
    GetByteContext gbc;
407
 
408
    if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
409
                                   &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
410
        return ret;
411
    cp = pkt.data;
412
    bytestream2_init(&gbc, cp, pkt.size);
413
    if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) {
414
        av_log(s, AV_LOG_ERROR, "Unable to read command string\n");
415
        ff_rtmp_packet_destroy(&pkt);
416
        return AVERROR_INVALIDDATA;
417
    }
418
    if (strcmp(command, "connect")) {
419
        av_log(s, AV_LOG_ERROR, "Expecting connect, got %s\n", command);
420
        ff_rtmp_packet_destroy(&pkt);
421
        return AVERROR_INVALIDDATA;
422
    }
423
    ret = ff_amf_read_number(&gbc, &seqnum);
424
    if (ret)
425
        av_log(s, AV_LOG_WARNING, "SeqNum not found\n");
426
    /* Here one could parse an AMF Object with data as flashVers and others. */
427
    ret = ff_amf_get_field_value(gbc.buffer,
428
                                 gbc.buffer + bytestream2_get_bytes_left(&gbc),
429
                                 "app", tmpstr, sizeof(tmpstr));
430
    if (ret)
431
        av_log(s, AV_LOG_WARNING, "App field not found in connect\n");
432
    if (!ret && strcmp(tmpstr, rt->app))
433
        av_log(s, AV_LOG_WARNING, "App field don't match up: %s <-> %s\n",
434
               tmpstr, rt->app);
435
    ff_rtmp_packet_destroy(&pkt);
436
 
437
    // Send Window Acknowledgement Size (as defined in speficication)
438
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
439
                                     RTMP_PT_SERVER_BW, 0, 4)) < 0)
440
        return ret;
441
    p = pkt.data;
442
    bytestream_put_be32(&p, rt->server_bw);
443
    pkt.size = p - pkt.data;
444
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
445
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
446
    ff_rtmp_packet_destroy(&pkt);
447
    if (ret < 0)
448
        return ret;
449
    // Send Peer Bandwidth
450
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
451
                                     RTMP_PT_CLIENT_BW, 0, 5)) < 0)
452
        return ret;
453
    p = pkt.data;
454
    bytestream_put_be32(&p, rt->server_bw);
455
    bytestream_put_byte(&p, 2); // dynamic
456
    pkt.size = p - pkt.data;
457
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
458
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
459
    ff_rtmp_packet_destroy(&pkt);
460
    if (ret < 0)
461
        return ret;
462
 
463
    // Ping request
464
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
465
                                     RTMP_PT_PING, 0, 6)) < 0)
466
        return ret;
467
 
468
    p = pkt.data;
469
    bytestream_put_be16(&p, 0); // 0 -> Stream Begin
470
    bytestream_put_be32(&p, 0);
471
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
472
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
473
    ff_rtmp_packet_destroy(&pkt);
474
    if (ret < 0)
475
        return ret;
476
 
477
    // Chunk size
478
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
479
                                     RTMP_PT_CHUNK_SIZE, 0, 4)) < 0)
480
        return ret;
481
 
482
    p = pkt.data;
483
    bytestream_put_be32(&p, rt->out_chunk_size);
484
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
485
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
486
    ff_rtmp_packet_destroy(&pkt);
487
    if (ret < 0)
488
        return ret;
489
 
490
    // Send result_ NetConnection.Connect.Success to connect
491
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
492
                                     RTMP_PT_INVOKE, 0,
493
                                     RTMP_PKTDATA_DEFAULT_SIZE)) < 0)
494
        return ret;
495
 
496
    p = pkt.data;
497
    ff_amf_write_string(&p, "_result");
498
    ff_amf_write_number(&p, seqnum);
499
 
500
    ff_amf_write_object_start(&p);
501
    ff_amf_write_field_name(&p, "fmsVer");
502
    ff_amf_write_string(&p, "FMS/3,0,1,123");
503
    ff_amf_write_field_name(&p, "capabilities");
504
    ff_amf_write_number(&p, 31);
505
    ff_amf_write_object_end(&p);
506
 
507
    ff_amf_write_object_start(&p);
508
    ff_amf_write_field_name(&p, "level");
509
    ff_amf_write_string(&p, "status");
510
    ff_amf_write_field_name(&p, "code");
511
    ff_amf_write_string(&p, "NetConnection.Connect.Success");
512
    ff_amf_write_field_name(&p, "description");
513
    ff_amf_write_string(&p, "Connection succeeded.");
514
    ff_amf_write_field_name(&p, "objectEncoding");
515
    ff_amf_write_number(&p, 0);
516
    ff_amf_write_object_end(&p);
517
 
518
    pkt.size = p - pkt.data;
519
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
520
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
521
    ff_rtmp_packet_destroy(&pkt);
522
    if (ret < 0)
523
        return ret;
524
 
525
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL,
526
                                     RTMP_PT_INVOKE, 0, 30)) < 0)
527
        return ret;
528
    p = pkt.data;
529
    ff_amf_write_string(&p, "onBWDone");
530
    ff_amf_write_number(&p, 0);
531
    ff_amf_write_null(&p);
532
    ff_amf_write_number(&p, 8192);
533
    pkt.size = p - pkt.data;
534
    ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
535
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
536
    ff_rtmp_packet_destroy(&pkt);
537
 
538
    return ret;
539
}
540
 
541
/**
542
 * Generate 'releaseStream' call and send it to the server. It should make
543
 * the server release some channel for media streams.
544
 */
545
static int gen_release_stream(URLContext *s, RTMPContext *rt)
546
{
547
    RTMPPacket pkt;
548
    uint8_t *p;
549
    int ret;
550
 
551
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
552
                                     0, 29 + strlen(rt->playpath))) < 0)
553
        return ret;
554
 
555
    av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
556
    p = pkt.data;
557
    ff_amf_write_string(&p, "releaseStream");
558
    ff_amf_write_number(&p, ++rt->nb_invokes);
559
    ff_amf_write_null(&p);
560
    ff_amf_write_string(&p, rt->playpath);
561
 
562
    return rtmp_send_packet(rt, &pkt, 1);
563
}
564
 
565
/**
566
 * Generate 'FCPublish' call and send it to the server. It should make
567
 * the server preapare for receiving media streams.
568
 */
569
static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
570
{
571
    RTMPPacket pkt;
572
    uint8_t *p;
573
    int ret;
574
 
575
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
576
                                     0, 25 + strlen(rt->playpath))) < 0)
577
        return ret;
578
 
579
    av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
580
    p = pkt.data;
581
    ff_amf_write_string(&p, "FCPublish");
582
    ff_amf_write_number(&p, ++rt->nb_invokes);
583
    ff_amf_write_null(&p);
584
    ff_amf_write_string(&p, rt->playpath);
585
 
586
    return rtmp_send_packet(rt, &pkt, 1);
587
}
588
 
589
/**
590
 * Generate 'FCUnpublish' call and send it to the server. It should make
591
 * the server destroy stream.
592
 */
593
static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
594
{
595
    RTMPPacket pkt;
596
    uint8_t *p;
597
    int ret;
598
 
599
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
600
                                     0, 27 + strlen(rt->playpath))) < 0)
601
        return ret;
602
 
603
    av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
604
    p = pkt.data;
605
    ff_amf_write_string(&p, "FCUnpublish");
606
    ff_amf_write_number(&p, ++rt->nb_invokes);
607
    ff_amf_write_null(&p);
608
    ff_amf_write_string(&p, rt->playpath);
609
 
610
    return rtmp_send_packet(rt, &pkt, 0);
611
}
612
 
613
/**
614
 * Generate 'createStream' call and send it to the server. It should make
615
 * the server allocate some channel for media streams.
616
 */
617
static int gen_create_stream(URLContext *s, RTMPContext *rt)
618
{
619
    RTMPPacket pkt;
620
    uint8_t *p;
621
    int ret;
622
 
623
    av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
624
 
625
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
626
                                     0, 25)) < 0)
627
        return ret;
628
 
629
    p = pkt.data;
630
    ff_amf_write_string(&p, "createStream");
631
    ff_amf_write_number(&p, ++rt->nb_invokes);
632
    ff_amf_write_null(&p);
633
 
634
    return rtmp_send_packet(rt, &pkt, 1);
635
}
636
 
637
 
638
/**
639
 * Generate 'deleteStream' call and send it to the server. It should make
640
 * the server remove some channel for media streams.
641
 */
642
static int gen_delete_stream(URLContext *s, RTMPContext *rt)
643
{
644
    RTMPPacket pkt;
645
    uint8_t *p;
646
    int ret;
647
 
648
    av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
649
 
650
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
651
                                     0, 34)) < 0)
652
        return ret;
653
 
654
    p = pkt.data;
655
    ff_amf_write_string(&p, "deleteStream");
656
    ff_amf_write_number(&p, ++rt->nb_invokes);
657
    ff_amf_write_null(&p);
658
    ff_amf_write_number(&p, rt->stream_id);
659
 
660
    return rtmp_send_packet(rt, &pkt, 0);
661
}
662
 
663
/**
664
 * Generate client buffer time and send it to the server.
665
 */
666
static int gen_buffer_time(URLContext *s, RTMPContext *rt)
667
{
668
    RTMPPacket pkt;
669
    uint8_t *p;
670
    int ret;
671
 
672
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
673
                                     1, 10)) < 0)
674
        return ret;
675
 
676
    p = pkt.data;
677
    bytestream_put_be16(&p, 3);
678
    bytestream_put_be32(&p, rt->stream_id);
679
    bytestream_put_be32(&p, rt->client_buffer_time);
680
 
681
    return rtmp_send_packet(rt, &pkt, 0);
682
}
683
 
684
/**
685
 * Generate 'play' call and send it to the server, then ping the server
686
 * to start actual playing.
687
 */
688
static int gen_play(URLContext *s, RTMPContext *rt)
689
{
690
    RTMPPacket pkt;
691
    uint8_t *p;
692
    int ret;
693
 
694
    av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
695
 
696
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
697
                                     0, 29 + strlen(rt->playpath))) < 0)
698
        return ret;
699
 
700
    pkt.extra = rt->stream_id;
701
 
702
    p = pkt.data;
703
    ff_amf_write_string(&p, "play");
704
    ff_amf_write_number(&p, ++rt->nb_invokes);
705
    ff_amf_write_null(&p);
706
    ff_amf_write_string(&p, rt->playpath);
707
    ff_amf_write_number(&p, rt->live * 1000);
708
 
709
    return rtmp_send_packet(rt, &pkt, 1);
710
}
711
 
712
static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp)
713
{
714
    RTMPPacket pkt;
715
    uint8_t *p;
716
    int ret;
717
 
718
    av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n",
719
           timestamp);
720
 
721
    if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0)
722
        return ret;
723
 
724
    pkt.extra = rt->stream_id;
725
 
726
    p = pkt.data;
727
    ff_amf_write_string(&p, "seek");
728
    ff_amf_write_number(&p, 0); //no tracking back responses
729
    ff_amf_write_null(&p); //as usual, the first null param
730
    ff_amf_write_number(&p, timestamp); //where we want to jump
731
 
732
    return rtmp_send_packet(rt, &pkt, 1);
733
}
734
 
735
/**
736
 * Generate 'publish' call and send it to the server.
737
 */
738
static int gen_publish(URLContext *s, RTMPContext *rt)
739
{
740
    RTMPPacket pkt;
741
    uint8_t *p;
742
    int ret;
743
 
744
    av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
745
 
746
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
747
                                     0, 30 + strlen(rt->playpath))) < 0)
748
        return ret;
749
 
750
    pkt.extra = rt->stream_id;
751
 
752
    p = pkt.data;
753
    ff_amf_write_string(&p, "publish");
754
    ff_amf_write_number(&p, ++rt->nb_invokes);
755
    ff_amf_write_null(&p);
756
    ff_amf_write_string(&p, rt->playpath);
757
    ff_amf_write_string(&p, "live");
758
 
759
    return rtmp_send_packet(rt, &pkt, 1);
760
}
761
 
762
/**
763
 * Generate ping reply and send it to the server.
764
 */
765
static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
766
{
767
    RTMPPacket pkt;
768
    uint8_t *p;
769
    int ret;
770
 
771
    if (ppkt->size < 6) {
772
        av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
773
               ppkt->size);
774
        return AVERROR_INVALIDDATA;
775
    }
776
 
777
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
778
                                     ppkt->timestamp + 1, 6)) < 0)
779
        return ret;
780
 
781
    p = pkt.data;
782
    bytestream_put_be16(&p, 7);
783
    bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
784
 
785
    return rtmp_send_packet(rt, &pkt, 0);
786
}
787
 
788
/**
789
 * Generate SWF verification message and send it to the server.
790
 */
791
static int gen_swf_verification(URLContext *s, RTMPContext *rt)
792
{
793
    RTMPPacket pkt;
794
    uint8_t *p;
795
    int ret;
796
 
797
    av_log(s, AV_LOG_DEBUG, "Sending SWF verification...\n");
798
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
799
                                     0, 44)) < 0)
800
        return ret;
801
 
802
    p = pkt.data;
803
    bytestream_put_be16(&p, 27);
804
    memcpy(p, rt->swfverification, 42);
805
 
806
    return rtmp_send_packet(rt, &pkt, 0);
807
}
808
 
809
/**
810
 * Generate server bandwidth message and send it to the server.
811
 */
812
static int gen_server_bw(URLContext *s, RTMPContext *rt)
813
{
814
    RTMPPacket pkt;
815
    uint8_t *p;
816
    int ret;
817
 
818
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
819
                                     0, 4)) < 0)
820
        return ret;
821
 
822
    p = pkt.data;
823
    bytestream_put_be32(&p, rt->server_bw);
824
 
825
    return rtmp_send_packet(rt, &pkt, 0);
826
}
827
 
828
/**
829
 * Generate check bandwidth message and send it to the server.
830
 */
831
static int gen_check_bw(URLContext *s, RTMPContext *rt)
832
{
833
    RTMPPacket pkt;
834
    uint8_t *p;
835
    int ret;
836
 
837
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
838
                                     0, 21)) < 0)
839
        return ret;
840
 
841
    p = pkt.data;
842
    ff_amf_write_string(&p, "_checkbw");
843
    ff_amf_write_number(&p, ++rt->nb_invokes);
844
    ff_amf_write_null(&p);
845
 
846
    return rtmp_send_packet(rt, &pkt, 1);
847
}
848
 
849
/**
850
 * Generate report on bytes read so far and send it to the server.
851
 */
852
static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
853
{
854
    RTMPPacket pkt;
855
    uint8_t *p;
856
    int ret;
857
 
858
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
859
                                     ts, 4)) < 0)
860
        return ret;
861
 
862
    p = pkt.data;
863
    bytestream_put_be32(&p, rt->bytes_read);
864
 
865
    return rtmp_send_packet(rt, &pkt, 0);
866
}
867
 
868
static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt,
869
                                  const char *subscribe)
870
{
871
    RTMPPacket pkt;
872
    uint8_t *p;
873
    int ret;
874
 
875
    if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
876
                                     0, 27 + strlen(subscribe))) < 0)
877
        return ret;
878
 
879
    p = pkt.data;
880
    ff_amf_write_string(&p, "FCSubscribe");
881
    ff_amf_write_number(&p, ++rt->nb_invokes);
882
    ff_amf_write_null(&p);
883
    ff_amf_write_string(&p, subscribe);
884
 
885
    return rtmp_send_packet(rt, &pkt, 1);
886
}
887
 
888
int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap,
889
                        const uint8_t *key, int keylen, uint8_t *dst)
890
{
891
    struct AVSHA *sha;
892
    uint8_t hmac_buf[64+32] = {0};
893
    int i;
894
 
895
    sha = av_sha_alloc();
896
    if (!sha)
897
        return AVERROR(ENOMEM);
898
 
899
    if (keylen < 64) {
900
        memcpy(hmac_buf, key, keylen);
901
    } else {
902
        av_sha_init(sha, 256);
903
        av_sha_update(sha,key, keylen);
904
        av_sha_final(sha, hmac_buf);
905
    }
906
    for (i = 0; i < 64; i++)
907
        hmac_buf[i] ^= HMAC_IPAD_VAL;
908
 
909
    av_sha_init(sha, 256);
910
    av_sha_update(sha, hmac_buf, 64);
911
    if (gap <= 0) {
912
        av_sha_update(sha, src, len);
913
    } else { //skip 32 bytes used for storing digest
914
        av_sha_update(sha, src, gap);
915
        av_sha_update(sha, src + gap + 32, len - gap - 32);
916
    }
917
    av_sha_final(sha, hmac_buf + 64);
918
 
919
    for (i = 0; i < 64; i++)
920
        hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL; //reuse XORed key for opad
921
    av_sha_init(sha, 256);
922
    av_sha_update(sha, hmac_buf, 64+32);
923
    av_sha_final(sha, dst);
924
 
925
    av_free(sha);
926
 
927
    return 0;
928
}
929
 
930
int ff_rtmp_calc_digest_pos(const uint8_t *buf, int off, int mod_val,
931
                            int add_val)
932
{
933
    int i, digest_pos = 0;
934
 
935
    for (i = 0; i < 4; i++)
936
        digest_pos += buf[i + off];
937
    digest_pos = digest_pos % mod_val + add_val;
938
 
939
    return digest_pos;
940
}
941
 
942
/**
943
 * Put HMAC-SHA2 digest of packet data (except for the bytes where this digest
944
 * will be stored) into that packet.
945
 *
946
 * @param buf handshake data (1536 bytes)
947
 * @param encrypted use an encrypted connection (RTMPE)
948
 * @return offset to the digest inside input data
949
 */
950
static int rtmp_handshake_imprint_with_digest(uint8_t *buf, int encrypted)
951
{
952
    int ret, digest_pos;
953
 
954
    if (encrypted)
955
        digest_pos = ff_rtmp_calc_digest_pos(buf, 772, 728, 776);
956
    else
957
        digest_pos = ff_rtmp_calc_digest_pos(buf, 8, 728, 12);
958
 
959
    ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
960
                              rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
961
                              buf + digest_pos);
962
    if (ret < 0)
963
        return ret;
964
 
965
    return digest_pos;
966
}
967
 
968
/**
969
 * Verify that the received server response has the expected digest value.
970
 *
971
 * @param buf handshake data received from the server (1536 bytes)
972
 * @param off position to search digest offset from
973
 * @return 0 if digest is valid, digest position otherwise
974
 */
975
static int rtmp_validate_digest(uint8_t *buf, int off)
976
{
977
    uint8_t digest[32];
978
    int ret, digest_pos;
979
 
980
    digest_pos = ff_rtmp_calc_digest_pos(buf, off, 728, off + 4);
981
 
982
    ret = ff_rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
983
                              rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
984
                              digest);
985
    if (ret < 0)
986
        return ret;
987
 
988
    if (!memcmp(digest, buf + digest_pos, 32))
989
        return digest_pos;
990
    return 0;
991
}
992
 
993
static int rtmp_calc_swf_verification(URLContext *s, RTMPContext *rt,
994
                                      uint8_t *buf)
995
{
996
    uint8_t *p;
997
    int ret;
998
 
999
    if (rt->swfhash_len != 32) {
1000
        av_log(s, AV_LOG_ERROR,
1001
               "Hash of the decompressed SWF file is not 32 bytes long.\n");
1002
        return AVERROR(EINVAL);
1003
    }
1004
 
1005
    p = &rt->swfverification[0];
1006
    bytestream_put_byte(&p, 1);
1007
    bytestream_put_byte(&p, 1);
1008
    bytestream_put_be32(&p, rt->swfsize);
1009
    bytestream_put_be32(&p, rt->swfsize);
1010
 
1011
    if ((ret = ff_rtmp_calc_digest(rt->swfhash, 32, 0, buf, 32, p)) < 0)
1012
        return ret;
1013
 
1014
    return 0;
1015
}
1016
 
1017
#if CONFIG_ZLIB
1018
static int rtmp_uncompress_swfplayer(uint8_t *in_data, int64_t in_size,
1019
                                     uint8_t **out_data, int64_t *out_size)
1020
{
1021
    z_stream zs = { 0 };
1022
    void *ptr;
1023
    int size;
1024
    int ret = 0;
1025
 
1026
    zs.avail_in = in_size;
1027
    zs.next_in  = in_data;
1028
    ret = inflateInit(&zs);
1029
    if (ret != Z_OK)
1030
        return AVERROR_UNKNOWN;
1031
 
1032
    do {
1033
        uint8_t tmp_buf[16384];
1034
 
1035
        zs.avail_out = sizeof(tmp_buf);
1036
        zs.next_out  = tmp_buf;
1037
 
1038
        ret = inflate(&zs, Z_NO_FLUSH);
1039
        if (ret != Z_OK && ret != Z_STREAM_END) {
1040
            ret = AVERROR_UNKNOWN;
1041
            goto fail;
1042
        }
1043
 
1044
        size = sizeof(tmp_buf) - zs.avail_out;
1045
        if (!(ptr = av_realloc(*out_data, *out_size + size))) {
1046
            ret = AVERROR(ENOMEM);
1047
            goto fail;
1048
        }
1049
        *out_data = ptr;
1050
 
1051
        memcpy(*out_data + *out_size, tmp_buf, size);
1052
        *out_size += size;
1053
    } while (zs.avail_out == 0);
1054
 
1055
fail:
1056
    inflateEnd(&zs);
1057
    return ret;
1058
}
1059
#endif
1060
 
1061
static int rtmp_calc_swfhash(URLContext *s)
1062
{
1063
    RTMPContext *rt = s->priv_data;
1064
    uint8_t *in_data = NULL, *out_data = NULL, *swfdata;
1065
    int64_t in_size, out_size;
1066
    URLContext *stream;
1067
    char swfhash[32];
1068
    int swfsize;
1069
    int ret = 0;
1070
 
1071
    /* Get the SWF player file. */
1072
    if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ,
1073
                          &s->interrupt_callback, NULL)) < 0) {
1074
        av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
1075
        goto fail;
1076
    }
1077
 
1078
    if ((in_size = ffurl_seek(stream, 0, AVSEEK_SIZE)) < 0) {
1079
        ret = AVERROR(EIO);
1080
        goto fail;
1081
    }
1082
 
1083
    if (!(in_data = av_malloc(in_size))) {
1084
        ret = AVERROR(ENOMEM);
1085
        goto fail;
1086
    }
1087
 
1088
    if ((ret = ffurl_read_complete(stream, in_data, in_size)) < 0)
1089
        goto fail;
1090
 
1091
    if (in_size < 3) {
1092
        ret = AVERROR_INVALIDDATA;
1093
        goto fail;
1094
    }
1095
 
1096
    if (!memcmp(in_data, "CWS", 3)) {
1097
        /* Decompress the SWF player file using Zlib. */
1098
        if (!(out_data = av_malloc(8))) {
1099
            ret = AVERROR(ENOMEM);
1100
            goto fail;
1101
        }
1102
        *in_data = 'F'; // magic stuff
1103
        memcpy(out_data, in_data, 8);
1104
        out_size = 8;
1105
 
1106
#if CONFIG_ZLIB
1107
        if ((ret = rtmp_uncompress_swfplayer(in_data + 8, in_size - 8,
1108
                                             &out_data, &out_size)) < 0)
1109
            goto fail;
1110
#else
1111
        av_log(s, AV_LOG_ERROR,
1112
               "Zlib is required for decompressing the SWF player file.\n");
1113
        ret = AVERROR(EINVAL);
1114
        goto fail;
1115
#endif
1116
        swfsize = out_size;
1117
        swfdata = out_data;
1118
    } else {
1119
        swfsize = in_size;
1120
        swfdata = in_data;
1121
    }
1122
 
1123
    /* Compute the SHA256 hash of the SWF player file. */
1124
    if ((ret = ff_rtmp_calc_digest(swfdata, swfsize, 0,
1125
                                   "Genuine Adobe Flash Player 001", 30,
1126
                                   swfhash)) < 0)
1127
        goto fail;
1128
 
1129
    /* Set SWFVerification parameters. */
1130
    av_opt_set_bin(rt, "rtmp_swfhash", swfhash, 32, 0);
1131
    rt->swfsize = swfsize;
1132
 
1133
fail:
1134
    av_freep(&in_data);
1135
    av_freep(&out_data);
1136
    ffurl_close(stream);
1137
    return ret;
1138
}
1139
 
1140
/**
1141
 * Perform handshake with the server by means of exchanging pseudorandom data
1142
 * signed with HMAC-SHA2 digest.
1143
 *
1144
 * @return 0 if handshake succeeds, negative value otherwise
1145
 */
1146
static int rtmp_handshake(URLContext *s, RTMPContext *rt)
1147
{
1148
    AVLFG rnd;
1149
    uint8_t tosend    [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
1150
        3,                // unencrypted data
1151
        0, 0, 0, 0,       // client uptime
1152
        RTMP_CLIENT_VER1,
1153
        RTMP_CLIENT_VER2,
1154
        RTMP_CLIENT_VER3,
1155
        RTMP_CLIENT_VER4,
1156
    };
1157
    uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
1158
    uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
1159
    int i;
1160
    int server_pos, client_pos;
1161
    uint8_t digest[32], signature[32];
1162
    int ret, type = 0;
1163
 
1164
    av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
1165
 
1166
    av_lfg_init(&rnd, 0xDEADC0DE);
1167
    // generate handshake packet - 1536 bytes of pseudorandom data
1168
    for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
1169
        tosend[i] = av_lfg_get(&rnd) >> 24;
1170
 
1171
    if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1172
        /* When the client wants to use RTMPE, we have to change the command
1173
         * byte to 0x06 which means to use encrypted data and we have to set
1174
         * the flash version to at least 9.0.115.0. */
1175
        tosend[0] = 6;
1176
        tosend[5] = 128;
1177
        tosend[6] = 0;
1178
        tosend[7] = 3;
1179
        tosend[8] = 2;
1180
 
1181
        /* Initialize the Diffie-Hellmann context and generate the public key
1182
         * to send to the server. */
1183
        if ((ret = ff_rtmpe_gen_pub_key(rt->stream, tosend + 1)) < 0)
1184
            return ret;
1185
    }
1186
 
1187
    client_pos = rtmp_handshake_imprint_with_digest(tosend + 1, rt->encrypted);
1188
    if (client_pos < 0)
1189
        return client_pos;
1190
 
1191
    if ((ret = ffurl_write(rt->stream, tosend,
1192
                           RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1193
        av_log(s, AV_LOG_ERROR, "Cannot write RTMP handshake request\n");
1194
        return ret;
1195
    }
1196
 
1197
    if ((ret = ffurl_read_complete(rt->stream, serverdata,
1198
                                   RTMP_HANDSHAKE_PACKET_SIZE + 1)) < 0) {
1199
        av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1200
        return ret;
1201
    }
1202
 
1203
    if ((ret = ffurl_read_complete(rt->stream, clientdata,
1204
                                   RTMP_HANDSHAKE_PACKET_SIZE)) < 0) {
1205
        av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
1206
        return ret;
1207
    }
1208
 
1209
    av_log(s, AV_LOG_DEBUG, "Type answer %d\n", serverdata[0]);
1210
    av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
1211
           serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
1212
 
1213
    if (rt->is_input && serverdata[5] >= 3) {
1214
        server_pos = rtmp_validate_digest(serverdata + 1, 772);
1215
        if (server_pos < 0)
1216
            return server_pos;
1217
 
1218
        if (!server_pos) {
1219
            type = 1;
1220
            server_pos = rtmp_validate_digest(serverdata + 1, 8);
1221
            if (server_pos < 0)
1222
                return server_pos;
1223
 
1224
            if (!server_pos) {
1225
                av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
1226
                return AVERROR(EIO);
1227
            }
1228
        }
1229
 
1230
        /* Generate SWFVerification token (SHA256 HMAC hash of decompressed SWF,
1231
         * key are the last 32 bytes of the server handshake. */
1232
        if (rt->swfsize) {
1233
            if ((ret = rtmp_calc_swf_verification(s, rt, serverdata + 1 +
1234
                                                  RTMP_HANDSHAKE_PACKET_SIZE - 32)) < 0)
1235
                return ret;
1236
        }
1237
 
1238
        ret = ff_rtmp_calc_digest(tosend + 1 + client_pos, 32, 0,
1239
                                  rtmp_server_key, sizeof(rtmp_server_key),
1240
                                  digest);
1241
        if (ret < 0)
1242
            return ret;
1243
 
1244
        ret = ff_rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32,
1245
                                  0, digest, 32, signature);
1246
        if (ret < 0)
1247
            return ret;
1248
 
1249
        if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1250
            /* Compute the shared secret key sent by the server and initialize
1251
             * the RC4 encryption. */
1252
            if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1253
                                                   tosend + 1, type)) < 0)
1254
                return ret;
1255
 
1256
            /* Encrypt the signature received by the server. */
1257
            ff_rtmpe_encrypt_sig(rt->stream, signature, digest, serverdata[0]);
1258
        }
1259
 
1260
        if (memcmp(signature, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
1261
            av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
1262
            return AVERROR(EIO);
1263
        }
1264
 
1265
        for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
1266
            tosend[i] = av_lfg_get(&rnd) >> 24;
1267
        ret = ff_rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
1268
                                  rtmp_player_key, sizeof(rtmp_player_key),
1269
                                  digest);
1270
        if (ret < 0)
1271
            return ret;
1272
 
1273
        ret = ff_rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
1274
                                  digest, 32,
1275
                                  tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
1276
        if (ret < 0)
1277
            return ret;
1278
 
1279
        if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1280
            /* Encrypt the signature to be send to the server. */
1281
            ff_rtmpe_encrypt_sig(rt->stream, tosend +
1282
                                 RTMP_HANDSHAKE_PACKET_SIZE - 32, digest,
1283
                                 serverdata[0]);
1284
        }
1285
 
1286
        // write reply back to the server
1287
        if ((ret = ffurl_write(rt->stream, tosend,
1288
                               RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1289
            return ret;
1290
 
1291
        if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1292
            /* Set RC4 keys for encryption and update the keystreams. */
1293
            if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1294
                return ret;
1295
        }
1296
    } else {
1297
        if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1298
            /* Compute the shared secret key sent by the server and initialize
1299
             * the RC4 encryption. */
1300
            if ((ret = ff_rtmpe_compute_secret_key(rt->stream, serverdata + 1,
1301
                            tosend + 1, 1)) < 0)
1302
                return ret;
1303
 
1304
            if (serverdata[0] == 9) {
1305
                /* Encrypt the signature received by the server. */
1306
                ff_rtmpe_encrypt_sig(rt->stream, signature, digest,
1307
                                     serverdata[0]);
1308
            }
1309
        }
1310
 
1311
        if ((ret = ffurl_write(rt->stream, serverdata + 1,
1312
                               RTMP_HANDSHAKE_PACKET_SIZE)) < 0)
1313
            return ret;
1314
 
1315
        if (CONFIG_FFRTMPCRYPT_PROTOCOL && rt->encrypted) {
1316
            /* Set RC4 keys for encryption and update the keystreams. */
1317
            if ((ret = ff_rtmpe_update_keystream(rt->stream)) < 0)
1318
                return ret;
1319
        }
1320
    }
1321
 
1322
    return 0;
1323
}
1324
 
1325
static int rtmp_receive_hs_packet(RTMPContext* rt, uint32_t *first_int,
1326
                                  uint32_t *second_int, char *arraydata,
1327
                                  int size)
1328
{
1329
    int inoutsize;
1330
 
1331
    inoutsize = ffurl_read_complete(rt->stream, arraydata,
1332
                                    RTMP_HANDSHAKE_PACKET_SIZE);
1333
    if (inoutsize <= 0)
1334
        return AVERROR(EIO);
1335
    if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1336
        av_log(rt, AV_LOG_ERROR, "Erroneous Message size %d"
1337
               " not following standard\n", (int)inoutsize);
1338
        return AVERROR(EINVAL);
1339
    }
1340
 
1341
    *first_int  = AV_RB32(arraydata);
1342
    *second_int = AV_RB32(arraydata + 4);
1343
    return 0;
1344
}
1345
 
1346
static int rtmp_send_hs_packet(RTMPContext* rt, uint32_t first_int,
1347
                               uint32_t second_int, char *arraydata, int size)
1348
{
1349
    int inoutsize;
1350
 
1351
    AV_WB32(arraydata, first_int);
1352
    AV_WB32(arraydata + 4, second_int);
1353
    inoutsize = ffurl_write(rt->stream, arraydata,
1354
                            RTMP_HANDSHAKE_PACKET_SIZE);
1355
    if (inoutsize != RTMP_HANDSHAKE_PACKET_SIZE) {
1356
        av_log(rt, AV_LOG_ERROR, "Unable to write answer\n");
1357
        return AVERROR(EIO);
1358
    }
1359
 
1360
    return 0;
1361
}
1362
 
1363
/**
1364
 * rtmp handshake server side
1365
 */
1366
static int rtmp_server_handshake(URLContext *s, RTMPContext *rt)
1367
{
1368
    uint8_t buffer[RTMP_HANDSHAKE_PACKET_SIZE];
1369
    uint32_t hs_epoch;
1370
    uint32_t hs_my_epoch;
1371
    uint8_t hs_c1[RTMP_HANDSHAKE_PACKET_SIZE];
1372
    uint8_t hs_s1[RTMP_HANDSHAKE_PACKET_SIZE];
1373
    uint32_t zeroes;
1374
    uint32_t temp       = 0;
1375
    int randomidx       = 0;
1376
    int inoutsize       = 0;
1377
    int ret;
1378
 
1379
    inoutsize = ffurl_read_complete(rt->stream, buffer, 1);       // Receive C0
1380
    if (inoutsize <= 0) {
1381
        av_log(s, AV_LOG_ERROR, "Unable to read handshake\n");
1382
        return AVERROR(EIO);
1383
    }
1384
    // Check Version
1385
    if (buffer[0] != 3) {
1386
        av_log(s, AV_LOG_ERROR, "RTMP protocol version mismatch\n");
1387
        return AVERROR(EIO);
1388
    }
1389
    if (ffurl_write(rt->stream, buffer, 1) <= 0) {                 // Send S0
1390
        av_log(s, AV_LOG_ERROR,
1391
               "Unable to write answer - RTMP S0\n");
1392
        return AVERROR(EIO);
1393
    }
1394
    /* Receive C1 */
1395
    ret = rtmp_receive_hs_packet(rt, &hs_epoch, &zeroes, hs_c1,
1396
                                 RTMP_HANDSHAKE_PACKET_SIZE);
1397
    if (ret) {
1398
        av_log(s, AV_LOG_ERROR, "RTMP Handshake C1 Error\n");
1399
        return ret;
1400
    }
1401
    /* Send S1 */
1402
    /* By now same epoch will be sent */
1403
    hs_my_epoch = hs_epoch;
1404
    /* Generate random */
1405
    for (randomidx = 8; randomidx < (RTMP_HANDSHAKE_PACKET_SIZE);
1406
         randomidx += 4)
1407
        AV_WB32(hs_s1 + randomidx, av_get_random_seed());
1408
 
1409
    ret = rtmp_send_hs_packet(rt, hs_my_epoch, 0, hs_s1,
1410
                              RTMP_HANDSHAKE_PACKET_SIZE);
1411
    if (ret) {
1412
        av_log(s, AV_LOG_ERROR, "RTMP Handshake S1 Error\n");
1413
        return ret;
1414
    }
1415
    /* Send S2 */
1416
    ret = rtmp_send_hs_packet(rt, hs_epoch, 0, hs_c1,
1417
                              RTMP_HANDSHAKE_PACKET_SIZE);
1418
    if (ret) {
1419
        av_log(s, AV_LOG_ERROR, "RTMP Handshake S2 Error\n");
1420
        return ret;
1421
    }
1422
    /* Receive C2 */
1423
    ret = rtmp_receive_hs_packet(rt, &temp, &zeroes, buffer,
1424
                                 RTMP_HANDSHAKE_PACKET_SIZE);
1425
    if (ret) {
1426
        av_log(s, AV_LOG_ERROR, "RTMP Handshake C2 Error\n");
1427
        return ret;
1428
    }
1429
    if (temp != hs_my_epoch)
1430
        av_log(s, AV_LOG_WARNING,
1431
               "Erroneous C2 Message epoch does not match up with C1 epoch\n");
1432
    if (memcmp(buffer + 8, hs_s1 + 8,
1433
               RTMP_HANDSHAKE_PACKET_SIZE - 8))
1434
        av_log(s, AV_LOG_WARNING,
1435
               "Erroneous C2 Message random does not match up\n");
1436
 
1437
    return 0;
1438
}
1439
 
1440
static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
1441
{
1442
    RTMPContext *rt = s->priv_data;
1443
    int ret;
1444
 
1445
    if (pkt->size < 4) {
1446
        av_log(s, AV_LOG_ERROR,
1447
               "Too short chunk size change packet (%d)\n",
1448
               pkt->size);
1449
        return AVERROR_INVALIDDATA;
1450
    }
1451
 
1452
    if (!rt->is_input) {
1453
        /* Send the same chunk size change packet back to the server,
1454
         * setting the outgoing chunk size to the same as the incoming one. */
1455
        if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
1456
                                        &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
1457
            return ret;
1458
        rt->out_chunk_size = AV_RB32(pkt->data);
1459
    }
1460
 
1461
    rt->in_chunk_size = AV_RB32(pkt->data);
1462
    if (rt->in_chunk_size <= 0) {
1463
        av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n",
1464
               rt->in_chunk_size);
1465
        return AVERROR_INVALIDDATA;
1466
    }
1467
    av_log(s, AV_LOG_DEBUG, "New incoming chunk size = %d\n",
1468
           rt->in_chunk_size);
1469
 
1470
    return 0;
1471
}
1472
 
1473
static int handle_ping(URLContext *s, RTMPPacket *pkt)
1474
{
1475
    RTMPContext *rt = s->priv_data;
1476
    int t, ret;
1477
 
1478
    if (pkt->size < 2) {
1479
        av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n",
1480
               pkt->size);
1481
        return AVERROR_INVALIDDATA;
1482
    }
1483
 
1484
    t = AV_RB16(pkt->data);
1485
    if (t == 6) {
1486
        if ((ret = gen_pong(s, rt, pkt)) < 0)
1487
            return ret;
1488
    } else if (t == 26) {
1489
        if (rt->swfsize) {
1490
            if ((ret = gen_swf_verification(s, rt)) < 0)
1491
                return ret;
1492
        } else {
1493
            av_log(s, AV_LOG_WARNING, "Ignoring SWFVerification request.\n");
1494
        }
1495
    }
1496
 
1497
    return 0;
1498
}
1499
 
1500
static int handle_client_bw(URLContext *s, RTMPPacket *pkt)
1501
{
1502
    RTMPContext *rt = s->priv_data;
1503
 
1504
    if (pkt->size < 4) {
1505
        av_log(s, AV_LOG_ERROR,
1506
               "Client bandwidth report packet is less than 4 bytes long (%d)\n",
1507
               pkt->size);
1508
        return AVERROR_INVALIDDATA;
1509
    }
1510
 
1511
    rt->client_report_size = AV_RB32(pkt->data);
1512
    if (rt->client_report_size <= 0) {
1513
        av_log(s, AV_LOG_ERROR, "Incorrect client bandwidth %d\n",
1514
                rt->client_report_size);
1515
        return AVERROR_INVALIDDATA;
1516
 
1517
    }
1518
    av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", rt->client_report_size);
1519
    rt->client_report_size >>= 1;
1520
 
1521
    return 0;
1522
}
1523
 
1524
static int handle_server_bw(URLContext *s, RTMPPacket *pkt)
1525
{
1526
    RTMPContext *rt = s->priv_data;
1527
 
1528
    if (pkt->size < 4) {
1529
        av_log(s, AV_LOG_ERROR,
1530
               "Too short server bandwidth report packet (%d)\n",
1531
               pkt->size);
1532
        return AVERROR_INVALIDDATA;
1533
    }
1534
 
1535
    rt->server_bw = AV_RB32(pkt->data);
1536
    if (rt->server_bw <= 0) {
1537
        av_log(s, AV_LOG_ERROR, "Incorrect server bandwidth %d\n",
1538
               rt->server_bw);
1539
        return AVERROR_INVALIDDATA;
1540
    }
1541
    av_log(s, AV_LOG_DEBUG, "Server bandwidth = %d\n", rt->server_bw);
1542
 
1543
    return 0;
1544
}
1545
 
1546
static int do_adobe_auth(RTMPContext *rt, const char *user, const char *salt,
1547
                         const char *opaque, const char *challenge)
1548
{
1549
    uint8_t hash[16];
1550
    char hashstr[AV_BASE64_SIZE(sizeof(hash))], challenge2[10];
1551
    struct AVMD5 *md5 = av_md5_alloc();
1552
    if (!md5)
1553
        return AVERROR(ENOMEM);
1554
 
1555
    snprintf(challenge2, sizeof(challenge2), "%08x", av_get_random_seed());
1556
 
1557
    av_md5_init(md5);
1558
    av_md5_update(md5, user, strlen(user));
1559
    av_md5_update(md5, salt, strlen(salt));
1560
    av_md5_update(md5, rt->password, strlen(rt->password));
1561
    av_md5_final(md5, hash);
1562
    av_base64_encode(hashstr, sizeof(hashstr), hash,
1563
                     sizeof(hash));
1564
    av_md5_init(md5);
1565
    av_md5_update(md5, hashstr, strlen(hashstr));
1566
    if (opaque)
1567
        av_md5_update(md5, opaque, strlen(opaque));
1568
    else if (challenge)
1569
        av_md5_update(md5, challenge, strlen(challenge));
1570
    av_md5_update(md5, challenge2, strlen(challenge2));
1571
    av_md5_final(md5, hash);
1572
    av_base64_encode(hashstr, sizeof(hashstr), hash,
1573
                     sizeof(hash));
1574
    snprintf(rt->auth_params, sizeof(rt->auth_params),
1575
             "?authmod=%s&user=%s&challenge=%s&response=%s",
1576
             "adobe", user, challenge2, hashstr);
1577
    if (opaque)
1578
        av_strlcatf(rt->auth_params, sizeof(rt->auth_params),
1579
                    "&opaque=%s", opaque);
1580
 
1581
    av_free(md5);
1582
    return 0;
1583
}
1584
 
1585
static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce)
1586
{
1587
    uint8_t hash[16];
1588
    char hashstr1[33], hashstr2[33];
1589
    const char *realm = "live";
1590
    const char *method = "publish";
1591
    const char *qop = "auth";
1592
    const char *nc = "00000001";
1593
    char cnonce[10];
1594
    struct AVMD5 *md5 = av_md5_alloc();
1595
    if (!md5)
1596
        return AVERROR(ENOMEM);
1597
 
1598
    snprintf(cnonce, sizeof(cnonce), "%08x", av_get_random_seed());
1599
 
1600
    av_md5_init(md5);
1601
    av_md5_update(md5, user, strlen(user));
1602
    av_md5_update(md5, ":", 1);
1603
    av_md5_update(md5, realm, strlen(realm));
1604
    av_md5_update(md5, ":", 1);
1605
    av_md5_update(md5, rt->password, strlen(rt->password));
1606
    av_md5_final(md5, hash);
1607
    ff_data_to_hex(hashstr1, hash, 16, 1);
1608
    hashstr1[32] = '\0';
1609
 
1610
    av_md5_init(md5);
1611
    av_md5_update(md5, method, strlen(method));
1612
    av_md5_update(md5, ":/", 2);
1613
    av_md5_update(md5, rt->app, strlen(rt->app));
1614
    if (!strchr(rt->app, '/'))
1615
        av_md5_update(md5, "/_definst_", strlen("/_definst_"));
1616
    av_md5_final(md5, hash);
1617
    ff_data_to_hex(hashstr2, hash, 16, 1);
1618
    hashstr2[32] = '\0';
1619
 
1620
    av_md5_init(md5);
1621
    av_md5_update(md5, hashstr1, strlen(hashstr1));
1622
    av_md5_update(md5, ":", 1);
1623
    if (nonce)
1624
        av_md5_update(md5, nonce, strlen(nonce));
1625
    av_md5_update(md5, ":", 1);
1626
    av_md5_update(md5, nc, strlen(nc));
1627
    av_md5_update(md5, ":", 1);
1628
    av_md5_update(md5, cnonce, strlen(cnonce));
1629
    av_md5_update(md5, ":", 1);
1630
    av_md5_update(md5, qop, strlen(qop));
1631
    av_md5_update(md5, ":", 1);
1632
    av_md5_update(md5, hashstr2, strlen(hashstr2));
1633
    av_md5_final(md5, hash);
1634
    ff_data_to_hex(hashstr1, hash, 16, 1);
1635
 
1636
    snprintf(rt->auth_params, sizeof(rt->auth_params),
1637
             "?authmod=%s&user=%s&nonce=%s&cnonce=%s&nc=%s&response=%s",
1638
             "llnw", user, nonce, cnonce, nc, hashstr1);
1639
 
1640
    av_free(md5);
1641
    return 0;
1642
}
1643
 
1644
static int handle_connect_error(URLContext *s, const char *desc)
1645
{
1646
    RTMPContext *rt = s->priv_data;
1647
    char buf[300], *ptr, authmod[15];
1648
    int i = 0, ret = 0;
1649
    const char *user = "", *salt = "", *opaque = NULL,
1650
               *challenge = NULL, *cptr = NULL, *nonce = NULL;
1651
 
1652
    if (!(cptr = strstr(desc, "authmod=adobe")) &&
1653
        !(cptr = strstr(desc, "authmod=llnw"))) {
1654
        av_log(s, AV_LOG_ERROR,
1655
               "Unknown connect error (unsupported authentication method?)\n");
1656
        return AVERROR_UNKNOWN;
1657
    }
1658
    cptr += strlen("authmod=");
1659
    while (*cptr && *cptr != ' ' && i < sizeof(authmod) - 1)
1660
        authmod[i++] = *cptr++;
1661
    authmod[i] = '\0';
1662
 
1663
    if (!rt->username[0] || !rt->password[0]) {
1664
        av_log(s, AV_LOG_ERROR, "No credentials set\n");
1665
        return AVERROR_UNKNOWN;
1666
    }
1667
 
1668
    if (strstr(desc, "?reason=authfailed")) {
1669
        av_log(s, AV_LOG_ERROR, "Incorrect username/password\n");
1670
        return AVERROR_UNKNOWN;
1671
    } else if (strstr(desc, "?reason=nosuchuser")) {
1672
        av_log(s, AV_LOG_ERROR, "Incorrect username\n");
1673
        return AVERROR_UNKNOWN;
1674
    }
1675
 
1676
    if (rt->auth_tried) {
1677
        av_log(s, AV_LOG_ERROR, "Authentication failed\n");
1678
        return AVERROR_UNKNOWN;
1679
    }
1680
 
1681
    rt->auth_params[0] = '\0';
1682
 
1683
    if (strstr(desc, "code=403 need auth")) {
1684
        snprintf(rt->auth_params, sizeof(rt->auth_params),
1685
                 "?authmod=%s&user=%s", authmod, rt->username);
1686
        return 0;
1687
    }
1688
 
1689
    if (!(cptr = strstr(desc, "?reason=needauth"))) {
1690
        av_log(s, AV_LOG_ERROR, "No auth parameters found\n");
1691
        return AVERROR_UNKNOWN;
1692
    }
1693
 
1694
    av_strlcpy(buf, cptr + 1, sizeof(buf));
1695
    ptr = buf;
1696
 
1697
    while (ptr) {
1698
        char *next  = strchr(ptr, '&');
1699
        char *value = strchr(ptr, '=');
1700
        if (next)
1701
            *next++ = '\0';
1702
        if (value)
1703
            *value++ = '\0';
1704
        if (!strcmp(ptr, "user")) {
1705
            user = value;
1706
        } else if (!strcmp(ptr, "salt")) {
1707
            salt = value;
1708
        } else if (!strcmp(ptr, "opaque")) {
1709
            opaque = value;
1710
        } else if (!strcmp(ptr, "challenge")) {
1711
            challenge = value;
1712
        } else if (!strcmp(ptr, "nonce")) {
1713
            nonce = value;
1714
        }
1715
        ptr = next;
1716
    }
1717
 
1718
    if (!strcmp(authmod, "adobe")) {
1719
        if ((ret = do_adobe_auth(rt, user, salt, opaque, challenge)) < 0)
1720
            return ret;
1721
    } else {
1722
        if ((ret = do_llnw_auth(rt, user, nonce)) < 0)
1723
            return ret;
1724
    }
1725
 
1726
    rt->auth_tried = 1;
1727
    return 0;
1728
}
1729
 
1730
static int handle_invoke_error(URLContext *s, RTMPPacket *pkt)
1731
{
1732
    RTMPContext *rt = s->priv_data;
1733
    const uint8_t *data_end = pkt->data + pkt->size;
1734
    char *tracked_method = NULL;
1735
    int level = AV_LOG_ERROR;
1736
    uint8_t tmpstr[256];
1737
    int ret;
1738
 
1739
    if ((ret = find_tracked_method(s, pkt, 9, &tracked_method)) < 0)
1740
        return ret;
1741
 
1742
    if (!ff_amf_get_field_value(pkt->data + 9, data_end,
1743
                                "description", tmpstr, sizeof(tmpstr))) {
1744
        if (tracked_method && (!strcmp(tracked_method, "_checkbw")      ||
1745
                               !strcmp(tracked_method, "releaseStream") ||
1746
                               !strcmp(tracked_method, "FCSubscribe")   ||
1747
                               !strcmp(tracked_method, "FCPublish"))) {
1748
            /* Gracefully ignore Adobe-specific historical artifact errors. */
1749
            level = AV_LOG_WARNING;
1750
            ret = 0;
1751
        } else if (tracked_method && !strcmp(tracked_method, "connect")) {
1752
            ret = handle_connect_error(s, tmpstr);
1753
            if (!ret) {
1754
                rt->do_reconnect = 1;
1755
                level = AV_LOG_VERBOSE;
1756
            }
1757
        } else
1758
            ret = AVERROR_UNKNOWN;
1759
        av_log(s, level, "Server error: %s\n", tmpstr);
1760
    }
1761
 
1762
    av_free(tracked_method);
1763
    return ret;
1764
}
1765
 
1766
static int write_begin(URLContext *s)
1767
{
1768
    RTMPContext *rt = s->priv_data;
1769
    PutByteContext pbc;
1770
    RTMPPacket spkt = { 0 };
1771
    int ret;
1772
 
1773
    // Send Stream Begin 1
1774
    if ((ret = ff_rtmp_packet_create(&spkt, RTMP_NETWORK_CHANNEL,
1775
                                     RTMP_PT_PING, 0, 6)) < 0) {
1776
        av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1777
        return ret;
1778
    }
1779
 
1780
    bytestream2_init_writer(&pbc, spkt.data, spkt.size);
1781
    bytestream2_put_be16(&pbc, 0);          // 0 -> Stream Begin
1782
    bytestream2_put_be32(&pbc, rt->nb_streamid);
1783
 
1784
    ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1785
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1786
 
1787
    ff_rtmp_packet_destroy(&spkt);
1788
 
1789
    return ret;
1790
}
1791
 
1792
static int write_status(URLContext *s, RTMPPacket *pkt,
1793
                        const char *status, const char *filename)
1794
{
1795
    RTMPContext *rt = s->priv_data;
1796
    RTMPPacket spkt = { 0 };
1797
    char statusmsg[128];
1798
    uint8_t *pp;
1799
    int ret;
1800
 
1801
    if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1802
                                     RTMP_PT_INVOKE, 0,
1803
                                     RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1804
        av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1805
        return ret;
1806
    }
1807
 
1808
    pp = spkt.data;
1809
    spkt.extra = pkt->extra;
1810
    ff_amf_write_string(&pp, "onStatus");
1811
    ff_amf_write_number(&pp, 0);
1812
    ff_amf_write_null(&pp);
1813
 
1814
    ff_amf_write_object_start(&pp);
1815
    ff_amf_write_field_name(&pp, "level");
1816
    ff_amf_write_string(&pp, "status");
1817
    ff_amf_write_field_name(&pp, "code");
1818
    ff_amf_write_string(&pp, status);
1819
    ff_amf_write_field_name(&pp, "description");
1820
    snprintf(statusmsg, sizeof(statusmsg),
1821
             "%s is now published", filename);
1822
    ff_amf_write_string(&pp, statusmsg);
1823
    ff_amf_write_field_name(&pp, "details");
1824
    ff_amf_write_string(&pp, filename);
1825
    ff_amf_write_field_name(&pp, "clientid");
1826
    snprintf(statusmsg, sizeof(statusmsg), "%s", LIBAVFORMAT_IDENT);
1827
    ff_amf_write_string(&pp, statusmsg);
1828
    ff_amf_write_object_end(&pp);
1829
 
1830
    spkt.size = pp - spkt.data;
1831
    ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1832
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1833
    ff_rtmp_packet_destroy(&spkt);
1834
 
1835
    return ret;
1836
}
1837
 
1838
static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
1839
{
1840
    RTMPContext *rt = s->priv_data;
1841
    double seqnum;
1842
    char filename[64];
1843
    char command[64];
1844
    int stringlen;
1845
    char *pchar;
1846
    const uint8_t *p = pkt->data;
1847
    uint8_t *pp      = NULL;
1848
    RTMPPacket spkt  = { 0 };
1849
    GetByteContext gbc;
1850
    int ret;
1851
 
1852
    bytestream2_init(&gbc, p, pkt->size);
1853
    if (ff_amf_read_string(&gbc, command, sizeof(command),
1854
                           &stringlen)) {
1855
        av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n");
1856
        return AVERROR_INVALIDDATA;
1857
    }
1858
 
1859
    ret = ff_amf_read_number(&gbc, &seqnum);
1860
    if (ret)
1861
        return ret;
1862
    ret = ff_amf_read_null(&gbc);
1863
    if (ret)
1864
        return ret;
1865
    if (!strcmp(command, "FCPublish") ||
1866
        !strcmp(command, "publish")) {
1867
        ret = ff_amf_read_string(&gbc, filename,
1868
                                 sizeof(filename), &stringlen);
1869
        // check with url
1870
        if (s->filename) {
1871
            pchar = strrchr(s->filename, '/');
1872
            if (!pchar) {
1873
                av_log(s, AV_LOG_WARNING,
1874
                       "Unable to find / in url %s, bad format\n",
1875
                       s->filename);
1876
                pchar = s->filename;
1877
            }
1878
            pchar++;
1879
            if (strcmp(pchar, filename))
1880
                av_log(s, AV_LOG_WARNING, "Unexpected stream %s, expecting"
1881
                       " %s\n", filename, pchar);
1882
        }
1883
        rt->state = STATE_RECEIVING;
1884
    }
1885
 
1886
    if (!strcmp(command, "FCPublish")) {
1887
        if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1888
                                         RTMP_PT_INVOKE, 0,
1889
                                         RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1890
            av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1891
            return ret;
1892
        }
1893
        pp = spkt.data;
1894
        ff_amf_write_string(&pp, "onFCPublish");
1895
    } else if (!strcmp(command, "publish")) {
1896
        ret = write_begin(s);
1897
        if (ret < 0)
1898
            return ret;
1899
 
1900
        // Send onStatus(NetStream.Publish.Start)
1901
        return write_status(s, pkt, "NetStream.Publish.Start",
1902
                           filename);
1903
    } else if (!strcmp(command, "play")) {
1904
        ret = write_begin(s);
1905
        if (ret < 0)
1906
            return ret;
1907
        rt->state = STATE_SENDING;
1908
        return write_status(s, pkt, "NetStream.Play.Start",
1909
                            filename);
1910
    } else {
1911
        if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL,
1912
                                         RTMP_PT_INVOKE, 0,
1913
                                         RTMP_PKTDATA_DEFAULT_SIZE)) < 0) {
1914
            av_log(s, AV_LOG_ERROR, "Unable to create response packet\n");
1915
            return ret;
1916
        }
1917
        pp = spkt.data;
1918
        ff_amf_write_string(&pp, "_result");
1919
        ff_amf_write_number(&pp, seqnum);
1920
        ff_amf_write_null(&pp);
1921
        if (!strcmp(command, "createStream")) {
1922
            rt->nb_streamid++;
1923
            if (rt->nb_streamid == 0 || rt->nb_streamid == 2)
1924
                rt->nb_streamid++; /* Values 0 and 2 are reserved */
1925
            ff_amf_write_number(&pp, rt->nb_streamid);
1926
            /* By now we don't control which streams are removed in
1927
             * deleteStream. There is no stream creation control
1928
             * if a client creates more than 2^32 - 2 streams. */
1929
        }
1930
    }
1931
    spkt.size = pp - spkt.data;
1932
    ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
1933
                               &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
1934
    ff_rtmp_packet_destroy(&spkt);
1935
    return ret;
1936
}
1937
 
1938
static int handle_invoke_result(URLContext *s, RTMPPacket *pkt)
1939
{
1940
    RTMPContext *rt = s->priv_data;
1941
    char *tracked_method = NULL;
1942
    int ret = 0;
1943
 
1944
    if ((ret = find_tracked_method(s, pkt, 10, &tracked_method)) < 0)
1945
        return ret;
1946
 
1947
    if (!tracked_method) {
1948
        /* Ignore this reply when the current method is not tracked. */
1949
        return ret;
1950
    }
1951
 
1952
    if (!strcmp(tracked_method, "connect")) {
1953
        if (!rt->is_input) {
1954
            if ((ret = gen_release_stream(s, rt)) < 0)
1955
                goto fail;
1956
 
1957
            if ((ret = gen_fcpublish_stream(s, rt)) < 0)
1958
                goto fail;
1959
        } else {
1960
            if ((ret = gen_server_bw(s, rt)) < 0)
1961
                goto fail;
1962
        }
1963
 
1964
        if ((ret = gen_create_stream(s, rt)) < 0)
1965
            goto fail;
1966
 
1967
        if (rt->is_input) {
1968
            /* Send the FCSubscribe command when the name of live
1969
             * stream is defined by the user or if it's a live stream. */
1970
            if (rt->subscribe) {
1971
                if ((ret = gen_fcsubscribe_stream(s, rt, rt->subscribe)) < 0)
1972
                    goto fail;
1973
            } else if (rt->live == -1) {
1974
                if ((ret = gen_fcsubscribe_stream(s, rt, rt->playpath)) < 0)
1975
                    goto fail;
1976
            }
1977
        }
1978
    } else if (!strcmp(tracked_method, "createStream")) {
1979
        //extract a number from the result
1980
        if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
1981
            av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
1982
        } else {
1983
            rt->stream_id = av_int2double(AV_RB64(pkt->data + 21));
1984
        }
1985
 
1986
        if (!rt->is_input) {
1987
            if ((ret = gen_publish(s, rt)) < 0)
1988
                goto fail;
1989
        } else {
1990
            if ((ret = gen_play(s, rt)) < 0)
1991
                goto fail;
1992
            if ((ret = gen_buffer_time(s, rt)) < 0)
1993
                goto fail;
1994
        }
1995
    }
1996
 
1997
fail:
1998
    av_free(tracked_method);
1999
    return ret;
2000
}
2001
 
2002
static int handle_invoke_status(URLContext *s, RTMPPacket *pkt)
2003
{
2004
    RTMPContext *rt = s->priv_data;
2005
    const uint8_t *data_end = pkt->data + pkt->size;
2006
    const uint8_t *ptr = pkt->data + RTMP_HEADER;
2007
    uint8_t tmpstr[256];
2008
    int i, t;
2009
 
2010
    for (i = 0; i < 2; i++) {
2011
        t = ff_amf_tag_size(ptr, data_end);
2012
        if (t < 0)
2013
            return 1;
2014
        ptr += t;
2015
    }
2016
 
2017
    t = ff_amf_get_field_value(ptr, data_end, "level", tmpstr, sizeof(tmpstr));
2018
    if (!t && !strcmp(tmpstr, "error")) {
2019
        t = ff_amf_get_field_value(ptr, data_end,
2020
                                   "description", tmpstr, sizeof(tmpstr));
2021
        if (t || !tmpstr[0])
2022
            t = ff_amf_get_field_value(ptr, data_end, "code",
2023
                                       tmpstr, sizeof(tmpstr));
2024
        if (!t)
2025
            av_log(s, AV_LOG_ERROR, "Server error: %s\n", tmpstr);
2026
        return -1;
2027
    }
2028
 
2029
    t = ff_amf_get_field_value(ptr, data_end, "code", tmpstr, sizeof(tmpstr));
2030
    if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
2031
    if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
2032
    if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
2033
    if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
2034
    if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING;
2035
 
2036
    return 0;
2037
}
2038
 
2039
static int handle_invoke(URLContext *s, RTMPPacket *pkt)
2040
{
2041
    RTMPContext *rt = s->priv_data;
2042
    int ret = 0;
2043
 
2044
    //TODO: check for the messages sent for wrong state?
2045
    if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
2046
        if ((ret = handle_invoke_error(s, pkt)) < 0)
2047
            return ret;
2048
    } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
2049
        if ((ret = handle_invoke_result(s, pkt)) < 0)
2050
            return ret;
2051
    } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
2052
        if ((ret = handle_invoke_status(s, pkt)) < 0)
2053
            return ret;
2054
    } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) {
2055
        if ((ret = gen_check_bw(s, rt)) < 0)
2056
            return ret;
2057
    } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") ||
2058
               ff_amf_match_string(pkt->data, pkt->size, "FCPublish")     ||
2059
               ff_amf_match_string(pkt->data, pkt->size, "publish")       ||
2060
               ff_amf_match_string(pkt->data, pkt->size, "play")          ||
2061
               ff_amf_match_string(pkt->data, pkt->size, "_checkbw")      ||
2062
               ff_amf_match_string(pkt->data, pkt->size, "createStream")) {
2063
        if ((ret = send_invoke_response(s, pkt)) < 0)
2064
            return ret;
2065
    }
2066
 
2067
    return ret;
2068
}
2069
 
2070
static int update_offset(RTMPContext *rt, int size)
2071
{
2072
    int old_flv_size;
2073
 
2074
    // generate packet header and put data into buffer for FLV demuxer
2075
    if (rt->flv_off < rt->flv_size) {
2076
        // There is old unread data in the buffer, thus append at the end
2077
        old_flv_size  = rt->flv_size;
2078
        rt->flv_size += size;
2079
    } else {
2080
        // All data has been read, write the new data at the start of the buffer
2081
        old_flv_size = 0;
2082
        rt->flv_size = size;
2083
        rt->flv_off  = 0;
2084
    }
2085
 
2086
    return old_flv_size;
2087
}
2088
 
2089
static int append_flv_data(RTMPContext *rt, RTMPPacket *pkt, int skip)
2090
{
2091
    int old_flv_size, ret;
2092
    PutByteContext pbc;
2093
    const uint8_t *data = pkt->data + skip;
2094
    const int size      = pkt->size - skip;
2095
    uint32_t ts         = pkt->timestamp;
2096
 
2097
    old_flv_size = update_offset(rt, size + 15);
2098
 
2099
    if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2100
        rt->flv_size = rt->flv_off = 0;
2101
        return ret;
2102
    }
2103
    bytestream2_init_writer(&pbc, rt->flv_data, rt->flv_size);
2104
    bytestream2_skip_p(&pbc, old_flv_size);
2105
    bytestream2_put_byte(&pbc, pkt->type);
2106
    bytestream2_put_be24(&pbc, size);
2107
    bytestream2_put_be24(&pbc, ts);
2108
    bytestream2_put_byte(&pbc, ts >> 24);
2109
    bytestream2_put_be24(&pbc, 0);
2110
    bytestream2_put_buffer(&pbc, data, size);
2111
    bytestream2_put_be32(&pbc, 0);
2112
 
2113
    return 0;
2114
}
2115
 
2116
static int handle_notify(URLContext *s, RTMPPacket *pkt)
2117
{
2118
    RTMPContext *rt  = s->priv_data;
2119
    uint8_t commandbuffer[64];
2120
    char statusmsg[128];
2121
    int stringlen, ret, skip = 0;
2122
    GetByteContext gbc;
2123
 
2124
    bytestream2_init(&gbc, pkt->data, pkt->size);
2125
    if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
2126
                           &stringlen))
2127
        return AVERROR_INVALIDDATA;
2128
 
2129
    // Skip the @setDataFrame string and validate it is a notification
2130
    if (!strcmp(commandbuffer, "@setDataFrame")) {
2131
        skip = gbc.buffer - pkt->data;
2132
        ret = ff_amf_read_string(&gbc, statusmsg,
2133
                                 sizeof(statusmsg), &stringlen);
2134
        if (ret < 0)
2135
            return AVERROR_INVALIDDATA;
2136
    }
2137
 
2138
    return append_flv_data(rt, pkt, skip);
2139
}
2140
 
2141
/**
2142
 * Parse received packet and possibly perform some action depending on
2143
 * the packet contents.
2144
 * @return 0 for no errors, negative values for serious errors which prevent
2145
 *         further communications, positive values for uncritical errors
2146
 */
2147
static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
2148
{
2149
    int ret;
2150
 
2151
#ifdef DEBUG
2152
    ff_rtmp_packet_dump(s, pkt);
2153
#endif
2154
 
2155
    switch (pkt->type) {
2156
    case RTMP_PT_BYTES_READ:
2157
        av_dlog(s, "received bytes read report\n");
2158
        break;
2159
    case RTMP_PT_CHUNK_SIZE:
2160
        if ((ret = handle_chunk_size(s, pkt)) < 0)
2161
            return ret;
2162
        break;
2163
    case RTMP_PT_PING:
2164
        if ((ret = handle_ping(s, pkt)) < 0)
2165
            return ret;
2166
        break;
2167
    case RTMP_PT_CLIENT_BW:
2168
        if ((ret = handle_client_bw(s, pkt)) < 0)
2169
            return ret;
2170
        break;
2171
    case RTMP_PT_SERVER_BW:
2172
        if ((ret = handle_server_bw(s, pkt)) < 0)
2173
            return ret;
2174
        break;
2175
    case RTMP_PT_INVOKE:
2176
        if ((ret = handle_invoke(s, pkt)) < 0)
2177
            return ret;
2178
        break;
2179
    case RTMP_PT_VIDEO:
2180
    case RTMP_PT_AUDIO:
2181
    case RTMP_PT_METADATA:
2182
    case RTMP_PT_NOTIFY:
2183
        /* Audio, Video and Metadata packets are parsed in get_packet() */
2184
        break;
2185
    default:
2186
        av_log(s, AV_LOG_VERBOSE, "Unknown packet type received 0x%02X\n", pkt->type);
2187
        break;
2188
    }
2189
    return 0;
2190
}
2191
 
2192
static int handle_metadata(RTMPContext *rt, RTMPPacket *pkt)
2193
{
2194
    int ret, old_flv_size, type;
2195
    const uint8_t *next;
2196
    uint8_t *p;
2197
    uint32_t size;
2198
    uint32_t ts, cts, pts = 0;
2199
 
2200
    old_flv_size = update_offset(rt, pkt->size);
2201
 
2202
    if ((ret = av_reallocp(&rt->flv_data, rt->flv_size)) < 0) {
2203
        rt->flv_size = rt->flv_off = 0;
2204
        return ret;
2205
    }
2206
 
2207
    next = pkt->data;
2208
    p    = rt->flv_data + old_flv_size;
2209
 
2210
    /* copy data while rewriting timestamps */
2211
    ts = pkt->timestamp;
2212
 
2213
    while (next - pkt->data < pkt->size - RTMP_HEADER) {
2214
        type = bytestream_get_byte(&next);
2215
        size = bytestream_get_be24(&next);
2216
        cts  = bytestream_get_be24(&next);
2217
        cts |= bytestream_get_byte(&next) << 24;
2218
        if (!pts)
2219
            pts = cts;
2220
        ts += cts - pts;
2221
        pts = cts;
2222
        if (size + 3 + 4 > pkt->data + pkt->size - next)
2223
            break;
2224
        bytestream_put_byte(&p, type);
2225
        bytestream_put_be24(&p, size);
2226
        bytestream_put_be24(&p, ts);
2227
        bytestream_put_byte(&p, ts >> 24);
2228
        memcpy(p, next, size + 3 + 4);
2229
        next += size + 3 + 4;
2230
        p    += size + 3 + 4;
2231
    }
2232
    if (p != rt->flv_data + rt->flv_size) {
2233
        av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in "
2234
                                     "RTMP_PT_METADATA packet\n");
2235
        rt->flv_size = p - rt->flv_data;
2236
    }
2237
 
2238
    return 0;
2239
}
2240
 
2241
/**
2242
 * Interact with the server by receiving and sending RTMP packets until
2243
 * there is some significant data (media data or expected status notification).
2244
 *
2245
 * @param s          reading context
2246
 * @param for_header non-zero value tells function to work until it
2247
 * gets notification from the server that playing has been started,
2248
 * otherwise function will work until some media data is received (or
2249
 * an error happens)
2250
 * @return 0 for successful operation, negative value in case of error
2251
 */
2252
static int get_packet(URLContext *s, int for_header)
2253
{
2254
    RTMPContext *rt = s->priv_data;
2255
    int ret;
2256
 
2257
    if (rt->state == STATE_STOPPED)
2258
        return AVERROR_EOF;
2259
 
2260
    for (;;) {
2261
        RTMPPacket rpkt = { 0 };
2262
        if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
2263
                                       rt->in_chunk_size, &rt->prev_pkt[0],
2264
                                       &rt->nb_prev_pkt[0])) <= 0) {
2265
            if (ret == 0) {
2266
                return AVERROR(EAGAIN);
2267
            } else {
2268
                return AVERROR(EIO);
2269
            }
2270
        }
2271
        rt->bytes_read += ret;
2272
        if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
2273
            av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
2274
            if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
2275
                return ret;
2276
            rt->last_bytes_read = rt->bytes_read;
2277
        }
2278
 
2279
        ret = rtmp_parse_result(s, rt, &rpkt);
2280
 
2281
        // At this point we must check if we are in the seek state and continue
2282
        // with the next packet. handle_invoke will get us out of this state
2283
        // when the right message is encountered
2284
        if (rt->state == STATE_SEEKING) {
2285
            ff_rtmp_packet_destroy(&rpkt);
2286
            // We continue, let the natural flow of things happen:
2287
            // AVERROR(EAGAIN) or handle_invoke gets us out of here
2288
            continue;
2289
        }
2290
 
2291
        if (ret < 0) {//serious error in current packet
2292
            ff_rtmp_packet_destroy(&rpkt);
2293
            return ret;
2294
        }
2295
        if (rt->do_reconnect && for_header) {
2296
            ff_rtmp_packet_destroy(&rpkt);
2297
            return 0;
2298
        }
2299
        if (rt->state == STATE_STOPPED) {
2300
            ff_rtmp_packet_destroy(&rpkt);
2301
            return AVERROR_EOF;
2302
        }
2303
        if (for_header && (rt->state == STATE_PLAYING    ||
2304
                           rt->state == STATE_PUBLISHING ||
2305
                           rt->state == STATE_SENDING    ||
2306
                           rt->state == STATE_RECEIVING)) {
2307
            ff_rtmp_packet_destroy(&rpkt);
2308
            return 0;
2309
        }
2310
        if (!rpkt.size || !rt->is_input) {
2311
            ff_rtmp_packet_destroy(&rpkt);
2312
            continue;
2313
        }
2314
        if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO) {
2315
            ret = append_flv_data(rt, &rpkt, 0);
2316
            ff_rtmp_packet_destroy(&rpkt);
2317
            return ret;
2318
        } else if (rpkt.type == RTMP_PT_NOTIFY) {
2319
            ret = handle_notify(s, &rpkt);
2320
            ff_rtmp_packet_destroy(&rpkt);
2321
            return ret;
2322
        } else if (rpkt.type == RTMP_PT_METADATA) {
2323
            ret = handle_metadata(rt, &rpkt);
2324
            ff_rtmp_packet_destroy(&rpkt);
2325
            return 0;
2326
        }
2327
        ff_rtmp_packet_destroy(&rpkt);
2328
    }
2329
}
2330
 
2331
static int rtmp_close(URLContext *h)
2332
{
2333
    RTMPContext *rt = h->priv_data;
2334
    int ret = 0, i, j;
2335
 
2336
    if (!rt->is_input) {
2337
        rt->flv_data = NULL;
2338
        if (rt->out_pkt.size)
2339
            ff_rtmp_packet_destroy(&rt->out_pkt);
2340
        if (rt->state > STATE_FCPUBLISH)
2341
            ret = gen_fcunpublish_stream(h, rt);
2342
    }
2343
    if (rt->state > STATE_HANDSHAKED)
2344
        ret = gen_delete_stream(h, rt);
2345
    for (i = 0; i < 2; i++) {
2346
        for (j = 0; j < rt->nb_prev_pkt[i]; j++)
2347
            ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
2348
        av_freep(&rt->prev_pkt[i]);
2349
    }
2350
 
2351
    free_tracked_methods(rt);
2352
    av_freep(&rt->flv_data);
2353
    ffurl_close(rt->stream);
2354
    return ret;
2355
}
2356
 
2357
/**
2358
 * Open RTMP connection and verify that the stream can be played.
2359
 *
2360
 * URL syntax: rtmp://server[:port][/app][/playpath]
2361
 *             where 'app' is first one or two directories in the path
2362
 *             (e.g. /ondemand/, /flash/live/, etc.)
2363
 *             and 'playpath' is a file name (the rest of the path,
2364
 *             may be prefixed with "mp4:")
2365
 */
2366
static int rtmp_open(URLContext *s, const char *uri, int flags)
2367
{
2368
    RTMPContext *rt = s->priv_data;
2369
    char proto[8], hostname[256], path[1024], auth[100], *fname;
2370
    char *old_app;
2371
    uint8_t buf[2048];
2372
    int port;
2373
    AVDictionary *opts = NULL;
2374
    int ret;
2375
 
2376
    if (rt->listen_timeout > 0)
2377
        rt->listen = 1;
2378
 
2379
    rt->is_input = !(flags & AVIO_FLAG_WRITE);
2380
 
2381
    av_url_split(proto, sizeof(proto), auth, sizeof(auth),
2382
                 hostname, sizeof(hostname), &port,
2383
                 path, sizeof(path), s->filename);
2384
 
2385
    if (strchr(path, ' ')) {
2386
        av_log(s, AV_LOG_WARNING,
2387
               "Detected librtmp style URL parameters, these aren't supported "
2388
               "by the libavformat internal RTMP handler currently enabled. "
2389
               "See the documentation for the correct way to pass parameters.\n");
2390
    }
2391
 
2392
    if (auth[0]) {
2393
        char *ptr = strchr(auth, ':');
2394
        if (ptr) {
2395
            *ptr = '\0';
2396
            av_strlcpy(rt->username, auth, sizeof(rt->username));
2397
            av_strlcpy(rt->password, ptr + 1, sizeof(rt->password));
2398
        }
2399
    }
2400
 
2401
    if (rt->listen && strcmp(proto, "rtmp")) {
2402
        av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n",
2403
               proto);
2404
        return AVERROR(EINVAL);
2405
    }
2406
    if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
2407
        if (!strcmp(proto, "rtmpts"))
2408
            av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
2409
 
2410
        /* open the http tunneling connection */
2411
        ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
2412
    } else if (!strcmp(proto, "rtmps")) {
2413
        /* open the tls connection */
2414
        if (port < 0)
2415
            port = RTMPS_DEFAULT_PORT;
2416
        ff_url_join(buf, sizeof(buf), "tls", NULL, hostname, port, NULL);
2417
    } else if (!strcmp(proto, "rtmpe") || (!strcmp(proto, "rtmpte"))) {
2418
        if (!strcmp(proto, "rtmpte"))
2419
            av_dict_set(&opts, "ffrtmpcrypt_tunneling", "1", 1);
2420
 
2421
        /* open the encrypted connection */
2422
        ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL);
2423
        rt->encrypted = 1;
2424
    } else {
2425
        /* open the tcp connection */
2426
        if (port < 0)
2427
            port = RTMP_DEFAULT_PORT;
2428
        if (rt->listen)
2429
            ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port,
2430
                        "?listen&listen_timeout=%d",
2431
                        rt->listen_timeout * 1000);
2432
        else
2433
            ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
2434
    }
2435
 
2436
reconnect:
2437
    if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
2438
                          &s->interrupt_callback, &opts)) < 0) {
2439
        av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
2440
        goto fail;
2441
    }
2442
 
2443
    if (rt->swfverify) {
2444
        if ((ret = rtmp_calc_swfhash(s)) < 0)
2445
            goto fail;
2446
    }
2447
 
2448
    rt->state = STATE_START;
2449
    if (!rt->listen && (ret = rtmp_handshake(s, rt)) < 0)
2450
        goto fail;
2451
    if (rt->listen && (ret = rtmp_server_handshake(s, rt)) < 0)
2452
        goto fail;
2453
 
2454
    rt->out_chunk_size = 128;
2455
    rt->in_chunk_size  = 128; // Probably overwritten later
2456
    rt->state = STATE_HANDSHAKED;
2457
 
2458
    // Keep the application name when it has been defined by the user.
2459
    old_app = rt->app;
2460
 
2461
    rt->app = av_malloc(APP_MAX_LENGTH);
2462
    if (!rt->app) {
2463
        ret = AVERROR(ENOMEM);
2464
        goto fail;
2465
    }
2466
 
2467
    //extract "app" part from path
2468
    if (!strncmp(path, "/ondemand/", 10)) {
2469
        fname = path + 10;
2470
        memcpy(rt->app, "ondemand", 9);
2471
    } else {
2472
        char *next = *path ? path + 1 : path;
2473
        char *p = strchr(next, '/');
2474
        if (!p) {
2475
            fname = next;
2476
            rt->app[0] = '\0';
2477
        } else {
2478
            // make sure we do not mismatch a playpath for an application instance
2479
            char *c = strchr(p + 1, ':');
2480
            fname = strchr(p + 1, '/');
2481
            if (!fname || (c && c < fname)) {
2482
                fname = p + 1;
2483
                av_strlcpy(rt->app, path + 1, FFMIN(p - path, APP_MAX_LENGTH));
2484
            } else {
2485
                fname++;
2486
                av_strlcpy(rt->app, path + 1, FFMIN(fname - path - 1, APP_MAX_LENGTH));
2487
            }
2488
        }
2489
    }
2490
 
2491
    if (old_app) {
2492
        // The name of application has been defined by the user, override it.
2493
        if (strlen(old_app) >= APP_MAX_LENGTH) {
2494
            ret = AVERROR(EINVAL);
2495
            goto fail;
2496
        }
2497
        av_free(rt->app);
2498
        rt->app = old_app;
2499
    }
2500
 
2501
    if (!rt->playpath) {
2502
        int len = strlen(fname);
2503
 
2504
        rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
2505
        if (!rt->playpath) {
2506
            ret = AVERROR(ENOMEM);
2507
            goto fail;
2508
        }
2509
 
2510
        if (!strchr(fname, ':') && len >= 4 &&
2511
            (!strcmp(fname + len - 4, ".f4v") ||
2512
             !strcmp(fname + len - 4, ".mp4"))) {
2513
            memcpy(rt->playpath, "mp4:", 5);
2514
        } else if (len >= 4 && !strcmp(fname + len - 4, ".flv")) {
2515
            fname[len - 4] = '\0';
2516
        } else {
2517
            rt->playpath[0] = 0;
2518
        }
2519
        av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH);
2520
    }
2521
 
2522
    if (!rt->tcurl) {
2523
        rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
2524
        if (!rt->tcurl) {
2525
            ret = AVERROR(ENOMEM);
2526
            goto fail;
2527
        }
2528
        ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
2529
                    port, "/%s", rt->app);
2530
    }
2531
 
2532
    if (!rt->flashver) {
2533
        rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
2534
        if (!rt->flashver) {
2535
            ret = AVERROR(ENOMEM);
2536
            goto fail;
2537
        }
2538
        if (rt->is_input) {
2539
            snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
2540
                    RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
2541
                    RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
2542
        } else {
2543
            snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
2544
                    "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
2545
        }
2546
    }
2547
 
2548
    rt->client_report_size = 1048576;
2549
    rt->bytes_read = 0;
2550
    rt->last_bytes_read = 0;
2551
    rt->server_bw = 2500000;
2552
 
2553
    av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
2554
           proto, path, rt->app, rt->playpath);
2555
    if (!rt->listen) {
2556
        if ((ret = gen_connect(s, rt)) < 0)
2557
            goto fail;
2558
    } else {
2559
        if (read_connect(s, s->priv_data) < 0)
2560
            goto fail;
2561
    }
2562
 
2563
    do {
2564
        ret = get_packet(s, 1);
2565
    } while (ret == AVERROR(EAGAIN));
2566
    if (ret < 0)
2567
        goto fail;
2568
 
2569
    if (rt->do_reconnect) {
2570
        int i;
2571
        ffurl_close(rt->stream);
2572
        rt->stream       = NULL;
2573
        rt->do_reconnect = 0;
2574
        rt->nb_invokes   = 0;
2575
        for (i = 0; i < 2; i++)
2576
            memset(rt->prev_pkt[i], 0,
2577
                   sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
2578
        free_tracked_methods(rt);
2579
        goto reconnect;
2580
    }
2581
 
2582
    if (rt->is_input) {
2583
        int err;
2584
        // generate FLV header for demuxer
2585
        rt->flv_size = 13;
2586
        if ((err = av_reallocp(&rt->flv_data, rt->flv_size)) < 0)
2587
            return err;
2588
        rt->flv_off  = 0;
2589
        memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
2590
    } else {
2591
        rt->flv_size = 0;
2592
        rt->flv_data = NULL;
2593
        rt->flv_off  = 0;
2594
        rt->skip_bytes = 13;
2595
    }
2596
 
2597
    s->max_packet_size = rt->stream->max_packet_size;
2598
    s->is_streamed     = 1;
2599
    return 0;
2600
 
2601
fail:
2602
    av_dict_free(&opts);
2603
    rtmp_close(s);
2604
    return ret;
2605
}
2606
 
2607
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
2608
{
2609
    RTMPContext *rt = s->priv_data;
2610
    int orig_size = size;
2611
    int ret;
2612
 
2613
    while (size > 0) {
2614
        int data_left = rt->flv_size - rt->flv_off;
2615
 
2616
        if (data_left >= size) {
2617
            memcpy(buf, rt->flv_data + rt->flv_off, size);
2618
            rt->flv_off += size;
2619
            return orig_size;
2620
        }
2621
        if (data_left > 0) {
2622
            memcpy(buf, rt->flv_data + rt->flv_off, data_left);
2623
            buf  += data_left;
2624
            size -= data_left;
2625
            rt->flv_off = rt->flv_size;
2626
            return data_left;
2627
        }
2628
        if ((ret = get_packet(s, 0)) < 0)
2629
           return ret;
2630
    }
2631
    return orig_size;
2632
}
2633
 
2634
static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp,
2635
                         int flags)
2636
{
2637
    RTMPContext *rt = s->priv_data;
2638
    int ret;
2639
    av_log(s, AV_LOG_DEBUG,
2640
           "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n",
2641
           stream_index, timestamp, flags);
2642
    if ((ret = gen_seek(s, rt, timestamp)) < 0) {
2643
        av_log(s, AV_LOG_ERROR,
2644
               "Unable to send seek command on stream index %d at timestamp "
2645
               "%"PRId64" with flags %08x\n",
2646
               stream_index, timestamp, flags);
2647
        return ret;
2648
    }
2649
    rt->flv_off = rt->flv_size;
2650
    rt->state = STATE_SEEKING;
2651
    return timestamp;
2652
}
2653
 
2654
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
2655
{
2656
    RTMPContext *rt = s->priv_data;
2657
    int size_temp = size;
2658
    int pktsize, pkttype;
2659
    uint32_t ts;
2660
    const uint8_t *buf_temp = buf;
2661
    uint8_t c;
2662
    int ret;
2663
 
2664
    do {
2665
        if (rt->skip_bytes) {
2666
            int skip = FFMIN(rt->skip_bytes, size_temp);
2667
            buf_temp       += skip;
2668
            size_temp      -= skip;
2669
            rt->skip_bytes -= skip;
2670
            continue;
2671
        }
2672
 
2673
        if (rt->flv_header_bytes < RTMP_HEADER) {
2674
            const uint8_t *header = rt->flv_header;
2675
            int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
2676
            int channel = RTMP_AUDIO_CHANNEL;
2677
            bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
2678
            rt->flv_header_bytes += copy;
2679
            size_temp            -= copy;
2680
            if (rt->flv_header_bytes < RTMP_HEADER)
2681
                break;
2682
 
2683
            pkttype = bytestream_get_byte(&header);
2684
            pktsize = bytestream_get_be24(&header);
2685
            ts = bytestream_get_be24(&header);
2686
            ts |= bytestream_get_byte(&header) << 24;
2687
            bytestream_get_be24(&header);
2688
            rt->flv_size = pktsize;
2689
 
2690
            if (pkttype == RTMP_PT_VIDEO)
2691
                channel = RTMP_VIDEO_CHANNEL;
2692
 
2693
            //force 12bytes header
2694
            if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
2695
                pkttype == RTMP_PT_NOTIFY) {
2696
                if (pkttype == RTMP_PT_NOTIFY)
2697
                    pktsize += 16;
2698
                if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
2699
                                                     &rt->nb_prev_pkt[1],
2700
                                                     channel)) < 0)
2701
                    return ret;
2702
                rt->prev_pkt[1][channel].channel_id = 0;
2703
            }
2704
 
2705
            //this can be a big packet, it's better to send it right here
2706
            if ((ret = ff_rtmp_packet_create(&rt->out_pkt, channel,
2707
                                             pkttype, ts, pktsize)) < 0)
2708
                return ret;
2709
 
2710
            rt->out_pkt.extra = rt->stream_id;
2711
            rt->flv_data = rt->out_pkt.data;
2712
 
2713
            if (pkttype == RTMP_PT_NOTIFY)
2714
                ff_amf_write_string(&rt->flv_data, "@setDataFrame");
2715
        }
2716
 
2717
        if (rt->flv_size - rt->flv_off > size_temp) {
2718
            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
2719
            rt->flv_off += size_temp;
2720
            size_temp = 0;
2721
        } else {
2722
            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
2723
            size_temp   -= rt->flv_size - rt->flv_off;
2724
            rt->flv_off += rt->flv_size - rt->flv_off;
2725
        }
2726
 
2727
        if (rt->flv_off == rt->flv_size) {
2728
            rt->skip_bytes = 4;
2729
 
2730
            if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
2731
                return ret;
2732
            rt->flv_size = 0;
2733
            rt->flv_off = 0;
2734
            rt->flv_header_bytes = 0;
2735
            rt->flv_nb_packets++;
2736
        }
2737
    } while (buf_temp - buf < size);
2738
 
2739
    if (rt->flv_nb_packets < rt->flush_interval)
2740
        return size;
2741
    rt->flv_nb_packets = 0;
2742
 
2743
    /* set stream into nonblocking mode */
2744
    rt->stream->flags |= AVIO_FLAG_NONBLOCK;
2745
 
2746
    /* try to read one byte from the stream */
2747
    ret = ffurl_read(rt->stream, &c, 1);
2748
 
2749
    /* switch the stream back into blocking mode */
2750
    rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
2751
 
2752
    if (ret == AVERROR(EAGAIN)) {
2753
        /* no incoming data to handle */
2754
        return size;
2755
    } else if (ret < 0) {
2756
        return ret;
2757
    } else if (ret == 1) {
2758
        RTMPPacket rpkt = { 0 };
2759
 
2760
        if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
2761
                                                rt->in_chunk_size,
2762
                                                &rt->prev_pkt[0],
2763
                                                &rt->nb_prev_pkt[0], c)) <= 0)
2764
             return ret;
2765
 
2766
        if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
2767
            return ret;
2768
 
2769
        ff_rtmp_packet_destroy(&rpkt);
2770
    }
2771
 
2772
    return size;
2773
}
2774
 
2775
#define OFFSET(x) offsetof(RTMPContext, x)
2776
#define DEC AV_OPT_FLAG_DECODING_PARAM
2777
#define ENC AV_OPT_FLAG_ENCODING_PARAM
2778
 
2779
static const AVOption rtmp_options[] = {
2780
    {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2781
    {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
2782
    {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2783
    {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2784
    {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
2785
    {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
2786
    {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
2787
    {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
2788
    {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
2789
    {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2790
    {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2791
    {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2792
    {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
2793
    {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
2794
    {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2795
    {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
2796
    {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
2797
    {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2798
    {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2799
    {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
2800
    { NULL },
2801
};
2802
 
2803
#define RTMP_PROTOCOL(flavor)                    \
2804
static const AVClass flavor##_class = {          \
2805
    .class_name = #flavor,                       \
2806
    .item_name  = av_default_item_name,          \
2807
    .option     = rtmp_options,                  \
2808
    .version    = LIBAVUTIL_VERSION_INT,         \
2809
};                                               \
2810
                                                 \
2811
URLProtocol ff_##flavor##_protocol = {           \
2812
    .name           = #flavor,                   \
2813
    .url_open       = rtmp_open,                 \
2814
    .url_read       = rtmp_read,                 \
2815
    .url_read_seek  = rtmp_seek,                 \
2816
    .url_write      = rtmp_write,                \
2817
    .url_close      = rtmp_close,                \
2818
    .priv_data_size = sizeof(RTMPContext),       \
2819
    .flags          = URL_PROTOCOL_FLAG_NETWORK, \
2820
    .priv_data_class= &flavor##_class,           \
2821
};
2822
 
2823
 
2824
RTMP_PROTOCOL(rtmp)
2825
RTMP_PROTOCOL(rtmpe)
2826
RTMP_PROTOCOL(rtmps)
2827
RTMP_PROTOCOL(rtmpt)
2828
RTMP_PROTOCOL(rtmpte)
2829
RTMP_PROTOCOL(rtmpts)