summaryrefslogtreecommitdiff
path: root/indra/llmessage/llurlrequest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llurlrequest.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llmessage/llurlrequest.cpp224
1 files changed, 143 insertions, 81 deletions
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index cb9d1c3731..1294379eca 100644..100755
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -33,14 +33,14 @@
#include <openssl/x509_vfy.h>
#include <openssl/ssl.h>
#include "llcurl.h"
+#include "llfasttimer.h"
#include "llioutil.h"
-#include "llmemtype.h"
+#include "llproxy.h"
#include "llpumpio.h"
#include "llsd.h"
#include "llstring.h"
#include "apr_env.h"
#include "llapr.h"
-static const U32 HTTP_STATUS_PIPE_ERROR = 499;
/**
* String constants
@@ -48,11 +48,12 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
+// These are defined in llhttpnode.h/llhttpnode.cpp
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
-
-
/**
* class LLURLRequestDetail
*/
@@ -63,7 +64,7 @@ public:
~LLURLRequestDetail();
std::string mURL;
LLCurlEasyRequest* mCurlRequest;
- LLBufferArray* mResponseBuffer;
+ LLIOPipe::buffer_ptr_t mResponseBuffer;
LLChannelDescriptors mChannels;
U8* mLastRead;
U32 mBodyLimit;
@@ -74,22 +75,24 @@ public:
LLURLRequestDetail::LLURLRequestDetail() :
mCurlRequest(NULL),
- mResponseBuffer(NULL),
mLastRead(NULL),
mBodyLimit(0),
mByteAccumulator(0),
mIsBodyLimitSet(false),
mSSLVerifyCallback(NULL)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mCurlRequest = new LLCurlEasyRequest();
+
+ if(!mCurlRequest->isValid()) //failed.
+ {
+ delete mCurlRequest ;
+ mCurlRequest = NULL ;
+ }
}
LLURLRequestDetail::~LLURLRequestDetail()
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
delete mCurlRequest;
- mResponseBuffer = NULL;
mLastRead = NULL;
}
@@ -128,63 +131,52 @@ CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param)
* class LLURLRequest
*/
-// static
-std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
-{
- static const std::string VERBS[] =
- {
- "(invalid)",
- "HEAD",
- "GET",
- "PUT",
- "POST",
- "DELETE",
- "MOVE"
- };
- if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT))
- {
- return VERBS[0];
- }
- return VERBS[action];
-}
-LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
- mAction(action)
+LLURLRequest::LLURLRequest(EHTTPMethod action, bool follow_redirects /* = true */) :
+ mAction(action),
+ mFollowRedirects(follow_redirects)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
initialize();
}
LLURLRequest::LLURLRequest(
- LLURLRequest::ERequestAction action,
- const std::string& url) :
- mAction(action)
+ EHTTPMethod action,
+ const std::string& url,
+ bool follow_redirects /* = true */) :
+ mAction(action),
+ mFollowRedirects(follow_redirects)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
initialize();
setURL(url);
}
LLURLRequest::~LLURLRequest()
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
delete mDetail;
+ mDetail = NULL ;
}
void LLURLRequest::setURL(const std::string& url)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mDetail->mURL = url;
+ if (url.empty())
+ {
+ LL_WARNS() << "empty URL specified" << LL_ENDL;
+ }
}
-std::string LLURLRequest::getURL() const
+const std::string& LLURLRequest::getURL() const
{
return mDetail->mURL;
}
-void LLURLRequest::addHeader(const char* header)
+void LLURLRequest::addHeader(const std::string& header, const std::string& value /* = "" */)
+{
+ mDetail->mCurlRequest->slist_append(header, value);
+}
+
+void LLURLRequest::addHeaderRaw(const char* header)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mDetail->mCurlRequest->slist_append(header);
}
@@ -196,7 +188,6 @@ void LLURLRequest::setBodyLimit(U32 size)
void LLURLRequest::setCallback(LLURLRequestComplete* callback)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mCompletionCallback = callback;
mDetail->mCurlRequest->setHeaderCallback(&headerCallback, (void*)callback);
}
@@ -228,7 +219,7 @@ void LLURLRequest::useProxy(bool use_proxy)
}
- lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl;
+ LL_DEBUGS() << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL;
if (env_proxy && use_proxy)
{
@@ -250,18 +241,28 @@ void LLURLRequest::allowCookies()
mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");
}
+//virtual
+bool LLURLRequest::isValid()
+{
+ return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid();
+}
+
// virtual
LLIOPipe::EStatus LLURLRequest::handleError(
LLIOPipe::EStatus status,
LLPumpIO* pump)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
+ if(!isValid())
+ {
+ return STATUS_EXPIRED ;
+ }
+
if(mCompletionCallback && pump)
{
LLURLRequestComplete* complete = NULL;
complete = (LLURLRequestComplete*)mCompletionCallback.get();
complete->httpStatus(
- HTTP_STATUS_PIPE_ERROR,
+ HTTP_INTERNAL_ERROR,
LLIOPipe::lookupStatusString(status));
complete->responseStatus(status);
pump->respond(complete);
@@ -270,6 +271,12 @@ LLIOPipe::EStatus LLURLRequest::handleError(
return status;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_REQUEST("URL Request");
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
+static LLTrace::BlockTimerStatHandle FTM_URL_PERFORM("Perform");
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond");
+static LLTrace::BlockTimerStatHandle FTM_URL_ADJUST_TIMEOUT("Adjust Timeout");
+
// virtual
LLIOPipe::EStatus LLURLRequest::process_impl(
const LLChannelDescriptors& channels,
@@ -278,9 +285,9 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_REQUEST);
PUMP_DEBUG;
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
- //llinfos << "LLURLRequest::process_impl()" << llendl;
+ //LL_INFOS() << "LLURLRequest::process_impl()" << LL_ENDL;
if (!buffer) return STATUS_ERROR;
// we're still waiting or prcessing, check how many
@@ -288,6 +295,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
const S32 MIN_ACCUMULATION = 100000;
if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
{
+ LL_RECORD_BLOCK_TIME(FTM_URL_ADJUST_TIMEOUT);
// This is a pretty sloppy calculation, but this
// tries to make the gross assumption that if data
// is coming in at 56kb/s, then this transfer will
@@ -297,10 +305,10 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
const F32 TIMEOUT_ADJUSTMENT = 2.0f;
mDetail->mByteAccumulator = 0;
pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
- lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+ LL_DEBUGS() << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << LL_ENDL;
if (mState == STATE_INITIALIZED)
{
- llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+ LL_INFOS() << "LLURLRequest adjustTimeoutSeconds called during upload" << LL_ENDL;
}
}
@@ -319,7 +327,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
// *FIX: bit of a hack, but it should work. The configure and
// callback method expect this information to be ready.
- mDetail->mResponseBuffer = buffer.get();
+ mDetail->mResponseBuffer = buffer;
mDetail->mChannels = channels;
if(!configure())
{
@@ -335,21 +343,36 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
{
PUMP_DEBUG;
LLIOPipe::EStatus status = STATUS_BREAK;
- mDetail->mCurlRequest->perform();
- while(1)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_URL_PERFORM);
+ if(!mDetail->mCurlRequest->wait())
+ {
+ return status ;
+ }
+ }
+
+ bool keep_looping = true;
+ while(keep_looping)
{
CURLcode result;
- bool newmsg = mDetail->mCurlRequest->getResult(&result);
+
+ bool newmsg = false;
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_REQUEST_GET_RESULT);
+ newmsg = mDetail->mCurlRequest->getResult(&result);
+ }
+
if(!newmsg)
{
// keep processing
break;
}
+
mState = STATE_HAVE_RESPONSE;
context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
- lldebugs << this << "Setting context to " << context << llendl;
+ LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
switch(result)
{
case CURLE_OK:
@@ -370,22 +393,27 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
link.mChannels = LLBufferArray::makeChannelConsumer(
channels);
chain.push_back(link);
- pump->respond(chain, buffer, context);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_PUMP_RESPOND);
+ pump->respond(chain, buffer, context);
+ }
mCompletionCallback = NULL;
}
break;
case CURLE_FAILED_INIT:
case CURLE_COULDNT_CONNECT:
status = STATUS_NO_CONNECTION;
+ keep_looping = false;
break;
- default:
- llwarns << "URLRequest Error: " << result
+ default: // CURLE_URL_MALFORMAT
+ LL_WARNS() << "URLRequest Error: " << result
<< ", "
<< LLCurl::strerror(result)
<< ", "
<< (mDetail->mURL.empty() ? "<EMPTY URL>" : mDetail->mURL)
- << llendl;
+ << LL_ENDL;
status = STATUS_ERROR;
+ keep_looping = false;
break;
}
}
@@ -398,23 +426,28 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
eos = true;
context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
- lldebugs << this << "Setting context to " << context << llendl;
+ LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
return STATUS_DONE;
default:
PUMP_DEBUG;
context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
- lldebugs << this << "Setting context to " << context << llendl;
+ LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
return STATUS_ERROR;
}
}
void LLURLRequest::initialize()
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mState = STATE_INITIALIZED;
mDetail = new LLURLRequestDetail;
+
+ if(!isValid())
+ {
+ return ;
+ }
+
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
@@ -422,9 +455,11 @@ void LLURLRequest::initialize()
mResponseTransferedBytes = 0;
}
+static LLTrace::BlockTimerStatHandle FTM_URL_REQUEST_CONFIGURE("URL Configure");
bool LLURLRequest::configure()
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
+ LL_RECORD_BLOCK_TIME(FTM_URL_REQUEST_CONFIGURE);
+
bool rv = false;
S32 bytes = mDetail->mResponseBuffer->countAfter(
mDetail->mChannels.in(),
@@ -434,54 +469,83 @@ bool LLURLRequest::configure()
case HTTP_HEAD:
mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);
mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1);
- mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
+ if (mFollowRedirects)
+ {
+ mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
+ }
rv = true;
break;
case HTTP_GET:
mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1);
- mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
+ if (mFollowRedirects)
+ {
+ mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
+ }
+
+ // Set Accept-Encoding to allow response compression
+ mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
rv = true;
break;
case HTTP_PUT:
// Disable the expect http 1.1 extension. POST and PUT default
// to turning this on, and I am not too sure what it means.
- addHeader("Expect:");
+ addHeader(HTTP_OUT_HEADER_EXPECT);
mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
rv = true;
break;
+ case HTTP_PATCH:
+ // Disable the expect http 1.1 extension. POST and PUT default
+ // to turning this on, and I am not too sure what it means.
+ addHeader(HTTP_OUT_HEADER_EXPECT);
+
+ mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
+ mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
+ mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "PATCH");
+ rv = true;
+ break;
+
case HTTP_POST:
// Disable the expect http 1.1 extension. POST and PUT default
// to turning this on, and I am not too sure what it means.
- addHeader("Expect:");
+ addHeader(HTTP_OUT_HEADER_EXPECT);
// Disable the content type http header.
// *FIX: what should it be?
- addHeader("Content-Type:");
+ addHeader(HTTP_OUT_HEADER_CONTENT_TYPE);
// Set the handle for an http post
mDetail->mCurlRequest->setPost(NULL, bytes);
+
+ // Set Accept-Encoding to allow response compression
+ mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
rv = true;
break;
case HTTP_DELETE:
- // Set the handle for an http post
+ // Set the handle for an http delete
mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
rv = true;
break;
+ case HTTP_COPY:
+ // Set the handle for an http copy
+ mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "COPY");
+ rv = true;
+ break;
+
case HTTP_MOVE:
- // Set the handle for an http post
+ // Set the handle for an http move
mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
// *NOTE: should we check for the Destination header?
rv = true;
break;
default:
- llwarns << "Unhandled URLRequest action: " << mAction << llendl;
+ LL_WARNS() << "Unhandled URLRequest action: " << mAction << LL_ENDL;
break;
}
if(rv)
@@ -498,7 +562,6 @@ size_t LLURLRequest::downCallback(
size_t nmemb,
void* user)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
LLURLRequest* req = (LLURLRequest*)user;
if(STATE_WAITING_FOR_RESPONSE == req->mState)
{
@@ -534,7 +597,6 @@ size_t LLURLRequest::upCallback(
size_t nmemb,
void* user)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
LLURLRequest* req = (LLURLRequest*)user;
S32 bytes = llmin(
(S32)(size * nmemb),
@@ -589,7 +651,7 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
S32 status_code = atoi(status.c_str());
if (status_code > 0)
{
- complete->httpStatus((U32)status_code, reason);
+ complete->httpStatus(status_code, reason);
return header_len;
}
}
@@ -611,13 +673,14 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
LLStringUtil::trim(header);
if (!header.empty())
{
- llwarns << "Unable to parse header: " << header << llendl;
+ LL_WARNS() << "Unable to parse header: " << header << LL_ENDL;
}
}
return header_len;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_EXTRACTOR("URL Extractor");
/**
* LLContextURLExtractor
*/
@@ -629,8 +692,8 @@ LLIOPipe::EStatus LLContextURLExtractor::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_EXTRACTOR);
PUMP_DEBUG;
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
// The destination host is in the context.
if(context.isUndefined() || !mRequest)
{
@@ -658,13 +721,11 @@ LLIOPipe::EStatus LLContextURLExtractor::process_impl(
LLURLRequestComplete::LLURLRequestComplete() :
mRequestStatus(LLIOPipe::STATUS_ERROR)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
}
// virtual
LLURLRequestComplete::~LLURLRequestComplete()
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
}
//virtual
@@ -690,23 +751,23 @@ void LLURLRequestComplete::complete(const LLChannelDescriptors& channels,
void LLURLRequestComplete::response(const LLChannelDescriptors& channels,
const buffer_ptr_t& buffer)
{
- llwarns << "LLURLRequestComplete::response default implementation called"
- << llendl;
+ LL_WARNS() << "LLURLRequestComplete::response default implementation called"
+ << LL_ENDL;
}
//virtual
void LLURLRequestComplete::noResponse()
{
- llwarns << "LLURLRequestComplete::noResponse default implementation called"
- << llendl;
+ LL_WARNS() << "LLURLRequestComplete::noResponse default implementation called"
+ << LL_ENDL;
}
void LLURLRequestComplete::responseStatus(LLIOPipe::EStatus status)
{
- LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mRequestStatus = status;
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_COMPLETE("URL Complete");
// virtual
LLIOPipe::EStatus LLURLRequestComplete::process_impl(
const LLChannelDescriptors& channels,
@@ -715,6 +776,7 @@ LLIOPipe::EStatus LLURLRequestComplete::process_impl(
LLSD& context,
LLPumpIO* pump)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_COMPLETE);
PUMP_DEBUG;
complete(channels, buffer);
return STATUS_OK;