00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 #include "libavutil/avstring.h"
00026 #include "avformat.h"
00027 #include "internal.h"
00028 #include "network.h"
00029 
00030 typedef struct {
00031     URLContext *hd;
00032 } GopherContext;
00033 
00034 static int gopher_write(URLContext *h, uint8_t *buf, int size)
00035 {
00036     GopherContext *s = h->priv_data;
00037     return url_write(s->hd, buf, size);
00038 }
00039 
00040 static int gopher_connect(URLContext *h, const char *path)
00041 {
00042     char buffer[1024];
00043 
00044     if (!*path) return AVERROR(EINVAL);
00045     switch (*++path) {
00046         case '5':
00047         case '9':
00048             path = strchr(path, '/');
00049             if (!path) return AVERROR(EINVAL);
00050             break;
00051         default:
00052             av_log(NULL, AV_LOG_WARNING,
00053                    "Gopher protocol type '%c' not supported yet!\n",
00054                    *path);
00055             return AVERROR(EINVAL);
00056     }
00057 
00058     
00059     snprintf(buffer, sizeof(buffer), "%s\r\n", path);
00060 
00061     if (gopher_write(h, buffer, strlen(buffer)) < 0)
00062         return AVERROR(EIO);
00063 
00064     return 0;
00065 }
00066 
00067 static int gopher_close(URLContext *h)
00068 {
00069     GopherContext *s = h->priv_data;
00070     if (s->hd) {
00071         url_close(s->hd);
00072         s->hd = NULL;
00073     }
00074     av_freep(&h->priv_data);
00075     return 0;
00076 }
00077 
00078 static int gopher_open(URLContext *h, const char *uri, int flags)
00079 {
00080     GopherContext *s;
00081     char hostname[1024], auth[1024], path[1024], buf[1024];
00082     int port, err;
00083 
00084     h->is_streamed = 1;
00085 
00086     s = av_malloc(sizeof(GopherContext));
00087     if (!s) {
00088         return AVERROR(ENOMEM);
00089     }
00090     h->priv_data = s;
00091 
00092     
00093     ff_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
00094                  path, sizeof(path), uri);
00095 
00096     if (port < 0)
00097         port = 70;
00098 
00099     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
00100 
00101     s->hd = NULL;
00102     err = url_open(&s->hd, buf, URL_RDWR);
00103     if (err < 0)
00104         goto fail;
00105 
00106     if ((err = gopher_connect(h, path)) < 0)
00107         goto fail;
00108     return 0;
00109  fail:
00110     gopher_close(h);
00111     return err;
00112 }
00113 
00114 static int gopher_read(URLContext *h, uint8_t *buf, int size)
00115 {
00116     GopherContext *s = h->priv_data;
00117     int len = url_read(s->hd, buf, size);
00118     return len;
00119 }
00120 
00121 
00122 URLProtocol gopher_protocol = {
00123     "gopher",
00124     gopher_open,
00125     gopher_read,
00126     gopher_write,
00127     NULL, 
00128     gopher_close,
00129 };