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 };