00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __WVHTTPPOOL_H
00011 #define __WVHTTPPOOL_H
00012
00013 #include "ftpparse.h"
00014 #include "wvurl.h"
00015 #include "wvstreamlist.h"
00016 #include "wvstreamclone.h"
00017 #include "wvlog.h"
00018 #include "wvhashtable.h"
00019 #include "wvhttp.h"
00020 #include "wvbufstream.h"
00021 #include "wvbuf.h"
00022
00023 class WvBufUrlStream;
00024 class WvUrlStream;
00025 class WvHttpStream;
00026
00027 static const WvString DEFAULT_ANON_PW("weasels@");
00028
00029 class WvUrlRequest
00030 {
00031 public:
00032 WvUrl url;
00033 WvString headers;
00034 WvUrlStream *instream;
00035 WvBufUrlStream *outstream;
00036 WvStream *putstream;
00037
00038 bool pipeline_test;
00039 bool inuse;
00040 bool is_dir;
00041 bool create_dirs;
00042 WvString method;
00043
00044 WvUrlRequest(WvStringParm _url, WvStringParm _method, WvStringParm _headers,
00045 WvStream *content_source, bool _create_dirs, bool _pipeline_test);
00046 ~WvUrlRequest();
00047
00048 void done();
00049 };
00050
00051 DeclareWvList(WvUrlRequest);
00052
00053
00054 struct WvUrlLink
00055 {
00056 WvString linkname;
00057 WvUrl url;
00058
00059 WvUrlLink::WvUrlLink(WvStringParm _linkname, WvStringParm _url)
00060 : linkname(_linkname), url(_url)
00061 {}
00062 };
00063 DeclareWvList(WvUrlLink);
00064
00065
00066 class WvBufUrlStream : public WvBufStream
00067 {
00068 public:
00069 WvString url;
00070 WvString proto;
00071 WvUrlLinkList links;
00072
00073
00074 WvString version;
00075 int status;
00076 WvHTTPHeaderDict headers;
00077
00078 WvBufUrlStream() : status(0), headers(10)
00079 {}
00080 virtual ~WvBufUrlStream()
00081 {}
00082 };
00083
00084 DeclareWvTable(WvIPPortAddr);
00085
00086
00087 class WvUrlStream : public WvStreamClone
00088 {
00089 public:
00090 class Target
00091 {
00092 public:
00093 WvIPPortAddr remaddr;
00094 WvString username;
00095
00096 Target(const WvIPPortAddr &_remaddr, WvStringParm _username)
00097 : remaddr(_remaddr), username(_username) {}
00098
00099 ~Target() {}
00100
00101 bool operator== (const Target &n2) const
00102 { return (username == n2.username && remaddr == n2.remaddr); }
00103 };
00104 Target target;
00105 static int max_requests;
00106
00107 protected:
00108 WvLog log;
00109 WvUrlRequestList urls, waiting_urls;
00110 int request_count;
00111 WvUrlRequest *curl;
00112 virtual void doneurl() = 0;
00113 virtual void request_next() = 0;
00114
00115 public:
00116 WvUrlStream(const WvIPPortAddr &_remaddr, WvStringParm _username,
00117 WvStringParm logname)
00118 : WvStreamClone(new WvTCPConn(_remaddr)), target(_remaddr, _username),
00119 log(logname, WvLog::Debug)
00120 {
00121 request_count = 0;
00122 curl = NULL;
00123 }
00124
00125 virtual ~WvUrlStream() {};
00126
00127 virtual void close() = 0;
00128 void addurl(WvUrlRequest *url);
00129 void delurl(WvUrlRequest *url);
00130
00131 virtual size_t remaining()
00132 { return 0; }
00133
00134 virtual void execute() = 0;
00135 };
00136
00137 unsigned WvHash(const WvUrlStream::Target &n);
00138
00139 DeclareWvDict(WvUrlStream, WvUrlStream::Target, target);
00140
00141
00142 class WvHttpStream : public WvUrlStream
00143 {
00144 public:
00145 static bool global_enable_pipelining;
00146 bool enable_pipelining;
00147
00148 private:
00149 int pipeline_test_count;
00150 bool ssl;
00151 bool sent_url_request;
00152 WvIPPortAddrTable &pipeline_incompatible;
00153 WvString http_response, pipeline_test_response;
00154 WvDynBuf putstream_data;
00155
00156 enum { Unknown, Chunked, ContentLength, Infinity } encoding;
00157 size_t bytes_remaining;
00158 bool in_chunk_trailer, last_was_pipeline_test;
00159
00160 virtual void doneurl();
00161 virtual void request_next();
00162 void start_pipeline_test(WvUrl *url);
00163 WvString request_str(WvUrlRequest *url, bool keep_alive);
00164 void send_request(WvUrlRequest *url);
00165 void pipelining_is_broken(int why);
00166
00167 public:
00168 WvHttpStream(const WvIPPortAddr &_remaddr, WvStringParm _username,
00169 bool ssl, WvIPPortAddrTable &_pipeline_incompatible);
00170 virtual ~WvHttpStream();
00171
00172 virtual void close();
00173 virtual bool pre_select(SelectInfo &si);
00174 virtual bool post_select(SelectInfo &si);
00175 virtual void execute();
00176 virtual size_t remaining()
00177 { return bytes_remaining; }
00178 };
00179
00180
00181 class WvFtpStream : public WvUrlStream
00182 {
00183 bool logged_in, pasv_acked;
00184 WvString password;
00185 WvTCPConn *data;
00186 time_t last_request_time;
00187
00188 virtual void doneurl();
00189 virtual void request_next();
00190
00191
00192
00193 char *get_important_line(int timeout);
00194
00195
00196
00197
00198 WvIPPortAddr *parse_pasv_response(char *line);
00199
00200 WvString parse_for_links(char *line);
00201
00202 public:
00203 WvFtpStream(const WvIPPortAddr &_remaddr, WvStringParm _username,
00204 WvStringParm _password);
00205 virtual ~WvFtpStream();
00206
00207 virtual bool pre_select(SelectInfo &si);
00208 virtual bool post_select(SelectInfo &si);
00209 virtual void close();
00210 virtual void execute();
00211 };
00212
00213
00214
00215 class WvHttpPool : public WvStreamList
00216 {
00217 WvLog log;
00218 WvResolver dns;
00219 WvUrlStreamDict conns;
00220 WvUrlRequestList urls;
00221 int num_streams_created;
00222
00223 WvIPPortAddrTable pipeline_incompatible;
00224
00225 public:
00226 WvHttpPool();
00227 virtual ~WvHttpPool();
00228
00229 virtual bool pre_select(SelectInfo &si);
00230 virtual void execute();
00231
00232 WvBufUrlStream *addurl(WvStringParm _url, WvStringParm _method = "GET",
00233 WvStringParm _headers = "",
00234 WvStream *content_source = NULL,
00235 bool create_dirs = false);
00236
00237
00238
00239
00240
00241 private:
00242 void unconnect(WvUrlStream *s);
00243
00244 public:
00245 bool idle() const
00246 { return !urls.count(); }
00247 };
00248
00249
00250 #endif // __WVHTTPPOOL_H