diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2017-10-24 11:22:49 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2017-10-24 11:22:49 -0400 | 
| commit | 96ac49c3e2c6f5253938d4fbcae722543f00aecb (patch) | |
| tree | 7caf590933840d0685b1442181f36989cfbd70b0 /indra/llcorehttp | |
| parent | 9c5becd67d7e6fe5f696dcae8690dd562b7b0449 (diff) | |
| parent | 7d63a3fa5f4aa0b7529a1404fb43e9480e9f0cdf (diff) | |
MAINT-7081: Merge from lindenlab/viewer64.
Diffstat (limited to 'indra/llcorehttp')
| -rw-r--r-- | indra/llcorehttp/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | indra/llcorehttp/_httplibcurl.cpp | 33 | ||||
| -rw-r--r-- | indra/llcorehttp/_httpoprequest.cpp | 153 | 
3 files changed, 80 insertions, 110 deletions
| diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 435fb09aa4..40ec836f12 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -6,6 +6,7 @@ include(00-Common)  include(GoogleMock)  include(CURL)  include(OpenSSL) +include(NGHTTP2)  include(ZLIB)  include(LLCoreHttp)  include(LLAddBuildTest) @@ -94,6 +95,7 @@ target_link_libraries(    ${CURL_LIBRARIES}    ${OPENSSL_LIBRARIES}    ${CRYPTO_LIBRARIES} +  ${NGHTTP2_LIBRARIES}    ${BOOST_THREAD_LIBRARY}    ${BOOST_SYSTEM_LIBRARY}    ) @@ -132,6 +134,7 @@ if (LL_TESTS)        ${CURL_LIBRARIES}        ${OPENSSL_LIBRARIES}        ${CRYPTO_LIBRARIES} +      ${NGHTTP2_LIBRARIES}        ${BOOST_THREAD_LIBRARY}        ${BOOST_SYSTEM_LIBRARY}        ) @@ -202,6 +205,7 @@ endif (DARWIN)        ${CURL_LIBRARIES}        ${OPENSSL_LIBRARIES}        ${CRYPTO_LIBRARIES} +      ${NGHTTP2_LIBRARIES}        ${BOOST_THREAD_LIBRARY}        ${BOOST_SYSTEM_LIBRARY}        ) diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp index c25e01a318..abd304f6a5 100644 --- a/indra/llcorehttp/_httplibcurl.cpp +++ b/indra/llcorehttp/_httplibcurl.cpp @@ -40,6 +40,15 @@ namespace  void check_curl_multi_code(CURLMcode code);  void check_curl_multi_code(CURLMcode 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_multi_setopt(CURLM* handle, CURLMoption option, ARG argument) +{ +    CURLMcode code = curl_multi_setopt(handle, option, argument); +    check_curl_multi_code(code, option); +} +  static const char * const LOG_CORE("CoreHttp");  } // end anonymous namespace @@ -461,46 +470,38 @@ void HttpLibcurl::policyUpdated(int policy_class)  		HttpPolicyClass & options(policy.getClassOptions(policy_class));  		CURLM * multi_handle(mMultiHandles[policy_class]); -		CURLMcode code;  		// Enable policy if stalled  		policy.stallPolicy(policy_class, false);  		mDirtyPolicy[policy_class] = false; -		 +  		if (options.mPipelining > 1)  		{  			// We'll try to do pipelining on this multihandle -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_PIPELINING,  									 1L); -			check_curl_multi_code(code, CURLMOPT_PIPELINING); -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_MAX_PIPELINE_LENGTH,  									 long(options.mPipelining)); -			check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH); -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_MAX_HOST_CONNECTIONS,  									 long(options.mPerHostConnectionLimit)); -			check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_MAX_TOTAL_CONNECTIONS,  									 long(options.mConnectionLimit)); -			check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);  		}  		else  		{ -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_PIPELINING,  									 0L); -			check_curl_multi_code(code, CURLMOPT_PIPELINING); -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_MAX_HOST_CONNECTIONS,  									 0L); -			check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS); -			code = curl_multi_setopt(multi_handle, +			check_curl_multi_setopt(multi_handle,  									 CURLMOPT_MAX_TOTAL_CONNECTIONS,  									 long(options.mConnectionLimit)); -			check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);  		}  	}  	else if (! mDirtyPolicy[policy_class]) diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 721147ffb0..1ef7730c8e 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -108,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 @@ -456,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; @@ -496,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;  	} @@ -552,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, @@ -569,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)  	{ @@ -593,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: @@ -685,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... @@ -767,6 +734,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  		//  		// xfer_timeout *= cpolicy.mPipelining;  		xfer_timeout *= 2L; + +		// Also try requesting HTTP/2. +		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) @@ -774,10 +744,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) @@ -785,15 +753,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) | 
