744 lines
32 KiB
Plaintext
744 lines
32 KiB
Plaintext
// Filename: httpChannel.I
|
|
// Created by: drose (24Sep02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::is_valid
|
|
// Access: Published
|
|
// Description: Returns true if the last-requested document was
|
|
// successfully retrieved and is ready to be read, false
|
|
// otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
is_valid() const {
|
|
return (_state != S_failure && (_status_code / 100) == 2 &&
|
|
(_server_response_has_no_body || !_source.is_null()));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::is_connection_ready
|
|
// Access: Published
|
|
// Description: Returns true if a connection has been established to
|
|
// the named server in a previous call to connect_to()
|
|
// or begin_connect_to(), false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
is_connection_ready() const {
|
|
return (!_source.is_null() && _state == S_ready);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_url
|
|
// Access: Published
|
|
// Description: Returns the URL that was used to retrieve the
|
|
// most recent document: whatever URL was last passed to
|
|
// get_document() or get_header(). If a redirect has
|
|
// transparently occurred, this will return the new,
|
|
// redirected URL (the actual URL at which the document
|
|
// was located).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const URLSpec &HTTPChannel::
|
|
get_url() const {
|
|
return _document_spec.get_url();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_document_spec
|
|
// Access: Published
|
|
// Description: Returns the DocumentSpec associated with the most
|
|
// recent document. This includes its actual URL
|
|
// (following redirects) along with the identity tag and
|
|
// last-modified date, if supplied by the server.
|
|
//
|
|
// This structure may be saved and used to retrieve the
|
|
// same version of the document later, or to
|
|
// conditionally retrieve a newer version if it is
|
|
// available.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const DocumentSpec &HTTPChannel::
|
|
get_document_spec() const {
|
|
return _document_spec;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_http_version
|
|
// Access: Published
|
|
// Description: Returns the HTTP version number returned by the
|
|
// server, as one of the HTTPClient enumerated types,
|
|
// e.g. HTTPClient::HV_11.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE HTTPEnum::HTTPVersion HTTPChannel::
|
|
get_http_version() const {
|
|
return _http_version;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_http_version_string
|
|
// Access: Published
|
|
// Description: Returns the HTTP version number returned by the
|
|
// server, formatted as a string, e.g. "HTTP/1.1".
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const string &HTTPChannel::
|
|
get_http_version_string() const {
|
|
return _http_version_string;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_status_code
|
|
// Access: Published
|
|
// Description: Returns the HTML return code from the document
|
|
// retrieval request. This will be in the 200 range if
|
|
// the document is successfully retrieved, or some other
|
|
// value in the case of an error.
|
|
//
|
|
// Some proxy errors during an https-over-proxy request
|
|
// would return the same status code as a different
|
|
// error that occurred on the host server. To
|
|
// differentiate these cases, status codes that are
|
|
// returned by the proxy during the CONNECT phase
|
|
// (except code 407) are incremented by 1000.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE int HTTPChannel::
|
|
get_status_code() const {
|
|
return _status_code;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_status_string
|
|
// Access: Published
|
|
// Description: Returns the string as returned by the server
|
|
// describing the status code for humans. This may or
|
|
// may not be meaningful.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const string &HTTPChannel::
|
|
get_status_string() const {
|
|
return _status_string;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_www_realm
|
|
// Access: Published
|
|
// Description: If the document failed to connect because of a 401
|
|
// (Authorization required), this method will return the
|
|
// "realm" returned by the server in which the requested
|
|
// document must be authenticated. This string may be
|
|
// presented to the user to request an associated
|
|
// username and password (which then should be stored in
|
|
// HTTPClient::set_username()).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const string &HTTPChannel::
|
|
get_www_realm() const {
|
|
return _www_realm;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_proxy_realm
|
|
// Access: Published
|
|
// Description: If the document failed to connect because of a 407
|
|
// (Proxy authorization required), this method will
|
|
// return the "realm" returned by the proxy. This
|
|
// string may be presented to the user to request an
|
|
// associated username and password (which then should
|
|
// be stored in HTTPClient::set_username()).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const string &HTTPChannel::
|
|
get_proxy_realm() const {
|
|
return _proxy_realm;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_redirect
|
|
// Access: Published
|
|
// Description: If the document failed with a redirect code (300
|
|
// series), this will generally contain the new URL the
|
|
// server wants us to try. In many cases, the client
|
|
// will automatically follow redirects; if these are
|
|
// succesful the client will return a successful code
|
|
// and get_redirect() will return empty, but get_url()
|
|
// will return the new, redirected URL.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE const URLSpec &HTTPChannel::
|
|
get_redirect() const {
|
|
return _redirect;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_persistent_connection
|
|
// Access: Published
|
|
// Description: Indicates whether the HTTPChannel should try to keep
|
|
// the connection to the server open and reuse that
|
|
// connection for multiple documents, or whether it
|
|
// should close the connection and open a new one for
|
|
// each request. Set this true to keep the connections
|
|
// around when possible, false to recycle them.
|
|
//
|
|
// It makes most sense to set this false when the
|
|
// HTTPChannel will be used only once to retrieve a
|
|
// single document, true when you will be using the same
|
|
// HTTPChannel object to retrieve multiple documents.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_persistent_connection(bool persistent_connection) {
|
|
_persistent_connection = persistent_connection;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_persistent_connection
|
|
// Access: Published
|
|
// Description: Returns whether the HTTPChannel should try to keep
|
|
// the connection to the server open and reuse that
|
|
// connection for multiple documents, or whether it
|
|
// should close the connection and open a new one for
|
|
// each request. See set_persistent_connection().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_persistent_connection() const {
|
|
return _persistent_connection;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_connect_timeout
|
|
// Access: Published
|
|
// Description: Sets the maximum length of time, in seconds, that the
|
|
// channel will wait before giving up on establishing a
|
|
// TCP connection.
|
|
//
|
|
// At present, this is used only for the nonblocking
|
|
// interfaces (e.g. begin_get_document(),
|
|
// begin_connect_to()), but it is used whether
|
|
// set_blocking_connect() is true or false.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_connect_timeout(double connect_timeout) {
|
|
_connect_timeout = connect_timeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_connect_timeout
|
|
// Access: Published
|
|
// Description: Returns the length of time, in seconds, to wait for a
|
|
// new nonblocking socket to connect. See
|
|
// set_connect_timeout().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double HTTPChannel::
|
|
get_connect_timeout() const {
|
|
return _connect_timeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_blocking_connect
|
|
// Access: Published
|
|
// Description: If this flag is true, a socket connect will block
|
|
// even for nonblocking I/O calls like
|
|
// begin_get_document(), begin_connect_to(), etc. If
|
|
// false, a socket connect will not block for
|
|
// nonblocking I/O calls, but will block for blocking
|
|
// I/O calls (get_document(), connect_to(), etc.).
|
|
|
|
// Setting this true is useful when you want to use
|
|
// non-blocking I/O once you have established the
|
|
// connection, but you don't want to bother with polling
|
|
// for the initial connection. It's also useful when
|
|
// you don't particularly care about non-blocking I/O,
|
|
// but you need to respect timeouts like connect_timeout
|
|
// and http_timeout.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_blocking_connect(bool blocking_connect) {
|
|
_blocking_connect = blocking_connect;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_blocking_connect
|
|
// Access: Published
|
|
// Description: If this flag is true, a socket connect will block
|
|
// even for nonblocking I/O calls like
|
|
// begin_get_document(), begin_connect_to(), etc. If
|
|
// false, a socket connect will not block for
|
|
// nonblocking I/O calls, but will block for blocking
|
|
// I/O calls (get_document(), connect_to(), etc.).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_blocking_connect() const {
|
|
return _blocking_connect;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_http_timeout
|
|
// Access: Published
|
|
// Description: Sets the maximum length of time, in seconds, that the
|
|
// channel will wait for the HTTP server to finish
|
|
// sending its response to our request.
|
|
//
|
|
// The timer starts counting after the TCP connection
|
|
// has been established (see set_connect_timeout(),
|
|
// above) and the request has been sent.
|
|
//
|
|
// At present, this is used only for the nonblocking
|
|
// interfaces (e.g. begin_get_document(),
|
|
// begin_connect_to()), but it is used whether
|
|
// set_blocking_connect() is true or false.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_http_timeout(double http_timeout) {
|
|
_http_timeout = http_timeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_http_timeout
|
|
// Access: Published
|
|
// Description: Returns the length of time, in seconds, to wait for
|
|
// the HTTP server to respond to our request. See
|
|
// set_http_timeout().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double HTTPChannel::
|
|
get_http_timeout() const {
|
|
return _http_timeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_download_throttle
|
|
// Access: Published
|
|
// Description: Specifies whether nonblocking downloads (via
|
|
// download_to_file() or download_to_ram()) will be
|
|
// limited so as not to use all available bandwidth.
|
|
//
|
|
// If this is true, when a download has been started on
|
|
// this channel it will be invoked no more frequently
|
|
// than get_max_updates_per_second(), and the total
|
|
// bandwidth used by the download will be no more than
|
|
// get_max_bytes_per_second(). If this is false,
|
|
// downloads will proceed as fast as the server can send
|
|
// the data.
|
|
//
|
|
// This only has effect on the nonblocking I/O methods
|
|
// like begin_get_document(), etc. The blocking methods
|
|
// like get_document() always use as much CPU and
|
|
// bandwidth as they can get.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_download_throttle(bool download_throttle) {
|
|
_download_throttle = download_throttle;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_download_throttle
|
|
// Access: Published
|
|
// Description: Returns whether the nonblocking downloads will be
|
|
// bandwidth-limited. See set_download_throttle().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_download_throttle() const {
|
|
return _download_throttle;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_max_bytes_per_second
|
|
// Access: Published
|
|
// Description: When bandwidth throttling is in effect (see
|
|
// set_download_throttle()), this specifies the maximum
|
|
// number of bytes per second that may be consumed by
|
|
// this channel.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_max_bytes_per_second(double max_bytes_per_second) {
|
|
_max_bytes_per_second = max_bytes_per_second;
|
|
_bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_max_bytes_per_second
|
|
// Access: Published
|
|
// Description: Returns the maximum number of bytes per second that
|
|
// may be consumed by this channel when
|
|
// get_download_throttle() is true.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double HTTPChannel::
|
|
get_max_bytes_per_second() const {
|
|
return _max_bytes_per_second;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::set_max_updates_per_second
|
|
// Access: Published
|
|
// Description: When bandwidth throttling is in effect (see
|
|
// set_download_throttle()), this specifies the maximum
|
|
// number of times per second that run() will attempt to
|
|
// do any downloading at all.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
set_max_updates_per_second(double max_updates_per_second) {
|
|
nassertv(max_updates_per_second != 0.0f);
|
|
_max_updates_per_second = max_updates_per_second;
|
|
_seconds_per_update = 1.0f / _max_updates_per_second;
|
|
_bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_max_updates_per_second
|
|
// Access: Published
|
|
// Description: Returns the maximum number of times per second that
|
|
// run() will do anything at all, when
|
|
// get_download_throttle() is true.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE double HTTPChannel::
|
|
get_max_updates_per_second() const {
|
|
return _max_updates_per_second;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_file_size
|
|
// Access: Published
|
|
// Description: Returns the size of the file, if it is known.
|
|
// Returns 0 if the file size is not known.
|
|
//
|
|
// If the file is dynamically generated, the size may
|
|
// not be available until a read has started
|
|
// (e.g. open_read_file() has been called); and even
|
|
// then it may increase as more of the file is read due
|
|
// to the nature of HTTP/1.1 requests which can change
|
|
// their minds midstream about how much data they're
|
|
// sending you.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE size_t HTTPChannel::
|
|
get_file_size() const {
|
|
return _file_size;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::reset
|
|
// Access: Published
|
|
// Description: Stops whatever file transaction is currently in
|
|
// progress, closes the connection, and resets to begin
|
|
// anew. You shouldn't ever need to call this, since
|
|
// the channel should be able to reset itself cleanly
|
|
// between requests, but it is provided in case you are
|
|
// an especially nervous type.
|
|
//
|
|
// Don't call this after every request unless you set
|
|
// set_persistent_connection() to false, since calling
|
|
// reset() rudely closes the connection regardless of
|
|
// whether we have told the server we intend to keep it
|
|
// open or not.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
reset() {
|
|
reset_for_new_request();
|
|
reset_to_new();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::clear_extra_headers
|
|
// Access: Published
|
|
// Description: Resets the extra headers that were previously added
|
|
// via calls to send_extra_header().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
clear_extra_headers() {
|
|
_send_extra_headers = string();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::send_extra_header
|
|
// Access: Published
|
|
// Description: Specifies an additional key: value pair that is added
|
|
// into the header sent to the server with the next
|
|
// request. This is passed along with no interpretation
|
|
// by the HTTPChannel code. You may call this
|
|
// repeatedly to append multiple headers.
|
|
//
|
|
// This is persistent for one request only; it must be
|
|
// set again for each new request.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
send_extra_header(const string &key, const string &value) {
|
|
_send_extra_headers += key;
|
|
_send_extra_headers += ": ";
|
|
_send_extra_headers += value;
|
|
_send_extra_headers += "\r\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_document
|
|
// Access: Published
|
|
// Description: Opens the named document for reading, if available.
|
|
// Returns true if successful, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_document(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_get, url, string(), false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_subdocument
|
|
// Access: Published
|
|
// Description: Retrieves only the specified byte range of the
|
|
// indicated document. If last_byte is 0, it stands for
|
|
// the last byte of the document. When a subdocument is
|
|
// requested, get_file_size() and get_bytes_downloaded()
|
|
// will report the number of bytes of the subdocument,
|
|
// not of the complete document.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_subdocument(const DocumentSpec &url, size_t first_byte, size_t last_byte) {
|
|
begin_request(HTTPEnum::M_get, url, string(), false, first_byte, last_byte);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_header
|
|
// Access: Published
|
|
// Description: Like get_document(), except only the header
|
|
// associated with the document is retrieved. This may
|
|
// be used to test for existence of the document; it
|
|
// might also return the size of the document (if the
|
|
// server gives us this information).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_header(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_head, url, string(), false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::post_form
|
|
// Access: Published
|
|
// Description: Posts form data to a particular URL and retrieves the
|
|
// response.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
post_form(const DocumentSpec &url, const string &body) {
|
|
begin_request(HTTPEnum::M_post, url, body, false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::put_document
|
|
// Access: Published
|
|
// Description: Uploads the indicated body to the server to replace
|
|
// the indicated URL, if the server allows this.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
put_document(const DocumentSpec &url, const string &body) {
|
|
begin_request(HTTPEnum::M_put, url, body, false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::delete_document
|
|
// Access: Published
|
|
// Description: Requests the server to remove the indicated URL.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
delete_document(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_delete, url, string(), false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_trace
|
|
// Access: Published
|
|
// Description: Sends a TRACE message to the server, which should
|
|
// return back the same message as the server received
|
|
// it, allowing inspection of proxy hops, etc.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
get_trace(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_trace, url, string(), false, 0, 0);
|
|
run();
|
|
return is_valid();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::connect_to
|
|
// Access: Published
|
|
// Description: Establish a direct connection to the server and port
|
|
// indicated by the URL, but do not issue any HTTP
|
|
// requests. If successful, the connection may then be
|
|
// taken to use for whatever purposes you like by
|
|
// calling get_connection().
|
|
//
|
|
// This establishes a blocking I/O socket. Also see
|
|
// begin_connect_to().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
connect_to(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_connect, url, string(), false, 0, 0);
|
|
run();
|
|
return is_connection_ready();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::begin_get_document
|
|
// Access: Published
|
|
// Description: Begins a non-blocking request to retrieve a given
|
|
// document. This method will return immediately, even
|
|
// before a connection to the server has necessarily
|
|
// been established; you must then call run() from time
|
|
// to time until the return value of run() is false.
|
|
// Then you may check is_valid() and get_status_code()
|
|
// to determine the status of your request.
|
|
//
|
|
// If a previous request had been pending, that request
|
|
// is discarded.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
begin_get_document(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_get, url, string(), true, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::begin_get_subdocument
|
|
// Access: Published
|
|
// Description: Begins a non-blocking request to retrieve only the
|
|
// specified byte range of the indicated document. If
|
|
// last_byte is 0, it stands for the last byte of the
|
|
// document. When a subdocument is requested,
|
|
// get_file_size() and get_bytes_downloaded() will
|
|
// report the number of bytes of the subdocument, not of
|
|
// the complete document.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
begin_get_subdocument(const DocumentSpec &url, size_t first_byte,
|
|
size_t last_byte) {
|
|
begin_request(HTTPEnum::M_get, url, string(), true, first_byte, last_byte);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::begin_get_header
|
|
// Access: Published
|
|
// Description: Begins a non-blocking request to retrieve a given
|
|
// header. See begin_get_document() and get_header().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
begin_get_header(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_head, url, string(), true, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::begin_post_form
|
|
// Access: Published
|
|
// Description: Posts form data to a particular URL and retrieves the
|
|
// response, all using non-blocking I/O. See
|
|
// begin_get_document() and post_form().
|
|
//
|
|
// It is important to note that you *must* call run()
|
|
// repeatedly after calling this method until run()
|
|
// returns false, and you may not call any other
|
|
// document posting or retrieving methods using the
|
|
// HTTPChannel object in the interim, or your form data
|
|
// may not get posted.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
begin_post_form(const DocumentSpec &url, const string &body) {
|
|
begin_request(HTTPEnum::M_post, url, body, true, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::begin_connect_to
|
|
// Access: Published
|
|
// Description: Begins a non-blocking request to establish a direct
|
|
// connection to the server and port indicated by the
|
|
// URL. No HTTP requests will be issued beyond what is
|
|
// necessary to establish the connection. When run()
|
|
// has finished, you may call is_connection_ready() to
|
|
// determine if the connection was successfully
|
|
// established.
|
|
//
|
|
// If successful, the connection may then be taken to
|
|
// use for whatever purposes you like by calling
|
|
// get_connection().
|
|
//
|
|
// This establishes a nonblocking I/O socket. Also see
|
|
// connect_to().
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE void HTTPChannel::
|
|
begin_connect_to(const DocumentSpec &url) {
|
|
begin_request(HTTPEnum::M_connect, url, string(), true, 0, 0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_bytes_downloaded
|
|
// Access: Published
|
|
// Description: Returns the number of bytes downloaded during the
|
|
// last (or current) download_to_file() or
|
|
// download_to_ram operation(). This can be used in
|
|
// conjunction with get_file_size() to report the
|
|
// percent complete (but be careful, since
|
|
// get_file_size() may return 0 if the server has not
|
|
// told us the size of the file).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE size_t HTTPChannel::
|
|
get_bytes_downloaded() const {
|
|
return _bytes_downloaded;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::get_bytes_requested
|
|
// Access: Published
|
|
// Description: When download throttling is in effect
|
|
// (set_download_throttle() has been set to true) and
|
|
// non-blocking I/O methods (like begin_get_document())
|
|
// are used, this returns the number of bytes
|
|
// "requested" from the server so far: that is, the
|
|
// theoretical maximum value for get_bytes_downloaded(),
|
|
// if the server has been keeping up with our demand.
|
|
//
|
|
// If this number is less than get_bytes_downloaded(),
|
|
// then the server has not been supplying bytes fast
|
|
// enough to meet our own download throttle rate.
|
|
//
|
|
// When download throttling is not in effect, or when
|
|
// the blocking I/O methods (like get_document(), etc.)
|
|
// are used, this returns 0.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE size_t HTTPChannel::
|
|
get_bytes_requested() const {
|
|
return _bytes_requested;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: HTTPChannel::is_download_complete
|
|
// Access: Published
|
|
// Description: Returns true when a download_to() or
|
|
// download_to_ram() has executed and the file has been
|
|
// fully downloaded. If this still returns false after
|
|
// processing has completed, there was an error in
|
|
// transmission.
|
|
//
|
|
// Note that simply testing is_download_complete() does
|
|
// not prove that the requested document was succesfully
|
|
// retrieved--you might have just downloaded the "404
|
|
// not found" stub (for instance) that a server would
|
|
// provide in response to some error condition. You
|
|
// should also check is_valid() to prove that the file
|
|
// you expected has been successfully retrieved.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE bool HTTPChannel::
|
|
is_download_complete() const {
|
|
return (_download_dest != DD_none &&
|
|
(_state == S_read_body || _state == S_read_trailer));
|
|
}
|