diff options
Diffstat (limited to 'indra/llmessage/llurlrequest.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/llmessage/llurlrequest.cpp | 224 |
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; |