From dccf9a9aacd0072136ab9db1d62c7093f8aec01d Mon Sep 17 00:00:00 2001 From: Mike Goslin Date: Wed, 20 Dec 2000 01:02:03 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/downloader/downloader.cxx | 236 +++++++++++------- panda/src/downloader/downloader.h | 56 ++++- panda/src/downloadertools/test_downloader.cxx | 4 +- 3 files changed, 194 insertions(+), 102 deletions(-) diff --git a/panda/src/downloader/downloader.cxx b/panda/src/downloader/downloader.cxx index ac0d740671..afea67db90 100644 --- a/panda/src/downloader/downloader.cxx +++ b/panda/src/downloader/downloader.cxx @@ -67,16 +67,7 @@ Downloader(void) { _got_any_data = false; _initiated = false; _ever_initiated = false; - -#if defined(WIN32) - WSAData mydata; - int answer1 = WSAStartup(0x0101, &mydata); - if(answer1 != 0) { - downloader_cat.error() - << "Downloader::Downloader() - Error initializing TCP stack!" - << endl; - } -#endif + _TCP_stack_initialized = false; } //////////////////////////////////////////////////////////////////// @@ -98,8 +89,23 @@ Downloader:: // Access: Public // Description: //////////////////////////////////////////////////////////////////// -bool Downloader:: +int Downloader:: connect_to_server(const string &name, uint port) { + +#if defined(WIN32) + if (_TCP_stack_initialized == false) { + WSAData mydata; + int answer1 = WSAStartup(0x0101, &mydata); + if(answer1 != 0) { + downloader_cat.error() + << "Downloader::connect_to_server() - WSAStartup() - error: " + << handle_socket_error() << endl; + return DL_error_abort; + } + _TCP_stack_initialized = true; + } +#endif + if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader connecting to server: " << name << " on port: " @@ -120,7 +126,7 @@ connect_to_server(const string &name, uint port) { downloader_cat.error() << "Downloader::connect_to_server() - gethostbyname() failed: " << handle_socket_error() << endl; - return false; + return get_network_error(); } } else (void)memcpy(&_sin.sin_addr, &addr, sizeof(addr)); @@ -133,10 +139,10 @@ connect_to_server(const string &name, uint port) { // Access: Private // Description: //////////////////////////////////////////////////////////////////// -bool Downloader:: +int Downloader:: connect_to_server(void) { if (_connected == true) - return true; + return DL_success; _socket = 0xffffffff; _socket = socket(PF_INET, SOCK_STREAM, 0); @@ -144,20 +150,20 @@ connect_to_server(void) { downloader_cat.error() << "Downloader::connect_to_server() - socket failed: " << handle_socket_error() << endl; - return false; + return get_network_error(); } - _connected = true; - if (connect(_socket, (struct sockaddr *)&_sin, sizeof(_sin)) < 0) { downloader_cat.error() << "Downloader::connect_to_server() - connect() failed: " << handle_socket_error() << endl; disconnect_from_server(); _connected = false; + return get_network_error(); } - return _connected; + _connected = true; + return DL_success; } /////////////////////////////////////////////////////////////////// @@ -188,7 +194,7 @@ safe_send(int socket, const char *data, int length, long timeout) { if (length == 0) { downloader_cat.error() << "Downloader::safe_send() - requested 0 length send!" << endl; - return SS_error; + return DL_error_abort; } int bytes = 0; struct timeval tv; @@ -203,12 +209,12 @@ safe_send(int socket, const char *data, int length, long timeout) { downloader_cat.error() << "Downloader::safe_send() - select timed out after: " << timeout << " seconds" << endl; - return SS_timeout; + return DL_error_network_timeout; } else if (sret == -1) { downloader_cat.error() << "Downloader::safe_send() - error: " << handle_socket_error() << endl; - return SS_error; + return get_network_error(); } int ret = send(socket, data, length, 0); if (ret > 0) @@ -217,10 +223,10 @@ safe_send(int socket, const char *data, int length, long timeout) { downloader_cat.error() << "Downloader::safe_send() - error: " << handle_socket_error() << endl; - return SS_error; + return get_network_error(); } } - return SS_success; + return DL_success; } //////////////////////////////////////////////////////////////////// @@ -235,7 +241,7 @@ fast_receive(int socket, DownloadStatus *status, int rec_size) { downloader_cat.error() << "Downloader::fast_receive() - Invalid receive size: " << rec_size << endl; - return FR_error; + return DL_error_abort; } // Poll the socket with select() to see if there is any data @@ -247,21 +253,21 @@ fast_receive(int socket, DownloadStatus *status, int rec_size) { FD_SET(socket, &rset); int sret = select(socket, &rset, NULL, NULL, &tv); if (sret == 0) { - return FR_no_data; + return DL_network_no_data; } else if (sret == -1) { downloader_cat.error() << "Downloader::fast_receive() - select() error: " << handle_socket_error() << endl; - return FR_error; + return get_network_error(); } int ret = recv(socket, status->_next_in, rec_size, 0); if (ret == 0) { - return FR_eof; + return DL_eof; } else if (ret == -1) { downloader_cat.error() << "Downloader::fast_receive() - recv() error: " << handle_socket_error() << endl; - return FR_error; + return get_network_error(); } if (downloader_cat.is_debug()) downloader_cat.debug() @@ -270,7 +276,7 @@ fast_receive(int socket, DownloadStatus *status, int rec_size) { status->_next_in += ret; status->_bytes_in_buffer += ret; status->_total_bytes += ret; - return FR_success; + return DL_success; } //////////////////////////////////////////////////////////////////// @@ -297,12 +303,13 @@ initiate(const string &file_name, Filename file_dest, downloader_cat.error() << "Downloader::initiate() - Download has already been initiated" << endl; - return DS_error; + return DL_error_abort; } // Connect to the server - if (connect_to_server() == false) - return DS_error_connect; + int connect_ret = connect_to_server(); + if (connect_ret < 0) + return connect_ret; // Attempt to open the destination file file_dest.set_binary(); @@ -315,8 +322,8 @@ initiate(const string &file_name, Filename file_dest, if (result == false) { downloader_cat.error() << "Downloader::initiate() - Error opening file: " << file_dest - << " for writing" << endl; - return DS_error_write; + << " for writing: " << strerror(errno) << endl; + return DL_error_write; } // Send an HTTP request for the file to the server @@ -342,16 +349,8 @@ initiate(const string &file_name, Filename file_dest, << "Downloader::initiate() - Sending request:\n" << request << endl; int send_ret = safe_send(_socket, request.c_str(), outlen, (long)downloader_timeout); - - // Handle timeouts on the send - if (send_ret == SS_timeout) { - downloader_cat.error() - << "Downloader::initiate() - send timed out" << endl; - return DS_error_connect; - } - - if (send_ret == SS_error) - return DS_error_connect; + if (send_ret < 0) + return send_ret; // Create a download status to maintain download progress information _current_status = new DownloadStatus(_buffer->_buffer, @@ -363,7 +362,7 @@ initiate(const string &file_name, Filename file_dest, _got_any_data = false; _initiated = true; _ever_initiated = true; - return DS_success; + return DL_success; } //////////////////////////////////////////////////////////////////// @@ -399,21 +398,23 @@ run(void) { downloader_cat.error() << "Downloader::run() - Download has not been initiated" << endl; - return DS_error; + return DL_error_abort; } - nassertr(_current_status != NULL, DS_error); + nassertr(_current_status != NULL, DL_error_abort); - if (connect_to_server() == false) - return DS_error_connect; + int connect_ret = connect_to_server(); + if (connect_ret < 0) + return connect_ret; - int ret = DS_ok; + int ret = DL_ok; + int write_ret; double t0 = _clock.get_real_time(); if (_tfirst == 0.0) { _tfirst = t0; } if (t0 - _tlast < _frequency) - return DS_ok; + return DL_ok; // Recompute the buffer size if necessary if (_recompute_buffer == true) { @@ -423,10 +424,11 @@ run(void) { // Flush the current buffer if it holds any data if (_current_status->_bytes_in_buffer > 0) { - if (write_to_disk(_current_status) == false) { - return DS_error_write; - } - ret = DS_write; + write_ret = write_to_disk(_current_status); + if (write_ret < 0) + return write_ret; + + ret = DL_write; } // Allocate a new buffer @@ -449,9 +451,10 @@ run(void) { if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::run() - Flushing buffer" << endl; - if (write_to_disk(_current_status) == false) - return DS_error_write; - ret = DS_write; + write_ret = write_to_disk(_current_status); + if (write_ret < 0) + return write_ret; + ret = DL_write; } // Attempt to receive the bytes from the socket @@ -471,9 +474,9 @@ run(void) { fret = fast_receive(_socket, _current_status, MAX_RECEIVE_BYTES); else if (remain > 0) fret = fast_receive(_socket, _current_status, remain); - if (fret == FR_eof || fret < 0) { + if (fret == DL_eof || fret < 0) { break; - } else if (fret == FR_success) { + } else if (fret == DL_success) { _got_any_data = true; } } @@ -486,30 +489,31 @@ run(void) { _tlast = _clock.get_real_time(); // Check for end of file - if (fret == FR_eof) { + if (fret == DL_eof) { if (_got_any_data == true) { if (_current_status->_bytes_in_buffer > 0) { - if (write_to_disk(_current_status) == false) - return DS_error_write; + write_ret = write_to_disk(_current_status); + if (write_ret < 0) + return write_ret; } if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::run() - Got eof" << endl; cleanup(); - return DS_success; + return DL_success; } else { if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::run() - Got 0 bytes" << endl; return ret; } - } else if (fret == FR_no_data) { + } else if (fret == DL_network_no_data) { if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::run() - No data" << endl; return ret; } else if (fret < 0) { - return DS_error; + return fret; } _got_any_data = true; @@ -521,7 +525,7 @@ run(void) { // Access: Private // Description: Check the HTTP response from the server //////////////////////////////////////////////////////////////////// -bool Downloader:: +int Downloader:: parse_http_response(const string &resp) { size_t ws = resp.find(" ", 0); string httpstr = resp.substr(0, ws); @@ -529,7 +533,7 @@ parse_http_response(const string &resp) { downloader_cat.error() << "Downloader::parse_http_response() - not HTTP/1.1 - got: " << httpstr << endl; - return false; + return DL_error_abort; } size_t ws2 = resp.find(" ", ws); string numstr = resp.substr(ws, ws2); @@ -538,18 +542,25 @@ parse_http_response(const string &resp) { switch (num) { case 200: case 206: - return true; + return DL_success; case 202: // Accepted - server may not honor request, though if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::parse_http_response() - got a 202 Accepted - " << "server does not guarantee to honor this request" << endl; - return true; + return DL_success; case 201: case 203: case 204: case 205: + break; + case 408: + return DL_error_http_server_timeout; + case 503: + return DL_error_http_service_unavailable; + case 504: + return DL_error_http_gateway_timeout; default: break; } @@ -557,7 +568,7 @@ parse_http_response(const string &resp) { downloader_cat.error() << "Downloader::parse_http_response() - Invalid response: " << resp << endl; - return false; + return DL_error_abort; } //////////////////////////////////////////////////////////////////// @@ -568,17 +579,17 @@ parse_http_response(const string &resp) { // the download status structure. Function returns false // on an error condition, otherwise true. //////////////////////////////////////////////////////////////////// -bool Downloader:: +int Downloader:: parse_header(DownloadStatus *status) { - nassertr(status != NULL, false); + nassertr(status != NULL, DL_error_abort); if (status->_header_is_complete == true) - return true; + return DL_success; if (status->_bytes_in_buffer == 0) { downloader_cat.error() << "Downloader::parse_header() - Empty buffer!" << endl; - return false; + return DL_error_abort; } string bufstr((char *)status->_start, status->_bytes_in_buffer); @@ -590,12 +601,12 @@ parse_header(DownloadStatus *status) { downloader_cat.error() << "Downloader::parse_header() - No newlines in buffer of " << "length: " << status->_bytes_in_buffer << endl; - return false; + return DL_error_abort; } else if (p == 0 && nl == p) { downloader_cat.error() << "Downloader::parse_header() - Buffer begins with newline!" << endl; - return false; + return DL_error_abort; } string component = bufstr.substr(p, nl - p); @@ -604,14 +615,15 @@ parse_header(DownloadStatus *status) { // got an error or not if (status->_first_line_complete == false) { status->_first_line_complete = true; - if (parse_http_response(component) == true) { + int parse_ret = parse_http_response(component); + if (parse_ret == DL_success) { if (downloader_cat.is_debug()) downloader_cat.debug() << "Downloader::parse_header() - Header is valid: " << component << endl; status->_header_is_valid = true; } else { - return false; + return parse_ret; } } @@ -630,7 +642,7 @@ parse_header(DownloadStatus *status) { << server_download_bytes << ", client size = " << client_download_bytes << " (" << status->_last_byte << "-" << status->_first_byte << ")" << endl; - return false; + return DL_error_abort; } } @@ -651,7 +663,7 @@ parse_header(DownloadStatus *status) { << "Downloader::parse_header() - Stripping out header of size: " << header_length << endl; - return true; + return DL_success; } p = nl + 2; @@ -663,9 +675,10 @@ parse_header(DownloadStatus *status) { << "Downloader::parse_header() - Reached end of buffer without " << "successfully parsing the header - buffer size: " << status->_bytes_in_buffer << endl; + return DL_error_abort; } - return true; + return DL_success; } //////////////////////////////////////////////////////////////////// @@ -676,20 +689,21 @@ parse_header(DownloadStatus *status) { // is excluded. Function returns false on error // condition. //////////////////////////////////////////////////////////////////// -bool Downloader:: +int Downloader:: write_to_disk(DownloadStatus *status) { - nassertr(status != NULL, false); + nassertr(status != NULL, DL_error_abort); // Ensure the header has been parsed successfully first - if (parse_header(status) == false) - return false; + int parse_ret = parse_header(status); + if (parse_ret < 0) + return parse_ret; if (status->_header_is_complete == false) { downloader_cat.error() << "Downloader::write_to_disk() - Incomplete HTTP header - " << "(or header was larger than download buffer) - " << "try increasing download-buffer-size" << endl; - return false; + return DL_error_abort; } // Write what we have so far to disk @@ -705,7 +719,7 @@ write_to_disk(DownloadStatus *status) { status->reset(); - return true; + return DL_success; } //////////////////////////////////////////////////////////////////// @@ -748,7 +762,7 @@ reset(void) { //////////////////////////////////////////////////////////////////// char *Downloader:: handle_socket_error(void) const { -#ifndef WIN32_VC +#ifndef WIN32 return strerror(errno); #else switch (WSAGetLastError()) { @@ -789,3 +803,47 @@ handle_socket_error(void) const { } #endif } + +//////////////////////////////////////////////////////////////////// +// Function: Downloader::error_gethostbyname +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +int Downloader:: +get_network_error(void) const { +#ifndef WIN32 + return DL_error; +#else + switch (WSAGetLastError()) { + case 10050: + return DL_error_network_dead; + case 10051: + return DL_error_network_unreachable; + case 10052: + case 10057: + case 10058: + return DL_error_network_disconnected; + case 10053: + return DL_error_network_disconnected_locally; + case 10054: + case 10061: + return DL_error_network_remote_host_disconnected; + case 10055: + return DL_error_network_buffer_overflow; + case 10060: + return DL_error_network_timeout; + case 10064: + return DL_error_network_remote_host_down; + case 10065: + return DL_error_network_remote_host_unreachable; + case 10069: + return DL_error_network_disk_quota_exceeded; + case 11001: + return DL_error_network_remote_host_not_found; + case 11002: + return DL_error_network_remote_host_no_response; + default: + return DL_error_abort; + } +#endif +} diff --git a/panda/src/downloader/downloader.h b/panda/src/downloader/downloader.h index 50cdbddb6c..4592be3b70 100644 --- a/panda/src/downloader/downloader.h +++ b/panda/src/downloader/downloader.h @@ -32,18 +32,49 @@ class EXPCL_PANDAEXPRESS Downloader { PUBLISHED: enum DownloadCode { - DS_ok = 3, - DS_write = 2, - DS_success = 1, - DS_error = -1, - DS_error_write = -2, - DS_error_connect = -3, + DL_eof = 5, + DL_network_no_data = 4, + + DL_ok = 3, + DL_write = 2, + DL_success = 1, + + // General download errors + DL_error = -1, + DL_error_abort = -2, + + // General network errors + DL_error_network_dead = -30, + DL_error_network_unreachable = -31, + DL_error_network_disconnected = -32, + DL_error_network_timeout = -33, + DL_error_network_no_data = -34, + + // Local network errors + DL_error_network_disconnected_locally = -40, + DL_error_network_buffer_overflow = -41, + DL_error_network_disk_quota_exceeded = -42, + + // Remote host network errors + DL_error_network_remote_host_disconnected = -50, + DL_error_network_remote_host_down = -51, + DL_error_network_remote_host_unreachable = -52, + DL_error_network_remote_host_not_found = -53, + DL_error_network_remote_host_no_response = -54, + + // General local errors + DL_error_write = -60, + + // HTTP errors + DL_error_http_server_timeout = -70, + DL_error_http_gateway_timeout = -71, + DL_error_http_service_unavailable = -72, }; Downloader(void); virtual ~Downloader(void); - bool connect_to_server(const string &name, uint port=80); + int connect_to_server(const string &name, uint port=80); void disconnect_from_server(void); int initiate(const string &file_name, Filename file_dest); @@ -85,21 +116,24 @@ private: INLINE void recompute_buffer(void); - bool connect_to_server(void); + int connect_to_server(void); int safe_send(int socket, const char *data, int length, long timeout); int fast_receive(int socket, DownloadStatus *status, int rec_size); - bool parse_http_response(const string &resp); - bool parse_header(DownloadStatus *status); - bool write_to_disk(DownloadStatus *status); + int parse_http_response(const string &resp); + int parse_header(DownloadStatus *status); + int write_to_disk(DownloadStatus *status); void cleanup(void); char *handle_socket_error(void) const; + int get_network_error(void) const; + private: bool _connected; int _socket; string _server_name; struct sockaddr_in _sin; + bool _TCP_stack_initialized; bool _initiated; bool _ever_initiated; diff --git a/panda/src/downloadertools/test_downloader.cxx b/panda/src/downloadertools/test_downloader.cxx index 265ef6b4e3..a49c1da68a 100644 --- a/panda/src/downloadertools/test_downloader.cxx +++ b/panda/src/downloadertools/test_downloader.cxx @@ -24,10 +24,10 @@ main(int argc, char *argv[]) { for (;;) { ret = dl.run(); - if (ret == Downloader::DS_success) { + if (ret == Downloader::DL_success) { cerr << "bytes per second: " << dl.get_bytes_per_second() << endl; return 1; - } else if (ret == Downloader::DS_write) { + } else if (ret == Downloader::DL_write) { cerr << "bytes per second: " << dl.get_bytes_per_second() << endl; } else if (ret < 0) { cerr << "error!" << endl;