diff --git a/include/wx/private/webrequest_curl.h b/include/wx/private/webrequest_curl.h index b0aa565584..d0e2f8a5d7 100644 --- a/include/wx/private/webrequest_curl.h +++ b/include/wx/private/webrequest_curl.h @@ -114,6 +114,7 @@ public: // Methods called from libcurl callbacks size_t CURLOnWrite(void *buffer, size_t size); size_t CURLOnHeader(const char* buffer, size_t size); + int CURLOnProgress(); private: wxWebRequestHeaderMap m_headers; @@ -149,6 +150,9 @@ public: void CancelRequest(wxWebRequestCURL* request); + static bool CurlRuntimeAtLeastVersion(unsigned int, unsigned int, + unsigned int); + private: static int TimerCallback(CURLM*, long, void*); static int SocketCallback(CURL*, curl_socket_t, int, void*, void*); @@ -165,6 +169,7 @@ private: CURLM* m_handle; static int ms_activeSessions; + static unsigned int ms_runtimeVersion; wxDECLARE_NO_COPY_CLASS(wxWebSessionCURL); }; diff --git a/src/common/webrequest_curl.cpp b/src/common/webrequest_curl.cpp index 30bcc269b4..d247e844af 100644 --- a/src/common/webrequest_curl.cpp +++ b/src/common/webrequest_curl.cpp @@ -44,12 +44,6 @@ (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) #endif -#if CURL_AT_LEAST_VERSION(7, 28, 0) - #define wxCURL_HAVE_MULTI_WAIT 1 -#else - #define wxCURL_HAVE_MULTI_WAIT 0 -#endif - // The new name was introduced in curl 7.21.6. #ifndef CURLOPT_ACCEPT_ENCODING #define CURLOPT_ACCEPT_ENCODING CURLOPT_ENCODING @@ -73,12 +67,53 @@ static size_t wxCURLHeader(char *buffer, size_t size, size_t nitems, void *userd return static_cast(userdata)->CURLOnHeader(buffer, size * nitems); } +int wxCURLXferInfo(void* clientp, curl_off_t WXUNUSED(dltotal), + curl_off_t WXUNUSED(dlnow), + curl_off_t WXUNUSED(ultotal), + curl_off_t WXUNUSED(ulnow)) +{ + wxCHECK_MSG( clientp, 0, "invalid curl progress callback data" ); + + wxWebResponseCURL* response = reinterpret_cast(clientp); + return response->CURLOnProgress(); +} + +int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal, + double ulnow) +{ + return wxCURLXferInfo(clientp, static_cast(dltotal), + static_cast(dlnow), + static_cast(ultotal), + static_cast(ulnow)); +} + wxWebResponseCURL::wxWebResponseCURL(wxWebRequestCURL& request) : wxWebResponseImpl(request) { curl_easy_setopt(GetHandle(), CURLOPT_WRITEDATA, static_cast(this)); curl_easy_setopt(GetHandle(), CURLOPT_HEADERDATA, static_cast(this)); + // Set the progress callback. + #if CURL_AT_LEAST_VERSION(7, 32, 0) + if ( wxWebSessionCURL::CurlRuntimeAtLeastVersion(7, 32, 0) ) + { + curl_easy_setopt(GetHandle(), CURLOPT_XFERINFOFUNCTION, + wxCURLXferInfo); + curl_easy_setopt(GetHandle(), CURLOPT_XFERINFODATA, + static_cast(this)); + } + else + #endif + { + curl_easy_setopt(GetHandle(), CURLOPT_PROGRESSFUNCTION, + wxCURLProgress); + curl_easy_setopt(GetHandle(), CURLOPT_PROGRESSDATA, + static_cast(this)); + } + + // Have curl call the progress callback. + curl_easy_setopt(GetHandle(), CURLOPT_NOPROGRESS, 0L); + Init(); } @@ -117,6 +152,11 @@ size_t wxWebResponseCURL::CURLOnHeader(const char * buffer, size_t size) return size; } +int wxWebResponseCURL::CURLOnProgress() +{ + return 0; +} + wxFileOffset wxWebResponseCURL::GetContentLength() const { #if CURL_AT_LEAST_VERSION(7, 55, 0) @@ -877,6 +917,7 @@ void SocketPoller::ThreadCheckSockets() // int wxWebSessionCURL::ms_activeSessions = 0; +unsigned int wxWebSessionCURL::ms_runtimeVersion = 0; wxWebSessionCURL::wxWebSessionCURL() : m_handle(NULL) @@ -885,7 +926,14 @@ wxWebSessionCURL::wxWebSessionCURL() : if ( ms_activeSessions == 0 ) { if ( curl_global_init(CURL_GLOBAL_ALL) ) + { wxLogError(_("libcurl could not be initialized")); + } + else + { + curl_version_info_data* data = curl_version_info(CURLVERSION_NOW); + ms_runtimeVersion = data->version_num; + } } ms_activeSessions++; @@ -970,6 +1018,13 @@ wxVersionInfo wxWebSessionCURL::GetLibraryVersionInfo() desc); } +bool wxWebSessionCURL::CurlRuntimeAtLeastVersion(unsigned int major, + unsigned int minor, + unsigned int patch) +{ + return (ms_runtimeVersion >= CURL_VERSION_BITS(major, minor, patch)); +} + // curl interacts with the wxWebSessionCURL class through 2 callback functions // 1) TimerCallback is called whenever curl wants us to start or stop a timer. // 2) SocketCallback is called when curl wants us to start monitoring a socket