summaryrefslogtreecommitdiff
path: root/indra/llcorehttp
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2012-06-06 13:52:38 -0400
committerMonty Brandenberg <monty@lindenlab.com>2012-06-06 13:52:38 -0400
commit05af16a23abe37210e0b880aa27387d8994419dd (patch)
tree0d23210106dce017e3d5e148dbab9a193fa6604b /indra/llcorehttp
parent6c6d1c8338b15828278d27912bb9fe3b0d133b12 (diff)
Policy + caching fixes + https support + POST working
Implemented first global policy definitions to support SSL CA certificate configuration to support https: operations. Fixed HTTP 206 status handling to match what is currently being done by grid services and to lay a foundation for fixes that will be a response to ER-1824. More libcurl CURLOPT options set on easy handles to do peer verification in the traditional way. HTTP POST working and now reporting asset metrics back to grid for the viewer's asset system. This uses LLSD so that is also showing as compatible with the new library.
Diffstat (limited to 'indra/llcorehttp')
-rw-r--r--indra/llcorehttp/CMakeLists.txt2
-rw-r--r--indra/llcorehttp/_httplibcurl.cpp1
-rw-r--r--indra/llcorehttp/_httpoprequest.cpp45
-rw-r--r--indra/llcorehttp/_httppolicy.cpp4
-rw-r--r--indra/llcorehttp/_httppolicy.h10
-rw-r--r--indra/llcorehttp/_httpservice.h8
-rw-r--r--indra/llcorehttp/httpcommon.cpp5
-rw-r--r--indra/llcorehttp/httpcommon.h11
-rw-r--r--indra/llcorehttp/httprequest.cpp13
-rw-r--r--indra/llcorehttp/httprequest.h16
10 files changed, 93 insertions, 22 deletions
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 9a073eb850..3fda524ddf 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -33,6 +33,7 @@ set(llcorehttp_SOURCE_FILES
_httpoprequest.cpp
_httpopsetpriority.cpp
_httppolicy.cpp
+ _httppolicyglobal.cpp
_httpreplyqueue.cpp
_httprequestqueue.cpp
_httpservice.cpp
@@ -55,6 +56,7 @@ set(llcorehttp_HEADER_FILES
_httpoprequest.h
_httpopsetpriority.h
_httppolicy.h
+ _httppolicyglobal.h
_httpreadyqueue.h
_httpreplyqueue.h
_httprequestqueue.h
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 704f9baac9..5272c391e8 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -27,6 +27,7 @@
#include "_httplibcurl.h"
#include "httpheaders.h"
+#include "bufferarray.h"
#include "_httpoprequest.h"
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index f52ff5a44c..4bdc4a5257 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -40,8 +40,10 @@
#include "_httpreplyqueue.h"
#include "_httpservice.h"
#include "_httppolicy.h"
+#include "_httppolicyglobal.h"
#include "_httplibcurl.h"
+#include "llhttpstatuscodes.h"
namespace
{
@@ -153,14 +155,14 @@ HttpOpRequest::~HttpOpRequest()
void HttpOpRequest::stageFromRequest(HttpService * service)
{
addRef();
- service->getPolicy()->addOp(this); // transfers refcount
+ service->getPolicy().addOp(this); // transfers refcount
}
void HttpOpRequest::stageFromReady(HttpService * service)
{
addRef();
- service->getTransport()->addOp(this); // transfers refcount
+ service->getTransport().addOp(this); // transfers refcount
}
@@ -195,6 +197,8 @@ void HttpOpRequest::stageFromActive(HttpService * service)
void HttpOpRequest::visitNotifier(HttpRequest * request)
{
+ static const HttpStatus partial_content(HTTP_PARTIAL_CONTENT, HE_SUCCESS);
+
if (mLibraryHandler)
{
HttpResponse * response = new HttpResponse();
@@ -208,9 +212,15 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
offset = mReplyOffset;
length = mReplyLength;
}
- else if (mReplyBody)
+ else if (mReplyBody && partial_content == mStatus)
{
- // Provide implicit offset/length from request/response
+ // Legacy grid services did not provide a 'Content-Range'
+ // header in responses to full- or partly-satisfyiable
+ // 'Range' requests. For these, we have to hope that
+ // the data starts where requested and the length is simply
+ // whatever we received. A bit of sanity could be provided
+ // by overlapping ranged requests and verifying that the
+ // overlap matches.
offset = mReqOffset;
length = mReplyBody->size();
}
@@ -306,6 +316,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// *FIXME: better error handling later
HttpStatus status;
+ // Get policy options
+ HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions());
+
mCurlHandle = curl_easy_init();
// curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, 30);
@@ -322,21 +335,40 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, 10);
+ curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, 10); // *FIXME: parameterize this later
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, mCurlHandle);
curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, mCurlHandle);
+ curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
+ curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+ std::string opt_value;
+ if (policy.get(HttpRequest::GP_CA_PATH, opt_value))
+ {
+ curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, opt_value.c_str());
+ }
+ if (policy.get(HttpRequest::GP_CA_FILE, opt_value))
+ {
+ curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, opt_value.c_str());
+ }
+ if (policy.get(HttpRequest::GP_HTTP_PROXY, opt_value))
+ {
+ curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value.c_str());
+ }
+
switch (mReqMethod)
{
case HOR_GET:
curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
break;
case HOR_POST:
{
curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
+ curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
long data_size(0);
if (mReqBody)
{
@@ -358,8 +390,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
data_size = mReqBody->size();
}
curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
+ curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Transfer-Encoding: chunked");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
+ mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
}
break;
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 1d28f23d56..51f5e487dc 100644
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -76,12 +76,12 @@ void HttpPolicy::addOp(HttpOpRequest * op)
HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
{
HttpService::ELoopSpeed result(HttpService::REQUEST_SLEEP);
- HttpLibcurl * pTransport(mService->getTransport());
+ HttpLibcurl & transport(mService->getTransport());
for (int policy_class(0); policy_class < HttpRequest::POLICY_CLASS_LIMIT; ++policy_class)
{
HttpReadyQueue & readyq(mReadyQueue[policy_class]);
- int active(pTransport->getActiveCountInClass(policy_class));
+ int active(transport.getActiveCountInClass(policy_class));
int needed(8 - active);
if (needed > 0 && mReadyInClass[policy_class] > 0)
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index 2bc03c531f..425079ec63 100644
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -31,6 +31,7 @@
#include "httprequest.h"
#include "_httpservice.h"
#include "_httpreadyqueue.h"
+#include "_httppolicyglobal.h"
namespace LLCore
@@ -68,11 +69,20 @@ public:
// Shadows HttpService's method
bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
+
+ // Get pointer to global policy options. Caller is expected
+ // to do context checks like no setting once running.
+ HttpPolicyGlobal & getGlobalOptions()
+ {
+ return mGlobalOptions;
+ }
+
protected:
int mReadyInClass[HttpRequest::POLICY_CLASS_LIMIT];
HttpReadyQueue mReadyQueue[HttpRequest::POLICY_CLASS_LIMIT];
HttpService * mService; // Naked pointer, not refcounted, not owner
+ HttpPolicyGlobal mGlobalOptions;
}; // end class HttpPolicy
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index 095316c8a7..748354a8e4 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -148,14 +148,14 @@ public:
/// Threading: callable by worker thread.
bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
- HttpPolicy * getPolicy()
+ HttpPolicy & getPolicy()
{
- return mPolicy;
+ return *mPolicy;
}
- HttpLibcurl * getTransport()
+ HttpLibcurl & getTransport()
{
- return mTransport;
+ return *mTransport;
}
protected:
diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index a01182cf23..9f17b5c842 100644
--- a/indra/llcorehttp/httpcommon.cpp
+++ b/indra/llcorehttp/httpcommon.cpp
@@ -66,7 +66,10 @@ std::string HttpStatus::toString() const
"Services shutting down",
"Operation canceled",
"Invalid Content-Range header encountered",
- "Request handle not found"
+ "Request handle not found",
+ "Invalid datatype for argument or option",
+ "Option has not been explicitly set",
+ "Option is not dynamic and must be set early"
};
static const int llcore_errors_count(sizeof(llcore_errors) / sizeof(llcore_errors[0]));
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index c01a5f85d3..fd2661b700 100644
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -137,7 +137,16 @@ enum HttpError
HE_INV_CONTENT_RANGE_HDR = 4,
// Request handle not found
- HE_HANDLE_NOT_FOUND = 5
+ HE_HANDLE_NOT_FOUND = 5,
+
+ // Invalid datatype for option/setting
+ HE_INVALID_ARG = 6,
+
+ // Option hasn't been explicitly set
+ HE_OPT_NOT_SET = 7,
+
+ // Option not dynamic, must be set during init phase
+ HE_OPT_NOT_DYNAMIC = 8
}; // end enum HttpError
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 0e512d97ed..baa0fe1a84 100644
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -29,6 +29,7 @@
#include "_httprequestqueue.h"
#include "_httpreplyqueue.h"
#include "_httpservice.h"
+#include "_httppolicy.h"
#include "_httpoperation.h"
#include "_httpoprequest.h"
#include "_httpopsetpriority.h"
@@ -127,9 +128,17 @@ HttpRequest::~HttpRequest()
HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, long value)
{
- HttpStatus status;
+ // *FIXME: Fail if thread is running.
- return status;
+ return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value);
+}
+
+
+HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value)
+{
+ // *FIXME: Fail if thread is running.
+
+ return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value);
}
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 57d2da245b..3592d5c6a3 100644
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -111,7 +111,10 @@ public:
/// Maximum number of connections the library will use to
/// perform operations. This is somewhat soft as the underlying
/// transport will cache some connections (up to 5).
- GLOBAL_CONNECTION_LIMIT
+ GP_CONNECTION_LIMIT, ///< Takes long giving number of connections
+ GP_CA_PATH, ///< System path/directory where SSL certs are stored.
+ GP_CA_FILE, ///< System path/file containing certs.
+ GP_HTTP_PROXY ///< String giving host/port to use for HTTP proxy
};
/// Set a parameter on a global policy option. Calls
@@ -122,6 +125,7 @@ public:
/// @param value Desired value of option.
/// @return Standard status code.
HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, long value);
+ HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value);
/// Create a new policy class into which requests can be made.
///
@@ -134,15 +138,15 @@ public:
enum EClassPolicy
{
/// Limits the number of connections used for the class.
- CLASS_CONNECTION_LIMIT,
+ CP_CONNECTION_LIMIT,
/// Limits the number of connections used for a single
/// literal address/port pair within the class.
- PER_HOST_CONNECTION_LIMIT,
+ CP_PER_HOST_CONNECTION_LIMIT,
/// Suitable requests are allowed to pipeline on their
/// connections when they ask for it.
- ENABLE_PIPELINING
+ CP_ENABLE_PIPELINING
};
/// Set a parameter on a class-based policy option. Calls
@@ -153,9 +157,7 @@ public:
/// @param opt Enum of option to be set.
/// @param value Desired value of option.
/// @return Standard status code.
- HttpStatus setPolicyClassOption(policy_t policy_id,
- EClassPolicy opt,
- long value);
+ HttpStatus setPolicyClassOption(policy_t policy_id, EClassPolicy opt, long value);
/// @}