Selaa lähdekoodia

*** empty log message ***

Mike Goslin 25 vuotta sitten
vanhempi
sitoutus
b7017f9e4b

+ 3 - 0
panda/src/downloader/config_downloader.cxx

@@ -26,6 +26,9 @@ const float downloader_frequency =
 const float downloader_bandwidth =
 	config_downloader.GetFloat("downloader-bandwidth", 3600.0);
 
+const int downloader_timeout =
+	config_downloader.GetInt("downloader-timeout", 2);
+
 const int decompressor_buffer_size =
 	config_downloader.GetInt("decompressor-buffer-size", 4096);
 

+ 1 - 0
panda/src/downloader/config_downloader.h

@@ -14,6 +14,7 @@ NotifyCategoryDecl(downloader, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
 extern const int downloader_buffer_size;
 extern const float downloader_frequency;
 extern const float downloader_bandwidth;
+extern const int downloader_timeout;
 
 extern const int decompressor_buffer_size;
 extern const float decompressor_frequency;

+ 100 - 18
panda/src/downloader/downloader.cxx

@@ -178,9 +178,6 @@ connect_to_server(void) {
     _connected = false;
   }
 
-  // Make socket non blocking
-  //if (setsockopt(_socket, SOL_SOCKET, 
-
   return _connected;
 }
 
@@ -336,6 +333,94 @@ process_request() {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Downloader::safe_send
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool Downloader::
+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 false;
+  }
+  int bytes = 0;
+  struct timeval tv;
+  tv.tv_sec = timeout;
+  tv.tv_usec = 0;
+  fd_set wset;
+  FD_ZERO(&wset);
+  while (bytes < length) {
+    FD_SET(socket, &wset);
+    int sret = select(socket + 1, NULL, &wset, NULL, &tv);
+    if (sret == 0) {
+      downloader_cat.error()
+	<< "Downloader::safe_send() - select timed out after: "
+	<< timeout << " seconds" << endl;
+      return false;
+    } else if (sret == -1) {
+      downloader_cat.error()
+	<< "Downloader::safe_send() - error: " << strerror(errno) << endl;
+      return false;
+    }
+    int ret = send(socket, data, length, 0);
+    if (ret > 0)
+      bytes += ret;
+    else {
+      downloader_cat.error()
+	<< "Downloader::safe_send() - error: " << strerror(errno) << endl;
+      return false;
+    }
+  }
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Downloader::safe_receive
+//       Access: Private
+//  Description:
+////////////////////////////////////////////////////////////////////
+int Downloader::
+safe_receive(int socket, char *data, int length, long timeout) {
+  if (length == 0) {
+    downloader_cat.error()
+      << "Downloader::safe_receive() - requested 0 length receive!" << endl;
+    return 0;
+  }
+  int bytes = 0;
+  struct timeval tv;
+  tv.tv_sec = timeout;
+  tv.tv_usec = 0;
+  fd_set rset;
+  FD_ZERO(&rset);
+  while (bytes < length) {
+    FD_SET(socket, &rset);
+    int sret = select(socket + 1, &rset, NULL, NULL, &tv);
+    if (sret == 0) {
+      downloader_cat.error()
+	<< "Downloader::safe_receive() - select timed out after: "
+	<< timeout << " seconds" << endl;
+      return bytes;
+    } else if (sret == -1) {
+      downloader_cat.error()
+	<< "Downloader::safe_receive() - error: " << strerror(errno) << endl;
+      return bytes;
+    }
+    int ret = recv(socket, data, length, 0);
+    if (ret > 0)
+      bytes += ret;
+    else if (ret == 0)
+      return 0;
+    else {
+      downloader_cat.error()
+	<< "Downloader::safe_receive() - error: " << strerror(errno) << endl;
+      return bytes;
+    }
+  }
+  return bytes;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Downloader::download
 //       Access: Private
@@ -383,27 +468,17 @@ download(const string &file_name, Filename file_dest,
   int outlen = request.size();
   downloader_cat.debug()
     << "Downloader::download() - Sending request:\n" << request << endl;
-  if (send(_socket, request.c_str(), outlen, 0) != outlen) {
-    downloader_cat.error()
-      << "Downloader::download() - Error sending HTTP request: "
-      << request << "\n" << "error: " << strerror(errno) << endl;
+  if (safe_send(_socket, request.c_str(), outlen, 
+			(long)downloader_timeout) == false)
     return false;
-  }
 
   // Loop at the requested frequency until the download completes
   DownloadStatus status(_buffer->_buffer, event_name, first_byte, last_byte,
 			total_bytes, partial_content, id);
   bool got_any_data = false;
   
-  // MPG - Get *safe* socket read code from Roger 
-  // send() can write fewer than the requested # of bytes, so we need to
-  // loop on send.
-  // recv() can block forever, so we probably want to use a non-blocking
-  // socket and then check for EWOULDBLOCK error (which wouldn't be an
-  // error for us in this case - we should just go back to sleep for
-  // a while).
   for (;;) {
-    if (_download_enabled) {
+    if (_download_enabled) { 
       // Ensure that these don't change while we're computing read_size
       _bandwidth_frequency_lock.lock();
  	int read_size = (int)(_bandwidth * _frequency);	
@@ -420,7 +495,8 @@ download(const string &file_name, Filename file_dest,
       }
 
       // Grab the next chunk
-      int ans = recv(_socket, status._next_in, read_size, 0); 
+      int ans = safe_receive(_socket, status._next_in, read_size,
+					(long)downloader_timeout); 
 
       if (ans < 0) {
         downloader_cat.error()
@@ -514,7 +590,7 @@ parse_header(DownloadStatus &status) {
       if (status._first_byte == 0)
 	client_download_bytes += 1;
       if (client_download_bytes != server_download_bytes) {
-	downloader_cat.error()
+  	downloader_cat.error()
 	  << "Downloader::parse_header() - server size = " 
 	  << server_download_bytes << ", client size = " 
 	  << client_download_bytes << " ("
@@ -544,6 +620,12 @@ parse_header(DownloadStatus &status) {
     p = nl + 2;
   }
 
+  if (status._total_bytes == 0) {
+    downloader_cat.error()
+      << "Downloader::parse_header() - Total bytes == 0!" << endl;
+    return false;
+  }
+
   return true;
 }
 

+ 2 - 0
panda/src/downloader/downloader.h

@@ -83,6 +83,8 @@ private:
   bool parse_header(DownloadStatus &status);
   bool write_to_disk(DownloadStatus &status);
   bool connect_to_server(void);
+  bool safe_send(int socket, const char *data, int length, long timeout);
+  int safe_receive(int socket, char *data, int length, long timeout);
 
   typedef TokenBoard<DownloaderToken> DownloaderTokenBoard;
   DownloaderTokenBoard *_token_board;

+ 3 - 0
panda/src/testbed/Sources.pp

@@ -29,6 +29,9 @@
   #define SOURCES \
     downloader_test.cxx
 
+  #define USE_ZLIB yes
+  #define TARGET_IF_ZLIB yes
+
 #end test_bin_target
 
 #begin test_bin_target