diff options
29 files changed, 277 insertions, 679 deletions
| diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 9631e960c5..161823079b 100755 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -26,6 +26,7 @@ set(llcorehttp_SOURCE_FILES      bufferarray.cpp      bufferstream.cpp      httpcommon.cpp +    llhttpconstants.cpp      httpheaders.cpp      httpoptions.cpp      httprequest.cpp @@ -51,6 +52,7 @@ set(llcorehttp_HEADER_FILES      bufferarray.h      bufferstream.h      httpcommon.h +    llhttpconstants.h      httphandler.h      httpheaders.h      httpoptions.h diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp index 99238ea920..c606f2b754 100755 --- a/indra/llcorehttp/httpcommon.cpp +++ b/indra/llcorehttp/httpcommon.cpp @@ -23,12 +23,24 @@   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ +#if LL_WINDOWS +#define SAFE_SSL 1 +#elif LL_DARWIN +#define SAFE_SSL 1 +#else +#define SAFE_SSL 1 +#endif +#include "linden_common.h"		// Modifies curl/curl.h interfaces  #include "httpcommon.h" - +#include "llmutex.h" +#include "llthread.h"  #include <curl/curl.h>  #include <string>  #include <sstream> +#if SAFE_SSL +#include <openssl/crypto.h> +#endif  namespace LLCore @@ -263,5 +275,151 @@ bool HttpStatus::isRetryable() const  			*this == inv_cont_range);	// Short data read disagrees with content-range  } -} // end namespace LLCore +namespace LLHttp +{ +namespace +{ +typedef boost::shared_ptr<LLMutex> LLMutex_ptr; +std::vector<LLMutex_ptr> sSSLMutex; + +CURL *getCurlTemplateHandle() +{ +    static CURL *curlpTemplateHandle = NULL; + +    if (curlpTemplateHandle == NULL) +    {	// Late creation of the template curl handle +        curlpTemplateHandle = curl_easy_init(); +        if (curlpTemplateHandle == NULL) +        { +            LL_WARNS() << "curl error calling curl_easy_init()" << LL_ENDL; +        } +        else +        { +            CURLcode result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); +            check_curl_code(result, CURLOPT_IPRESOLVE); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOSIGNAL, 1); +            check_curl_code(result, CURLOPT_NOSIGNAL); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOPROGRESS, 1); +            check_curl_code(result, CURLOPT_NOPROGRESS); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_ENCODING, ""); +            check_curl_code(result, CURLOPT_ENCODING); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_AUTOREFERER, 1); +            check_curl_code(result, CURLOPT_AUTOREFERER); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_FOLLOWLOCATION, 1); +            check_curl_code(result, CURLOPT_FOLLOWLOCATION); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_SSL_VERIFYPEER, 1); +            check_curl_code(result, CURLOPT_SSL_VERIFYPEER); +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_SSL_VERIFYHOST, 0); +            check_curl_code(result, CURLOPT_SSL_VERIFYHOST); + +            // The Linksys WRT54G V5 router has an issue with frequent +            // DNS lookups from LAN machines.  If they happen too often, +            // like for every HTTP request, the router gets annoyed after +            // about 700 or so requests and starts issuing TCP RSTs to +            // new connections.  Reuse the DNS lookups for even a few +            // seconds and no RSTs. +            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15); +            check_curl_code(result, CURLOPT_DNS_CACHE_TIMEOUT); +        } +    } + +    return curlpTemplateHandle; +} +     +LLMutex *getCurlMutex() +{ +    static LLMutex* sHandleMutexp = NULL; + +    if (!sHandleMutexp) +    { +        sHandleMutexp = new LLMutex(NULL); +    } + +    return sHandleMutexp; +} + +void deallocateEasyCurl(CURL *curlp) +{ +    LLMutexLock lock(getCurlMutex()); + +    curl_easy_cleanup(curlp); +} + + +#if SAFE_SSL +//static +void ssl_locking_callback(int mode, int type, const char *file, int line) +{ +    if (mode & CRYPTO_LOCK) +    { +        sSSLMutex[type]->lock(); +    } +    else +    { +        sSSLMutex[type]->unlock(); +    } +} + +//static +unsigned long ssl_thread_id(void) +{ +    return LLThread::currentID(); +} +#endif + +} + +void initialize() +{ +    // Do not change this "unless you are familiar with and mean to control  +    // internal operations of libcurl" +    // - http://curl.haxx.se/libcurl/c/curl_global_init.html +    CURLcode code = curl_global_init(CURL_GLOBAL_ALL); + +    check_curl_code(code, CURL_GLOBAL_ALL); + +#if SAFE_SSL +    S32 mutex_count = CRYPTO_num_locks(); +    for (S32 i = 0; i < mutex_count; i++) +    { +        sSSLMutex.push_back(LLMutex_ptr(new LLMutex(NULL))); +    } +    CRYPTO_set_id_callback(&ssl_thread_id); +    CRYPTO_set_locking_callback(&ssl_locking_callback); +#endif + +} + + +CURL_ptr createEasyHandle() +{ +    LLMutexLock lock(getCurlMutex()); + +    CURL* handle = curl_easy_duphandle(getCurlTemplateHandle()); + +    return CURL_ptr(handle, &deallocateEasyCurl); +} + +std::string getCURLVersion() +{ +    return std::string(curl_version()); +} + +void check_curl_code(CURLcode code, int curl_setopt_option) +{ +    if (CURLE_OK != code) +    { +        // Comment from old llcurl code which may no longer apply: +        // +        // linux appears to throw a curl error once per session for a bad initialization +        // at a pretty random time (when enabling cookies). +        LL_WARNS() << "libcurl error detected:  " << curl_easy_strerror(code) +            << ", curl_easy_setopt option:  " << curl_setopt_option +            << LL_ENDL; +    } + +} + +} +} // end namespace LLCore diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h index 898d3d47fa..3e98600a92 100755 --- a/indra/llcorehttp/httpcommon.h +++ b/indra/llcorehttp/httpcommon.h @@ -193,6 +193,7 @@  #include "boost/weak_ptr.hpp"  #include "boost/function.hpp"  #include <string> +#include <curl/curl.h>  namespace LLCore  { @@ -490,6 +491,19 @@ private:  }; // end struct HttpStatus +///  A namespace for several free methods and low level utilities.  +namespace LLHttp +{ +    typedef boost::shared_ptr<CURL> CURL_ptr; + +    void initialize(); + +    CURL_ptr createEasyHandle(); +    std::string getCURLVersion(); + +    void check_curl_code(CURLcode code, int curl_setopt_option); +} +  }  // end namespace LLCore  #endif	// _LLCORE_HTTP_COMMON_H_ diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llcorehttp/llhttpconstants.cpp index 32f76f0d70..71d4f19408 100755 --- a/indra/llmessage/llhttpconstants.cpp +++ b/indra/llcorehttp/llhttpconstants.cpp @@ -133,94 +133,3 @@ const std::string HTTP_VERB_MOVE("MOVE");  const std::string HTTP_VERB_OPTIONS("OPTIONS");  const std::string HTTP_VERB_PATCH("PATCH");  const std::string HTTP_VERB_COPY("COPY"); - -const std::string& httpMethodAsVerb(EHTTPMethod method) -{ -	static const std::string VERBS[] = -	{ -		HTTP_VERB_INVALID, -		HTTP_VERB_HEAD, -		HTTP_VERB_GET, -		HTTP_VERB_PUT, -		HTTP_VERB_POST, -		HTTP_VERB_DELETE, -		HTTP_VERB_MOVE, -		HTTP_VERB_OPTIONS, -		HTTP_VERB_PATCH, -		HTTP_VERB_COPY -	}; -	if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT)) -	{ -		return VERBS[0]; -	} -	return VERBS[method]; -} - -bool isHttpInformationalStatus(S32 status) -{ -	// Check for status 1xx. -	return((100 <= status) && (status < 200)); -} - -bool isHttpGoodStatus(S32 status) -{ -	// Check for status 2xx. -	return((200 <= status) && (status < 300)); -} - -bool isHttpRedirectStatus(S32 status) -{ -	// Check for status 3xx. -	return((300 <= status) && (status < 400)); -} - -bool isHttpClientErrorStatus(S32 status) -{ -	// Status 499 is sometimes used for re-interpreted status 2xx errors -	// based on body content.  Treat these as potentially retryable 'server' status errors, -	// since we do not have enough context to know if this will always fail. -	if (HTTP_INTERNAL_ERROR == status) return false; - -	// Check for status 5xx. -	return((400 <= status) && (status < 500)); -} - -bool isHttpServerErrorStatus(S32 status) -{ -	// Status 499 is sometimes used for re-interpreted status 2xx errors. -	// Allow retry of these, since we don't have enough information in this -	// context to know if this will always fail. -	if (HTTP_INTERNAL_ERROR == status) return true; - -	// Check for status 5xx. -	return((500 <= status) && (status < 600)); -} - -// Parses 'Retry-After' header contents and returns seconds until retry should occur. -bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait) -{ -	// *TODO:  This needs testing!   Not in use yet. -	// Examples of Retry-After headers: -	// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT -	// Retry-After: 120 - -	// Check for number of seconds version, first: -	char* end = 0; -	// Parse as double -	double seconds = std::strtod(retry_after.c_str(), &end); -	if ( end != 0 && *end == 0 ) -	{ -		// Successful parse -		seconds_to_wait = (F32) seconds; -		return true; -	} - -	// Parse rfc1123 date. -	time_t date = curl_getdate(retry_after.c_str(), NULL ); -	if (-1 == date) return false; - -	seconds_to_wait = (F64)date - LLTimer::getTotalSeconds(); - -	return true; -} - diff --git a/indra/llmessage/llhttpconstants.h b/indra/llcorehttp/llhttpconstants.h index d6bcbd3c19..121448854e 100755 --- a/indra/llmessage/llhttpconstants.h +++ b/indra/llcorehttp/llhttpconstants.h @@ -116,13 +116,6 @@ enum EHTTPMethod  	HTTP_METHOD_COUNT  }; -const std::string& httpMethodAsVerb(EHTTPMethod method); -bool isHttpInformationalStatus(S32 status); -bool isHttpGoodStatus(S32 status); -bool isHttpRedirectStatus(S32 status); -bool isHttpClientErrorStatus(S32 status); -bool isHttpServerErrorStatus(S32 status); -  // Parses 'Retry-After' header contents and returns seconds until retry should occur.  bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait); diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 4caf6dcd05..6fd4579876 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -214,11 +214,13 @@ void LLCrashLogger::gatherFiles()  		mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString();  		if(mDebugLog.has("CAFilename"))  		{ -			LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); +            LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE, +                LLCore::HttpRequest::GLOBAL_POLICY_ID, mDebugLog["CAFilename"].asString(), NULL);  		}  		else  		{ -			LLCurl::setCAFile(gDirUtilp->getCAFile()); +            LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE, +                LLCore::HttpRequest::GLOBAL_POLICY_ID, gDirUtilp->getCAFile(), NULL);  		}  		LL_INFOS() << "Using log file from debug log " << mFileMap["SecondLifeLog"] << LL_ENDL; @@ -227,7 +229,8 @@ void LLCrashLogger::gatherFiles()  	else  	{  		// Figure out the filename of the second life log -		LLCurl::setCAFile(gDirUtilp->getCAFile()); +        LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE, +            LLCore::HttpRequest::GLOBAL_POLICY_ID, gDirUtilp->getCAFile(), NULL);  		mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");          mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); @@ -531,7 +534,7 @@ void LLCrashLogger::updateApplication(const std::string& message)  bool LLCrashLogger::init()  { -	LLCurl::initClass(false); +    LLCore::LLHttp::initialize();  	// We assume that all the logs we're looking for reside on the current drive  	gDirUtilp->initAppDirs("SecondLife"); diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 9cbb76e794..3bcee13d28 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -42,13 +42,11 @@ set(llmessage_SOURCE_FILES      llclassifiedflags.cpp      llcoproceduremanager.cpp      llcorehttputil.cpp -    llcurl.cpp      lldatapacker.cpp      lldispatcher.cpp      llexperiencecache.cpp      llfiltersd2xmlrpc.cpp      llhost.cpp -    llhttpconstants.cpp      llhttpnode.cpp      llhttpsdhandler.cpp      llinstantmessage.cpp @@ -126,7 +124,6 @@ set(llmessage_HEADER_FILES      llclassifiedflags.h      llcoproceduremanager.h      llcorehttputil.h -    llcurl.h      lldatapacker.h      lldbstrings.h      lldispatcher.h @@ -136,7 +133,6 @@ set(llmessage_HEADER_FILES      llfiltersd2xmlrpc.h      llfollowcamparams.h      llhost.h -    llhttpconstants.h      llhttpnode.h      llhttpnodeadapter.h      llhttpsdhandler.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp deleted file mode 100755 index 0094c42a02..0000000000 --- a/indra/llmessage/llcurl.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/** - * @file llcurl.cpp - * @author Zero / Donovan - * @date 2006-10-15 - * @brief Implementation of wrapper around libcurl. - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010-2013, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#if LL_WINDOWS -#define SAFE_SSL 1 -#elif LL_DARWIN -#define SAFE_SSL 1 -#else -#define SAFE_SSL 1 -#endif - -#include "linden_common.h" - -#include "llcurl.h" - -#include <algorithm> -#include <iomanip> -#include <curl/curl.h> -#if SAFE_SSL -#include <openssl/crypto.h> -#endif - -#include "llbufferstream.h" -#include "llproxy.h" -#include "llsdserialize.h" -#include "llstl.h" -#include "llstring.h" -#include "llthread.h" -#include "lltimer.h" - -////////////////////////////////////////////////////////////////////////////// -/* -	The trick to getting curl to do keep-alives is to reuse the -	same easy handle for the requests.  It appears that curl -	keeps a pool of connections alive for each easy handle, but -	doesn't share them between easy handles.  Therefore it is -	important to keep a pool of easy handles and reuse them, -	rather than create and destroy them with each request.  This -	code does this. - -	Furthermore, it would behoove us to keep track of which -	hosts an easy handle was used for and pick an easy handle -	that matches the next request.  This code does not current -	do this. - */ - -// *TODO: TSN remove the commented code from this file -////////////////////////////////////////////////////////////////////////////// - -//static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; - -// DEBUG // -S32 gCurlEasyCount = 0; -S32 gCurlMultiCount = 0; - -////////////////////////////////////////////////////////////////////////////// - -//static -std::vector<LLMutex*> LLCurl::sSSLMutex; -std::string LLCurl::sCAPath; -std::string LLCurl::sCAFile; -//LLCurlThread* LLCurl::sCurlThread = NULL ; -LLMutex* LLCurl::sHandleMutexp = NULL ; -S32      LLCurl::sTotalHandles = 0 ; -bool     LLCurl::sNotQuitting = true; -F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds -S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined). -CURL*	 LLCurl::sCurlTemplateStandardHandle = NULL; - -void check_curl_code(CURLcode code) -{ -	if (code != CURLE_OK) -	{ -		// linux appears to throw a curl error once per session for a bad initialization -		// at a pretty random time (when enabling cookies). -		LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL; -	} -} - -void check_curl_multi_code(CURLMcode code)  -{ -	if (code != CURLM_OK) -	{ -		// linux appears to throw a curl error once per session for a bad initialization -		// at a pretty random time (when enabling cookies). -		LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL; -	} -} - -//static -void LLCurl::setCAPath(const std::string& path) -{ -	sCAPath = path; -} - -//static -void LLCurl::setCAFile(const std::string& file) -{ -	sCAFile = file; -} - -//static -std::string LLCurl::getVersionString() -{ -	return std::string(curl_version()); -} - - -//static -std::string LLCurl::strerror(CURLcode errorcode) -{ -	return std::string(curl_easy_strerror(errorcode)); -} - - -//////////////////////////////////////////////////////////////////////////// - -#if SAFE_SSL -//static -void LLCurl::ssl_locking_callback(int mode, int type, const char *file, int line) -{ -	if (mode & CRYPTO_LOCK) -	{ -		LLCurl::sSSLMutex[type]->lock(); -	} -	else -	{ -		LLCurl::sSSLMutex[type]->unlock(); -	} -} - -//static -unsigned long LLCurl::ssl_thread_id(void) -{ -	return LLThread::currentID(); -} -#endif - -void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded) -{ -	sCurlRequestTimeOut = curl_reuest_timeout ; //seconds -	sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). - -	// Do not change this "unless you are familiar with and mean to control  -	// internal operations of libcurl" -	// - http://curl.haxx.se/libcurl/c/curl_global_init.html -	CURLcode code = curl_global_init(CURL_GLOBAL_ALL); - -	check_curl_code(code); -	 -#if SAFE_SSL -	S32 mutex_count = CRYPTO_num_locks(); -	for (S32 i=0; i<mutex_count; i++) -	{ -		sSSLMutex.push_back(new LLMutex(NULL)); -	} -	CRYPTO_set_id_callback(&LLCurl::ssl_thread_id); -	CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback); -#endif - -//	sCurlThread = new LLCurlThread(multi_threaded) ; -	if(multi_threaded) -	{ -		sHandleMutexp = new LLMutex(NULL) ; -//		Easy::sHandleMutexp = new LLMutex(NULL) ; -	} -} - -void LLCurl::cleanupClass() -{ -	sNotQuitting = false; //set quitting - -	//shut down curl thread -// 	while(1) -// 	{ -// 		if(!sCurlThread->update(1)) //finish all tasks -// 		{ -// 			break ; -// 		} -// 	} -	LL_CHECK_MEMORY -//	sCurlThread->shutdown() ; -	LL_CHECK_MEMORY -//	delete sCurlThread ; -//	sCurlThread = NULL ; -	LL_CHECK_MEMORY - -#if SAFE_SSL -	CRYPTO_set_locking_callback(NULL); -	for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer()); -	sSSLMutex.clear(); -#endif -	 -    LL_CHECK_MEMORY - -	// Free the template easy handle -	curl_easy_cleanup(sCurlTemplateStandardHandle); -	sCurlTemplateStandardHandle = NULL; -	LL_CHECK_MEMORY - - -	delete sHandleMutexp ; -	sHandleMutexp = NULL ; - -	LL_CHECK_MEMORY - -	// removed as per https://jira.secondlife.com/browse/SH-3115 -	//llassert(Easy::sActiveHandles.empty()); -} - -//static  -CURLM* LLCurl::newMultiHandle() -{ -	llassert(sNotQuitting); - -	LLMutexLock lock(sHandleMutexp) ; - -	if(sTotalHandles + 1 > sMaxHandles) -	{ -		LL_WARNS() << "no more handles available." << LL_ENDL ; -		return NULL ; //failed -	} -	sTotalHandles++; - -	CURLM* ret = curl_multi_init() ; -	if(!ret) -	{ -		LL_WARNS() << "curl_multi_init failed." << LL_ENDL ; -	} - -	return ret ; -} - -//static  -CURLMcode  LLCurl::deleteMultiHandle(CURLM* handle) -{ -	if(handle) -	{ -		LLMutexLock lock(sHandleMutexp) ;		 -		sTotalHandles-- ; -		return curl_multi_cleanup(handle) ; -	} -	return CURLM_OK ; -} - -//static  -CURL*  LLCurl::newEasyHandle() -{ -	llassert(sNotQuitting); -	LLMutexLock lock(sHandleMutexp) ; - -	if(sTotalHandles + 1 > sMaxHandles) -	{ -		LL_WARNS() << "no more handles available." << LL_ENDL ; -		return NULL ; //failed -	} -	sTotalHandles++; - -	CURL* ret = createStandardCurlHandle(); -	if(!ret) -	{ -		LL_WARNS() << "failed to create curl handle." << LL_ENDL ; -	} - -	return ret ; -} - -//static  -void  LLCurl::deleteEasyHandle(CURL* handle) -{ -	if(handle) -	{ -		LLMutexLock lock(sHandleMutexp) ; -		LL_CHECK_MEMORY -		curl_easy_cleanup(handle) ; -		LL_CHECK_MEMORY -		sTotalHandles-- ; -	} -} - -const unsigned int LLCurl::MAX_REDIRECTS = 5; - -// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. -void LLCurlFF::check_easy_code(CURLcode code) -{ -	check_curl_code(code); -} -// void LLCurlFF::check_multi_code(CURLMcode code) -// { -// 	check_curl_multi_code(code); -// } - - -// Static -CURL* LLCurl::createStandardCurlHandle() -{ -	if (sCurlTemplateStandardHandle == NULL) -	{	// Late creation of the template curl handle -		sCurlTemplateStandardHandle = curl_easy_init(); -		if (sCurlTemplateStandardHandle == NULL) -		{ -			LL_WARNS() << "curl error calling curl_easy_init()" << LL_ENDL; -		} -		else -		{ -			CURLcode result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOSIGNAL, 1); -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOPROGRESS, 1); -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_ENCODING, "");	 -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_AUTOREFERER, 1); -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_FOLLOWLOCATION, 1);	 -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYPEER, 1); -			check_curl_code(result); -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYHOST, 0); -			check_curl_code(result); - -			// The Linksys WRT54G V5 router has an issue with frequent -			// DNS lookups from LAN machines.  If they happen too often, -			// like for every HTTP request, the router gets annoyed after -			// about 700 or so requests and starts issuing TCP RSTs to -			// new connections.  Reuse the DNS lookups for even a few -			// seconds and no RSTs. -			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15); -			check_curl_code(result); -		} -	} - -	return curl_easy_duphandle(sCurlTemplateStandardHandle); -} diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h deleted file mode 100755 index 289e4bfd22..0000000000 --- a/indra/llmessage/llcurl.h +++ /dev/null @@ -1,142 +0,0 @@ -/**  - * @file llcurl.h - * @author Zero / Donovan - * @date 2006-10-15 - * @brief A wrapper around libcurl. - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ -  -#ifndef LL_LLCURL_H -#define LL_LLCURL_H - -#include "linden_common.h" - -#include <sstream> -#include <string> -#include <vector> - -#include <boost/intrusive_ptr.hpp> -#include <curl/curl.h> // TODO: remove dependency - -#include "llbuffer.h" -#include "llhttpconstants.h" -#include "lliopipe.h" -#include "llsd.h" -#include "llqueuedthread.h" -#include "llframetimer.h" -#include "llpointer.h" -#include "llsingleton.h" - -class LLMutex; -//class LLCurlThread; - -// For whatever reason, this is not typedef'd in curl.h -typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream); - -class LLCurl -{ -	LOG_CLASS(LLCurl); -	 -public: - -	/** -	 * @ brief Set certificate authority file used to verify HTTPS certs. -	 */ -	static void setCAFile(const std::string& file); - -	/** -	 * @ brief Set certificate authority path used to verify HTTPS certs. -	 */ -	static void setCAPath(const std::string& path); - -	/** -	 * @ brief Return human-readable string describing libcurl version. -	 */ -	static std::string getVersionString(); -	 -	/** -	 * @ brief Get certificate authority file used to verify HTTPS certs. -	 */ -	static const std::string& getCAFile() { return sCAFile; } - -	/** -	 * @ brief Get certificate authority path used to verify HTTPS certs. -	 */ -	static const std::string& getCAPath() { return sCAPath; } - -	/** -	 * @ brief Initialize LLCurl class -	 */ -	static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false); - -	/** -	 * @ brief Cleanup LLCurl class -	 */ -	static void cleanupClass(); - -	/** -	 * @ brief curl error code -> string -	 */ -	static std::string strerror(CURLcode errorcode); -	 -	// For OpenSSL callbacks -	static std::vector<LLMutex*> sSSLMutex; - -	// OpenSSL callbacks -	static void ssl_locking_callback(int mode, int type, const char *file, int line); -	static unsigned long ssl_thread_id(void); - -//	static LLCurlThread* getCurlThread() { return sCurlThread ;} - -	static CURLM* newMultiHandle() ; -	static CURLMcode deleteMultiHandle(CURLM* handle) ; -	static CURL*  newEasyHandle() ; -	static void   deleteEasyHandle(CURL* handle) ; - -	static CURL*	createStandardCurlHandle(); - -private: -	static std::string sCAPath; -	static std::string sCAFile; -	static const unsigned int MAX_REDIRECTS; -    //	static LLCurlThread* sCurlThread; -//    static LLCurlThread* sCurlThread; - -	static LLMutex* sHandleMutexp ; -	static S32      sTotalHandles ; -	static S32      sMaxHandles; -	static CURL*	sCurlTemplateStandardHandle; -public: -	static bool     sNotQuitting; -	static F32      sCurlRequestTimeOut;	 -}; - - -// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. -namespace LLCurlFF -{ -	void check_easy_code(CURLcode code); -	//void check_multi_code(CURLMcode code); -} - -#endif // LL_LLCURL_H diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index c25f1ec5e5..537efa69d8 100755 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -30,9 +30,8 @@  #include <string>  #include <curl/curl.h> - +#include "httpcommon.h"  #include "llapr.h" -#include "llcurl.h"  #include "llhost.h"  // Static class variable instances @@ -429,21 +428,21 @@ void LLProxy::applyProxySettings(CURL* handle)  		// Now test again to verify that the proxy wasn't disabled between the first check and the lock.  		if (mHTTPProxyEnabled)  		{ -			LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); -			LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); +            LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY); +            LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()), CURLOPT_PROXYPORT);  			if (mProxyType == LLPROXY_SOCKS)  			{ -				LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); +                LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);  				if (mAuthMethodSelected == METHOD_PASSWORD)  				{  					std::string auth_string = mSocksUsername + ":" + mSocksPassword; -					LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); +                    LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);  				}  			}  			else  			{ -				LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); +                LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);  			}  		}  	} diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index da965219fa..bd23dd39de 100755 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -27,12 +27,12 @@  #ifndef LL_PROXY_H  #define LL_PROXY_H -#include "llcurl.h"  #include "llhost.h"  #include "lliosocket.h"  #include "llmemory.h"  #include "llsingleton.h"  #include "llthread.h" +#include <curl/curl.h>  #include <string>  // SOCKS error codes returned from the StartProxy method diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp index 5bd1112cfe..33944f7883 100755 --- a/indra/llmessage/lltrustedmessageservice.cpp +++ b/indra/llmessage/lltrustedmessageservice.cpp @@ -30,6 +30,7 @@  #include "llhost.h"  #include "llmessageconfig.h"  #include "message.h" +#include "llhttpconstants.h"  bool LLTrustedMessageService::validate(const std::string& name, LLSD& context) diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index fc391da633..133db620e6 100755 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -50,7 +50,6 @@  #include "lltimer.h"  #include "llpacketring.h"  #include "llhost.h" -#include "llcurl.h"  #include "llhttpnode.h"  //#include "llpacketack.h"  #include "llsingleton.h" diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 48c081991a..e97059014b 100755 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -31,7 +31,6 @@  #include <map>  #include <set>  #include <string> -#include "llcurl.h"  #include "llhttpretrypolicy.h"  #include "llviewerinventory.h"  #include "llcorehttputil.h" diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 51cca273d8..91a5148e4c 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -138,6 +138,9 @@ LLAppCoreHttp::~LLAppCoreHttp()  void LLAppCoreHttp::init()  { + +    LLCore::LLHttp::initialize(); +  	LLCore::HttpStatus status = LLCore::HttpRequest::createService();  	if (! status)  	{ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 45e21d9129..ba76341b69 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -58,7 +58,6 @@  #include "llviewerjoystick.h"  #include "llallocator.h"  #include "llares.h"  -#include "llcurl.h"  #include "llcalc.h"  #include "llconversationlog.h"  #include "lldxhardware.h" @@ -828,12 +827,7 @@ bool LLAppViewer::init()  	// before consumers (LLTextureFetch).  	mAppCoreHttp.init(); -    // *NOTE:Mani - LLCurl::initClass is not thread safe.  -    // Called before threads are created. -    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"),  -						gSavedSettings.getS32("CurlMaximumNumberOfHandles"),  -						gSavedSettings.getBOOL("CurlUseMultipleThreads")); -	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; +	LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ;      LLMachineID::init(); @@ -903,7 +897,7 @@ bool LLAppViewer::init()  	// the libs involved in getting to a full login screen.  	//  	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL; -	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL; +	LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL;  	/////////////////////////////////////////////////  	// OS-specific login dialogs @@ -1313,7 +1307,6 @@ bool LLAppViewer::mainLoop()  		// Create IO Pump to use for HTTP Requests.  		gServicePump = new LLPumpIO(gAPRPoolp); -		LLCurl::setCAFile(gDirUtilp->getCAFile());  		// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. @@ -3348,7 +3341,7 @@ LLSD LLAppViewer::getViewerInfo() const  #endif  	info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION)); -	info["LIBCURL_VERSION"] = LLCurl::getVersionString(); +	info["LIBCURL_VERSION"] = LLCore::LLHttp::getCURLVersion();  	info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();  	bool want_fullname = true;  	info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 01c9416973..7bd01f6beb 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -48,7 +48,6 @@  // Linden library includes  #include "llaudioengine.h"  #include "llbutton.h" -#include "llcurl.h"  #include "llglheaders.h"  #include "llfloater.h"  #include "llfloaterreg.h" diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index e2e151eb63..6a2daeeb90 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -25,9 +25,23 @@   */  #include "llviewerprecompiledheaders.h" -  #include "llhttpretrypolicy.h" +namespace +{ +    // Moved from httpconstants.h... only used in this file. +    bool isHttpServerErrorStatus(S32 status) +    { +        // Status 499 is sometimes used for re-interpreted status 2xx errors. +        // Allow retry of these, since we don't have enough information in this +        // context to know if this will always fail. +        if (HTTP_INTERNAL_ERROR == status) return true; + +        // Check for status 5xx. +        return((500 <= status) && (status < 600)); +    } +} +  LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):  	mMinDelay(min_delay),  	mMaxDelay(max_delay), @@ -140,3 +154,34 @@ bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const  	seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;  	return mShouldRetry;  } + +// Moved from httpconstants.  Only used by this file. +// Parses 'Retry-After' header contents and returns seconds until retry should occur. +/*static*/ +bool LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait) +{ +    // *TODO:  This needs testing!   Not in use yet. +    // Examples of Retry-After headers: +    // Retry-After: Fri, 31 Dec 1999 23:59:59 GMT +    // Retry-After: 120 + +    // Check for number of seconds version, first: +    char* end = 0; +    // Parse as double +    double seconds = std::strtod(retry_after.c_str(), &end); +    if (end != 0 && *end == 0) +    { +        // Successful parse +        seconds_to_wait = (F32)seconds; +        return true; +    } + +    // Parse rfc1123 date. +    time_t date = curl_getdate(retry_after.c_str(), NULL); +    if (-1 == date) return false; + +    seconds_to_wait = (F64)date - LLTimer::getTotalSeconds(); + +    return true; +} + diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index c0cc263546..af07b4afec 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -76,6 +76,8 @@ public:  	// virtual  	bool shouldRetry(F32& seconds_to_wait) const; +    static bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait); +  protected:  	void init();  	bool getRetryAfter(const LLSD& headers, F32& retry_header_time); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index e8977bc7d7..a74e3b69f4 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -35,7 +35,6 @@  #include "llassettype.h"  #include "llfoldertype.h"  #include "llframetimer.h" -#include "llcurl.h"  #include "lluuid.h"  #include "llpermissionsflags.h"  #include "llviewerinventory.h" diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index b8ff76aa6d..bfd0700a2f 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -631,14 +631,8 @@ void LLMediaDataClient::Handler::onFailure(LLCore::HttpResponse * response, LLCo      if (status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE))      {          F32 retry_timeout; -#if 0 -        // *TODO: Honor server Retry-After header. -        if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER) -            || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout)) -#endif -        { -            retry_timeout = mRequest->getRetryTimerDelay(); -        } + +        retry_timeout = mRequest->getRetryTimerDelay();          mRequest->incRetryCount(); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 5bd9df54e2..40de31b9af 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -36,7 +36,6 @@  #include "llappviewer.h"  #include "llbufferstream.h"  #include "llcallbacklist.h" -#include "llcurl.h"  #include "lldatapacker.h"  #include "lldeadmantimer.h"  #include "llfloatermodelpreview.h" diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index f972b320c3..bd23478694 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -40,7 +40,6 @@  #include "llcheckboxctrl.h"  #include "llcommandhandler.h"		// for secondlife:///app/login/  #include "llcombobox.h" -#include "llcurl.h"  #include "llviewercontrol.h"  #include "llfloaterpreference.h"  #include "llfocusmgr.h" diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index e569175e8f..50233eee5e 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -37,7 +37,6 @@  #include "lltextureinfo.h"  #include "llapr.h"  #include "llimageworker.h" -#include "llcurl.h"  #include "httprequest.h"  #include "httpoptions.h"  #include "httpheaders.h" diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 5828aee7fc..442ed73c2d 100755 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -34,8 +34,8 @@  #include "llxmlrpctransaction.h"  #include "llxmlrpclistener.h" -#include "llcurl.h"  #include "httpcommon.h" +#include "llhttpconstants.h"  #include "httprequest.h"  #include "httpoptions.h"  #include "httpheaders.h" diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 03712c1065..57e2faca5b 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -105,7 +105,6 @@  #include "llspatialpartition.h"  #include "llmutelist.h"  #include "lltoolpie.h" -#include "llcurl.h"  #include "llnotifications.h"  #include "llpathinglib.h"  #include "llfloaterpathfindingconsole.h" diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 8bd6cc2690..21c83184dc 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -234,13 +234,13 @@ void RetryPolicyTestObject::test<6>()  	std::string str1("0");  	seconds_to_wait = F32_MAX; -	success = getSecondsUntilRetryAfter(str1, seconds_to_wait); +    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str1, seconds_to_wait);  	ensure("parse 1", success);  	ensure_equals("parse 1", seconds_to_wait, 0.0);  	std::string str2("999.9");  	seconds_to_wait = F32_MAX; -	success = getSecondsUntilRetryAfter(str2, seconds_to_wait); +    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str2, seconds_to_wait);  	ensure("parse 2", success);  	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8); @@ -248,7 +248,7 @@ void RetryPolicyTestObject::test<6>()  	time(&nowseconds);  	std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123();  	seconds_to_wait = F32_MAX; -	success = getSecondsUntilRetryAfter(str3, seconds_to_wait); +    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str3, seconds_to_wait);  	std::cerr << " str3 [" << str3 << "]" << std::endl;  	ensure("parse 3", success);  	ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F); diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index aa23699de0..8718360f0c 100755 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -28,7 +28,7 @@  #include <tut/tut.hpp>  #include "linden_common.h"  #include "lltut.h" - +#include "llhttpconstants.h"  #include "llapr.h"  #include "llmessageconfig.h"  #include "llsdserialize.h" diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index f868e5cc2c..53c729469b 100755 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -26,7 +26,7 @@  #include "linden_common.h"  #include "llupdatedownloader.h" - +#include "httpcommon.h"  #include <stdexcept>  #include <boost/format.hpp>  #include <boost/lexical_cast.hpp> @@ -39,7 +39,6 @@  #include "llsdserialize.h"  #include "llthread.h"  #include "llupdaterservice.h" -#include "llcurl.h"  class LLUpdateDownloader::Implementation:  	public LLThread @@ -65,7 +64,7 @@ private:  	curl_off_t mBandwidthLimit;  	bool mCancelled;  	LLUpdateDownloader::Client & mClient; -	CURL * mCurl; +	LLCore::LLHttp::CURL_ptr mCurl;  	LLSD mDownloadData;  	llofstream mDownloadStream;  	unsigned char mDownloadPercent; @@ -192,7 +191,7 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &  	mBandwidthLimit(0),  	mCancelled(false),  	mClient(client), -	mCurl(0), +	mCurl(),  	mDownloadPercent(0),  	mHeaderList(0)  { @@ -212,10 +211,7 @@ LLUpdateDownloader::Implementation::~Implementation()  	{  		; // No op.  	} -	if(mCurl) -	{ -		LLCurl::deleteEasyHandle(mCurl); -	} +    mCurl.reset();  } @@ -331,9 +327,9 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond)  {  	if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean())  	{ -		llassert(mCurl != 0); +		llassert(static_cast<bool>(mCurl));  		mBandwidthLimit = bytesPerSecond; -		CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); +		CURLcode code = curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);  		if(code != CURLE_OK)  		{  			LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL; @@ -416,7 +412,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b  void LLUpdateDownloader::Implementation::run(void)  { -	CURLcode code = curl_easy_perform(mCurl); +    CURLcode code = curl_easy_perform(mCurl.get());  	mDownloadStream.close();  	if(code == CURLE_OK)  	{ @@ -460,36 +456,36 @@ void LLUpdateDownloader::Implementation::run(void)  void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)  { -	if(mCurl == 0) +	if(!mCurl)  	{ -		mCurl = LLCurl::newEasyHandle(); +		mCurl = LLCore::LLHttp::createEasyHandle();  	}  	else  	{ -		curl_easy_reset(mCurl); +        curl_easy_reset(mCurl.get());  	} -	if(mCurl == 0) +	if(!mCurl)  	{  		throw DownloadError("failed to initialize curl");  	} -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this)); +    throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEFUNCTION, &write_function)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEDATA, this));  	if(processHeader)  	{ -	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function)); -	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this)); -	} -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this)); -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false)); +	   throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERFUNCTION, &header_function)); +	   throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERDATA, this)); +	} +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPGET, true)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_URL, url.c_str())); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_PROGRESSFUNCTION, &progress_callback)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_PROGRESSDATA, this)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOPROGRESS, false));  	// if it's a required update set the bandwidth limit to 0 (unlimited)  	curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit; -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, limit)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, limit));  	mDownloadPercent = 0;  } @@ -511,7 +507,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)  	{  		throw DownloadError("cannot add Range header");  	} -	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList)); +	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));  	mDownloadStream.open(mDownloadData["path"].asString().c_str(),  						 std::ios_base::out | std::ios_base::binary | std::ios_base::app); | 
