Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/downloader/httpChannel.h

Go to the documentation of this file.
00001 // Filename: httpChannel.h
00002 // Created by:  drose (24Sep02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #ifndef HTTPCHANNEL_H
00020 #define HTTPCHANNEL_H
00021 
00022 #include "pandabase.h"
00023 
00024 // This module requires OpenSSL to compile, even if you do not intend
00025 // to use this to establish https connections; this is because it uses
00026 // the OpenSSL library to portably handle all of the socket
00027 // communications.
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 //       Class : HTTPChannel
00049 // Description : A single channel of communication from an HTTPClient.
00050 //               This is similar to the concept of a 'connection',
00051 //               except that HTTP is technically connectionless; in
00052 //               fact, a channel may represent one unbroken connection
00053 //               or it may transparently close and reopen a new
00054 //               connection with each request.
00055 //
00056 //               A channel is conceptually a single thread of I/O.
00057 //               One document at a time may be requested using a
00058 //               channel; a new document may (in general) not be
00059 //               requested from the same HTTPChannel until the first
00060 //               document has been fully retrieved.
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   // What type of response do we get to our HTTP request?
00264   enum ResponseType {
00265     RT_none,
00266     RT_hangup,       // immediately lost connection 
00267     RT_non_http,     // something that wasn't an expected HTTP response
00268     RT_http_hangup,  // the start of an HTTP response, then a lost connection
00269     RT_http_complete // a valid HTTP response completed
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   // These members are used to maintain the current state while
00282   // communicating with the server.  We need to store everything in
00283   // the class object instead of using local variables because in the
00284   // case of nonblocking I/O we have to be able to return to the
00285   // caller after any I/O operation and resume later where we left
00286   // off.
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 

Generated on Fri May 2 00:36:48 2003 for Panda by doxygen1.3