summaryrefslogtreecommitdiff
path: root/indra/llcorehttp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcorehttp')
-rwxr-xr-xindra/llcorehttp/CMakeLists.txt47
-rwxr-xr-xindra/llcorehttp/_httpinternal.h5
-rwxr-xr-xindra/llcorehttp/_httplibcurl.cpp131
-rwxr-xr-xindra/llcorehttp/_httplibcurl.h8
-rwxr-xr-xindra/llcorehttp/_httpopcancel.h5
-rwxr-xr-xindra/llcorehttp/_httpoperation.cpp126
-rwxr-xr-xindra/llcorehttp/_httpoperation.h52
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp320
-rwxr-xr-xindra/llcorehttp/_httpoprequest.h77
-rwxr-xr-xindra/llcorehttp/_httpopsetget.h3
-rwxr-xr-xindra/llcorehttp/_httpopsetpriority.h1
-rwxr-xr-xindra/llcorehttp/_httppolicy.cpp51
-rwxr-xr-xindra/llcorehttp/_httppolicy.h8
-rwxr-xr-xindra/llcorehttp/_httppolicyglobal.cpp30
-rwxr-xr-xindra/llcorehttp/_httppolicyglobal.h3
-rwxr-xr-xindra/llcorehttp/_httpreadyqueue.h6
-rwxr-xr-xindra/llcorehttp/_httpreplyqueue.cpp19
-rwxr-xr-xindra/llcorehttp/_httpreplyqueue.h23
-rwxr-xr-xindra/llcorehttp/_httprequestqueue.cpp15
-rwxr-xr-xindra/llcorehttp/_httprequestqueue.h8
-rwxr-xr-xindra/llcorehttp/_httpretryqueue.h6
-rwxr-xr-xindra/llcorehttp/_httpservice.cpp99
-rwxr-xr-xindra/llcorehttp/_httpservice.h9
-rwxr-xr-xindra/llcorehttp/_refcounted.h30
-rwxr-xr-xindra/llcorehttp/bufferarray.h4
-rwxr-xr-xindra/llcorehttp/examples/http_texture_load.cpp29
-rwxr-xr-xindra/llcorehttp/httpcommon.cpp207
-rwxr-xr-xindra/llcorehttp/httpcommon.h166
-rwxr-xr-xindra/llcorehttp/httphandler.h12
-rwxr-xr-xindra/llcorehttp/httpheaders.cpp21
-rwxr-xr-xindra/llcorehttp/httpheaders.h20
-rwxr-xr-xindra/llcorehttp/httpoptions.cpp48
-rwxr-xr-xindra/llcorehttp/httpoptions.h97
-rwxr-xr-xindra/llcorehttp/httprequest.cpp289
-rwxr-xr-xindra/llcorehttp/httprequest.h149
-rwxr-xr-xindra/llcorehttp/httpresponse.cpp28
-rwxr-xr-xindra/llcorehttp/httpresponse.h52
-rwxr-xr-xindra/llcorehttp/llhttpconstants.cpp135
-rwxr-xr-xindra/llcorehttp/llhttpconstants.h219
-rwxr-xr-xindra/llcorehttp/tests/llcorehttp_test.cpp2
-rwxr-xr-xindra/llcorehttp/tests/test_httpheaders.hpp27
-rwxr-xr-xindra/llcorehttp/tests/test_httpoperation.hpp20
-rwxr-xr-xindra/llcorehttp/tests/test_httprequest.hpp497
-rwxr-xr-xindra/llcorehttp/tests/test_httprequestqueue.hpp32
-rwxr-xr-xindra/llcorehttp/tests/test_httpstatus.hpp126
45 files changed, 2279 insertions, 983 deletions
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index a0b1ea13b1..0bb0348d26 100755
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -5,7 +5,6 @@ project(llcorehttp)
include(00-Common)
include(GoogleMock)
include(CURL)
-include(CARes)
include(OpenSSL)
include(ZLIB)
include(LLCoreHttp)
@@ -26,6 +25,7 @@ set(llcorehttp_SOURCE_FILES
bufferarray.cpp
bufferstream.cpp
httpcommon.cpp
+ llhttpconstants.cpp
httpheaders.cpp
httpoptions.cpp
httprequest.cpp
@@ -51,6 +51,7 @@ set(llcorehttp_HEADER_FILES
bufferarray.h
bufferstream.h
httpcommon.h
+ llhttpconstants.h
httphandler.h
httpheaders.h
httpoptions.h
@@ -89,7 +90,6 @@ add_library (llcorehttp ${llcorehttp_SOURCE_FILES})
target_link_libraries(
llcorehttp
${CURL_LIBRARIES}
- ${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${BOOST_THREAD_LIBRARY}
@@ -127,20 +127,60 @@ if (LL_TESTS)
${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
${CURL_LIBRARIES}
- ${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${BOOST_SYSTEM_LIBRARY}
${BOOST_THREAD_LIBRARY}
)
+ # If http_proxy is in the current environment (e.g. to fetch s3-proxy
+ # autobuild packages), suppress it for this integration test: it screws up
+ # the tests.
LL_ADD_INTEGRATION_TEST(llcorehttp
"${llcorehttp_TEST_SOURCE_FILES}"
"${test_libs}"
+ "-Dhttp_proxy"
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llcorehttp_peer.py"
)
+if (DARWIN)
+ # Path inside the app bundle where we'll need to copy libraries
+ set(LL_TEST_DESTINATION_DIR
+ ${CMAKE_SOURCE_DIR}/../build-darwin-i386/sharedlibs/Resources
+ )
+
+ # Create the Contents/Resources directory
+ add_custom_command(
+ TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ make_directory
+ ${LL_TEST_DESTINATION_DIR}
+ COMMENT "Creating Resources directory in app bundle."
+ )
+
+ # Copy the required libraries to the package app
+ add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib ${LL_TEST_DESTINATION_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib
+ )
+ add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib ${LL_TEST_DESTINATION_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib
+ )
+ add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib ${LL_TEST_DESTINATION_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib
+ )
+ add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib ${LL_TEST_DESTINATION_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib
+ )
+
+endif (DARWIN)
+
#
# Example Programs
#
@@ -155,7 +195,6 @@ if (LL_TESTS)
${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
${CURL_LIBRARIES}
- ${CARES_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${BOOST_SYSTEM_LIBRARY}
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index a2a60ca056..79c89d6c92 100755
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -104,8 +104,9 @@ namespace LLCore
{
// Maxium number of policy classes that can be defined.
-// *TODO: Currently limited to the default class + 1, extend.
-const int HTTP_POLICY_CLASS_LIMIT = 8;
+// *TODO: Currently limited to the default class + 1, extend.
+// (TSN: should this be more dynamically sized. Is there a reason to hard limit the number of policies?)
+const int HTTP_POLICY_CLASS_LIMIT = 32;
// Debug/informational tracing. Used both
// as a global option and in per-request traces.
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 81b44ab90b..c25e01a318 100755
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -71,11 +71,10 @@ void HttpLibcurl::shutdown()
{
while (! mActiveOps.empty())
{
- HttpOpRequest * op(* mActiveOps.begin());
+ HttpOpRequest::ptr_t op(* mActiveOps.begin());
mActiveOps.erase(mActiveOps.begin());
cancelRequest(op);
- op->release();
}
if (mMultiHandles)
@@ -204,7 +203,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
// Caller has provided us with a ref count on op.
-void HttpLibcurl::addOp(HttpOpRequest * op)
+void HttpLibcurl::addOp(const HttpOpRequest::ptr_t &op)
{
llassert_always(op->mReqPolicy < mPolicyCount);
llassert_always(mMultiHandles[op->mReqPolicy] != NULL);
@@ -235,21 +234,21 @@ void HttpLibcurl::addOp(HttpOpRequest * op)
HttpPolicy & policy(mService->getPolicy());
LL_INFOS(LOG_CORE) << "TRACE, ToActiveQueue, Handle: "
- << static_cast<HttpHandle>(op)
- << ", Actives: " << mActiveOps.size()
- << ", Readies: " << policy.getReadyCount(op->mReqPolicy)
- << LL_ENDL;
+ << op->getHandle()
+ << ", Actives: " << mActiveOps.size()
+ << ", Readies: " << policy.getReadyCount(op->mReqPolicy)
+ << LL_ENDL;
}
}
// Implements the transport part of any cancel operation.
// See if the handle is an active operation and if so,
-// use the more complicated transport-based cancelation
+// use the more complicated transport-based cancellation
// method to kill the request.
bool HttpLibcurl::cancel(HttpHandle handle)
{
- HttpOpRequest * op(static_cast<HttpOpRequest *>(handle));
+ HttpOpRequest::ptr_t op = HttpOpRequest::fromHandle<HttpOpRequest>(handle);
active_set_t::iterator it(mActiveOps.find(op));
if (mActiveOps.end() == it)
{
@@ -262,7 +261,6 @@ bool HttpLibcurl::cancel(HttpHandle handle)
// Drop references
mActiveOps.erase(it);
--mActiveHandles[op->mReqPolicy];
- op->release();
return true;
}
@@ -273,7 +271,7 @@ bool HttpLibcurl::cancel(HttpHandle handle)
// remove the op from the active list and release the op *after*
// calling this method. It must be called first to deliver the
// op to the reply queue with refcount intact.
-void HttpLibcurl::cancelRequest(HttpOpRequest * op)
+void HttpLibcurl::cancelRequest(const HttpOpRequest::ptr_t &op)
{
// Deactivate request
op->mCurlActive = false;
@@ -287,7 +285,7 @@ void HttpLibcurl::cancelRequest(HttpOpRequest * op)
if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS(LOG_CORE) << "TRACE, RequestCanceled, Handle: "
- << static_cast<HttpHandle>(op)
+ << op->getHandle()
<< ", Status: " << op->mStatus.toTerseString()
<< LL_ENDL;
}
@@ -301,8 +299,23 @@ void HttpLibcurl::cancelRequest(HttpOpRequest * op)
// Keep them synchronized as necessary.
bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)
{
- HttpOpRequest * op(NULL);
- curl_easy_getinfo(handle, CURLINFO_PRIVATE, &op);
+ HttpHandle ophandle(NULL);
+
+ CURLcode ccode(CURLE_OK);
+
+ ccode = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &ophandle);
+ if (ccode)
+ {
+ LL_WARNS(LOG_CORE) << "libcurl error: " << ccode << " Unable to retrieve operation handle from CURL handle" << LL_ENDL;
+ return false;
+ }
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(ophandle));
+
+ if (!op)
+ {
+ LL_WARNS() << "Unable to locate operation by handle. May have expired!" << LL_ENDL;
+ return false;
+ }
if (handle != op->mCurlHandle || ! op->mCurlActive)
{
@@ -331,42 +344,72 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
{
op->mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, status);
}
- if (op->mStatus)
- {
- int http_status(HTTP_OK);
-
- curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_status);
- if (http_status >= 100 && http_status <= 999)
- {
- char * cont_type(NULL);
- curl_easy_getinfo(handle, CURLINFO_CONTENT_TYPE, &cont_type);
- if (cont_type)
- {
- op->mReplyConType = cont_type;
- }
- op->mStatus = HttpStatus(http_status);
- }
- else
- {
- LL_WARNS(LOG_CORE) << "Invalid HTTP response code ("
- << http_status << ") received from server."
- << LL_ENDL;
- op->mStatus = HttpStatus(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS);
- }
+ if (op->mStatus)
+ {
+ int http_status(HTTP_OK);
+
+ if (handle)
+ {
+ ccode = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_status);
+ if (ccode == CURLE_OK)
+ {
+ if (http_status >= 100 && http_status <= 999)
+ {
+ char * cont_type(NULL);
+ ccode = curl_easy_getinfo(handle, CURLINFO_CONTENT_TYPE, &cont_type);
+ if (ccode == CURLE_OK)
+ {
+ if (cont_type)
+ {
+ op->mReplyConType = cont_type;
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_CORE) << "CURL error:" << ccode << " Attempting to get content type." << LL_ENDL;
+ }
+ op->mStatus = HttpStatus(http_status);
+ }
+ else
+ {
+ LL_WARNS(LOG_CORE) << "Invalid HTTP response code ("
+ << http_status << ") received from server."
+ << LL_ENDL;
+ op->mStatus = HttpStatus(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS);
+ }
+ }
+ else
+ {
+ op->mStatus = HttpStatus(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS);
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_CORE) << "Attempt to retrieve status from NULL handle!" << LL_ENDL;
+ }
}
- // Detach from multi and recycle handle
- curl_multi_remove_handle(multi_handle, handle);
- mHandleCache.freeHandle(op->mCurlHandle);
- op->mCurlHandle = NULL;
+ if (multi_handle && handle)
+ {
+ // Detach from multi and recycle handle
+ curl_multi_remove_handle(multi_handle, handle);
+ mHandleCache.freeHandle(op->mCurlHandle);
+ }
+ else
+ {
+ LL_WARNS(LOG_CORE) << "Curl multi_handle or handle is NULL on remove! multi:"
+ << std::hex << multi_handle << " h:" << std::hex << handle << std::dec << LL_ENDL;
+ }
+
+ op->mCurlHandle = NULL;
// Tracing
if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS(LOG_CORE) << "TRACE, RequestComplete, Handle: "
- << static_cast<HttpHandle>(op)
- << ", Status: " << op->mStatus.toTerseString()
- << LL_ENDL;
+ << op->getHandle()
+ << ", Status: " << op->mStatus.toTerseString()
+ << LL_ENDL;
}
// Dispatch to next stage
@@ -554,7 +597,7 @@ void HttpLibcurl::HandleCache::freeHandle(CURL * handle)
// ---------------------------------------
-struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct curl_slist * slist)
+struct curl_slist * append_headers_to_slist(const HttpHeaders::ptr_t &headers, struct curl_slist * slist)
{
const HttpHeaders::const_iterator end(headers->end());
for (HttpHeaders::const_iterator it(headers->begin()); end != it; ++it)
diff --git a/indra/llcorehttp/_httplibcurl.h b/indra/llcorehttp/_httplibcurl.h
index ffc24c63a8..a71eae59c0 100755
--- a/indra/llcorehttp/_httplibcurl.h
+++ b/indra/llcorehttp/_httplibcurl.h
@@ -65,6 +65,8 @@ private:
void operator=(const HttpLibcurl &); // Not defined
public:
+ typedef boost::shared_ptr<HttpOpRequest> opReqPtr_t;
+
/// Give cycles to libcurl to run active requests. Completed
/// operations (successful or failed) will be retried or handed
/// over to the reply queue as final responses.
@@ -80,7 +82,7 @@ public:
/// request. (No additional references will be added.)
///
/// Threading: called by worker thread.
- void addOp(HttpOpRequest * op);
+ void addOp(const opReqPtr_t & op);
/// One-time call to set the number of policy classes to be
/// serviced and to create the resources for each. Value
@@ -148,10 +150,10 @@ protected:
/// Invoked to cancel an active request, mainly during shutdown
/// and destroy.
- void cancelRequest(HttpOpRequest * op);
+ void cancelRequest(const opReqPtr_t &op);
protected:
- typedef std::set<HttpOpRequest *> active_set_t;
+ typedef std::set<opReqPtr_t> active_set_t;
/// Simple request handle cache for libcurl.
///
diff --git a/indra/llcorehttp/_httpopcancel.h b/indra/llcorehttp/_httpopcancel.h
index 336dfdc573..86944eb159 100755
--- a/indra/llcorehttp/_httpopcancel.h
+++ b/indra/llcorehttp/_httpopcancel.h
@@ -56,13 +56,8 @@ public:
/// be canceled.
HttpOpCancel(HttpHandle handle);
-protected:
virtual ~HttpOpCancel(); // Use release()
-private:
- HttpOpCancel(const HttpOpCancel &); // Not defined
- void operator=(const HttpOpCancel &); // Not defined
-
public:
virtual void stageFromRequest(HttpService *);
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index fefe561f80..3fc4e28910 100755
--- a/indra/llcorehttp/_httpoperation.cpp
+++ b/indra/llcorehttp/_httpoperation.cpp
@@ -53,15 +53,18 @@ namespace LLCore
// ==================================
// HttpOperation
// ==================================
-
-
-HttpOperation::HttpOperation()
- : LLCoreInt::RefCounted(true),
- mReplyQueue(NULL),
- mUserHandler(NULL),
- mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
- mReqPriority(0U),
- mTracing(HTTP_TRACE_OFF)
+/*static*/
+HttpOperation::handleMap_t HttpOperation::mHandleMap;
+LLCoreInt::HttpMutex HttpOperation::mOpMutex;
+
+HttpOperation::HttpOperation():
+ boost::enable_shared_from_this<HttpOperation>(),
+ mReplyQueue(),
+ mUserHandler(),
+ mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
+ mReqPriority(0U),
+ mTracing(HTTP_TRACE_OFF),
+ mMyHandle(LLCORE_HTTP_HANDLE_INVALID)
{
mMetricCreated = totalTime();
}
@@ -69,30 +72,17 @@ HttpOperation::HttpOperation()
HttpOperation::~HttpOperation()
{
- setReplyPath(NULL, NULL);
+ destroyHandle();
+ mReplyQueue.reset();
+ mUserHandler.reset();
}
-void HttpOperation::setReplyPath(HttpReplyQueue * reply_queue,
- HttpHandler * user_handler)
+void HttpOperation::setReplyPath(HttpReplyQueue::ptr_t reply_queue,
+ HttpHandler::ptr_t user_handler)
{
- if (reply_queue != mReplyQueue)
- {
- if (mReplyQueue)
- {
- mReplyQueue->release();
- }
-
- if (reply_queue)
- {
- reply_queue->addRef();
- }
-
- mReplyQueue = reply_queue;
- }
-
- // Not refcounted
- mUserHandler = user_handler;
+ mReplyQueue.swap(reply_queue);
+ mUserHandler.swap(user_handler);
}
@@ -134,7 +124,7 @@ void HttpOperation::visitNotifier(HttpRequest *)
HttpResponse * response = new HttpResponse();
response->setStatus(mStatus);
- mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
+ mUserHandler->onCompleted(getHandle(), response);
response->release();
}
@@ -148,20 +138,83 @@ HttpStatus HttpOperation::cancel()
return status;
}
+// Handle methods
+HttpHandle HttpOperation::getHandle()
+{
+ if (mMyHandle == LLCORE_HTTP_HANDLE_INVALID)
+ return createHandle();
+
+ return mMyHandle;
+}
+
+HttpHandle HttpOperation::createHandle()
+{
+ HttpHandle handle = static_cast<HttpHandle>(this);
+
+ {
+ LLCoreInt::HttpScopedLock lock(mOpMutex);
+
+ mHandleMap[handle] = shared_from_this();
+ mMyHandle = handle;
+ }
+
+ return mMyHandle;
+}
+
+void HttpOperation::destroyHandle()
+{
+ if (mMyHandle == LLCORE_HTTP_HANDLE_INVALID)
+ return;
+ {
+ LLCoreInt::HttpScopedLock lock(mOpMutex);
+
+ handleMap_t::iterator it = mHandleMap.find(mMyHandle);
+ if (it != mHandleMap.end())
+ mHandleMap.erase(it);
+ }
+}
+
+/*static*/
+HttpOperation::ptr_t HttpOperation::findByHandle(HttpHandle handle)
+{
+ wptr_t weak;
+
+ if (!handle)
+ return ptr_t();
+
+ {
+ LLCoreInt::HttpScopedLock lock(mOpMutex);
+
+ handleMap_t::iterator it = mHandleMap.find(handle);
+ if (it == mHandleMap.end())
+ {
+ LL_WARNS("LLCore::HTTP") << "Could not find operation for handle " << handle << LL_ENDL;
+ return ptr_t();
+ }
+
+ weak = (*it).second;
+ }
+
+ if (!weak.expired())
+ return weak.lock();
+
+ return ptr_t();
+}
+
void HttpOperation::addAsReply()
{
if (mTracing > HTTP_TRACE_OFF)
{
LL_INFOS(LOG_CORE) << "TRACE, ToReplyQueue, Handle: "
- << static_cast<HttpHandle>(this)
+ << getHandle()
<< LL_ENDL;
}
if (mReplyQueue)
{
- addRef();
- mReplyQueue->addOp(this);
+ HttpOperation::ptr_t op = shared_from_this();
+ mReplyQueue->addOp(op);
}
}
@@ -244,11 +297,8 @@ void HttpOpSpin::stageFromRequest(HttpService * service)
else
{
ms_sleep(1); // backoff interlock plumbing a bit
- this->addRef();
- if (! service->getRequestQueue().addOp(this))
- {
- this->release();
- }
+ HttpOperation::ptr_t opptr = shared_from_this();
+ service->getRequestQueue().addOp(opptr);
}
}
diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h
index 937a61187d..1a75921c09 100755
--- a/indra/llcorehttp/_httpoperation.h
+++ b/indra/llcorehttp/_httpoperation.h
@@ -30,8 +30,7 @@
#include "httpcommon.h"
#include "httprequest.h"
-#include "_refcounted.h"
-
+#include "_mutex.h"
namespace LLCore
{
@@ -69,19 +68,20 @@ class HttpService;
/// via queue-like interfaces that are thread compatible
/// and those interfaces establish the access rules.
-class HttpOperation : public LLCoreInt::RefCounted
+class HttpOperation : private boost::noncopyable,
+ public boost::enable_shared_from_this<HttpOperation>
{
public:
+ typedef boost::shared_ptr<HttpOperation> ptr_t;
+ typedef boost::weak_ptr<HttpOperation> wptr_t;
+ typedef boost::shared_ptr<HttpReplyQueue> HttpReplyQueuePtr_t;
+
/// Threading: called by consumer thread.
HttpOperation();
-protected:
/// Threading: called by any thread.
virtual ~HttpOperation(); // Use release()
-private:
- HttpOperation(const HttpOperation &); // Not defined
- void operator=(const HttpOperation &); // Not defined
public:
/// Register a reply queue and a handler for completion notifications.
@@ -110,8 +110,8 @@ public:
///
/// Threading: called by consumer thread.
///
- void setReplyPath(HttpReplyQueue * reply_queue,
- HttpHandler * handler);
+ void setReplyPath(HttpReplyQueuePtr_t reply_queue,
+ HttpHandler::ptr_t handler);
/// The three possible staging steps in an operation's lifecycle.
/// Asynchronous requests like HTTP operations move from the
@@ -152,6 +152,18 @@ public:
/// Threading: called by worker thread.
///
virtual HttpStatus cancel();
+
+ /// Retrieves a unique handle for this operation.
+ HttpHandle getHandle();
+
+ template< class OPT >
+ static boost::shared_ptr< OPT > fromHandle(HttpHandle handle)
+ {
+ ptr_t ptr = findByHandle(handle);
+ if (!ptr)
+ return boost::shared_ptr< OPT >();
+ return boost::dynamic_pointer_cast< OPT >(ptr);
+ }
protected:
/// Delivers request to reply queue on completion. After this
@@ -163,8 +175,8 @@ protected:
void addAsReply();
protected:
- HttpReplyQueue * mReplyQueue; // Have refcount
- HttpHandler * mUserHandler; // Naked pointer
+ HttpReplyQueuePtr_t mReplyQueue;
+ HttpHandler::ptr_t mUserHandler;
public:
// Request Data
@@ -177,6 +189,21 @@ public:
// Tracing, debug and metrics
HttpTime mMetricCreated;
int mTracing;
+
+private:
+ typedef std::map<HttpHandle, wptr_t> handleMap_t;
+
+ HttpHandle createHandle();
+ void destroyHandle();
+ HttpHandle mMyHandle;
+
+ static handleMap_t mHandleMap;
+ static LLCoreInt::HttpMutex mOpMutex;
+
+protected:
+ static ptr_t findByHandle(HttpHandle handle);
+
+
}; // end class HttpOperation
@@ -195,7 +222,6 @@ class HttpOpStop : public HttpOperation
public:
HttpOpStop();
-protected:
virtual ~HttpOpStop();
private:
@@ -218,7 +244,6 @@ class HttpOpNull : public HttpOperation
public:
HttpOpNull();
-protected:
virtual ~HttpOpNull();
private:
@@ -241,7 +266,6 @@ public:
// 1 does a soft spin continuously requeuing itself
HttpOpSpin(int mode);
-protected:
virtual ~HttpOpSpin();
private:
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index b9632a7921..db57869a1b 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -122,8 +122,8 @@ HttpOpRequest::HttpOpRequest()
mReqBody(NULL),
mReqOffset(0),
mReqLength(0),
- mReqHeaders(NULL),
- mReqOptions(NULL),
+ mReqHeaders(),
+ mReqOptions(),
mCurlActive(false),
mCurlHandle(NULL),
mCurlService(NULL),
@@ -135,11 +135,12 @@ HttpOpRequest::HttpOpRequest()
mReplyOffset(0),
mReplyLength(0),
mReplyFullLength(0),
- mReplyHeaders(NULL),
+ mReplyHeaders(),
mPolicyRetries(0),
mPolicy503Retries(0),
mPolicyRetryAt(HttpTime(0)),
- mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT)
+ mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT),
+ mCallbackSSLVerify(NULL)
{
// *NOTE: As members are added, retry initialization/cleanup
// may need to be extended in @see prepareRequest().
@@ -155,18 +156,6 @@ HttpOpRequest::~HttpOpRequest()
mReqBody = NULL;
}
- if (mReqOptions)
- {
- mReqOptions->release();
- mReqOptions = NULL;
- }
-
- if (mReqHeaders)
- {
- mReqHeaders->release();
- mReqHeaders = NULL;
- }
-
if (mCurlHandle)
{
// Uncertain of thread context so free using
@@ -193,25 +182,20 @@ HttpOpRequest::~HttpOpRequest()
mReplyBody = NULL;
}
- if (mReplyHeaders)
- {
- mReplyHeaders->release();
- mReplyHeaders = NULL;
- }
}
void HttpOpRequest::stageFromRequest(HttpService * service)
{
- addRef();
- service->getPolicy().addOp(this); // transfers refcount
+ HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));
+ service->getPolicy().addOp(self); // transfers refcount
}
void HttpOpRequest::stageFromReady(HttpService * service)
{
- addRef();
- service->getTransport().addOp(this); // transfers refcount
+ HttpOpRequest::ptr_t self(boost::dynamic_pointer_cast<HttpOpRequest>(shared_from_this()));
+ service->getTransport().addOp(self); // transfers refcount
}
@@ -259,7 +243,9 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
response->setStatus(mStatus);
response->setBody(mReplyBody);
response->setHeaders(mReplyHeaders);
- if (mReplyOffset || mReplyLength)
+ response->setRequestURL(mReqURL);
+
+ if (mReplyOffset || mReplyLength)
{
// Got an explicit offset/length in response
response->setRange(mReplyOffset, mReplyLength, mReplyFullLength);
@@ -267,12 +253,27 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
response->setContentType(mReplyConType);
response->setRetries(mPolicyRetries, mPolicy503Retries);
- mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
+ HttpResponse::TransferStats::ptr_t stats = HttpResponse::TransferStats::ptr_t(new HttpResponse::TransferStats);
+
+ curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &stats->mSizeDownload);
+ curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &stats->mTotalTime);
+ curl_easy_getinfo(mCurlHandle, CURLINFO_SPEED_DOWNLOAD, &stats->mSpeedDownload);
+
+ response->setTransferStats(stats);
+
+ mUserHandler->onCompleted(this->getHandle(), response);
response->release();
}
}
+// /*static*/
+// HttpOpRequest::ptr_t HttpOpRequest::fromHandle(HttpHandle handle)
+// {
+//
+// return boost::dynamic_pointer_cast<HttpOpRequest>((static_cast<HttpOpRequest *>(handle))->shared_from_this());
+// }
+
HttpStatus HttpOpRequest::cancel()
{
@@ -287,8 +288,8 @@ HttpStatus HttpOpRequest::cancel()
HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
- HttpOptions * options,
- HttpHeaders * headers)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
{
setupCommon(policy_id, priority, url, NULL, options, headers);
mReqMethod = HOR_GET;
@@ -302,8 +303,8 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
const std::string & url,
size_t offset,
size_t len,
- HttpOptions * options,
- HttpHeaders * headers)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
{
setupCommon(policy_id, priority, url, NULL, options, headers);
mReqMethod = HOR_GET;
@@ -322,8 +323,8 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
{
setupCommon(policy_id, priority, url, body, options, headers);
mReqMethod = HOR_POST;
@@ -336,8 +337,8 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
{
setupCommon(policy_id, priority, url, body, options, headers);
mReqMethod = HOR_PUT;
@@ -346,12 +347,65 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
}
+HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
+{
+ setupCommon(policy_id, priority, url, NULL, options, headers);
+ mReqMethod = HOR_DELETE;
+
+ return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ BufferArray * body,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
+{
+ setupCommon(policy_id, priority, url, body, options, headers);
+ mReqMethod = HOR_PATCH;
+
+ return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t &headers)
+{
+ setupCommon(policy_id, priority, url, NULL, options, headers);
+ mReqMethod = HOR_COPY;
+
+ return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t &headers)
+{
+ setupCommon(policy_id, priority, url, NULL, options, headers);
+ mReqMethod = HOR_MOVE;
+
+ return HttpStatus();
+}
+
+
void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers)
{
mProcFlags = 0U;
mReqPolicy = policy_id;
@@ -364,12 +418,10 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
}
if (headers && ! mReqHeaders)
{
- headers->addRef();
mReqHeaders = headers;
}
- if (options && ! mReqOptions)
+ if (options && !mReqOptions)
{
- options->addRef();
mReqOptions = options;
if (options->getWantHeaders())
{
@@ -416,11 +468,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
mReplyOffset = 0;
mReplyLength = 0;
mReplyFullLength = 0;
- if (mReplyHeaders)
- {
- mReplyHeaders->release();
- mReplyHeaders = NULL;
- }
+ mReplyHeaders.reset();
mReplyConType.clear();
// *FIXME: better error handling later
@@ -447,38 +495,74 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_code(code, CURLOPT_NOPROGRESS);
code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
check_curl_easy_code(code, CURLOPT_URL);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
check_curl_easy_code(code, CURLOPT_PRIVATE);
code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
check_curl_easy_code(code, CURLOPT_ENCODING);
- // 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.
- code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
- check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
check_curl_easy_code(code, CURLOPT_AUTOREFERER);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
- check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
check_curl_easy_code(code, CURLOPT_MAXREDIRS);
code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
check_curl_easy_code(code, CURLOPT_WRITEFUNCTION);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle());
check_curl_easy_code(code, CURLOPT_WRITEDATA);
code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
check_curl_easy_code(code, CURLOPT_READFUNCTION);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle());
check_curl_easy_code(code, CURLOPT_READDATA);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback);
+ check_curl_easy_code(code, CURLOPT_SEEKFUNCTION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle());
+ check_curl_easy_code(code, CURLOPT_SEEKDATA);
+
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, "");
+ check_curl_easy_code(code, CURLOPT_COOKIEFILE);
+
+ if (gpolicy.mSslCtxCallback)
+ {
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback);
+ check_curl_easy_code(code, CURLOPT_SSL_CTX_FUNCTION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle());
+ check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA);
+ mCallbackSSLVerify = gpolicy.mSslCtxCallback;
+ }
+
+ long follow_redirect(1L);
+ long sslPeerV(0L);
+ long sslHostV(0L);
+ long dnsCacheTimeout(-1L);
+ long nobody(0L);
+
+ if (mReqOptions)
+ {
+ follow_redirect = mReqOptions->getFollowRedirects() ? 1L : 0L;
+ sslPeerV = mReqOptions->getSSLVerifyPeer() ? 1L : 0L;
+ sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;
+ dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
+ nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
+ }
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
+ check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
+
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV);
check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);
check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
+ check_curl_easy_code(code, CURLOPT_NOBODY);
+
+ // 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.
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
+ check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
+
if (gpolicy.mUseLLProxy)
{
// Use the viewer-based thread-safe API which has a
@@ -509,10 +593,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
switch (mReqMethod)
{
case HOR_GET:
- code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+ if (nobody == 0)
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
check_curl_easy_code(code, CURLOPT_HTTPGET);
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
break;
case HOR_POST:
@@ -531,12 +614,14 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
}
break;
- case HOR_PUT:
+ case HOR_PATCH:
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
+ check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+ // fall through. The rest is the same as PUT
+ case HOR_PUT:
{
code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
check_curl_easy_code(code, CURLOPT_UPLOAD);
@@ -547,15 +632,25 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
}
code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
check_curl_easy_code(code, CURLOPT_INFILESIZE);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
- check_curl_easy_code(code, CURLOPT_POSTFIELDS);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
- // *TODO: Should this be 'Keep-Alive' ?
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
- mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
}
break;
+ case HOR_DELETE:
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+ check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+ break;
+
+ case HOR_COPY:
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY");
+ check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+ break;
+
+ case HOR_MOVE:
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE");
+ check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+ break;
+
default:
LL_ERRS(LOG_CORE) << "Invalid HTTP method in request: "
<< int(mReqMethod) << ". Can't recover."
@@ -563,6 +658,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
break;
}
+
+ // *TODO: Should this be 'Keep-Alive' ?
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
+
// Tracing
if (mTracing >= HTTP_TRACE_CURL_HEADERS)
{
@@ -650,7 +750,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
xfer_timeout *= 2L;
}
// *DEBUG: Enable following override for timeout handling and "[curl:bugs] #1420" tests
- // xfer_timeout = 1L;
+ //if (cpolicy.mPipelining)
+ //{
+ // xfer_timeout = 1L;
+ // timeout = 1L;
+ //}
code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
check_curl_easy_code(code, CURLOPT_TIMEOUT);
code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
@@ -683,7 +787,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
- HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (! op->mReplyBody)
{
@@ -697,7 +801,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void
size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
- HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
if (! op->mReqBody)
{
@@ -723,6 +827,37 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
return read_size;
}
+
+int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
+{
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
+
+ if (!op->mReqBody)
+ {
+ return 0;
+ }
+
+ size_t newPos = 0;
+ if (origin == SEEK_SET)
+ newPos = offset;
+ else if (origin == SEEK_END)
+ newPos = static_cast<curl_off_t>(op->mReqBody->size()) + offset;
+ else if (origin == SEEK_CUR)
+ newPos = static_cast<curl_off_t>(op->mCurlBodyPos) + offset;
+ else
+ return 2;
+
+ if (newPos >= op->mReqBody->size())
+ {
+ LL_WARNS(LOG_CORE) << "Attempt to seek to position outside post body." << LL_ENDL;
+ return 2;
+ }
+
+ op->mCurlBodyPos = (size_t)newPos;
+
+ return 0;
+}
+
size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata)
{
@@ -731,7 +866,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
static const char con_ran_line[] = "content-range";
static const char con_retry_line[] = "retry-after";
- HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
const size_t hdr_size(size * nmemb);
const char * hdr_data(static_cast<const char *>(data)); // Not null terminated
@@ -817,7 +952,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
// Save headers in response
if (! op->mReplyHeaders)
{
- op->mReplyHeaders = new HttpHeaders;
+ op->mReplyHeaders = HttpHeaders::ptr_t(new HttpHeaders);
}
op->mReplyHeaders->append(name, value ? value : "");
}
@@ -873,9 +1008,38 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
}
+CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)
+{
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
+
+ if (op->mCallbackSSLVerify)
+ {
+ SSL_CTX * ctx = (SSL_CTX *)sslctx;
+ // disable any default verification for server certs
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+ // set the verification callback.
+ SSL_CTX_set_cert_verify_callback(ctx, sslCertVerifyCallback, userdata);
+ // the calls are void
+ }
+
+ return CURLE_OK;
+}
+
+int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
+{
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(param));
+
+ if (op->mCallbackSSLVerify)
+ {
+ op->mStatus = op->mCallbackSSLVerify(op->mReqURL, op->mUserHandler, ctx);
+ }
+
+ return (op->mStatus) ? 1 : 0;
+}
+
int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata)
{
- HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+ HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
std::string safe_line;
std::string tag;
@@ -955,7 +1119,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
if (logit)
{
LL_INFOS(LOG_CORE) << "TRACE, LibcurlDebug, Handle: "
- << static_cast<HttpHandle>(op)
+ << op->getHandle()
<< ", Type: " << tag
<< ", Data: " << safe_line
<< LL_ENDL;
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 2f628b5aba..dbcc57d0fd 100755
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -33,19 +33,22 @@
#include <string>
#include <curl/curl.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+
#include "httpcommon.h"
#include "httprequest.h"
#include "_httpoperation.h"
#include "_refcounted.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
namespace LLCore
{
class BufferArray;
-class HttpHeaders;
-class HttpOptions;
/// HttpOpRequest requests a supported HTTP method invocation with
@@ -63,9 +66,10 @@ class HttpOptions;
class HttpOpRequest : public HttpOperation
{
public:
+ typedef boost::shared_ptr<HttpOpRequest> ptr_t;
+
HttpOpRequest();
-protected:
virtual ~HttpOpRequest(); // Use release()
private:
@@ -77,7 +81,11 @@ public:
{
HOR_GET,
HOR_POST,
- HOR_PUT
+ HOR_PUT,
+ HOR_DELETE,
+ HOR_PATCH,
+ HOR_COPY,
+ HOR_MOVE
};
virtual void stageFromRequest(HttpService *);
@@ -98,32 +106,57 @@ public:
HttpStatus setupGet(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
- HttpOptions * options,
- HttpHeaders * headers);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
size_t offset,
size_t len,
- HttpOptions * options,
- HttpHeaders * headers);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
HttpStatus setupPost(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
HttpStatus setupPut(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
+
+ HttpStatus setupDelete(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
+
+ HttpStatus setupPatch(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ BufferArray * body,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
- // Internal method used to setup the libcurl options for a request.
+ HttpStatus setupCopy(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
+
+ HttpStatus setupMove(HttpRequest::policy_t policy_id,
+ HttpRequest::priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
+
+ // Internal method used to setup the libcurl options for a request.
// Does all the libcurl handle setup in one place.
//
// Threading: called by worker thread
@@ -141,8 +174,8 @@ protected:
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers);
// libcurl operational callbacks
//
@@ -150,7 +183,11 @@ protected:
//
static size_t writeCallback(void * data, size_t size, size_t nmemb, void * userdata);
static size_t readCallback(void * data, size_t size, size_t nmemb, void * userdata);
+ static int seekCallback(void *data, curl_off_t offset, int origin);
static size_t headerCallback(void * data, size_t size, size_t nmemb, void * userdata);
+ static CURLcode curlSslCtxCallback(CURL *curl, void *ssl_ctx, void *userptr);
+ static int sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
+
static int debugCallback(CURL *, curl_infotype info, char * buffer, size_t len, void * userdata);
protected:
@@ -159,6 +196,8 @@ protected:
static const unsigned int PF_SAVE_HEADERS = 0x00000002U;
static const unsigned int PF_USE_RETRY_AFTER = 0x00000004U;
+ HttpRequest::policyCallback_t mCallbackSSLVerify;
+
public:
// Request data
EMethod mReqMethod;
@@ -166,8 +205,8 @@ public:
BufferArray * mReqBody;
off_t mReqOffset;
size_t mReqLength;
- HttpHeaders * mReqHeaders;
- HttpOptions * mReqOptions;
+ HttpHeaders::ptr_t mReqHeaders;
+ HttpOptions::ptr_t mReqOptions;
// Transport data
bool mCurlActive;
@@ -184,7 +223,7 @@ public:
off_t mReplyOffset;
size_t mReplyLength;
size_t mReplyFullLength;
- HttpHeaders * mReplyHeaders;
+ HttpHeaders::ptr_t mReplyHeaders;
std::string mReplyConType;
int mReplyRetryAfter;
@@ -215,7 +254,7 @@ public:
// Internal function to append the contents of an HttpHeaders
// instance to a curl_slist object.
-curl_slist * append_headers_to_slist(const HttpHeaders *, curl_slist * slist);
+curl_slist * append_headers_to_slist(const HttpHeaders::ptr_t &, curl_slist * slist);
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httpopsetget.h b/indra/llcorehttp/_httpopsetget.h
index a1e76dd429..eabd41e79f 100755
--- a/indra/llcorehttp/_httpopsetget.h
+++ b/indra/llcorehttp/_httpopsetget.h
@@ -53,9 +53,10 @@ namespace LLCore
class HttpOpSetGet : public HttpOperation
{
public:
+ typedef boost::shared_ptr<HttpOpSetGet> ptr_t;
+
HttpOpSetGet();
-protected:
virtual ~HttpOpSetGet(); // Use release()
private:
diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h
index 31706b737c..43e2aa081b 100755
--- a/indra/llcorehttp/_httpopsetpriority.h
+++ b/indra/llcorehttp/_httpopsetpriority.h
@@ -51,7 +51,6 @@ class HttpOpSetPriority : public HttpOperation
public:
HttpOpSetPriority(HttpHandle handle, HttpRequest::priority_t priority);
-protected:
virtual ~HttpOpSetPriority();
private:
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index e5d6321401..b2709b53ec 100755
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -116,21 +116,19 @@ void HttpPolicy::shutdown()
HttpRetryQueue & retryq(state.mRetryQueue);
while (! retryq.empty())
{
- HttpOpRequest * op(retryq.top());
+ HttpOpRequest::ptr_t op(retryq.top());
retryq.pop();
op->cancel();
- op->release();
}
HttpReadyQueue & readyq(state.mReadyQueue);
while (! readyq.empty())
{
- HttpOpRequest * op(readyq.top());
+ HttpOpRequest::ptr_t op(readyq.top());
readyq.pop();
op->cancel();
- op->release();
}
}
}
@@ -141,7 +139,7 @@ void HttpPolicy::start()
}
-void HttpPolicy::addOp(HttpOpRequest * op)
+void HttpPolicy::addOp(const HttpOpRequest::ptr_t &op)
{
const int policy_class(op->mReqPolicy);
@@ -151,7 +149,7 @@ void HttpPolicy::addOp(HttpOpRequest * op)
}
-void HttpPolicy::retryOp(HttpOpRequest * op)
+void HttpPolicy::retryOp(const HttpOpRequest::ptr_t &op)
{
static const HttpTime retry_deltas[] =
{
@@ -180,7 +178,7 @@ void HttpPolicy::retryOp(HttpOpRequest * op)
{
++op->mPolicy503Retries;
}
- LL_DEBUGS(LOG_CORE) << "HTTP request " << static_cast<HttpHandle>(op)
+ LL_DEBUGS(LOG_CORE) << "HTTP request " << op->getHandle()
<< " retry " << op->mPolicyRetries
<< " scheduled in " << (delta / HttpTime(1000))
<< " mS (" << (external_delta ? "external" : "internal")
@@ -189,10 +187,10 @@ void HttpPolicy::retryOp(HttpOpRequest * op)
if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS(LOG_CORE) << "TRACE, ToRetryQueue, Handle: "
- << static_cast<HttpHandle>(op)
- << ", Delta: " << (delta / HttpTime(1000))
- << ", Retries: " << op->mPolicyRetries
- << LL_ENDL;
+ << op->getHandle()
+ << ", Delta: " << (delta / HttpTime(1000))
+ << ", Retries: " << op->mPolicyRetries
+ << LL_ENDL;
}
mClasses[policy_class]->mRetryQueue.push(op);
}
@@ -264,14 +262,14 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
// First see if we have any retries...
while (needed > 0 && ! retryq.empty())
{
- HttpOpRequest * op(retryq.top());
+ HttpOpRequest::ptr_t op(retryq.top());
if (op->mPolicyRetryAt > now)
break;
retryq.pop();
op->stageFromReady(mService);
- op->release();
+ op.reset();
++state.mRequestCount;
--needed;
@@ -296,11 +294,11 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
// Now go on to the new requests...
while (needed > 0 && ! readyq.empty())
{
- HttpOpRequest * op(readyq.top());
+ HttpOpRequest::ptr_t op(readyq.top());
readyq.pop();
op->stageFromReady(mService);
- op->release();
+ op.reset();
++state.mRequestCount;
--needed;
@@ -351,9 +349,9 @@ bool HttpPolicy::changePriority(HttpHandle handle, HttpRequest::priority_t prior
{
HttpReadyQueue::container_type::iterator cur(iter++);
- if (static_cast<HttpHandle>(*cur) == handle)
+ if ((*cur)->getHandle() == handle)
{
- HttpOpRequest * op(*cur);
+ HttpOpRequest::ptr_t op(*cur);
c.erase(cur); // All iterators are now invalidated
op->mReqPriority = priority;
state.mReadyQueue.push(op); // Re-insert using adapter class
@@ -378,12 +376,11 @@ bool HttpPolicy::cancel(HttpHandle handle)
{
HttpRetryQueue::container_type::iterator cur(iter++);
- if (static_cast<HttpHandle>(*cur) == handle)
+ if ((*cur)->getHandle() == handle)
{
- HttpOpRequest * op(*cur);
+ HttpOpRequest::ptr_t op(*cur);
c1.erase(cur); // All iterators are now invalidated
op->cancel();
- op->release();
return true;
}
}
@@ -394,12 +391,11 @@ bool HttpPolicy::cancel(HttpHandle handle)
{
HttpReadyQueue::container_type::iterator cur(iter++);
- if (static_cast<HttpHandle>(*cur) == handle)
+ if ((*cur)->getHandle() == handle)
{
- HttpOpRequest * op(*cur);
+ HttpOpRequest::ptr_t op(*cur);
c2.erase(cur); // All iterators are now invalidated
op->cancel();
- op->release();
return true;
}
}
@@ -409,7 +405,7 @@ bool HttpPolicy::cancel(HttpHandle handle)
}
-bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
+bool HttpPolicy::stageAfterCompletion(const HttpOpRequest::ptr_t &op)
{
// Retry or finalize
if (! op->mStatus)
@@ -420,7 +416,7 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
#if 0
if (op->mStatus == HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT))
{
- LL_WARNS(LOG_CORE) << "HTTP request " << static_cast<HttpHandle>(op)
+ LL_WARNS(LOG_CORE) << "HTTP request " << op->getHandle()
<< " timed out."
<< LL_ENDL;
}
@@ -438,7 +434,7 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
// This op is done, finalize it delivering it to the reply queue...
if (! op->mStatus)
{
- LL_WARNS(LOG_CORE) << "HTTP request " << static_cast<HttpHandle>(op)
+ LL_WARNS(LOG_CORE) << "HTTP request " << op->getHandle()
<< " failed after " << op->mPolicyRetries
<< " retries. Reason: " << op->mStatus.toString()
<< " (" << op->mStatus.toTerseString() << ")"
@@ -446,13 +442,12 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
}
else if (op->mPolicyRetries)
{
- LL_DEBUGS(LOG_CORE) << "HTTP request " << static_cast<HttpHandle>(op)
+ LL_DEBUGS(LOG_CORE) << "HTTP request " << op->getHandle()
<< " succeeded on retry " << op->mPolicyRetries << "."
<< LL_ENDL;
}
op->stageFromActive(mService);
- op->release();
return false; // not active
}
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index 11cd89bbd1..3c4126e14b 100755
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -60,6 +60,8 @@ private:
void operator=(const HttpPolicy &); // Not defined
public:
+ typedef boost::shared_ptr<HttpOpRequest> opReqPtr_t;
+
/// Threading: called by init thread.
HttpRequest::policy_t createPolicyClass();
@@ -96,7 +98,7 @@ public:
/// from queue.
///
/// Threading: called by worker thread
- void addOp(HttpOpRequest *);
+ void addOp(const opReqPtr_t &);
/// Similar to addOp, used when a caller wants to retry a
/// request that has failed. It's placed on a special retry
@@ -106,7 +108,7 @@ public:
/// order.
///
/// Threading: called by worker thread
- void retryOp(HttpOpRequest *);
+ void retryOp(const opReqPtr_t &);
/// Attempt to change the priority of an earlier request.
/// Request that Shadows HttpService's method
@@ -130,7 +132,7 @@ public:
/// sent on to the reply queue.
///
/// Threading: called by worker thread
- bool stageAfterCompletion(HttpOpRequest * op);
+ bool stageAfterCompletion(const opReqPtr_t &op);
/// Get a reference to global policy options. Caller is expected
/// to do context checks like no setting once running. These
diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp
index 1dc95f3dce..3d0df96ade 100755
--- a/indra/llcorehttp/_httppolicyglobal.cpp
+++ b/indra/llcorehttp/_httppolicyglobal.cpp
@@ -106,6 +106,20 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, const std::stri
return HttpStatus();
}
+HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value)
+{
+ switch (opt)
+ {
+ case HttpRequest::PO_SSL_VERIFY_CALLBACK:
+ mSslCtxCallback = value;
+ break;
+
+ default:
+ return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
+ }
+
+ return HttpStatus();
+}
HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, long * value) const
{
@@ -154,4 +168,20 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, std::string * v
return HttpStatus();
}
+
+HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const
+{
+ switch (opt)
+ {
+ case HttpRequest::PO_SSL_VERIFY_CALLBACK:
+ *value = mSslCtxCallback;
+ break;
+
+ default:
+ return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
+ }
+
+ return HttpStatus();
+}
+
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httppolicyglobal.h b/indra/llcorehttp/_httppolicyglobal.h
index 67c4ba9481..e02da4386a 100755
--- a/indra/llcorehttp/_httppolicyglobal.h
+++ b/indra/llcorehttp/_httppolicyglobal.h
@@ -60,8 +60,10 @@ private:
public:
HttpStatus set(HttpRequest::EPolicyOption opt, long value);
HttpStatus set(HttpRequest::EPolicyOption opt, const std::string & value);
+ HttpStatus set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value);
HttpStatus get(HttpRequest::EPolicyOption opt, long * value) const;
HttpStatus get(HttpRequest::EPolicyOption opt, std::string * value) const;
+ HttpStatus get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const;
public:
long mConnectionLimit;
@@ -70,6 +72,7 @@ public:
std::string mHttpProxy;
long mTrace;
long mUseLLProxy;
+ HttpRequest::policyCallback_t mSslCtxCallback;
}; // end class HttpPolicyGlobal
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httpreadyqueue.h b/indra/llcorehttp/_httpreadyqueue.h
index 5f19a9c5f9..7418988ec1 100755
--- a/indra/llcorehttp/_httpreadyqueue.h
+++ b/indra/llcorehttp/_httpreadyqueue.h
@@ -56,12 +56,12 @@ namespace LLCore
#if LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
-typedef std::deque<HttpOpRequest *> HttpReadyQueueBase;
+typedef std::deque<HttpOpRequest::ptr_t> HttpReadyQueueBase;
#else
-typedef std::priority_queue<HttpOpRequest *,
- std::deque<HttpOpRequest *>,
+typedef std::priority_queue<HttpOpRequest::ptr_t,
+ std::deque<HttpOpRequest::ptr_t>,
LLCore::HttpOpRequestCompare> HttpReadyQueueBase;
#endif // LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp
index 558b7bdee9..2b138f3ad5 100755
--- a/indra/llcorehttp/_httpreplyqueue.cpp
+++ b/indra/llcorehttp/_httpreplyqueue.cpp
@@ -39,23 +39,17 @@ namespace LLCore
HttpReplyQueue::HttpReplyQueue()
- : RefCounted(true)
{
}
HttpReplyQueue::~HttpReplyQueue()
{
- while (! mQueue.empty())
- {
- HttpOperation * op = mQueue.back();
- mQueue.pop_back();
- op->release();
- }
+ mQueue.clear();
}
-void HttpReplyQueue::addOp(HttpOperation * op)
+void HttpReplyQueue::addOp(const HttpReplyQueue::opPtr_t &op)
{
{
HttpScopedLock lock(mQueueMutex);
@@ -66,15 +60,15 @@ void HttpReplyQueue::addOp(HttpOperation * op)
}
-HttpOperation * HttpReplyQueue::fetchOp()
+HttpReplyQueue::opPtr_t HttpReplyQueue::fetchOp()
{
- HttpOperation * result(NULL);
+ HttpOperation::ptr_t result;
{
HttpScopedLock lock(mQueueMutex);
if (mQueue.empty())
- return NULL;
+ return opPtr_t();
result = mQueue.front();
mQueue.erase(mQueue.begin());
@@ -98,9 +92,6 @@ void HttpReplyQueue::fetchAll(OpContainer & ops)
mQueue.swap(ops);
}
}
-
- // Caller also acquires the reference counts on each op.
- return;
}
diff --git a/indra/llcorehttp/_httpreplyqueue.h b/indra/llcorehttp/_httpreplyqueue.h
index 4220a09a3b..0e39e22dde 100755
--- a/indra/llcorehttp/_httpreplyqueue.h
+++ b/indra/llcorehttp/_httpreplyqueue.h
@@ -58,21 +58,19 @@ class HttpOperation;
/// will be coded anyway so it shouldn't be too much of a
/// burden.
-class HttpReplyQueue : public LLCoreInt::RefCounted
+class HttpReplyQueue : private boost::noncopyable
{
-public:
- /// Caller acquires a Refcount on construction
- HttpReplyQueue();
-protected:
- virtual ~HttpReplyQueue(); // Use release()
+public:
+ typedef boost::shared_ptr<HttpOperation> opPtr_t;
+ typedef boost::shared_ptr<HttpReplyQueue> ptr_t;
-private:
- HttpReplyQueue(const HttpReplyQueue &); // Not defined
- void operator=(const HttpReplyQueue &); // Not defined
+ HttpReplyQueue();
+ virtual ~HttpReplyQueue();
public:
- typedef std::vector<HttpOperation *> OpContainer;
+
+ typedef std::vector< opPtr_t > OpContainer;
/// Insert an object at the back of the reply queue.
///
@@ -80,7 +78,7 @@ public:
/// through the queue.
///
/// Threading: callable by any thread.
- void addOp(HttpOperation * op);
+ void addOp(const opPtr_t &op);
/// Fetch an operation from the head of the queue. Returns
/// NULL if none exists.
@@ -88,7 +86,7 @@ public:
/// Caller acquires reference count on returned operation.
///
/// Threading: callable by any thread.
- HttpOperation * fetchOp();
+ opPtr_t fetchOp();
/// Caller acquires reference count on each returned operation
///
@@ -96,6 +94,7 @@ public:
void fetchAll(OpContainer & ops);
protected:
+
OpContainer mQueue;
LLCoreInt::HttpMutex mQueueMutex;
LLCoreInt::HttpConditionVariable mQueueCV;
diff --git a/indra/llcorehttp/_httprequestqueue.cpp b/indra/llcorehttp/_httprequestqueue.cpp
index c16966d078..c6f4ad789f 100755
--- a/indra/llcorehttp/_httprequestqueue.cpp
+++ b/indra/llcorehttp/_httprequestqueue.cpp
@@ -47,12 +47,7 @@ HttpRequestQueue::HttpRequestQueue()
HttpRequestQueue::~HttpRequestQueue()
{
- while (! mQueue.empty())
- {
- HttpOperation * op = mQueue.back();
- mQueue.pop_back();
- op->release();
- }
+ mQueue.clear();
}
@@ -73,7 +68,7 @@ void HttpRequestQueue::term()
}
-HttpStatus HttpRequestQueue::addOp(HttpOperation * op)
+HttpStatus HttpRequestQueue::addOp(const HttpRequestQueue::opPtr_t &op)
{
bool wake(false);
{
@@ -95,9 +90,9 @@ HttpStatus HttpRequestQueue::addOp(HttpOperation * op)
}
-HttpOperation * HttpRequestQueue::fetchOp(bool wait)
+HttpRequestQueue::opPtr_t HttpRequestQueue::fetchOp(bool wait)
{
- HttpOperation * result(NULL);
+ HttpOperation::ptr_t result;
{
HttpScopedLock lock(mQueueMutex);
@@ -105,7 +100,7 @@ HttpOperation * HttpRequestQueue::fetchOp(bool wait)
while (mQueue.empty())
{
if (! wait || mQueueStopped)
- return NULL;
+ return HttpOperation::ptr_t();
mQueueCV.wait(lock);
}
diff --git a/indra/llcorehttp/_httprequestqueue.h b/indra/llcorehttp/_httprequestqueue.h
index c9c52b7233..3c3d134b07 100755
--- a/indra/llcorehttp/_httprequestqueue.h
+++ b/indra/llcorehttp/_httprequestqueue.h
@@ -61,6 +61,8 @@ private:
void operator=(const HttpRequestQueue &); // Not defined
public:
+ typedef boost::shared_ptr<HttpOperation> opPtr_t;
+
static void init();
static void term();
@@ -71,7 +73,7 @@ public:
}
public:
- typedef std::vector<HttpOperation *> OpContainer;
+ typedef std::vector<opPtr_t> OpContainer;
/// Insert an object at the back of the request queue.
///
@@ -83,7 +85,7 @@ public:
/// an explicit release() call.
///
/// Threading: callable by any thread.
- HttpStatus addOp(HttpOperation * op);
+ HttpStatus addOp(const opPtr_t &op);
/// Return the operation on the front of the queue. If
/// the queue is empty and @wait is false, call returns
@@ -95,7 +97,7 @@ public:
/// Caller acquires reference count any returned operation
///
/// Threading: callable by any thread.
- HttpOperation * fetchOp(bool wait);
+ opPtr_t fetchOp(bool wait);
/// Return all queued requests to caller. The @ops argument
/// should be empty when called and will be swap()'d with
diff --git a/indra/llcorehttp/_httpretryqueue.h b/indra/llcorehttp/_httpretryqueue.h
index 745adec09d..5d8c529cff 100755
--- a/indra/llcorehttp/_httpretryqueue.h
+++ b/indra/llcorehttp/_httpretryqueue.h
@@ -49,15 +49,15 @@ namespace LLCore
struct HttpOpRetryCompare
{
- bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs)
+ bool operator()(const HttpOpRequest::ptr_t &lhs, const HttpOpRequest::ptr_t &rhs)
{
return lhs->mPolicyRetryAt < rhs->mPolicyRetryAt;
}
};
-typedef std::priority_queue<HttpOpRequest *,
- std::deque<HttpOpRequest *>,
+typedef std::priority_queue<HttpOpRequest::ptr_t,
+ std::deque<HttpOpRequest::ptr_t>,
LLCore::HttpOpRetryCompare> HttpRetryQueueBase;
class HttpRetryQueue : public HttpRetryQueueBase
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index c673e1be1d..6c39fdc61b 100755
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -53,15 +53,16 @@ namespace LLCore
const HttpService::OptionDescriptor HttpService::sOptionDesc[] =
{ // isLong isDynamic isGlobal isClass
- { true, true, true, true }, // PO_CONNECTION_LIMIT
- { true, true, false, true }, // PO_PER_HOST_CONNECTION_LIMIT
- { false, false, true, false }, // PO_CA_PATH
- { false, false, true, false }, // PO_CA_FILE
- { false, true, true, false }, // PO_HTTP_PROXY
- { true, true, true, false }, // PO_LLPROXY
- { true, true, true, false }, // PO_TRACE
- { true, true, false, true }, // PO_ENABLE_PIPELINING
- { true, true, false, true } // PO_THROTTLE_RATE
+ { true, true, true, true, false }, // PO_CONNECTION_LIMIT
+ { true, true, false, true, false }, // PO_PER_HOST_CONNECTION_LIMIT
+ { false, false, true, false, false }, // PO_CA_PATH
+ { false, false, true, false, false }, // PO_CA_FILE
+ { false, true, true, false, false }, // PO_HTTP_PROXY
+ { true, true, true, false, false }, // PO_LLPROXY
+ { true, true, true, false, false }, // PO_TRACE
+ { true, true, false, true, false }, // PO_ENABLE_PIPELINING
+ { true, true, false, true, false }, // PO_THROTTLE_RATE
+ { false, false, true, false, true } // PO_SSL_VERIFY_CALLBACK
};
HttpService * HttpService::sInstance(NULL);
volatile HttpService::EState HttpService::sState(NOT_INITIALIZED);
@@ -262,14 +263,13 @@ void HttpService::shutdown()
// Cancel requests already on the request queue
HttpRequestQueue::OpContainer ops;
mRequestQueue->fetchAll(false, ops);
- while (! ops.empty())
- {
- HttpOperation * op(ops.front());
- ops.erase(ops.begin());
- op->cancel();
- op->release();
- }
+ for (HttpRequestQueue::OpContainer::iterator it = ops.begin();
+ it != ops.end(); ++it)
+ {
+ (*it)->cancel();
+ }
+ ops.clear();
// Shutdown transport canceling requests, freeing resources
mTransport->shutdown();
@@ -323,7 +323,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
mRequestQueue->fetchAll(wait_for_req, ops);
while (! ops.empty())
{
- HttpOperation * op(ops.front());
+ HttpOperation::ptr_t op(ops.front());
ops.erase(ops.begin());
// Process operation
@@ -337,7 +337,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS(LOG_CORE) << "TRACE, FromRequestQueue, Handle: "
- << static_cast<HttpHandle>(op)
+ << op->getHandle()
<< LL_ENDL;
}
@@ -346,7 +346,7 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
}
// Done with operation
- op->release();
+ op.reset();
}
// Queue emptied, allow polling loop to sleep
@@ -413,6 +413,34 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
return status;
}
+HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+ HttpRequest::policyCallback_t * ret_value)
+{
+ HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
+
+ if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
+ || opt >= HttpRequest::PO_LAST // ditto
+ || (sOptionDesc[opt].mIsLong) // datatype is string
+ || (pclass != HttpRequest::GLOBAL_POLICY_ID && pclass > mLastPolicy) // pclass in valid range
+ || (pclass == HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsGlobal) // global setting permitted
+ || (pclass != HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsClass)) // class setting permitted
+ // can always get, no dynamic check
+ {
+ return status;
+ }
+
+ // Only global has callback values
+ if (pclass == HttpRequest::GLOBAL_POLICY_ID)
+ {
+ HttpPolicyGlobal & opts(mPolicy->getGlobalOptions());
+
+ status = opts.get(opt, ret_value);
+ }
+
+ return status;
+}
+
+
HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
long value, long * ret_value)
@@ -489,6 +517,37 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
return status;
}
-
+
+HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+ HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value)
+{
+ HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
+
+ if (opt < HttpRequest::PO_CONNECTION_LIMIT // option must be in range
+ || opt >= HttpRequest::PO_LAST // ditto
+ || (sOptionDesc[opt].mIsLong) // datatype is string
+ || (pclass != HttpRequest::GLOBAL_POLICY_ID && pclass > mLastPolicy) // pclass in valid range
+ || (pclass == HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsGlobal) // global setting permitted
+ || (pclass != HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsClass) // class setting permitted
+ || (RUNNING == sState && !sOptionDesc[opt].mIsDynamic)) // dynamic setting permitted
+ {
+ return status;
+ }
+
+ // Callbacks values are always global (at this time).
+ if (pclass == HttpRequest::GLOBAL_POLICY_ID)
+ {
+ HttpPolicyGlobal & opts(mPolicy->getGlobalOptions());
+
+ status = opts.set(opt, value);
+ if (status && ret_value)
+ {
+ status = opts.get(opt, ret_value);
+ }
+ }
+
+ return status;
+}
+
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index cf23f3ab61..ac518a5de7 100755
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -201,17 +201,24 @@ protected:
bool mIsDynamic;
bool mIsGlobal;
bool mIsClass;
+ bool mIsCallback;
};
HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
long * ret_value);
HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
std::string * ret_value);
+ HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
+ HttpRequest::policyCallback_t * ret_value);
+
HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
long value, long * ret_value);
HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
const std::string & value, std::string * ret_value);
-
+ HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
+ HttpRequest::policyCallback_t value,
+ HttpRequest::policyCallback_t * ret_value);
+
protected:
static const OptionDescriptor sOptionDesc[HttpRequest::PO_LAST];
static HttpService * sInstance;
diff --git a/indra/llcorehttp/_refcounted.h b/indra/llcorehttp/_refcounted.h
index 402e725152..7f713f2298 100755
--- a/indra/llcorehttp/_refcounted.h
+++ b/indra/llcorehttp/_refcounted.h
@@ -32,6 +32,7 @@
#include "fix_macros.h"
#include <boost/thread.hpp>
+#include <boost/intrusive_ptr.hpp>
#include "llapr.h"
@@ -120,7 +121,36 @@ inline void RefCounted::destroySelf()
delete this;
}
+/**
+ * boost::intrusive_ptr may be used to manage RefCounted classes.
+ * Unfortunately RefCounted and boost::intrusive_ptr use different conventions
+ * for the initial refcount value. To avoid leaky (immortal) objects, you
+ * should really construct boost::intrusive_ptr<RefCounted*>(rawptr, false).
+ * IntrusivePtr<T> encapsulates that for you.
+ */
+template <typename T>
+struct IntrusivePtr: public boost::intrusive_ptr<T>
+{
+ IntrusivePtr():
+ boost::intrusive_ptr<T>()
+ {}
+ IntrusivePtr(T* p):
+ boost::intrusive_ptr<T>(p, false)
+ {}
+};
+
+inline void intrusive_ptr_add_ref(RefCounted* p)
+{
+ p->addRef();
+}
+
+inline void intrusive_ptr_release(RefCounted* p)
+{
+ p->release();
+}
+
} // end namespace LLCoreInt
+
#endif // LLCOREINT__REFCOUNTED_H_
diff --git a/indra/llcorehttp/bufferarray.h b/indra/llcorehttp/bufferarray.h
index 1094a435b4..320adf2b8b 100755
--- a/indra/llcorehttp/bufferarray.h
+++ b/indra/llcorehttp/bufferarray.h
@@ -30,6 +30,7 @@
#include <cstdlib>
#include <vector>
+#include "boost/intrusive_ptr.hpp"
#include "_refcounted.h"
@@ -73,6 +74,8 @@ public:
BufferArray();
+ typedef LLCoreInt::IntrusivePtr<BufferArray> ptr_t;
+
protected:
virtual ~BufferArray(); // Use release()
@@ -129,6 +132,7 @@ protected:
container_t mBlocks;
size_t mLen;
+
}; // end class BufferArray
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index 9d9631b980..b91aaf0593 100755
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -83,7 +83,7 @@ public:
WorkingSet();
~WorkingSet();
- bool reload(LLCore::HttpRequest *, LLCore::HttpOptions *);
+ bool reload(LLCore::HttpRequest *, LLCore::HttpOptions::ptr_t &);
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
@@ -121,7 +121,7 @@ public:
int mRetriesHttp503;
int mSuccesses;
long mByteCount;
- LLCore::HttpHeaders * mHeaders;
+ LLCore::HttpHeaders::ptr_t mHeaders;
};
@@ -304,7 +304,7 @@ int main(int argc, char** argv)
LLCore::HttpRequest * hr = new LLCore::HttpRequest();
// Get request options
- LLCore::HttpOptions * opt = new LLCore::HttpOptions();
+ LLCore::HttpOptions::ptr_t opt = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
opt->setRetries(12);
opt->setUseRetryAfter(true);
@@ -361,10 +361,9 @@ int main(int argc, char** argv)
<< std::endl;
// Clean up
- hr->requestStopThread(NULL);
+ hr->requestStopThread(LLCore::HttpHandler::ptr_t());
ms_sleep(1000);
- opt->release();
- opt = NULL;
+ opt.reset();
delete hr;
LLCore::HttpRequest::destroyService();
term_curl();
@@ -427,22 +426,22 @@ WorkingSet::WorkingSet()
{
mAssets.reserve(30000);
- mHeaders = new LLCore::HttpHeaders;
+ mHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHeaders->append("Accept", "image/x-j2c");
}
WorkingSet::~WorkingSet()
{
- if (mHeaders)
- {
- mHeaders->release();
- mHeaders = NULL;
- }
}
+namespace
+{
+ void NoOpDeletor(LLCore::HttpHandler *)
+ { /*NoOp*/ }
+}
-bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions * opt)
+bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & opt)
{
if (mRequestLowWater <= mHandles.size())
{
@@ -470,11 +469,11 @@ bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions * opt)
LLCore::HttpHandle handle;
if (offset || length)
{
- handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, this);
+ handle = hr->requestGetByteRange(0, 0, buffer, offset, length, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
else
{
- handle = hr->requestGet(0, 0, buffer, opt, mHeaders, this);
+ handle = hr->requestGet(0, 0, buffer, opt, mHeaders, LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
}
if (! handle)
{
diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index 7907e958a4..c423047bb0 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
@@ -42,7 +54,7 @@ HttpStatus::operator unsigned long() const
{
static const int shift(sizeof(unsigned long) * 4);
- unsigned long result(((unsigned long) mType) << shift | (unsigned long) (int) mStatus);
+ unsigned long result(((unsigned long)mDetails->mType) << shift | (unsigned long)(int)mDetails->mStatus);
return result;
}
@@ -131,30 +143,34 @@ std::string HttpStatus::toString() const
{
return std::string("");
}
- switch (mType)
+ switch (getType())
{
case EXT_CURL_EASY:
- return std::string(curl_easy_strerror(CURLcode(mStatus)));
+ return std::string(curl_easy_strerror(CURLcode(getStatus())));
case EXT_CURL_MULTI:
- return std::string(curl_multi_strerror(CURLMcode(mStatus)));
+ return std::string(curl_multi_strerror(CURLMcode(getStatus())));
case LLCORE:
- if (mStatus >= 0 && mStatus < llcore_errors_count)
+ if (getStatus() >= 0 && getStatus() < llcore_errors_count)
{
- return std::string(llcore_errors[mStatus]);
+ return std::string(llcore_errors[getStatus()]);
}
break;
default:
if (isHttpStatus())
{
+ // special handling for status 499 "Linden Catchall"
+ if ((getType() == 499) && (!getMessage().empty()))
+ return getMessage();
+
// Binary search for the error code and string
int bottom(0), top(http_errors_count);
while (true)
{
int at((bottom + top) / 2);
- if (mType == http_errors[at].mCode)
+ if (getType() == http_errors[at].mCode)
{
return std::string(http_errors[at].mText);
}
@@ -162,7 +178,7 @@ std::string HttpStatus::toString() const
{
break;
}
- else if (mType < http_errors[at].mCode)
+ else if (getType() < http_errors[at].mCode)
{
top = at;
}
@@ -182,9 +198,9 @@ std::string HttpStatus::toTerseString() const
{
std::ostringstream result;
- unsigned int error_value((unsigned short) mStatus);
+ unsigned int error_value((unsigned short)getStatus());
- switch (mType)
+ switch (getType())
{
case EXT_CURL_EASY:
result << "Easy_";
@@ -202,7 +218,7 @@ std::string HttpStatus::toTerseString() const
if (isHttpStatus())
{
result << "Http_";
- error_value = mType;
+ error_value = getType();
}
else
{
@@ -244,7 +260,7 @@ bool HttpStatus::isRetryable() const
// Disable the '*this == inv_status' test and look for 'Core_9'
// failures in log files.
- return ((isHttpStatus() && mType >= 499 && mType <= 599) || // Include special 499 in retryables
+ return ((isHttpStatus() && getType() >= 499 && getType() <= 599) || // Include special 499 in retryables
*this == cant_connect || // Connection reset/endpoint problems
*this == cant_res_proxy || // DNS problems
*this == cant_res_host || // DNS problems
@@ -259,5 +275,168 @@ 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 (type >= sSSLMutex.size())
+ {
+ LL_WARNS() << "Attempt to get unknown MUTEX in SSL Lock." << LL_ENDL;
+ }
+
+ 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
+
+}
+
+
+void cleanup()
+{
+#if SAFE_SSL
+ CRYPTO_set_id_callback(NULL);
+ CRYPTO_set_locking_callback(NULL);
+ sSSLMutex.clear();
+#endif
+
+ curl_global_cleanup();
+}
+
+
+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 9601f94125..b2db01d038 100755
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -188,9 +188,12 @@
///
#include "linden_common.h" // Modifies curl/curl.h interfaces
-
+#include "boost/intrusive_ptr.hpp"
+#include "boost/shared_ptr.hpp"
+#include "boost/weak_ptr.hpp"
+#include "boost/function.hpp"
#include <string>
-
+#include <curl/curl.h>
namespace LLCore
{
@@ -206,6 +209,7 @@ namespace LLCore
/// becomes invalid and may be recycled for other queued requests.
typedef void * HttpHandle;
+
#define LLCORE_HTTP_HANDLE_INVALID (NULL)
/// For internal scheduling and metrics, we use a microsecond
@@ -286,52 +290,63 @@ enum HttpError
/// 5. Construct an HTTP 301 status code to be treated as success:
/// HttpStatus(301, HE_SUCCESS);
///
+/// 6. Construct a failed status of HTTP Status 499 with a custom error message
+/// HttpStatus(499, "Failed LLSD Response");
struct HttpStatus
{
typedef unsigned short type_enum_t;
HttpStatus()
- : mType(LLCORE),
- mStatus(HE_SUCCESS)
- {}
+ {
+ mDetails = boost::shared_ptr<Details>(new Details(LLCORE, HE_SUCCESS));
+ }
HttpStatus(type_enum_t type, short status)
- : mType(type),
- mStatus(status)
- {}
+ {
+ mDetails = boost::shared_ptr<Details>(new Details(type, status));
+ }
HttpStatus(int http_status)
- : mType(http_status),
- mStatus(http_status >= 200 && http_status <= 299
- ? HE_SUCCESS
- : HE_REPLY_ERROR)
- {
- llassert(http_status >= 100 && http_status <= 999);
- }
+ {
+ mDetails = boost::shared_ptr<Details>(new Details(http_status,
+ (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR));
+ llassert(http_status >= 100 && http_status <= 999);
+ }
+
+ HttpStatus(int http_status, const std::string &message)
+ {
+ mDetails = boost::shared_ptr<Details>(new Details(http_status,
+ (http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR));
+ llassert(http_status >= 100 && http_status <= 999);
+ mDetails->mMessage = message;
+ }
HttpStatus(const HttpStatus & rhs)
- : mType(rhs.mType),
- mStatus(rhs.mStatus)
- {}
+ {
+ mDetails = rhs.mDetails;
+ }
+
+ ~HttpStatus()
+ {
+ }
HttpStatus & operator=(const HttpStatus & rhs)
- {
- // Don't care if lhs & rhs are the same object
+ {
+ mDetails = rhs.mDetails;
+ return *this;
+ }
- mType = rhs.mType;
- mStatus = rhs.mStatus;
- return *this;
- }
+ HttpStatus & clone(const HttpStatus &rhs)
+ {
+ mDetails = boost::shared_ptr<Details>(new Details(*rhs.mDetails));
+ return *this;
+ }
static const type_enum_t EXT_CURL_EASY = 0; ///< mStatus is an error from a curl_easy_*() call
static const type_enum_t EXT_CURL_MULTI = 1; ///< mStatus is an error from a curl_multi_*() call
static const type_enum_t LLCORE = 2; ///< mStatus is an HE_* error code
///< 100-999 directly represent HTTP status codes
-
- type_enum_t mType;
- short mStatus;
-
/// Test for successful status in the code regardless
/// of error source (internal, libcurl).
///
@@ -339,7 +354,7 @@ struct HttpStatus
///
operator bool() const
{
- return 0 == mStatus;
+ return 0 == mDetails->mStatus;
}
/// Inverse of previous operator.
@@ -347,14 +362,14 @@ struct HttpStatus
/// @return 'true' on any error condition
bool operator !() const
{
- return 0 != mStatus;
+ return 0 != mDetails->mStatus;
}
/// Equality and inequality tests to bypass bool conversion
/// which will do the wrong thing in conditional expressions.
bool operator==(const HttpStatus & rhs) const
{
- return mType == rhs.mType && mStatus == rhs.mStatus;
+ return (*mDetails == *rhs.mDetails);
}
bool operator!=(const HttpStatus & rhs) const
@@ -395,7 +410,7 @@ struct HttpStatus
/// HTTP response status (100 - 999).
bool isHttpStatus() const
{
- return mType >= type_enum_t(100) && mType <= type_enum_t(999);
+ return mDetails->mType >= type_enum_t(100) && mDetails->mType <= type_enum_t(999);
}
/// Returns true if the status is one that will be retried
@@ -403,9 +418,94 @@ struct HttpStatus
/// where that logic needs to be replicated. Only applies
/// to failed statuses, successful statuses will return false.
bool isRetryable() const;
-
+
+ /// Returns the currently set status code as a raw number
+ ///
+ short getStatus() const
+ {
+ return mDetails->mStatus;
+ }
+
+ /// Returns the currently set status type
+ ///
+ type_enum_t getType() const
+ {
+ return mDetails->mType;
+ }
+
+ /// Returns an optional error message if one has been set.
+ ///
+ std::string getMessage() const
+ {
+ return mDetails->mMessage;
+ }
+
+ /// Sets an optional error message
+ ///
+ void setMessage(const std::string &message)
+ {
+ mDetails->mMessage = message;
+ }
+
+ /// Retrieves an optionally recorded SSL certificate.
+ void * getErrorData() const
+ {
+ return mDetails->mErrorData;
+ }
+
+ /// Optionally sets an SSL certificate on this status.
+ void setErrorData(void *data)
+ {
+ mDetails->mErrorData = data;
+ }
+
+private:
+
+ struct Details
+ {
+ Details(type_enum_t type, short status):
+ mType(type),
+ mStatus(status),
+ mMessage(),
+ mErrorData(NULL)
+ {}
+
+ Details(const Details &rhs) :
+ mType(rhs.mType),
+ mStatus(rhs.mStatus),
+ mMessage(rhs.mMessage),
+ mErrorData(rhs.mErrorData)
+ {}
+
+ bool operator == (const Details &rhs) const
+ {
+ return (mType == rhs.mType) && (mStatus == rhs.mStatus);
+ }
+
+ type_enum_t mType;
+ short mStatus;
+ std::string mMessage;
+ void * mErrorData;
+ };
+
+ boost::shared_ptr<Details> mDetails;
+
}; // end struct HttpStatus
+/// A namespace for several free methods and low level utilities.
+namespace LLHttp
+{
+ typedef boost::shared_ptr<CURL> CURL_ptr;
+
+ void initialize();
+ void cleanup();
+
+ 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/llcorehttp/httphandler.h b/indra/llcorehttp/httphandler.h
index 9171e4e7b9..65e043f5d3 100755
--- a/indra/llcorehttp/httphandler.h
+++ b/indra/llcorehttp/httphandler.h
@@ -45,7 +45,7 @@ class HttpResponse;
/// be shared by any number of requests and across instances
/// of HttpRequest running in the same thread.
///
-/// Threading: HttpHandler itself is pure interface and is
+/// Threading: HttpHandler itself is interface and is
/// tread-compatible. Most derivations, however, will have
/// different constraints.
///
@@ -53,12 +53,16 @@ class HttpResponse;
/// that is rarely a good idea. Queued requests and replies keep
/// a naked pointer to the handler and this can result in a
/// dangling pointer if lifetimes aren't managed correctly.
-
-class HttpHandler
+///
+/// *TODO: public std::enable_shared_from_this<HttpHandler>
+class HttpHandler
{
public:
+ typedef boost::shared_ptr<HttpHandler> ptr_t;
+ typedef boost::weak_ptr<HttpHandler> wptr_t;
+
virtual ~HttpHandler()
- {}
+ { }
/// Method invoked during calls to @see update(). Each invocation
/// represents the completion of some requested operation. Caller
diff --git a/indra/llcorehttp/httpheaders.cpp b/indra/llcorehttp/httpheaders.cpp
index 23ebea361c..f586191a7c 100755
--- a/indra/llcorehttp/httpheaders.cpp
+++ b/indra/llcorehttp/httpheaders.cpp
@@ -34,7 +34,6 @@ namespace LLCore
HttpHeaders::HttpHeaders()
- : RefCounted(true)
{}
@@ -105,7 +104,7 @@ void HttpHeaders::appendNormal(const char * header, size_t size)
// Find from end to simulate a tradition of using single-valued
// std::map for this in the past.
-const std::string * HttpHeaders::find(const char * name) const
+const std::string * HttpHeaders::find(const std::string &name) const
{
const_reverse_iterator iend(rend());
for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)
@@ -118,6 +117,24 @@ const std::string * HttpHeaders::find(const char * name) const
return NULL;
}
+void HttpHeaders::remove(const char *name)
+{
+ remove(std::string(name));
+}
+
+void HttpHeaders::remove(const std::string &name)
+{
+ iterator iend(end());
+ for (iterator iter(begin()); iend != iter; ++iter)
+ {
+ if ((*iter).first == name)
+ {
+ mHeaders.erase(iter);
+ return;
+ }
+ }
+}
+
// Standard Iterators
HttpHeaders::iterator HttpHeaders::begin()
diff --git a/indra/llcorehttp/httpheaders.h b/indra/llcorehttp/httpheaders.h
index f70cd898f3..b9168cb6ec 100755
--- a/indra/llcorehttp/httpheaders.h
+++ b/indra/llcorehttp/httpheaders.h
@@ -28,8 +28,8 @@
#define _LLCORE_HTTP_HEADERS_H_
+#include "httpcommon.h"
#include <string>
-
#include "_refcounted.h"
@@ -74,7 +74,7 @@ namespace LLCore
/// constructor is given a refcount.
///
-class HttpHeaders : public LLCoreInt::RefCounted
+class HttpHeaders: private boost::noncopyable
{
public:
typedef std::pair<std::string, std::string> header_t;
@@ -85,15 +85,17 @@ public:
typedef container_t::const_reverse_iterator const_reverse_iterator;
typedef container_t::value_type value_type;
typedef container_t::size_type size_type;
+ typedef boost::shared_ptr<HttpHeaders> ptr_t;
public:
/// @post In addition to the instance, caller has a refcount
/// to the instance. A call to @see release() will destroy
/// the instance.
HttpHeaders();
+ virtual ~HttpHeaders(); // Use release()
+ //typedef LLCoreInt::IntrusivePtr<HttpHeaders> ptr_t;
protected:
- virtual ~HttpHeaders(); // Use release()
HttpHeaders(const HttpHeaders &); // Not defined
void operator=(const HttpHeaders &); // Not defined
@@ -145,8 +147,16 @@ public:
// a pointer to a std::string in the container.
// Pointer is valid only for the lifetime of
// the container or until container is modifed.
- //
- const std::string * find(const char * name) const;
+ const std::string * find(const std::string &name) const;
+ const std::string * find(const char * name) const
+ {
+ return find(std::string(name));
+ }
+
+ // Remove the header from the list if found.
+ //
+ void remove(const std::string &name);
+ void remove(const char *name);
// Count of headers currently in the list.
size_type size() const
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index 5bf1ecb4a5..aab447f2dd 100755
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -25,7 +25,7 @@
*/
#include "httpoptions.h"
-
+#include "lldefs.h"
#include "_httpinternal.h"
@@ -33,14 +33,18 @@ namespace LLCore
{
-HttpOptions::HttpOptions()
- : RefCounted(true),
- mWantHeaders(false),
- mTracing(HTTP_TRACE_OFF),
- mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
- mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
- mRetries(HTTP_RETRY_COUNT_DEFAULT),
- mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT)
+HttpOptions::HttpOptions() :
+ mWantHeaders(false),
+ mTracing(HTTP_TRACE_OFF),
+ mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
+ mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
+ mRetries(HTTP_RETRY_COUNT_DEFAULT),
+ mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),
+ mFollowRedirects(true),
+ mVerifyPeer(false),
+ mVerifyHost(false),
+ mDNSCacheTimeout(-1L),
+ mNoBody(false)
{}
@@ -82,5 +86,31 @@ void HttpOptions::setUseRetryAfter(bool use_retry)
mUseRetryAfter = use_retry;
}
+void HttpOptions::setFollowRedirects(bool follow_redirect)
+{
+ mFollowRedirects = follow_redirect;
+}
+
+void HttpOptions::setSSLVerifyPeer(bool verify)
+{
+ mVerifyPeer = verify;
+}
+
+void HttpOptions::setSSLVerifyHost(bool verify)
+{
+ mVerifyHost = verify;
+}
+
+void HttpOptions::setDNSCacheTimeout(int timeout)
+{
+ mDNSCacheTimeout = timeout;
+}
+
+void HttpOptions::setHeadersOnly(bool nobody)
+{
+ mNoBody = nobody;
+ if (mNoBody)
+ setWantHeaders(true);
+}
} // end namespace LLCore
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 4ab5ff18c4..510eaa45bb 100755
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -29,7 +29,6 @@
#include "httpcommon.h"
-
#include "_refcounted.h"
@@ -56,59 +55,110 @@ namespace LLCore
/// Allocation: Refcounted, heap only. Caller of the constructor
/// is given a refcount.
///
-class HttpOptions : public LLCoreInt::RefCounted
+class HttpOptions : private boost::noncopyable
{
public:
HttpOptions();
+ typedef boost::shared_ptr<HttpOptions> ptr_t;
+
+ virtual ~HttpOptions(); // Use release()
+
protected:
- virtual ~HttpOptions(); // Use release()
HttpOptions(const HttpOptions &); // Not defined
void operator=(const HttpOptions &); // Not defined
public:
+
// Default: false
void setWantHeaders(bool wanted);
bool getWantHeaders() const
- {
- return mWantHeaders;
- }
+ {
+ return mWantHeaders;
+ }
// Default: 0
void setTrace(int long);
int getTrace() const
- {
- return mTracing;
- }
+ {
+ return mTracing;
+ }
// Default: 30
void setTimeout(unsigned int timeout);
unsigned int getTimeout() const
- {
- return mTimeout;
- }
+ {
+ return mTimeout;
+ }
// Default: 0
void setTransferTimeout(unsigned int timeout);
unsigned int getTransferTimeout() const
- {
- return mTransferTimeout;
- }
+ {
+ return mTransferTimeout;
+ }
+ /// Sets the number of retries on an LLCore::HTTPRequest before the
+ /// request fails.
// Default: 8
void setRetries(unsigned int retries);
unsigned int getRetries() const
- {
- return mRetries;
- }
+ {
+ return mRetries;
+ }
// Default: true
void setUseRetryAfter(bool use_retry);
bool getUseRetryAfter() const
- {
- return mUseRetryAfter;
- }
+ {
+ return mUseRetryAfter;
+ }
+
+ /// Instructs the LLCore::HTTPRequest to follow redirects
+ /// Default: false
+ void setFollowRedirects(bool follow_redirect);
+ bool getFollowRedirects() const
+ {
+ return mFollowRedirects;
+ }
+
+ /// Instructs the LLCore::HTTPRequest to verify that the exchanged security
+ /// certificate is authentic.
+ /// Default: false
+ void setSSLVerifyPeer(bool verify);
+ bool getSSLVerifyPeer() const
+ {
+ return mVerifyPeer;
+ }
+
+ /// Instructs the LLCore::HTTPRequest to verify that the name in the
+ /// security certificate matches the name of the host contacted.
+ /// Default: false
+ void setSSLVerifyHost(bool verify);
+ bool getSSLVerifyHost() const
+ {
+ return mVerifyHost;
+ }
+
+ /// Sets the time for DNS name caching in seconds. Setting this value
+ /// to 0 will disable name caching. Setting this value to -1 causes the
+ /// name cache to never time out.
+ /// Default: -1
+ void setDNSCacheTimeout(int timeout);
+ int getDNSCacheTimeout() const
+ {
+ return mDNSCacheTimeout;
+ }
+
+ /// Retrieve only the headers and status from the request. Setting this
+ /// to true implies setWantHeaders(true) as well.
+ /// Default: false
+ void setHeadersOnly(bool nobody);
+ bool getHeadersOnly() const
+ {
+ return mNoBody;
+ }
protected:
bool mWantHeaders;
@@ -117,6 +167,11 @@ protected:
unsigned int mTransferTimeout;
unsigned int mRetries;
bool mUseRetryAfter;
+ bool mFollowRedirects;
+ bool mVerifyPeer;
+ bool mVerifyHost;
+ int mDNSCacheTimeout;
+ bool mNoBody;
}; // end class HttpOptions
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 7b1888e3eb..e09f0c3b18 100755
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -55,13 +55,13 @@ namespace LLCore
HttpRequest::HttpRequest()
- : mReplyQueue(NULL),
+ : mReplyQueue(),
mRequestQueue(NULL)
{
mRequestQueue = HttpRequestQueue::instanceOf();
mRequestQueue->addRef();
- mReplyQueue = new HttpReplyQueue();
+ mReplyQueue.reset( new HttpReplyQueue() );
}
@@ -73,11 +73,7 @@ HttpRequest::~HttpRequest()
mRequestQueue = NULL;
}
- if (mReplyQueue)
- {
- mReplyQueue->release();
- mReplyQueue = NULL;
- }
+ mReplyQueue.reset();
}
@@ -117,60 +113,59 @@ HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass
return HttpService::instanceOf()->setPolicyOption(opt, pclass, value, ret_value);
}
+HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass, policyCallback_t value, policyCallback_t * ret_value)
+{
+ if (HttpService::RUNNING == HttpService::instanceOf()->getState())
+ {
+ return HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_DYNAMIC);
+ }
+
+ return HttpService::instanceOf()->setPolicyOption(opt, pclass, value, ret_value);
+}
HttpHandle HttpRequest::setPolicyOption(EPolicyOption opt, policy_t pclass,
- long value, HttpHandler * handler)
+ long value, HttpHandler::ptr_t handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpSetGet * op = new HttpOpSetGet();
+ HttpOpSetGet::ptr_t op(new HttpOpSetGet());
if (! (status = op->setupSet(opt, pclass, value)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
HttpHandle HttpRequest::setPolicyOption(EPolicyOption opt, policy_t pclass,
- const std::string & value, HttpHandler * handler)
+ const std::string & value, HttpHandler::ptr_t handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpSetGet * op = new HttpOpSetGet();
+ HttpOpSetGet::ptr_t op (new HttpOpSetGet());
if (! (status = op->setupSet(opt, pclass, value)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
@@ -188,32 +183,27 @@ HttpStatus HttpRequest::getStatus() const
HttpHandle HttpRequest::requestGet(policy_t policy_id,
priority_t priority,
const std::string & url,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * user_handler)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest::ptr_t op(new HttpOpRequest());
if (! (status = op->setupGet(policy_id, priority, url, options, headers)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
@@ -222,32 +212,27 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
const std::string & url,
size_t offset,
size_t len,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * user_handler)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest::ptr_t op(new HttpOpRequest());
if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
@@ -255,32 +240,27 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * user_handler)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest::ptr_t op(new HttpOpRequest());
if (! (status = op->setupPost(policy_id, priority, url, body, options, headers)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
@@ -288,59 +268,156 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * user_handler)
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest::ptr_t op (new HttpOpRequest());
if (! (status = op->setupPut(policy_id, priority, url, body, options, headers)))
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
+HttpHandle HttpRequest::requestDelete(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
+{
+ HttpStatus status;
+
+ HttpOpRequest::ptr_t op(new HttpOpRequest());
+ if (!(status = op->setupDelete(policy_id, priority, url, options, headers)))
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+ op->setReplyPath(mReplyQueue, user_handler);
+ if (!(status = mRequestQueue->addOp(op))) // transfers refcount
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+
+ mLastReqStatus = status;
+ return op->getHandle();
+}
+
+HttpHandle HttpRequest::requestPatch(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ BufferArray * body,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
+{
+ HttpStatus status;
+
+ HttpOpRequest::ptr_t op (new HttpOpRequest());
+ if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers)))
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+ op->setReplyPath(mReplyQueue, user_handler);
+ if (!(status = mRequestQueue->addOp(op))) // transfers refcount
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+
+ mLastReqStatus = status;
+ return op->getHandle();
+}
-HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)
+HttpHandle HttpRequest::requestCopy(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
+{
+ HttpStatus status;
+
+ HttpOpRequest::ptr_t op(new HttpOpRequest());
+ if (!(status = op->setupCopy(policy_id, priority, url, options, headers)))
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+ op->setReplyPath(mReplyQueue, user_handler);
+ if (!(status = mRequestQueue->addOp(op))) // transfers refcount
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+
+ mLastReqStatus = status;
+ return op->getHandle();
+
+}
+
+HttpHandle HttpRequest::requestMove(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler)
+{
+ HttpStatus status;
+
+ HttpOpRequest::ptr_t op (new HttpOpRequest());
+ if (!(status = op->setupMove(policy_id, priority, url, options, headers)))
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+ op->setReplyPath(mReplyQueue, user_handler);
+ if (!(status = mRequestQueue->addOp(op))) // transfers refcount
+ {
+ mLastReqStatus = status;
+ return LLCORE_HTTP_HANDLE_INVALID;
+ }
+
+ mLastReqStatus = status;
+ return op->getHandle();
+}
+
+
+HttpHandle HttpRequest::requestNoOp(HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpNull * op = new HttpOpNull();
+ HttpOperation::ptr_t op (new HttpOpNull());
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
-
- return handle;
+ return op->getHandle();
}
HttpStatus HttpRequest::update(long usecs)
{
- HttpOperation * op(NULL);
+ HttpOperation::ptr_t op;
if (usecs)
{
@@ -351,7 +428,7 @@ HttpStatus HttpRequest::update(long usecs)
op->visitNotifier(this);
// We're done with the operation
- op->release();
+ op.reset();
}
}
else
@@ -366,13 +443,13 @@ HttpStatus HttpRequest::update(long usecs)
++iter)
{
// Swap op pointer for NULL;
- op = *iter; *iter = NULL;
+ op.reset();
+ op.swap(*iter);
// Process operation
op->visitNotifier(this);
// We're done with the operation
- op->release();
}
}
}
@@ -387,46 +464,38 @@ HttpStatus HttpRequest::update(long usecs)
// Request Management Methods
// ====================================
-HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler * user_handler)
+HttpHandle HttpRequest::requestCancel(HttpHandle request, HttpHandler::ptr_t user_handler)
{
HttpStatus status;
- HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpCancel * op = new HttpOpCancel(request);
+ HttpOperation::ptr_t op(new HttpOpCancel(request));
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return ret_handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- ret_handle = static_cast<HttpHandle>(op);
-
- return ret_handle;
+ return op->getHandle();
}
HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority,
- HttpHandler * handler)
+ HttpHandler::ptr_t handler)
{
HttpStatus status;
- HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpSetPriority * op = new HttpOpSetPriority(request, priority);
+ HttpOperation::ptr_t op (new HttpOpSetPriority(request, priority));
op->setReplyPath(mReplyQueue, handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
- return ret_handle;
+ return LLCORE_HTTP_HANDLE_INVALID;
}
mLastReqStatus = status;
- ret_handle = static_cast<HttpHandle>(op);
-
- return ret_handle;
+ return op->getHandle();
}
@@ -475,22 +544,21 @@ HttpStatus HttpRequest::startThread()
}
-HttpHandle HttpRequest::requestStopThread(HttpHandler * user_handler)
+HttpHandle HttpRequest::requestStopThread(HttpHandler::ptr_t user_handler)
{
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpStop * op = new HttpOpStop();
+ HttpOperation::ptr_t op(new HttpOpStop());
op->setReplyPath(mReplyQueue, user_handler);
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
return handle;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
+ handle = op->getHandle();
return handle;
}
@@ -501,17 +569,16 @@ HttpHandle HttpRequest::requestSpin(int mode)
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpSpin * op = new HttpOpSpin(mode);
- op->setReplyPath(mReplyQueue, NULL);
+ HttpOperation::ptr_t op(new HttpOpSpin(mode));
+ op->setReplyPath(mReplyQueue, HttpHandler::ptr_t());
if (! (status = mRequestQueue->addOp(op))) // transfers refcount
{
- op->release();
mLastReqStatus = status;
return handle;
}
mLastReqStatus = status;
- handle = static_cast<HttpHandle>(op);
+ handle = op->getHandle();
return handle;
}
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 7f23723b0b..17cfdcd7b6 100755
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -31,6 +31,8 @@
#include "httpcommon.h"
#include "httphandler.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
namespace LLCore
{
@@ -38,8 +40,6 @@ namespace LLCore
class HttpRequestQueue;
class HttpReplyQueue;
class HttpService;
-class HttpOptions;
-class HttpHeaders;
class HttpOperation;
class BufferArray;
@@ -97,6 +97,8 @@ public:
typedef unsigned int policy_t;
typedef unsigned int priority_t;
+ typedef boost::shared_ptr<HttpRequest> ptr_t;
+ typedef boost::weak_ptr<HttpRequest> wptr_t;
public:
/// @name PolicyMethods
/// @{
@@ -163,7 +165,7 @@ public:
/// Long value that if non-zero enables the use of the
/// traditional LLProxy code for http/socks5 support. If
- // enabled, has priority over GP_HTTP_PROXY.
+ /// enabled, has priority over GP_HTTP_PROXY.
///
/// Global only
PO_LLPROXY,
@@ -219,15 +221,25 @@ public:
/// Controls whether client-side throttling should be
/// performed on this policy class. Positive values
/// enable throttling and specify the request rate
- /// (requests per second) that should be targetted.
+ /// (requests per second) that should be targeted.
/// A value of zero, the default, specifies no throttling.
///
/// Per-class only
PO_THROTTLE_RATE,
+ /// Controls the callback function used to control SSL CTX
+ /// certificate verification.
+ ///
+ /// Global only
+ PO_SSL_VERIFY_CALLBACK,
+
PO_LAST // Always at end
};
+ /// Prototype for policy based callbacks. The callback methods will be executed
+ /// on the worker thread so no modifications should be made to the HttpHandler object.
+ typedef boost::function<HttpStatus(const std::string &, const HttpHandler::ptr_t &, void *)> policyCallback_t;
+
/// Set a policy option for a global or class parameter at
/// startup time (prior to thread start).
///
@@ -243,6 +255,8 @@ public:
long value, long * ret_value);
static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass,
const std::string & value, std::string * ret_value);
+ static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass,
+ policyCallback_t value, policyCallback_t * ret_value);;
/// Set a parameter on a class-based policy option. Calls
/// made after the start of the servicing thread are
@@ -256,9 +270,9 @@ public:
/// @return Handle of dynamic request. Use @see getStatus() if
/// the returned handle is invalid.
HttpHandle setPolicyOption(EPolicyOption opt, policy_t pclass, long value,
- HttpHandler * handler);
+ HttpHandler::ptr_t handler);
HttpHandle setPolicyOption(EPolicyOption opt, policy_t pclass, const std::string & value,
- HttpHandler * handler);
+ HttpHandler::ptr_t handler);
/// @}
@@ -334,9 +348,9 @@ public:
HttpHandle requestGet(policy_t policy_id,
priority_t priority,
const std::string & url,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * handler);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t handler);
/// Queue a full HTTP GET request to be issued with a 'Range' header.
@@ -377,9 +391,9 @@ public:
const std::string & url,
size_t offset,
size_t len,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * handler);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t handler);
/// Queue a full HTTP POST. Query arguments and body may
@@ -418,9 +432,9 @@ public:
priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * handler);
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t handler);
/// Queue a full HTTP PUT. Query arguments and body may
@@ -459,12 +473,92 @@ public:
priority_t priority,
const std::string & url,
BufferArray * body,
- HttpOptions * options,
- HttpHeaders * headers,
- HttpHandler * handler);
-
-
- /// Queue a NoOp request.
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t handler);
+
+
+ /// Queue a full HTTP DELETE. Query arguments and body may
+ /// be provided. Caller is responsible for escaping and
+ /// encoding and communicating the content types.
+ ///
+ /// @param policy_id @see requestGet()
+ /// @param priority "
+ /// @param url "
+ /// @param options @see requestGet()K(optional)
+ /// @param headers "
+ /// @param handler "
+ /// @return "
+ ///
+ HttpHandle requestDelete(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler);
+
+ /// Queue a full HTTP PATCH. Query arguments and body may
+ /// be provided. Caller is responsible for escaping and
+ /// encoding and communicating the content types.
+ ///
+ /// @param policy_id @see requestGet()
+ /// @param priority "
+ /// @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 @see requestGet()K(optional)
+ /// @param headers "
+ /// @param handler "
+ /// @return "
+ ///
+ HttpHandle requestPatch(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ BufferArray * body,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler);
+
+ /// Queue a full HTTP COPY. Query arguments and body may
+ /// be provided. Caller is responsible for escaping and
+ /// encoding and communicating the content types.
+ ///
+ /// @param policy_id @see requestGet()
+ /// @param priority "
+ /// @param url "
+ /// @param options @see requestGet()K(optional)
+ /// @param headers "
+ /// @param handler "
+ /// @return "
+ ///
+ HttpHandle requestCopy(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_handler);
+
+ /// Queue a full HTTP MOVE. Query arguments and body may
+ /// be provided. Caller is responsible for escaping and
+ /// encoding and communicating the content types.
+ ///
+ /// @param policy_id @see requestGet()
+ /// @param priority "
+ /// @param url "
+ /// @param options @see requestGet()K(optional)
+ /// @param headers "
+ /// @param handler "
+ /// @return "
+ ///
+ HttpHandle requestMove(policy_t policy_id,
+ priority_t priority,
+ const std::string & url,
+ const HttpOptions::ptr_t & options,
+ const HttpHeaders::ptr_t & headers,
+ HttpHandler::ptr_t user_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
/// queue.
@@ -472,7 +566,7 @@ public:
/// @param handler @see requestGet()
/// @return "
///
- HttpHandle requestNoOp(HttpHandler * handler);
+ HttpHandle requestNoOp(HttpHandler::ptr_t handler);
/// While all the heavy work is done by the worker thread, notifications
/// must be performed in the context of the application thread. These
@@ -497,7 +591,7 @@ public:
///
/// @{
- HttpHandle requestCancel(HttpHandle request, HttpHandler *);
+ HttpHandle requestCancel(HttpHandle request, HttpHandler::ptr_t);
/// Request that a previously-issued request be reprioritized.
/// The status of whether the change itself succeeded arrives
@@ -509,7 +603,7 @@ public:
/// @param handler @see requestGet()
/// @return "
///
- HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler * handler);
+ HttpHandle requestSetPriority(HttpHandle request, priority_t priority, HttpHandler::ptr_t handler);
/// @}
@@ -547,7 +641,7 @@ public:
/// As the request cannot be cancelled, the handle
/// is generally not useful.
///
- HttpHandle requestStopThread(HttpHandler * handler);
+ HttpHandle requestStopThread(HttpHandler::ptr_t handler);
/// Queue a Spin request.
/// DEBUG/TESTING ONLY. This puts the worker into a CPU spin for
@@ -561,14 +655,15 @@ public:
/// @}
protected:
- void generateNotification(HttpOperation * op);
private:
+ typedef boost::shared_ptr<HttpReplyQueue> HttpReplyQueuePtr_t;
+
/// @name InstanceData
///
/// @{
HttpStatus mLastReqStatus;
- HttpReplyQueue * mReplyQueue;
+ HttpReplyQueuePtr_t mReplyQueue;
HttpRequestQueue * mRequestQueue;
/// @}
diff --git a/indra/llcorehttp/httpresponse.cpp b/indra/llcorehttp/httpresponse.cpp
index c974395b0a..f5ad2ebd47 100755
--- a/indra/llcorehttp/httpresponse.cpp
+++ b/indra/llcorehttp/httpresponse.cpp
@@ -39,16 +39,17 @@ HttpResponse::HttpResponse()
mReplyLength(0U),
mReplyFullLength(0U),
mBufferArray(NULL),
- mHeaders(NULL),
+ mHeaders(),
mRetries(0U),
- m503Retries(0U)
+ m503Retries(0U),
+ mRequestUrl()
{}
HttpResponse::~HttpResponse()
{
setBody(NULL);
- setHeaders(NULL);
+ //setHeaders();
}
@@ -71,23 +72,14 @@ void HttpResponse::setBody(BufferArray * ba)
}
-void HttpResponse::setHeaders(HttpHeaders * headers)
+void HttpResponse::setHeaders(HttpHeaders::ptr_t &headers)
{
- if (mHeaders == headers)
- return;
-
- if (mHeaders)
- {
- mHeaders->release();
- }
-
- if (headers)
- {
- headers->addRef();
- }
-
- mHeaders = headers;
+ mHeaders = headers;
}
+size_t HttpResponse::getBodySize() const
+{
+ return (mBufferArray) ? mBufferArray->size() : 0;
+}
} // end namespace LLCore
diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h
index aee64e2878..0bfa4585c7 100755
--- a/indra/llcorehttp/httpresponse.h
+++ b/indra/llcorehttp/httpresponse.h
@@ -31,7 +31,7 @@
#include <string>
#include "httpcommon.h"
-
+#include "httpheaders.h"
#include "_refcounted.h"
@@ -69,6 +69,18 @@ protected:
void operator=(const HttpResponse &); // Not defined
public:
+ /// Statistics for the HTTP
+ struct TransferStats
+ {
+ typedef boost::shared_ptr<TransferStats> ptr_t;
+
+ TransferStats() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
+ F64 mSizeDownload;
+ F64 mTotalTime;
+ F64 mSpeedDownload;
+ };
+
+
/// Returns the final status of the requested operation.
///
HttpStatus getStatus() const
@@ -92,6 +104,10 @@ public:
return mBufferArray;
}
+ /// Safely get the size of the body buffer. If the body buffer is missing
+ /// return 0 as the size.
+ size_t getBodySize() const;
+
/// Set the response data in the instance. Will drop the reference
/// count to any existing data and increment the count of that passed
/// in. It is legal to set the data to NULL.
@@ -104,13 +120,13 @@ public:
///
/// Caller can hold onto the headers by incrementing the reference
/// count of the returned object.
- HttpHeaders * getHeaders() const
- {
+ HttpHeaders::ptr_t getHeaders() const
+ {
return mHeaders;
- }
+ }
/// Behaves like @see setResponse() but for header data.
- void setHeaders(HttpHeaders * headers);
+ void setHeaders(HttpHeaders::ptr_t &headers);
/// If a 'Range:' header was used, these methods are involved
/// in setting and returning data about the actual response.
@@ -168,6 +184,27 @@ public:
m503Retries = retries_503;
}
+ void setTransferStats(TransferStats::ptr_t &stats)
+ {
+ mStats = stats;
+ }
+
+ TransferStats::ptr_t getTransferStats()
+ {
+ return mStats;
+ }
+
+ void setRequestURL(const std::string &url)
+ {
+ mRequestUrl = url;
+ }
+
+ const std::string &getRequestURL() const
+ {
+ return mRequestUrl;
+ }
+
+
protected:
// Response data here
HttpStatus mStatus;
@@ -175,10 +212,13 @@ protected:
unsigned int mReplyLength;
unsigned int mReplyFullLength;
BufferArray * mBufferArray;
- HttpHeaders * mHeaders;
+ HttpHeaders::ptr_t mHeaders;
std::string mContentType;
unsigned int mRetries;
unsigned int m503Retries;
+ std::string mRequestUrl;
+
+ TransferStats::ptr_t mStats;
};
diff --git a/indra/llcorehttp/llhttpconstants.cpp b/indra/llcorehttp/llhttpconstants.cpp
new file mode 100755
index 0000000000..71d4f19408
--- /dev/null
+++ b/indra/llcorehttp/llhttpconstants.cpp
@@ -0,0 +1,135 @@
+/**
+ * @file llhttpconstants.cpp
+ * @brief Implementation of the HTTP request / response constant lookups
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013-2014, 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 "linden_common.h"
+#include "llhttpconstants.h"
+#include "lltimer.h"
+
+// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
+#include <curl/curl.h>
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+const std::string HTTP_OUT_HEADER_ACCEPT("Accept");
+const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET("Accept-Charset");
+const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING("Accept-Encoding");
+const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE("Accept-Language");
+const std::string HTTP_OUT_HEADER_ACCEPT_RANGES("Accept-Ranges");
+const std::string HTTP_OUT_HEADER_AGE("Age");
+const std::string HTTP_OUT_HEADER_ALLOW("Allow");
+const std::string HTTP_OUT_HEADER_AUTHORIZATION("Authorization");
+const std::string HTTP_OUT_HEADER_CACHE_CONTROL("Cache-Control");
+const std::string HTTP_OUT_HEADER_CONNECTION("Connection");
+const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION("Content-Description");
+const std::string HTTP_OUT_HEADER_CONTENT_ENCODING("Content-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_ID("Content-ID");
+const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE("Content-Language");
+const std::string HTTP_OUT_HEADER_CONTENT_LENGTH("Content-Length");
+const std::string HTTP_OUT_HEADER_CONTENT_LOCATION("Content-Location");
+const std::string HTTP_OUT_HEADER_CONTENT_MD5("Content-MD5");
+const std::string HTTP_OUT_HEADER_CONTENT_RANGE("Content-Range");
+const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_TYPE("Content-Type");
+const std::string HTTP_OUT_HEADER_COOKIE("Cookie");
+const std::string HTTP_OUT_HEADER_DATE("Date");
+const std::string HTTP_OUT_HEADER_DESTINATION("Destination");
+const std::string HTTP_OUT_HEADER_ETAG("ETag");
+const std::string HTTP_OUT_HEADER_EXPECT("Expect");
+const std::string HTTP_OUT_HEADER_EXPIRES("Expires");
+const std::string HTTP_OUT_HEADER_FROM("From");
+const std::string HTTP_OUT_HEADER_HOST("Host");
+const std::string HTTP_OUT_HEADER_IF_MATCH("If-Match");
+const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
+const std::string HTTP_OUT_HEADER_IF_NONE_MATCH("If-None-Match");
+const std::string HTTP_OUT_HEADER_IF_RANGE("If-Range");
+const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
+const std::string HTTP_OUT_HEADER_KEEP_ALIVE("Keep-Alive");
+const std::string HTTP_OUT_HEADER_LAST_MODIFIED("Last-Modified");
+const std::string HTTP_OUT_HEADER_LOCATION("Location");
+const std::string HTTP_OUT_HEADER_MAX_FORWARDS("Max-Forwards");
+const std::string HTTP_OUT_HEADER_MIME_VERSION("MIME-Version");
+const std::string HTTP_OUT_HEADER_PRAGMA("Pragma");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
+const std::string HTTP_OUT_HEADER_RANGE("Range");
+const std::string HTTP_OUT_HEADER_REFERER("Referer");
+const std::string HTTP_OUT_HEADER_RETRY_AFTER("Retry-After");
+const std::string HTTP_OUT_HEADER_SERVER("Server");
+const std::string HTTP_OUT_HEADER_SET_COOKIE("Set-Cookie");
+const std::string HTTP_OUT_HEADER_TE("TE");
+const std::string HTTP_OUT_HEADER_TRAILER("Trailer");
+const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_UPGRADE("Upgrade");
+const std::string HTTP_OUT_HEADER_USER_AGENT("User-Agent");
+const std::string HTTP_OUT_HEADER_VARY("Vary");
+const std::string HTTP_OUT_HEADER_VIA("Via");
+const std::string HTTP_OUT_HEADER_WARNING("Warning");
+const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
+
+// Incoming headers are normalized to lower-case.
+const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE("accept-language");
+const std::string HTTP_IN_HEADER_CACHE_CONTROL("cache-control");
+const std::string HTTP_IN_HEADER_CONTENT_LENGTH("content-length");
+const std::string HTTP_IN_HEADER_CONTENT_LOCATION("content-location");
+const std::string HTTP_IN_HEADER_CONTENT_TYPE("content-type");
+const std::string HTTP_IN_HEADER_HOST("host");
+const std::string HTTP_IN_HEADER_LOCATION("location");
+const std::string HTTP_IN_HEADER_RETRY_AFTER("retry-after");
+const std::string HTTP_IN_HEADER_SET_COOKIE("set-cookie");
+const std::string HTTP_IN_HEADER_USER_AGENT("user-agent");
+const std::string HTTP_IN_HEADER_X_FORWARDED_FOR("x-forwarded-for");
+
+const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
+const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream");
+const std::string HTTP_CONTENT_VND_LL_MESH("application/vnd.ll.mesh");
+const std::string HTTP_CONTENT_XML("application/xml");
+const std::string HTTP_CONTENT_JSON("application/json");
+const std::string HTTP_CONTENT_TEXT_HTML("text/html");
+const std::string HTTP_CONTENT_TEXT_HTML_UTF8("text/html; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8("text/plain; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_LLSD("text/llsd");
+const std::string HTTP_CONTENT_TEXT_XML("text/xml");
+const std::string HTTP_CONTENT_TEXT_LSL("text/lsl");
+const std::string HTTP_CONTENT_TEXT_PLAIN("text/plain");
+const std::string HTTP_CONTENT_IMAGE_X_J2C("image/x-j2c");
+const std::string HTTP_CONTENT_IMAGE_J2C("image/j2c");
+const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg");
+const std::string HTTP_CONTENT_IMAGE_PNG("image/png");
+const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
+
+const std::string HTTP_NO_CACHE("no-cache");
+const std::string HTTP_NO_CACHE_CONTROL("no-cache, max-age=0");
+
+const std::string HTTP_VERB_INVALID("(invalid)");
+const std::string HTTP_VERB_HEAD("HEAD");
+const std::string HTTP_VERB_GET("GET");
+const std::string HTTP_VERB_PUT("PUT");
+const std::string HTTP_VERB_POST("POST");
+const std::string HTTP_VERB_DELETE("DELETE");
+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");
diff --git a/indra/llcorehttp/llhttpconstants.h b/indra/llcorehttp/llhttpconstants.h
new file mode 100755
index 0000000000..121448854e
--- /dev/null
+++ b/indra/llcorehttp/llhttpconstants.h
@@ -0,0 +1,219 @@
+/**
+ * @file llhttpconstants.h
+ * @brief Constants for HTTP requests and responses
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2001-2014, 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_HTTP_CONSTANTS_H
+#define LL_HTTP_CONSTANTS_H
+
+#include "stdtypes.h"
+
+/////// HTTP STATUS CODES ///////
+
+// Standard errors from HTTP spec:
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
+const S32 HTTP_CONTINUE = 100;
+const S32 HTTP_SWITCHING_PROTOCOLS = 101;
+
+// Success
+const S32 HTTP_OK = 200;
+const S32 HTTP_CREATED = 201;
+const S32 HTTP_ACCEPTED = 202;
+const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
+const S32 HTTP_NO_CONTENT = 204;
+const S32 HTTP_RESET_CONTENT = 205;
+const S32 HTTP_PARTIAL_CONTENT = 206;
+
+// Redirection
+const S32 HTTP_MULTIPLE_CHOICES = 300;
+const S32 HTTP_MOVED_PERMANENTLY = 301;
+const S32 HTTP_FOUND = 302;
+const S32 HTTP_SEE_OTHER = 303;
+const S32 HTTP_NOT_MODIFIED = 304;
+const S32 HTTP_USE_PROXY = 305;
+const S32 HTTP_TEMPORARY_REDIRECT = 307;
+
+// Client Error
+const S32 HTTP_BAD_REQUEST = 400;
+const S32 HTTP_UNAUTHORIZED = 401;
+const S32 HTTP_PAYMENT_REQUIRED = 402;
+const S32 HTTP_FORBIDDEN = 403;
+const S32 HTTP_NOT_FOUND = 404;
+const S32 HTTP_METHOD_NOT_ALLOWED = 405;
+const S32 HTTP_NOT_ACCEPTABLE = 406;
+const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
+const S32 HTTP_REQUEST_TIME_OUT = 408;
+const S32 HTTP_CONFLICT = 409;
+const S32 HTTP_GONE = 410;
+const S32 HTTP_LENGTH_REQUIRED = 411;
+const S32 HTTP_PRECONDITION_FAILED = 412;
+const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
+const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
+const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
+const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+const S32 HTTP_EXPECTATION_FAILED = 417;
+
+// Server Error
+const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
+const S32 HTTP_NOT_IMPLEMENTED = 501;
+const S32 HTTP_BAD_GATEWAY = 502;
+const S32 HTTP_SERVICE_UNAVAILABLE = 503;
+const S32 HTTP_GATEWAY_TIME_OUT = 504;
+const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
+
+// We combine internal process errors with status codes
+// These status codes should not be sent over the wire
+// and indicate something went wrong internally.
+// If you get these they are not normal.
+const S32 HTTP_INTERNAL_CURL_ERROR = 498;
+const S32 HTTP_INTERNAL_ERROR = 499;
+
+
+////// HTTP Methods //////
+
+extern const std::string HTTP_VERB_INVALID;
+extern const std::string HTTP_VERB_HEAD;
+extern const std::string HTTP_VERB_GET;
+extern const std::string HTTP_VERB_PUT;
+extern const std::string HTTP_VERB_POST;
+extern const std::string HTTP_VERB_DELETE;
+extern const std::string HTTP_VERB_MOVE;
+extern const std::string HTTP_VERB_OPTIONS;
+
+enum EHTTPMethod
+{
+ HTTP_INVALID = 0,
+ HTTP_HEAD,
+ HTTP_GET,
+ HTTP_PUT,
+ HTTP_POST,
+ HTTP_DELETE,
+ HTTP_MOVE, // Caller will need to set 'Destination' header
+ HTTP_OPTIONS,
+ HTTP_PATCH,
+ HTTP_COPY,
+ HTTP_METHOD_COUNT
+};
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
+//// HTTP Headers /////
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+extern const std::string HTTP_OUT_HEADER_ACCEPT;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_RANGES;
+extern const std::string HTTP_OUT_HEADER_AGE;
+extern const std::string HTTP_OUT_HEADER_ALLOW;
+extern const std::string HTTP_OUT_HEADER_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_OUT_HEADER_CONNECTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ID;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_MD5;
+extern const std::string HTTP_OUT_HEADER_CONTENT_RANGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_OUT_HEADER_COOKIE;
+extern const std::string HTTP_OUT_HEADER_DATE;
+extern const std::string HTTP_OUT_HEADER_DESTINATION;
+extern const std::string HTTP_OUT_HEADER_ETAG;
+extern const std::string HTTP_OUT_HEADER_EXPECT;
+extern const std::string HTTP_OUT_HEADER_EXPIRES;
+extern const std::string HTTP_OUT_HEADER_FROM;
+extern const std::string HTTP_OUT_HEADER_HOST;
+extern const std::string HTTP_OUT_HEADER_IF_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_IF_NONE_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_RANGE;
+extern const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_KEEP_ALIVE;
+extern const std::string HTTP_OUT_HEADER_LAST_MODIFIED;
+extern const std::string HTTP_OUT_HEADER_LOCATION;
+extern const std::string HTTP_OUT_HEADER_MAX_FORWARDS;
+extern const std::string HTTP_OUT_HEADER_MIME_VERSION;
+extern const std::string HTTP_OUT_HEADER_PRAGMA;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_RANGE;
+extern const std::string HTTP_OUT_HEADER_REFERER;
+extern const std::string HTTP_OUT_HEADER_RETRY_AFTER;
+extern const std::string HTTP_OUT_HEADER_SERVER;
+extern const std::string HTTP_OUT_HEADER_SET_COOKIE;
+extern const std::string HTTP_OUT_HEADER_TE;
+extern const std::string HTTP_OUT_HEADER_TRAILER;
+extern const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_UPGRADE;
+extern const std::string HTTP_OUT_HEADER_USER_AGENT;
+extern const std::string HTTP_OUT_HEADER_VARY;
+extern const std::string HTTP_OUT_HEADER_VIA;
+extern const std::string HTTP_OUT_HEADER_WARNING;
+extern const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE;
+
+// Incoming headers are normalized to lower-case.
+extern const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_IN_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_IN_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_IN_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_IN_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_IN_HEADER_HOST;
+extern const std::string HTTP_IN_HEADER_LOCATION;
+extern const std::string HTTP_IN_HEADER_RETRY_AFTER;
+extern const std::string HTTP_IN_HEADER_SET_COOKIE;
+extern const std::string HTTP_IN_HEADER_USER_AGENT;
+extern const std::string HTTP_IN_HEADER_X_FORWARDED_FOR;
+
+//// HTTP Content Types ////
+
+extern const std::string HTTP_CONTENT_LLSD_XML;
+extern const std::string HTTP_CONTENT_OCTET_STREAM;
+extern const std::string HTTP_CONTENT_VND_LL_MESH;
+extern const std::string HTTP_CONTENT_XML;
+extern const std::string HTTP_CONTENT_JSON;
+extern const std::string HTTP_CONTENT_TEXT_HTML;
+extern const std::string HTTP_CONTENT_TEXT_HTML_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_LLSD;
+extern const std::string HTTP_CONTENT_TEXT_XML;
+extern const std::string HTTP_CONTENT_TEXT_LSL;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN;
+extern const std::string HTTP_CONTENT_IMAGE_X_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_JPEG;
+extern const std::string HTTP_CONTENT_IMAGE_PNG;
+extern const std::string HTTP_CONTENT_IMAGE_BMP;
+
+//// HTTP Cache Settings ////
+extern const std::string HTTP_NO_CACHE;
+extern const std::string HTTP_NO_CACHE_CONTROL;
+
+#endif
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index e863ddd13f..bef762f5ce 100755
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -160,7 +160,7 @@ void stop_thread(LLCore::HttpRequest * req)
{
if (req)
{
- req->requestStopThread(NULL);
+ req->requestStopThread(LLCore::HttpHandler::ptr_t());
int count = 0;
int limit = 10;
diff --git a/indra/llcorehttp/tests/test_httpheaders.hpp b/indra/llcorehttp/tests/test_httpheaders.hpp
index 668c36dc66..c05f1d9429 100755
--- a/indra/llcorehttp/tests/test_httpheaders.hpp
+++ b/indra/llcorehttp/tests/test_httpheaders.hpp
@@ -59,13 +59,12 @@ void HttpHeadersTestObjectType::test<1>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
- ensure("One ref on construction of HttpHeaders", headers->getRefCount() == 1);
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
ensure("Memory being used", mMemTotal < GetMemTotal());
ensure("Nothing in headers", 0 == headers->size());
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -80,7 +79,7 @@ void HttpHeadersTestObjectType::test<2>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
{
// Append a few strings
@@ -101,7 +100,7 @@ void HttpHeadersTestObjectType::test<2>()
}
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -116,7 +115,7 @@ void HttpHeadersTestObjectType::test<3>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
{
// Append a few strings
@@ -151,7 +150,7 @@ void HttpHeadersTestObjectType::test<3>()
}
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -166,8 +165,8 @@ void HttpHeadersTestObjectType::test<4>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
-
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
+
{
static char line1[] = " AcCePT : image/yourfacehere";
static char line1v[] = "image/yourfacehere";
@@ -251,7 +250,7 @@ void HttpHeadersTestObjectType::test<4>()
}
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -267,7 +266,7 @@ void HttpHeadersTestObjectType::test<5>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
HttpHeaders::iterator end(headers->end()), begin(headers->begin());
ensure("Empty container has equal begin/end const iterators", end == begin);
@@ -337,7 +336,7 @@ void HttpHeadersTestObjectType::test<5>()
}
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -353,7 +352,7 @@ void HttpHeadersTestObjectType::test<6>()
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpHeaders * headers = new HttpHeaders();
+ HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
@@ -421,7 +420,7 @@ void HttpHeadersTestObjectType::test<6>()
}
// release the implicit reference, causing the object to be released
- headers->release();
+ headers.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
diff --git a/indra/llcorehttp/tests/test_httpoperation.hpp b/indra/llcorehttp/tests/test_httpoperation.hpp
index 17b1a96878..e7df2337de 100755
--- a/indra/llcorehttp/tests/test_httpoperation.hpp
+++ b/indra/llcorehttp/tests/test_httpoperation.hpp
@@ -76,12 +76,12 @@ namespace tut
mMemTotal = GetMemTotal();
// create a new ref counted object with an implicit reference
- HttpOpNull * op = new HttpOpNull();
- ensure(op->getRefCount() == 1);
+ HttpOperation::ptr_t op (new HttpOpNull());
+ ensure(op.use_count() == 1);
ensure(mMemTotal < GetMemTotal());
// release the implicit reference, causing the object to be released
- op->release();
+ op.reset();
// make sure we didn't leak any memory
ensure(mMemTotal == GetMemTotal());
@@ -96,26 +96,24 @@ namespace tut
mMemTotal = GetMemTotal();
// Get some handlers
- TestHandler * h1 = new TestHandler();
+ LLCore::HttpHandler::ptr_t h1 (new TestHandler());
// create a new ref counted object with an implicit reference
- HttpOpNull * op = new HttpOpNull();
+ HttpOperation::ptr_t op (new HttpOpNull());
// Add the handlers
- op->setReplyPath(NULL, h1);
+ op->setReplyPath(LLCore::HttpOperation::HttpReplyQueuePtr_t(), h1);
// Check ref count
- ensure(op->getRefCount() == 1);
+ ensure(op.unique() == 1);
// release the reference, releasing the operation but
// not the handlers.
- op->release();
- op = NULL;
+ op.reset();
ensure(mMemTotal != GetMemTotal());
// release the handlers
- delete h1;
- h1 = NULL;
+ h1.reset();
ensure(mMemTotal == GetMemTotal());
}
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 43f7e36da5..463e55dd7e 100755
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -112,7 +112,7 @@ public:
if (! mHeadersRequired.empty() || ! mHeadersDisallowed.empty())
{
ensure("Response required with header check", response != NULL);
- HttpHeaders * header(response->getHeaders()); // Will not hold onto this
+ HttpHeaders::ptr_t header(response->getHeaders()); // Will not hold onto this
ensure("Some quantity of headers returned", header != NULL);
if (! mHeadersRequired.empty())
@@ -247,7 +247,7 @@ void HttpRequestTestObjectType::test<2>()
ensure("Memory being used", mMemTotal < GetMemTotal());
// Issue a NoOp
- HttpHandle handle = req->requestNoOp(NULL);
+ HttpHandle handle = req->requestNoOp(LLCore::HttpHandler::ptr_t());
ensure("Request issued", handle != LLCORE_HTTP_HANDLE_INVALID);
// release the request object
@@ -275,6 +275,10 @@ void HttpRequestTestObjectType::test<2>()
}
}
+namespace
+{
+ void NoOpDeletor(LLCore::HttpHandler *) { }
+}
template <> template <>
void HttpRequestTestObjectType::test<3>()
@@ -287,7 +291,8 @@ void HttpRequestTestObjectType::test<3>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -296,9 +301,8 @@ void HttpRequestTestObjectType::test<3>()
try
{
-
// Get singletons created
- HttpRequest::createService();
+ HttpRequest::createService();
// Start threading early so that thread memory is invariant
// over the test.
@@ -309,7 +313,7 @@ void HttpRequestTestObjectType::test<3>()
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
// Issue a NoOp
- HttpHandle handle = req->requestNoOp(&handler);
+ HttpHandle handle = req->requestNoOp(handlerp);
ensure("Valid handle returned for first request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -324,7 +328,7 @@ void HttpRequestTestObjectType::test<3>()
ensure("One handler invocation for request", mHandlerCalls == 1);
// Okay, request a shutdown of the servicing thread
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -378,7 +382,10 @@ void HttpRequestTestObjectType::test<4>()
// references to it after completion of this method.
TestHandler2 handler1(this, "handler1");
TestHandler2 handler2(this, "handler2");
-
+
+ LLCore::HttpHandler::ptr_t handler1p(&handler1, NoOpDeletor);
+ LLCore::HttpHandler::ptr_t handler2p(&handler2, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -388,7 +395,7 @@ void HttpRequestTestObjectType::test<4>()
try
{
-
+
// Get singletons created
HttpRequest::createService();
@@ -402,11 +409,11 @@ void HttpRequestTestObjectType::test<4>()
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
// Issue some NoOps
- HttpHandle handle = req1->requestNoOp(&handler1);
+ HttpHandle handle = req1->requestNoOp(handler1p);
ensure("Valid handle returned for first request", handle != LLCORE_HTTP_HANDLE_INVALID);
handler1.mExpectHandle = handle;
- handle = req2->requestNoOp(&handler2);
+ handle = req2->requestNoOp(handler2p);
ensure("Valid handle returned for first request", handle != LLCORE_HTTP_HANDLE_INVALID);
handler2.mExpectHandle = handle;
@@ -423,7 +430,7 @@ void HttpRequestTestObjectType::test<4>()
ensure("One handler invocation for request", mHandlerCalls == 2);
// Okay, request a shutdown of the servicing thread
- handle = req2->requestStopThread(&handler2);
+ handle = req2->requestStopThread(handler2p);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
handler2.mExpectHandle = handle;
@@ -482,7 +489,8 @@ void HttpRequestTestObjectType::test<5>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -491,7 +499,6 @@ void HttpRequestTestObjectType::test<5>()
try
{
-
// Get singletons created
HttpRequest::createService();
@@ -508,7 +515,7 @@ void HttpRequestTestObjectType::test<5>()
ensure("Valid handle returned for spin request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Issue a NoOp
- handle = req->requestNoOp(&handler);
+ handle = req->requestNoOp(handlerp);
ensure("Valid handle returned for no-op request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -567,7 +574,8 @@ void HttpRequestTestObjectType::test<6>()
try
{
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// Get singletons created
HttpRequest::createService();
@@ -584,7 +592,7 @@ void HttpRequestTestObjectType::test<6>()
ensure("Valid handle returned for spin request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Issue a NoOp
- handle = req->requestNoOp(&handler);
+ handle = req->requestNoOp(handlerp);
ensure("Valid handle returned for no-op request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -632,17 +640,19 @@ void HttpRequestTestObjectType::test<7>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * opts = NULL;
+ HttpOptions::ptr_t opts;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -653,7 +663,7 @@ void HttpRequestTestObjectType::test<7>()
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
- opts = new HttpOptions();
+ opts = HttpOptions::ptr_t(new HttpOptions());
opts->setRetries(1); // Don't try for too long - default retries take about 18S
// Issue a GET that can't connect
@@ -664,8 +674,8 @@ void HttpRequestTestObjectType::test<7>()
0,
0,
opts,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -681,7 +691,7 @@ void HttpRequestTestObjectType::test<7>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -705,8 +715,7 @@ void HttpRequestTestObjectType::test<7>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
- opts->release();
- opts = NULL;
+ opts.reset();
// release the request object
delete req;
@@ -728,11 +737,7 @@ void HttpRequestTestObjectType::test<7>()
catch (...)
{
stop_thread(req);
- if (opts)
- {
- opts->release();
- opts = NULL;
- }
+ opts.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -754,7 +759,8 @@ void HttpRequestTestObjectType::test<8>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -763,7 +769,7 @@ void HttpRequestTestObjectType::test<8>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -779,9 +785,9 @@ void HttpRequestTestObjectType::test<8>()
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -797,7 +803,7 @@ void HttpRequestTestObjectType::test<8>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -862,7 +868,8 @@ void HttpRequestTestObjectType::test<9>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -871,7 +878,7 @@ void HttpRequestTestObjectType::test<9>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -889,9 +896,9 @@ void HttpRequestTestObjectType::test<9>()
url_base,
0,
0,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -907,7 +914,7 @@ void HttpRequestTestObjectType::test<9>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -972,7 +979,8 @@ void HttpRequestTestObjectType::test<10>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -982,7 +990,7 @@ void HttpRequestTestObjectType::test<10>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1001,9 +1009,9 @@ void HttpRequestTestObjectType::test<10>()
0U,
url_base,
body,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1019,7 +1027,7 @@ void HttpRequestTestObjectType::test<10>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1090,7 +1098,8 @@ void HttpRequestTestObjectType::test<11>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -1100,7 +1109,7 @@ void HttpRequestTestObjectType::test<11>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1119,9 +1128,9 @@ void HttpRequestTestObjectType::test<11>()
0U,
url_base,
body,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1137,7 +1146,7 @@ void HttpRequestTestObjectType::test<11>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1209,7 +1218,8 @@ void HttpRequestTestObjectType::test<12>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
@@ -1218,7 +1228,7 @@ void HttpRequestTestObjectType::test<12>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Enable tracing
@@ -1239,9 +1249,9 @@ void HttpRequestTestObjectType::test<12>()
url_base,
0,
0,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1257,7 +1267,7 @@ void HttpRequestTestObjectType::test<12>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1326,17 +1336,18 @@ void HttpRequestTestObjectType::test<13>()
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
handler.mHeadersRequired.reserve(20); // Avoid memory leak test failure
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * opts = NULL;
+ HttpOptions::ptr_t opts;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Enable tracing
@@ -1350,7 +1361,7 @@ void HttpRequestTestObjectType::test<13>()
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
- opts = new HttpOptions();
+ opts = HttpOptions::ptr_t(new HttpOptions());
opts->setWantHeaders(true);
// Issue a GET that succeeds
@@ -1364,13 +1375,12 @@ void HttpRequestTestObjectType::test<13>()
0,
0,
opts,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// release options
- opts->release();
- opts = NULL;
+ opts.reset();
// Run the notification pump.
int count(0);
@@ -1386,7 +1396,7 @@ void HttpRequestTestObjectType::test<13>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1430,11 +1440,7 @@ void HttpRequestTestObjectType::test<13>()
catch (...)
{
stop_thread(req);
- if (opts)
- {
- opts->release();
- opts = NULL;
- }
+ opts.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -1453,18 +1459,19 @@ void HttpRequestTestObjectType::test<14>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
- std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+ std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * opts = NULL;
+ HttpOptions::ptr_t opts;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1475,7 +1482,7 @@ void HttpRequestTestObjectType::test<14>()
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
- opts = new HttpOptions();
+ opts = HttpOptions::ptr_t(new HttpOptions);
opts->setRetries(0); // Don't retry
opts->setTimeout(2);
@@ -1487,8 +1494,8 @@ void HttpRequestTestObjectType::test<14>()
0,
0,
opts,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1504,7 +1511,7 @@ void HttpRequestTestObjectType::test<14>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1528,8 +1535,7 @@ void HttpRequestTestObjectType::test<14>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
- opts->release();
- opts = NULL;
+ opts.reset();
// release the request object
delete req;
@@ -1552,11 +1558,7 @@ void HttpRequestTestObjectType::test<14>()
catch (...)
{
stop_thread(req);
- if (opts)
- {
- opts->release();
- opts = NULL;
- }
+ opts.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -1578,6 +1580,7 @@ void HttpRequestTestObjectType::test<15>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// Load and clear the string setting to preload std::string object
// for memory return tests.
@@ -1592,7 +1595,7 @@ void HttpRequestTestObjectType::test<15>()
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1609,9 +1612,9 @@ void HttpRequestTestObjectType::test<15>()
HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
0U,
url_base,
- NULL,
- NULL,
- &handler);
+ HttpOptions::ptr_t(),
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1628,7 +1631,7 @@ void HttpRequestTestObjectType::test<15>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
handler.mCheckContentType.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1697,18 +1700,19 @@ void HttpRequestTestObjectType::test<16>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1719,7 +1723,7 @@ void HttpRequestTestObjectType::test<16>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// Issue a GET that *can* connect
@@ -1776,8 +1780,8 @@ void HttpRequestTestObjectType::test<16>()
0U,
url_base + "reflect/",
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1792,7 +1796,7 @@ void HttpRequestTestObjectType::test<16>()
ensure("One handler invocation for request", mHandlerCalls == 1);
// Do a texture-style fetch
- headers = new HttpHeaders;
+ headers = HttpHeaders::ptr_t(new HttpHeaders);
headers->append("Accept", "image/x-j2c");
mStatus = HttpStatus(200);
@@ -1854,7 +1858,7 @@ void HttpRequestTestObjectType::test<16>()
47,
options,
headers,
- &handler);
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -1873,7 +1877,7 @@ void HttpRequestTestObjectType::test<16>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -1897,17 +1901,8 @@ void HttpRequestTestObjectType::test<16>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -1919,16 +1914,9 @@ void HttpRequestTestObjectType::test<16>()
catch (...)
{
stop_thread(req);
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
+ options.reset();
+ headers.reset();
+
delete req;
HttpRequest::destroyService();
throw;
@@ -1954,19 +1942,20 @@ void HttpRequestTestObjectType::test<17>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
BufferArray * ba = NULL;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -1977,7 +1966,7 @@ void HttpRequestTestObjectType::test<17>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// And a buffer array
@@ -2049,8 +2038,8 @@ void HttpRequestTestObjectType::test<17>()
url_base + "reflect/",
ba,
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
ba->release();
ba = NULL;
@@ -2071,7 +2060,7 @@ void HttpRequestTestObjectType::test<17>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -2095,17 +2084,8 @@ void HttpRequestTestObjectType::test<17>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -2122,17 +2102,10 @@ void HttpRequestTestObjectType::test<17>()
ba->release();
ba = NULL;
}
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
- delete req;
+ options.reset();
+ headers.reset();
+
+ delete req;
HttpRequest::destroyService();
throw;
}
@@ -2157,19 +2130,20 @@ void HttpRequestTestObjectType::test<18>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
BufferArray * ba = NULL;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -2180,7 +2154,7 @@ void HttpRequestTestObjectType::test<18>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// And a buffer array
@@ -2253,8 +2227,8 @@ void HttpRequestTestObjectType::test<18>()
url_base + "reflect/",
ba,
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
ba->release();
ba = NULL;
@@ -2275,7 +2249,7 @@ void HttpRequestTestObjectType::test<18>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -2299,17 +2273,8 @@ void HttpRequestTestObjectType::test<18>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -2326,17 +2291,10 @@ void HttpRequestTestObjectType::test<18>()
ba->release();
ba = NULL;
}
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
- delete req;
+ options.reset();
+ headers.reset();
+
+ delete req;
HttpRequest::destroyService();
throw;
}
@@ -2361,18 +2319,19 @@ void HttpRequestTestObjectType::test<19>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -2383,11 +2342,11 @@ void HttpRequestTestObjectType::test<19>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// headers
- headers = new HttpHeaders;
+ headers = HttpHeaders::ptr_t(new HttpHeaders);
headers->append("Keep-Alive", "120");
headers->append("Accept-encoding", "deflate");
headers->append("Accept", "text/plain");
@@ -2460,7 +2419,7 @@ void HttpRequestTestObjectType::test<19>()
url_base + "reflect/",
options,
headers,
- &handler);
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump.
@@ -2478,7 +2437,7 @@ void HttpRequestTestObjectType::test<19>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -2502,17 +2461,8 @@ void HttpRequestTestObjectType::test<19>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -2524,16 +2474,9 @@ void HttpRequestTestObjectType::test<19>()
catch (...)
{
stop_thread(req);
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
+ options.reset();
+ headers.reset();
+
delete req;
HttpRequest::destroyService();
throw;
@@ -2559,19 +2502,21 @@ void HttpRequestTestObjectType::test<20>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
BufferArray * ba = NULL;
try
{
- // Get singletons created
+
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -2582,11 +2527,11 @@ void HttpRequestTestObjectType::test<20>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// headers
- headers = new HttpHeaders();
+ headers = HttpHeaders::ptr_t(new HttpHeaders());
headers->append("keep-Alive", "120");
headers->append("Accept", "text/html");
headers->append("content-type", "application/llsd+xml");
@@ -2675,7 +2620,7 @@ void HttpRequestTestObjectType::test<20>()
ba,
options,
headers,
- &handler);
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
ba->release();
ba = NULL;
@@ -2696,7 +2641,7 @@ void HttpRequestTestObjectType::test<20>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -2720,17 +2665,8 @@ void HttpRequestTestObjectType::test<20>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -2747,16 +2683,8 @@ void HttpRequestTestObjectType::test<20>()
ba->release();
ba = NULL;
}
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
+ options.reset();
+ headers.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -2782,19 +2710,20 @@ void HttpRequestTestObjectType::test<21>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * options = NULL;
- HttpHeaders * headers = NULL;
+ HttpOptions::ptr_t options;
+ HttpHeaders::ptr_t headers;
BufferArray * ba = NULL;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -2805,11 +2734,11 @@ void HttpRequestTestObjectType::test<21>()
req = new HttpRequest();
// options set
- options = new HttpOptions();
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setWantHeaders(true);
// headers
- headers = new HttpHeaders;
+ headers = HttpHeaders::ptr_t(new HttpHeaders);
headers->append("content-type", "text/plain");
headers->append("content-type", "text/html");
headers->append("content-type", "application/llsd+xml");
@@ -2892,7 +2821,7 @@ void HttpRequestTestObjectType::test<21>()
ba,
options,
headers,
- &handler);
+ handlerp);
ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
ba->release();
ba = NULL;
@@ -2913,7 +2842,7 @@ void HttpRequestTestObjectType::test<21>()
mStatus = HttpStatus();
handler.mHeadersRequired.clear();
handler.mHeadersDisallowed.clear();
- handle = req->requestStopThread(&handler);
+ handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -2937,17 +2866,8 @@ void HttpRequestTestObjectType::test<21>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options & headers
- if (options)
- {
- options->release();
- }
- options = NULL;
-
- if (headers)
- {
- headers->release();
- }
- headers = NULL;
+ options.reset();
+ headers.reset();
// release the request object
delete req;
@@ -2964,16 +2884,8 @@ void HttpRequestTestObjectType::test<21>()
ba->release();
ba = NULL;
}
- if (options)
- {
- options->release();
- options = NULL;
- }
- if (headers)
- {
- headers->release();
- headers = NULL;
- }
+ options.reset();
+ headers.reset();
delete req;
HttpRequest::destroyService();
throw;
@@ -2995,18 +2907,19 @@ void HttpRequestTestObjectType::test<22>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
-
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
- HttpOptions * options = NULL;
+ HttpOptions::ptr_t options;
HttpRequest * req = NULL;
try
{
- // options set
- options = new HttpOptions();
+ // options set
+ options = HttpOptions::ptr_t(new HttpOptions());
options->setRetries(1); // Partial_File is retryable and can timeout in here
// Get singletons created
@@ -3035,8 +2948,8 @@ void HttpRequestTestObjectType::test<22>()
0,
25,
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
@@ -3067,8 +2980,8 @@ void HttpRequestTestObjectType::test<22>()
0,
25,
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
@@ -3099,8 +3012,8 @@ void HttpRequestTestObjectType::test<22>()
0,
25,
options,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
}
@@ -3120,7 +3033,7 @@ void HttpRequestTestObjectType::test<22>()
// ======================================
mStatus = HttpStatus();
mHandlerCalls = 0;
- HttpHandle handle = req->requestStopThread(&handler);
+ HttpHandle handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -3144,11 +3057,7 @@ void HttpRequestTestObjectType::test<22>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
- if (options)
- {
- options->release();
- options = NULL;
- }
+ options.reset();
// release the request object
delete req;
@@ -3191,18 +3100,19 @@ void HttpRequestTestObjectType::test<23>()
// references to it after completion of this method.
// Create before memory record as the string copy will bump numbers.
TestHandler2 handler(this, "handler");
- std::string url_base(get_base_url() + "/503/"); // path to 503 generators
+ LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor);
+ std::string url_base(get_base_url() + "/503/"); // path to 503 generators
// record the total amount of dynamically allocated memory
mMemTotal = GetMemTotal();
mHandlerCalls = 0;
HttpRequest * req = NULL;
- HttpOptions * opts = NULL;
+ HttpOptions::ptr_t opts;
try
{
- // Get singletons created
+ // Get singletons created
HttpRequest::createService();
// Start threading early so that thread memory is invariant
@@ -3213,7 +3123,7 @@ void HttpRequestTestObjectType::test<23>()
req = new HttpRequest();
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
- opts = new HttpOptions();
+ opts = HttpOptions::ptr_t(new HttpOptions());
opts->setRetries(1); // Retry once only
opts->setUseRetryAfter(true); // Try to parse the retry-after header
@@ -3230,8 +3140,8 @@ void HttpRequestTestObjectType::test<23>()
0,
0,
opts,
- NULL,
- &handler);
+ HttpHeaders::ptr_t(),
+ handlerp);
std::ostringstream testtag;
testtag << "Valid handle returned for 503 request #" << i;
@@ -3253,7 +3163,7 @@ void HttpRequestTestObjectType::test<23>()
// Okay, request a shutdown of the servicing thread
mStatus = HttpStatus();
mHandlerCalls = 0;
- HttpHandle handle = req->requestStopThread(&handler);
+ HttpHandle handle = req->requestStopThread(handlerp);
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
// Run the notification pump again
@@ -3277,8 +3187,7 @@ void HttpRequestTestObjectType::test<23>()
ensure("Thread actually stopped running", HttpService::isStopped());
// release options
- opts->release();
- opts = NULL;
+ opts.reset();
// release the request object
delete req;
@@ -3299,11 +3208,7 @@ void HttpRequestTestObjectType::test<23>()
catch (...)
{
stop_thread(req);
- if (opts)
- {
- opts->release();
- opts = NULL;
- }
+ opts.reset();
delete req;
HttpRequest::destroyService();
throw;
diff --git a/indra/llcorehttp/tests/test_httprequestqueue.hpp b/indra/llcorehttp/tests/test_httprequestqueue.hpp
index 1de2d8f9ab..ef4ce0479b 100755
--- a/indra/llcorehttp/tests/test_httprequestqueue.hpp
+++ b/indra/llcorehttp/tests/test_httprequestqueue.hpp
@@ -113,16 +113,16 @@ void HttpRequestqueueTestObjectType::test<3>()
HttpRequestQueue * rq = HttpRequestQueue::instanceOf();
- HttpOperation * op = new HttpOpNull();
+ HttpOperation::ptr_t op(new HttpOpNull());
rq->addOp(op); // transfer my refcount
op = rq->fetchOp(true); // Potentially hangs the test on failure
- ensure("One goes in, one comes out", NULL != op);
- op->release();
+ ensure("One goes in, one comes out", static_cast<bool>(op));
+ op.reset();
op = rq->fetchOp(false);
- ensure("Better not be two of them", NULL == op);
+ ensure("Better not be two of them", !op);
// release the singleton, hold on to the object
HttpRequestQueue::term();
@@ -144,13 +144,13 @@ void HttpRequestqueueTestObjectType::test<4>()
HttpRequestQueue * rq = HttpRequestQueue::instanceOf();
- HttpOperation * op = new HttpOpNull();
+ HttpOperation::ptr_t op (new HttpOpNull());
rq->addOp(op); // transfer my refcount
- op = new HttpOpNull();
+ op.reset(new HttpOpNull());
rq->addOp(op); // transfer my refcount
- op = new HttpOpNull();
+ op.reset(new HttpOpNull());
rq->addOp(op); // transfer my refcount
{
@@ -159,8 +159,9 @@ void HttpRequestqueueTestObjectType::test<4>()
ensure("Three go in, three come out", 3 == ops.size());
op = rq->fetchOp(false);
- ensure("Better not be any more of them", NULL == op);
-
+ ensure("Better not be any more of them", !op);
+ op.reset();
+
// release the singleton, hold on to the object
HttpRequestQueue::term();
@@ -168,12 +169,13 @@ void HttpRequestqueueTestObjectType::test<4>()
ensure(mMemTotal < GetMemTotal());
// Release them
- while (! ops.empty())
- {
- HttpOperation * op = ops.front();
- ops.erase(ops.begin());
- op->release();
- }
+ ops.clear();
+// while (! ops.empty())
+// {
+// HttpOperation * op = ops.front();
+// ops.erase(ops.begin());
+// op->release();
+// }
}
// Should be clean
diff --git a/indra/llcorehttp/tests/test_httpstatus.hpp b/indra/llcorehttp/tests/test_httpstatus.hpp
index 0b379836c9..4502d32fe1 100755
--- a/indra/llcorehttp/tests/test_httpstatus.hpp
+++ b/indra/llcorehttp/tests/test_httpstatus.hpp
@@ -55,77 +55,68 @@ void HttpStatusTestObjectType::test<1>()
// auto allocation fine for this
HttpStatus status;
- status.mType = HttpStatus::EXT_CURL_EASY;
- status.mStatus = 0;
+
+ status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
ensure(bool(status));
ensure(false == !(status));
- status.mType = HttpStatus::EXT_CURL_MULTI;
- status.mStatus = 0;
+ status = HttpStatus(HttpStatus::EXT_CURL_MULTI, 0);
ensure(bool(status));
ensure(false == !(status));
-
- status.mType = HttpStatus::LLCORE;
- status.mStatus = HE_SUCCESS;
+
+ status = HttpStatus(HttpStatus::LLCORE, HE_SUCCESS);
ensure(bool(status));
ensure(false == !(status));
- status.mType = HttpStatus::EXT_CURL_MULTI;
- status.mStatus = -1;
+ status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -1);
ensure(false == bool(status));
ensure(!(status));
- status.mType = HttpStatus::EXT_CURL_EASY;
- status.mStatus = CURLE_BAD_DOWNLOAD_RESUME;
+ status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_DOWNLOAD_RESUME);
ensure(false == bool(status));
ensure(!(status));
}
-template <> template <>
-void HttpStatusTestObjectType::test<2>()
-{
- set_test_name("HttpStatus memory structure");
-
- // Require that an HttpStatus object can be trivially
- // returned as a function return value in registers.
- // One should fit in an int on all platforms.
-
- ensure(sizeof(HttpStatus) <= sizeof(int));
-}
+// template <> template <>
+// void HttpStatusTestObjectType::test<2>()
+// {
+// set_test_name("HttpStatus memory structure");
+//
+// // Require that an HttpStatus object can be trivially
+// // returned as a function return value in registers.
+// // One should fit in an int on all platforms.
+//
+// //ensure(sizeof(HttpStatus) <= sizeof(int));
+// }
template <> template <>
-void HttpStatusTestObjectType::test<3>()
+void HttpStatusTestObjectType::test<2>()
{
set_test_name("HttpStatus valid status string conversion");
- HttpStatus status;
- status.mType = HttpStatus::EXT_CURL_EASY;
- status.mStatus = 0;
+ HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
std::string msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(msg.empty());
-
- status.mType = HttpStatus::EXT_CURL_EASY;
- status.mStatus = CURLE_BAD_FUNCTION_ARGUMENT;
+
+ status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_FUNCTION_ARGUMENT);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
- status.mType = HttpStatus::EXT_CURL_MULTI;
- status.mStatus = CURLM_OUT_OF_MEMORY;
+ status = HttpStatus(HttpStatus::EXT_CURL_MULTI, CURLM_OUT_OF_MEMORY);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
- status.mType = HttpStatus::LLCORE;
- status.mStatus = HE_SHUTTING_DOWN;
+ status = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
@@ -133,32 +124,28 @@ void HttpStatusTestObjectType::test<3>()
template <> template <>
-void HttpStatusTestObjectType::test<4>()
+void HttpStatusTestObjectType::test<3>()
{
set_test_name("HttpStatus invalid status string conversion");
- HttpStatus status;
- status.mType = HttpStatus::EXT_CURL_EASY;
- status.mStatus = 32726;
+ HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 32726);
std::string msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
-
- status.mType = HttpStatus::EXT_CURL_MULTI;
- status.mStatus = -470;
+
+ status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -470);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
- status.mType = HttpStatus::LLCORE;
- status.mStatus = 923;
+ status = HttpStatus(HttpStatus::LLCORE, 923);
msg = status.toString();
// std::cout << "Result: " << msg << std::endl;
ensure(! msg.empty());
}
template <> template <>
-void HttpStatusTestObjectType::test<5>()
+void HttpStatusTestObjectType::test<4>()
{
set_test_name("HttpStatus equality/inequality testing");
@@ -170,62 +157,55 @@ void HttpStatusTestObjectType::test<5>()
HttpStatus status2(HttpStatus::EXT_CURL_EASY, HE_SUCCESS);
ensure(status1 != status2);
- status1.mType = HttpStatus::LLCORE;
- status1.mStatus = HE_REPLY_ERROR;
- status2.mType = HttpStatus::LLCORE;
- status2.mStatus= HE_SHUTTING_DOWN;
+ status1 = HttpStatus(HttpStatus::LLCORE, HE_REPLY_ERROR);
+ status1 = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
+
ensure(status1 != status2);
}
template <> template <>
-void HttpStatusTestObjectType::test<6>()
+void HttpStatusTestObjectType::test<5>()
{
set_test_name("HttpStatus basic HTTP status encoding");
HttpStatus status;
- status.mType = 200;
- status.mStatus = HE_SUCCESS;
+
+ status = HttpStatus(200, HE_SUCCESS);
std::string msg = status.toString();
ensure(msg.empty());
ensure(bool(status));
// Normally a success but application says error
- status.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(200, HE_REPLY_ERROR);
msg = status.toString();
ensure(! msg.empty());
ensure(! bool(status));
ensure(status.toULong() > 1UL); // Biggish number, not a bool-to-ulong
// Same statuses with distinct success/fail are distinct
- status.mType = 200;
- status.mStatus = HE_SUCCESS;
+ status = HttpStatus(200, HE_SUCCESS);
HttpStatus status2(200, HE_REPLY_ERROR);
ensure(status != status2);
// Normally an error but application says okay
- status.mType = 406;
- status.mStatus = HE_SUCCESS;
+ status = HttpStatus(406, HE_SUCCESS);
msg = status.toString();
ensure(msg.empty());
ensure(bool(status));
// Different statuses but both successful are distinct
- status.mType = 200;
- status.mStatus = HE_SUCCESS;
- status2.mType = 201;
- status2.mStatus = HE_SUCCESS;
+ status = HttpStatus(200, HE_SUCCESS);
+ status2 = HttpStatus(201, HE_SUCCESS);
ensure(status != status2);
// Different statuses but both failed are distinct
- status.mType = 200;
- status.mStatus = HE_REPLY_ERROR;
- status2.mType = 201;
- status2.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(200, HE_REPLY_ERROR);
+ status2 = HttpStatus(201, HE_REPLY_ERROR);
ensure(status != status2);
}
template <> template <>
-void HttpStatusTestObjectType::test<7>()
+void HttpStatusTestObjectType::test<6>()
{
set_test_name("HttpStatus HTTP status text strings");
@@ -234,34 +214,30 @@ void HttpStatusTestObjectType::test<7>()
ensure(! msg.empty()); // Should be something
ensure(msg == "Continue");
- status.mStatus = HE_SUCCESS;
+ status = HttpStatus(200, HE_SUCCESS);
msg = status.toString();
ensure(msg.empty()); // Success is empty
- status.mType = 199;
- status.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(199, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
- status.mType = 505; // Last defined string
- status.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(505, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "HTTP Version not supported");
- status.mType = 506; // One beyond
- status.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(506, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
- status.mType = 999; // Last HTTP status
- status.mStatus = HE_REPLY_ERROR;
+ status = HttpStatus(999, HE_REPLY_ERROR);
msg = status.toString();
ensure(msg == "Unknown error");
}
template <> template <>
-void HttpStatusTestObjectType::test<8>()
+void HttpStatusTestObjectType::test<7>()
{
set_test_name("HttpStatus toHex() nominal function");
@@ -273,7 +249,7 @@ void HttpStatusTestObjectType::test<8>()
template <> template <>
-void HttpStatusTestObjectType::test<9>()
+void HttpStatusTestObjectType::test<8>()
{
set_test_name("HttpStatus toTerseString() nominal function");