From 7135f46c75dff9bb3148e47e4a4d1f47ab84b349 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 5 Mar 2015 15:19:41 -0800 Subject: [PATCH] client: if get 417 HTTP status, switch to HTTP 1.0 417 (Expectation Failed) probably means we're talking to a 1.0 proxy --- client/http_curl.cpp | 9 ++++++++- lib/common_defs.h | 4 ++++ lib/str_util.cpp | 17 +++++++++-------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/client/http_curl.cpp b/client/http_curl.cpp index f0c64e3131..5fea257ab8 100644 --- a/client/http_curl.cpp +++ b/client/http_curl.cpp @@ -63,6 +63,10 @@ static CURLM* g_curlMulti = NULL; static char g_user_agent_string[256] = {""}; static const char g_content_type[] = {"Content-Type: application/x-www-form-urlencoded"}; static unsigned int g_trace_count = 0; +static bool got_expectation_failed = false; + // Whether we've got a 417 HTTP error. + // If we did, it's probably because we talked HTTP 1.1 to a 1.0 proxy; + // use 1.0 from now on. char* get_user_agent_string() { sprintf(g_user_agent_string, "BOINC client (%s %d.%d.%d)", @@ -557,7 +561,7 @@ int HTTP_OP::libcurl_exec( // force curl to use HTTP/1.0 if config specifies it // (curl uses 1.1 by default) // - if (cc_config.http_1_0 || (cc_config.force_auth == "ntlm")) { + if (cc_config.http_1_0 || (cc_config.force_auth == "ntlm") || got_expectation_failed) { curl_easy_setopt(curlEasy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } curl_easy_setopt(curlEasy, CURLOPT_MAXREDIRS, 50L); @@ -1011,6 +1015,9 @@ void HTTP_OP::handle_messages(CURLMsg *pcurlMsg) { safe_strcpy(error_msg, boincerror(response)); break; default: // 400 + if (response == HTTP_STATUS_EXPECTATION_FAILED) { + got_expectation_failed = true; + } http_op_retval = ERR_HTTP_PERMANENT; safe_strcpy(error_msg, boincerror(response)); break; diff --git a/lib/common_defs.h b/lib/common_defs.h index 863a549dcd..92483ae9bf 100644 --- a/lib/common_defs.h +++ b/lib/common_defs.h @@ -59,8 +59,12 @@ #define HTTP_STATUS_NOT_FOUND 404 #define HTTP_STATUS_PROXY_AUTH_REQ 407 #define HTTP_STATUS_RANGE_REQUEST_ERROR 416 +#define HTTP_STATUS_EXPECTATION_FAILED 417 #define HTTP_STATUS_INTERNAL_SERVER_ERROR 500 +#define HTTP_STATUS_NOT_IMPLEMENTED 501 +#define HTTP_STATUS_BAD_GATEWAY 502 #define HTTP_STATUS_SERVICE_UNAVAILABLE 503 +#define HTTP_STATUS_GATEWAY_TIMEOUT 504 // graphics messages // diff --git a/lib/str_util.cpp b/lib/str_util.cpp index 898f6541dd..e0f78b97ec 100644 --- a/lib/str_util.cpp +++ b/lib/str_util.cpp @@ -534,14 +534,15 @@ const char* boincerror(int which_error) { case ERR_PROC_PARSE: return "a /proc entry was not parsed correctly"; case ERR_PIPE: return "pipe() failed"; case ERR_NEED_HTTPS: return "HTTPS needed"; - case 404: return "HTTP file not found"; - case 407: return "HTTP proxy authentication failure"; - case 416: return "HTTP range request error"; - case 500: return "HTTP internal server error"; - case 501: return "HTTP not implemented"; - case 502: return "HTTP bad gateway"; - case 503: return "HTTP service unavailable"; - case 504: return "HTTP gateway timeout"; + case HTTP_STATUS_NOT_FOUND: return "HTTP file not found"; + case HTTP_STATUS_PROXY_AUTH_REQ: return "HTTP proxy authentication failure"; + case HTTP_STATUS_RANGE_REQUEST_ERROR: return "HTTP range request error"; + case HTTP_STATUS_EXPECTATION_FAILED: return "HTTP expectation failed"; + case HTTP_STATUS_INTERNAL_SERVER_ERROR: return "HTTP internal server error"; + case HTTP_STATUS_NOT_IMPLEMENTED: return "HTTP not implemented"; + case HTTP_STATUS_BAD_GATEWAY: return "HTTP bad gateway"; + case HTTP_STATUS_SERVICE_UNAVAILABLE: return "HTTP service unavailable"; + case HTTP_STATUS_GATEWAY_TIMEOUT: return "HTTP gateway timeout"; } static char buf[128]; sprintf(buf, "Error %d", which_error);