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