diff options
Diffstat (limited to 'backends/networking/curl/networkreadstream.cpp')
-rw-r--r-- | backends/networking/curl/networkreadstream.cpp | 123 |
1 files changed, 71 insertions, 52 deletions
diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp index b8f06b728f..06f4dc52a8 100644 --- a/backends/networking/curl/networkreadstream.cpp +++ b/backends/networking/curl/networkreadstream.cpp @@ -63,13 +63,18 @@ int NetworkReadStream::curlProgressCallbackOlder(void *p, double dltotal, double return curlProgressCallback(p, (curl_off_t)dltotal, (curl_off_t)dlnow, (curl_off_t)ultotal, (curl_off_t)ulnow); } -void NetworkReadStream::init(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) { +void NetworkReadStream::resetStream() { _eos = _requestComplete = false; - _errorBuffer = (char *)calloc(CURL_ERROR_SIZE, 1); + if (!_errorBuffer) + _errorBuffer = (char *)calloc(CURL_ERROR_SIZE, 1); _sendingContentsBuffer = nullptr; _sendingContentsSize = _sendingContentsPos = 0; _progressDownloaded = _progressTotal = 0; _bufferCopy = nullptr; +} + +void NetworkReadStream::initCurl(const char *url, curl_slist *headersList) { + resetStream(); _easy = curl_easy_init(); curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); @@ -102,6 +107,30 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt curl_easy_setopt(_easy, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); curl_easy_setopt(_easy, CURLOPT_XFERINFODATA, this); #endif + + if (_keepAlive) { + curl_easy_setopt(_easy, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(_easy, CURLOPT_TCP_KEEPIDLE, _keepAliveIdle); + curl_easy_setopt(_easy, CURLOPT_TCP_KEEPINTVL, _keepAliveInterval); + } +} + +bool NetworkReadStream::reuseCurl(const char *url, curl_slist *headersList) { + if (!_keepAlive) { + warning("NetworkReadStream: Can't reuse curl handle (was not setup as keep-alive)"); + return false; + } + + resetStream(); + + curl_easy_setopt(_easy, CURLOPT_URL, url); + curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); + curl_easy_setopt(_easy, CURLOPT_USERAGENT, gScummVMFullVersion); // in case headersList rewrites it + + return true; +} + +void NetworkReadStream::setupBufferContents(const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) { if (uploading) { curl_easy_setopt(_easy, CURLOPT_UPLOAD, 1L); curl_easy_setopt(_easy, CURLOPT_READDATA, this); @@ -126,46 +155,7 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt ConnMan.registerEasyHandle(_easy); } -void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::HashMap<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> formFiles) { - _eos = _requestComplete = false; - _errorBuffer = (char *)calloc(CURL_ERROR_SIZE, 1); - _sendingContentsBuffer = nullptr; - _sendingContentsSize = _sendingContentsPos = 0; - _progressDownloaded = _progressTotal = 0; - _bufferCopy = nullptr; - - _easy = curl_easy_init(); - curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); - curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us - curl_easy_setopt(_easy, CURLOPT_PRIVATE, this); //so ConnectionManager can call us when request is complete - curl_easy_setopt(_easy, CURLOPT_HEADER, 0L); - curl_easy_setopt(_easy, CURLOPT_HEADERDATA, this); - curl_easy_setopt(_easy, CURLOPT_HEADERFUNCTION, curlHeadersCallback); - curl_easy_setopt(_easy, CURLOPT_URL, url); - curl_easy_setopt(_easy, CURLOPT_ERRORBUFFER, _errorBuffer); - curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); - curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on - curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); - curl_easy_setopt(_easy, CURLOPT_USERAGENT, gScummVMFullVersion); - curl_easy_setopt(_easy, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(_easy, CURLOPT_PROGRESSFUNCTION, curlProgressCallbackOlder); - curl_easy_setopt(_easy, CURLOPT_PROGRESSDATA, this); -#if defined NINTENDO_SWITCH || defined ANDROID_PLAIN_PORT - curl_easy_setopt(_easy, CURLOPT_SSL_VERIFYPEER, 0); -#endif - - const char *caCertPath = ConnMan.getCaCertPath(); - if (caCertPath) { - curl_easy_setopt(_easy, CURLOPT_CAINFO, caCertPath); - } - -#if LIBCURL_VERSION_NUM >= 0x072000 - // CURLOPT_XFERINFOFUNCTION introduced in libcurl 7.32.0 - // CURLOPT_PROGRESSFUNCTION is used as a backup plan in case older version is used - curl_easy_setopt(_easy, CURLOPT_XFERINFOFUNCTION, curlProgressCallback); - curl_easy_setopt(_easy, CURLOPT_XFERINFODATA, this); -#endif - +void NetworkReadStream::setupFormMultipart(Common::HashMap<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> formFiles) { // set POST multipart upload form fields/files struct curl_httppost *formpost = nullptr; struct curl_httppost *lastptr = nullptr; @@ -197,23 +187,52 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::H } curl_easy_setopt(_easy, CURLOPT_HTTPPOST, formpost); - ConnMan.registerEasyHandle(_easy); } -NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading, bool usingPatch) : - _backingStream(DisposeAfterUse::YES) { - init(url, headersList, (const byte *)postFields.c_str(), postFields.size(), uploading, usingPatch, false); +NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading, bool usingPatch, bool keepAlive, long keepAliveIdle, long keepAliveInterval): + _backingStream(DisposeAfterUse::YES), _keepAlive(keepAlive), _keepAliveIdle(keepAliveIdle), _keepAliveInterval(keepAliveInterval), _errorBuffer(nullptr) { + initCurl(url, headersList); + setupBufferContents((const byte *)postFields.c_str(), postFields.size(), uploading, usingPatch, false); +} + +NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::HashMap<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> formFiles, bool keepAlive, long keepAliveIdle, long keepAliveInterval): + _backingStream(DisposeAfterUse::YES), _keepAlive(keepAlive), _keepAliveIdle(keepAliveIdle), _keepAliveInterval(keepAliveInterval), _errorBuffer(nullptr) { + initCurl(url, headersList); + setupFormMultipart(formFields, formFiles); } -NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::HashMap<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> formFiles) : - _backingStream(DisposeAfterUse::YES) { - init(url, headersList, formFields, formFiles); +NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post, bool keepAlive, long keepAliveIdle, long keepAliveInterval): + _backingStream(DisposeAfterUse::YES), _keepAlive(keepAlive), _keepAliveIdle(keepAliveIdle), _keepAliveInterval(keepAliveInterval), _errorBuffer(nullptr) { + initCurl(url, headersList); + setupBufferContents(buffer, bufferSize, uploading, usingPatch, post); } -NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) : - _backingStream(DisposeAfterUse::YES) { - init(url, headersList, buffer, bufferSize, uploading, usingPatch, post); +bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, Common::String postFields, bool uploading, bool usingPatch) { + if (!reuseCurl(url, headersList)) + return false; + + _backingStream = Common::MemoryReadWriteStream(DisposeAfterUse::YES); + setupBufferContents((const byte *)postFields.c_str(), postFields.size(), uploading, usingPatch, false); + return true; +} + +bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, Common::HashMap<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> formFiles) { + if (!reuseCurl(url, headersList)) + return false; + + _backingStream = Common::MemoryReadWriteStream(DisposeAfterUse::YES); + setupFormMultipart(formFields, formFiles); + return true; +} + +bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) { + if (!reuseCurl(url, headersList)) + return false; + + _backingStream = Common::MemoryReadWriteStream(DisposeAfterUse::YES); + setupBufferContents(buffer, bufferSize, uploading, usingPatch, post); + return true; } NetworkReadStream::~NetworkReadStream() { |