yading@11: /* yading@11: * Gopher protocol yading@11: * yading@11: * Copyright (c) 2009 Toshimitsu Kimura yading@11: * yading@11: * based on libavformat/http.c, Copyright (c) 2000, 2001 Fabrice Bellard yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "libavutil/avstring.h" yading@11: #include "avformat.h" yading@11: #include "internal.h" yading@11: #include "network.h" yading@11: #include "url.h" yading@11: yading@11: typedef struct { yading@11: URLContext *hd; yading@11: } GopherContext; yading@11: yading@11: static int gopher_write(URLContext *h, const uint8_t *buf, int size) yading@11: { yading@11: GopherContext *s = h->priv_data; yading@11: return ffurl_write(s->hd, buf, size); yading@11: } yading@11: yading@11: static int gopher_connect(URLContext *h, const char *path) yading@11: { yading@11: char buffer[1024]; yading@11: yading@11: if (!*path) return AVERROR(EINVAL); yading@11: switch (*++path) { yading@11: case '5': yading@11: case '9': yading@11: path = strchr(path, '/'); yading@11: if (!path) return AVERROR(EINVAL); yading@11: break; yading@11: default: yading@11: av_log(h, AV_LOG_WARNING, yading@11: "Gopher protocol type '%c' not supported yet!\n", yading@11: *path); yading@11: return AVERROR(EINVAL); yading@11: } yading@11: yading@11: /* send gopher sector */ yading@11: snprintf(buffer, sizeof(buffer), "%s\r\n", path); yading@11: yading@11: if (gopher_write(h, buffer, strlen(buffer)) < 0) yading@11: return AVERROR(EIO); yading@11: yading@11: return 0; yading@11: } yading@11: yading@11: static int gopher_close(URLContext *h) yading@11: { yading@11: GopherContext *s = h->priv_data; yading@11: if (s->hd) { yading@11: ffurl_close(s->hd); yading@11: s->hd = NULL; yading@11: } yading@11: return 0; yading@11: } yading@11: yading@11: static int gopher_open(URLContext *h, const char *uri, int flags) yading@11: { yading@11: GopherContext *s = h->priv_data; yading@11: char hostname[1024], auth[1024], path[1024], buf[1024]; yading@11: int port, err; yading@11: yading@11: h->is_streamed = 1; yading@11: yading@11: /* needed in any case to build the host string */ yading@11: av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, yading@11: path, sizeof(path), uri); yading@11: yading@11: if (port < 0) yading@11: port = 70; yading@11: yading@11: ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); yading@11: yading@11: s->hd = NULL; yading@11: err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, yading@11: &h->interrupt_callback, NULL); yading@11: if (err < 0) yading@11: goto fail; yading@11: yading@11: if ((err = gopher_connect(h, path)) < 0) yading@11: goto fail; yading@11: return 0; yading@11: fail: yading@11: gopher_close(h); yading@11: return err; yading@11: } yading@11: yading@11: static int gopher_read(URLContext *h, uint8_t *buf, int size) yading@11: { yading@11: GopherContext *s = h->priv_data; yading@11: int len = ffurl_read(s->hd, buf, size); yading@11: return len; yading@11: } yading@11: yading@11: yading@11: URLProtocol ff_gopher_protocol = { yading@11: .name = "gopher", yading@11: .url_open = gopher_open, yading@11: .url_read = gopher_read, yading@11: .url_write = gopher_write, yading@11: .url_close = gopher_close, yading@11: .priv_data_size = sizeof(GopherContext), yading@11: .flags = URL_PROTOCOL_FLAG_NETWORK, yading@11: };