]> git.sesse.net Git - ffmpeg/blob - libavformat/avio.c
Merge commit '5eb562831b3a9bea8026c413ef1338e06450d005'
[ffmpeg] / libavformat / avio.c
1 /*
2  * unbuffered I/O
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/avstring.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/time.h"
26 #include "libavutil/avassert.h"
27 #include "os_support.h"
28 #include "avformat.h"
29 #if CONFIG_NETWORK
30 #include "network.h"
31 #endif
32 #include "url.h"
33
34 static URLProtocol *first_protocol = NULL;
35
36 URLProtocol *ffurl_protocol_next(const URLProtocol *prev)
37 {
38     return prev ? prev->next : first_protocol;
39 }
40
41 /** @name Logging context. */
42 /*@{*/
43 static const char *urlcontext_to_name(void *ptr)
44 {
45     URLContext *h = (URLContext *)ptr;
46     if (h->prot)
47         return h->prot->name;
48     else
49         return "NULL";
50 }
51
52 static void *urlcontext_child_next(void *obj, void *prev)
53 {
54     URLContext *h = obj;
55     if (!prev && h->priv_data && h->prot->priv_data_class)
56         return h->priv_data;
57     return NULL;
58 }
59
60 static const AVClass *urlcontext_child_class_next(const AVClass *prev)
61 {
62     URLProtocol *p = NULL;
63
64     /* find the protocol that corresponds to prev */
65     while (prev && (p = ffurl_protocol_next(p)))
66         if (p->priv_data_class == prev)
67             break;
68
69     /* find next protocol with priv options */
70     while (p = ffurl_protocol_next(p))
71         if (p->priv_data_class)
72             return p->priv_data_class;
73     return NULL;
74 }
75
76 #define OFFSET(x) offsetof(URLContext,x)
77 #define E AV_OPT_FLAG_ENCODING_PARAM
78 #define D AV_OPT_FLAG_DECODING_PARAM
79 static const AVOption options[] = {
80     {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
81     { NULL }
82 };
83 const AVClass ffurl_context_class = {
84     .class_name       = "URLContext",
85     .item_name        = urlcontext_to_name,
86     .option           = options,
87     .version          = LIBAVUTIL_VERSION_INT,
88     .child_next       = urlcontext_child_next,
89     .child_class_next = urlcontext_child_class_next,
90 };
91 /*@}*/
92
93 const char *avio_enum_protocols(void **opaque, int output)
94 {
95     URLProtocol *p;
96     *opaque = ffurl_protocol_next(*opaque);
97     if (!(p = *opaque))
98         return NULL;
99     if ((output && p->url_write) || (!output && p->url_read))
100         return p->name;
101     return avio_enum_protocols(opaque, output);
102 }
103
104 int ffurl_register_protocol(URLProtocol *protocol)
105 {
106     URLProtocol **p;
107     p = &first_protocol;
108     while (*p)
109         p = &(*p)->next;
110     *p             = protocol;
111     protocol->next = NULL;
112     return 0;
113 }
114
115 static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up,
116                                   const char *filename, int flags,
117                                   const AVIOInterruptCB *int_cb)
118 {
119     URLContext *uc;
120     int err;
121
122 #if CONFIG_NETWORK
123     if (up->flags & URL_PROTOCOL_FLAG_NETWORK && !ff_network_init())
124         return AVERROR(EIO);
125 #endif
126     if ((flags & AVIO_FLAG_READ) && !up->url_read) {
127         av_log(NULL, AV_LOG_ERROR,
128                "Impossible to open the '%s' protocol for reading\n", up->name);
129         return AVERROR(EIO);
130     }
131     if ((flags & AVIO_FLAG_WRITE) && !up->url_write) {
132         av_log(NULL, AV_LOG_ERROR,
133                "Impossible to open the '%s' protocol for writing\n", up->name);
134         return AVERROR(EIO);
135     }
136     uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
137     if (!uc) {
138         err = AVERROR(ENOMEM);
139         goto fail;
140     }
141     uc->av_class = &ffurl_context_class;
142     uc->filename = (char *)&uc[1];
143     strcpy(uc->filename, filename);
144     uc->prot            = up;
145     uc->flags           = flags;
146     uc->is_streamed     = 0; /* default = not streamed */
147     uc->max_packet_size = 0; /* default: stream file */
148     if (up->priv_data_size) {
149         uc->priv_data = av_mallocz(up->priv_data_size);
150         if (!uc->priv_data) {
151             err = AVERROR(ENOMEM);
152             goto fail;
153         }
154         if (up->priv_data_class) {
155             int proto_len= strlen(up->name);
156             char *start = strchr(uc->filename, ',');
157             *(const AVClass **)uc->priv_data = up->priv_data_class;
158             av_opt_set_defaults(uc->priv_data);
159             if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){
160                 int ret= 0;
161                 char *p= start;
162                 char sep= *++p;
163                 char *key, *val;
164                 p++;
165
166                 if (strcmp(up->name, "subfile"))
167                     ret = AVERROR(EINVAL);
168
169                 while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){
170                     *val= *key= 0;
171                     if (strcmp(p, "start") && strcmp(p, "end")) {
172                         ret = AVERROR_OPTION_NOT_FOUND;
173                     } else
174                         ret= av_opt_set(uc->priv_data, p, key+1, 0);
175                     if (ret == AVERROR_OPTION_NOT_FOUND)
176                         av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p);
177                     *val= *key= sep;
178                     p= val+1;
179                 }
180                 if(ret<0 || p!=key){
181                     av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start);
182                     av_freep(&uc->priv_data);
183                     av_freep(&uc);
184                     err = AVERROR(EINVAL);
185                     goto fail;
186                 }
187                 memmove(start, key+1, strlen(key));
188             }
189         }
190     }
191     if (int_cb)
192         uc->interrupt_callback = *int_cb;
193
194     *puc = uc;
195     return 0;
196 fail:
197     *puc = NULL;
198     if (uc)
199         av_freep(&uc->priv_data);
200     av_freep(&uc);
201 #if CONFIG_NETWORK
202     if (up->flags & URL_PROTOCOL_FLAG_NETWORK)
203         ff_network_close();
204 #endif
205     return err;
206 }
207
208 int ffurl_connect(URLContext *uc, AVDictionary **options)
209 {
210     int err;
211     AVDictionary *tmp_opts = NULL;
212     AVDictionaryEntry *e;
213
214     if (!options)
215         options = &tmp_opts;
216
217     // Check that URLContext was initialized correctly and lists are matching if set
218     av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
219                (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
220
221     if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
222         av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
223         return AVERROR(EINVAL);
224     }
225
226     if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
227         av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
228         uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
229         if (!uc->protocol_whitelist) {
230             return AVERROR(ENOMEM);
231         }
232     } else if (!uc->protocol_whitelist)
233         av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist
234
235     if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
236         return err;
237
238     err =
239         uc->prot->url_open2 ? uc->prot->url_open2(uc,
240                                                   uc->filename,
241                                                   uc->flags,
242                                                   options) :
243         uc->prot->url_open(uc, uc->filename, uc->flags);
244
245     av_dict_set(options, "protocol_whitelist", NULL, 0);
246
247     if (err)
248         return err;
249     uc->is_connected = 1;
250     /* We must be careful here as ffurl_seek() could be slow,
251      * for example for http */
252     if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
253         if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
254             uc->is_streamed = 1;
255     return 0;
256 }
257
258 int ffurl_accept(URLContext *s, URLContext **c)
259 {
260     av_assert0(!*c);
261     if (s->prot->url_accept)
262         return s->prot->url_accept(s, c);
263     return AVERROR(EBADF);
264 }
265
266 int ffurl_handshake(URLContext *c)
267 {
268     int ret;
269     if (c->prot->url_handshake) {
270         ret = c->prot->url_handshake(c);
271         if (ret)
272             return ret;
273     }
274     c->is_connected = 1;
275     return 0;
276 }
277
278 #define URL_SCHEME_CHARS                        \
279     "abcdefghijklmnopqrstuvwxyz"                \
280     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                \
281     "0123456789+-."
282
283 static struct URLProtocol *url_find_protocol(const char *filename)
284 {
285     URLProtocol *up = NULL;
286     char proto_str[128], proto_nested[128], *ptr;
287     size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
288
289     if (filename[proto_len] != ':' &&
290         (strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) ||
291         is_dos_path(filename))
292         strcpy(proto_str, "file");
293     else
294         av_strlcpy(proto_str, filename,
295                    FFMIN(proto_len + 1, sizeof(proto_str)));
296
297     if ((ptr = strchr(proto_str, ',')))
298         *ptr = '\0';
299     av_strlcpy(proto_nested, proto_str, sizeof(proto_nested));
300     if ((ptr = strchr(proto_nested, '+')))
301         *ptr = '\0';
302
303     while (up = ffurl_protocol_next(up)) {
304         if (!strcmp(proto_str, up->name))
305             break;
306         if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
307             !strcmp(proto_nested, up->name))
308             break;
309     }
310
311     return up;
312 }
313
314 int ffurl_alloc(URLContext **puc, const char *filename, int flags,
315                 const AVIOInterruptCB *int_cb)
316 {
317     URLProtocol *p = NULL;
318
319     if (!first_protocol) {
320         av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
321                                      "Missing call to av_register_all()?\n");
322     }
323
324     p = url_find_protocol(filename);
325     if (p)
326        return url_alloc_for_protocol(puc, p, filename, flags, int_cb);
327
328     *puc = NULL;
329     if (av_strstart(filename, "https:", NULL))
330         av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
331                                      "openssl, gnutls,\n"
332                                      "or securetransport enabled.\n");
333     return AVERROR_PROTOCOL_NOT_FOUND;
334 }
335
336 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
337                          const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
338 {
339     AVDictionary *tmp_opts = NULL;
340     AVDictionaryEntry *e;
341     int ret = ffurl_alloc(puc, filename, flags, int_cb);
342     if (ret < 0)
343         return ret;
344     if (options && (*puc)->prot->priv_data_class &&
345         (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
346         goto fail;
347
348     if (!options)
349         options = &tmp_opts;
350
351     av_assert0(!whitelist ||
352                !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
353                !strcmp(whitelist, e->value));
354
355     if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
356         goto fail;
357
358     if ((ret = av_opt_set_dict(*puc, options)) < 0)
359         goto fail;
360
361     ret = ffurl_connect(*puc, options);
362
363     if (!ret)
364         return 0;
365 fail:
366     ffurl_close(*puc);
367     *puc = NULL;
368     return ret;
369 }
370
371 int ffurl_open(URLContext **puc, const char *filename, int flags,
372                const AVIOInterruptCB *int_cb, AVDictionary **options)
373 {
374     return ffurl_open_whitelist(puc, filename, flags,
375                                 int_cb, options, NULL);
376 }
377
378 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
379                                          int size, int size_min,
380                                          int (*transfer_func)(URLContext *h,
381                                                               uint8_t *buf,
382                                                               int size))
383 {
384     int ret, len;
385     int fast_retries = 5;
386     int64_t wait_since = 0;
387
388     len = 0;
389     while (len < size_min) {
390         if (ff_check_interrupt(&h->interrupt_callback))
391             return AVERROR_EXIT;
392         ret = transfer_func(h, buf + len, size - len);
393         if (ret == AVERROR(EINTR))
394             continue;
395         if (h->flags & AVIO_FLAG_NONBLOCK)
396             return ret;
397         if (ret == AVERROR(EAGAIN)) {
398             ret = 0;
399             if (fast_retries) {
400                 fast_retries--;
401             } else {
402                 if (h->rw_timeout) {
403                     if (!wait_since)
404                         wait_since = av_gettime_relative();
405                     else if (av_gettime_relative() > wait_since + h->rw_timeout)
406                         return AVERROR(EIO);
407                 }
408                 av_usleep(1000);
409             }
410         } else if (ret < 1)
411             return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
412         if (ret)
413             fast_retries = FFMAX(fast_retries, 2);
414         len += ret;
415     }
416     return len;
417 }
418
419 int ffurl_read(URLContext *h, unsigned char *buf, int size)
420 {
421     if (!(h->flags & AVIO_FLAG_READ))
422         return AVERROR(EIO);
423     return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
424 }
425
426 int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
427 {
428     if (!(h->flags & AVIO_FLAG_READ))
429         return AVERROR(EIO);
430     return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read);
431 }
432
433 int ffurl_write(URLContext *h, const unsigned char *buf, int size)
434 {
435     if (!(h->flags & AVIO_FLAG_WRITE))
436         return AVERROR(EIO);
437     /* avoid sending too big packets */
438     if (h->max_packet_size && size > h->max_packet_size)
439         return AVERROR(EIO);
440
441     return retry_transfer_wrapper(h, (unsigned char *)buf, size, size,
442                                   (int (*)(struct URLContext *, uint8_t *, int))
443                                   h->prot->url_write);
444 }
445
446 int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
447 {
448     int64_t ret;
449
450     if (!h->prot->url_seek)
451         return AVERROR(ENOSYS);
452     ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE);
453     return ret;
454 }
455
456 int ffurl_closep(URLContext **hh)
457 {
458     URLContext *h= *hh;
459     int ret = 0;
460     if (!h)
461         return 0;     /* can happen when ffurl_open fails */
462
463     if (h->is_connected && h->prot->url_close)
464         ret = h->prot->url_close(h);
465 #if CONFIG_NETWORK
466     if (h->prot->flags & URL_PROTOCOL_FLAG_NETWORK)
467         ff_network_close();
468 #endif
469     if (h->prot->priv_data_size) {
470         if (h->prot->priv_data_class)
471             av_opt_free(h->priv_data);
472         av_freep(&h->priv_data);
473     }
474     av_opt_free(h);
475     av_freep(hh);
476     return ret;
477 }
478
479 int ffurl_close(URLContext *h)
480 {
481     return ffurl_closep(&h);
482 }
483
484
485 const char *avio_find_protocol_name(const char *url)
486 {
487     URLProtocol *p = url_find_protocol(url);
488
489     return p ? p->name : NULL;
490 }
491
492 int avio_check(const char *url, int flags)
493 {
494     URLContext *h;
495     int ret = ffurl_alloc(&h, url, flags, NULL);
496     if (ret < 0)
497         return ret;
498
499     if (h->prot->url_check) {
500         ret = h->prot->url_check(h, flags);
501     } else {
502         ret = ffurl_connect(h, NULL);
503         if (ret >= 0)
504             ret = flags;
505     }
506
507     ffurl_close(h);
508     return ret;
509 }
510
511 int avpriv_io_move(const char *url_src, const char *url_dst)
512 {
513     URLContext *h_src, *h_dst;
514     int ret = ffurl_alloc(&h_src, url_src, AVIO_FLAG_READ_WRITE, NULL);
515     if (ret < 0)
516         return ret;
517     ret = ffurl_alloc(&h_dst, url_dst, AVIO_FLAG_WRITE, NULL);
518     if (ret < 0) {
519         ffurl_close(h_src);
520         return ret;
521     }
522
523     if (h_src->prot == h_dst->prot && h_src->prot->url_move)
524         ret = h_src->prot->url_move(h_src, h_dst);
525     else
526         ret = AVERROR(ENOSYS);
527
528     ffurl_close(h_src);
529     ffurl_close(h_dst);
530     return ret;
531 }
532
533 int avpriv_io_delete(const char *url)
534 {
535     URLContext *h;
536     int ret = ffurl_alloc(&h, url, AVIO_FLAG_WRITE, NULL);
537     if (ret < 0)
538         return ret;
539
540     if (h->prot->url_delete)
541         ret = h->prot->url_delete(h);
542     else
543         ret = AVERROR(ENOSYS);
544
545     ffurl_close(h);
546     return ret;
547 }
548
549 int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options)
550 {
551     URLContext *h = NULL;
552     AVIODirContext *ctx = NULL;
553     int ret;
554     av_assert0(s);
555
556     ctx = av_mallocz(sizeof(*ctx));
557     if (!ctx) {
558         ret = AVERROR(ENOMEM);
559         goto fail;
560     }
561
562     if ((ret = ffurl_alloc(&h, url, AVIO_FLAG_READ, NULL)) < 0)
563         goto fail;
564
565     if (h->prot->url_open_dir && h->prot->url_read_dir && h->prot->url_close_dir) {
566         if (options && h->prot->priv_data_class &&
567             (ret = av_opt_set_dict(h->priv_data, options)) < 0)
568             goto fail;
569         ret = h->prot->url_open_dir(h);
570     } else
571         ret = AVERROR(ENOSYS);
572     if (ret < 0)
573         goto fail;
574
575     h->is_connected = 1;
576     ctx->url_context = h;
577     *s = ctx;
578     return 0;
579
580   fail:
581     av_free(ctx);
582     *s = NULL;
583     ffurl_close(h);
584     return ret;
585 }
586
587 int avio_read_dir(AVIODirContext *s, AVIODirEntry **next)
588 {
589     URLContext *h;
590     int ret;
591
592     if (!s || !s->url_context)
593         return AVERROR(EINVAL);
594     h = s->url_context;
595     if ((ret = h->prot->url_read_dir(h, next)) < 0)
596         avio_free_directory_entry(next);
597     return ret;
598 }
599
600 int avio_close_dir(AVIODirContext **s)
601 {
602     URLContext *h;
603
604     av_assert0(s);
605     if (!(*s) || !(*s)->url_context)
606         return AVERROR(EINVAL);
607     h = (*s)->url_context;
608     h->prot->url_close_dir(h);
609     ffurl_close(h);
610     av_freep(s);
611     *s = NULL;
612     return 0;
613 }
614
615 void avio_free_directory_entry(AVIODirEntry **entry)
616 {
617     if (!entry || !*entry)
618         return;
619     av_free((*entry)->name);
620     av_freep(entry);
621 }
622
623 int64_t ffurl_size(URLContext *h)
624 {
625     int64_t pos, size;
626
627     size = ffurl_seek(h, 0, AVSEEK_SIZE);
628     if (size < 0) {
629         pos = ffurl_seek(h, 0, SEEK_CUR);
630         if ((size = ffurl_seek(h, -1, SEEK_END)) < 0)
631             return size;
632         size++;
633         ffurl_seek(h, pos, SEEK_SET);
634     }
635     return size;
636 }
637
638 int ffurl_get_file_handle(URLContext *h)
639 {
640     if (!h->prot->url_get_file_handle)
641         return -1;
642     return h->prot->url_get_file_handle(h);
643 }
644
645 int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
646 {
647     if (!h->prot->url_get_multi_file_handle) {
648         if (!h->prot->url_get_file_handle)
649             return AVERROR(ENOSYS);
650         *handles = av_malloc(sizeof(**handles));
651         if (!*handles)
652             return AVERROR(ENOMEM);
653         *numhandles = 1;
654         *handles[0] = h->prot->url_get_file_handle(h);
655         return 0;
656     }
657     return h->prot->url_get_multi_file_handle(h, handles, numhandles);
658 }
659
660 int ffurl_shutdown(URLContext *h, int flags)
661 {
662     if (!h->prot->url_shutdown)
663         return AVERROR(EINVAL);
664     return h->prot->url_shutdown(h, flags);
665 }
666
667 int ff_check_interrupt(AVIOInterruptCB *cb)
668 {
669     int ret;
670     if (cb && cb->callback && (ret = cb->callback(cb->opaque)))
671         return ret;
672     return 0;
673 }