Libav 0.7.1
libavformat/gopher.c
Go to the documentation of this file.
00001 /*
00002  * Gopher protocol
00003  *
00004  * Copyright (c) 2009 Toshimitsu Kimura
00005  *
00006  * based on libavformat/http.c, Copyright (c) 2000, 2001 Fabrice Bellard
00007  *
00008  * This file is part of Libav.
00009  *
00010  * Libav is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * Libav is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with Libav; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00023  */
00024 
00025 #include "libavutil/avstring.h"
00026 #include "avformat.h"
00027 #include "internal.h"
00028 #include "network.h"
00029 #include "url.h"
00030 
00031 typedef struct {
00032     URLContext *hd;
00033 } GopherContext;
00034 
00035 static int gopher_write(URLContext *h, const uint8_t *buf, int size)
00036 {
00037     GopherContext *s = h->priv_data;
00038     return ffurl_write(s->hd, buf, size);
00039 }
00040 
00041 static int gopher_connect(URLContext *h, const char *path)
00042 {
00043     char buffer[1024];
00044 
00045     if (!*path) return AVERROR(EINVAL);
00046     switch (*++path) {
00047         case '5':
00048         case '9':
00049             path = strchr(path, '/');
00050             if (!path) return AVERROR(EINVAL);
00051             break;
00052         default:
00053             av_log(h, AV_LOG_WARNING,
00054                    "Gopher protocol type '%c' not supported yet!\n",
00055                    *path);
00056             return AVERROR(EINVAL);
00057     }
00058 
00059     /* send gopher sector */
00060     snprintf(buffer, sizeof(buffer), "%s\r\n", path);
00061 
00062     if (gopher_write(h, buffer, strlen(buffer)) < 0)
00063         return AVERROR(EIO);
00064 
00065     return 0;
00066 }
00067 
00068 static int gopher_close(URLContext *h)
00069 {
00070     GopherContext *s = h->priv_data;
00071     if (s->hd) {
00072         ffurl_close(s->hd);
00073         s->hd = NULL;
00074     }
00075     av_freep(&h->priv_data);
00076     return 0;
00077 }
00078 
00079 static int gopher_open(URLContext *h, const char *uri, int flags)
00080 {
00081     GopherContext *s;
00082     char hostname[1024], auth[1024], path[1024], buf[1024];
00083     int port, err;
00084 
00085     h->is_streamed = 1;
00086 
00087     s = av_malloc(sizeof(GopherContext));
00088     if (!s) {
00089         return AVERROR(ENOMEM);
00090     }
00091     h->priv_data = s;
00092 
00093     /* needed in any case to build the host string */
00094     av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
00095                  path, sizeof(path), uri);
00096 
00097     if (port < 0)
00098         port = 70;
00099 
00100     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
00101 
00102     s->hd = NULL;
00103     err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE);
00104     if (err < 0)
00105         goto fail;
00106 
00107     if ((err = gopher_connect(h, path)) < 0)
00108         goto fail;
00109     return 0;
00110  fail:
00111     gopher_close(h);
00112     return err;
00113 }
00114 
00115 static int gopher_read(URLContext *h, uint8_t *buf, int size)
00116 {
00117     GopherContext *s = h->priv_data;
00118     int len = ffurl_read(s->hd, buf, size);
00119     return len;
00120 }
00121 
00122 
00123 URLProtocol ff_gopher_protocol = {
00124     .name      = "gopher",
00125     .url_open  = gopher_open,
00126     .url_read  = gopher_read,
00127     .url_write = gopher_write,
00128     .url_close = gopher_close,
00129 };