diff options
24 files changed, 702 insertions, 163 deletions
| diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index a0827286e3..4273b32fe3 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -10,12 +10,14 @@ include(OpenSSL)  include(ZLIB)  include(LLCoreHttp)  include(LLAddBuildTest) +include(LLMessage)  include(LLCommon)  include(Tut)  include_directories (${CMAKE_CURRENT_SOURCE_DIR})  include_directories( +    ${LLMESSAGE_INCLUDE_DIRS}      ${LLCOMMON_INCLUDE_DIRS}      ${LLCOREHTTP_INCLUDE_DIRS}      ) @@ -31,6 +33,7 @@ set(llcorehttp_SOURCE_FILES      _httpopcancel.cpp      _httpoperation.cpp      _httpoprequest.cpp +    _httpopsetget.cpp      _httpopsetpriority.cpp      _httppolicy.cpp      _httppolicyglobal.cpp @@ -54,6 +57,7 @@ set(llcorehttp_HEADER_FILES      _httpopcancel.h      _httpoperation.h      _httpoprequest.h +    _httpopsetget.h      _httpopsetpriority.h      _httppolicy.h      _httppolicyglobal.h @@ -113,6 +117,7 @@ if (LL_TESTS)    set(test_libs        ${LLCOREHTTP_LIBRARIES}        ${WINDOWS_LIBRARIES} +      ${LLMESSAGE_LIBRARIES}        ${LLCOMMON_LIBRARIES}        ${GOOGLEMOCK_LIBRARIES}        ${CURL_LIBRARIES} diff --git a/indra/llcorehttp/_httpopcancel.cpp b/indra/llcorehttp/_httpopcancel.cpp index 69dbff4bb4..ad624d2e57 100644 --- a/indra/llcorehttp/_httpopcancel.cpp +++ b/indra/llcorehttp/_httpopcancel.cpp @@ -66,17 +66,6 @@ void HttpOpCancel::stageFromRequest(HttpService * service)  } -void HttpOpCancel::visitNotifier(HttpRequest * request) -{ -	if (mLibraryHandler) -	{ -		HttpResponse * response = new HttpResponse(); -		mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response); -		response->release(); -	} -} - -  }   // end namespace LLCore diff --git a/indra/llcorehttp/_httpopcancel.h b/indra/llcorehttp/_httpopcancel.h index fab6f1f362..6d1e0f8774 100644 --- a/indra/llcorehttp/_httpopcancel.h +++ b/indra/llcorehttp/_httpopcancel.h @@ -59,13 +59,10 @@ private:  public:  	virtual void stageFromRequest(HttpService *); - -	virtual void visitNotifier(HttpRequest * request);  public:  	// Request data  	HttpHandle			mHandle; -  };  // end class HttpOpCancel diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp index d966efd12b..b5c58013d4 100644 --- a/indra/llcorehttp/_httpoperation.cpp +++ b/indra/llcorehttp/_httpoperation.cpp @@ -47,7 +47,6 @@ namespace LLCore  HttpOperation::HttpOperation()  	: LLCoreInt::RefCounted(true),  	  mReplyQueue(NULL), -	  mLibraryHandler(NULL),  	  mUserHandler(NULL),  	  mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),  	  mReqPriority(0U) @@ -57,13 +56,12 @@ HttpOperation::HttpOperation()  HttpOperation::~HttpOperation()  { -	setHandlers(NULL, NULL, NULL); +	setReplyPath(NULL, NULL);  } -void HttpOperation::setHandlers(HttpReplyQueue * reply_queue, -								HttpHandler * lib_handler, -								HttpHandler * user_handler) +void HttpOperation::setReplyPath(HttpReplyQueue * reply_queue, +								 HttpHandler * user_handler)  {  	if (reply_queue != mReplyQueue)  	{ @@ -81,9 +79,6 @@ void HttpOperation::setHandlers(HttpReplyQueue * reply_queue,  	}  	// Not refcounted -	mLibraryHandler = lib_handler; - -	// Not refcounted  	mUserHandler = user_handler;  } @@ -121,11 +116,12 @@ void HttpOperation::stageFromActive(HttpService *)  void HttpOperation::visitNotifier(HttpRequest *)  { -	if (mLibraryHandler) +	if (mUserHandler)  	{  		HttpResponse * response = new HttpResponse(); -		mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response); +		response->setStatus(mStatus); +		mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);  		response->release();  	} @@ -142,7 +138,7 @@ HttpStatus HttpOperation::cancel()  void HttpOperation::addAsReply()  { -	if (mReplyQueue && mLibraryHandler) +	if (mReplyQueue)  	{  		addRef();  		mReplyQueue->addOp(this); diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h index 01e26029d2..c93aa2def9 100644 --- a/indra/llcorehttp/_httpoperation.h +++ b/indra/llcorehttp/_httpoperation.h @@ -80,9 +80,8 @@ private:  	void operator=(const HttpOperation &);				// Not defined  public: -	void setHandlers(HttpReplyQueue * reply_queue, -					 HttpHandler * lib_handler, -					 HttpHandler * user_handler); +	void setReplyPath(HttpReplyQueue * reply_queue, +					  HttpHandler * handler);  	HttpHandler * getUserHandler() const  		{ @@ -102,13 +101,15 @@ protected:  protected:  	HttpReplyQueue *			mReplyQueue;			// Have refcount -	HttpHandler *				mLibraryHandler;		// Have refcount -	HttpHandler *				mUserHandler;			// Have refcount +	HttpHandler *				mUserHandler;  public: +	// Request Data  	HttpRequest::policy_t		mReqPolicy;  	HttpRequest::priority_t		mReqPriority; -	 + +	// Reply Data +	HttpStatus					mStatus;  };  // end class HttpOperation diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index ea0b99303e..e2550d057e 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -44,6 +44,7 @@  #include "_httplibcurl.h"  #include "llhttpstatuscodes.h" +#include "llproxy.h"  namespace  { @@ -207,7 +208,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)  {  	static const HttpStatus partial_content(HTTP_PARTIAL_CONTENT, HE_SUCCESS); -	if (mLibraryHandler) +	if (mUserHandler)  	{  		HttpResponse * response = new HttpResponse();  		response->setStatus(mStatus); @@ -219,7 +220,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)  			response->setRange(mReplyOffset, mReplyLength);  		} -		mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response); +		mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);  		response->release();  	} @@ -304,6 +305,39 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,  } +HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id, +								   HttpRequest::priority_t priority, +								   const std::string & url, +								   BufferArray * body, +								   HttpOptions * options, +								   HttpHeaders * headers) +{ +	HttpStatus status; + +	mProcFlags = 0; +	mReqPolicy = policy_id; +	mReqPriority = priority; +	mReqMethod = HOR_PUT; +	mReqURL = url; +	if (body) +	{ +		body->addRef(); +		mReqBody = body; +	} +	if (headers && ! mReqHeaders) +	{ +		headers->addRef(); +		mReqHeaders = headers; +	} +	if (options && ! mReqOptions) +	{ +		mReqOptions = new HttpOptions(*options); +	} +	 +	return status; +} + +  HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  {  	// Scrub transport and result data for retried op case @@ -346,8 +380,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());  	curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);  	curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); -	// *FIXME:  Need to deal with proxy setup... -	// curl_easy_setopt(handle, CURLOPT_PROXY, "");  	// *FIXME:  Revisit this old DNS timeout setting - may no longer be valid  	curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); @@ -361,18 +393,31 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);  	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0); -	std::string opt_value; +	const std::string * opt_value(NULL);  	if (policy.get(HttpRequest::GP_CA_PATH, opt_value))  	{ -		curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, opt_value.c_str()); +		curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, opt_value->c_str());  	}  	if (policy.get(HttpRequest::GP_CA_FILE, opt_value))  	{ -		curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, opt_value.c_str()); +		curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, opt_value->c_str());  	}  	if (policy.get(HttpRequest::GP_HTTP_PROXY, opt_value))  	{ -		curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value.c_str()); +		if (*opt_value == "LLProxy") +		{ +			// Use the viewer-based thread-safe API which has a +			// fast/safe check for proxy enable.  Would like to +			// encapsulate this someway... +			LLProxy::getInstance()->applyProxySettings(mCurlHandle); +		} +		else +		{ +			// *TODO:  This is fine for now but get fuller socks/ +			// authentication thing going later.... +			curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value->c_str()); +			curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); +		}  	}  	switch (mReqMethod) @@ -394,7 +439,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  			}  			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));  			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size); -			mCurlHeaders = curl_slist_append(mCurlHeaders, "Transfer-Encoding: chunked");  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");  		}  		break; @@ -409,7 +453,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  			}  			curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);  			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL); -			mCurlHeaders = curl_slist_append(mCurlHeaders, "Transfer-Encoding: chunked");  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300"); diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index 6dcf30ca0c..80893beb40 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -91,6 +91,13 @@ public:  						 HttpOptions * options,  						 HttpHeaders * headers); +	HttpStatus setupPut(HttpRequest::policy_t policy_id, +						HttpRequest::priority_t priority, +						const std::string & url, +						BufferArray * body, +						HttpOptions * options, +						HttpHeaders * headers); +	  	HttpStatus prepareRequest(HttpService * service);  	virtual HttpStatus cancel(); diff --git a/indra/llcorehttp/_httpopsetget.cpp b/indra/llcorehttp/_httpopsetget.cpp new file mode 100644 index 0000000000..21e058b2be --- /dev/null +++ b/indra/llcorehttp/_httpopsetget.cpp @@ -0,0 +1,105 @@ +/** + * @file _httpopsetget.cpp + * @brief Definitions for internal class HttpOpSetGet + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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$ + */ + +#include "_httpopsetget.h" + +#include <cstdio> +#include <algorithm> + +#include "httpcommon.h" +#include "httphandler.h" +#include "httpresponse.h" + +#include "_httprequestqueue.h" +#include "_httpreplyqueue.h" +#include "_httpservice.h" +#include "_httppolicy.h" +#include "_httplibcurl.h" + + +namespace LLCore +{ + + +// ================================== +// HttpOpSetget +// ================================== + + +HttpOpSetGet::HttpOpSetGet() +	: HttpOperation(), +	  mIsGlobal(false), +	  mDoSet(false), +	  mSetting(-1),				// Nothing requested +	  mLongValue(0L) +{} + + +HttpOpSetGet::~HttpOpSetGet() +{} + + +void HttpOpSetGet::setupGet(HttpRequest::EGlobalPolicy setting) +{ +	mIsGlobal = true; +	mSetting = setting; +} + + +void HttpOpSetGet::setupSet(HttpRequest::EGlobalPolicy setting, const std::string & value) +{ +	mIsGlobal = true; +	mDoSet = true; +	mSetting = setting; +	mStrValue = value; +} + + +void HttpOpSetGet::stageFromRequest(HttpService * service) +{ +	HttpPolicyGlobal & pol_opt(service->getPolicy().getGlobalOptions()); +	HttpRequest::EGlobalPolicy setting(static_cast<HttpRequest::EGlobalPolicy>(mSetting)); +	 +	if (mDoSet) +	{ +		mStatus = pol_opt.set(setting, mStrValue); +	} +	if (mStatus) +	{ +		const std::string * value; +		if ((mStatus = pol_opt.get(setting, value))) +		{ +			mStrValue = *value; +		} +	} +	 +	addAsReply(); +} + + +}   // end namespace LLCore + +		 diff --git a/indra/llcorehttp/_httpopsetget.h b/indra/llcorehttp/_httpopsetget.h new file mode 100644 index 0000000000..e065eb4c30 --- /dev/null +++ b/indra/llcorehttp/_httpopsetget.h @@ -0,0 +1,78 @@ +/** + * @file _httpopsetget.h + * @brief Internal declarations for the HttpOpSetGet subclass + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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	_LLCORE_HTTP_OPSETGET_H_ +#define	_LLCORE_HTTP_OPSETGET_H_ + + +#include "linden_common.h"		// Modifies curl/curl.h interfaces + +#include "httpcommon.h" + +#include <curl/curl.h> + +#include "_httpoperation.h" +#include "_refcounted.h" + + +namespace LLCore +{ + + +/// HttpOpSetGet requests dynamic changes to policy and +/// configuration settings. + +class HttpOpSetGet : public HttpOperation +{ +public: +	HttpOpSetGet(); +	virtual ~HttpOpSetGet(); + +private: +	HttpOpSetGet(const HttpOpSetGet &);					// Not defined +	void operator=(const HttpOpSetGet &);				// Not defined + +public: +	void setupGet(HttpRequest::EGlobalPolicy setting); +	void setupSet(HttpRequest::EGlobalPolicy setting, const std::string & value); + +	virtual void stageFromRequest(HttpService *); + +public: +	// Request data +	bool				mIsGlobal; +	bool				mDoSet; +	int					mSetting; +	long				mLongValue; +	std::string			mStrValue; + +};  // end class HttpOpSetGet + + +}   // end namespace LLCore + +#endif	// _LLCORE_HTTP_OPSETGET_H_ + diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp index b0ee577087..d48c7a0b7d 100644 --- a/indra/llcorehttp/_httpopsetpriority.cpp +++ b/indra/llcorehttp/_httpopsetpriority.cpp @@ -60,18 +60,4 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service)  } -void HttpOpSetPriority::visitNotifier(HttpRequest * request) -{ -	if (mLibraryHandler) -	{ -		HttpResponse * response = new HttpResponse(); - -		response->setStatus(mStatus); -		mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response); - -		response->release(); -	} -} - -  }   // end namespace LLCore diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h index b972f50fff..f1e94b6e43 100644 --- a/indra/llcorehttp/_httpopsetpriority.h +++ b/indra/llcorehttp/_httpopsetpriority.h @@ -56,10 +56,8 @@ private:  public:  	virtual void stageFromRequest(HttpService *); -	virtual void visitNotifier(HttpRequest * request); -  protected: -	HttpStatus					mStatus; +	// Request Data  	HttpHandle					mHandle;  	HttpRequest::priority_t		mPriority;  }; // end class HttpOpSetPriority diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index 72bb6f14e4..8ee3f88658 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -71,6 +71,12 @@ HttpPolicy::~HttpPolicy()  } +void HttpPolicy::setPolicies(const HttpPolicyGlobal & global) +{ +	mGlobalOptions = global; +} + +  void HttpPolicy::addOp(HttpOpRequest * op)  {  	const int policy_class(op->mReqPolicy); diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h index 14f6a9a676..73c22bab78 100644 --- a/indra/llcorehttp/_httppolicy.h +++ b/indra/llcorehttp/_httppolicy.h @@ -95,7 +95,9 @@ public:  		{  			return mGlobalOptions;  		} -	 + +	void setPolicies(const HttpPolicyGlobal & global); +			  protected:  	struct State  	{ diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp index 877b85896f..d95d73cfba 100644 --- a/indra/llcorehttp/_httppolicyglobal.cpp +++ b/indra/llcorehttp/_httppolicyglobal.cpp @@ -32,7 +32,7 @@ namespace LLCore  HttpPolicyGlobal::HttpPolicyGlobal() -	: mValidMask(0UL), +	: mSetMask(0UL),  	  mConnectionLimit(32L)  {} @@ -41,6 +41,20 @@ HttpPolicyGlobal::~HttpPolicyGlobal()  {} +HttpPolicyGlobal & HttpPolicyGlobal::operator=(const HttpPolicyGlobal & other) +{ +	if (this != &other) +	{ +		mSetMask = other.mSetMask; +		mConnectionLimit = other.mConnectionLimit; +		mCAPath = other.mCAPath; +		mCAFile = other.mCAFile; +		mHttpProxy = other.mHttpProxy; +	} +	return *this; +} + +  HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, long value)  {  	switch (opt) @@ -53,7 +67,7 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, long value)  		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);  	} -	mValidMask |= 1UL << int(opt); +	mSetMask |= 1UL << int(opt);  	return HttpStatus();  } @@ -78,7 +92,7 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, const std::stri  		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);  	} -	mValidMask |= 1UL << int(opt); +	mSetMask |= 1UL << int(opt);  	return HttpStatus();  } @@ -90,7 +104,7 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, long & value)  	switch (opt)  	{  	case HttpRequest::GP_CONNECTION_LIMIT: -		if (! (mValidMask & (1UL << int(opt)))) +		if (! (mSetMask & (1UL << int(opt))))  			return not_set;  		value = mConnectionLimit;  		break; @@ -103,28 +117,28 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, long & value)  } -HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, std::string & value) +HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, const std::string *& value)  {  	static const HttpStatus not_set(HttpStatus::LLCORE, HE_OPT_NOT_SET); -	 +  	switch (opt)  	{  	case HttpRequest::GP_CA_PATH: -		if (! (mValidMask & (1UL << int(opt)))) +		if (! (mSetMask & (1UL << int(opt))))  			return not_set; -		value = mCAPath; +		value = &mCAPath;  		break;  	case HttpRequest::GP_CA_FILE: -		if (! (mValidMask & (1UL << int(opt)))) +		if (! (mSetMask & (1UL << int(opt))))  			return not_set; -		value = mCAFile; +		value = &mCAFile;  		break;  	case HttpRequest::GP_HTTP_PROXY: -		if (! (mValidMask & (1UL << int(opt)))) +		if (! (mSetMask & (1UL << int(opt))))  			return not_set; -		value = mHttpProxy; +		value = &mHttpProxy;  		break;  	default: diff --git a/indra/llcorehttp/_httppolicyglobal.h b/indra/llcorehttp/_httppolicyglobal.h index 39ffbcb9bb..f4bb4d4b25 100644 --- a/indra/llcorehttp/_httppolicyglobal.h +++ b/indra/llcorehttp/_httppolicyglobal.h @@ -40,18 +40,19 @@ public:  	HttpPolicyGlobal();  	~HttpPolicyGlobal(); +	HttpPolicyGlobal & operator=(const HttpPolicyGlobal &); +	  private:  	HttpPolicyGlobal(const HttpPolicyGlobal &);			// Not defined -	void operator=(const HttpPolicyGlobal &);			// Not defined  public:  	HttpStatus set(HttpRequest::EGlobalPolicy opt, long value);  	HttpStatus set(HttpRequest::EGlobalPolicy opt, const std::string & value);  	HttpStatus get(HttpRequest::EGlobalPolicy opt, long & value); -	HttpStatus get(HttpRequest::EGlobalPolicy opt, std::string & value); +	HttpStatus get(HttpRequest::EGlobalPolicy opt, const std::string *& value);  public: -	unsigned long		mValidMask; +	unsigned long		mSetMask;  	long				mConnectionLimit;  	std::string			mCAPath;  	std::string			mCAFile; diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index b038bdb720..920a3f3b6d 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -79,11 +79,8 @@ HttpService::~HttpService()  		mTransport = NULL;  	} -	if (mPolicy) -	{ -		delete mPolicy; -		mPolicy = NULL; -	} +	delete mPolicy; +	mPolicy = NULL;  	if (mThread)  	{ @@ -145,6 +142,10 @@ void HttpService::startThread()  	{  		mThread->release();  	} + +	// Push current policy definitions +	mPolicy->setPolicies(mPolicyGlobal); +	  	mThread = new LLCoreInt::HttpThread(boost::bind(&HttpService::threadRun, this, _1));  	mThread->addRef();		// Need an explicit reference, implicit one is used internally  	sState = RUNNING; diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h index 748354a8e4..3f953ec1a7 100644 --- a/indra/llcorehttp/_httpservice.h +++ b/indra/llcorehttp/_httpservice.h @@ -30,6 +30,7 @@  #include "httpcommon.h"  #include "httprequest.h" +#include "_httppolicyglobal.h"  namespace LLCoreInt @@ -157,6 +158,11 @@ public:  		{  			return *mTransport;  		} + +	HttpPolicyGlobal & getGlobalOptions() +		{ +			return mPolicyGlobal; +		}  protected:  	void threadRun(LLCoreInt::HttpThread * thread); @@ -173,11 +179,11 @@ protected:  	// === calling-thread-only data ===  	LLCoreInt::HttpThread *		mThread; - +	HttpPolicyGlobal			mPolicyGlobal; +	  	// === working-thread-only data ===  	HttpPolicy *				mPolicy;		// Simple pointer, has ownership  	HttpLibcurl *				mTransport;		// Simple pointer, has ownership -	  };  // end class HttpService  }  // end namespace LLCore diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp index 2f36168f8b..089eee76f3 100644 --- a/indra/llcorehttp/httprequest.cpp +++ b/indra/llcorehttp/httprequest.cpp @@ -34,6 +34,7 @@  #include "_httpoprequest.h"  #include "_httpopsetpriority.h"  #include "_httpopcancel.h" +#include "_httpopsetget.h"  #include "lltimer.h" @@ -49,39 +50,6 @@ namespace LLCore  {  // ==================================== -// InternalHandler Implementation -// ==================================== - - -class HttpRequest::InternalHandler : public HttpHandler -{ -public: -	InternalHandler(HttpRequest & request) -		: mRequest(request) -		{} - -protected: -	InternalHandler(const InternalHandler &);			// Not defined -	void operator=(const InternalHandler &);			// Not defined - -public: -	void onCompleted(HttpHandle handle, HttpResponse * response) -		{ -			HttpOperation * op(static_cast<HttpOperation *>(handle)); -			HttpHandler * user_handler(op->getUserHandler()); -			if (user_handler) -			{ -				user_handler->onCompleted(handle, response); -			} -		} - -protected: -	HttpRequest &		mRequest; -	 -};  // end class HttpRequest::InternalHandler - - -// ====================================  // HttpRequest Implementation  // ==================================== @@ -92,15 +60,12 @@ HttpRequest::policy_t HttpRequest::sNextPolicyID(1);  HttpRequest::HttpRequest()  	: //HttpHandler(),  	  mReplyQueue(NULL), -	  mRequestQueue(NULL), -	  mSelfHandler(NULL) +	  mRequestQueue(NULL)  {  	mRequestQueue = HttpRequestQueue::instanceOf();  	mRequestQueue->addRef();  	mReplyQueue = new HttpReplyQueue(); - -	mSelfHandler = new InternalHandler(*this);  } @@ -117,9 +82,6 @@ HttpRequest::~HttpRequest()  		mReplyQueue->release();  		mReplyQueue = NULL;  	} - -	delete mSelfHandler; -	mSelfHandler = NULL;  } @@ -132,7 +94,7 @@ HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, long value)  {  	// *FIXME:  Fail if thread is running. -	return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value); +	return HttpService::instanceOf()->getGlobalOptions().set(opt, value);  } @@ -140,7 +102,7 @@ HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, const std::stri  {  	// *FIXME:  Fail if thread is running. -	return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value); +	return HttpService::instanceOf()->getGlobalOptions().set(opt, value);  } @@ -192,7 +154,7 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,  		mLastReqStatus = status;  		return handle;  	} -	op->setHandlers(mReplyQueue, mSelfHandler, user_handler); +	op->setReplyPath(mReplyQueue, user_handler);  	mRequestQueue->addOp(op);			// transfers refcount  	mLastReqStatus = status; @@ -220,7 +182,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,  		mLastReqStatus = status;  		return handle;  	} -	op->setHandlers(mReplyQueue, mSelfHandler, user_handler); +	op->setReplyPath(mReplyQueue, user_handler);  	mRequestQueue->addOp(op);			// transfers refcount  	mLastReqStatus = status; @@ -230,19 +192,31 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,  } -HttpHandle HttpRequest::requestCancel(HttpHandle handle, HttpHandler * user_handler) +HttpHandle HttpRequest::requestPut(policy_t policy_id, +								   priority_t priority, +								   const std::string & url, +								   BufferArray * body, +								   HttpOptions * options, +								   HttpHeaders * headers, +								   HttpHandler * user_handler)  {  	HttpStatus status; -	HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID); - -	HttpOpCancel * op = new HttpOpCancel(handle); -	op->setHandlers(mReplyQueue, mSelfHandler, user_handler); -	mRequestQueue->addOp(op);			// transfer refcount as well +	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); +	HttpOpRequest * op = new HttpOpRequest(); +	if (! (status = op->setupPut(policy_id, priority, url, body, options, headers))) +	{ +		op->release(); +		mLastReqStatus = status; +		return handle; +	} +	op->setReplyPath(mReplyQueue, user_handler); +	mRequestQueue->addOp(op);			// transfers refcount +	  	mLastReqStatus = status; -	ret_handle = static_cast<HttpHandle>(op); +	handle = static_cast<HttpHandle>(op); -	return ret_handle; +	return handle;  } @@ -252,7 +226,7 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)  	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);  	HttpOpNull * op = new HttpOpNull(); -	op->setHandlers(mReplyQueue, mSelfHandler, user_handler); +	op->setReplyPath(mReplyQueue, user_handler);  	mRequestQueue->addOp(op);			// transfer refcount as well  	mLastReqStatus = status; @@ -262,23 +236,6 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)  } -HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority, -										   HttpHandler * handler) -{ -	HttpStatus status; -	HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID); - -	HttpOpSetPriority * op = new HttpOpSetPriority(request, priority); -	op->setHandlers(mReplyQueue, mSelfHandler, handler); -	mRequestQueue->addOp(op);			// transfer refcount as well - -	mLastReqStatus = status; -	ret_handle = static_cast<HttpHandle>(op); -	 -	return ret_handle; -} - -  HttpStatus HttpRequest::update(long millis)  {  	const HttpTime limit(totalTime() + (1000 * HttpTime(millis))); @@ -302,6 +259,38 @@ HttpStatus HttpRequest::update(long millis)  // Request Management Methods  // ==================================== +HttpHandle HttpRequest::requestCancel(HttpHandle handle, HttpHandler * user_handler) +{ +	HttpStatus status; +	HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID); + +	HttpOpCancel * op = new HttpOpCancel(handle); +	op->setReplyPath(mReplyQueue, user_handler); +	mRequestQueue->addOp(op);			// transfer refcount as well + +	mLastReqStatus = status; +	ret_handle = static_cast<HttpHandle>(op); +	 +	return ret_handle; +} + + +HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority, +										   HttpHandler * handler) +{ +	HttpStatus status; +	HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID); + +	HttpOpSetPriority * op = new HttpOpSetPriority(request, priority); +	op->setReplyPath(mReplyQueue, handler); +	mRequestQueue->addOp(op);			// transfer refcount as well + +	mLastReqStatus = status; +	ret_handle = static_cast<HttpHandle>(op); +	 +	return ret_handle; +} +  // ====================================  // Utility Methods @@ -350,7 +339,27 @@ HttpHandle HttpRequest::requestStopThread(HttpHandler * user_handler)  	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);  	HttpOpStop * op = new HttpOpStop(); -	op->setHandlers(mReplyQueue, mSelfHandler, user_handler); +	op->setReplyPath(mReplyQueue, user_handler); +	mRequestQueue->addOp(op);			// transfer refcount as well + +	mLastReqStatus = status; +	handle = static_cast<HttpHandle>(op); + +	return handle; +} + +// ==================================== +// Dynamic Policy Methods +// ==================================== + +HttpHandle HttpRequest::requestSetHttpProxy(const std::string & proxy, HttpHandler * handler) +{ +	HttpStatus status; +	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); + +	HttpOpSetGet * op = new HttpOpSetGet(); +	op->setupSet(GP_HTTP_PROXY, proxy); +	op->setReplyPath(mReplyQueue, handler);  	mRequestQueue->addOp(op);			// transfer refcount as well  	mLastReqStatus = status; diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h index 01dbfba6dd..a953aa28d0 100644 --- a/indra/llcorehttp/httprequest.h +++ b/indra/llcorehttp/httprequest.h @@ -124,8 +124,8 @@ public:  	/// @param opt		Enum of option to be set.  	/// @param value	Desired value of option.  	/// @return			Standard status code. -	HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, long value); -	HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value); +	static HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, long value); +	static HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value);  	/// Create a new policy class into which requests can be made.  	/// @@ -236,6 +236,32 @@ public:  						   HttpHandler * handler); +	/// +	/// @param	policy_id		Default or user-defined policy class under +	///							which this request is to be serviced. +	/// @param	priority		Standard priority scheme inherited from +	///							Indra code base. +	/// @param	url +	/// @param	body			Byte stream to be sent as the body.  No +	///							further encoding or escaping will be done +	///							to the content. +	/// @param	options			(optional) +	/// @param	headers			(optional) +	/// @param	handler			(optional) +	/// @return					The handle of the request if successfully +	///							queued or LLCORE_HTTP_HANDLE_INVALID if the +	///							request could not be queued.  In the latter +	///							case, @see getStatus() will return more info. +	/// +	HttpHandle requestPut(policy_t policy_id, +						  priority_t priority, +						  const std::string & url, +						  BufferArray * body, +						  HttpOptions * options, +						  HttpHeaders * headers, +						  HttpHandler * handler); + +  	/// Queue a NoOp request.  	/// The request is queued and serviced by the working thread which  	/// immediately processes it and returns the request to the reply @@ -325,13 +351,20 @@ public:  	HttpHandle requestStopThread(HttpHandler * handler);  	/// @} +	 +	/// @name DynamicPolicyMethods +	/// +	/// @{ + +	/// Request that a running transport pick up a new proxy setting. +	/// An empty string will indicate no proxy is to be used. +	HttpHandle requestSetHttpProxy(const std::string & proxy, HttpHandler * handler); + +    /// @}  protected:  	void generateNotification(HttpOperation * op); -	class InternalHandler; -	friend class InternalHandler; -  private:  	/// @name InstanceData  	/// @@ -339,7 +372,6 @@ private:  	HttpStatus			mLastReqStatus;  	HttpReplyQueue *	mReplyQueue;  	HttpRequestQueue *	mRequestQueue; -	InternalHandler *	mSelfHandler;  	/// @} diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp index f59361ab53..2b36d3a982 100644 --- a/indra/llcorehttp/tests/llcorehttp_test.cpp +++ b/indra/llcorehttp/tests/llcorehttp_test.cpp @@ -44,6 +44,8 @@  #include "test_bufferarray.hpp"  #include "test_httprequestqueue.hpp" +#include "llproxy.h" +  unsigned long ssl_thread_id_callback(void);  void ssl_locking_callback(int mode, int type, const char * file, int line); @@ -91,11 +93,15 @@ void init_curl()  		CRYPTO_set_locking_callback(ssl_locking_callback);  		CRYPTO_set_id_callback(ssl_thread_id_callback);  	} + +	LLProxy::getInstance();  }  void term_curl()  { +	LLProxy::cleanupClass(); +	  	CRYPTO_set_locking_callback(NULL);  	for (int i(0); i < ssl_mutex_count; ++i)  	{ diff --git a/indra/llcorehttp/tests/test_httpoperation.hpp b/indra/llcorehttp/tests/test_httpoperation.hpp index 6c3df1e9e3..17b1a96878 100644 --- a/indra/llcorehttp/tests/test_httpoperation.hpp +++ b/indra/llcorehttp/tests/test_httpoperation.hpp @@ -97,13 +97,12 @@ namespace tut  		// Get some handlers  		TestHandler * h1 = new TestHandler(); -		TestHandler * h2 = new TestHandler();  		// create a new ref counted object with an implicit reference  		HttpOpNull * op = new HttpOpNull();  		// Add the handlers -		op->setHandlers(NULL, h1, h2); +		op->setReplyPath(NULL, h1);  		// Check ref count  		ensure(op->getRefCount() == 1); @@ -117,8 +116,6 @@ namespace tut  		// release the handlers  		delete h1;  		h1 = NULL; -		delete h2; -		h2 = NULL;  		ensure(mMemTotal == GetMemTotal());  	} diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 81f8fe4a85..61698f34d8 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -27,6 +27,7 @@  #define TEST_LLCORE_HTTP_REQUEST_H_  #include "httprequest.h" +#include "bufferarray.h"  #include "httphandler.h"  #include "httpresponse.h"  #include "_httpservice.h" @@ -604,6 +605,244 @@ void HttpRequestTestObjectType::test<6>()  	}  } +template <> template <> +void HttpRequestTestObjectType::test<7>() +{ +	ScopedCurlInit ready; + +	std::string url_base(get_base_url()); +	std::cerr << "Base:  "  << url_base << std::endl; +	 +	set_test_name("HttpRequest PUT to real service"); + +	// Handler can be stack-allocated *if* there are no dangling +	// references to it after completion of this method. +	// Create before memory record as the string copy will bump numbers. +	TestHandler2 handler(this, "handler"); +		 +	// record the total amount of dynamically allocated memory +	mMemTotal = GetMemTotal(); +	mHandlerCalls = 0; + +	HttpRequest * req = NULL; +	BufferArray * body = new BufferArray; +	 +	try +	{ +		// Get singletons created +		HttpRequest::createService(); +		 +		// Start threading early so that thread memory is invariant +		// over the test. +		HttpRequest::startThread(); + +		// create a new ref counted object with an implicit reference +		req = new HttpRequest(); +		ensure("Memory allocated on construction", mMemTotal < GetMemTotal()); + +		// Issue a GET that *can* connect +		static const char * body_text("Now is the time for all good men..."); +		body->append(body_text, strlen(body_text)); +		mStatus = HttpStatus(200); +		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID, +											0U, +											url_base, +											body, +											NULL, +											NULL, +											&handler); +		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID); + +		// Run the notification pump. +		int count(0); +		int limit(10); +		while (count++ < limit && mHandlerCalls < 1) +		{ +			req->update(1000); +			usleep(100000); +		} +		ensure("Request executed in reasonable time", count < limit); +		ensure("One handler invocation for request", mHandlerCalls == 1); + +		// Okay, request a shutdown of the servicing thread +		mStatus = HttpStatus(); +		handle = req->requestStopThread(&handler); +		ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID); +	 +		// Run the notification pump again +		count = 0; +		limit = 10; +		while (count++ < limit && mHandlerCalls < 2) +		{ +			req->update(1000); +			usleep(100000); +		} +		ensure("Second request executed in reasonable time", count < limit); +		ensure("Second handler invocation", mHandlerCalls == 2); + +		// See that we actually shutdown the thread +		count = 0; +		limit = 10; +		while (count++ < limit && ! HttpService::isStopped()) +		{ +			usleep(100000); +		} +		ensure("Thread actually stopped running", HttpService::isStopped()); + +		// Lose the request body +		body->release(); +		body = NULL; +		 +		// release the request object +		delete req; +		req = NULL; + +		// Shut down service +		HttpRequest::destroyService(); +	 +		ensure("Two handler calls on the way out", 2 == mHandlerCalls); + +#if defined(WIN32) +		// Can only do this memory test on Windows.  On other platforms, +		// the LL logging system holds on to memory and produces what looks +		// like memory leaks... +	 +		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal()); +		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); +#endif +	} +	catch (...) +	{ +		if (body) +		{ +			body->release(); +		} +		stop_thread(req); +		delete req; +		HttpRequest::destroyService(); +		throw; +	} +} + +template <> template <> +void HttpRequestTestObjectType::test<8>() +{ +	ScopedCurlInit ready; + +	std::string url_base(get_base_url()); +	std::cerr << "Base:  "  << url_base << std::endl; +	 +	set_test_name("HttpRequest POST to real service"); + +	// Handler can be stack-allocated *if* there are no dangling +	// references to it after completion of this method. +	// Create before memory record as the string copy will bump numbers. +	TestHandler2 handler(this, "handler"); +		 +	// record the total amount of dynamically allocated memory +	mMemTotal = GetMemTotal(); +	mHandlerCalls = 0; + +	HttpRequest * req = NULL; +	BufferArray * body = new BufferArray; +	 +	try +	{ +		// Get singletons created +		HttpRequest::createService(); +		 +		// Start threading early so that thread memory is invariant +		// over the test. +		HttpRequest::startThread(); + +		// create a new ref counted object with an implicit reference +		req = new HttpRequest(); +		ensure("Memory allocated on construction", mMemTotal < GetMemTotal()); + +		// Issue a GET that *can* connect +		static const char * body_text("Now is the time for all good men..."); +		body->append(body_text, strlen(body_text)); +		mStatus = HttpStatus(200); +		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID, +											 0U, +											 url_base, +											 body, +											 NULL, +											 NULL, +											 &handler); +		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID); + +		// Run the notification pump. +		int count(0); +		int limit(10); +		while (count++ < limit && mHandlerCalls < 1) +		{ +			req->update(1000); +			usleep(100000); +		} +		ensure("Request executed in reasonable time", count < limit); +		ensure("One handler invocation for request", mHandlerCalls == 1); + +		// Okay, request a shutdown of the servicing thread +		mStatus = HttpStatus(); +		handle = req->requestStopThread(&handler); +		ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID); +	 +		// Run the notification pump again +		count = 0; +		limit = 10; +		while (count++ < limit && mHandlerCalls < 2) +		{ +			req->update(1000); +			usleep(100000); +		} +		ensure("Second request executed in reasonable time", count < limit); +		ensure("Second handler invocation", mHandlerCalls == 2); + +		// See that we actually shutdown the thread +		count = 0; +		limit = 10; +		while (count++ < limit && ! HttpService::isStopped()) +		{ +			usleep(100000); +		} +		ensure("Thread actually stopped running", HttpService::isStopped()); + +		// Lose the request body +		body->release(); +		body = NULL; +		 +		// release the request object +		delete req; +		req = NULL; + +		// Shut down service +		HttpRequest::destroyService(); +	 +		ensure("Two handler calls on the way out", 2 == mHandlerCalls); + +#if defined(WIN32) +		// Can only do this memory test on Windows.  On other platforms, +		// the LL logging system holds on to memory and produces what looks +		// like memory leaks... +	 +		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal()); +		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); +#endif +	} +	catch (...) +	{ +		if (body) +		{ +			body->release(); +		} +		stop_thread(req); +		delete req; +		HttpRequest::destroyService(); +		throw; +	} +} +  }  // end namespace tut  namespace diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 3e200a5c19..8c3ad805b3 100644 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -85,7 +85,15 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):      def do_POST(self):          # Read the provided POST data. -        self.answer(self.read()) +        # self.answer(self.read()) +        self.answer(dict(reply="success", status=200, +                         reason=self.read())) + +    def do_PUT(self): +        # Read the provided PUT data. +        # self.answer(self.read()) +        self.answer(dict(reply="success", status=200, +                         reason=self.read()))      def answer(self, data):          debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7a44415fba..e2c13e77e3 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5358,6 +5358,7 @@ void CoreHttp::init()  	mRequest = new LLCore::HttpRequest; +	// Point to our certs or SSH/https: will fail on connect  	status = mRequest->setPolicyGlobalOption(LLCore::HttpRequest::GP_CA_FILE,  											 gDirUtilp->getCAFile());  	if (! status) @@ -5366,6 +5367,18 @@ void CoreHttp::init()  						<< status.toString()  						<< LL_ENDL;  	} + +	// Establish HTTP Proxy.  "LLProxy" is a special string which directs +	// the code to use LLProxy::applyProxySettings() to establish any +	// HTTP or SOCKS proxy for http operations. +	status = mRequest->setPolicyGlobalOption(LLCore::HttpRequest::GP_HTTP_PROXY, +											 std::string("LLProxy")); +	if (! status) +	{ +		LL_ERRS("Init") << "Failed to set HTTP proxy for HTTP services.  Reason:  " +						<< status.toString() +						<< LL_ENDL; +	}  	status = LLCore::HttpRequest::startThread();  	if (! status) | 
