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