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);
// 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:
// Called by wxWebRequestImpl only.
friend class wxWebRequestImpl;

View File

@@ -16,12 +16,15 @@
#include "wx/thread.h"
#include "wx/vector.h"
#include "wx/timer.h"
#include "wx/hashmap.h"
#include "curl/curl.h"
class wxWebRequestCURL;
class wxWebResponseCURL;
class wxWebSessionCURL;
class SocketPoller;
class wxWebAuthChallengeCURL : public wxWebAuthChallengeImpl
{
@@ -112,10 +115,12 @@ 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(curl_off_t);
private:
wxWebRequestHeaderMap m_headers;
wxString m_statusText;
wxFileOffset m_knownDownloadSize;
CURL* GetHandle() const
{ return static_cast<wxWebRequestCURL&>(m_request).GetHandle(); }
@@ -123,7 +128,7 @@ private:
wxDECLARE_NO_COPY_CLASS(wxWebResponseCURL);
};
class wxWebSessionCURL : public wxWebSessionImpl, private wxThreadHelper
class wxWebSessionCURL : public wxWebSessionImpl, public wxEvtHandler
{
public:
wxWebSessionCURL();
@@ -147,26 +152,40 @@ public:
void CancelRequest(wxWebRequestCURL* request);
protected:
wxThread::ExitCode Entry() wxOVERRIDE;
void RequestHasTerminated(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*);
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;
// 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 unsigned int ms_runtimeVersion;
wxDECLARE_NO_COPY_CLASS(wxWebSessionCURL);
};

View File

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

File diff suppressed because it is too large Load Diff