00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef HTTPCHANNEL_H
00020 #define HTTPCHANNEL_H
00021
00022 #include "pandabase.h"
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_SSL
00030
00031 #include "httpClient.h"
00032 #include "httpEnum.h"
00033 #include "urlSpec.h"
00034 #include "documentSpec.h"
00035 #include "virtualFile.h"
00036 #include "bioPtr.h"
00037 #include "bioStreamPtr.h"
00038 #include "pmap.h"
00039 #include "pointerTo.h"
00040 #include "config_downloader.h"
00041 #include "filename.h"
00042 #include <openssl/ssl.h>
00043
00044 class Ramfile;
00045 class HTTPClient;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 class EXPCL_PANDAEXPRESS HTTPChannel : public VirtualFile {
00063 private:
00064 HTTPChannel(HTTPClient *client);
00065
00066 public:
00067 virtual ~HTTPChannel();
00068
00069 virtual VirtualFileSystem *get_file_system() const;
00070 virtual Filename get_filename() const;
00071
00072 virtual bool is_regular_file() const;
00073 virtual istream *open_read_file() const;
00074
00075 bool will_close_connection() const;
00076
00077 PUBLISHED:
00078 INLINE bool is_valid() const;
00079 INLINE bool is_connection_ready() const;
00080 INLINE const URLSpec &get_url() const;
00081 INLINE const DocumentSpec &get_document_spec() const;
00082 INLINE HTTPEnum::HTTPVersion get_http_version() const;
00083 INLINE const string &get_http_version_string() const;
00084 INLINE int get_status_code() const;
00085 INLINE const string &get_status_string() const;
00086 INLINE const string &get_www_realm() const;
00087 INLINE const string &get_proxy_realm() const;
00088 INLINE const URLSpec &get_redirect() const;
00089 string get_header_value(const string &key) const;
00090
00091 INLINE void set_persistent_connection(bool persistent_connection);
00092 INLINE bool get_persistent_connection() const;
00093
00094 INLINE void set_connect_timeout(double timeout_seconds);
00095 INLINE double get_connect_timeout() const;
00096 INLINE void set_blocking_connect(bool blocking_connect);
00097 INLINE bool get_blocking_connect() const;
00098
00099 INLINE void set_http_timeout(double timeout_seconds);
00100 INLINE double get_http_timeout() const;
00101
00102 INLINE void set_download_throttle(bool download_throttle);
00103 INLINE bool get_download_throttle() const;
00104
00105 INLINE void set_max_bytes_per_second(double max_bytes_per_second);
00106 INLINE double get_max_bytes_per_second() const;
00107
00108 INLINE void set_max_updates_per_second(double max_updates_per_second);
00109 INLINE double get_max_updates_per_second() const;
00110
00111 INLINE size_t get_file_size() const;
00112
00113 void write_headers(ostream &out) const;
00114
00115 INLINE void reset();
00116
00117 INLINE void clear_extra_headers();
00118 INLINE void send_extra_header(const string &key, const string &value);
00119
00120 INLINE bool get_document(const DocumentSpec &url);
00121 INLINE bool get_subdocument(const DocumentSpec &url,
00122 size_t first_byte, size_t last_byte);
00123 INLINE bool get_header(const DocumentSpec &url);
00124 INLINE bool post_form(const DocumentSpec &url, const string &body);
00125 INLINE bool put_document(const DocumentSpec &url, const string &body);
00126 INLINE bool delete_document(const DocumentSpec &url);
00127 INLINE bool get_trace(const DocumentSpec &url);
00128 INLINE bool connect_to(const DocumentSpec &url);
00129 INLINE bool get_options(const DocumentSpec &url);
00130
00131 INLINE void begin_get_document(const DocumentSpec &url);
00132 INLINE void begin_get_subdocument(const DocumentSpec &url,
00133 size_t first_byte, size_t last_byte);
00134 INLINE void begin_get_header(const DocumentSpec &url);
00135 INLINE void begin_post_form(const DocumentSpec &url, const string &body);
00136 bool run();
00137 INLINE void begin_connect_to(const DocumentSpec &url);
00138
00139 ISocketStream *read_body();
00140 bool download_to_file(const Filename &filename, bool subdocument_resumes = true);
00141 bool download_to_ram(Ramfile *ramfile, bool subdocument_resumes = true);
00142 SocketStream *get_connection();
00143
00144 INLINE size_t get_bytes_downloaded() const;
00145 INLINE size_t get_bytes_requested() const;
00146 INLINE bool is_download_complete() const;
00147
00148 public:
00149 static string downcase(const string &s);
00150
00151 private:
00152 bool reached_done_state();
00153 bool run_connecting();
00154 bool run_connecting_wait();
00155 bool run_proxy_ready();
00156 bool run_proxy_request_sent();
00157 bool run_proxy_reading_header();
00158 bool run_setup_ssl();
00159 bool run_ssl_handshake();
00160 bool run_ready();
00161 bool run_request_sent();
00162 bool run_reading_header();
00163 bool run_read_header();
00164 bool run_begin_body();
00165 bool run_reading_body();
00166 bool run_read_body();
00167 bool run_read_trailer();
00168
00169 bool run_download_to_file();
00170 bool run_download_to_ram();
00171
00172 void begin_request(HTTPEnum::Method method, const DocumentSpec &url,
00173 const string &body, bool nonblocking,
00174 size_t first_byte, size_t last_byte);
00175 void reset_for_new_request();
00176
00177 void finished_body(bool has_trailer);
00178 bool reset_download_position();
00179
00180 bool http_getline(string &str);
00181 bool http_send(const string &str);
00182 bool parse_http_response(const string &line);
00183 bool parse_http_header();
00184 bool parse_content_range(const string &content_range);
00185
00186 void check_socket();
00187 bool verify_server(X509_NAME *subject) const;
00188
00189 static string get_x509_name_component(X509_NAME *name, int nid);
00190 static bool x509_name_subset(X509_NAME *name_a, X509_NAME *name_b);
00191
00192 void make_header();
00193 void make_proxy_request_text();
00194 void make_request_text();
00195
00196 void reset_url(const URLSpec &old_url, const URLSpec &new_url);
00197 void store_header_field(const string &field_name, const string &field_value);
00198
00199 #ifndef NDEBUG
00200 static void show_send(const string &message);
00201 #endif
00202
00203 void reset_download_to();
00204 void reset_to_new();
00205 void close_connection();
00206
00207 HTTPClient *_client;
00208 URLSpec _proxy;
00209 PT(BioPtr) _bio;
00210 PT(BioStreamPtr) _source;
00211 bool _persistent_connection;
00212 double _connect_timeout;
00213 double _http_timeout;
00214 bool _blocking_connect;
00215 bool _download_throttle;
00216 double _max_bytes_per_second;
00217 double _max_updates_per_second;
00218 double _seconds_per_update;
00219 int _bytes_per_update;
00220 bool _nonblocking;
00221 string _send_extra_headers;
00222
00223 DocumentSpec _document_spec;
00224 DocumentSpec _request;
00225 HTTPEnum::Method _method;
00226 string request_path;
00227 string _header;
00228 string _body;
00229 bool _want_ssl;
00230 bool _proxy_serves_document;
00231 bool _server_response_has_no_body;
00232 size_t _first_byte;
00233 size_t _last_byte;
00234 int _connect_count;
00235
00236 enum DownloadDest {
00237 DD_none,
00238 DD_file,
00239 DD_ram,
00240 };
00241 DownloadDest _download_dest;
00242 bool _subdocument_resumes;
00243 Filename _download_to_filename;
00244 ofstream _download_to_file;
00245 Ramfile *_download_to_ramfile;
00246
00247 int _read_index;
00248
00249 HTTPEnum::HTTPVersion _http_version;
00250 string _http_version_string;
00251 int _status_code;
00252 string _status_string;
00253 URLSpec _redirect;
00254
00255 string _proxy_realm;
00256 string _proxy_username;
00257 PT(HTTPAuthorization) _proxy_auth;
00258
00259 string _www_realm;
00260 string _www_username;
00261 PT(HTTPAuthorization) _www_auth;
00262
00263
00264 enum ResponseType {
00265 RT_none,
00266 RT_hangup,
00267 RT_non_http,
00268 RT_http_hangup,
00269 RT_http_complete
00270 };
00271 ResponseType _response_type;
00272
00273
00274 typedef pmap<string, string> Headers;
00275 Headers _headers;
00276
00277 size_t _file_size;
00278 size_t _bytes_downloaded;
00279 size_t _bytes_requested;
00280
00281
00282
00283
00284
00285
00286
00287 enum State {
00288 S_new,
00289 S_connecting,
00290 S_connecting_wait,
00291 S_proxy_ready,
00292 S_proxy_request_sent,
00293 S_proxy_reading_header,
00294 S_setup_ssl,
00295 S_ssl_handshake,
00296 S_ready,
00297 S_request_sent,
00298 S_reading_header,
00299 S_read_header,
00300 S_begin_body,
00301 S_reading_body,
00302 S_read_body,
00303 S_read_trailer,
00304 S_failure
00305 };
00306 State _state;
00307 State _done_state;
00308 double _started_connecting_time;
00309 double _sent_request_time;
00310 bool _started_download;
00311 string _proxy_header;
00312 string _proxy_request_text;
00313 bool _proxy_tunnel;
00314 string _request_text;
00315 string _working_getline;
00316 size_t _sent_so_far;
00317 string _current_field_name;
00318 string _current_field_value;
00319 ISocketStream *_body_stream;
00320 BIO *_sbio;
00321 pset<URLSpec> _redirect_trail;
00322 int _last_status_code;
00323 double _last_run_time;
00324
00325 public:
00326 virtual TypeHandle get_type() const {
00327 return get_class_type();
00328 }
00329 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00330 static TypeHandle get_class_type() {
00331 return _type_handle;
00332 }
00333 static void init_type() {
00334 VirtualFile::init_type();
00335 register_type(_type_handle, "HTTPChannel",
00336 VirtualFile::get_class_type());
00337 }
00338
00339 private:
00340 static TypeHandle _type_handle;
00341 friend class ChunkedStreamBuf;
00342 friend class IdentityStreamBuf;
00343 friend class HTTPClient;
00344 };
00345
00346 #include "httpChannel.I"
00347
00348 #endif // HAVE_SSL
00349
00350 #endif
00351
00352