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
);
56 path
= strchr(path
, '/');
57 if (!path
) return AVERROR(EINVAL
);
60 av_log(h
, AV_LOG_WARNING
,
61 "Gopher protocol type '%c' not supported yet!\n",
63 return AVERROR(EINVAL
);
66 /* send gopher sector */
67 snprintf(buffer
, sizeof(buffer
), "%s\r\n", path
);
69 if (gopher_write(h
, buffer
, strlen(buffer
)) < 0)
75 static int gopher_close(URLContext
*h
)
77 GopherContext
*s
= h
->priv_data
;
82 static int gopher_open(URLContext
*h
, const char *uri
, int flags
)
84 GopherContext
*s
= h
->priv_data
;
85 char proto
[10], hostname
[1024], auth
[1024], path
[1024], buf
[1024];
87 const char *lower_proto
= "tcp";
91 /* needed in any case to build the host string */
92 av_url_split(proto
, sizeof(proto
), auth
, sizeof(auth
),
93 hostname
, sizeof(hostname
), &port
, path
, sizeof(path
), uri
);
98 if (!strcmp(proto
, "gophers"))
101 ff_url_join(buf
, sizeof(buf
), lower_proto
, NULL
, hostname
, port
, NULL
);
104 err
= ffurl_open_whitelist(&s
->hd
, buf
, AVIO_FLAG_READ_WRITE
,
105 &h
->interrupt_callback
, NULL
, h
->protocol_whitelist
, h
->protocol_blacklist
, h
);
109 if ((err
= gopher_connect(h
, path
)) < 0)
117 static int gopher_read(URLContext
*h
, uint8_t *buf
, int size
)
119 GopherContext
*s
= h
->priv_data
;
120 int len
= ffurl_read(s
->hd
, buf
, size
);
124 #if CONFIG_GOPHER_PROTOCOL
125 const URLProtocol ff_gopher_protocol
= {
127 .url_open
= gopher_open
,
128 .url_read
= gopher_read
,
129 .url_write
= gopher_write
,
130 .url_close
= gopher_close
,
131 .priv_data_size
= sizeof(GopherContext
),
132 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
133 .default_whitelist
= "gopher,tcp"
135 #endif /* CONFIG_GOPHER_PROTOCOL */
137 #if CONFIG_GOPHERS_PROTOCOL
138 const URLProtocol ff_gophers_protocol
= {
140 .url_open
= gopher_open
,
141 .url_read
= gopher_read
,
142 .url_write
= gopher_write
,
143 .url_close
= gopher_close
,
144 .priv_data_size
= sizeof(GopherContext
),
145 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
146 .default_whitelist
= "gopher,gophers,tcp,tls"
148 #endif /* CONFIG_GOPHERS_PROTOCOL */