From 3e80fa3dbc943de9b784fedc202ba38cf238f46d Mon Sep 17 00:00:00 2001
From: David Parks <davep@lindenlab.com>
Date: Mon, 2 Nov 2009 19:55:37 +0000
Subject: Sync up with render-pipeline-7 ignore-dead-branch

---
 indra/llmessage/llassetstorage.cpp        | 2 +-
 indra/llmessage/lltransfermanager.cpp     | 2 +-
 indra/llmessage/lltransfersourceasset.cpp | 2 ++
 3 files changed, 4 insertions(+), 2 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index b3087bcc3f..eeb903de6a 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -502,7 +502,7 @@ void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType at
 			tpvf.setAsset(uuid, atype);
 			tpvf.setCallback(downloadCompleteCallback, req);
 
-			llinfos << "Starting transfer for " << uuid << llendl;
+			//llinfos << "Starting transfer for " << uuid << llendl;
 			LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
 			ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
 		}
diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp
index d67911e8e2..72662bb782 100644
--- a/indra/llmessage/lltransfermanager.cpp
+++ b/indra/llmessage/lltransfermanager.cpp
@@ -344,7 +344,7 @@ void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
 		}
 	}
 
-	llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
+	//llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
 	ttp->setSize(size);
 	ttp->setGotInfo(TRUE);
 
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 5a1cd95ffc..f255a2cf7e 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -271,6 +271,7 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
 		case LLAssetType::AT_ANIMATION:
 		case LLAssetType::AT_GESTURE:
 		case LLAssetType::AT_FAVORITE:
+		case LLAssetType::AT_MESH:
 			rv = true;
 			break;
 		default:
@@ -296,6 +297,7 @@ bool is_asset_id_knowable(LLAssetType::EType type)
 		case LLAssetType::AT_FAVORITE:
 		case LLAssetType::AT_LINK:
 		case LLAssetType::AT_LINK_FOLDER:
+	    case LLAssetType::AT_MESH:
 			rv = true;
 			break;
 		default:
-- 
cgit v1.2.3


From 4c9d37c0906bd0218a5db08ea4fc253adfc684c9 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 16 Dec 2009 12:31:24 -0600
Subject: Tracking down stalls in llpumpio and agent updates.

---
 indra/llmessage/llpumpio.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 5e9dfd81fa..e3ce2c5ad3 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -444,13 +444,13 @@ void LLPumpIO::pump()
 	pump(DEFAULT_POLL_TIMEOUT);
 }
 
