From f8bf11d574722923655389e9be3961796000e0a5 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Thu, 15 Nov 2012 13:51:16 +0100 Subject: [PATCH 1/4] More clearly state the implications of the NoVerifySSLCert debug option --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0ccac5736..06dfc90e4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9104,7 +9104,7 @@ Found in Advanced->Rendering->Info Displays NoVerifySSLCert Comment - Do not verify SSL peers + Do not verify SSL certificates. WARNING: Setting this to TRUE allows anyone to impersonate the server and intercept your data (man in the middle attack). Persist 1 Type From e3f30fece9c1a8ad0d0fd6f14c598d93e91b2672 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 16 Nov 2012 16:06:30 +0100 Subject: [PATCH 2/4] Fix print_diagnostics for windows. --- indra/llmessage/aicurlthread.cpp | 37 ++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 7009d5bf3..55e891137 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -1971,6 +1971,10 @@ void HTTPTimeout::done(AICurlEasyRequest_wat const& curlEasyRequest_w, CURLcode DoutCurl("done: mStalled set to -1"); } +// Libcurl uses GetTickCount on windows, with a resolution of 10 to 16 ms. +// As a result, we can not assume that namelookup_time == 0 has a special meaning. +#define LOWRESTIMER LL_WINDOWS + void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, char const* eff_url) { llwarns << "Request to \"" << curl_easy_request->getLowercaseHostname() << "\" timed out for " << curl_easy_request->getTimeoutPolicy()->name() << llendl; @@ -1981,8 +1985,15 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch curl_easy_request->getinfo(CURLINFO_APPCONNECT_TIME, &appconnect_time); curl_easy_request->getinfo(CURLINFO_PRETRANSFER_TIME, &pretransfer_time); curl_easy_request->getinfo(CURLINFO_STARTTRANSFER_TIME, &starttransfer_time); - if (namelookup_time == 0) + if (namelookup_time == 0 +#if LOWRESTIMER + && connect_time == 0 +#endif + ) { +#if LOWRESTIMER + llinfos << "Hostname seems to have been still in the DNS cache." << llendl; +#else llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but DNS lookup did not occur according to timings. Expected CURLE_COULDNT_RESOLVE_PROXY or CURLE_COULDNT_RESOLVE_HOST!" << llendl; llassert(connect_time == 0); llassert(appconnect_time == 0); @@ -1990,17 +2001,26 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch llassert(starttransfer_time == 0); // Fatal error for diagnostics. return; +#endif } // If namelookup_time is less than 500 microseconds, then it's very likely just a DNS cache lookup. else if (namelookup_time < 500e-6) { +#if LOWRESTIMER + llinfos << "Hostname was most likely still in DNS cache (or lookup occured in under ~10ms)." << llendl; +#else llinfos << "Hostname was still in DNS cache." << llendl; +#endif } else { - llwarns << "DNS lookup of " << curl_easy_request->getLowercaseHostname() << " took " << namelookup_time << " seconds." << llendl; + llinfos << "DNS lookup of " << curl_easy_request->getLowercaseHostname() << " took " << namelookup_time << " seconds." << llendl; } - if (connect_time == 0) + if (connect_time == 0 +#if LOWRESTIMER + && namelookup_time > 0 // connect_time, when set, is namelookup_time + something. +#endif + ) { llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but connection did not occur according to timings. Expected CURLE_COULDNT_CONNECT!" << llendl; llassert(appconnect_time == 0); @@ -2010,16 +2030,21 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch return; } // If connect_time is almost equal to namelookup_time, then it was just set because it was already connected. - if (connect_time - namelookup_time <= 1e-6) + if (connect_time - namelookup_time <= 1e-5) { +#if LOWRESTIMER // Assuming 10ms resolution. + llinfos << "The socket was most likely already connected (or you connected to a proxy with a connect time of under ~10 ms)." << llendl; +#else llinfos << "The socket was already connected (to remote or proxy)." << llendl; +#endif + // I'm assuming that the SSL/TLS handshake can be measured with a low res timer. if (appconnect_time == 0) { llwarns << "The SSL/TLS handshake never occurred according to the timings!" << llendl; return; } // If appconnect_time is almost equal to connect_time, then it was just set because this is a connection re-use. - if (appconnect_time - connect_time <= 1e-6) + if (appconnect_time - connect_time <= 1e-5) { llinfos << "Connection with HTTP server was already established; this was a re-used connection." << llendl; } @@ -2043,7 +2068,7 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch llwarns << "The transfer never happened because there was too much in the pipeline (apparently)." << llendl; return; } - else if (pretransfer_time - appconnect_time >= 1e-6) + else if (pretransfer_time - appconnect_time >= 1e-5) { llinfos << "Apparently there was a delay, due to waits in line for the pipeline, of " << (pretransfer_time - appconnect_time) << " seconds before the transfer began." << llendl; } From e781870da35ab1adef68146bfbd6e37065577986 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 17 Nov 2012 04:55:34 +0100 Subject: [PATCH 3/4] Fix Ratany Residents crash --- indra/llmessage/aicurlprivate.h | 3 ++- indra/llmessage/aicurlthread.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index a1d449998..327637a3d 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -376,7 +376,8 @@ class CurlEasyRequest : public CurlEasyHandle { // This creates mTimeout (unless mTimeoutIsOrphan is set in which case it adopts the orphan). LLPointer& get_timeout_object(ThreadSafeBufferedCurlEasyRequest* lockobj); // Accessor for mTimeout with optional creation of orphaned object (if lockobj != NULL). - LLPointer& httptimeout(ThreadSafeBufferedCurlEasyRequest* lockobj = NULL) { if (lockobj && !mTimeout) create_timeout_object(lockobj); return mTimeout; } + LLPointer& httptimeout(ThreadSafeBufferedCurlEasyRequest* lockobj = NULL) + { if (lockobj && !mTimeout) { create_timeout_object(lockobj); mTimeoutIsOrphan = true; } return mTimeout; } // Return true if no data has been received on the latest socket (if any) for too long. bool has_stalled(void) const { return mTimeout && mTimeout->has_stalled(); } diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 55e891137..0b4a6e121 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -2284,7 +2284,7 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size char const* const header_line = static_cast(data); size_t const header_len = size * nmemb; - if (self_w->httptimeout()->data_received(header_len)) // Update timeout administration. + if (self_w->httptimeout(lockobj)->data_received(header_len)) // Update timeout administration. { // Transfer timed out. Return 0 which will abort with error CURLE_WRITE_ERROR. return 0; From 5d1a138c5c78320ddaabe12133ea880cfb6df580 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 17 Nov 2012 05:16:21 +0100 Subject: [PATCH 4/4] Code clean up of code related to previous commit. --- indra/llmessage/aicurl.cpp | 10 +++++++--- indra/llmessage/aicurlprivate.h | 7 +++---- indra/llmessage/aicurlthread.cpp | 11 ++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index 2353f24bd..bfd2a2243 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -1148,12 +1148,16 @@ void CurlEasyRequest::set_timeout_opts(void) setopt(CURLOPT_TIMEOUT, mTimeoutPolicy->getCurlTransaction()); } -void CurlEasyRequest::create_timeout_object(ThreadSafeBufferedCurlEasyRequest* lockobj) +void CurlEasyRequest::create_timeout_object(void) { + ThreadSafeBufferedCurlEasyRequest* lockobj = NULL; +#if defined(CWDEBUG) || defined(DEBUG_CURLIO) + lockobj = static_cast(this)->get_lockobj(); +#endif mTimeout = new curlthread::HTTPTimeout(mTimeoutPolicy, lockobj); } -LLPointer& CurlEasyRequest::get_timeout_object(ThreadSafeBufferedCurlEasyRequest* lockobj) +LLPointer& CurlEasyRequest::get_timeout_object(void) { if (mTimeoutIsOrphan) { @@ -1162,7 +1166,7 @@ LLPointer& CurlEasyRequest::get_timeout_object(ThreadSa } else { - create_timeout_object(lockobj); + create_timeout_object(); } return mTimeout; } diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index 327637a3d..abb663d4a 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -316,7 +316,7 @@ class CurlEasyRequest : public CurlEasyHandle { static CURLcode curlCtxCallback(CURL* curl, void* sslctx, void* parm); // Called from get_timeout_object and httptimeout. - void create_timeout_object(ThreadSafeBufferedCurlEasyRequest* lockobj); + void create_timeout_object(void); public: // Set default options that we want applied to all curl easy handles. @@ -374,10 +374,9 @@ class CurlEasyRequest : public CurlEasyHandle { std::string const& getLowercaseHostname(void) const { return mLowercaseHostname; } // Called by CurlSocketInfo to allow access to the last (after a redirect) HTTPTimeout object related to this request. // This creates mTimeout (unless mTimeoutIsOrphan is set in which case it adopts the orphan). - LLPointer& get_timeout_object(ThreadSafeBufferedCurlEasyRequest* lockobj); + LLPointer& get_timeout_object(void); // Accessor for mTimeout with optional creation of orphaned object (if lockobj != NULL). - LLPointer& httptimeout(ThreadSafeBufferedCurlEasyRequest* lockobj = NULL) - { if (lockobj && !mTimeout) { create_timeout_object(lockobj); mTimeoutIsOrphan = true; } return mTimeout; } + LLPointer& httptimeout(void) { if (!mTimeout) { create_timeout_object(); mTimeoutIsOrphan = true; } return mTimeout; } // Return true if no data has been received on the latest socket (if any) for too long. bool has_stalled(void) const { return mTimeout && mTimeout->has_stalled(); } diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 0b4a6e121..1fbe57d3e 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -775,7 +775,7 @@ CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socke // CurlSocketInfo objects for a request and we need upload_finished() to be called on the HTTPTimeout // object related to THIS CurlSocketInfo. AICurlEasyRequest_wat easy_request_w(*lockobj); - mTimeout = easy_request_w->get_timeout_object(lockobj); + mTimeout = easy_request_w->get_timeout_object(); } CurlSocketInfo::~CurlSocketInfo() @@ -2259,11 +2259,8 @@ size_t BufferedCurlEasyRequest::curlReadCallback(char* data, size_t size, size_t S32 bytes = size * nmemb; // The maximum amount to read. self_w->mLastRead = self_w->getInput()->readAfter(sChannels.out(), self_w->mLastRead, (U8*)data, bytes); self_w->mRequestTransferedBytes += bytes; // Accumulate data sent to the server. - // Timeout administration. Note that it can happen that we get here - // before the socket callback has been called, because the silly libcurl - // writes headers without informing us. In that case it's OK to create - // the Timeout object on the fly, so pass lockobj. - if (self_w->httptimeout(lockobj)->data_sent(bytes)) + // Timeout administration. + if (self_w->httptimeout()->data_sent(bytes)) { // Transfer timed out. Return CURL_READFUNC_ABORT which will abort with error CURLE_ABORTED_BY_CALLBACK. return CURL_READFUNC_ABORT; @@ -2284,7 +2281,7 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size char const* const header_line = static_cast(data); size_t const header_len = size * nmemb; - if (self_w->httptimeout(lockobj)->data_received(header_len)) // Update timeout administration. + if (self_w->httptimeout()->data_received(header_len)) // Update timeout administration. { // Transfer timed out. Return 0 which will abort with error CURLE_WRITE_ERROR. return 0;