Coverage Report

Created: 2026-01-26 07:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpv/stream/stream.c
Line
Count
Source
1
/*
2
 * This file is part of mpv.
3
 *
4
 * mpv is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * mpv is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with mpv.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#include <stdio.h>
19
#include <stdlib.h>
20
#include <limits.h>
21
22
#include <assert.h>
23
24
#include "osdep/io.h"
25
26
#include "mpv_talloc.h"
27
28
#include "config.h"
29
30
#include "common/common.h"
31
#include "common/global.h"
32
#include "demux/demux.h"
33
#include "misc/bstr.h"
34
#include "misc/thread_tools.h"
35
#include "common/msg.h"
36
#include "options/m_config.h"
37
#include "options/options.h"
38
#include "options/path.h"
39
#include "osdep/timer.h"
40
#include "stream.h"
41
42
#include "options/m_option.h"
43
#include "options/m_config.h"
44
45
extern const stream_info_t stream_info_mpv;
46
extern const stream_info_t stream_info_cdda;
47
extern const stream_info_t stream_info_dvb;
48
extern const stream_info_t stream_info_null;
49
extern const stream_info_t stream_info_memory;
50
extern const stream_info_t stream_info_mf;
51
extern const stream_info_t stream_info_ffmpeg;
52
extern const stream_info_t stream_info_ffmpeg_unsafe;
53
extern const stream_info_t stream_info_avdevice;
54
extern const stream_info_t stream_info_file;
55
extern const stream_info_t stream_info_slice;
56
extern const stream_info_t stream_info_fd;
57
extern const stream_info_t stream_info_ifo_dvdnav;
58
extern const stream_info_t stream_info_dvdnav;
59
extern const stream_info_t stream_info_bdmv_dir;
60
extern const stream_info_t stream_info_bluray;
61
extern const stream_info_t stream_info_edl;
62
extern const stream_info_t stream_info_libarchive;
63
extern const stream_info_t stream_info_cb;
64
65
static const stream_info_t *const stream_list[] = {
66
    &stream_info_mpv,
67
#if HAVE_CDDA
68
    &stream_info_cdda,
69
#endif
70
    &stream_info_avdevice,
71
#if HAVE_DVBIN
72
    &stream_info_dvb,
73
#endif
74
#if HAVE_DVDNAV
75
    &stream_info_ifo_dvdnav,
76
    &stream_info_dvdnav,
77
#endif
78
#if HAVE_LIBBLURAY
79
    &stream_info_bdmv_dir,
80
    &stream_info_bluray,
81
#endif
82
#if HAVE_LIBARCHIVE
83
    &stream_info_libarchive,
84
#endif
85
    &stream_info_memory,
86
    &stream_info_null,
87
    &stream_info_mf,
88
    &stream_info_edl,
89
    &stream_info_file,
90
    &stream_info_slice,
91
    &stream_info_fd,
92
    &stream_info_cb,
93
    &stream_info_ffmpeg,
94
    &stream_info_ffmpeg_unsafe,
95
};
96
97
// Because of guarantees documented on STREAM_BUFFER_SIZE.
98
// Half the buffer is used as forward buffer, the other for seek-back.
99
#define STREAM_MIN_BUFFER_SIZE (STREAM_BUFFER_SIZE * 2)
100
// Sort of arbitrary; keep *2 of it comfortably within integer limits.
101
// Must be power of 2.
102
#define STREAM_MAX_BUFFER_SIZE (512 * 1024 * 1024)
103
104
struct stream_opts {
105
    int64_t buffer_size;
106
    bool load_unsafe_playlists;
107
};
108
109
#define OPT_BASE_STRUCT struct stream_opts
110
111
const struct m_sub_options stream_conf = {
112
    .opts = (const struct m_option[]){
113
        {"stream-buffer-size", OPT_BYTE_SIZE(buffer_size),
114
            M_RANGE(STREAM_MIN_BUFFER_SIZE, STREAM_MAX_BUFFER_SIZE)},
115
        {"load-unsafe-playlists", OPT_BOOL(load_unsafe_playlists)},
116
        {0}
117
    },
118
    .size = sizeof(struct stream_opts),
119
    .defaults = &(const struct stream_opts){
120
        .buffer_size = 128 * 1024,
121
    },
122
};
123
124
// return -1 if not hex char
125
static int hex2dec(char c)
126
85.0M
{
127
85.0M
    if (c >= '0' && c <= '9')
128
4.66M
        return c - '0';
129
80.4M
    if (c >= 'A' && c <= 'F')
130
15.4M
        return 10 + c - 'A';
131
64.9M
    if (c >= 'a' && c <= 'f')
132
2.00M
        return 10 + c - 'a';
133
62.9M
    return -1;
134
64.9M
}
135
136
// Replace escape sequences in an URL (or a part of an URL)
137
void mp_url_unescape_inplace(char *url)
138
3.08M
{
139
36.0G
    for (int len = strlen(url), i = 0, o = 0; i <= len;) {
140
36.0G
        if ((url[i] != '%') || (i > len - 3)) {  // %NN can't start after len-3
141
36.0G
            url[o++] = url[i++];
142
36.0G
            continue;
143
36.0G
        }
144
145
42.5M
        int msd = hex2dec(url[i + 1]),
146
42.5M
            lsd = hex2dec(url[i + 2]);
147
148
42.5M
        if (msd >= 0 && lsd >= 0) {
149
801k
            url[o++] = 16 * msd + lsd;
150
801k
            i += 3;
151
41.7M
        } else {
152
41.7M
            url[o++] = url[i++];
153
41.7M
            url[o++] = url[i++];
154
41.7M
            url[o++] = url[i++];
155
41.7M
        }
156
42.5M
    }
157
3.08M
}
158
159
char *mp_url_unescape(void *talloc_ctx, char *url)
160
9.91k
{
161
9.91k
    char *unescaped = talloc_strdup(talloc_ctx, url);
162
9.91k
    mp_url_unescape_inplace(unescaped);
163
9.91k
    return unescaped;
164
9.91k
}
165
166
static const char hex_digits[] = "0123456789ABCDEF";
167
168
169
static const char url_default_ok[] = "abcdefghijklmnopqrstuvwxyz"
170
                                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
171
                                     "0123456789"
172
                                     "-._~";
173
174
// Escape according to http://tools.ietf.org/html/rfc3986#section-2.1
175
// Only unreserved characters are not escaped.
176
// The argument ok (if not NULL) is as follows:
177
//      ok[0] != '~': additional characters that are not escaped
178
//      ok[0] == '~': do not escape anything but these characters
179
//                    (can't override the unreserved characters, which are
180
//                     never escaped)
181
char *mp_url_escape(void *talloc_ctx, const char *url, const char *ok)
182
125
{
183
125
    char *rv = talloc_size(talloc_ctx, strlen(url) * 3 + 1);
184
125
    char *out = rv;
185
125
    bool negate = ok && ok[0] == '~';
186
187
27.7k
    for (char c; (c = *url); url++) {
188
27.6k
        bool as_is = negate ? !strchr(ok + 1, c)
189
27.6k
                            : (strchr(url_default_ok, c) || (ok && strchr(ok, c)));
190
27.6k
        if (as_is) {
191
12.2k
            *out++ = c;
192
15.4k
        } else {
193
15.4k
            unsigned char v = c;
194
15.4k
            *out++ = '%';
195
15.4k
            *out++ = hex_digits[v / 16];
196
15.4k
            *out++ = hex_digits[v % 16];
197
15.4k
        }
198
27.6k
    }
199
200
125
    *out = 0;
201
125
    return rv;
202
125
}
203
204
static const char *match_proto(const char *url, const char *proto)
205
2.27M
{
206
2.27M
    int l = strlen(proto);
207
2.27M
    if (l > 0) {
208
2.18M
        if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
209
320k
            return url + l + 3;
210
2.18M
    } else if (!mp_is_url(bstr0(url))) {
211
6.17k
        return url; // pure filenames
212
6.17k
    }
213
1.95M
    return NULL;
214
2.27M
}
215
216
// src and new are both STREAM_ORIGIN_* values. This checks whether a stream
217
// with flags "new" can be opened from the "src". On success, return
218
// new origin, on incompatibility return 0.
219
static int check_origin(int src, int new)
220
153k
{
221
153k
    switch (src) {
222
115k
    case STREAM_ORIGIN_DIRECT:
223
117k
    case STREAM_ORIGIN_UNSAFE:
224
        // Allow anything, but constrain it to the new origin.
225
117k
        return new;
226
19.8k
    case STREAM_ORIGIN_FS:
227
        // From unix FS, allow all but unsafe.
228
19.8k
        if (new == STREAM_ORIGIN_FS || new == STREAM_ORIGIN_NET)
229
8.58k
            return new;
230
11.2k
        break;
231
16.6k
    case STREAM_ORIGIN_NET:
232
        // Allow only other network links.
233
16.6k
        if (new == STREAM_ORIGIN_NET)
234
8.16k
            return new;
235
8.45k
        break;
236
153k
    }
237
19.6k
    return 0;
238
153k
}
239
240
// Read len bytes from the start position, and wrap around as needed. Limit the
241
// actually read data to the size of the buffer. Return amount of copied bytes.
242
//  len: max bytes to copy to dst
243
//  pos: index into s->buffer[], e.g. s->buf_start is byte 0
244
//  returns: bytes copied to dst (limited by len and available buffered data)
245
static int ring_copy(struct stream *s, void *dst, int len, int pos)
246
4.42M
{
247
4.42M
    mp_assert(len >= 0);
248
249
4.42M
    if (pos < s->buf_start || pos > s->buf_end)
250
0
        return 0;
251
252
4.42M
    int copied = 0;
253
4.42M
    len = MPMIN(len, s->buf_end - pos);
254
255
4.42M
    if (len && pos <= s->buffer_mask) {
256
3.63M
        int copy = MPMIN(len, s->buffer_mask + 1 - pos);
257
3.63M
        memcpy(dst, &s->buffer[pos], copy);
258
3.63M
        copied += copy;
259
3.63M
        len -= copy;
260
3.63M
        pos += copy;
261
3.63M
    }
262
263
4.42M
    if (len) {
264
1.84k
        memcpy((char *)dst + copied, &s->buffer[pos & s->buffer_mask], len);
265
1.84k
        copied += len;
266
1.84k
    }
267
268
4.42M
    return copied;
269
4.42M
}
270
271
// Resize the current stream buffer. Uses a larger size if needed to keep data.
272
// Does nothing if the size is adequate. Calling this with 0 ensures it uses the
273
// default buffer size if possible.
274
// The caller must check whether enough data was really allocated.
275
//  keep: keep at least [buf_end-keep, buf_end] (used for mp_assert()s only)
276
//  new: new total size of buffer
277
//  returns: false if buffer allocation failed, true if reallocated or size ok
278
static bool stream_resize_buffer(struct stream *s, int keep, int new)
279
2.17M
{
280
2.17M
    mp_assert(keep >= s->buf_end - s->buf_cur);
281
2.17M
    mp_assert(keep <= new);
282
283
2.17M
    new = MPMAX(new, s->requested_buffer_size);
284
2.17M
    new = MPMIN(new, STREAM_MAX_BUFFER_SIZE);
285
2.17M
    new = mp_round_next_power_of_2(new);
286
287
2.17M
    mp_assert(keep <= new); // can't fail (if old buffer size was valid)
288
289
2.17M
    if (new == s->buffer_mask + 1)
290
1.86M
        return true;
291
292
315k
    int old_pos = s->buf_cur - s->buf_start;
293
315k
    int old_used_len = s->buf_end - s->buf_start;
294
315k
    int skip = old_used_len > new ? old_used_len - new : 0;
295
296
315k
    MP_DBG(s, "resize stream to %d bytes, drop %d bytes\n", new, skip);
297
298
315k
    void *nbuf = ta_alloc_size(s, new);
299
315k
    if (!nbuf)
300
0
        return false; // oom; tolerate it, caller needs to check if required
301
302
315k
    int new_len = 0;
303
315k
    if (s->buffer)
304
2.52k
        new_len = ring_copy(s, nbuf, new, s->buf_start + skip);
305
315k
    mp_assert(new_len == old_used_len - skip);
306
315k
    mp_assert(old_pos >= skip); // "keep" too low
307
315k
    mp_assert(old_pos - skip <= new_len);
308
315k
    s->buf_start = 0;
309
315k
    s->buf_cur = old_pos - skip;
310
315k
    s->buf_end = new_len;
311
312
315k
    ta_free(s->buffer);
313
314
315k
    s->buffer = nbuf;
315
315k
    s->buffer_mask = new - 1;
316
317
315k
    return true;
318
315k
}
319
320
static int stream_create_instance(const stream_info_t *sinfo,
321
                                  struct stream_open_args *args,
322
                                  struct stream **ret)
323
1.49M
{
324
1.49M
    const char *url = args->url;
325
1.49M
    int flags = args->flags;
326
327
1.49M
    *ret = NULL;
328
329
1.49M
    const char *path = url;
330
331
1.49M
    if (flags & STREAM_LOCAL_FS_ONLY) {
332
0
        if (!sinfo->local_fs)
333
0
            return STREAM_NO_MATCH;
334
1.49M
    } else {
335
1.49M
        char **get_protocols = sinfo->get_protocols ? sinfo->get_protocols() : NULL;
336
1.49M
        char **protocols = get_protocols ? get_protocols : (char **)sinfo->protocols;
337
338
3.44M
        for (int n = 0; protocols && protocols[n]; n++) {
339
2.27M
            path = match_proto(url, protocols[n]);
340
2.27M
            if (path)
341
326k
                break;
342
2.27M
        }
343
344
1.49M
        talloc_free(get_protocols);
345
346
1.49M
        if (!path)
347
1.12M
            return STREAM_NO_MATCH;
348
1.49M
    }
349
350
369k
    stream_t *s = talloc_zero(NULL, stream_t);
351
369k
    s->global = args->global;
352
369k
    struct stream_opts *opts = mp_get_config_group(s, s->global, &stream_conf);
353
369k
    if (flags & STREAM_SILENT) {
354
168k
        s->log = mp_null_log;
355
201k
    } else {
356
201k
        s->log = mp_log_new(s, s->global->log, sinfo->name);
357
201k
    }
358
369k
    s->info = sinfo;
359
369k
    s->cancel = args->cancel;
360
369k
    s->url = talloc_strdup(s, url);
361
369k
    s->path = talloc_strdup(s, path);
362
369k
    s->mode = flags & (STREAM_READ | STREAM_WRITE);
363
369k
    s->requested_buffer_size = opts->buffer_size;
364
369k
    s->allow_partial_read = flags & STREAM_ALLOW_PARTIAL_READ;
365
366
369k
    if (flags & STREAM_LESS_NOISE)
367
0
        mp_msg_set_max_level(s->log, MSGL_WARN);
368
369
369k
    struct demux_opts *demux_opts = mp_get_config_group(s, s->global, &demux_conf);
370
369k
    s->access_references = demux_opts->access_references;
371
369k
    talloc_free(demux_opts);
372
373
369k
    MP_VERBOSE(s, "Opening %s\n", url);
374
375
369k
    if (strlen(url) > INT_MAX / 8) {
376
0
        MP_ERR(s, "URL too large.\n");
377
0
        talloc_free(s);
378
0
        return STREAM_ERROR;
379
0
    }
380
381
369k
    if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
382
0
        MP_DBG(s, "No write access implemented.\n");
383
0
        talloc_free(s);
384
0
        return STREAM_NO_MATCH;
385
0
    }
386
387
369k
    s->stream_origin = flags & STREAM_ORIGIN_MASK; // pass through by default
388
369k
    if (opts->load_unsafe_playlists) {
389
2
        s->stream_origin = STREAM_ORIGIN_DIRECT;
390
369k
    } else if (sinfo->stream_origin) {
391
153k
        s->stream_origin = check_origin(s->stream_origin, sinfo->stream_origin);
392
153k
    }
393
394
369k
    if (!s->stream_origin) {
395
19.6k
        talloc_free(s);
396
19.6k
        return STREAM_UNSAFE;
397
19.6k
    }
398
399
349k
    int r = STREAM_UNSUPPORTED;
400
349k
    if (sinfo->open2) {
401
259k
        r = sinfo->open2(s, args);
402
259k
    } else if (!args->special_arg) {
403
90.5k
        r = (sinfo->open)(s);
404
90.5k
    }
405
349k
    if (r != STREAM_OK) {
406
37.0k
        talloc_free(s);
407
37.0k
        return r;
408
37.0k
    }
409
410
312k
    if (!stream_resize_buffer(s, 0, 0)) {
411
0
        free_stream(s);
412
0
        return STREAM_ERROR;
413
0
    }
414
415
312k
    mp_assert(s->seekable == !!s->seek);
416
417
312k
    if (s->mime_type)
418
312k
        MP_VERBOSE(s, "Mime-type: '%s'\n", s->mime_type);
419
420
312k
    MP_DBG(s, "Stream opened successfully.\n");
421
422
312k
    *ret = s;
423
312k
    return STREAM_OK;
424
312k
}
425
426
int stream_create_with_args(struct stream_open_args *args, struct stream **ret)
427
336k
{
428
336k
    mp_assert(args->url);
429
430
336k
    int r = STREAM_NO_MATCH;
431
336k
    *ret = NULL;
432
433
    // Open stream proper
434
336k
    if (args->sinfo) {
435
168k
        r = stream_create_instance(args->sinfo, args, ret);
436
168k
    } else {
437
1.33M
        for (int i = 0; i < MP_ARRAY_SIZE(stream_list); i++) {
438
1.32M
            r = stream_create_instance(stream_list[i], args, ret);
439
1.32M
            if (r == STREAM_OK)
440
144k
                break;
441
1.17M
            if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
442
1.14M
                continue;
443
31.2k
            if (r == STREAM_UNSAFE)
444
19.6k
                continue;
445
11.5k
            break;
446
31.2k
        }
447
168k
    }
448
449
336k
    if (!*ret && !(args->flags & STREAM_SILENT) && !mp_cancel_test(args->cancel))
450
24.1k
    {
451
24.1k
        struct mp_log *log = mp_log_new(NULL, args->global->log, "!stream");
452
453
24.1k
        if (r == STREAM_UNSAFE) {
454
370
            mp_err(log, "\nRefusing to load potentially unsafe URL from a playlist.\n"
455
370
                   "Use the --load-unsafe-playlists option to load it anyway.\n\n");
456
23.7k
        } else if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED) {
457
12.1k
            mp_err(log, "No protocol handler found to open URL %s\n", args->url);
458
12.1k
            mp_err(log, "The protocol is either unsupported, or was disabled "
459
12.1k
                        "at compile-time.\n");
460
12.1k
        } else {
461
11.5k
            mp_err(log, "Failed to open %s.\n", args->url);
462
11.5k
        }
463
464
24.1k
        talloc_free(log);
465
24.1k
    }
466
467
336k
    return r;
468
336k
}
469
470
struct stream *stream_create(const char *url, int flags,
471
                             struct mp_cancel *c, struct mpv_global *global)
472
164k
{
473
164k
    struct stream_open_args args = {
474
164k
        .global = global,
475
164k
        .cancel = c,
476
164k
        .flags = flags,
477
164k
        .url = url,
478
164k
    };
479
164k
    struct stream *s;
480
164k
    stream_create_with_args(&args, &s);
481
164k
    return s;
482
164k
}
483
484
stream_t *open_output_stream(const char *filename, struct mpv_global *global)
485
0
{
486
0
    struct stream *s = stream_create(filename, STREAM_ORIGIN_DIRECT | STREAM_WRITE,
487
0
                                     NULL, global);
488
0
    if (s && s->is_directory) {
489
0
        free_stream(s);
490
0
        s = NULL;
491
0
    }
492
0
    return s;
493
0
}
494
495
// Read function bypassing the local stream buffer. This will not write into
496
// s->buffer, but into buf[0..len] instead.
497
// Returns 0 on error or EOF, and length of bytes read on success.
498
// Partial reads are possible, even if EOF is not reached.
499
static int stream_read_unbuffered(stream_t *s, void *buf, int len)
500
1.85M
{
501
1.85M
    mp_assert(len >= 0);
502
1.85M
    if (len <= 0)
503
0
        return 0;
504
505
1.85M
    int res = 0;
506
    // we will retry even if we already reached EOF previously.
507
1.85M
    if (s->fill_buffer && !mp_cancel_test(s->cancel))
508
1.85M
        res = s->fill_buffer(s, buf, len);
509
1.85M
    if (res <= 0) {
510
1.51M
        s->eof = 1;
511
1.51M
        return 0;
512
1.51M
    }
513
345k
    mp_assert(res <= len);
514
    // When reading succeeded we are obviously not at eof.
515
345k
    s->eof = 0;
516
345k
    s->pos += res;
517
345k
    s->total_unbuffered_read_bytes += res;
518
345k
    return res;
519
345k
}
520
521
// Ask for having at most "forward" bytes ready to read in the buffer.
522
// To read everything, you may have to call this in a loop.
523
//  forward: desired amount of bytes in buffer after s->cur_pos
524
//  returns: progress (false on EOF or on OOM or if enough data was available)
525
static bool stream_read_more(struct stream *s, int forward)
526
4.29M
{
527
4.29M
    mp_assert(forward >= 0);
528
529
4.29M
    int forward_avail = s->buf_end - s->buf_cur;
530
4.29M
    if (forward_avail >= forward)
531
2.47M
        return false;
532
533
    // Avoid that many small reads will lead to many low-level read calls.
534
1.81M
    forward = MPMAX(forward, s->requested_buffer_size / 2);
535
1.81M
    mp_assert(forward_avail < forward);
536
537
    // Keep guaranteed seek-back.
538
1.81M
    int buf_old = MPMIN(s->buf_cur - s->buf_start, s->requested_buffer_size / 2);
539
540
1.81M
    if (!stream_resize_buffer(s, buf_old + forward_avail, buf_old + forward))
541
0
        return false;
542
543
1.81M
    int buf_alloc = s->buffer_mask + 1;
544
545
1.81M
    mp_assert(s->buf_start <= s->buf_cur);
546
1.81M
    mp_assert(s->buf_cur <= s->buf_end);
547
1.81M
    mp_assert(s->buf_cur < buf_alloc * 2);
548
1.81M
    mp_assert(s->buf_end < buf_alloc * 2);
549
1.81M
    mp_assert(s->buf_start < buf_alloc);
550
551
    // Note: read as much as possible, even if forward is much smaller. Do
552
    // this because the stream buffer is supposed to set an approx. minimum
553
    // read size on it.
554
1.81M
    int read = buf_alloc - (buf_old + forward_avail); // free buffer past end
555
556
1.81M
    int pos = s->buf_end & s->buffer_mask;
557
1.81M
    read = MPMIN(read, buf_alloc - pos);
558
559
    // Note: if wrap-around happens, we need to make two calls. This may
560
    // affect latency (e.g. waiting for new data on a socket), so do only
561
    // 1 read call always.
562
1.81M
    read = stream_read_unbuffered(s, &s->buffer[pos], read);
563
564
1.81M
    s->buf_end += read;
565
566
    // May have overwritten old data.
567
1.81M
    if (s->buf_end - s->buf_start >= buf_alloc) {
568
1.97k
        mp_assert(s->buf_end >= buf_alloc);
569
570
1.97k
        s->buf_start = s->buf_end - buf_alloc;
571
572
1.97k
        mp_assert(s->buf_start <= s->buf_cur);
573
1.97k
        mp_assert(s->buf_cur <= s->buf_end);
574
575
1.97k
        if (s->buf_start >= buf_alloc) {
576
3
            s->buf_start -= buf_alloc;
577
3
            s->buf_cur -= buf_alloc;
578
3
            s->buf_end -= buf_alloc;
579
3
        }
580
1.97k
    }
581
582
    // Must not have overwritten guaranteed old data.
583
1.81M
    mp_assert(s->buf_cur - s->buf_start >= buf_old);
584
585
1.81M
    if (s->buf_cur < s->buf_end)
586
1.01M
        s->eof = 0;
587
588
1.81M
    return !!read;
589
1.81M
}
590
591
// Read between 1..buf_size bytes of data, return how much data has been read.
592
// Return 0 on EOF, error, or if buf_size was 0.
593
int stream_read_partial(stream_t *s, void *buf, int buf_size)
594
1.03M
{
595
1.03M
    mp_assert(s->buf_cur <= s->buf_end);
596
1.03M
    mp_assert(buf_size >= 0);
597
1.03M
    if (s->buf_cur == s->buf_end && buf_size > 0) {
598
640k
        if (buf_size > (s->buffer_mask + 1) / 2) {
599
            // Direct read if the buffer is too small anyway.
600
45.0k
            stream_drop_buffers(s);
601
45.0k
            return stream_read_unbuffered(s, buf, buf_size);
602
45.0k
        }
603
595k
        stream_read_more(s, 1);
604
595k
    }
605
989k
    int res = ring_copy(s, buf, buf_size, s->buf_cur);
606
989k
    s->buf_cur += res;
607
989k
    return res;
608
1.03M
}
609
610
// Slow version of stream_read_char(); called by it if the buffer is empty.
611
int stream_read_char_fallback(stream_t *s)
612
22.9k
{
613
22.9k
    uint8_t c;
614
22.9k
    return stream_read_partial(s, &c, 1) ? c : STREAM_EOF;
615
22.9k
}
616
617
int stream_read(stream_t *s, void *mem, int total)
618
582k
{
619
582k
    int len = total;
620
993k
    while (len > 0) {
621
445k
        int read = stream_read_partial(s, mem, len);
622
445k
        if (read <= 0)
623
33.8k
            break; // EOF
624
411k
        mem = (char *)mem + read;
625
411k
        len -= read;
626
411k
    }
627
582k
    total -= len;
628
582k
    return total;
629
582k
}
630
631
// Read ahead so that at least forward_size bytes are readable ahead. Returns
632
// the actual forward amount available (restricted by EOF or buffer limits).
633
int stream_peek(stream_t *s, int forward_size)
634
3.43M
{
635
3.68M
    while (stream_read_more(s, forward_size)) {}
636
3.43M
    return s->buf_end - s->buf_cur;
637
3.43M
}
638
639
// Like stream_read(), but do not advance the current position. This may resize
640
// the buffer to satisfy the read request.
641
int stream_read_peek(stream_t *s, void *buf, int buf_size)
642
3.43M
{
643
3.43M
    stream_peek(s, buf_size);
644
3.43M
    return ring_copy(s, buf, buf_size, s->buf_cur);
645
3.43M
}
646
647
int stream_write_buffer(stream_t *s, void *buf, int len)
648
0
{
649
0
    if (!s->write_buffer)
650
0
        return -1;
651
0
    int orig_len = len;
652
0
    while (len) {
653
0
        int w = s->write_buffer(s, buf, len);
654
0
        if (w <= 0)
655
0
            return -1;
656
0
        s->pos += w;
657
0
        buf = (char *)buf + w;
658
0
        len -= w;
659
0
    }
660
0
    return orig_len;
661
0
}
662
663
// Drop len bytes form input, possibly reading more until all is skipped. If
664
// EOF or an error was encountered before all could be skipped, return false,
665
// otherwise return true.
666
static bool stream_skip_read(struct stream *s, int64_t len)
667
13.8k
{
668
24.7k
    while (len > 0) {
669
24.7k
        unsigned int left = s->buf_end - s->buf_cur;
670
24.7k
        if (!left) {
671
13.9k
            if (!stream_read_more(s, 1))
672
13.8k
                return false;
673
42
            continue;
674
13.9k
        }
675
10.8k
        unsigned skip = MPMIN(len, left);
676
10.8k
        s->buf_cur += skip;
677
10.8k
        len -= skip;
678
10.8k
    }
679
29
    return true;
680
13.8k
}
681
682
// Drop the internal buffer. Note that this will advance the stream position
683
// (as seen by stream_tell()), because the real stream position is ahead of the
684
// logical stream position by the amount of buffered but not yet read data.
685
void stream_drop_buffers(stream_t *s)
686
48.7k
{
687
48.7k
    s->pos = stream_tell(s);
688
48.7k
    s->buf_start = s->buf_cur = s->buf_end = 0;
689
48.7k
    s->eof = 0;
690
48.7k
    stream_resize_buffer(s, 0, 0);
691
48.7k
}
692
693
// Seek function bypassing the local stream buffer.
694
static bool stream_seek_unbuffered(stream_t *s, int64_t newpos)
695
778k
{
696
778k
    if (newpos != s->pos) {
697
778k
        MP_VERBOSE(s, "stream level seek from %" PRId64 " to %" PRId64 "\n",
698
778k
                   s->pos, newpos);
699
700
778k
        s->total_stream_seeks++;
701
702
778k
        if (newpos > s->pos && !s->seekable) {
703
0
            MP_ERR(s, "Cannot seek forward in this stream\n");
704
0
            return false;
705
0
        }
706
778k
        if (newpos < s->pos && !s->seekable) {
707
0
            MP_ERR(s, "Cannot seek backward in linear streams!\n");
708
0
            return false;
709
0
        }
710
778k
        if (s->seek(s, newpos) <= 0) {
711
774k
            int level = mp_cancel_test(s->cancel) ? MSGL_V : MSGL_ERR;
712
774k
            MP_MSG(s, level, "Seek failed (to %lld, size %lld)\n",
713
774k
                   (long long)newpos, (long long)stream_get_size(s));
714
774k
            return false;
715
774k
        }
716
3.77k
        stream_drop_buffers(s);
717
3.77k
        s->pos = newpos;
718
3.77k
    }
719
3.77k
    return true;
720
778k
}
721
722
bool stream_seek(stream_t *s, int64_t pos)
723
4.58M
{
724
4.58M
    MP_TRACE(s, "seek request from %" PRId64 " to %" PRId64 "\n",
725
4.58M
             stream_tell(s), pos);
726
727
4.58M
    s->eof = 0; // eof should be set only on read; seeking always clears it
728
729
4.58M
    if (pos < 0) {
730
4
        MP_ERR(s, "Invalid seek to negative position %lld!\n", (long long)pos);
731
4
        pos = 0;
732
4
    }
733
734
4.58M
    if (pos <= s->pos) {
735
3.79M
        int64_t x = pos - (s->pos - (int)s->buf_end);
736
3.79M
        if (x >= (int)s->buf_start) {
737
3.79M
            s->buf_cur = x;
738
3.79M
            mp_assert(s->buf_cur >= s->buf_start);
739
3.79M
            mp_assert(s->buf_cur <= s->buf_end);
740
3.79M
            return true;
741
3.79M
        }
742
3.79M
    }
743
744
792k
    if (s->mode == STREAM_WRITE)
745
0
        return s->seekable && s->seek(s, pos);
746
747
    // Skip data instead of performing a seek in some cases.
748
792k
    if (pos >= s->pos &&
749
790k
        ((!s->seekable && s->fast_skip) ||
750
790k
         pos - s->pos <= s->requested_buffer_size))
751
13.8k
    {
752
13.8k
        return stream_skip_read(s, pos - stream_tell(s));
753
13.8k
    }
754
755
778k
    return stream_seek_unbuffered(s, pos);
756
792k
}
757
758
// Like stream_seek(), but strictly prefer skipping data instead of failing, if
759
// it's a forward-seek.
760
bool stream_seek_skip(stream_t *s, int64_t pos)
761
1.76M
{
762
1.76M
    uint64_t cur_pos = stream_tell(s);
763
764
1.76M
    if (cur_pos == pos)
765
283k
        return true;
766
767
1.47M
    return !s->seekable && pos > cur_pos
768
1.47M
        ? stream_skip_read(s, pos - cur_pos)
769
1.47M
        : stream_seek(s, pos);
770
1.76M
}
771
772
int stream_control(stream_t *s, int cmd, void *arg)
773
6.34M
{
774
6.34M
    return s->control ? s->control(s, cmd, arg) : STREAM_UNSUPPORTED;
775
6.34M
}
776
777
// Return the current size of the stream, or a negative value if unknown.
778
int64_t stream_get_size(stream_t *s)
779
1.10M
{
780
1.10M
    return s->get_size ? s->get_size(s) : -1;
781
1.10M
}
782
783
void free_stream(stream_t *s)
784
1.34M
{
785
1.34M
    if (!s)
786
1.02M
        return;
787
788
312k
    if (s->close)
789
67.3k
        s->close(s);
790
312k
    talloc_free(s);
791
312k
}
792
793
static const char *const bom[3] = {"\xEF\xBB\xBF", "\xFF\xFE", "\xFE\xFF"};
794
795
// Return utf16 argument for stream_read_line
796
int stream_skip_bom(struct stream *s)
797
174k
{
798
174k
    char buf[4];
799
174k
    int len = stream_read_peek(s, buf, sizeof(buf));
800
174k
    bstr data = {buf, len};
801
692k
    for (int n = 0; n < 3; n++) {
802
520k
        if (bstr_startswith0(data, bom[n])) {
803
2.63k
            stream_seek_skip(s, stream_tell(s) + strlen(bom[n]));
804
2.63k
            return n;
805
2.63k
        }
806
520k
    }
807
171k
    return -1; // default to 8 bit codepages
808
174k
}
809
810
// Read the rest of the stream into memory (current pos to EOF), and return it.
811
//  talloc_ctx: used as talloc parent for the returned allocation
812
//  max_size: must be set to >=0. If the file is larger than that, it is treated
813
//            as error. This is a minor robustness measure. If the stream is
814
//            created with STREAM_ALLOW_PARTIAL_READ flag, partial result up to
815
//            max_size is returned instead.
816
//  returns: stream contents, or .start/.len set to NULL on error
817
// If the file was empty, but no error happened, .start will be non-NULL and
818
// .len will be 0.
819
// For convenience, the returned buffer is padded with a 0 byte. The padding
820
// is not included in the returned length.
821
struct bstr stream_read_complete(struct stream *s, void *talloc_ctx,
822
                                 int max_size)
823
31.4k
{
824
31.4k
    if (max_size < 0 || max_size > STREAM_MAX_READ_SIZE)
825
0
        abort();
826
31.4k
    if (s->is_directory)
827
0
        return (struct bstr){NULL, 0};
828
829
31.4k
    int bufsize;
830
31.4k
    int total_read = 0;
831
31.4k
    int padding = 1;
832
31.4k
    char *buf = NULL;
833
31.4k
    int64_t size = stream_get_size(s) - stream_tell(s);
834
31.4k
    if (size > max_size && !s->allow_partial_read)
835
91
        return (struct bstr){NULL, 0};
836
31.3k
    if (size > 0)
837
25.7k
        bufsize = size + padding;
838
5.61k
    else
839
5.61k
        bufsize = 1000;
840
31.3k
    if (s->allow_partial_read)
841
0
        bufsize = MPMIN(bufsize, max_size + padding);
842
35.2k
    while (1) {
843
35.2k
        buf = talloc_realloc_size(talloc_ctx, buf, bufsize);
844
35.2k
        int readsize = stream_read(s, buf + total_read, bufsize - total_read);
845
35.2k
        total_read += readsize;
846
35.2k
        if (total_read >= max_size && s->allow_partial_read) {
847
0
            total_read = max_size;
848
0
            break;
849
0
        }
850
35.2k
        if (total_read < bufsize)
851
31.3k
            break;
852
3.89k
        if (bufsize > max_size) {
853
2
            talloc_free(buf);
854
2
            return (struct bstr){NULL, 0};
855
2
        }
856
3.89k
        bufsize = MPMIN(bufsize + (bufsize >> 1), max_size + padding);
857
3.89k
    }
858
31.3k
    buf = talloc_realloc_size(talloc_ctx, buf, total_read + padding);
859
31.3k
    memset(&buf[total_read], 0, padding);
860
31.3k
    return (struct bstr){buf, total_read};
861
31.3k
}
862
863
struct bstr stream_read_file(const char *filename, void *talloc_ctx,
864
                             struct mpv_global *global, int max_size)
865
0
{
866
0
    return stream_read_file2(filename, talloc_ctx, STREAM_READ_FILE_FLAGS_DEFAULT,
867
0
                             global, max_size);
868
0
}
869
870
struct bstr stream_read_file2(const char *filename, void *talloc_ctx,
871
                              int flags, struct mpv_global *global, int max_size)
872
20.7k
{
873
20.7k
    struct bstr res = {0};
874
20.7k
    stream_t *s = stream_create(filename, flags, NULL, global);
875
20.7k
    if (s) {
876
19.2k
        if (s->is_directory)
877
0
            mp_err(s->log, "Failed to open %s (not a file).\n", filename);
878
19.2k
        else
879
19.2k
            res = stream_read_complete(s, talloc_ctx, max_size);
880
19.2k
    }
881
20.7k
    free_stream(s);
882
20.7k
    return res;
883
20.7k
}
884
885
char **stream_get_proto_list(bool safe_only)
886
2.70k
{
887
2.70k
    char **list = NULL;
888
2.70k
    int num = 0;
889
37.9k
    for (int i = 0; i < MP_ARRAY_SIZE(stream_list); i++) {
890
35.2k
        const stream_info_t *stream_info = stream_list[i];
891
35.2k
        if (safe_only && (stream_info->stream_origin & STREAM_ORIGIN_UNSAFE))
892
0
            continue;
893
894
35.2k
        char **get_protocols = stream_info->get_protocols ? stream_info->get_protocols() : NULL;
895
35.2k
        char **protocols = get_protocols ? get_protocols : (char **)stream_info->protocols;
896
897
111k
        for (int j = 0; protocols && protocols[j]; j++) {
898
75.8k
            if (*protocols[j] == '\0')
899
2.70k
                continue;
900
901
73.1k
            MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(list, protocols[j]));
902
73.1k
        }
903
904
35.2k
        talloc_free(get_protocols);
905
35.2k
    }
906
2.70k
    MP_TARRAY_APPEND(NULL, list, num, NULL);
907
2.70k
    return list;
908
2.70k
}
909
910
void stream_print_proto_list(struct mp_log *log)
911
2.56k
{
912
2.56k
    int count = 0;
913
914
2.56k
    mp_info(log, "Protocols:\n\n");
915
2.56k
    char **list = stream_get_proto_list(false);
916
71.9k
    for (int i = 0; list[i]; i++) {
917
69.3k
        mp_info(log, " %s://\n", list[i]);
918
69.3k
        count++;
919
69.3k
    }
920
2.56k
    talloc_free(list);
921
2.56k
    mp_info(log, "\nTotal: %d protocols\n", count);
922
2.56k
}
923
924
bool stream_has_proto(const char *proto)
925
0
{
926
0
    for (int i = 0; i < MP_ARRAY_SIZE(stream_list); i++) {
927
0
        const stream_info_t *stream_info = stream_list[i];
928
929
0
        bool match = false;
930
0
        char **get_protocols = stream_info->get_protocols ? stream_info->get_protocols() : NULL;
931
0
        char **protocols = get_protocols ? get_protocols : (char **)stream_info->protocols;
932
933
0
        for (int j = 0; protocols && protocols[j]; j++) {
934
0
            if (strcmp(protocols[j], proto) == 0) {
935
0
                match = true;
936
0
                break;
937
0
            }
938
0
        }
939
940
0
        talloc_free(get_protocols);
941
0
        if (match)
942
0
            return match;
943
0
    }
944
945
0
    return false;
946
0
}