2002-04-30 22:22:54 +00:00
|
|
|
// The contents of this file are subject to the Mozilla Public License
|
|
|
|
// Version 1.0 (the "License"); you may not use this file except in
|
|
|
|
// compliance with the License. You may obtain a copy of the License at
|
|
|
|
// http://www.mozilla.org/MPL/
|
|
|
|
//
|
|
|
|
// Software distributed under the License is distributed on an "AS IS"
|
|
|
|
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
|
|
// License for the specific language governing rights and limitations
|
|
|
|
// under the License.
|
|
|
|
//
|
|
|
|
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
|
|
|
|
//
|
|
|
|
// The Initial Developer of the Original Code is the SETI@home project.
|
|
|
|
// Portions created by the SETI@home project are Copyright (C) 2002
|
|
|
|
// University of California at Berkeley. All Rights Reserved.
|
|
|
|
//
|
|
|
|
// Contributor(s):
|
|
|
|
//
|
|
|
|
|
2002-06-06 18:42:01 +00:00
|
|
|
#include "windows_cpp.h"
|
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "util.h"
|
2002-07-05 05:33:40 +00:00
|
|
|
#include "file_names.h"
|
2002-08-12 21:54:19 +00:00
|
|
|
#include "filesys.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "log_flags.h"
|
|
|
|
#include "file_xfer.h"
|
2002-08-21 19:12:42 +00:00
|
|
|
#include "parse.h"
|
2002-07-11 01:09:53 +00:00
|
|
|
#include "error_numbers.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
|
|
|
|
FILE_XFER::FILE_XFER() {
|
|
|
|
file_xfer_done = false;
|
|
|
|
file_xfer_retval = 0;
|
2002-07-15 23:21:20 +00:00
|
|
|
start_time = 0;
|
|
|
|
end_time = 0;
|
|
|
|
fip = NULL;
|
|
|
|
strcpy(pathname,"");
|
|
|
|
strcpy(header,"");
|
2002-08-21 19:12:42 +00:00
|
|
|
file_size_query = false;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FILE_XFER::~FILE_XFER() {
|
|
|
|
}
|
|
|
|
|
2002-07-05 05:33:40 +00:00
|
|
|
int FILE_XFER::init_download(FILE_INFO& file_info) {
|
2002-12-06 07:33:45 +00:00
|
|
|
double f_size;
|
2002-08-12 21:54:19 +00:00
|
|
|
|
2002-07-05 05:33:40 +00:00
|
|
|
fip = &file_info;
|
|
|
|
get_pathname(fip, pathname);
|
2002-08-21 23:01:12 +00:00
|
|
|
// Check the current file size
|
2002-08-12 21:54:19 +00:00
|
|
|
if (file_size(pathname, f_size)) {
|
|
|
|
f_size = 0;
|
|
|
|
}
|
2002-12-06 07:33:45 +00:00
|
|
|
return HTTP_OP::init_get(fip->get_url(), pathname, false, (int)f_size);
|
2002-07-05 05:33:40 +00:00
|
|
|
}
|
|
|
|
|
2002-07-07 20:39:24 +00:00
|
|
|
// for uploads, we need to build a header with xml_signature etc.
|
2002-12-02 04:29:40 +00:00
|
|
|
// (see doc/upload.html)
|
2002-07-05 05:33:40 +00:00
|
|
|
// Do this in memory.
|
|
|
|
//
|
|
|
|
int FILE_XFER::init_upload(FILE_INFO& file_info) {
|
2002-08-12 21:54:19 +00:00
|
|
|
// If upload_offset < 0, we need to query the upload handler
|
|
|
|
// for the offset information
|
|
|
|
// TODO: give priority to URL of unfinished upload if there
|
|
|
|
// are multiple choices
|
|
|
|
//
|
2002-07-05 05:33:40 +00:00
|
|
|
fip = &file_info;
|
|
|
|
get_pathname(fip, pathname);
|
2002-08-12 21:54:19 +00:00
|
|
|
|
|
|
|
if (file_info.upload_offset < 0) {
|
|
|
|
sprintf(header,
|
2002-12-02 04:29:40 +00:00
|
|
|
"<data_server_request>\n"
|
|
|
|
" <core_client_major_version>%d</core_client_major_version>\n"
|
|
|
|
" <core_client_minor_version>%d</core_client_minor_version>\n"
|
|
|
|
" <get_file_size>%s</get_file_size>\n"
|
|
|
|
"</data_server_request>\n",
|
|
|
|
MAJOR_VERSION, MINOR_VERSION,
|
2002-08-12 21:54:19 +00:00
|
|
|
file_info.name
|
|
|
|
);
|
2002-08-21 19:12:42 +00:00
|
|
|
file_size_query = true;
|
2002-08-12 21:54:19 +00:00
|
|
|
return HTTP_OP::init_post2(fip->get_url(), header, NULL, 0);
|
|
|
|
} else {
|
|
|
|
sprintf(header,
|
2002-12-02 04:29:40 +00:00
|
|
|
"<data_server_request>\n"
|
|
|
|
" <core_client_major_version>%d</core_client_major_version>\n"
|
|
|
|
" <core_client_minor_version>%d</core_client_minor_version>\n"
|
|
|
|
"<file_upload>\n"
|
2002-08-12 21:54:19 +00:00
|
|
|
"<file_info>\n"
|
|
|
|
"%s"
|
|
|
|
"<xml_signature>\n"
|
|
|
|
"%s"
|
|
|
|
"</xml_signature>\n"
|
|
|
|
"</file_info>\n"
|
2002-12-02 04:29:40 +00:00
|
|
|
"<nbytes>%.0f</nbytes>\n"
|
2002-08-12 21:54:19 +00:00
|
|
|
"<offset>%.0f</offset>\n"
|
|
|
|
"<data>\n",
|
2002-12-02 04:29:40 +00:00
|
|
|
MAJOR_VERSION, MINOR_VERSION,
|
2002-08-12 21:54:19 +00:00
|
|
|
file_info.signed_xml,
|
|
|
|
file_info.xml_signature,
|
|
|
|
file_info.nbytes,
|
|
|
|
file_info.upload_offset
|
|
|
|
);
|
2002-08-21 19:12:42 +00:00
|
|
|
file_size_query = false;
|
2002-08-26 22:57:17 +00:00
|
|
|
return HTTP_OP::init_post2(
|
2002-12-02 04:29:40 +00:00
|
|
|
fip->get_url(), header, pathname, fip->upload_offset
|
|
|
|
);
|
2002-08-12 21:54:19 +00:00
|
|
|
}
|
2002-07-05 05:33:40 +00:00
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2002-08-21 19:12:42 +00:00
|
|
|
// Parse the server response in req1
|
|
|
|
//
|
2002-12-02 04:29:40 +00:00
|
|
|
int FILE_XFER::parse_server_response(double &nbytes) {
|
|
|
|
int status = 0;
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
parse_double(req1, "<file_size>", nbytes);
|
2002-08-21 19:12:42 +00:00
|
|
|
parse_int(req1, "<status>", status);
|
2002-12-02 04:29:40 +00:00
|
|
|
|
|
|
|
// TODO: show error message to user
|
|
|
|
//
|
|
|
|
if (parse_str(req1, "<message>", buf, sizeof(buf))) {
|
|
|
|
fprintf(stderr, "%s\n", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("status: %d nbytes: %f\n", status, nbytes);
|
2002-08-21 19:12:42 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2002-07-15 23:21:20 +00:00
|
|
|
// Returns the total time that the file xfer has taken
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
double FILE_XFER::elapsed_time() {
|
|
|
|
return end_time - start_time;
|
|
|
|
}
|
|
|
|
|
2002-07-15 23:21:20 +00:00
|
|
|
// Create a new empty FILE_XFER_SET
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
FILE_XFER_SET::FILE_XFER_SET(HTTP_OP_SET* p) {
|
|
|
|
http_ops = p;
|
|
|
|
}
|
|
|
|
|
2002-07-15 23:21:20 +00:00
|
|
|
// Insert a FILE_XFER object into the set
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
int FILE_XFER_SET::insert(FILE_XFER* fxp) {
|
|
|
|
int retval;
|
2002-08-15 22:03:41 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
// record start time.
|
|
|
|
// This could be made more accurate by omitting the connection
|
|
|
|
// setup and initial request times.
|
|
|
|
//
|
|
|
|
fxp->start_time = dtime();
|
|
|
|
retval = http_ops->insert(fxp);
|
|
|
|
if (retval) return retval;
|
|
|
|
file_xfers.push_back(fxp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-07-15 23:21:20 +00:00
|
|
|
// Remove a FILE_XFER object from the set
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
int FILE_XFER_SET::remove(FILE_XFER* fxp) {
|
|
|
|
vector<FILE_XFER*>::iterator iter;
|
2002-08-15 22:03:41 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
http_ops->remove(fxp);
|
|
|
|
|
|
|
|
iter = file_xfers.begin();
|
|
|
|
while (iter != file_xfers.end()) {
|
|
|
|
if (*iter == fxp) {
|
|
|
|
file_xfers.erase(iter);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
fprintf(stderr, "FILE_XFER_SET::remove(): not found\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-07-15 23:21:20 +00:00
|
|
|
// Run through the FILE_XFER_SET and determine if any of the file
|
|
|
|
// transfers are complete or had an error
|
|
|
|
//
|
2002-04-30 22:22:54 +00:00
|
|
|
bool FILE_XFER_SET::poll() {
|
|
|
|
unsigned int i;
|
|
|
|
FILE_XFER* fxp;
|
|
|
|
bool action = false;
|
2002-08-21 19:12:42 +00:00
|
|
|
int retval;
|
2002-04-30 22:22:54 +00:00
|
|
|
|
|
|
|
for (i=0; i<file_xfers.size(); i++) {
|
|
|
|
fxp = file_xfers[i];
|
|
|
|
if (fxp->http_op_done()) {
|
|
|
|
action = true;
|
|
|
|
fxp->end_time = dtime();
|
|
|
|
fxp->file_xfer_done = true;
|
|
|
|
if (log_flags.file_xfer_debug) {
|
2003-01-09 07:24:27 +00:00
|
|
|
printf("http op done; retval %d\n", fxp->http_op_retval);
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2002-08-21 23:01:12 +00:00
|
|
|
if (fxp->http_op_retval == 0) {
|
2002-08-21 19:12:42 +00:00
|
|
|
// If this was a file size query, restart the transfer
|
|
|
|
// using the remote file size information
|
|
|
|
if (fxp->file_size_query) {
|
|
|
|
// Parse the server's response.
|
|
|
|
retval = fxp->parse_server_response(fxp->fip->upload_offset);
|
|
|
|
|
|
|
|
if (retval) {
|
2002-12-02 04:29:40 +00:00
|
|
|
printf("ERROR: file upload returned %d\n", retval);
|
2002-08-21 19:12:42 +00:00
|
|
|
fxp->fip->upload_offset = -1;
|
|
|
|
fxp->file_xfer_retval = retval;
|
|
|
|
} else {
|
2002-10-15 18:09:16 +00:00
|
|
|
remove(fxp);
|
|
|
|
i--;
|
|
|
|
|
2002-08-21 19:12:42 +00:00
|
|
|
// Restart the upload, using the newly obtained upload_offset
|
|
|
|
retval = fxp->init_upload(*fxp->fip);
|
2002-08-21 23:01:12 +00:00
|
|
|
|
|
|
|
if (!retval) {
|
|
|
|
retval = insert(fxp);
|
|
|
|
if (!retval) {
|
|
|
|
fxp->file_xfer_done = false;
|
|
|
|
fxp->http_op_retval = 0;
|
|
|
|
}
|
|
|
|
}
|
2002-08-21 19:12:42 +00:00
|
|
|
}
|
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
} else {
|
|
|
|
fxp->file_xfer_retval = fxp->http_op_retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return action;
|
|
|
|
}
|