detect lack of physical network connection

svn path=/trunk/boinc/; revision=9404
This commit is contained in:
David Anderson 2006-02-06 22:23:04 +00:00
parent c6a2d33145
commit ab8ff092db
5 changed files with 71 additions and 16 deletions

View File

@ -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

View File

@ -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() {

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}