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