00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef HTTPCHANNEL_H
00016 #define HTTPCHANNEL_H
00017
00018 #include "pandabase.h"
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_OPENSSL
00026 #define OPENSSL_NO_KRB5
00027
00028 #include "httpClient.h"
00029 #include "httpEnum.h"
00030 #include "urlSpec.h"
00031 #include "documentSpec.h"
00032 #include "bioPtr.h"
00033 #include "bioStreamPtr.h"
00034 #include "pmap.h"
00035 #include "pvector.h"
00036 #include "pointerTo.h"
00037 #include "config_downloader.h"
00038 #include "filename.h"
00039 #include "openSSLWrapper.h"
00040 #include "openssl/ssl.h"
00041 #include "typedReferenceCount.h"
00042
00043 class Ramfile;
00044 class HTTPClient;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 class EXPCL_PANDAEXPRESS HTTPChannel : public TypedReferenceCount {
00062 private:
00063 HTTPChannel(HTTPClient *client);
00064
00065 public:
00066 virtual ~HTTPChannel();
00067
00068 PUBLISHED:
00069
00070
00071
00072 enum StatusCode {
00073 SC_incomplete = 0,
00074 SC_internal_error,
00075 SC_no_connection,
00076 SC_timeout,
00077 SC_lost_connection,
00078 SC_non_http_response,
00079 SC_invalid_http,
00080 SC_socks_invalid_version,
00081 SC_socks_no_acceptable_login_method,
00082 SC_socks_refused,
00083 SC_socks_no_connection,
00084 SC_ssl_internal_failure,
00085 SC_ssl_no_handshake,
00086
00087
00088
00089 SC_http_error_watermark,
00090
00091 SC_ssl_invalid_server_certificate,
00092 SC_ssl_self_signed_server_certificate,
00093 SC_ssl_unexpected_server,
00094
00095
00096
00097 SC_download_open_error,
00098 SC_download_write_error,
00099 SC_download_invalid_range,
00100 };
00101
00102 INLINE HTTPClient *get_client() const;
00103
00104 INLINE bool is_valid() const;
00105 INLINE bool is_connection_ready() const;
00106
00107 INLINE const URLSpec &get_url() const;
00108 INLINE const DocumentSpec &get_document_spec() const;
00109 INLINE HTTPEnum::HTTPVersion get_http_version() const;
00110 INLINE const string &get_http_version_string() const;
00111 INLINE int get_status_code() const;
00112 string get_status_string() const;
00113 INLINE const string &get_www_realm() const;
00114 INLINE const string &get_proxy_realm() const;
00115 INLINE const URLSpec &get_redirect() const;
00116 string get_header_value(const string &key) const;
00117
00118 INLINE int get_num_redirect_steps() const;
00119 INLINE const URLSpec &get_redirect_step(int n) const;
00120 MAKE_SEQ(get_redirect_steps, get_num_redirect_steps, get_redirect_step);
00121
00122 INLINE void set_persistent_connection(bool persistent_connection);
00123 INLINE bool get_persistent_connection() const;
00124 bool will_close_connection() const;
00125
00126 INLINE void set_allow_proxy(bool allow_proxy);
00127 INLINE bool get_allow_proxy() const;
00128 INLINE void set_proxy_tunnel(bool proxy_tunnel);
00129 INLINE bool get_proxy_tunnel() const;
00130
00131 INLINE void set_connect_timeout(double timeout_seconds);
00132 INLINE double get_connect_timeout() const;
00133 INLINE void set_blocking_connect(bool blocking_connect);
00134 INLINE bool get_blocking_connect() const;
00135
00136 INLINE void set_http_timeout(double timeout_seconds);
00137 INLINE double get_http_timeout() const;
00138
00139 INLINE void set_skip_body_size(size_t skip_body_size);
00140 INLINE size_t get_skip_body_size() const;
00141 INLINE void set_idle_timeout(double idle_timeout);
00142 INLINE double get_idle_timeout() const;
00143
00144 INLINE void set_download_throttle(bool download_throttle);
00145 INLINE bool get_download_throttle() const;
00146
00147 INLINE void set_max_bytes_per_second(double max_bytes_per_second);
00148 INLINE double get_max_bytes_per_second() const;
00149
00150 INLINE void set_max_updates_per_second(double max_updates_per_second);
00151 INLINE double get_max_updates_per_second() const;
00152
00153 INLINE void set_expected_file_size(size_t file_size);
00154 off_t get_file_size() const;
00155 INLINE bool is_file_size_known() const;
00156
00157 INLINE size_t get_first_byte_requested() const;
00158 INLINE size_t get_last_byte_requested() const;
00159 INLINE size_t get_first_byte_delivered() const;
00160 INLINE size_t get_last_byte_delivered() const;
00161
00162 void write_headers(ostream &out) const;
00163
00164 INLINE void reset();
00165 INLINE void preserve_status();
00166
00167 INLINE void clear_extra_headers();
00168 INLINE void send_extra_header(const string &key, const string &value);
00169
00170 BLOCKING INLINE bool get_document(const DocumentSpec &url);
00171 BLOCKING INLINE bool get_subdocument(const DocumentSpec &url,
00172 size_t first_byte, size_t last_byte);
00173 BLOCKING INLINE bool get_header(const DocumentSpec &url);
00174 BLOCKING INLINE bool post_form(const DocumentSpec &url, const string &body);
00175 BLOCKING INLINE bool put_document(const DocumentSpec &url, const string &body);
00176 BLOCKING INLINE bool delete_document(const DocumentSpec &url);
00177 BLOCKING INLINE bool get_trace(const DocumentSpec &url);
00178 BLOCKING INLINE bool connect_to(const DocumentSpec &url);
00179 BLOCKING INLINE bool get_options(const DocumentSpec &url);
00180
00181 INLINE void begin_get_document(const DocumentSpec &url);
00182 INLINE void begin_get_subdocument(const DocumentSpec &url,
00183 size_t first_byte, size_t last_byte);
00184 INLINE void begin_get_header(const DocumentSpec &url);
00185 INLINE void begin_post_form(const DocumentSpec &url, const string &body);
00186 bool run();
00187 INLINE void begin_connect_to(const DocumentSpec &url);
00188
00189 ISocketStream *open_read_body();
00190 void close_read_body(istream *stream) const;
00191
00192 BLOCKING bool download_to_file(const Filename &filename, bool subdocument_resumes = true);
00193 BLOCKING bool download_to_ram(Ramfile *ramfile, bool subdocument_resumes = true);
00194 BLOCKING bool download_to_stream(ostream *strm, bool subdocument_resumes = true);
00195 SocketStream *get_connection();
00196
00197 INLINE size_t get_bytes_downloaded() const;
00198 INLINE size_t get_bytes_requested() const;
00199 INLINE bool is_download_complete() const;
00200
00201 public:
00202 static string downcase(const string &s);
00203 void body_stream_destructs(ISocketStream *stream);
00204
00205 private:
00206 bool reached_done_state();
00207 bool run_try_next_proxy();
00208 bool run_connecting();
00209 bool run_connecting_wait();
00210 bool run_http_proxy_ready();
00211 bool run_http_proxy_request_sent();
00212 bool run_http_proxy_reading_header();
00213 bool run_socks_proxy_greet();
00214 bool run_socks_proxy_greet_reply();
00215 bool run_socks_proxy_connect();
00216 bool run_socks_proxy_connect_reply();
00217 bool run_setup_ssl();
00218 bool run_ssl_handshake();
00219 bool run_ready();
00220 bool run_request_sent();
00221 bool run_reading_header();
00222 bool run_start_direct_file_read();
00223 bool run_read_header();
00224 bool run_begin_body();
00225 bool run_reading_body();
00226 bool run_read_body();
00227 bool run_read_trailer();
00228
00229 bool run_download_to_file();
00230 bool run_download_to_ram();
00231 bool run_download_to_stream();
00232
00233 void begin_request(HTTPEnum::Method method, const DocumentSpec &url,
00234 const string &body, bool nonblocking,
00235 size_t first_byte, size_t last_byte);
00236 void reconsider_proxy();
00237 void reset_for_new_request();
00238
00239 void finished_body(bool has_trailer);
00240 bool open_download_file();
00241
00242 bool server_getline(string &str);
00243 bool server_getline_failsafe(string &str);
00244 bool server_get(string &str, size_t num_bytes);
00245 bool server_get_failsafe(string &str, size_t num_bytes);
00246 bool server_send(const string &str, bool secret);
00247 bool parse_http_response(const string &line);
00248 bool parse_http_header();
00249 bool parse_content_range(const string &content_range);
00250
00251 void check_socket();
00252
00253 void check_preapproved_server_certificate(X509 *cert, bool &cert_preapproved,
00254 bool &cert_name_preapproved) const;
00255 bool validate_server_name(X509 *cert);
00256 static bool match_cert_name(const string &cert_name, const string &hostname);
00257 static string get_x509_name_component(X509_NAME *name, int nid);
00258
00259 void make_header();
00260 void make_proxy_request_text();
00261 void make_request_text();
00262
00263 void reset_url(const URLSpec &old_url, const URLSpec &new_url);
00264 void store_header_field(const string &field_name, const string &field_value);
00265
00266 #ifndef NDEBUG
00267 static void show_send(const string &message);
00268 #endif
00269
00270 void reset_download_to();
00271 void close_download_stream();
00272 void reset_to_new();
00273 void reset_body_stream();
00274 void close_connection();
00275
00276 static bool more_useful_status_code(int a, int b);
00277
00278 public:
00279
00280
00281 enum State {
00282 S_new,
00283 S_try_next_proxy,
00284 S_connecting,
00285 S_connecting_wait,
00286 S_http_proxy_ready,
00287 S_http_proxy_request_sent,
00288 S_http_proxy_reading_header,
00289 S_socks_proxy_greet,
00290 S_socks_proxy_greet_reply,
00291 S_socks_proxy_connect,
00292 S_socks_proxy_connect_reply,
00293 S_setup_ssl,
00294 S_ssl_handshake,
00295 S_ready,
00296 S_request_sent,
00297 S_reading_header,
00298 S_start_direct_file_read,
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
00307 private:
00308 class StatusEntry {
00309 public:
00310 INLINE StatusEntry();
00311 int _status_code;
00312 string _status_string;
00313 };
00314 typedef pvector<URLSpec> Proxies;
00315 typedef pvector<StatusEntry> StatusList;
00316
00317 HTTPClient *_client;
00318 Proxies _proxies;
00319 size_t _proxy_next_index;
00320 StatusList _status_list;
00321 URLSpec _proxy;
00322 PT(BioPtr) _bio;
00323 PT(BioStreamPtr) _source;
00324 bool _persistent_connection;
00325 bool _allow_proxy;
00326 bool _proxy_tunnel;
00327 double _connect_timeout;
00328 double _http_timeout;
00329 size_t _skip_body_size;
00330 double _idle_timeout;
00331 bool _blocking_connect;
00332 bool _download_throttle;
00333 double _max_bytes_per_second;
00334 double _max_updates_per_second;
00335 double _seconds_per_update;
00336 int _bytes_per_update;
00337 bool _nonblocking;
00338 bool _wanted_nonblocking;
00339 string _send_extra_headers;
00340
00341 DocumentSpec _document_spec;
00342 DocumentSpec _request;
00343 HTTPEnum::Method _method;
00344 string request_path;
00345 string _header;
00346 string _body;
00347 bool _want_ssl;
00348 bool _proxy_serves_document;
00349 bool _proxy_tunnel_now;
00350 bool _server_response_has_no_body;
00351 size_t _first_byte_requested;
00352 size_t _last_byte_requested;
00353 size_t _first_byte_delivered;
00354 size_t _last_byte_delivered;
00355 int _connect_count;
00356
00357 enum DownloadDest {
00358 DD_none,
00359 DD_file,
00360 DD_ram,
00361 DD_stream,
00362 };
00363 DownloadDest _download_dest;
00364 bool _subdocument_resumes;
00365 Filename _download_to_filename;
00366 Ramfile *_download_to_ramfile;
00367 ostream *_download_to_stream;
00368
00369 int _read_index;
00370
00371 HTTPEnum::HTTPVersion _http_version;
00372 string _http_version_string;
00373 StatusEntry _status_entry;
00374 URLSpec _redirect;
00375
00376 string _proxy_realm;
00377 string _proxy_username;
00378 PT(HTTPAuthorization) _proxy_auth;
00379
00380 string _www_realm;
00381 string _www_username;
00382 PT(HTTPAuthorization) _www_auth;
00383
00384
00385 enum ResponseType {
00386 RT_none,
00387 RT_hangup,
00388 RT_non_http,
00389 RT_http_hangup,
00390 RT_http_complete
00391 };
00392 ResponseType _response_type;
00393
00394
00395 typedef pmap<string, string> Headers;
00396 Headers _headers;
00397
00398 size_t _expected_file_size;
00399 size_t _file_size;
00400 size_t _transfer_file_size;
00401 size_t _bytes_downloaded;
00402 size_t _bytes_requested;
00403 bool _got_expected_file_size;
00404 bool _got_file_size;
00405 bool _got_transfer_file_size;
00406
00407
00408
00409
00410
00411
00412
00413 State _state;
00414 State _done_state;
00415 double _started_connecting_time;
00416 double _sent_request_time;
00417 bool _started_download;
00418 string _proxy_header;
00419 string _proxy_request_text;
00420 string _request_text;
00421 string _working_get;
00422 size_t _sent_so_far;
00423 string _current_field_name;
00424 string _current_field_value;
00425 ISocketStream *_body_stream;
00426 bool _owns_body_stream;
00427 BIO *_sbio;
00428 string _cipher_list;
00429 pvector<URLSpec> _redirect_trail;
00430 int _last_status_code;
00431 double _last_run_time;
00432
00433
00434
00435 double _extra_ssl_handshake_time;
00436
00437 public:
00438 virtual TypeHandle get_type() const {
00439 return get_class_type();
00440 }
00441 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00442 static TypeHandle get_class_type() {
00443 return _type_handle;
00444 }
00445 static void init_type() {
00446 TypedReferenceCount::init_type();
00447 register_type(_type_handle, "HTTPChannel",
00448 TypedReferenceCount::get_class_type());
00449 }
00450
00451 private:
00452 static TypeHandle _type_handle;
00453 friend class ChunkedStreamBuf;
00454 friend class IdentityStreamBuf;
00455 friend class HTTPClient;
00456 };
00457
00458 ostream &operator << (ostream &out, HTTPChannel::State state);
00459
00460 #include "httpChannel.I"
00461
00462 #endif // HAVE_OPENSSL
00463
00464 #endif
00465
00466