1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Gopher protocol 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2009 Toshimitsu Kimura 5cabdff1aSopenharmony_ci * Copyright (c) 2021 parazyd <parazyd@dyne.org> 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * based on libavformat/http.c, Copyright (c) 2000, 2001 Fabrice Bellard 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * This file is part of FFmpeg. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 12cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 13cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 14cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 17cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 18cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19cabdff1aSopenharmony_ci * Lesser General Public License for more details. 20cabdff1aSopenharmony_ci * 21cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 22cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 23cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "config.h" 27cabdff1aSopenharmony_ci#include "config_components.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 30cabdff1aSopenharmony_ci#include "avformat.h" 31cabdff1aSopenharmony_ci#include "internal.h" 32cabdff1aSopenharmony_ci#include "network.h" 33cabdff1aSopenharmony_ci#include "url.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_citypedef struct GopherContext { 36cabdff1aSopenharmony_ci URLContext *hd; 37cabdff1aSopenharmony_ci} GopherContext; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_cistatic int gopher_write(URLContext *h, const uint8_t *buf, int size) 40cabdff1aSopenharmony_ci{ 41cabdff1aSopenharmony_ci GopherContext *s = h->priv_data; 42cabdff1aSopenharmony_ci return ffurl_write(s->hd, buf, size); 43cabdff1aSopenharmony_ci} 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistatic int gopher_connect(URLContext *h, const char *path) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci char buffer[1024]; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci if (!*path) return AVERROR(EINVAL); 50cabdff1aSopenharmony_ci switch (*++path) { 51cabdff1aSopenharmony_ci case '5': 52cabdff1aSopenharmony_ci case '9': 53cabdff1aSopenharmony_ci path = strchr(path, '/'); 54cabdff1aSopenharmony_ci if (!path) return AVERROR(EINVAL); 55cabdff1aSopenharmony_ci break; 56cabdff1aSopenharmony_ci default: 57cabdff1aSopenharmony_ci av_log(h, AV_LOG_WARNING, 58cabdff1aSopenharmony_ci "Gopher protocol type '%c' not supported yet!\n", 59cabdff1aSopenharmony_ci *path); 60cabdff1aSopenharmony_ci return AVERROR(EINVAL); 61cabdff1aSopenharmony_ci } 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci /* send gopher sector */ 64cabdff1aSopenharmony_ci snprintf(buffer, sizeof(buffer), "%s\r\n", path); 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci if (gopher_write(h, buffer, strlen(buffer)) < 0) 67cabdff1aSopenharmony_ci return AVERROR(EIO); 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci return 0; 70cabdff1aSopenharmony_ci} 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_cistatic int gopher_close(URLContext *h) 73cabdff1aSopenharmony_ci{ 74cabdff1aSopenharmony_ci GopherContext *s = h->priv_data; 75cabdff1aSopenharmony_ci ffurl_closep(&s->hd); 76cabdff1aSopenharmony_ci return 0; 77cabdff1aSopenharmony_ci} 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_cistatic int gopher_open(URLContext *h, const char *uri, int flags) 80cabdff1aSopenharmony_ci{ 81cabdff1aSopenharmony_ci GopherContext *s = h->priv_data; 82cabdff1aSopenharmony_ci char proto[10], hostname[1024], auth[1024], path[1024], buf[1024]; 83cabdff1aSopenharmony_ci int port, err; 84cabdff1aSopenharmony_ci const char *lower_proto = "tcp"; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci h->is_streamed = 1; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci /* needed in any case to build the host string */ 89cabdff1aSopenharmony_ci av_url_split(proto, sizeof(proto), auth, sizeof(auth), 90cabdff1aSopenharmony_ci hostname, sizeof(hostname), &port, path, sizeof(path), uri); 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci if (port < 0) 93cabdff1aSopenharmony_ci port = 70; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci if (!strcmp(proto, "gophers")) 96cabdff1aSopenharmony_ci lower_proto = "tls"; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci s->hd = NULL; 101cabdff1aSopenharmony_ci err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE, 102cabdff1aSopenharmony_ci &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h); 103cabdff1aSopenharmony_ci if (err < 0) 104cabdff1aSopenharmony_ci goto fail; 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci if ((err = gopher_connect(h, path)) < 0) 107cabdff1aSopenharmony_ci goto fail; 108cabdff1aSopenharmony_ci return 0; 109cabdff1aSopenharmony_ci fail: 110cabdff1aSopenharmony_ci gopher_close(h); 111cabdff1aSopenharmony_ci return err; 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_cistatic int gopher_read(URLContext *h, uint8_t *buf, int size) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci GopherContext *s = h->priv_data; 117cabdff1aSopenharmony_ci int len = ffurl_read(s->hd, buf, size); 118cabdff1aSopenharmony_ci return len; 119cabdff1aSopenharmony_ci} 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci#if CONFIG_GOPHER_PROTOCOL 122cabdff1aSopenharmony_ciconst URLProtocol ff_gopher_protocol = { 123cabdff1aSopenharmony_ci .name = "gopher", 124cabdff1aSopenharmony_ci .url_open = gopher_open, 125cabdff1aSopenharmony_ci .url_read = gopher_read, 126cabdff1aSopenharmony_ci .url_write = gopher_write, 127cabdff1aSopenharmony_ci .url_close = gopher_close, 128cabdff1aSopenharmony_ci .priv_data_size = sizeof(GopherContext), 129cabdff1aSopenharmony_ci .flags = URL_PROTOCOL_FLAG_NETWORK, 130cabdff1aSopenharmony_ci .default_whitelist = "gopher,tcp" 131cabdff1aSopenharmony_ci}; 132cabdff1aSopenharmony_ci#endif /* CONFIG_GOPHER_PROTOCOL */ 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci#if CONFIG_GOPHERS_PROTOCOL 135cabdff1aSopenharmony_ciconst URLProtocol ff_gophers_protocol = { 136cabdff1aSopenharmony_ci .name = "gophers", 137cabdff1aSopenharmony_ci .url_open = gopher_open, 138cabdff1aSopenharmony_ci .url_read = gopher_read, 139cabdff1aSopenharmony_ci .url_write = gopher_write, 140cabdff1aSopenharmony_ci .url_close = gopher_close, 141cabdff1aSopenharmony_ci .priv_data_size = sizeof(GopherContext), 142cabdff1aSopenharmony_ci .flags = URL_PROTOCOL_FLAG_NETWORK, 143cabdff1aSopenharmony_ci .default_whitelist = "gopher,gophers,tcp,tls" 144cabdff1aSopenharmony_ci}; 145cabdff1aSopenharmony_ci#endif /* CONFIG_GOPHERS_PROTOCOL */ 146