diff options
Diffstat (limited to 'indra/llcorehttp/_httpoprequest.cpp')
-rw-r--r-- | indra/llcorehttp/_httpoprequest.cpp | 184 |
1 files changed, 89 insertions, 95 deletions
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index fceed8524b..cc49a2af80 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -47,6 +47,8 @@ #include "llhttpconstants.h" #include "llproxy.h" +#include "httpstats.h" + // *DEBUG: "[curl:bugs] #1420" problem and testing. // // A pipelining problem, https://sourceforge.net/p/curl/bugs/1420/, @@ -106,6 +108,15 @@ void os_strlower(char * str); // Error testing and reporting for libcurl status codes void check_curl_easy_code(CURLcode code, int curl_setopt_option); +// This is a template because different 'option' values require different +// types for 'ARG'. Just pass them through unchanged (by value). +template <typename ARG> +void check_curl_easy_setopt(CURL* handle, CURLoption option, ARG argument) +{ + CURLcode code = curl_easy_setopt(handle, option, argument); + check_curl_easy_code(code, option); +} + static const char * const LOG_CORE("CoreHttp"); } // end anonymous namespace @@ -247,6 +258,8 @@ void HttpOpRequest::visitNotifier(HttpRequest * request) response->setHeaders(mReplyHeaders); response->setRequestURL(mReqURL); + response->setRequestMethod(methodToString(mReqMethod)); + if (mReplyOffset || mReplyLength) { // Got an explicit offset/length in response @@ -452,8 +465,6 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, // *TODO: Move this to _httplibcurl where it belongs. HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { - CURLcode code; - // Scrub transport and result data for retried op case mCurlActive = false; mCurlHandle = NULL; @@ -492,45 +503,28 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - check_curl_easy_code(code, CURLOPT_IPRESOLVE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); - check_curl_easy_code(code, CURLOPT_NOSIGNAL); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); - check_curl_easy_code(code, CURLOPT_NOPROGRESS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); - check_curl_easy_code(code, CURLOPT_URL); - code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle()); - check_curl_easy_code(code, CURLOPT_PRIVATE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - check_curl_easy_code(code, CURLOPT_ENCODING); - - code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1); - check_curl_easy_code(code, CURLOPT_AUTOREFERER); - code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); - check_curl_easy_code(code, CURLOPT_MAXREDIRS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback); - check_curl_easy_code(code, CURLOPT_WRITEFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_WRITEDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback); - check_curl_easy_code(code, CURLOPT_READFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_READDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback); - check_curl_easy_code(code, CURLOPT_SEEKFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle()); - check_curl_easy_code(code, CURLOPT_SEEKDATA); - - code = curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, ""); - check_curl_easy_code(code, CURLOPT_COOKIEFILE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); + + check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); + check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle()); + + check_curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, ""); if (gpolicy.mSslCtxCallback) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback); - check_curl_easy_code(code, CURLOPT_SSL_CTX_FUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle()); - check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle()); mCallbackSSLVerify = gpolicy.mSslCtxCallback; } @@ -548,16 +542,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) dnsCacheTimeout = mReqOptions->getDNSCacheTimeout(); nobody = mReqOptions->getHeadersOnly() ? 1L : 0L; } - code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect); - check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION); + check_curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect); - 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, sslHostV); - check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV); + check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV); - code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody); - check_curl_easy_code(code, CURLOPT_NOBODY); + check_curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody); // The Linksys WRT54G V5 router has an issue with frequent // DNS lookups from LAN machines. If they happen too often, @@ -565,8 +555,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // 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); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout); if (gpolicy.mUseLLProxy) { @@ -589,81 +578,66 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) { // *TODO: This is fine for now but get fuller socks5/ // authentication thing going later.... - code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str()); - check_curl_easy_code(code, CURLOPT_PROXY); - code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - check_curl_easy_code(code, CURLOPT_PROXYTYPE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str()); + check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); } if (gpolicy.mCAPath.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str()); - check_curl_easy_code(code, CURLOPT_CAPATH); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str()); } if (gpolicy.mCAFile.size()) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str()); - check_curl_easy_code(code, CURLOPT_CAINFO); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str()); } switch (mReqMethod) { case HOR_GET: if (nobody == 0) - code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1); - check_curl_easy_code(code, CURLOPT_HTTPGET); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1); break; case HOR_POST: { - code = curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1); - check_curl_easy_code(code, CURLOPT_POST); - code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - check_curl_easy_code(code, CURLOPT_ENCODING); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); long data_size(0); if (mReqBody) { data_size = mReqBody->size(); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL)); - check_curl_easy_code(code, CURLOPT_POSTFIELDS); - code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size); - check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL)); + check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size); mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:"); } break; case HOR_PATCH: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH"); // fall through. The rest is the same as PUT case HOR_PUT: { - code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1); - check_curl_easy_code(code, CURLOPT_UPLOAD); + check_curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1); long data_size(0); if (mReqBody) { data_size = mReqBody->size(); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size); - check_curl_easy_code(code, CURLOPT_INFILESIZE); + check_curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size); mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:"); } break; case HOR_DELETE: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE"); break; case HOR_COPY: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY"); break; case HOR_MOVE: - code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE"); - check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE"); break; default: @@ -681,12 +655,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Tracing if (mTracing >= HTTP_TRACE_CURL_HEADERS) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1); - check_curl_easy_code(code, CURLOPT_VERBOSE); - code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this); - check_curl_easy_code(code, CURLOPT_DEBUGDATA); - code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback); - check_curl_easy_code(code, CURLOPT_DEBUGFUNCTION); + check_curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this); + check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback); } // There's a CURLOPT for this now... @@ -763,6 +734,13 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // // xfer_timeout *= cpolicy.mPipelining; xfer_timeout *= 2L; + + // Also try requesting HTTP/2. +/******************************/ + // but for test purposes, only if overriding VIEWERASSET + if (getenv("VIEWERASSET")) +/******************************/ + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); } // *DEBUG: Enable following override for timeout handling and "[curl:bugs] #1420" tests //if (cpolicy.mPipelining) @@ -770,10 +748,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // xfer_timeout = 1L; // timeout = 1L; //} - code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout); - check_curl_easy_code(code, CURLOPT_TIMEOUT); - code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout); - check_curl_easy_code(code, CURLOPT_CONNECTTIMEOUT); + check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout); + check_curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout); // Request headers if (mReqHeaders) @@ -781,15 +757,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Caller's headers last to override mCurlHeaders = append_headers_to_slist(mReqHeaders, mCurlHeaders); } - code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders); - check_curl_easy_code(code, CURLOPT_HTTPHEADER); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders); if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_USE_RETRY_AFTER)) { - code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback); - check_curl_easy_code(code, CURLOPT_HEADERFUNCTION); - code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this); - check_curl_easy_code(code, CURLOPT_HEADERDATA); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback); + check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this); } if (status) @@ -810,6 +783,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void } const size_t req_size(size * nmemb); const size_t write_size(op->mReplyBody->append(static_cast<char *>(data), req_size)); + HTTPStats::instance().recordDataDown(write_size); return write_size; } @@ -838,7 +812,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos)); const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size)); - op->mCurlBodyPos += read_size; + HTTPStats::instance().recordDataUp(read_size); + op->mCurlBodyPos += read_size; return read_size; } @@ -1143,6 +1118,25 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe return 0; } +std::string HttpOpRequest::methodToString(const HttpOpRequest::EMethod &e) +{ + if (e == HOR_COPY) + return "COPY"; + else if (e == HOR_DELETE) + return "DELETE"; + else if (e == HOR_GET) + return "GET"; + else if (e == HOR_MOVE) + return "MOVE"; + else if (e == HOR_PATCH) + return "PATCH"; + else if (e == HOR_POST) + return "POST"; + else if (e == HOR_PUT) + return "PUT"; + + return "UNKNOWN"; +} } // end namespace LLCore |