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
28 #include "libavutil/avstring.h"
34 typedef struct GopherContext
{
38 static int gopher_write(URLContext
*h
, const uint8_t *buf
, int size
)
40 GopherContext
*s
= h
->priv_data
;
41 return ffurl_write(s
->hd
, buf
, size
);
44 static int gopher_connect(URLContext
*h
, const char *path
)
48 if (!*path
) return AVERROR(EINVAL
);
52 path
= strchr(path
, '/');
53 if (!path
) return AVERROR(EINVAL
);
56 av_log(h
, AV_LOG_WARNING
,
57 "Gopher protocol type '%c' not supported yet!\n",
59 return AVERROR(EINVAL
);
62 /* send gopher sector */
63 snprintf(buffer
, sizeof(buffer
), "%s\r\n", path
);
65 if (gopher_write(h
, buffer
, strlen(buffer
)) < 0)
71 static int gopher_close(URLContext
*h
)
73 GopherContext
*s
= h
->priv_data
;
78 static int gopher_open(URLContext
*h
, const char *uri
, int flags
)
80 GopherContext
*s
= h
->priv_data
;
81 char proto
[10], hostname
[1024], auth
[1024], path
[1024], buf
[1024];
83 const char *lower_proto
= "tcp";
87 /* needed in any case to build the host string */
88 av_url_split(proto
, sizeof(proto
), auth
, sizeof(auth
),
89 hostname
, sizeof(hostname
), &port
, path
, sizeof(path
), uri
);
94 if (!strcmp(proto
, "gophers"))
97 ff_url_join(buf
, sizeof(buf
), lower_proto
, NULL
, hostname
, port
, NULL
);
100 err
= ffurl_open_whitelist(&s
->hd
, buf
, AVIO_FLAG_READ_WRITE
,
101 &h
->interrupt_callback
, NULL
, h
->protocol_whitelist
, h
->protocol_blacklist
, h
);
105 if ((err
= gopher_connect(h
, path
)) < 0)
113 static int gopher_read(URLContext
*h
, uint8_t *buf
, int size
)
115 GopherContext
*s
= h
->priv_data
;
116 int len
= ffurl_read(s
->hd
, buf
, size
);
120 #if CONFIG_GOPHER_PROTOCOL
121 const URLProtocol ff_gopher_protocol
= {
123 .url_open
= gopher_open
,
124 .url_read
= gopher_read
,
125 .url_write
= gopher_write
,
126 .url_close
= gopher_close
,
127 .priv_data_size
= sizeof(GopherContext
),
128 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
129 .default_whitelist
= "gopher,tcp"
131 #endif /* CONFIG_GOPHER_PROTOCOL */
133 #if CONFIG_GOPHERS_PROTOCOL
134 const URLProtocol ff_gophers_protocol
= {
136 .url_open
= gopher_open
,
137 .url_read
= gopher_read
,
138 .url_write
= gopher_write
,
139 .url_close
= gopher_close
,
140 .priv_data_size
= sizeof(GopherContext
),
141 .flags
= URL_PROTOCOL_FLAG_NETWORK
,
142 .default_whitelist
= "gopher,gophers,tcp,tls"
144 #endif /* CONFIG_GOPHERS_PROTOCOL */