Panda3D
httpChannel.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file httpChannel.I
10  * @author drose
11  * @date 2002-09-24
12  */
13 
14 /**
15  * Returns the HTTPClient object that owns this channel.
16  */
17 INLINE HTTPClient *HTTPChannel::
18 get_client() const {
19  return _client;
20 }
21 
22 /**
23  * Returns true if the last-requested document was successfully retrieved and
24  * is ready to be read, false otherwise.
25  */
26 INLINE bool HTTPChannel::
27 is_valid() const {
28  return (_state != S_failure && (get_status_code() / 100) == 2 &&
29  (_server_response_has_no_body || !_source.is_null()));
30 }
31 
32 /**
33  * Returns true if a connection has been established to the named server in a
34  * previous call to connect_to() or begin_connect_to(), false otherwise.
35  */
36 INLINE bool HTTPChannel::
37 is_connection_ready() const {
38  return (!_source.is_null() && _state == S_ready);
39 }
40 
41 /**
42  * Returns the URL that was used to retrieve the most recent document:
43  * whatever URL was last passed to get_document() or get_header(). If a
44  * redirect has transparently occurred, this will return the new, redirected
45  * URL (the actual URL at which the document was located).
46  */
47 INLINE const URLSpec &HTTPChannel::
48 get_url() const {
49  return _document_spec.get_url();
50 }
51 
52 /**
53  * Returns the DocumentSpec associated with the most recent document. This
54  * includes its actual URL (following redirects) along with the identity tag
55  * and last-modified date, if supplied by the server.
56  *
57  * This structure may be saved and used to retrieve the same version of the
58  * document later, or to conditionally retrieve a newer version if it is
59  * available.
60  */
61 INLINE const DocumentSpec &HTTPChannel::
62 get_document_spec() const {
63  return _document_spec;
64 }
65 
66 /**
67  * Returns the HTTP version number returned by the server, as one of the
68  * HTTPClient enumerated types, e.g. HTTPClient::HV_11.
69  */
70 INLINE HTTPEnum::HTTPVersion HTTPChannel::
71 get_http_version() const {
72  return _http_version;
73 }
74 
75 /**
76  * Returns the HTTP version number returned by the server, formatted as a
77  * string, e.g. "HTTP/1.1".
78  */
79 INLINE const std::string &HTTPChannel::
80 get_http_version_string() const {
81  return _http_version_string;
82 }
83 
84 /**
85  * Returns the HTML return code from the document retrieval request. This
86  * will be in the 200 range if the document is successfully retrieved, or some
87  * other value in the case of an error.
88  *
89  * Some proxy errors during an https-over-proxy request would return the same
90  * status code as a different error that occurred on the host server. To
91  * differentiate these cases, status codes that are returned by the proxy
92  * during the CONNECT phase (except code 407) are incremented by 1000.
93  */
94 INLINE int HTTPChannel::
95 get_status_code() const {
96  return _status_entry._status_code;
97 }
98 
99 /**
100  * If the document failed to connect because of a 401 (Authorization
101  * required), this method will return the "realm" returned by the server in
102  * which the requested document must be authenticated. This string may be
103  * presented to the user to request an associated username and password (which
104  * then should be stored in HTTPClient::set_username()).
105  */
106 INLINE const std::string &HTTPChannel::
107 get_www_realm() const {
108  return _www_realm;
109 }
110 
111 /**
112  * If the document failed to connect because of a 407 (Proxy authorization
113  * required), this method will return the "realm" returned by the proxy. This
114  * string may be presented to the user to request an associated username and
115  * password (which then should be stored in HTTPClient::set_username()).
116  */
117 INLINE const std::string &HTTPChannel::
118 get_proxy_realm() const {
119  return _proxy_realm;
120 }
121 
122 /**
123  * If the document failed with a redirect code (300 series), this will
124  * generally contain the new URL the server wants us to try. In many cases,
125  * the client will automatically follow redirects; if these are successful the
126  * client will return a successful code and get_redirect() will return empty,
127  * but get_url() will return the new, redirected URL.
128  */
129 INLINE const URLSpec &HTTPChannel::
130 get_redirect() const {
131  return _redirect;
132 }
133 
134 /**
135  * If the document automatically followed one or more redirects, this will
136  * return the number of redirects that were automatically followed. Use
137  * get_redirect_step() to retrieve each URL in sequence.
138  */
139 INLINE int HTTPChannel::
140 get_num_redirect_steps() const {
141  return _redirect_trail.size();
142 }
143 
144 /**
145  * Use in conjunction with get_num_redirect_steps() to extract the chain of
146  * URL's that the channel was automatically redirected through to arrive at
147  * the final document.
148  */
149 INLINE const URLSpec &HTTPChannel::
150 get_redirect_step(int n) const {
151  nassertr(n >= 0 && n < (int)_redirect_trail.size(), _redirect_trail[0]);
152  return _redirect_trail[n];
153 }
154 
155 /**
156  * Indicates whether the HTTPChannel should try to keep the connection to the
157  * server open and reuse that connection for multiple documents, or whether it
158  * should close the connection and open a new one for each request. Set this
159  * true to keep the connections around when possible, false to recycle them.
160  *
161  * It makes most sense to set this false when the HTTPChannel will be used
162  * only once to retrieve a single document, true when you will be using the
163  * same HTTPChannel object to retrieve multiple documents.
164  */
165 INLINE void HTTPChannel::
166 set_persistent_connection(bool persistent_connection) {
167  _persistent_connection = persistent_connection;
168 }
169 
170 /**
171  * Returns whether the HTTPChannel should try to keep the connection to the
172  * server open and reuse that connection for multiple documents, or whether it
173  * should close the connection and open a new one for each request. See
174  * set_persistent_connection().
175  */
176 INLINE bool HTTPChannel::
177 get_persistent_connection() const {
178  return _persistent_connection;
179 }
180 
181 /**
182  * If this is true (the normal case), the HTTPClient will be consulted for
183  * information about the proxy to be used for each connection via this
184  * HTTPChannel. If this has been set to false by the user, then all
185  * connections will be made directly, regardless of the proxy settings
186  * indicated on the HTTPClient.
187  */
188 INLINE void HTTPChannel::
189 set_allow_proxy(bool allow_proxy) {
190  _allow_proxy = allow_proxy;
191 }
192 
193 /**
194  * If this is true (the normal case), the HTTPClient will be consulted for
195  * information about the proxy to be used for each connection via this
196  * HTTPChannel. If this has been set to false by the user, then all
197  * connections will be made directly, regardless of the proxy settings
198  * indicated on the HTTPClient.
199  */
200 INLINE bool HTTPChannel::
201 get_allow_proxy() const {
202  return _allow_proxy;
203 }
204 
205 /**
206  * Normally, a proxy is itself asked for ordinary URL's, and the proxy decides
207  * whether to hand the client a cached version of the document or to contact
208  * the server for a fresh version. The proxy may also modify the headers and
209  * transfer encoding on the way.
210  *
211  * If this is set to true, then instead of asking for URL's from the proxy, we
212  * will ask the proxy to open a connection to the server (for instance, on
213  * port 80); if the proxy honors this request, then we contact the server
214  * directly through this connection to retrieve the document. If the proxy
215  * does not honor the connect request, then the retrieve operation fails.
216  *
217  * SSL connections (e.g. https), and connections through a Socks proxy, are
218  * always tunneled, regardless of the setting of this flag.
219  */
220 INLINE void HTTPChannel::
221 set_proxy_tunnel(bool proxy_tunnel) {
222  _proxy_tunnel = proxy_tunnel;
223 }
224 
225 /**
226  * Returns true if connections always tunnel through a proxy, or false (the
227  * normal case) if we allow the proxy to serve up documents. See
228  * set_proxy_tunnel().
229  */
230 INLINE bool HTTPChannel::
231 get_proxy_tunnel() const {
232  return _proxy_tunnel;
233 }
234 
235 /**
236  * Sets the maximum length of time, in seconds, that the channel will wait
237  * before giving up on establishing a TCP connection.
238  *
239  * At present, this is used only for the nonblocking interfaces (e.g.
240  * begin_get_document(), begin_connect_to()), but it is used whether
241  * set_blocking_connect() is true or false.
242  */
243 INLINE void HTTPChannel::
244 set_connect_timeout(double connect_timeout) {
245  _connect_timeout = connect_timeout;
246 }
247 
248 /**
249  * Returns the length of time, in seconds, to wait for a new nonblocking
250  * socket to connect. See set_connect_timeout().
251  */
252 INLINE double HTTPChannel::
253 get_connect_timeout() const {
254  return _connect_timeout;
255 }
256 
257 /**
258  * If this flag is true, a socket connect will block even for nonblocking I/O
259  * calls like begin_get_document(), begin_connect_to(), etc. If false, a
260  * socket connect will not block for nonblocking I/O calls, but will block for
261  * blocking I/O calls (get_document(), connect_to(), etc.).
262  *
263  * Setting this true is useful when you want to use non-blocking I/O once you
264  * have established the connection, but you don't want to bother with polling
265  * for the initial connection. It's also useful when you don't particularly
266  * care about non-blocking I/O, but you need to respect timeouts like
267  * connect_timeout and http_timeout.
268  */
269 INLINE void HTTPChannel::
270 set_blocking_connect(bool blocking_connect) {
271  _blocking_connect = blocking_connect;
272 }
273 
274 /**
275  * If this flag is true, a socket connect will block even for nonblocking I/O
276  * calls like begin_get_document(), begin_connect_to(), etc. If false, a
277  * socket connect will not block for nonblocking I/O calls, but will block for
278  * blocking I/O calls (get_document(), connect_to(), etc.).
279  */
280 INLINE bool HTTPChannel::
281 get_blocking_connect() const {
282  return _blocking_connect;
283 }
284 
285 /**
286  * Sets the maximum length of time, in seconds, that the channel will wait for
287  * the HTTP server to finish sending its response to our request.
288  *
289  * The timer starts counting after the TCP connection has been established
290  * (see set_connect_timeout(), above) and the request has been sent.
291  *
292  * At present, this is used only for the nonblocking interfaces (e.g.
293  * begin_get_document(), begin_connect_to()), but it is used whether
294  * set_blocking_connect() is true or false.
295  */
296 INLINE void HTTPChannel::
297 set_http_timeout(double http_timeout) {
298  _http_timeout = http_timeout;
299 }
300 
301 /**
302  * Returns the length of time, in seconds, to wait for the HTTP server to
303  * respond to our request. See set_http_timeout().
304  */
305 INLINE double HTTPChannel::
306 get_http_timeout() const {
307  return _http_timeout;
308 }
309 
310 /**
311  * Specifies the maximum number of bytes in a received (but unwanted) body
312  * that will be skipped past, in order to reset to a new request.
313  *
314  * That is, if this HTTPChannel requests a file via get_document(), but does
315  * not call download_to_ram(), download_to_file(), or open_read_body(), and
316  * instead immediately requests a new file, then the HTTPChannel has a choice
317  * whether to skip past the unwanted document, or to close the connection and
318  * open a new one. If the number of bytes to skip is more than this
319  * threshold, the connection will be closed; otherwise, the data will simply
320  * be read and discarded.
321  */
322 INLINE void HTTPChannel::
323 set_skip_body_size(size_t skip_body_size) {
324  _skip_body_size = skip_body_size;
325 }
326 
327 /**
328  * Returns the maximum number of bytes in a received (but unwanted) body that
329  * will be skipped past, in order to reset to a new request. See
330  * set_skip_body_size().
331  */
332 INLINE size_t HTTPChannel::
333 get_skip_body_size() const {
334  return _skip_body_size;
335 }
336 
337 /**
338  * Specifies the amount of time, in seconds, in which a previously-established
339  * connection is allowed to remain open and unused. If a previous connection
340  * has remained unused for at least this number of seconds, it will be closed
341  * and a new connection will be opened; otherwise, the same connection will be
342  * reused for the next request (for this particular HTTPChannel).
343  */
344 INLINE void HTTPChannel::
345 set_idle_timeout(double idle_timeout) {
346  _idle_timeout = idle_timeout;
347 }
348 
349 /**
350  * Returns the amount of time, in seconds, in which an previously-established
351  * connection is allowed to remain open and unused. See set_idle_timeout().
352  */
353 INLINE double HTTPChannel::
354 get_idle_timeout() const {
355  return _idle_timeout;
356 }
357 
358 /**
359  * Specifies whether nonblocking downloads (via download_to_file() or
360  * download_to_ram()) will be limited so as not to use all available
361  * bandwidth.
362  *
363  * If this is true, when a download has been started on this channel it will
364  * be invoked no more frequently than get_max_updates_per_second(), and the
365  * total bandwidth used by the download will be no more than
366  * get_max_bytes_per_second(). If this is false, downloads will proceed as
367  * fast as the server can send the data.
368  *
369  * This only has effect on the nonblocking I/O methods like
370  * begin_get_document(), etc. The blocking methods like get_document() always
371  * use as much CPU and bandwidth as they can get.
372  */
373 INLINE void HTTPChannel::
374 set_download_throttle(bool download_throttle) {
375  _download_throttle = download_throttle;
376 }
377 
378 /**
379  * Returns whether the nonblocking downloads will be bandwidth-limited. See
380  * set_download_throttle().
381  */
382 INLINE bool HTTPChannel::
383 get_download_throttle() const {
384  return _download_throttle;
385 }
386 
387 /**
388  * When bandwidth throttling is in effect (see set_download_throttle()), this
389  * specifies the maximum number of bytes per second that may be consumed by
390  * this channel.
391  */
392 INLINE void HTTPChannel::
393 set_max_bytes_per_second(double max_bytes_per_second) {
394  _max_bytes_per_second = max_bytes_per_second;
395  _bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
396 }
397 
398 /**
399  * Returns the maximum number of bytes per second that may be consumed by this
400  * channel when get_download_throttle() is true.
401  */
402 INLINE double HTTPChannel::
403 get_max_bytes_per_second() const {
404  return _max_bytes_per_second;
405 }
406 
407 /**
408  * When bandwidth throttling is in effect (see set_download_throttle()), this
409  * specifies the maximum number of times per second that run() will attempt to
410  * do any downloading at all.
411  */
412 INLINE void HTTPChannel::
413 set_max_updates_per_second(double max_updates_per_second) {
414  nassertv(max_updates_per_second != 0.0f);
415  _max_updates_per_second = max_updates_per_second;
416  _seconds_per_update = 1.0f / _max_updates_per_second;
417  _bytes_per_update = int(_max_bytes_per_second * _seconds_per_update);
418 }
419 
420 /**
421  * Returns the maximum number of times per second that run() will do anything
422  * at all, when get_download_throttle() is true.
423  */
424 INLINE double HTTPChannel::
425 get_max_updates_per_second() const {
426  return _max_updates_per_second;
427 }
428 
429 /**
430  * Specifies the Content-Type header, useful for applications that require
431  * different types of content, such as JSON.
432  */
433 INLINE void HTTPChannel::
434 set_content_type(std::string content_type) {
435  _content_type = content_type;
436 }
437 
438 /**
439  * Returns the value of the Content-Type header.
440  */
441 INLINE std::string HTTPChannel::
442 get_content_type() const {
443  return _content_type;
444 }
445 
446 /**
447  * This may be called immediately after a call to get_document() or some
448  * related function to specify the expected size of the document we are
449  * retrieving, if we happen to know. This is used as the return value to
450  * get_file_size() only in the case that the server does not tell us the
451  * actual file size.
452  */
453 INLINE void HTTPChannel::
454 set_expected_file_size(size_t file_size) {
455  _expected_file_size = file_size;
456  _got_expected_file_size = true;
457 }
458 
459 
460 /**
461  * Returns true if the size of the file we are currently retrieving was told
462  * us by the server and thus is reliably known, or false if the size reported
463  * by get_file_size() represents an educated guess (possibly as set by
464  * set_expected_file_size(), or as inferred from a chunked transfer encoding
465  * in progress).
466  */
467 INLINE bool HTTPChannel::
468 is_file_size_known() const {
469  return _got_file_size;
470 }
471 
472 /**
473  * Returns the first byte of the file requested by the request. This will
474  * normally be 0 to indicate that the file is being requested from the
475  * beginning, but if the file was requested via a get_subdocument() call, this
476  * will contain the first_byte parameter from that call.
477  */
478 INLINE size_t HTTPChannel::
479 get_first_byte_requested() const {
480  return _first_byte_requested;
481 }
482 
483 /**
484  * Returns the last byte of the file requested by the request. This will
485  * normally be 0 to indicate that the file is being requested to its last
486  * byte, but if the file was requested via a get_subdocument() call, this will
487  * contain the last_byte parameter from that call.
488  */
489 INLINE size_t HTTPChannel::
490 get_last_byte_requested() const {
491  return _last_byte_requested;
492 }
493 
494 /**
495  * Returns the first byte of the file (that will be) delivered by the server
496  * in response to the current request. Normally, this is the same as
497  * get_first_byte_requested(), but some servers will ignore a subdocument
498  * request and always return the whole file, in which case this value will be
499  * 0, regardless of what was requested to get_subdocument().
500  */
501 INLINE size_t HTTPChannel::
502 get_first_byte_delivered() const {
503  return _first_byte_delivered;
504 }
505 
506 /**
507  * Returns the last byte of the file (that will be) delivered by the server in
508  * response to the current request. Normally, this is the same as
509  * get_last_byte_requested(), but some servers will ignore a subdocument
510  * request and always return the whole file, in which case this value will be
511  * 0, regardless of what was requested to get_subdocument().
512  */
513 INLINE size_t HTTPChannel::
514 get_last_byte_delivered() const {
515  return _last_byte_delivered;
516 }
517 
518 /**
519  * Stops whatever file transaction is currently in progress, closes the
520  * connection, and resets to begin anew. You shouldn't ever need to call
521  * this, since the channel should be able to reset itself cleanly between
522  * requests, but it is provided in case you are an especially nervous type.
523  *
524  * Don't call this after every request unless you set
525  * set_persistent_connection() to false, since calling reset() rudely closes
526  * the connection regardless of whether we have told the server we intend to
527  * keep it open or not.
528  */
529 INLINE void HTTPChannel::
530 reset() {
531  reset_for_new_request();
532  reset_to_new();
533  _status_list.clear();
534 }
535 
536 /**
537  * Preserves the previous status code (presumably a failure) from the previous
538  * connection attempt. If the subsequent connection attempt also fails, the
539  * returned status code will be the better of the previous code and the
540  * current code.
541  *
542  * This can be called to daisy-chain subsequent attempts to download the same
543  * document from different servers. After all servers have been attempted,
544  * the final status code will reflect the attempt that most nearly succeeded.
545  */
546 INLINE void HTTPChannel::
547 preserve_status() {
548  _status_list.push_back(_status_entry);
549 }
550 
551 
552 /**
553  * Resets the extra headers that were previously added via calls to
554  * send_extra_header().
555  */
556 INLINE void HTTPChannel::
557 clear_extra_headers() {
558  _send_extra_headers = std::string();
559 }
560 
561 /**
562  * Specifies an additional key: value pair that is added into the header sent
563  * to the server with the next request. This is passed along with no
564  * interpretation by the HTTPChannel code. You may call this repeatedly to
565  * append multiple headers.
566  *
567  * This is persistent for one request only; it must be set again for each new
568  * request.
569  */
570 INLINE void HTTPChannel::
571 send_extra_header(const std::string &key, const std::string &value) {
572  _send_extra_headers += key;
573  _send_extra_headers += ": ";
574  _send_extra_headers += value;
575  _send_extra_headers += "\r\n";
576 }
577 
578 /**
579  * Opens the named document for reading, if available. Returns true if
580  * successful, false otherwise.
581  */
582 INLINE bool HTTPChannel::
583 get_document(const DocumentSpec &url) {
584  begin_request(HTTPEnum::M_get, url, std::string(), false, 0, 0);
585  while (run()) {
586  }
587  return is_valid();
588 }
589 
590 /**
591  * Retrieves only the specified byte range of the indicated document. If
592  * last_byte is 0, it stands for the last byte of the document. When a
593  * subdocument is requested, get_file_size() and get_bytes_downloaded() will
594  * report the number of bytes of the subdocument, not of the complete
595  * document.
596  */
597 INLINE bool HTTPChannel::
598 get_subdocument(const DocumentSpec &url, size_t first_byte, size_t last_byte) {
599  begin_request(HTTPEnum::M_get, url, std::string(), false, first_byte, last_byte);
600  while (run()) {
601  }
602  return is_valid();
603 }
604 
605 /**
606  * Like get_document(), except only the header associated with the document is
607  * retrieved. This may be used to test for existence of the document; it
608  * might also return the size of the document (if the server gives us this
609  * information).
610  */
611 INLINE bool HTTPChannel::
612 get_header(const DocumentSpec &url) {
613  begin_request(HTTPEnum::M_head, url, std::string(), false, 0, 0);
614  while (run()) {
615  }
616  return is_valid();
617 }
618 
619 /**
620  * Posts form data to a particular URL and retrieves the response.
621  */
622 INLINE bool HTTPChannel::
623 post_form(const DocumentSpec &url, const std::string &body) {
624  begin_request(HTTPEnum::M_post, url, body, false, 0, 0);
625  while (run()) {
626  }
627  return is_valid();
628 }
629 
630 /**
631  * Uploads the indicated body to the server to replace the indicated URL, if
632  * the server allows this.
633  */
634 INLINE bool HTTPChannel::
635 put_document(const DocumentSpec &url, const std::string &body) {
636  begin_request(HTTPEnum::M_put, url, body, false, 0, 0);
637  while (run()) {
638  }
639  return is_valid();
640 }
641 
642 /**
643  * Requests the server to remove the indicated URL.
644  */
645 INLINE bool HTTPChannel::
646 delete_document(const DocumentSpec &url) {
647  begin_request(HTTPEnum::M_delete, url, std::string(), false, 0, 0);
648  while (run()) {
649  }
650  return is_valid();
651 }
652 
653 /**
654  * Sends a TRACE message to the server, which should return back the same
655  * message as the server received it, allowing inspection of proxy hops, etc.
656  */
657 INLINE bool HTTPChannel::
658 get_trace(const DocumentSpec &url) {
659  begin_request(HTTPEnum::M_trace, url, std::string(), false, 0, 0);
660  while (run()) {
661  }
662  return is_valid();
663 }
664 
665 /**
666  * Establish a direct connection to the server and port indicated by the URL,
667  * but do not issue any HTTP requests. If successful, the connection may then
668  * be taken to use for whatever purposes you like by calling get_connection().
669  *
670  * This establishes a blocking I/O socket. Also see begin_connect_to().
671  */
672 INLINE bool HTTPChannel::
673 connect_to(const DocumentSpec &url) {
674  begin_request(HTTPEnum::M_connect, url, std::string(), false, 0, 0);
675  while (run()) {
676  }
677  return is_connection_ready();
678 }
679 
680 /**
681  * Sends an OPTIONS message to the server, which should query the available
682  * options, possibly in relation to a specified URL.
683  */
684 INLINE bool HTTPChannel::
685 get_options(const DocumentSpec &url) {
686  begin_request(HTTPEnum::M_options, url, std::string(), false, 0, 0);
687  while (run()) {
688  }
689  return is_valid();
690 }
691 
692 /**
693  * Begins a non-blocking request to retrieve a given document. This method
694  * will return immediately, even before a connection to the server has
695  * necessarily been established; you must then call run() from time to time
696  * until the return value of run() is false. Then you may check is_valid()
697  * and get_status_code() to determine the status of your request.
698  *
699  * If a previous request had been pending, that request is discarded.
700  */
701 INLINE void HTTPChannel::
702 begin_get_document(const DocumentSpec &url) {
703  begin_request(HTTPEnum::M_get, url, std::string(), true, 0, 0);
704 }
705 
706 /**
707  * Begins a non-blocking request to retrieve only the specified byte range of
708  * the indicated document. If last_byte is 0, it stands for the last byte of
709  * the document. When a subdocument is requested, get_file_size() and
710  * get_bytes_downloaded() will report the number of bytes of the subdocument,
711  * not of the complete document.
712  */
713 INLINE void HTTPChannel::
714 begin_get_subdocument(const DocumentSpec &url, size_t first_byte,
715  size_t last_byte) {
716  begin_request(HTTPEnum::M_get, url, std::string(), true, first_byte, last_byte);
717 }
718 
719 /**
720  * Begins a non-blocking request to retrieve a given header. See
721  * begin_get_document() and get_header().
722  */
723 INLINE void HTTPChannel::
724 begin_get_header(const DocumentSpec &url) {
725  begin_request(HTTPEnum::M_head, url, std::string(), true, 0, 0);
726 }
727 
728 /**
729  * Posts form data to a particular URL and retrieves the response, all using
730  * non-blocking I/O. See begin_get_document() and post_form().
731  *
732  * It is important to note that you *must* call run() repeatedly after calling
733  * this method until run() returns false, and you may not call any other
734  * document posting or retrieving methods using the HTTPChannel object in the
735  * interim, or your form data may not get posted.
736  */
737 INLINE void HTTPChannel::
738 begin_post_form(const DocumentSpec &url, const std::string &body) {
739  begin_request(HTTPEnum::M_post, url, body, true, 0, 0);
740 }
741 
742 /**
743  * Begins a non-blocking request to establish a direct connection to the
744  * server and port indicated by the URL. No HTTP requests will be issued
745  * beyond what is necessary to establish the connection. When run() has
746  * finished, you may call is_connection_ready() to determine if the connection
747  * was successfully established.
748  *
749  * If successful, the connection may then be taken to use for whatever
750  * purposes you like by calling get_connection().
751  *
752  * This establishes a nonblocking I/O socket. Also see connect_to().
753  */
754 INLINE void HTTPChannel::
755 begin_connect_to(const DocumentSpec &url) {
756  begin_request(HTTPEnum::M_connect, url, std::string(), true, 0, 0);
757 }
758 
759 /**
760  * Returns the number of bytes downloaded during the last (or current)
761  * download_to_file() or download_to_ram operation(). This can be used in
762  * conjunction with get_file_size() to report the percent complete (but be
763  * careful, since get_file_size() may return 0 if the server has not told us
764  * the size of the file).
765  */
766 INLINE size_t HTTPChannel::
767 get_bytes_downloaded() const {
768  return _bytes_downloaded;
769 }
770 
771 /**
772  * When download throttling is in effect (set_download_throttle() has been set
773  * to true) and non-blocking I/O methods (like begin_get_document()) are used,
774  * this returns the number of bytes "requested" from the server so far: that
775  * is, the theoretical maximum value for get_bytes_downloaded(), if the server
776  * has been keeping up with our demand.
777  *
778  * If this number is less than get_bytes_downloaded(), then the server has not
779  * been supplying bytes fast enough to meet our own download throttle rate.
780  *
781  * When download throttling is not in effect, or when the blocking I/O methods
782  * (like get_document(), etc.) are used, this returns 0.
783  */
784 INLINE size_t HTTPChannel::
785 get_bytes_requested() const {
786  return _bytes_requested;
787 }
788 
789 /**
790  * Returns true when a download_to() or download_to_ram() has executed and the
791  * file has been fully downloaded. If this still returns false after
792  * processing has completed, there was an error in transmission.
793  *
794  * Note that simply testing is_download_complete() does not prove that the
795  * requested document was successfully retrieved--you might have just
796  * downloaded the "404 not found" stub (for instance) that a server would
797  * provide in response to some error condition. You should also check
798  * is_valid() to prove that the file you expected has been successfully
799  * retrieved.
800  */
801 INLINE bool HTTPChannel::
802 is_download_complete() const {
803  return (_download_dest != DD_none &&
804  (_state == S_read_body || _state == S_read_trailer));
805 }
806 
807 /**
808  *
809  */
810 INLINE HTTPChannel::StatusEntry::
811 StatusEntry() {
812  _status_code = SC_incomplete;
813 }
A container for a URL, e.g.
Definition: urlSpec.h:28
const std::string & get_url() const
Returns the complete URL specification.
Definition: urlSpec.I:184
A descriptor that refers to a particular version of a document.
Definition: documentSpec.h:30