diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index 2f90b8e6e..d22408491 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -717,8 +717,78 @@ void intrusive_ptr_release(ThreadSafeCurlEasyRequest* threadsafe_curl_easy_reque } } +CURLcode CurlEasyHandle::setopt(CURLoption option, long parameter) +{ + llassert((CURLOPTTYPE_LONG <= option && option < CURLOPTTYPE_LONG + 1000) || + (sizeof(curl_off_t) == sizeof(long) && + CURLOPTTYPE_OFF_T <= option && option < CURLOPTTYPE_OFF_T + 1000)); + llassert(!mActiveMultiHandle); + setErrorBuffer(); + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); +} + +// The standard requires that sizeof(long) < sizeof(long long), so it's safe to overload like this. +// We assume that one of them is 64 bit, the size of curl_off_t. +CURLcode CurlEasyHandle::setopt(CURLoption option, long long parameter) +{ + llassert(sizeof(curl_off_t) == sizeof(long long) && + CURLOPTTYPE_OFF_T <= option && option < CURLOPTTYPE_OFF_T + 1000); + llassert(!mActiveMultiHandle); + setErrorBuffer(); + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); +} + +CURLcode CurlEasyHandle::setopt(CURLoption option, void const* parameter) +{ + llassert(CURLOPTTYPE_OBJECTPOINT <= option && option < CURLOPTTYPE_OBJECTPOINT + 1000); + setErrorBuffer(); + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); +} + +#define DEFINE_FUNCTION_SETOPT1(function_type, opt1) \ + CURLcode CurlEasyHandle::setopt(CURLoption option, function_type parameter) \ + { \ + llassert(option == opt1); \ + setErrorBuffer(); \ + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); \ + } + +#define DEFINE_FUNCTION_SETOPT3(function_type, opt1, opt2, opt3) \ + CURLcode CurlEasyHandle::setopt(CURLoption option, function_type parameter) \ + { \ + llassert(option == opt1 || option == opt2 || option == opt3); \ + setErrorBuffer(); \ + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); \ + } + +#define DEFINE_FUNCTION_SETOPT4(function_type, opt1, opt2, opt3, opt4) \ + CURLcode CurlEasyHandle::setopt(CURLoption option, function_type parameter) \ + { \ + llassert(option == opt1 || option == opt2 || option == opt3 || option == opt4); \ + setErrorBuffer(); \ + return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); \ + } + +DEFINE_FUNCTION_SETOPT1(curl_debug_callback, CURLOPT_DEBUGFUNCTION) +DEFINE_FUNCTION_SETOPT4(curl_write_callback, CURLOPT_HEADERFUNCTION, CURLOPT_WRITEFUNCTION, CURLOPT_INTERLEAVEFUNCTION, CURLOPT_READFUNCTION) +//DEFINE_FUNCTION_SETOPT1(curl_read_callback, CURLOPT_READFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_ssl_ctx_callback, CURLOPT_SSL_CTX_FUNCTION) +DEFINE_FUNCTION_SETOPT3(curl_conv_callback, CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPT_CONV_FROM_UTF8_FUNCTION) +#if 0 // Not used by the viewer. +DEFINE_FUNCTION_SETOPT1(curl_progress_callback, CURLOPT_PROGRESSFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_seek_callback, CURLOPT_SEEKFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_ioctl_callback, CURLOPT_IOCTLFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_sockopt_callback, CURLOPT_SOCKOPTFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_opensocket_callback, CURLOPT_OPENSOCKETFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_closesocket_callback, CURLOPT_CLOSESOCKETFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_sshkeycallback, CURLOPT_SSH_KEYFUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_chunk_bgn_callback, CURLOPT_CHUNK_BGN_FUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_chunk_end_callback, CURLOPT_CHUNK_END_FUNCTION) +DEFINE_FUNCTION_SETOPT1(curl_fnmatch_callback, CURLOPT_FNMATCH_FUNCTION) +#endif + //----------------------------------------------------------------------------- -// CurlEasyReqest +// CurlEasyRequest void CurlEasyRequest::setoptString(CURLoption option, std::string const& value) { @@ -729,8 +799,8 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value) void CurlEasyRequest::setPost(char const* postdata, S32 size) { setopt(CURLOPT_POST, 1L); - setopt(CURLOPT_POSTFIELDS, static_cast(const_cast(postdata))); setopt(CURLOPT_POSTFIELDSIZE, size); + setopt(CURLOPT_POSTFIELDS, postdata); } ThreadSafeCurlEasyRequest* CurlEasyRequest::get_lockobj(void) diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index 14a8b0fa2..ead30e82e 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -59,6 +59,9 @@ void stopCurlThread(void); class ThreadSafeCurlEasyRequest; class ThreadSafeBufferedCurlEasyRequest; +#define DECLARE_SETOPT(param_type) \ + CURLcode setopt(CURLoption option, param_type parameter) + // This class wraps CURL*'s. // It guarantees that a pointer is cleaned up when no longer needed, as required by libcurl. class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEvents { @@ -75,8 +78,31 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven void reset(void) { llassert(!mActiveMultiHandle); curl_easy_reset(mEasyHandle); } // Set options for a curl easy handle. - template - CURLcode setopt(CURLoption option, BUILTIN parameter); + DECLARE_SETOPT(long); + DECLARE_SETOPT(long long); + DECLARE_SETOPT(void const*); + DECLARE_SETOPT(curl_debug_callback); + DECLARE_SETOPT(curl_write_callback); + //DECLARE_SETOPT(curl_read_callback); Same type as curl_write_callback + DECLARE_SETOPT(curl_ssl_ctx_callback); + DECLARE_SETOPT(curl_conv_callback); +#if 0 // Not used by the viewer. + DECLARE_SETOPT(curl_progress_callback); + DECLARE_SETOPT(curl_seek_callback); + DECLARE_SETOPT(curl_ioctl_callback); + DECLARE_SETOPT(curl_sockopt_callback); + DECLARE_SETOPT(curl_opensocket_callback); + DECLARE_SETOPT(curl_closesocket_callback); + DECLARE_SETOPT(curl_sshkeycallback); + DECLARE_SETOPT(curl_chunk_bgn_callback); + DECLARE_SETOPT(curl_chunk_end_callback); + DECLARE_SETOPT(curl_fnmatch_callback); +#endif +#if __LP64__ // sizeof(long) > sizeof(S32), see http://en.cppreference.com/w/cpp/language/types + // Automatically cast small int types to a long if they differ in size. + CURLcode setopt(CURLoption option, U32 parameter) { return setopt(option, (long)parameter); } + CURLcode setopt(CURLoption option, S32 parameter) { return setopt(option, (long)parameter); } +#endif // Clone a libcurl session handle using all the options previously set. //CurlEasyHandle(CurlEasyHandle const& orig); @@ -160,14 +186,6 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven static char* getTLErrorBuffer(void); }; -template -CURLcode CurlEasyHandle::setopt(CURLoption option, BUILTIN parameter) -{ - llassert(!mActiveMultiHandle); - setErrorBuffer(); - return check_easy_code(curl_easy_setopt(mEasyHandle, option, parameter)); -} - // CurlEasyRequest adds a slightly more powerful interface that can be used // to set the options on a curl easy handle. // @@ -397,16 +415,41 @@ class CurlMultiHandle : public boost::noncopyable { public: // Set options for a curl multi handle. - template - CURLMcode setopt(CURLMoption option, BUILTIN parameter); + CURLMcode setopt(CURLMoption option, long parameter); + CURLMcode setopt(CURLMoption option, curl_socket_callback parameter); + CURLMcode setopt(CURLMoption option, curl_multi_timer_callback parameter); + CURLMcode setopt(CURLMoption option, void* parameter); // Returns total number of existing CURLM* handles (excluding ones created outside this class). static U32 getTotalMultiHandles(void) { return sTotalMultiHandles; } }; -template -CURLMcode CurlMultiHandle::setopt(CURLMoption option, BUILTIN parameter) +// Overload the setopt methods in order to enforce the correct types (ie, convert an int to a long). + +// curl_multi_setopt may only be passed a long, +inline CURLMcode CurlMultiHandle::setopt(CURLMoption option, long parameter) { + llassert(option == CURLMOPT_MAXCONNECTS || option == CURLMOPT_PIPELINING); + return check_multi_code(curl_multi_setopt(mMultiHandle, option, parameter)); +} + +// ... or a function pointer, +inline CURLMcode CurlMultiHandle::setopt(CURLMoption option, curl_socket_callback parameter) +{ + llassert(option == CURLMOPT_SOCKETFUNCTION); + return check_multi_code(curl_multi_setopt(mMultiHandle, option, parameter)); +} + +inline CURLMcode CurlMultiHandle::setopt(CURLMoption option, curl_multi_timer_callback parameter) +{ + llassert(option == CURLMOPT_TIMERFUNCTION); + return check_multi_code(curl_multi_setopt(mMultiHandle, option, parameter)); +} + +// ... or an object pointer. +inline CURLMcode CurlMultiHandle::setopt(CURLMoption option, void* parameter) +{ + llassert(option == CURLMOPT_SOCKETDATA || option == CURLMOPT_TIMERDATA); return check_multi_code(curl_multi_setopt(mMultiHandle, option, parameter)); } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 7320ccb0e..9c58bc466 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -446,7 +446,7 @@ static LLSD blocking_request( std::string body_str; // * Set curl handle options - curlEasyRequest_w->setopt(CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function. + curlEasyRequest_w->setopt(CURLOPT_TIMEOUT, (long)timeout); // seconds, see warning at top of function. curlEasyRequest_w->setWriteCallback(&LLHTTPBuffer::curl_write, &http_buffer); // * Setup headers. diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 9d729b8da..b1bb2ee0f 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -263,7 +263,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) if (mRequestText) { Dout(dc::curl, "Writing " << mRequestTextSize << " bytes: \"" << libcwd::buf2str(mRequestText, mRequestTextSize) << "\".");; - curlEasyRequest_w->setopt(CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)mRequestTextSize); + curlEasyRequest_w->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize); curlEasyRequest_w->setoptString(CURLOPT_COPYPOSTFIELDS, mRequestText); } else diff --git a/indra/plugins/webkit/linux_volume_catcher.cpp b/indra/plugins/webkit/linux_volume_catcher.cpp index 0cb73ca1e..5298056fd 100644 --- a/indra/plugins/webkit/linux_volume_catcher.cpp +++ b/indra/plugins/webkit/linux_volume_catcher.cpp @@ -36,9 +36,10 @@ */ #include "linden_common.h" -# include +#include #include "volume_catcher.h" +#include "llaprpool.h" #ifndef LL_WINDOWS #include @@ -53,7 +54,6 @@ extern "C" { #include #include // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. -#include "llaprpool.h" #include "apr_dso.h" #ifdef LL_STANDALONE #include