mirror of https://github.com/BOINC/boinc.git
fix partial-transfer problem
svn path=/trunk/boinc/; revision=9491
This commit is contained in:
parent
8e0d3dde71
commit
0cbe340ed8
|
@ -1955,3 +1955,17 @@ Rom 16 Feb 2006
|
|||
clientlib/win/
|
||||
BOINCSENSSink.cpp
|
||||
NetworkTracker.cpp
|
||||
|
||||
David 16 Feb 2006
|
||||
- core client: bug fix (hopefully) for situation where
|
||||
a server or proxy doesn't understand Range: in HTTP header,
|
||||
and sends us the entire file when we just want the tail.
|
||||
Solution: if we asked for a partial transfer,
|
||||
and we got a 200 HTTP return,
|
||||
and the file is bigger than it's supposed to be,
|
||||
trim off the part that was there initially.
|
||||
- remove NET_XFER::strCurlResult, file_read_buf* fields
|
||||
|
||||
client/
|
||||
file_xfer.C,h
|
||||
net_xfer_curl.C,h
|
||||
|
|
|
@ -197,6 +197,8 @@ bool FILE_XFER_SET::poll() {
|
|||
FILE_XFER* fxp;
|
||||
bool action = false;
|
||||
static double last_time=0;
|
||||
char pathname[256];
|
||||
double size;
|
||||
|
||||
if (gstate.now - last_time < 1.0) return false;
|
||||
last_time = gstate.now;
|
||||
|
@ -266,9 +268,6 @@ bool FILE_XFER_SET::poll() {
|
|||
// since it may be a proxy error message
|
||||
//
|
||||
if (!fxp->is_upload && fxp->fip->nbytes) {
|
||||
char pathname[256];
|
||||
double size;
|
||||
|
||||
get_pathname(fxp->fip, pathname);
|
||||
if (file_size(pathname, size)) continue;
|
||||
if (size == fxp->fip->nbytes) continue;
|
||||
|
@ -281,6 +280,35 @@ bool FILE_XFER_SET::poll() {
|
|||
boinc_truncate(pathname, fxp->starting_size);
|
||||
}
|
||||
}
|
||||
|
||||
// for downloads: if we requested a partial transfer,
|
||||
// and the HTTP response is 200,
|
||||
// and the file is larger than it should be,
|
||||
// the server or proxy must have sent us the entire file
|
||||
// (i.e. it doesn't understand Range: requests).
|
||||
// In this case, trim off the initial part of the file
|
||||
//
|
||||
if (!fxp->is_upload && fxp->starting_size
|
||||
&& fxp->response==HTTP_STATUS_OK
|
||||
) {
|
||||
get_pathname(fxp->fip, pathname);
|
||||
if (file_size(pathname, size)) continue;
|
||||
if (size > fxp->fip->nbytes) {
|
||||
FILE* f1 = boinc_fopen(pathname, "rb");
|
||||
FILE* f2 = boinc_fopen(TEMP_FILE_NAME, "wb");
|
||||
if (f1 && f2) {
|
||||
fseek(f1, (long)fxp->starting_size, SEEK_SET);
|
||||
copy_stream(f1, f2);
|
||||
fclose(f1);
|
||||
fclose(f2);
|
||||
f1 = boinc_fopen(TEMP_FILE_NAME, "rb");
|
||||
f2 = boinc_fopen(pathname, "wb");
|
||||
copy_stream(f1, f2);
|
||||
fclose(f1);
|
||||
fclose(f2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
|
|
@ -38,10 +38,12 @@ public:
|
|||
bool file_size_query;
|
||||
bool is_upload;
|
||||
double starting_size;
|
||||
// File size at start of transfer.
|
||||
// This is used to to implement a "minimum download increment"
|
||||
// File size at start of transfer, used for:
|
||||
// 1) a "minimum download increment"
|
||||
// that rejects partial downloads of less than 5K,
|
||||
// since these may be error messages from proxies.
|
||||
// 2) lets us recover when server ignored Range request
|
||||
// and sent us whole file
|
||||
|
||||
FILE_XFER();
|
||||
~FILE_XFER();
|
||||
|
|
|
@ -92,7 +92,6 @@ void NET_XFER::reset() {
|
|||
strcpy(infile, "");
|
||||
strcpy(outfile, "");
|
||||
CurlResult = CURLE_OK;
|
||||
strcpy(strCurlResult, "");
|
||||
bTempOutfile = true;
|
||||
is_connected = false;
|
||||
want_download = false;
|
||||
|
@ -103,8 +102,6 @@ void NET_XFER::reset() {
|
|||
fileOut = NULL;
|
||||
io_ready = true;
|
||||
error = 0;
|
||||
file_read_buf_offset = 0;
|
||||
file_read_buf_len = 0;
|
||||
bytes_xferred = 0;
|
||||
xfer_speed = 0;
|
||||
bSentHeader = false;
|
||||
|
@ -285,7 +282,8 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
// included with Mac OS X 10.3.9
|
||||
//
|
||||
curlErr = curl_easy_getinfo(nxf->curlEasy,
|
||||
(CURLINFO)(CURLINFO_LONG+25) /*CURLINFO_OS_ERRNO*/, &nxf->error);
|
||||
(CURLINFO)(CURLINFO_LONG+25) /*CURLINFO_OS_ERRNO*/, &nxf->error
|
||||
);
|
||||
|
||||
nxf->io_done = true;
|
||||
nxf->io_ready = false;
|
||||
|
@ -309,27 +307,8 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
//
|
||||
nxf->http_op_state = HTTP_STATE_DONE;
|
||||
|
||||
// added a more useful error string
|
||||
// (just pass the curl string up for now)
|
||||
//
|
||||
nxf->CurlResult = pcurlMsg->data.result;
|
||||
safe_strcpy(nxf->strCurlResult, curl_easy_strerror(nxf->CurlResult));
|
||||
|
||||
// optional, example use, non-zero CurlResult has a useful error string:
|
||||
//if (nxf->CurlResult) fprintf(stdout, "Error: %s\n", nxf->strCurlResult);
|
||||
|
||||
// 200 is a good HTTP response code
|
||||
// It may not mean the data received is "good"
|
||||
// (the calling program will have to check/parse that)
|
||||
// but it at least means that the server operation
|
||||
// went through fine
|
||||
//
|
||||
// NOTE: http_op_retval is multipurposed,
|
||||
// it can also contain any error code that BOINC would return
|
||||
// for IO errors and DNS errors.
|
||||
// We need to translate between the curl error codes and the equiv.
|
||||
// BOINC error codes here.
|
||||
//
|
||||
if (nxf->CurlResult == CURLE_OK) {
|
||||
if ((nxf->response/100)*100 == HTTP_STATUS_OK) {
|
||||
nxf->http_op_retval = 0;
|
||||
|
@ -349,7 +328,9 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
std::string url = "http://www.google.com";
|
||||
gstate.lookup_website_op.do_rpc(url);
|
||||
}
|
||||
msg_printf(0, MSG_ERROR, "HTTP error: %s", nxf->strCurlResult);
|
||||
msg_printf(0, MSG_ERROR,
|
||||
"HTTP error: %s", curl_easy_strerror(nxf->CurlResult)
|
||||
);
|
||||
nxf->http_op_retval = ERR_HTTP_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ net_xfer object status codes (using libcurl):
|
|||
nxf->response maps to HTTP_STATUS_* (from http_curl.h)
|
||||
nxf->http_op_state maps to HTTP_STATE_* (from http_curl.h)
|
||||
nxf->CurlError is a curl specific code (maps to the CURLE_* enums in curl/curl.h)
|
||||
nxf->strCurlError is a human-readable msg (i.e. "couldn't connect to server")
|
||||
*/
|
||||
|
||||
class NET_XFER {
|
||||
|
@ -74,7 +73,6 @@ public:
|
|||
char* req1;
|
||||
bool bSentHeader; // CMC -- a flag that I already sent the header
|
||||
CURLcode CurlResult; // CMC -- send up curl result code
|
||||
char strCurlResult[_MAX_PATH]; // CMC -- 'human-readable' string with result info
|
||||
|
||||
// int socket; // CMC -- deprecated, net_xfer's via curlEasy handle above
|
||||
char hostname[256]; // The host we're connecting to (possibly a proxy)
|
||||
|
@ -105,8 +103,6 @@ public:
|
|||
double xfer_speed;
|
||||
double bytes_xferred; // bytes transferred in this session
|
||||
double content_length;
|
||||
char file_read_buf[MAX_BLOCKSIZE];
|
||||
int file_read_buf_offset, file_read_buf_len;
|
||||
int seconds_until_timeout;
|
||||
|
||||
// CMC - moved from http_op
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
$light_blue="#d8e8ff";
|
||||
$med_blue="#c0d0f0";
|
||||
|
||||
function last_mod() {
|
||||
return gmdate("g:i A \U\T\C, F d Y", filemtime($_SERVER["SCRIPT_FILENAME"]));
|
||||
function last_mod($datefile) {
|
||||
return gmdate("g:i A \U\T\C, F d Y", filemtime($datefile));
|
||||
}
|
||||
|
||||
function page_head($title) {
|
||||
$d = last_mod();
|
||||
function page_head($title, $datefile=null) {
|
||||
if (!$datefile) {
|
||||
$datefile = $_SERVER["SCRIPT_FILENAME"];
|
||||
}
|
||||
$d = last_mod($datefile);
|
||||
echo "<html>
|
||||
<head>
|
||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"white.css\"/>
|
||||
|
|
Loading…
Reference in New Issue