mirror of https://github.com/BOINC/boinc.git
detect lack of physical network connection
svn path=/trunk/boinc/; revision=9404
This commit is contained in:
parent
c6a2d33145
commit
ab8ff092db
|
@ -1487,3 +1487,20 @@ Rom 6 Feb 2006
|
|||
client/
|
||||
client_state.h
|
||||
main.C
|
||||
|
||||
David 6 Feb 2005
|
||||
- Core client: when we switched to Curl, we lost the code
|
||||
that sets gstate.want_network_flag when name resolution fails.
|
||||
I restored this to the Curl code.
|
||||
|
||||
- The above is a kludge for detecting lack of physical connection.
|
||||
But name resolution can fail for reasons other than lack of
|
||||
physical connection; e.g. hostname might be bad.
|
||||
So if get name resolution failure,
|
||||
try to contact a reference web site,
|
||||
and only if that also fails set want_network_flag.
|
||||
|
||||
client/
|
||||
acct_setup.C
|
||||
client_state.C,h
|
||||
net_xfer_curl.C
|
||||
|
|
|
@ -188,6 +188,15 @@ int LOOKUP_WEBSITE_OP::do_rpc(string& url) {
|
|||
|
||||
void LOOKUP_WEBSITE_OP::handle_reply(int http_op_retval) {
|
||||
error_num = http_op_retval;
|
||||
|
||||
// if we couldn't contact a reference web site,
|
||||
// we can assume there's a problem that requires user attention
|
||||
// (usually no physical network connection).
|
||||
// Set a flag that will signal the Manager to that effect
|
||||
//
|
||||
if (error_num) {
|
||||
gstate.want_network_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
int GET_CURRENT_VERSION_OP::do_rpc() {
|
||||
|
|
|
@ -1393,15 +1393,15 @@ int CLIENT_STATE::detach_project(PROJECT* project) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Return true if the core client wants a network connection.
|
||||
// Don't return false if we've actually been using the network
|
||||
// in the last 10 seconds (so that polling mechanisms
|
||||
// have a change to trigger)
|
||||
// Return true if the core client wants a network connection,
|
||||
// or if we've been using the network in the last 10 seconds
|
||||
// (so that polling mechanisms have a change to trigger)
|
||||
//
|
||||
bool CLIENT_STATE::want_network() {
|
||||
static double last_true_return=0;
|
||||
|
||||
if (http_ops->nops()) goto return_true;
|
||||
// if we're using network, return true
|
||||
if (network_suspended) goto return_false;
|
||||
if (want_network_flag) goto return_true;
|
||||
if (active_tasks.want_network()) goto return_true;
|
||||
|
|
|
@ -241,7 +241,19 @@ public:
|
|||
int report_result_error(RESULT&, const char *format, ...);
|
||||
int reset_project(PROJECT*);
|
||||
bool want_network_flag;
|
||||
// client wants to do network comm and no physical connection exists.
|
||||
// Initially false; set whenever a Curl operation
|
||||
// returns CURLE_COULDNT_RESOLVE_HOST;
|
||||
// cleared whenever a Curl operation returns anything else
|
||||
// TODO: is this the best way to do this?
|
||||
// won't it set this flag when user enters URL with
|
||||
// non-existent URL, e.g.?
|
||||
//
|
||||
bool have_sporadic_connection;
|
||||
// we have a network connection, but it's likely to go away soon,
|
||||
// so do as much network comm as possible
|
||||
// (e.g. report completed results)
|
||||
//
|
||||
bool want_network();
|
||||
void network_available();
|
||||
bool no_gui_rpc;
|
||||
|
|
|
@ -66,12 +66,14 @@ using std::vector;
|
|||
//
|
||||
#define NET_XFER_TIMEOUT 600
|
||||
|
||||
CURLM* g_curlMulti = NULL; // global curl for this module, can handle http & https
|
||||
CURLM* g_curlMulti = NULL;
|
||||
|
||||
// the file descriptor sets need to be global so libcurl has access always
|
||||
//
|
||||
fd_set read_fds, write_fds, error_fds;
|
||||
|
||||
// call these once at the start of the program and once at the end (init & cleanup of course)
|
||||
// call these once at the start of the program and once at the end
|
||||
//
|
||||
int curl_init() {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
g_curlMulti = curl_multi_init();
|
||||
|
@ -95,11 +97,11 @@ void NET_XFER::reset() {
|
|||
is_connected = false;
|
||||
want_download = false;
|
||||
want_upload = false;
|
||||
do_file_io = true; // CMC Note: should I default to true, i.e. this does all i/o?
|
||||
do_file_io = true;
|
||||
io_done = false;
|
||||
fileIn = NULL;
|
||||
fileOut = NULL;
|
||||
io_ready = true; // don't allow higher levels to do i/o?
|
||||
io_ready = true;
|
||||
error = 0;
|
||||
file_read_buf_offset = 0;
|
||||
file_read_buf_len = 0;
|
||||
|
@ -125,7 +127,8 @@ NET_XFER::~NET_XFER() {
|
|||
}
|
||||
|
||||
void NET_XFER::close_socket() {
|
||||
// CMC: this just cleans up the curlEasy, and "spoofs" the old close_socket
|
||||
// this cleans up the curlEasy, and "spoofs" the old close_socket
|
||||
//
|
||||
if (pcurlList) {
|
||||
curl_slist_free_all(pcurlList);
|
||||
pcurlList = NULL;
|
||||
|
@ -195,9 +198,6 @@ NET_XFER_SET::NET_XFER_SET() {
|
|||
bytes_down = 0;
|
||||
}
|
||||
|
||||
// Connect to a server,
|
||||
// and if successful insert the NET_XFER object into the set
|
||||
//
|
||||
int NET_XFER_SET::insert(NET_XFER* nxp) {
|
||||
net_xfers.push_back(nxp);
|
||||
return 0;
|
||||
|
@ -223,7 +223,9 @@ int NET_XFER_SET::remove(NET_XFER* nxp) {
|
|||
|
||||
void NET_XFER_SET::get_fdset(FDSET_GROUP& fg) {
|
||||
CURLMcode curlMErr;
|
||||
curlMErr = curl_multi_fdset(g_curlMulti, &fg.read_fds, &fg.write_fds, &fg.exc_fds, &fg.max_fd);
|
||||
curlMErr = curl_multi_fdset(
|
||||
g_curlMulti, &fg.read_fds, &fg.write_fds, &fg.exc_fds, &fg.max_fd
|
||||
);
|
||||
//printf("curl msfd %d %d\n", curlMErr, fg.max_fd);
|
||||
}
|
||||
|
||||
|
@ -265,6 +267,7 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
}
|
||||
|
||||
// read messages from curl that may have come in from the above loop
|
||||
//
|
||||
while ((pcurlMsg = curl_multi_info_read(g_curlMulti, &iNumMsg))) {
|
||||
// if we have a msg, then somebody finished
|
||||
// can check also with pcurlMsg->msg == CURLMSG_DONE
|
||||
|
@ -304,9 +307,12 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
}
|
||||
|
||||
// the op is done if curl_multi_msg_read gave us a msg for this http_op
|
||||
//
|
||||
nxf->http_op_state = HTTP_STATE_DONE;
|
||||
|
||||
// added a more useful error string (just pass the curl string up for now)
|
||||
// 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));
|
||||
|
||||
|
@ -334,6 +340,16 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
nxf->http_op_retval = nxf->response;
|
||||
}
|
||||
} else {
|
||||
// If we couldn't resolve hostname,
|
||||
// it could be because there's no physical network connection.
|
||||
// Find out for sure by trying to contact google
|
||||
//
|
||||
if (nxf->CurlResult == CURLE_COULDNT_RESOLVE_HOST) {
|
||||
std::string url = "http://www.google.com";
|
||||
gstate.lookup_website_op.do_rpc(url);
|
||||
} else {
|
||||
gstate.want_network_flag = false;
|
||||
}
|
||||
msg_printf(0, MSG_ERROR, "HTTP error: %s", nxf->strCurlResult);
|
||||
nxf->http_op_retval = ERR_HTTP_ERROR;
|
||||
}
|
||||
|
@ -347,11 +363,12 @@ void NET_XFER_SET::got_select(FDSET_GROUP&, double timeout) {
|
|||
file_size(nxf->outfile, dSize);
|
||||
nxf->fileOut = boinc_fopen(nxf->outfile, "rb");
|
||||
if (!nxf->fileOut) { // ack, can't open back up!
|
||||
nxf->response = 1; // flag as a bad response for a possible retry later
|
||||
nxf->response = 1;
|
||||
// flag as a bad response for a possible retry later
|
||||
} else {
|
||||
fseek(nxf->fileOut, 0, SEEK_SET);
|
||||
// CMC Note: req1 is a pointer to "header" which is 4096
|
||||
memset(nxf->req1, 0x00, 4096);
|
||||
memset(nxf->req1, 0, 4096);
|
||||
fread(nxf->req1, 1, (size_t) dSize, nxf->fileOut);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue