4 * Copyright (c) 2009 Toshimitsu Kimura
5 * Copyright (c) 2021 parazyd <parazyd@dyne.org>
7 * based on libavformat/http.c, Copyright (c) 2000, 2001 Fabrice Bellard
9 * This file is part of FFmpeg.
11 * FFmpeg is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * FFmpeg is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with FFmpeg; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "config_components.h"
29 #include "libavutil/avstring.h"
35 typedef struct GopherContext
{
39 static int gopher_write(URLContext
*h
, const uint8_t *buf
, int size
)
41 GopherContext
*s
= h
->priv_data
;
42 return ffurl_write(s
->hd
, buf
, size
);
45 static int gopher_connect(URLContext
*h
, const char *path
)
49 if (!*path
) return AVERROR(EINVAL
);
53 path
= strchr(path
, '/');
54 if (!path
) return AVERROR(EINVAL
);
57 av_log(h
, AV_LOG_WARNING
,
58 "Gopher protocol type '%c' not supported yet!\n",
60 return AVERROR(EINVAL
);
63 /* send gopher sector */
64 snprintf(buffer
, sizeof(buffer
), "%s\r\n", path
);
66 if (gopher_write(h
, buffer
, strlen(buffer
)) < 0)
72 static int gopher_close(URLContext
*h
)
74 GopherContext
*s
= h
->priv_data
;
79 static int gopher_open(URLContext
*h
, const char *uri
, int flags
)
81 GopherContext
*s
= h
->priv_data
;
82 char proto
[10], hostname
[1024], auth
[1024], path
[1024], buf
[1024];
84 const char *lower_proto
= "tcp";
88 /* needed in any case to build the host string */
89 av_url_split(proto
, sizeof(proto
), auth
, sizeof(auth
),
90 hostname
, sizeof(hostname
), &port
, path
, sizeof(path
), uri
);
95 if (!strcmp(proto
, "gophers"))
98 ff_url_join(buf
, sizeof(buf
), lower_proto
, NULL
, hostname
, port
, NULL
);
101 err
= ffurl_open_whitelist(&s
->hd
, buf
, AVIO_FLAG_READ_WRITE
,
102 &h
->interrupt_callback
, NULL
, h
->protocol_whitelist
, h
->protocol_blacklist
, h
);
106 if ((err
= gopher_connect(h
, path
)) < 0)
114 static int gopher_read(URLContext
*h
, uint8_t *buf
, int size
)
116 GopherContext
*s
= h
->priv_data
;
117 int len
= ffurl_read(s
->hd
, buf
, size
);
121 #if CONFIG_GOPHER_PROTOCOL
122 const URLProtocol ff_gopher_protocol
= {
124 .url_open
= gopher_open
,
125 .url_read
= gopher_read
,
126 .url_write
= gopher_write
,
127 .url_close
= gopher_close
,
128 .priv_data_size
= sizeof(GopherContext
),
129 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
130 .default_whitelist
= "gopher,tcp"
132 #endif /* CONFIG_GOPHER_PROTOCOL */
134 #if CONFIG_GOPHERS_PROTOCOL
135 const URLProtocol ff_gophers_protocol
= {
137 .url_open
= gopher_open
,
138 .url_read
= gopher_read
,
139 .url_write
= gopher_write
,
140 .url_close
= gopher_close
,
141 .priv_data_size
= sizeof(GopherContext
),
142 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
143 .default_whitelist
= "gopher,gophers,tcp,tls"
145 #endif /* CONFIG_GOPHERS_PROTOCOL */