-static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
+static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO");
 
 //timeout is in microseconds
 void LLPumpIO::pump(const S32& poll_timeout)
 {
 	LLMemType m1(LLMemType::MTYPE_IO_PUMP);
-	LLFastTimer t1(FTM_PUMP);
+	LLFastTimer t1(FTM_PUMP_IO);
 	//llinfos << "LLPumpIO::pump()" << llendl;
 
 	// Run any pending runners.
@@ -778,6 +778,8 @@ bool LLPumpIO::respond(
 	return true;
 }
 
+static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain");
+
 void LLPumpIO::callback()
 {
 	LLMemType m1(LLMemType::MTYPE_IO_PUMP);
@@ -799,6 +801,7 @@ void LLPumpIO::callback()
 		callbacks_t::iterator end = mCallbacks.end();
 		for(; it != end; ++it)
 		{
+			LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN);
 			// it's always the first and last time for respone chains
 			(*it).mHead = (*it).mChainLinks.begin();
 			(*it).mInit = true;
-- 
cgit v1.2.3


From ffcbbf4aaabc652c2050ca6147a9388217cfcaa7 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 11 Feb 2010 18:00:00 -0600
Subject: Multi-threaded asset uploading with proper ordering first draft.

---
 indra/llmessage/llcurl.cpp       | 28 ++++++++++++++++++++++++++++
 indra/llmessage/llcurl.h         |  3 +++
 indra/llmessage/llhttpclient.cpp |  1 +
 3 files changed, 32 insertions(+)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 024e17a777..b93b94cd25 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -55,6 +55,7 @@
 #include "llstl.h"
 #include "llsdserialize.h"
 #include "llthread.h"
+#include "llvfile.h"
 
 //////////////////////////////////////////////////////////////////////////////
 /*
@@ -801,7 +802,34 @@ bool LLCurlRequest::post(const std::string& url,
 	bool res = addEasy(easy);
 	return res;
 }
+
+bool LLCurlRequest::post(const std::string& url,
+						 const headers_t& headers,
+						 const std::string& data,
+						 LLCurl::ResponderPtr responder)
+{
+	LLCurl::Easy* easy = allocEasy();
+	if (!easy)
+	{
+		return false;
+	}
+	easy->prepRequest(url, headers, responder);
+
+	easy->getInput().write(data.data(), data.size());
+	S32 bytes = easy->getInput().str().length();
 	
+	easy->setopt(CURLOPT_POST, 1);
+	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
+	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
+
+	easy->slist_append("Content-Type: application/octet-stream");
+	easy->setHeaders();
+
+	lldebugs << "POSTING: " << bytes << " bytes." << llendl;
+	bool res = addEasy(easy);
+	return res;
+}
+
 // Note: call once per frame
 S32 LLCurlRequest::process()
 {
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index caf02cccd9..4302c19113 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -44,6 +44,7 @@
 #include <boost/intrusive_ptr.hpp>
 #include <curl/curl.h> // TODO: remove dependency
 
+#include "llassettype.h"
 #include "llbuffer.h"
 #include "lliopipe.h"
 #include "llsd.h"
@@ -213,6 +214,8 @@ public:
 	void get(const std::string& url, LLCurl::ResponderPtr responder);
 	bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
 	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
+	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder);
+
 	S32  process();
 	S32  getQueued();
 
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index dd56e18caf..46952fa434 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -194,6 +194,7 @@ namespace
 			fileBuffer = new U8 [fileSize];
             vfile.read(fileBuffer, fileSize);
             ostream.write((char*)fileBuffer, fileSize);
+			delete [] fileBuffer;
 			eos = true;
 			return STATUS_DONE;
 		}
-- 
cgit v1.2.3


From de88d6ced487fd55fa6f6bb860849979f031a363 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 17 Feb 2010 11:29:16 -0600
Subject: Switched program database on windows to edit and continue for
 non-release builds. Adding a debug watch to LLCurlRequest to avoid
 invalidating iterator on processing posts. Mesh bulk uploading rewrite work
 in progress. 404 icons for mesh assets.

---
 indra/llmessage/llcurl.cpp | 9 +++++++++
 indra/llmessage/llcurl.h   | 3 ++-
 2 files changed, 11 insertions(+), 1 deletion(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index b93b94cd25..5212ba1eca 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -711,6 +711,7 @@ LLCurlRequest::LLCurlRequest() :
 	mActiveRequestCount(0)
 {
 	mThreadID = LLThread::currentID();
+	mProcessing = FALSE;
 }
 
 LLCurlRequest::~LLCurlRequest()
@@ -745,6 +746,11 @@ LLCurl::Easy* LLCurlRequest::allocEasy()
 bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
 {
 	llassert_always(mActiveMulti);
+	
+	if (mProcessing)
+	{
+		llerrs << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << llendl;
+	}
 	bool res = mActiveMulti->addEasy(easy);
 	return res;
 }
@@ -835,6 +841,8 @@ S32 LLCurlRequest::process()
 {
 	llassert_always(mThreadID == LLThread::currentID());
 	S32 res = 0;
+
+	mProcessing = TRUE;
 	for (curlmulti_set_t::iterator iter = mMultiSet.begin();
 		 iter != mMultiSet.end(); )
 	{
@@ -848,6 +856,7 @@ S32 LLCurlRequest::process()
 			delete multi;
 		}
 	}
+	mProcessing = FALSE;
 	return res;
 }
 
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 4302c19113..5367643289 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -215,7 +215,7 @@ public:
 	bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
 	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
 	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder);
-
+	
 	S32  process();
 	S32  getQueued();
 
@@ -229,6 +229,7 @@ private:
 	curlmulti_set_t mMultiSet;
 	LLCurl::Multi* mActiveMulti;
 	S32 mActiveRequestCount;
+	BOOL mProcessing;
 	U32 mThreadID; // debug
 };
 
-- 
cgit v1.2.3


From 74621ff8a8a141d50a3c92430afbe53a9e00edb5 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 17 Feb 2010 15:50:50 -0600
Subject: Post-review cleanup.

---
 indra/llmessage/llcurl.cpp | 1 -
 indra/llmessage/llcurl.h   | 1 -
 2 files changed, 2 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 5212ba1eca..0c919011ac 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -55,7 +55,6 @@
 #include "llstl.h"
 #include "llsdserialize.h"
 #include "llthread.h"
-#include "llvfile.h"
 
 //////////////////////////////////////////////////////////////////////////////
 /*
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 5367643289..6ec0a5d8a7 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -44,7 +44,6 @@
 #include <boost/intrusive_ptr.hpp>
 #include <curl/curl.h> // TODO: remove dependency
 
-#include "llassettype.h"
 #include "llbuffer.h"
 #include "lliopipe.h"
 #include "llsd.h"
-- 
cgit v1.2.3


From 4de18937025f92a0340277c3215fc43cac2f6688 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Wed, 24 Feb 2010 19:53:22 -0600
Subject: Added lower level pool to curl easy handles to speed up HTTP requests
 (from 40 ms per request to < 1 ms per request).

---
 indra/llmessage/llcurl.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 84 insertions(+), 3 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 0c919011ac..c640e176ee 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -55,6 +55,7 @@
 #include "llstl.h"
 #include "llsdserialize.h"
 #include "llthread.h"
+#include "lltimer.h"
 
 //////////////////////////////////////////////////////////////////////////////
 /*
@@ -256,7 +257,12 @@ public:
 	
 	void resetState();
 
+	static CURL* allocEasyHandle();
+	static void releaseEasyHandle(CURL* handle);
+
 private:	
+	friend class LLCurl;
+
 	CURL*				mCurlEasyHandle;
 	struct curl_slist*	mHeaders;
 	
@@ -271,8 +277,62 @@ private:
 	std::vector<char*>	mStrings;
 	
 	ResponderPtr		mResponder;
+
+	static std::set<CURL*> sFreeHandles;
+	static std::set<CURL*> sActiveHandles;
+	static LLMutex* sHandleMutex;
 };
 
+std::set<CURL*> LLCurl::Easy::sFreeHandles;
+std::set<CURL*> LLCurl::Easy::sActiveHandles;
+LLMutex* LLCurl::Easy::sHandleMutex = NULL;
+
+
+//static
+CURL* LLCurl::Easy::allocEasyHandle()
+{
+	CURL* ret = NULL;
+	LLMutexLock lock(sHandleMutex);
+	if (sFreeHandles.empty())
+	{
+		ret = curl_easy_init();
+	}
+	else
+	{
+		ret = *(sFreeHandles.begin());
+		sFreeHandles.erase(ret);
+		curl_easy_reset(ret);
+	}
+
+	if (ret)
+	{
+		sActiveHandles.insert(ret);
+	}
+
+	return ret;
+}
+
+//static
+void LLCurl::Easy::releaseEasyHandle(CURL* handle)
+{
+	if (!handle)
+	{
+		llerrs << "handle cannot be NULL!" << llendl;
+	}
+
+	LLMutexLock lock(sHandleMutex);
+	
+	if (sActiveHandles.find(handle) != sActiveHandles.end())
+	{
+		sActiveHandles.erase(handle);
+		sFreeHandles.insert(handle);
+	}
+	else
+	{
+		llerrs << "Invalid handle." << llendl;
+	}
+}
+
 LLCurl::Easy::Easy()
 	: mHeaders(NULL),
 	  mCurlEasyHandle(NULL)
@@ -283,11 +343,12 @@ LLCurl::Easy::Easy()
 LLCurl::Easy* LLCurl::Easy::getEasy()
 {
 	Easy* easy = new Easy();
-	easy->mCurlEasyHandle = curl_easy_init();
+	easy->mCurlEasyHandle = allocEasyHandle(); 
+	
 	if (!easy->mCurlEasyHandle)
 	{
 		// this can happen if we have too many open files (fails in c-ares/ares_init.c)
-		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
+		llwarns << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
 		delete easy;
 		return NULL;
 	}
@@ -301,7 +362,7 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
 
 LLCurl::Easy::~Easy()
 {
-	curl_easy_cleanup(mCurlEasyHandle);
+	releaseEasyHandle(mCurlEasyHandle);
 	--gCurlEasyCount;
 	curl_slist_free_all(mHeaders);
 	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
@@ -543,6 +604,7 @@ LLCurl::Multi::Multi()
 	  mErrorCount(0)
 {
 	mCurlMultiHandle = curl_multi_init();
+	
 	if (!mCurlMultiHandle)
 	{
 		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
@@ -1078,6 +1140,8 @@ void LLCurl::initClass()
 	// - http://curl.haxx.se/libcurl/c/curl_global_init.html
 	curl_global_init(CURL_GLOBAL_ALL);
 	
+	Easy::sHandleMutex = new LLMutex(NULL);
+
 #if SAFE_SSL
 	S32 mutex_count = CRYPTO_num_locks();
 	for (S32 i=0; i<mutex_count; i++)
@@ -1095,5 +1159,22 @@ void LLCurl::cleanupClass()
 	CRYPTO_set_locking_callback(NULL);
 	for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer());
 #endif
+
+	delete Easy::sHandleMutex;
+	Easy::sHandleMutex = NULL;
+
+	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
+	{
+		CURL* curl = *iter;
+		curl_easy_cleanup(curl);
+	}
+
+	Easy::sFreeHandles.clear();
+
+	if (!Easy::sActiveHandles.empty())
+	{
+		llerrs << "CURL easy handles not cleaned up on shutdown!" << llendl;
+	}
+
 	curl_global_cleanup();
 }
-- 
cgit v1.2.3


From e9d926385f4d8933d10bb4a3168628e0a6f0ad2a Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 2 Mar 2010 12:03:00 -0600
Subject: Curl tweaks to get rid of various types of timeouts. - Scrub host
 names from capability ips (requires disabling SSL host name verification) -
 Reset connections that have received a timeout (avoids cascading timeouts
 from reusing a cached bad connection)

---
 indra/llmessage/llcurl.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index c640e176ee..637110ba0f 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -353,9 +353,10 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
 		return NULL;
 	}
 	
-	// set no DMS caching as default for all easy handles. This prevents them adopting a
+	// set no DNS caching as default for all easy handles. This prevents them adopting a
 	// multi handles cache if they are added to one.
 	curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
+
 	++gCurlEasyCount;
 	return easy;
 }
@@ -440,6 +441,7 @@ U32 LLCurl::Easy::report(CURLcode code)
 	{
 		responseCode = 499;
 		responseReason = strerror(code) + " : " + mErrorBuffer;
+		setopt(CURLOPT_FRESH_CONNECT, TRUE);
 	}
 		
 	if (mResponder)
@@ -526,7 +528,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	
 	if (post) setoptString(CURLOPT_ENCODING, "");
 
-//	setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
+	//setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
 	setopt(CURLOPT_NOSIGNAL, 1);
 
 	mOutput.reset(new LLBufferArray);
@@ -543,9 +545,12 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 	setCA();
 
 	setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
-	setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
+	//setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
+	setopt(CURLOPT_SSL_VERIFYHOST, 0);
 	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
 
+	setopt(CURLOPT_FORBID_REUSE, TRUE);
+
 	setoptString(CURLOPT_URL, url);
 
 	mResponder = responder;
-- 
cgit v1.2.3


From e38adc5baf0bf4090168088fc4b9a71a5b231aa4 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 2 Mar 2010 12:35:19 -0600
Subject: cleanup from review

---
 indra/llmessage/llcurl.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 637110ba0f..f8a7eb0417 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -546,11 +546,11 @@ void LLCurl::Easy::prepRequest(const std::string& url,
 
 	setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
 	//setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
+	
+	//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
 	setopt(CURLOPT_SSL_VERIFYHOST, 0);
 	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
 
-	setopt(CURLOPT_FORBID_REUSE, TRUE);
-
 	setoptString(CURLOPT_URL, url);
 
 	mResponder = responder;
-- 
cgit v1.2.3


From 8f16be49dc86f0fca228b09ce0b788ad03482888 Mon Sep 17 00:00:00 2001
From: Tofu Linden <tofu.linden@lindenlab.com>
Date: Tue, 6 Apr 2010 15:09:18 +0100
Subject: some fixing from the viewer-trunk merge.

---
 indra/llmessage/llcurl.cpp | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'indra/llmessage')

diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 63a684ccc4..7c6660e28b 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -1173,4 +1173,6 @@ void LLCurl::cleanupClass()
 	{
 		llerrs << "CURL easy handles not cleaned up on shutdown!" << llendl;
 	}
+}
+
 
-- 
cgit v1.2.3