summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRider Linden <none@none>2015-03-16 17:14:34 -0700
committerRider Linden <none@none>2015-03-16 17:14:34 -0700
commit6f4d36634e980bb989b9a8b762c3c622804c43dd (patch)
treeefa71ac14bdef46b9796688d4a445d60fdd5b1c3
parentd4a2e9fd9a0e7001a6c824ddd6cf37039a632b9d (diff)
Removal of RPCXML dep on LLCurl switching to LLCore::Html
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp95
-rwxr-xr-xindra/llcorehttp/_httpoprequest.h11
-rwxr-xr-xindra/llcorehttp/_httppolicyglobal.cpp30
-rwxr-xr-xindra/llcorehttp/_httppolicyglobal.h3
-rwxr-xr-xindra/llcorehttp/_httpservice.cpp80
-rwxr-xr-xindra/llcorehttp/_httpservice.h9
-rwxr-xr-xindra/llcorehttp/_refcounted.h11
-rwxr-xr-xindra/llcorehttp/bufferarray.h2
-rwxr-xr-xindra/llcorehttp/httpcommon.cpp24
-rwxr-xr-xindra/llcorehttp/httpcommon.h116
-rwxr-xr-xindra/llcorehttp/httphandler.h4
-rwxr-xr-xindra/llcorehttp/httpheaders.h1
-rwxr-xr-xindra/llcorehttp/httpoptions.cpp39
-rwxr-xr-xindra/llcorehttp/httpoptions.h31
-rwxr-xr-xindra/llcorehttp/httprequest.cpp17
-rwxr-xr-xindra/llcorehttp/httprequest.h17
-rwxr-xr-xindra/llcorehttp/httpresponse.h25
-rwxr-xr-xindra/llmessage/llcurl.cpp854
-rwxr-xr-xindra/llmessage/llcurl.h9
-rwxr-xr-xindra/llmessage/llhttpclient.cpp49
-rwxr-xr-xindra/llmessage/llhttpclientadapter.cpp90
-rwxr-xr-xindra/llmessage/llhttpclientadapter.h2
-rwxr-xr-xindra/llmessage/llhttpclientinterface.h16
-rwxr-xr-xindra/llmessage/llsdrpcclient.h8
-rwxr-xr-xindra/newview/llappcorehttp.cpp69
-rwxr-xr-xindra/newview/llappcorehttp.h4
-rwxr-xr-xindra/newview/llhttpretrypolicy.cpp2
-rwxr-xr-xindra/newview/llvoavatarself.cpp1
-rwxr-xr-xindra/newview/llxmlrpctransaction.cpp497
-rwxr-xr-xindra/newview/llxmlrpctransaction.h4
30 files changed, 1280 insertions, 840 deletions
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index b9632a7921..48e22468cd 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -115,8 +115,9 @@ namespace LLCore
{
-HttpOpRequest::HttpOpRequest()
+HttpOpRequest::HttpOpRequest(HttpRequest const * const request)
: HttpOperation(),
+ mRequest(request),
mProcFlags(0U),
mReqMethod(HOR_GET),
mReqBody(NULL),
@@ -139,7 +140,8 @@ HttpOpRequest::HttpOpRequest()
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().
@@ -267,6 +269,14 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
response->setContentType(mReplyConType);
response->setRetries(mPolicyRetries, mPolicy503Retries);
+ 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(static_cast<HttpHandle>(this), response);
response->release();
@@ -452,18 +462,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
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);
@@ -474,11 +474,49 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_code(code, CURLOPT_READFUNCTION);
code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
check_curl_easy_code(code, CURLOPT_READDATA);
- code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
+
+ 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, this);
+ check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA);
+ mCallbackSSLVerify = gpolicy.mSslCtxCallback;
+ }
+
+ long follow_redirect(1L);
+ long sslPeerV(0L);
+ long sslHostV(0L);
+ long dnsCacheTimeout(15L);
+
+ if (mReqOptions)
+ {
+ follow_redirect = mReqOptions->getFollowRedirects() ? 1L : 0L;
+ sslPeerV = mReqOptions->getSSLVerifyHost() ? 0L : 1L;
+ sslHostV = mReqOptions->getSSLVerifyHost();
+ dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
+ }
+ 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);
+ // 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
@@ -873,6 +911,35 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
}
+CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)
+{
+ HttpOpRequest * op(static_cast<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 * op(static_cast<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));
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 2f628b5aba..7a4b7c189e 100755
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -33,6 +33,9 @@
#include <string>
#include <curl/curl.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+
#include "httpcommon.h"
#include "httprequest.h"
#include "_httpoperation.h"
@@ -63,7 +66,7 @@ class HttpOptions;
class HttpOpRequest : public HttpOperation
{
public:
- HttpOpRequest();
+ HttpOpRequest(HttpRequest const * const request);
protected:
virtual ~HttpOpRequest(); // Use release()
@@ -151,6 +154,9 @@ 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 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,8 +165,11 @@ protected:
static const unsigned int PF_SAVE_HEADERS = 0x00000002U;
static const unsigned int PF_USE_RETRY_AFTER = 0x00000004U;
+ HttpRequest::policyCallback mCallbackSSLVerify;
+
public:
// Request data
+ HttpRequest const * const mRequest;
EMethod mReqMethod;
std::string mReqURL;
BufferArray * mReqBody;
diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp
index 1dc95f3dce..c4ef38a815 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 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 * 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..1696238814 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 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 * value) const;
public:
long mConnectionLimit;
@@ -70,6 +72,7 @@ public:
std::string mHttpProxy;
long mTrace;
long mUseLLProxy;
+ HttpRequest::policyCallback mSslCtxCallback;
}; // end class HttpPolicyGlobal
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index c673e1be1d..7b8aac35a8 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);
@@ -413,6 +414,34 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
return status;
}
+HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+ HttpRequest::policyCallback * 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 +518,37 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
return status;
}
-
+
+HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+ HttpRequest::policyCallback value, HttpRequest::policyCallback * 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..699a8eaa4f 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 * 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 value,
+ HttpRequest::policyCallback * 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..cd16e2e2b4 100755
--- a/indra/llcorehttp/_refcounted.h
+++ b/indra/llcorehttp/_refcounted.h
@@ -120,7 +120,18 @@ inline void RefCounted::destroySelf()
delete this;
}
+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..9c2b991de6 100755
--- a/indra/llcorehttp/bufferarray.h
+++ b/indra/llcorehttp/bufferarray.h
@@ -73,6 +73,8 @@ public:
BufferArray();
+ typedef boost::intrusive_ptr<BufferArray> ptr_t;
+
protected:
virtual ~BufferArray(); // Use release()
diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index 7907e958a4..1aece696e3 100755
--- a/indra/llcorehttp/httpcommon.cpp
+++ b/indra/llcorehttp/httpcommon.cpp
@@ -42,7 +42,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,18 +131,18 @@ std::string HttpStatus::toString() const
{
return std::string("");
}
- switch (mType)
+ switch (mDetails->mType)
{
case EXT_CURL_EASY:
- return std::string(curl_easy_strerror(CURLcode(mStatus)));
+ return std::string(curl_easy_strerror(CURLcode(mDetails->mStatus)));
case EXT_CURL_MULTI:
- return std::string(curl_multi_strerror(CURLMcode(mStatus)));
+ return std::string(curl_multi_strerror(CURLMcode(mDetails->mStatus)));
case LLCORE:
- if (mStatus >= 0 && mStatus < llcore_errors_count)
+ if (mDetails->mStatus >= 0 && mDetails->mStatus < llcore_errors_count)
{
- return std::string(llcore_errors[mStatus]);
+ return std::string(llcore_errors[mDetails->mStatus]);
}
break;
@@ -154,7 +154,7 @@ std::string HttpStatus::toString() const
while (true)
{
int at((bottom + top) / 2);
- if (mType == http_errors[at].mCode)
+ if (mDetails->mType == http_errors[at].mCode)
{
return std::string(http_errors[at].mText);
}
@@ -162,7 +162,7 @@ std::string HttpStatus::toString() const
{
break;
}
- else if (mType < http_errors[at].mCode)
+ else if (mDetails->mType < http_errors[at].mCode)
{
top = at;
}
@@ -182,9 +182,9 @@ std::string HttpStatus::toTerseString() const
{
std::ostringstream result;
- unsigned int error_value((unsigned short) mStatus);
+ unsigned int error_value((unsigned short)mDetails->mStatus);
- switch (mType)
+ switch (mDetails->mType)
{
case EXT_CURL_EASY:
result << "Easy_";
@@ -202,7 +202,7 @@ std::string HttpStatus::toTerseString() const
if (isHttpStatus())
{
result << "Http_";
- error_value = mType;
+ error_value = mDetails->mType;
}
else
{
@@ -244,7 +244,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() && mDetails->mType >= 499 && mDetails->mType <= 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
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index 9601f94125..0244755272 100755
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -191,7 +191,6 @@
#include <string>
-
namespace LLCore
{
@@ -292,35 +291,35 @@ struct HttpStatus
typedef unsigned short type_enum_t;
HttpStatus()
- : mType(LLCORE),
- mStatus(HE_SUCCESS)
- {}
+ {
+ mDetails = std::unique_ptr<Details>(new Details(LLCORE, HE_SUCCESS));
+ }
HttpStatus(type_enum_t type, short status)
- : mType(type),
- mStatus(status)
- {}
+ {
+ mDetails = std::unique_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)
{
+ mDetails = std::unique_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(const HttpStatus & rhs)
- : mType(rhs.mType),
- mStatus(rhs.mStatus)
- {}
+ {
+ mDetails = std::unique_ptr<Details>(new Details(*rhs.mDetails));
+ }
HttpStatus & operator=(const HttpStatus & rhs)
{
// Don't care if lhs & rhs are the same object
+ mDetails->mType = rhs.mDetails->mType;
+ mDetails->mStatus = rhs.mDetails->mStatus;
+ mDetails->mMessage = rhs.mDetails->mMessage;
+ mDetails->mErrorData = rhs.mDetails->mErrorData;
- mType = rhs.mType;
- mStatus = rhs.mStatus;
return *this;
}
@@ -328,10 +327,6 @@ struct HttpStatus
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 +334,7 @@ struct HttpStatus
///
operator bool() const
{
- return 0 == mStatus;
+ return 0 == mDetails->mStatus;
}
/// Inverse of previous operator.
@@ -347,14 +342,15 @@ 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->mType == rhs.mDetails->mType) &&
+ (mDetails->mStatus == rhs.mDetails->mStatus);
}
bool operator!=(const HttpStatus & rhs) const
@@ -395,7 +391,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,7 +399,77 @@ 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;
+ }
+
+ // TODO: There must be a better way to do this. Don't want to set these
+ // values here since they increase the size of a structure that is already
+ // being passed on the stack. Consider my options
+ /// 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)
+ {}
+
+
+ type_enum_t mType;
+ short mStatus;
+ std::string mMessage;
+ void * mErrorData;
+ };
+
+ std::unique_ptr<Details> mDetails;
+
}; // end struct HttpStatus
} // end namespace LLCore
diff --git a/indra/llcorehttp/httphandler.h b/indra/llcorehttp/httphandler.h
index 9171e4e7b9..740e986dec 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.
///
@@ -58,7 +58,7 @@ class HttpHandler
{
public:
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.h b/indra/llcorehttp/httpheaders.h
index f70cd898f3..c89d6af222 100755
--- a/indra/llcorehttp/httpheaders.h
+++ b/indra/llcorehttp/httpheaders.h
@@ -92,6 +92,7 @@ public:
/// the instance.
HttpHeaders();
+ typedef boost::intrusive_ptr<HttpHeaders> ptr_t;
protected:
virtual ~HttpHeaders(); // Use release()
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index 5bf1ecb4a5..28c2c25e92 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,17 @@ 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() : 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),
+ mFollowRedirects(false),
+ mVerifyPeer(false),
+ mVerifyHost(0),
+ mDNSCacheTimeout(15)
{}
@@ -82,5 +85,23 @@ 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(unsigned int type)
+{
+ mVerifyHost = llclamp<unsigned int>(type, 0, 2);
+}
+
+void HttpOptions::setDNSCacheTimeout(int timeout)
+{
+ mDNSCacheTimeout = timeout;
+}
} // end namespace LLCore
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 4ab5ff18c4..d6d892213d 100755
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -61,6 +61,8 @@ class HttpOptions : public LLCoreInt::RefCounted
public:
HttpOptions();
+ typedef boost::intrusive_ptr<HttpOptions> ptr_t;
+
protected:
virtual ~HttpOptions(); // Use release()
@@ -109,6 +111,31 @@ public:
{
return mUseRetryAfter;
}
+
+ // Default: false
+ void setFollowRedirects(bool follow_redirect);
+ bool getFollowRedirects() const
+ {
+ return mFollowRedirects;
+ }
+
+ void setSSLVerifyPeer(bool verify);
+ bool getSSLVerifyPeer() const
+ {
+ return mVerifyPeer;
+ }
+
+ void setSSLVerifyHost(unsigned int type);
+ unsigned int getSSLVerifyHost() const
+ {
+ return mVerifyHost;
+ }
+
+ void setDNSCacheTimeout(int timeout);
+ int getDNSCacheTimeout() const
+ {
+ return mDNSCacheTimeout;
+ }
protected:
bool mWantHeaders;
@@ -117,6 +144,10 @@ protected:
unsigned int mTransferTimeout;
unsigned int mRetries;
bool mUseRetryAfter;
+ bool mFollowRedirects;
+ bool mVerifyPeer;
+ unsigned int mVerifyHost;
+ int mDNSCacheTimeout;
}; // end class HttpOptions
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 7b1888e3eb..5f1ed3d43b 100755
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -117,6 +117,15 @@ 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 value, policyCallback * 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)
@@ -195,7 +204,7 @@ HttpHandle HttpRequest::requestGet(policy_t policy_id,
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest * op = new HttpOpRequest(this);
if (! (status = op->setupGet(policy_id, priority, url, options, headers)))
{
op->release();
@@ -229,7 +238,7 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest * op = new HttpOpRequest(this);
if (! (status = op->setupGetByteRange(policy_id, priority, url, offset, len, options, headers)))
{
op->release();
@@ -262,7 +271,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest * op = new HttpOpRequest(this);
if (! (status = op->setupPost(policy_id, priority, url, body, options, headers)))
{
op->release();
@@ -295,7 +304,7 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
HttpStatus status;
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
- HttpOpRequest * op = new HttpOpRequest();
+ HttpOpRequest * op = new HttpOpRequest(this);
if (! (status = op->setupPut(policy_id, priority, url, body, options, headers)))
{
op->release();
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 7f23723b0b..c90e056d62 100755
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -97,6 +97,7 @@ public:
typedef unsigned int policy_t;
typedef unsigned int priority_t;
+ typedef std::shared_ptr<HttpRequest> ptr_t;
public:
/// @name PolicyMethods
/// @{
@@ -163,7 +164,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 +220,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 HttpStatus(*policyCallback)(const std::string &, HttpHandler const * const, void *);
+
/// Set a policy option for a global or class parameter at
/// startup time (prior to thread start).
///
@@ -243,6 +254,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 value, policyCallback * ret_value);;
/// Set a parameter on a class-based policy option. Calls
/// made after the start of the servicing thread are
diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h
index aee64e2878..01e9dd2bc6 100755
--- a/indra/llcorehttp/httpresponse.h
+++ b/indra/llcorehttp/httpresponse.h
@@ -69,6 +69,18 @@ protected:
void operator=(const HttpResponse &); // Not defined
public:
+ /// Statistics for the HTTP
+ struct TransferStats
+ {
+ typedef std::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
@@ -168,6 +180,17 @@ public:
m503Retries = retries_503;
}
+ void setTransferStats(TransferStats::ptr_t &stats)
+ {
+ mStats = stats;
+ }
+
+ TransferStats::ptr_t getTransferStats()
+ {
+ return mStats;
+ }
+
+
protected:
// Response data here
HttpStatus mStatus;
@@ -179,6 +202,8 @@ protected:
std::string mContentType;
unsigned int mRetries;
unsigned int m503Retries;
+
+ TransferStats::ptr_t mStats;
};
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 73df47b933..0080dd6138 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -676,6 +676,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
}
////////////////////////////////////////////////////////////////////////////
+#if 1
LLCurl::Multi::Multi(F32 idle_time_out)
: mQueued(0),
mErrorCount(0),
@@ -1056,6 +1057,7 @@ void LLCurl::Multi::removeEasy(Easy* easy)
easyFree(easy);
}
+#endif
//------------------------------------------------------------
//LLCurlThread
LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) :
@@ -1176,428 +1178,428 @@ std::string LLCurl::strerror(CURLcode errorcode)
// For generating a simple request for data
// using one multi and one easy per request
-LLCurlRequest::LLCurlRequest() :
- mActiveMulti(NULL),
- mActiveRequestCount(0)
-{
- mProcessing = FALSE;
-}
-
-LLCurlRequest::~LLCurlRequest()
-{
- //stop all Multi handle background threads
- for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
- {
- LLCurl::getCurlThread()->killMulti(*iter) ;
- }
- mMultiSet.clear() ;
-}
-
-void LLCurlRequest::addMulti()
-{
- LLCurl::Multi* multi = new LLCurl::Multi();
- if(!multi->isValid())
- {
- LLCurl::getCurlThread()->killMulti(multi) ;
- mActiveMulti = NULL ;
- mActiveRequestCount = 0 ;
- return;
- }
-
- mMultiSet.insert(multi);
- mActiveMulti = multi;
- mActiveRequestCount = 0;
-}
-
-LLCurl::Easy* LLCurlRequest::allocEasy()
-{
- if (!mActiveMulti ||
- mActiveRequestCount >= MAX_ACTIVE_REQUEST_COUNT ||
- mActiveMulti->mErrorCount > 0)
- {
- addMulti();
- }
- if(!mActiveMulti)
- {
- return NULL ;
- }
-
- //llassert_always(mActiveMulti);
- ++mActiveRequestCount;
- LLCurl::Easy* easy = mActiveMulti->allocEasy();
- return easy;
-}
-
-bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
-{
- llassert_always(mActiveMulti);
-
- if (mProcessing)
- {
- LL_ERRS() << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << LL_ENDL;
- }
- bool res = mActiveMulti->addEasy(easy);
- return res;
-}
-
-void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
- getByteRange(url, headers_t(), 0, -1, responder);
-}
-
-// Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
-// the remainder of the file if not.
-bool LLCurlRequest::getByteRange(const std::string& url,
- const headers_t& headers,
- S32 offset, S32 length,
- LLCurl::ResponderPtr responder)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder);
- easy->setopt(CURLOPT_HTTPGET, 1);
- if (length > 0)
- {
- std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
- easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
- }
- else if (offset > 0)
- {
- std::string range = llformat("bytes=%d-", offset);
- easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
- }
- easy->setHeaders();
- bool res = addEasy(easy);
- return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
- const headers_t& headers,
- const LLSD& data,
- LLCurl::ResponderPtr responder, S32 time_out)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder, time_out);
-
- LLSDSerialize::toXML(data, easy->getInput());
- S32 bytes = easy->getInput().str().length();
-
- easy->setopt(CURLOPT_POST, 1);
- easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
- easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
- easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
- easy->setHeaders();
-
- LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
- bool res = addEasy(easy);
- return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
- const headers_t& headers,
- const std::string& data,
- LLCurl::ResponderPtr responder, S32 time_out)
-{
- llassert(LLCurl::sNotQuitting);
- LLCurl::Easy* easy = allocEasy();
- if (!easy)
- {
- return false;
- }
- easy->prepRequest(url, headers, responder, time_out);
-
- easy->getInput().write(data.data(), data.size());
- S32 bytes = easy->getInput().str().length();
-
- easy->setopt(CURLOPT_POST, 1);
- easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
- easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
- easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
- easy->setHeaders();
-
- LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
- bool res = addEasy(easy);
- return res;
-}
-
-// Note: call once per frame
-S32 LLCurlRequest::process()
-{
- S32 res = 0;
-
- mProcessing = TRUE;
- for (curlmulti_set_t::iterator iter = mMultiSet.begin();
- iter != mMultiSet.end(); )
- {
- curlmulti_set_t::iterator curiter = iter++;
- LLCurl::Multi* multi = *curiter;
-
- if(!multi->isValid())
- {
- if(multi == mActiveMulti)
- {
- mActiveMulti = NULL ;
- mActiveRequestCount = 0 ;
- }
- mMultiSet.erase(curiter) ;
- LLCurl::getCurlThread()->killMulti(multi) ;
- continue ;
- }
-
- S32 tres = multi->process();
- res += tres;
- if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
- {
- mMultiSet.erase(curiter);
- LLCurl::getCurlThread()->killMulti(multi);
- }
- }
- mProcessing = FALSE;
- return res;
-}
-
-S32 LLCurlRequest::getQueued()
-{
- S32 queued = 0;
- for (curlmulti_set_t::iterator iter = mMultiSet.begin();
- iter != mMultiSet.end(); )
- {
- curlmulti_set_t::iterator curiter = iter++;
- LLCurl::Multi* multi = *curiter;
-
- if(!multi->isValid())
- {
- if(multi == mActiveMulti)
- {
- mActiveMulti = NULL ;
- mActiveRequestCount = 0 ;
- }
- LLCurl::getCurlThread()->killMulti(multi);
- mMultiSet.erase(curiter) ;
- continue ;
- }
-
- queued += multi->mQueued;
- if (multi->getState() != LLCurl::Multi::STATE_READY)
- {
- ++queued;
- }
- }
- return queued;
-}
-
-LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) :
- LLCurlRequest(),
- mConcurrency(concurrency),
- mInQueue(0),
- mMutex(NULL),
- mHandleCounter(1),
- mTotalIssuedRequests(0),
- mTotalReceivedBits(0)
-{
- mGlobalTimer.reset();
-}
-
-LLCurlTextureRequest::~LLCurlTextureRequest()
-{
- mRequestMap.clear();
-
- for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
- {
- delete *iter;
- }
- mCachedRequests.clear();
-}
-
-//return 0: success
-// > 0: cached handle
-U32 LLCurlTextureRequest::getByteRange(const std::string& url,
- const headers_t& headers,
- S32 offset, S32 length, U32 pri,
- LLCurl::ResponderPtr responder, F32 delay_time)
-{
- U32 ret_val = 0;
- bool success = false;
-
- if(mInQueue < mConcurrency && delay_time < 0.f)
- {
- success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);
- }
-
- LLMutexLock lock(&mMutex);
-
- if(success)
- {
- mInQueue++;
- mTotalIssuedRequests++;
- }
- else
- {
- request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
- if(delay_time > 0.f)
- {
- request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
- }
-
- mCachedRequests.insert(request);
- mRequestMap[mHandleCounter] = request;
- ret_val = mHandleCounter;
- mHandleCounter++;
-
- if(!mHandleCounter)
- {
- mHandleCounter = 1;
- }
- }
-
- return ret_val;
-}
-
-void LLCurlTextureRequest::completeRequest(S32 received_bytes)
-{
- LLMutexLock lock(&mMutex);
-
- llassert_always(mInQueue > 0);
-
- mInQueue--;
- mTotalReceivedBits += received_bytes * 8;
-}
-
-void LLCurlTextureRequest::nextRequests()
-{
- if(mCachedRequests.empty() || mInQueue >= mConcurrency)
- {
- return;
- }
-
- F32 cur_time = mGlobalTimer.getElapsedTimeF32();
-
- req_queue_t::iterator iter;
- {
- LLMutexLock lock(&mMutex);
- iter = mCachedRequests.begin();
- }
- while(1)
- {
- request_t* request = *iter;
- if(request->mStartTime < cur_time)
- {
- if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
- {
- break;
- }
-
- LLMutexLock lock(&mMutex);
- ++iter;
- mInQueue++;
- mTotalIssuedRequests++;
- mCachedRequests.erase(request);
- mRequestMap.erase(request->mHandle);
- delete request;
-
- if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
- {
- break;
- }
- }
- else
- {
- LLMutexLock lock(&mMutex);
- ++iter;
- if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
- {
- break;
- }
- }
- }
-
- return;
-}
-
-void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
-{
- if(!handle)
- {
- return;
- }
-
- LLMutexLock lock(&mMutex);
-
- std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
- if(iter != mRequestMap.end())
- {
- request_t* req = iter->second;
-
- if(req->mPriority != pri)
- {
- mCachedRequests.erase(req);
- req->mPriority = pri;
- mCachedRequests.insert(req);
- }
- }
-}
-
-void LLCurlTextureRequest::removeRequest(U32 handle)
-{
- if(!handle)
- {
- return;
- }
-
- LLMutexLock lock(&mMutex);
-
- std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
- if(iter != mRequestMap.end())
- {
- request_t* req = iter->second;
- mRequestMap.erase(iter);
- mCachedRequests.erase(req);
- delete req;
- }
-}
-
-bool LLCurlTextureRequest::isWaiting(U32 handle)
-{
- if(!handle)
- {
- return false;
- }
-
- LLMutexLock lock(&mMutex);
- return mRequestMap.find(handle) != mRequestMap.end();
-}
-
-U32 LLCurlTextureRequest::getTotalReceivedBits()
-{
- LLMutexLock lock(&mMutex);
-
- U32 bits = mTotalReceivedBits;
- mTotalReceivedBits = 0;
- return bits;
-}
-
-U32 LLCurlTextureRequest::getTotalIssuedRequests()
-{
- LLMutexLock lock(&mMutex);
- return mTotalIssuedRequests;
-}
-
-S32 LLCurlTextureRequest::getNumRequests()
-{
- LLMutexLock lock(&mMutex);
- return mInQueue;
-}
+// LLCurlRequest::LLCurlRequest() :
+// mActiveMulti(NULL),
+// mActiveRequestCount(0)
+// {
+// mProcessing = FALSE;
+// }
+//
+// LLCurlRequest::~LLCurlRequest()
+// {
+// //stop all Multi handle background threads
+// for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
+// {
+// LLCurl::getCurlThread()->killMulti(*iter) ;
+// }
+// mMultiSet.clear() ;
+// }
+//
+// void LLCurlRequest::addMulti()
+// {
+// LLCurl::Multi* multi = new LLCurl::Multi();
+// if(!multi->isValid())
+// {
+// LLCurl::getCurlThread()->killMulti(multi) ;
+// mActiveMulti = NULL ;
+// mActiveRequestCount = 0 ;
+// return;
+// }
+//
+// mMultiSet.insert(multi);
+// mActiveMulti = multi;
+// mActiveRequestCount = 0;
+// }
+//
+// LLCurl::Easy* LLCurlRequest::allocEasy()
+// {
+// if (!mActiveMulti ||
+// mActiveRequestCount >= MAX_ACTIVE_REQUEST_COUNT ||
+// mActiveMulti->mErrorCount > 0)
+// {
+// addMulti();
+// }
+// if(!mActiveMulti)
+// {
+// return NULL ;
+// }
+//
+// //llassert_always(mActiveMulti);
+// ++mActiveRequestCount;
+// LLCurl::Easy* easy = mActiveMulti->allocEasy();
+// return easy;
+// }
+//
+// bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
+// {
+// llassert_always(mActiveMulti);
+//
+// if (mProcessing)
+// {
+// LL_ERRS() << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << LL_ENDL;
+// }
+// bool res = mActiveMulti->addEasy(easy);
+// return res;
+// }
+//
+// void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
+// {
+// getByteRange(url, headers_t(), 0, -1, responder);
+// }
+//
+// // Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
+// // the remainder of the file if not.
+// bool LLCurlRequest::getByteRange(const std::string& url,
+// const headers_t& headers,
+// S32 offset, S32 length,
+// LLCurl::ResponderPtr responder)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder);
+// easy->setopt(CURLOPT_HTTPGET, 1);
+// if (length > 0)
+// {
+// std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
+// easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
+// }
+// else if (offset > 0)
+// {
+// std::string range = llformat("bytes=%d-", offset);
+// easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
+// }
+// easy->setHeaders();
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// bool LLCurlRequest::post(const std::string& url,
+// const headers_t& headers,
+// const LLSD& data,
+// LLCurl::ResponderPtr responder, S32 time_out)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder, time_out);
+//
+// LLSDSerialize::toXML(data, easy->getInput());
+// S32 bytes = easy->getInput().str().length();
+//
+// easy->setopt(CURLOPT_POST, 1);
+// easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
+// easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
+//
+// easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+// easy->setHeaders();
+//
+// LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// bool LLCurlRequest::post(const std::string& url,
+// const headers_t& headers,
+// const std::string& data,
+// LLCurl::ResponderPtr responder, S32 time_out)
+// {
+// llassert(LLCurl::sNotQuitting);
+// LLCurl::Easy* easy = allocEasy();
+// if (!easy)
+// {
+// return false;
+// }
+// easy->prepRequest(url, headers, responder, time_out);
+//
+// easy->getInput().write(data.data(), data.size());
+// S32 bytes = easy->getInput().str().length();
+//
+// easy->setopt(CURLOPT_POST, 1);
+// easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
+// easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
+//
+// easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
+// easy->setHeaders();
+//
+// LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
+// bool res = addEasy(easy);
+// return res;
+// }
+//
+// // Note: call once per frame
+// S32 LLCurlRequest::process()
+// {
+// S32 res = 0;
+//
+// mProcessing = TRUE;
+// for (curlmulti_set_t::iterator iter = mMultiSet.begin();
+// iter != mMultiSet.end(); )
+// {
+// curlmulti_set_t::iterator curiter = iter++;
+// LLCurl::Multi* multi = *curiter;
+//
+// if(!multi->isValid())
+// {
+// if(multi == mActiveMulti)
+// {
+// mActiveMulti = NULL ;
+// mActiveRequestCount = 0 ;
+// }
+// mMultiSet.erase(curiter) ;
+// LLCurl::getCurlThread()->killMulti(multi) ;
+// continue ;
+// }
+//
+// S32 tres = multi->process();
+// res += tres;
+// if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
+// {
+// mMultiSet.erase(curiter);
+// LLCurl::getCurlThread()->killMulti(multi);
+// }
+// }
+// mProcessing = FALSE;
+// return res;
+// }
+//
+// S32 LLCurlRequest::getQueued()
+// {
+// S32 queued = 0;
+// for (curlmulti_set_t::iterator iter = mMultiSet.begin();
+// iter != mMultiSet.end(); )
+// {
+// curlmulti_set_t::iterator curiter = iter++;
+// LLCurl::Multi* multi = *curiter;
+//
+// if(!multi->isValid())
+// {
+// if(multi == mActiveMulti)
+// {
+// mActiveMulti = NULL ;
+// mActiveRequestCount = 0 ;
+// }
+// LLCurl::getCurlThread()->killMulti(multi);
+// mMultiSet.erase(curiter) ;
+// continue ;
+// }
+//
+// queued += multi->mQueued;
+// if (multi->getState() != LLCurl::Multi::STATE_READY)
+// {
+// ++queued;
+// }
+// }
+// return queued;
+// }
+
+// LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) :
+// LLCurlRequest(),
+// mConcurrency(concurrency),
+// mInQueue(0),
+// mMutex(NULL),
+// mHandleCounter(1),
+// mTotalIssuedRequests(0),
+// mTotalReceivedBits(0)
+// {
+// mGlobalTimer.reset();
+// }
+//
+// LLCurlTextureRequest::~LLCurlTextureRequest()
+// {
+// mRequestMap.clear();
+//
+// for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
+// {
+// delete *iter;
+// }
+// mCachedRequests.clear();
+// }
+//
+// //return 0: success
+// // > 0: cached handle
+// U32 LLCurlTextureRequest::getByteRange(const std::string& url,
+// const headers_t& headers,
+// S32 offset, S32 length, U32 pri,
+// LLCurl::ResponderPtr responder, F32 delay_time)
+// {
+// U32 ret_val = 0;
+// bool success = false;
+//
+// if(mInQueue < mConcurrency && delay_time < 0.f)
+// {
+// success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// if(success)
+// {
+// mInQueue++;
+// mTotalIssuedRequests++;
+// }
+// else
+// {
+// request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
+// if(delay_time > 0.f)
+// {
+// request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
+// }
+//
+// mCachedRequests.insert(request);
+// mRequestMap[mHandleCounter] = request;
+// ret_val = mHandleCounter;
+// mHandleCounter++;
+//
+// if(!mHandleCounter)
+// {
+// mHandleCounter = 1;
+// }
+// }
+//
+// return ret_val;
+// }
+//
+// void LLCurlTextureRequest::completeRequest(S32 received_bytes)
+// {
+// LLMutexLock lock(&mMutex);
+//
+// llassert_always(mInQueue > 0);
+//
+// mInQueue--;
+// mTotalReceivedBits += received_bytes * 8;
+// }
+//
+// void LLCurlTextureRequest::nextRequests()
+// {
+// if(mCachedRequests.empty() || mInQueue >= mConcurrency)
+// {
+// return;
+// }
+//
+// F32 cur_time = mGlobalTimer.getElapsedTimeF32();
+//
+// req_queue_t::iterator iter;
+// {
+// LLMutexLock lock(&mMutex);
+// iter = mCachedRequests.begin();
+// }
+// while(1)
+// {
+// request_t* request = *iter;
+// if(request->mStartTime < cur_time)
+// {
+// if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
+// {
+// break;
+// }
+//
+// LLMutexLock lock(&mMutex);
+// ++iter;
+// mInQueue++;
+// mTotalIssuedRequests++;
+// mCachedRequests.erase(request);
+// mRequestMap.erase(request->mHandle);
+// delete request;
+//
+// if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+// {
+// break;
+// }
+// }
+// else
+// {
+// LLMutexLock lock(&mMutex);
+// ++iter;
+// if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+// {
+// break;
+// }
+// }
+// }
+//
+// return;
+// }
+//
+// void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
+// {
+// if(!handle)
+// {
+// return;
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+// if(iter != mRequestMap.end())
+// {
+// request_t* req = iter->second;
+//
+// if(req->mPriority != pri)
+// {
+// mCachedRequests.erase(req);
+// req->mPriority = pri;
+// mCachedRequests.insert(req);
+// }
+// }
+// }
+//
+// void LLCurlTextureRequest::removeRequest(U32 handle)
+// {
+// if(!handle)
+// {
+// return;
+// }
+//
+// LLMutexLock lock(&mMutex);
+//
+// std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+// if(iter != mRequestMap.end())
+// {
+// request_t* req = iter->second;
+// mRequestMap.erase(iter);
+// mCachedRequests.erase(req);
+// delete req;
+// }
+// }
+//
+// bool LLCurlTextureRequest::isWaiting(U32 handle)
+// {
+// if(!handle)
+// {
+// return false;
+// }
+//
+// LLMutexLock lock(&mMutex);
+// return mRequestMap.find(handle) != mRequestMap.end();
+// }
+//
+// U32 LLCurlTextureRequest::getTotalReceivedBits()
+// {
+// LLMutexLock lock(&mMutex);
+//
+// U32 bits = mTotalReceivedBits;
+// mTotalReceivedBits = 0;
+// return bits;
+// }
+//
+// U32 LLCurlTextureRequest::getTotalIssuedRequests()
+// {
+// LLMutexLock lock(&mMutex);
+// return mTotalIssuedRequests;
+// }
+//
+// S32 LLCurlTextureRequest::getNumRequests()
+// {
+// LLMutexLock lock(&mMutex);
+// return mInQueue;
+// }
////////////////////////////////////////////////////////////////////////////
// For generating one easy request
@@ -1988,10 +1990,10 @@ void LLCurlFF::check_easy_code(CURLcode code)
{
check_curl_code(code);
}
-void LLCurlFF::check_multi_code(CURLMcode code)
-{
- check_curl_multi_code(code);
-}
+// void LLCurlFF::check_multi_code(CURLMcode code)
+// {
+// check_curl_multi_code(code);
+// }
// Static
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index 385d9fffa8..295e9c9fe5 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -309,6 +309,7 @@ private:
static void deleteAllFreeHandles();
};
+#if 1
class LLCurl::Multi
{
LOG_CLASS(Multi);
@@ -379,6 +380,7 @@ private:
LLFrameTimer mIdleTimer ;
F32 mIdleTimeOut;
};
+#endif
class LLCurlThread : public LLQueuedThread
{
@@ -417,7 +419,7 @@ private:
void cleanupMulti(LLCurl::Multi* multi) ;
} ;
-
+#if 0
class LLCurlRequest
{
public:
@@ -446,7 +448,9 @@ private:
S32 mActiveRequestCount;
BOOL mProcessing;
};
+#endif
+#if 0
//for texture fetch only
class LLCurlTextureRequest : public LLCurlRequest
{
@@ -511,6 +515,7 @@ private:
LLFrameTimer mGlobalTimer;
};
+#endif
class LLCurlEasyRequest
{
@@ -550,7 +555,7 @@ private:
namespace LLCurlFF
{
void check_easy_code(CURLcode code);
- void check_multi_code(CURLMcode code);
+ //void check_multi_code(CURLMcode code);
}
#endif // LL_LLCURL_H
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 200116337d..27c94b1182 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -38,6 +38,10 @@
#include "lluri.h"
#include "message.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+
#include <curl/curl.h>
@@ -214,6 +218,51 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal
LLHTTPClient::mCertVerifyCallback = callback;
}
+#if 0
+typedef std::shared_ptr<LLCore::HttpRequest> HttpRequestPtr_t;
+typedef std::unique_ptr<LLCore::HttpOptions> HttpOptionsPtr_t;
+typedef std::unique_ptr<Injector> InjectorPtr_t;
+
+static void request_(
+ const std::string& url,
+ EHTTPMethod method,
+ Injector* body_injector,
+ LLCurl::ResponderPtr responder,
+ const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
+ const LLSD& headers = LLSD(),
+ bool follow_redirects = true
+ )
+{
+ HttpRequestPtr_t httpReq = HttpRequestPtr_t(new LLCore::HttpRequest());
+
+ HttpOptionsPtr_t httpOpts = HttpOptionsPtr_t(new LLCore::HttpOptions());
+
+ httpOpts->setFollowRedirects(follow_redirects);
+ httpOpts->setRetries(12);
+ httpOpts->setUseRetryAfter(true);
+ // for the moment lets just truncate. 60 seconds vs 60.5 seconds
+ httpOpts->setTransferTimeout((unsigned int)timeout);
+
+ switch (method)
+ {
+ case HTTP_GET:
+ httpReq->requestGet(0, 0, url, httpOpts.get(), headers, handler);
+ break;
+ case HTTP_HEAD:
+ httpReq->requestHead(0, 0, url, httpOpts.get(), headers, handler);
+ break;
+ case HTTP_PUT:
+ httpReq->requestPut(0, 0, url, );
+ break;
+ case HTTP_POST:
+ httpReq->requestPost(0, 0, url, null, httpOpts.get(), headers, handler);
+ break;
+ }
+
+
+}
+#endif
+
static void request(
const std::string& url,
EHTTPMethod method,
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index b56a804f94..8c2a0ad9cf 100755
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -26,48 +26,48 @@
#include "llhttpclientadapter.h"
#include "llhttpclient.h"
-
-LLHTTPClientAdapter::~LLHTTPClientAdapter()
-{
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
- LLSD empty_pragma_header;
- // Pragma is required to stop curl adding "no-cache"
- // Space is required to stop llurlrequest from turning off proxying
- empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
- LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
-{
- LLSD empty_pragma_header = headers;
- if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
- {
- // as above
- empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
- }
- LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
-{
- LLHTTPClient::put(url, body, responder);
-}
-
-void LLHTTPClientAdapter::put(
- const std::string& url,
- const LLSD& body,
- LLCurl::ResponderPtr responder,
- const LLSD& headers)
-{
- LLHTTPClient::put(url, body, responder, headers);
-}
-
-void LLHTTPClientAdapter::del(
- const std::string& url,
- LLCurl::ResponderPtr responder)
-{
- LLHTTPClient::del(url, responder);
-}
+//
+// LLHTTPClientAdapter::~LLHTTPClientAdapter()
+// {
+// }
+//
+// void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
+// {
+// LLSD empty_pragma_header;
+// // Pragma is required to stop curl adding "no-cache"
+// // Space is required to stop llurlrequest from turning off proxying
+// empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
+// LLHTTPClient::get(url, responder, empty_pragma_header);
+// }
+//
+// void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
+// {
+// LLSD empty_pragma_header = headers;
+// if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
+// {
+// // as above
+// empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
+// }
+// LLHTTPClient::get(url, responder, empty_pragma_header);
+// }
+//
+// void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
+// {
+// LLHTTPClient::put(url, body, responder);
+// }
+//
+// void LLHTTPClientAdapter::put(
+// const std::string& url,
+// const LLSD& body,
+// LLCurl::ResponderPtr responder,
+// const LLSD& headers)
+// {
+// LLHTTPClient::put(url, body, responder, headers);
+// }
+//
+// void LLHTTPClientAdapter::del(
+// const std::string& url,
+// LLCurl::ResponderPtr responder)
+// {
+// LLHTTPClient::del(url, responder);
+// }
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 270282c66f..0067703895 100755
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -30,6 +30,7 @@
#include "llhttpclientinterface.h"
#include "llsingleton.h" // LLSingleton<>
+/*
class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLHTTPClientAdapter>
{
public:
@@ -46,6 +47,7 @@ public:
const std::string& url,
LLCurl::ResponderPtr responder);
};
+*/
#endif
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 12a3857a61..9c1c8e7c11 100755
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -32,14 +32,14 @@
#include <string>
-class LLHTTPClientInterface
-{
-public:
- virtual ~LLHTTPClientInterface() {}
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
- virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
- virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
-};
+// class LLHTTPClientInterface
+// {
+// public:
+// virtual ~LLHTTPClientInterface() {}
+// virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
+// virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
+// virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
+// };
#endif // LL_LLHTTPCLIENTINTERFACE_H
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
index c4e0333ca3..d097ecdff7 100755
--- a/indra/llmessage/llsdrpcclient.h
+++ b/indra/llmessage/llsdrpcclient.h
@@ -37,7 +37,9 @@
#include "llchainio.h"
#include "llfiltersd2xmlrpc.h"
#include "lliopipe.h"
-#include "llurlrequest.h"
+#if 0
+//#include "llurlrequest.h"
+#endif
/**
* @class LLSDRPCClientResponse
@@ -218,6 +220,7 @@ protected:
LLIOPipe::ptr_t mResponse;
};
+#if 0
/**
* @class LLSDRPCClientFactory
* @brief Basic implementation for making an SD RPC client factory
@@ -267,7 +270,9 @@ public:
protected:
std::string mURL;
};
+#endif
+#if 0
/**
* @class LLXMLSDRPCClientFactory
* @brief Basic implementation for making an XMLRPC to SD RPC client factory
@@ -319,5 +324,6 @@ public:
protected:
std::string mURL;
};
+#endif
#endif // LL_LLSDRPCCLIENT_H
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index f5f224b83e..dd39b9a959 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -31,6 +31,10 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+#include "llsecapi.h"
+#include <curl/curl.h>
// Here is where we begin to get our connection usage under control.
// This establishes llcorehttp policy classes that, among other
@@ -151,6 +155,15 @@ void LLAppCoreHttp::init()
<< LL_ENDL;
}
+ // Set up SSL Verification call back.
+ status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_SSL_VERIFY_CALLBACK,
+ LLCore::HttpRequest::GLOBAL_POLICY_ID,
+ sslVerify, NULL);
+ if (!status)
+ {
+ LL_WARNS("Init") << "Failed to set SSL Verification. Reason: " << status.toString() << LL_ENDL;
+ }
+
// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):
// 0 - None
// 1 - Basic start, stop simple transitions
@@ -457,6 +470,62 @@ void LLAppCoreHttp::refreshSettings(bool initial)
}
}
+LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
+ LLCore::HttpHandler const * const handler, void *appdata)
+{
+ X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
+ LLCore::HttpStatus result;
+ LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
+ LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
+ LLSD validation_params = LLSD::emptyMap();
+ LLURI uri(url);
+
+ validation_params[CERT_HOSTNAME] = uri.hostName();
+
+ // *TODO*: In the case of an exception while validating the cert, we need a way
+ // to pass the offending(?) cert back out. *Rider*
+
+ try
+ {
+ // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects
+ store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
+ }
+ catch (LLCertValidationTrustException &cert_exception)
+ {
+ // this exception is is handled differently than the general cert
+ // exceptions, as we allow the user to actually add the certificate
+ // for trust.
+ // therefore we pass back a different error code
+ // NOTE: We're currently 'wired' to pass around CURL error codes. This is
+ // somewhat clumsy, as we may run into errors that do not map directly to curl
+ // error codes. Should be refactored with login refactoring, perhaps.
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
+ result.setMessage(cert_exception.getMessage());
+ LLPointer<LLCertificate> cert = cert_exception.getCert();
+ cert->ref(); // adding an extra ref here
+ result.setErrorData(cert.get());
+ // We should probably have a more generic way of passing information
+ // back to the error handlers.
+ }
+ catch (LLCertException &cert_exception)
+ {
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
+ result.setMessage(cert_exception.getMessage());
+ LLPointer<LLCertificate> cert = cert_exception.getCert();
+ cert->ref(); // adding an extra ref here
+ result.setErrorData(cert.get());
+ }
+ catch (...)
+ {
+ // any other odd error, we just handle as a connect error.
+ result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
+ }
+
+ return result;
+}
+
+
+
void LLAppCoreHttp::onCompleted(LLCore::HttpHandle, LLCore::HttpResponse *)
{
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index 37d7a737e7..9616354093 100755
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -233,7 +233,9 @@ private:
bool mStopped;
HttpClass mHttpClasses[AP_COUNT];
bool mPipelined; // Global setting
- boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
+ boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
+
+ static LLCore::HttpStatus sslVerify(const std::string &uri, LLCore::HttpHandler const * const handler, void *appdata);
};
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 2d4ce6c883..530eb685fa 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -87,7 +87,7 @@ void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
F32 retry_header_time;
const LLCore::HttpHeaders *headers = response->getHeaders();
bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
- onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time);
+ onFailureCommon(response->getStatus().getType(), has_retry_header_time, retry_header_time);
}
void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index aa440c06a6..4f08057477 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2294,7 +2294,6 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
if (!caps_url.empty())
{
gPendingMetricsUploads++;
- LLCurlRequest::headers_t headers;
LLHTTPClient::post(caps_url,
msg,
new ViewerAppearanceChangeMetricsResponder(report_sequence,
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index c12c2cc24c..e4e63afa16 100755
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -35,6 +35,11 @@
#include "llxmlrpclistener.h"
#include "llcurl.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+#include "httpheaders.h"
+#include "bufferarray.h"
#include "llviewercontrol.h"
// Have to include these last to avoid queue redefinition!
@@ -155,55 +160,159 @@ XMLRPC_VALUE LLXMLRPCValue::getValue() const
}
+class LLXMLRPCTransaction::Handler : public LLCore::HttpHandler
+{
+public:
+ Handler(LLCore::HttpRequest::ptr_t &request, LLXMLRPCTransaction::Impl *impl);
+ virtual ~Handler();
+
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+ typedef std::unique_ptr<LLXMLRPCTransaction::Handler> ptr_t;
+
+private:
+
+ LLXMLRPCTransaction::Impl *mImpl;
+ LLCore::HttpRequest::ptr_t mRequest;
+};
+
class LLXMLRPCTransaction::Impl
{
public:
typedef LLXMLRPCTransaction::EStatus EStatus;
- LLCurlEasyRequest* mCurlRequest;
+ LLCore::HttpRequest::ptr_t mHttpRequest;
+
+
+ EStatus mStatus;
+ CURLcode mCurlCode;
+ std::string mStatusMessage;
+ std::string mStatusURI;
+ LLCore::HttpResponse::TransferStats::ptr_t mTransferStats;
+ Handler::ptr_t mHandler;
+ LLCore::HttpHandle mPostH;
- EStatus mStatus;
- CURLcode mCurlCode;
- std::string mStatusMessage;
- std::string mStatusURI;
- LLCurl::TransferInfo mTransferInfo;
-
std::string mURI;
- char* mRequestText;
- int mRequestTextSize;
-
+
std::string mProxyAddress;
std::string mResponseText;
XMLRPC_REQUEST mResponse;
std::string mCertStore;
LLPointer<LLCertificate> mErrorCert;
-
+
Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
Impl(const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip);
+ const std::string& method, LLXMLRPCValue params, bool useGzip);
~Impl();
-
+
bool process();
-
- void setStatus(EStatus code,
- const std::string& message = "", const std::string& uri = "");
- void setCurlStatus(CURLcode);
+
+ void setStatus(EStatus code, const std::string& message = "", const std::string& uri = "");
+ void setHttpStatus(const LLCore::HttpStatus &status);
private:
void init(XMLRPC_REQUEST request, bool useGzip);
- static int _sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
- static CURLcode _sslCtxFunction(CURL * curl, void *sslctx, void *param);
- static size_t curlDownloadCallback(
- char* data, size_t size, size_t nmemb, void* user_data);
};
+LLXMLRPCTransaction::Handler::Handler(LLCore::HttpRequest::ptr_t &request,
+ LLXMLRPCTransaction::Impl *impl) :
+ mImpl(impl),
+ mRequest(request)
+{
+}
+
+LLXMLRPCTransaction::Handler::~Handler()
+{
+}
+
+void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
+ LLCore::HttpResponse * response)
+{
+ LLCore::HttpStatus status = response->getStatus();
+
+ if (!status)
+ {
+ if ((status.toULong() != CURLE_SSL_PEER_CERTIFICATE) &&
+ (status.toULong() != CURLE_SSL_CACERT))
+ {
+ // if we have a curl error that's not already been handled
+ // (a non cert error), then generate the error message as
+ // appropriate
+ mImpl->setHttpStatus(status);
+ LLCertificate *errordata = static_cast<LLCertificate *>(status.getErrorData());
+
+ if (errordata)
+ {
+ mImpl->mErrorCert = LLPointer<LLCertificate>(errordata);
+ status.setErrorData(NULL);
+ errordata->unref();
+ }
+
+ LL_WARNS() << "LLXMLRPCTransaction error "
+ << status.toHex() << ": " << status.toString() << LL_ENDL;
+ LL_WARNS() << "LLXMLRPCTransaction request URI: "
+ << mImpl->mURI << LL_ENDL;
+ }
+
+ return;
+ }
+
+ mImpl->setStatus(LLXMLRPCTransaction::StatusComplete);
+ mImpl->mTransferStats = response->getTransferStats();
+
+ // the contents of a buffer array are potentially noncontiguous, so we
+ // will need to copy them into an contiguous block of memory for XMLRPC.
+ LLCore::BufferArray *body = response->getBody();
+ char * bodydata = new char[body->size()];
+
+ body->read(0, bodydata, body->size());
+
+ mImpl->mResponse = XMLRPC_REQUEST_FromXML(bodydata, body->size(), 0);
+
+ delete[] bodydata;
+
+ bool hasError = false;
+ bool hasFault = false;
+ int faultCode = 0;
+ std::string faultString;
+
+ LLXMLRPCValue error(XMLRPC_RequestGetError(mImpl->mResponse));
+ if (error.isValid())
+ {
+ hasError = true;
+ faultCode = error["faultCode"].asInt();
+ faultString = error["faultString"].asString();
+ }
+ else if (XMLRPC_ResponseIsFault(mImpl->mResponse))
+ {
+ hasFault = true;
+ faultCode = XMLRPC_GetResponseFaultCode(mImpl->mResponse);
+ faultString = XMLRPC_GetResponseFaultString(mImpl->mResponse);
+ }
+
+ if (hasError || hasFault)
+ {
+ mImpl->setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
+
+ LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
+ << (hasError ? "error " : "fault ")
+ << faultCode << ": "
+ << faultString << LL_ENDL;
+ LL_WARNS() << "LLXMLRPCTransaction request URI: "
+ << mImpl->mURI << LL_ENDL;
+ }
+
+}
+
+//=========================================================================
+
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
XMLRPC_REQUEST request, bool useGzip)
- : mCurlRequest(0),
+ : mHttpRequest(0),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
- mRequestText(0),
+// mRequestText(0),
mResponse(0)
{
init(request, useGzip);
@@ -212,10 +321,10 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
const std::string& method, LLXMLRPCValue params, bool useGzip)
- : mCurlRequest(0),
+ : mHttpRequest(0),
mStatus(LLXMLRPCTransaction::StatusNotStarted),
mURI(uri),
- mRequestText(0),
+// mRequestText(0),
mResponse(0)
{
XMLRPC_REQUEST request = XMLRPC_RequestNew();
@@ -231,127 +340,53 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
XMLRPC_RequestFree(request, 1);
}
-// _sslCertVerifyCallback
-// callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-int LLXMLRPCTransaction::Impl::_sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
+void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
{
- LLXMLRPCTransaction::Impl *transaction = (LLXMLRPCTransaction::Impl *)param;
- LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(transaction->mCertStore);
- LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
- LLSD validation_params = LLSD::emptyMap();
- LLURI uri(transaction->mURI);
- validation_params[CERT_HOSTNAME] = uri.hostName();
- try
- {
- // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects
- store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
- }
- catch (LLCertValidationTrustException& cert_exception)
- {
- // this exception is is handled differently than the general cert
- // exceptions, as we allow the user to actually add the certificate
- // for trust.
- // therefore we pass back a different error code
- // NOTE: We're currently 'wired' to pass around CURL error codes. This is
- // somewhat clumsy, as we may run into errors that do not map directly to curl
- // error codes. Should be refactored with login refactoring, perhaps.
- transaction->mCurlCode = CURLE_SSL_CACERT;
- // set the status directly. set curl status generates error messages and we want
- // to use the fixed ones from the exceptions
- transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
- // We should probably have a more generic way of passing information
- // back to the error handlers.
- transaction->mErrorCert = cert_exception.getCert();
- return 0;
- }
- catch (LLCertException& cert_exception)
- {
- transaction->mCurlCode = CURLE_SSL_PEER_CERTIFICATE;
- // set the status directly. set curl status generates error messages and we want
- // to use the fixed ones from the exceptions
- transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
- transaction->mErrorCert = cert_exception.getCert();
- return 0;
- }
- catch (...)
- {
- // any other odd error, we just handle as a connect error.
- transaction->mCurlCode = CURLE_SSL_CONNECT_ERROR;
- transaction->setCurlStatus(CURLE_SSL_CONNECT_ERROR);
- return 0;
- }
- return 1;
-}
+ LLCore::HttpOptions::ptr_t httpOpts;
+ LLCore::HttpHeaders::ptr_t httpHeaders;
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validate(<, <#const & xs#>, <#T * #>, <#long #>)tion
-// based on SECAPI
-
-CURLcode LLXMLRPCTransaction::Impl::_sslCtxFunction(CURL * curl, void *sslctx, void *param)
-{
- 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, param);
- // the calls are void
- return CURLE_OK;
-
-}
-void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
-{
- if (!mCurlRequest)
+ if (!mHttpRequest)
{
- mCurlRequest = new LLCurlEasyRequest();
+ mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
}
- if(!mCurlRequest->isValid())
- {
- LL_WARNS() << "mCurlRequest is invalid." << LL_ENDL ;
- delete mCurlRequest ;
- mCurlRequest = NULL ;
- return ;
- }
+ // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+ httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false);
- mErrorCert = NULL;
+ httpOpts->setTimeout(40L);
-// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging
- mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
- mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
- BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
+ bool vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
mCertStore = gSavedSettings.getString("CertStore");
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
- // Be a little impatient about establishing connections.
- mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
- mCurlRequest->setSSLCtxCallback(_sslCtxFunction, (void *)this);
- /* Setting the DNS cache timeout to -1 disables it completely.
- This might help with bug #503 */
- mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
+ httpOpts->setSSLVerifyPeer( vefifySSLCert );
+ httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0);
- mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+ // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+ httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
- if (useGzip)
- {
- mCurlRequest->setoptString(CURLOPT_ENCODING, "");
- }
+ httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+
+ ///* Setting the DNS cache timeout to -1 disables it completely.
+ //This might help with bug #503 */
+ //httpOpts->setDNSCacheTimeout(-1);
+
+ LLCore::BufferArray::ptr_t body = LLCore::BufferArray::ptr_t(new LLCore::BufferArray(), false);
+
+ // TODO: See if there is a way to serialize to a preallocated buffer I'm
+ // not fond of the copy here.
+ int requestSize(0);
+ char * requestText = XMLRPC_REQUEST_ToXML(request, &requestSize);
+
+ body->append(requestText, requestSize);
- mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize);
- if (mRequestText)
- {
- mCurlRequest->setoptString(CURLOPT_POSTFIELDS, mRequestText);
- mCurlRequest->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize);
- }
- else
- {
- setStatus(StatusOtherError);
- }
+ XMLRPC_Free(requestText);
+
+ mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
+
+ mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+ mURI, body.get(), httpOpts.get(), httpHeaders.get(), mHandler.get());
- mCurlRequest->sendRequest(mURI);
}
@@ -362,27 +397,24 @@ LLXMLRPCTransaction::Impl::~Impl()
XMLRPC_RequestFree(mResponse, 1);
}
- if (mRequestText)
- {
- XMLRPC_Free(mRequestText);
- }
+ //if (mRequestText)
+ //{
+ // XMLRPC_Free(mRequestText);
+ //}
- delete mCurlRequest;
- mCurlRequest = NULL ;
+ //delete mCurlRequest;
+ //mCurlRequest = NULL ;
}
bool LLXMLRPCTransaction::Impl::process()
{
- if(!mCurlRequest || !mCurlRequest->isValid())
+ if (!mPostH || !mHttpRequest)
{
- LL_WARNS() << "transaction failed." << LL_ENDL ;
-
- delete mCurlRequest ;
- mCurlRequest = NULL ;
- return true ; //failed, quit.
+ LL_WARNS() << "transaction failed." << LL_ENDL;
+ return true; //failed, quit.
}
- switch(mStatus)
+ switch (mStatus)
{
case LLXMLRPCTransaction::StatusComplete:
case LLXMLRPCTransaction::StatusCURLError:
@@ -391,93 +423,25 @@ bool LLXMLRPCTransaction::Impl::process()
{
return true;
}
-
+
case LLXMLRPCTransaction::StatusNotStarted:
{
setStatus(LLXMLRPCTransaction::StatusStarted);
break;
}
-
+
default:
- {
- // continue onward
- }
- }
-
- if(!mCurlRequest->wait())
- {
- return false ;
+ break;
}
- while(1)
- {
- CURLcode result;
- bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
- if (newmsg)
- {
- if (result != CURLE_OK)
- {
- if ((result != CURLE_SSL_PEER_CERTIFICATE) &&
- (result != CURLE_SSL_CACERT))
- {
- // if we have a curl error that's not already been handled
- // (a non cert error), then generate the error message as
- // appropriate
- setCurlStatus(result);
-
- LL_WARNS() << "LLXMLRPCTransaction CURL error "
- << mCurlCode << ": " << mCurlRequest->getErrorString() << LL_ENDL;
- LL_WARNS() << "LLXMLRPCTransaction request URI: "
- << mURI << LL_ENDL;
- }
-
- return true;
- }
-
- setStatus(LLXMLRPCTransaction::StatusComplete);
-
- mResponse = XMLRPC_REQUEST_FromXML(
- mResponseText.data(), mResponseText.size(), NULL);
-
- bool hasError = false;
- bool hasFault = false;
- int faultCode = 0;
- std::string faultString;
+ LLCore::HttpStatus status = mHttpRequest->update(0);
- LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
- if (error.isValid())
- {
- hasError = true;
- faultCode = error["faultCode"].asInt();
- faultString = error["faultString"].asString();
- }
- else if (XMLRPC_ResponseIsFault(mResponse))
- {
- hasFault = true;
- faultCode = XMLRPC_GetResponseFaultCode(mResponse);
- faultString = XMLRPC_GetResponseFaultString(mResponse);
- }
-
- if (hasError || hasFault)
- {
- setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
-
- LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
- << (hasError ? "error " : "fault ")
- << faultCode << ": "
- << faultString << LL_ENDL;
- LL_WARNS() << "LLXMLRPCTransaction request URI: "
- << mURI << LL_ENDL;
- }
-
- return true;
- }
- else
- {
- break; // done
- }
+ status = mHttpRequest->getStatus();
+ if (!status)
+ {
+ return false;
}
-
+
return false;
}
@@ -516,64 +480,49 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
}
}
-void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code)
+void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
{
+ CURLcode code = static_cast<CURLcode>(status.toULong());
std::string message;
std::string uri = "http://secondlife.com/community/support.php";
-
+
switch (code)
{
- case CURLE_COULDNT_RESOLVE_HOST:
- message =
- "DNS could not resolve the host name.\n"
- "Please verify that you can connect to the www.secondlife.com\n"
- "web site. If you can, but continue to receive this error,\n"
- "please go to the support section and report this problem.";
- break;
-
- case CURLE_SSL_PEER_CERTIFICATE:
- message =
- "The login server couldn't verify itself via SSL.\n"
- "If you continue to receive this error, please go\n"
- "to the Support section of the SecondLife.com web site\n"
- "and report the problem.";
- break;
-
- case CURLE_SSL_CACERT:
- case CURLE_SSL_CONNECT_ERROR:
- message =
- "Often this means that your computer\'s clock is set incorrectly.\n"
- "Please go to Control Panels and make sure the time and date\n"
- "are set correctly.\n"
- "Also check that your network and firewall are set up correctly.\n"
- "If you continue to receive this error, please go\n"
- "to the Support section of the SecondLife.com web site\n"
- "and report the problem.";
- break;
-
- default:
- break;
+ case CURLE_COULDNT_RESOLVE_HOST:
+ message =
+ "DNS could not resolve the host name.\n"
+ "Please verify that you can connect to the www.secondlife.com\n"
+ "web site. If you can, but continue to receive this error,\n"
+ "please go to the support section and report this problem.";
+ break;
+
+ case CURLE_SSL_PEER_CERTIFICATE:
+ message =
+ "The login server couldn't verify itself via SSL.\n"
+ "If you continue to receive this error, please go\n"
+ "to the Support section of the SecondLife.com web site\n"
+ "and report the problem.";
+ break;
+
+ case CURLE_SSL_CACERT:
+ case CURLE_SSL_CONNECT_ERROR:
+ message =
+ "Often this means that your computer\'s clock is set incorrectly.\n"
+ "Please go to Control Panels and make sure the time and date\n"
+ "are set correctly.\n"
+ "Also check that your network and firewall are set up correctly.\n"
+ "If you continue to receive this error, please go\n"
+ "to the Support section of the SecondLife.com web site\n"
+ "and report the problem.";
+ break;
+
+ default:
+ break;
}
-
+
mCurlCode = code;
setStatus(StatusCURLError, message, uri);
-}
-
-size_t LLXMLRPCTransaction::Impl::curlDownloadCallback(
- char* data, size_t size, size_t nmemb, void* user_data)
-{
- Impl& impl(*(Impl*)user_data);
-
- size_t n = size * nmemb;
- impl.mResponseText.append(data, n);
-
- if (impl.mStatus == LLXMLRPCTransaction::StatusStarted)
- {
- impl.setStatus(LLXMLRPCTransaction::StatusDownloading);
- }
-
- return n;
}
@@ -645,11 +594,11 @@ F64 LLXMLRPCTransaction::transferRate()
return 0.0L;
}
- double rate_bits_per_sec = impl.mTransferInfo.mSpeedDownload * 8.0;
+ double rate_bits_per_sec = impl.mTransferStats->mSpeedDownload * 8.0;
LL_INFOS("AppInit") << "Buffer size: " << impl.mResponseText.size() << " B" << LL_ENDL;
- LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferInfo.mSizeDownload << " B" << LL_ENDL;
- LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferInfo.mTotalTime << " s" << LL_ENDL;
+ LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferStats->mSizeDownload << " B" << LL_ENDL;
+ LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferStats->mTotalTime << " s" << LL_ENDL;
LL_INFOS("AppInit") << "Transfer rate: " << rate_bits_per_sec / 1000.0 << " Kb/s" << LL_ENDL;
return rate_bits_per_sec;
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index f2589c7f41..3a1c9c82b7 100755
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -81,7 +81,7 @@ private:
class LLXMLRPCTransaction
- // an asynchronous request and respones via XML-RPC
+ // an asynchronous request and responses via XML-RPC
{
public:
LLXMLRPCTransaction(const std::string& uri,
@@ -127,7 +127,9 @@ public:
// only valid if StsatusComplete, otherwise 0.0
private:
+ class Handler;
class Impl;
+
Impl& impl;
};