Panda3D
Loading...
Searching...
No Matches
httpChannel.h
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.h
10 * @author drose
11 * @date 2002-09-24
12 */
13
14#ifndef HTTPCHANNEL_H
15#define HTTPCHANNEL_H
16
17#include "pandabase.h"
18
19// This module requires OpenSSL to compile, even if you do not intend to use
20// this to establish https connections; this is because it uses the OpenSSL
21// library to portably handle all of the socket communications.
22
23#ifdef HAVE_OPENSSL
24
25#include "httpClient.h"
26#include "httpEnum.h"
27#include "urlSpec.h"
28#include "documentSpec.h"
29#include "bioPtr.h"
30#include "bioStreamPtr.h"
31#include "pmap.h"
32#include "pvector.h"
33#include "pointerTo.h"
34#include "config_downloader.h"
35#include "filename.h"
36#include "typedReferenceCount.h"
37
38typedef struct bio_st BIO;
39
40class Ramfile;
41class HTTPClient;
42
43/**
44 * A single channel of communication from an HTTPClient. This is similar to
45 * the concept of a 'connection', except that HTTP is technically
46 * connectionless; in fact, a channel may represent one unbroken connection or
47 * it may transparently close and reopen a new connection with each request.
48 *
49 * A channel is conceptually a single thread of I/O. One document at a time
50 * may be requested using a channel; a new document may (in general) not be
51 * requested from the same HTTPChannel until the first document has been fully
52 * retrieved.
53 */
54class EXPCL_PANDA_DOWNLOADER HTTPChannel : public TypedReferenceCount {
55private:
56 HTTPChannel(HTTPClient *client);
57
58public:
59 virtual ~HTTPChannel();
60
61PUBLISHED:
62 // get_status_code() will either return an HTTP-style status code >= 100
63 // (e.g. 404), or one of the following values. In general, these are
64 // ordered from less-successful to more-successful.
65 enum StatusCode {
66 SC_incomplete = 0,
67 SC_internal_error,
68 SC_no_connection,
69 SC_timeout,
70 SC_lost_connection,
71 SC_non_http_response,
72 SC_invalid_http,
73 SC_socks_invalid_version,
74 SC_socks_no_acceptable_login_method,
75 SC_socks_refused,
76 SC_socks_no_connection,
77 SC_ssl_internal_failure,
78 SC_ssl_no_handshake,
79
80 // No one returns this code, but StatusCode values higher than this are
81 // deemed more successful than any generic HTTP response.
82 SC_http_error_watermark,
83
84 SC_ssl_invalid_server_certificate,
85 SC_ssl_self_signed_server_certificate,
86 SC_ssl_unexpected_server,
87
88 // These errors are only generated after a download_to_*() call been
89 // issued.
90 SC_download_open_error,
91 SC_download_write_error,
92 SC_download_invalid_range,
93 };
94
95 INLINE HTTPClient *get_client() const;
96
97 INLINE bool is_valid() const;
98 INLINE bool is_connection_ready() const;
99
100 INLINE const URLSpec &get_url() const;
101 INLINE const DocumentSpec &get_document_spec() const;
102 INLINE HTTPEnum::HTTPVersion get_http_version() const;
103 INLINE const std::string &get_http_version_string() const;
104 INLINE int get_status_code() const;
105 std::string get_status_string() const;
106 INLINE const std::string &get_www_realm() const;
107 INLINE const std::string &get_proxy_realm() const;
108 INLINE const URLSpec &get_redirect() const;
109 std::string get_header_value(const std::string &key) const;
110
111 INLINE int get_num_redirect_steps() const;
112 INLINE const URLSpec &get_redirect_step(int n) const;
113 MAKE_SEQ(get_redirect_steps, get_num_redirect_steps, get_redirect_step);
114
115 INLINE void set_persistent_connection(bool persistent_connection);
116 INLINE bool get_persistent_connection() const;
117 bool will_close_connection() const;
118
119 INLINE void set_allow_proxy(bool allow_proxy);
120 INLINE bool get_allow_proxy() const;
121 INLINE void set_proxy_tunnel(bool proxy_tunnel);
122 INLINE bool get_proxy_tunnel() const;
123
124 INLINE void set_connect_timeout(double timeout_seconds);
125 INLINE double get_connect_timeout() const;
126 INLINE void set_blocking_connect(bool blocking_connect);
127 INLINE bool get_blocking_connect() const;
128
129 INLINE void set_http_timeout(double timeout_seconds);
130 INLINE double get_http_timeout() const;
131
132 INLINE void set_skip_body_size(size_t skip_body_size);
133 INLINE size_t get_skip_body_size() const;
134 INLINE void set_idle_timeout(double idle_timeout);
135 INLINE double get_idle_timeout() const;
136
137 INLINE void set_download_throttle(bool download_throttle);
138 INLINE bool get_download_throttle() const;
139
140 INLINE void set_max_bytes_per_second(double max_bytes_per_second);
141 INLINE double get_max_bytes_per_second() const;
142
143 INLINE void set_max_updates_per_second(double max_updates_per_second);
144 INLINE double get_max_updates_per_second() const;
145
146 INLINE void set_content_type(std::string content_type);
147 INLINE std::string get_content_type() const;
148
149 INLINE void set_expected_file_size(size_t file_size);
150 std::streamsize get_file_size() const;
151 INLINE bool is_file_size_known() const;
152
153 INLINE size_t get_first_byte_requested() const;
154 INLINE size_t get_last_byte_requested() const;
155 INLINE size_t get_first_byte_delivered() const;
156 INLINE size_t get_last_byte_delivered() const;
157
158 void write_headers(std::ostream &out) const;
159
160 INLINE void reset();
161 INLINE void preserve_status();
162
163 INLINE void clear_extra_headers();
164 INLINE void send_extra_header(const std::string &key, const std::string &value);
165
166 BLOCKING INLINE bool get_document(const DocumentSpec &url);
167 BLOCKING INLINE bool get_subdocument(const DocumentSpec &url,
168 size_t first_byte, size_t last_byte);
169 BLOCKING INLINE bool get_header(const DocumentSpec &url);
170 BLOCKING INLINE bool post_form(const DocumentSpec &url, const std::string &body);
171 BLOCKING INLINE bool put_document(const DocumentSpec &url, const std::string &body);
172 BLOCKING INLINE bool delete_document(const DocumentSpec &url);
173 BLOCKING INLINE bool get_trace(const DocumentSpec &url);
174 BLOCKING INLINE bool connect_to(const DocumentSpec &url);
175 BLOCKING INLINE bool get_options(const DocumentSpec &url);
176
177 INLINE void begin_get_document(const DocumentSpec &url);
178 INLINE void begin_get_subdocument(const DocumentSpec &url,
179 size_t first_byte, size_t last_byte);
180 INLINE void begin_get_header(const DocumentSpec &url);
181 INLINE void begin_post_form(const DocumentSpec &url, const std::string &body);
182 bool run();
183 INLINE void begin_connect_to(const DocumentSpec &url);
184
185 ISocketStream *open_read_body();
186 void close_read_body(std::istream *stream) const;
187
188 BLOCKING bool download_to_file(const Filename &filename, bool subdocument_resumes = true);
189 BLOCKING bool download_to_ram(Ramfile *ramfile, bool subdocument_resumes = true);
190 BLOCKING bool download_to_stream(std::ostream *strm, bool subdocument_resumes = true);
191 SocketStream *get_connection();
192
193 INLINE size_t get_bytes_downloaded() const;
194 INLINE size_t get_bytes_requested() const;
195 INLINE bool is_download_complete() const;
196
197public:
198 static std::string downcase(const std::string &s);
199 void body_stream_destructs(ISocketStream *stream);
200
201private:
202 bool reached_done_state();
203 bool run_try_next_proxy();
204 bool run_connecting();
205 bool run_connecting_wait();
206 bool run_http_proxy_ready();
207 bool run_http_proxy_request_sent();
208 bool run_http_proxy_reading_header();
209 bool run_socks_proxy_greet();
210 bool run_socks_proxy_greet_reply();
211 bool run_socks_proxy_connect();
212 bool run_socks_proxy_connect_reply();
213 bool run_setup_ssl();
214 bool run_ssl_handshake();
215 bool run_ready();
216 bool run_request_sent();
217 bool run_reading_header();
218 bool run_start_direct_file_read();
219 bool run_read_header();
220 bool run_begin_body();
221 bool run_reading_body();
222 bool run_read_body();
223 bool run_read_trailer();
224
225 bool run_download_to_file();
226 bool run_download_to_ram();
227 bool run_download_to_stream();
228
229 void begin_request(HTTPEnum::Method method, const DocumentSpec &url,
230 const std::string &body, bool nonblocking,
231 size_t first_byte, size_t last_byte);
232 void reconsider_proxy();
233 void reset_for_new_request();
234
235 void finished_body(bool has_trailer);
236 bool open_download_file();
237
238 bool server_getline(std::string &str);
239 bool server_getline_failsafe(std::string &str);
240 bool server_get(std::string &str, size_t num_bytes);
241 bool server_get_failsafe(std::string &str, size_t num_bytes);
242 bool server_send(const std::string &str, bool secret);
243 bool parse_http_response(const std::string &line);
244 bool parse_http_header();
245 bool parse_content_range(const std::string &content_range);
246
247 void check_socket();
248
249 void check_preapproved_server_certificate(X509 *cert, bool &cert_preapproved,
250 bool &cert_name_preapproved) const;
251 bool validate_server_name(X509 *cert);
252 static bool match_cert_name(const std::string &cert_name, const std::string &hostname);
253 static std::string get_x509_name_component(X509_NAME *name, int nid);
254
255 void make_header();
256 void make_proxy_request_text();
257 void make_request_text();
258
259 void reset_url(const URLSpec &old_url, const URLSpec &new_url);
260 void store_header_field(const std::string &field_name, const std::string &field_value);
261
262#ifndef NDEBUG
263 static void show_send(const std::string &message);
264#endif
265
266 void reset_download_to();
267 void close_download_stream();
268 void reset_to_new();
269 void reset_body_stream();
270 void close_connection();
271
272 static bool more_useful_status_code(int a, int b);
273
274public:
275 // This is declared public solely so we can make an ostream operator for it.
276 enum State {
277 S_new,
278 S_try_next_proxy,
279 S_connecting,
280 S_connecting_wait,
281 S_http_proxy_ready,
282 S_http_proxy_request_sent,
283 S_http_proxy_reading_header,
284 S_socks_proxy_greet,
285 S_socks_proxy_greet_reply,
286 S_socks_proxy_connect,
287 S_socks_proxy_connect_reply,
288 S_setup_ssl,
289 S_ssl_handshake,
290 S_ready,
291 S_request_sent,
292 S_reading_header,
293 S_start_direct_file_read,
294 S_read_header,
295 S_begin_body,
296 S_reading_body,
297 S_read_body,
298 S_read_trailer,
299 S_failure
300 };
301
302private:
303 class StatusEntry {
304 public:
305 INLINE StatusEntry();
306 int _status_code;
307 std::string _status_string;
308 };
309 typedef pvector<URLSpec> Proxies;
310 typedef pvector<StatusEntry> StatusList;
311
312 HTTPClient *_client;
313 Proxies _proxies;
314 size_t _proxy_next_index;
315 StatusList _status_list;
316 URLSpec _proxy;
317 PT(BioPtr) _bio;
318 PT(BioStreamPtr) _source;
319 bool _persistent_connection;
320 bool _allow_proxy;
321 bool _proxy_tunnel;
322 double _connect_timeout;
323 double _http_timeout;
324 size_t _skip_body_size;
325 double _idle_timeout;
326 bool _blocking_connect;
327 bool _download_throttle;
328 double _max_bytes_per_second;
329 double _max_updates_per_second;
330 double _seconds_per_update;
331 int _bytes_per_update;
332 bool _nonblocking;
333 bool _wanted_nonblocking;
334 std::string _send_extra_headers;
335
336 DocumentSpec _document_spec;
337 DocumentSpec _request;
338 HTTPEnum::Method _method;
339 std::string request_path;
340 std::string _header;
341 std::string _body;
342 std::string _content_type;
343 bool _want_ssl;
344 bool _proxy_serves_document;
345 bool _proxy_tunnel_now;
346 bool _server_response_has_no_body;
347 size_t _first_byte_requested;
348 size_t _last_byte_requested;
349 size_t _first_byte_delivered;
350 size_t _last_byte_delivered;
351 int _connect_count;
352
353 enum DownloadDest {
354 DD_none,
355 DD_file,
356 DD_ram,
357 DD_stream,
358 };
359 DownloadDest _download_dest;
360 bool _subdocument_resumes;
361 Filename _download_to_filename;
362 Ramfile *_download_to_ramfile;
363 std::ostream *_download_to_stream;
364
365 int _read_index;
366
367 HTTPEnum::HTTPVersion _http_version;
368 std::string _http_version_string;
369 StatusEntry _status_entry;
370 URLSpec _redirect;
371
372 std::string _proxy_realm;
373 std::string _proxy_username;
374 PT(HTTPAuthorization) _proxy_auth;
375
376 std::string _www_realm;
377 std::string _www_username;
378 PT(HTTPAuthorization) _www_auth;
379
380 // What type of response do we get to our HTTP request?
381 enum ResponseType {
382 RT_none,
383 RT_hangup, // immediately lost connection
384 RT_non_http, // something that wasn't an expected HTTP response
385 RT_http_hangup, // the start of an HTTP response, then a lost connection
386 RT_http_complete // a valid HTTP response completed
387 };
388 ResponseType _response_type;
389
390 // Not a phash_map, to maintain sorted order.
391 typedef pmap<std::string, std::string> Headers;
392 Headers _headers;
393
394 size_t _expected_file_size;
395 size_t _file_size;
396 size_t _transfer_file_size;
397 size_t _bytes_downloaded;
398 size_t _bytes_requested;
399 bool _got_expected_file_size;
400 bool _got_file_size;
401 bool _got_transfer_file_size;
402
403 // These members are used to maintain the current state while communicating
404 // with the server. We need to store everything in the class object instead
405 // of using local variables because in the case of nonblocking IO we have to
406 // be able to return to the caller after any IO operation and resume later
407 // where we left off.
408 State _state;
409 State _done_state;
410 double _started_connecting_time;
411 double _sent_request_time;
412 bool _started_download;
413 std::string _proxy_header;
414 std::string _proxy_request_text;
415 std::string _request_text;
416 std::string _working_get;
417 size_t _sent_so_far;
418 std::string _current_field_name;
419 std::string _current_field_value;
420 ISocketStream *_body_stream;
421 bool _owns_body_stream;
422 BIO *_sbio;
423 std::string _cipher_list;
424 pvector<URLSpec> _redirect_trail;
425 int _last_status_code;
426 double _last_run_time;
427
428 // RAU we find that we may need a little more time for the ssl handshake
429 // when the phase files are downloading
430 double _extra_ssl_handshake_time;
431
432public:
433 virtual TypeHandle get_type() const {
434 return get_class_type();
435 }
436 virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
437 static TypeHandle get_class_type() {
438 return _type_handle;
439 }
440 static void init_type() {
441 TypedReferenceCount::init_type();
442 register_type(_type_handle, "HTTPChannel",
443 TypedReferenceCount::get_class_type());
444 }
445
446private:
447 static TypeHandle _type_handle;
448 friend class ChunkedStreamBuf;
449 friend class IdentityStreamBuf;
450 friend class HTTPClient;
451};
452
453std::ostream &operator << (std::ostream &out, HTTPChannel::State state);
454
455#include "httpChannel.I"
456
457#endif // HAVE_OPENSSL
458
459#endif
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A descriptor that refers to a particular version of a document.
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
An in-memory buffer specifically designed for downloading files to memory.
Definition ramfile.h:25
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
A container for a URL, e.g.
Definition urlSpec.h:28
This is our own Panda specialization on the default STL map.
Definition pmap.h:49
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.