Rewrite CURL-based wxWebRequest implementation using multi-socket
support for much better efficiency and reliability.

See https://github.com/wxWidgets/wxWidgets/pull/2193
This commit is contained in:
Vadim Zeitlin
2021-02-22 00:40:53 +01:00
4 changed files with 860 additions and 164 deletions

View File

@@ -187,6 +187,10 @@ protected:
void ReportDataReceived(size_t sizeReceived); void ReportDataReceived(size_t sizeReceived);
// This function can optionally be called to preallocate the read buffer,
// if the total amount of data to be downloaded is known in advance.
void PreAllocBuffer(size_t sizeNeeded);
private: private:
// Called by wxWebRequestImpl only. // Called by wxWebRequestImpl only.
friend class wxWebRequestImpl; friend class wxWebRequestImpl;

View File

@@ -16,12 +16,15 @@
#include "wx/thread.h" #include "wx/thread.h"
#include "wx/vector.h" #include "wx/vector.h"
#include "wx/timer.h"
#include "wx/hashmap.h"
#include "curl/curl.h" #include "curl/curl.h"
class wxWebRequestCURL; class wxWebRequestCURL;
class wxWebResponseCURL; class wxWebResponseCURL;
class wxWebSessionCURL; class wxWebSessionCURL;
class SocketPoller;
class wxWebAuthChallengeCURL : public wxWebAuthChallengeImpl class wxWebAuthChallengeCURL : public wxWebAuthChallengeImpl
{ {
@@ -112,10 +115,12 @@ public:
// Methods called from libcurl callbacks // Methods called from libcurl callbacks
size_t CURLOnWrite(void *buffer, size_t size); size_t CURLOnWrite(void *buffer, size_t size);
size_t CURLOnHeader(const char* buffer, size_t size); size_t CURLOnHeader(const char* buffer, size_t size);
int CURLOnProgress(curl_off_t);
private: private:
wxWebRequestHeaderMap m_headers; wxWebRequestHeaderMap m_headers;
wxString m_statusText; wxString m_statusText;
wxFileOffset m_knownDownloadSize;
CURL* GetHandle() const CURL* GetHandle() const
{ return static_cast<wxWebRequestCURL&>(m_request).GetHandle(); } { return static_cast<wxWebRequestCURL&>(m_request).GetHandle(); }
@@ -123,7 +128,7 @@ private:
wxDECLARE_NO_COPY_CLASS(wxWebResponseCURL); wxDECLARE_NO_COPY_CLASS(wxWebResponseCURL);
}; };
class wxWebSessionCURL : public wxWebSessionImpl, private wxThreadHelper class wxWebSessionCURL : public wxWebSessionImpl, public wxEvtHandler
{ {
public: public:
wxWebSessionCURL(); wxWebSessionCURL();
@@ -147,26 +152,40 @@ public:
void CancelRequest(wxWebRequestCURL* request); void CancelRequest(wxWebRequestCURL* request);
protected: void RequestHasTerminated(wxWebRequestCURL* request);
wxThread::ExitCode Entry() wxOVERRIDE;
static bool CurlRuntimeAtLeastVersion(unsigned int, unsigned int,
unsigned int);
private: private:
static int TimerCallback(CURLM*, long, void*);
static int SocketCallback(CURL*, curl_socket_t, int, void*, void*);
void ProcessTimerCallback(long);
void TimeoutNotification(wxTimerEvent&);
void ProcessTimeoutNotification();
void ProcessSocketCallback(CURL*, curl_socket_t, int);
void ProcessSocketPollerResult(wxThreadEvent&);
void CheckForCompletedTransfers();
void FailRequest(CURL*, const wxString&);
void StopActiveTransfer(CURL*);
void RemoveActiveSocket(CURL*);
WX_DECLARE_HASH_MAP(CURL*, wxWebRequestCURL*, wxPointerHash, \
wxPointerEqual, TransferSet);
WX_DECLARE_HASH_MAP(CURL*, curl_socket_t, wxPointerHash, \
wxPointerEqual, CurlSocketMap);
TransferSet m_activeTransfers;
CurlSocketMap m_activeSockets;
SocketPoller* m_socketPoller;
wxTimer m_timeoutTimer;
CURLM* m_handle; CURLM* m_handle;
// Mutex and condition are used together to signal to the worker thread to
// wake up and mutex is also used to protected m_shuttingDown field.
wxMutex m_mutex;
wxCondition m_condition;
bool m_shuttingDown;
// MT-safe vector of requests for which Cancel() was called.
struct CancelledData
{
wxCriticalSection cs;
wxVector< wxObjectDataPtr<wxWebRequestCURL> > requests;
} m_cancelled;
static int ms_activeSessions; static int ms_activeSessions;
static unsigned int ms_runtimeVersion;
wxDECLARE_NO_COPY_CLASS(wxWebSessionCURL); wxDECLARE_NO_COPY_CLASS(wxWebSessionCURL);
}; };

View File

@@ -690,6 +690,11 @@ void* wxWebResponseImpl::GetDataBuffer(size_t sizeNeeded)
return m_readBuffer.GetAppendBuf(sizeNeeded); return m_readBuffer.GetAppendBuf(sizeNeeded);
} }
void wxWebResponseImpl::PreAllocBuffer(size_t sizeNeeded)
{
m_readBuffer.SetBufSize(sizeNeeded);
}
void wxWebResponseImpl::ReportDataReceived(size_t sizeReceived) void wxWebResponseImpl::ReportDataReceived(size_t sizeReceived)
{ {
m_readBuffer.UngetAppendBuf(sizeReceived); m_readBuffer.UngetAppendBuf(sizeReceived);

File diff suppressed because it is too large Load Diff