From 99e21f4320d86d027c6fac1884310f4f86835d66 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 3 Nov 2019 02:16:00 +0700 Subject: NETWORKING: Enter Session Session allows to reuse SessionRequests to the same host by making them keeping alive connection. Turns out, though, that libcurl already does that for us, and we didn't gain any speedup we thought we'd get. Usage: ``` Networking::Session s; Networking::SessionRequest *request = s.get(url); request->startAndWait(); warning("HTTP GET: %s", request->text()); s.close(); ``` You can still use SessionRequest without Session (but you can't put them on stack!): ``` Networking::SessionRequest *request = new Networking::SessionRequest(url); request->startAndWait(); warning("HTTP GET: %s", request->text()); request->close(); ``` --- backends/networking/curl/curlrequest.cpp | 18 +++- backends/networking/curl/curlrequest.h | 6 ++ backends/networking/curl/networkreadstream.cpp | 123 ++++++++++++++----------- backends/networking/curl/networkreadstream.h | 33 +++++-- backends/networking/curl/session.cpp | 77 ++++++++++++++++ backends/networking/curl/session.h | 45 +++++++++ backends/networking/curl/sessionrequest.cpp | 68 +++++++++++--- backends/networking/curl/sessionrequest.h | 12 ++- 8 files changed, 302 insertions(+), 80 deletions(-) create mode 100644 backends/networking/curl/session.cpp create mode 100644 backends/networking/curl/session.h diff --git a/backends/networking/curl/curlrequest.cpp b/backends/networking/curl/curlrequest.cpp index 887ba86c6e..a3c836b7c4 100644 --- a/backends/networking/curl/curlrequest.cpp +++ b/backends/networking/curl/curlrequest.cpp @@ -32,7 +32,7 @@ namespace Networking { CurlRequest::CurlRequest(DataCallback cb, ErrorCallback ecb, Common::String url): Request(cb, ecb), _url(url), _stream(nullptr), _headersList(nullptr), _bytesBuffer(nullptr), - _bytesBufferSize(0), _uploading(false), _usingPatch(false) {} + _bytesBufferSize(0), _uploading(false), _usingPatch(false), _keepAlive(false), _keepAliveIdle(120), _keepAliveInterval(60) {} CurlRequest::~CurlRequest() { delete _stream; @@ -41,10 +41,10 @@ CurlRequest::~CurlRequest() { NetworkReadStream *CurlRequest::makeStream() { if (_bytesBuffer) - return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, _uploading, _usingPatch, true); + return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, _uploading, _usingPatch, true, _keepAlive, _keepAliveIdle, _keepAliveInterval); if (!_formFields.empty() || !_formFiles.empty()) - return new NetworkReadStream(_url.c_str(), _headersList, _formFields, _formFiles); - return new NetworkReadStream(_url.c_str(), _headersList, _postFields, _uploading, _usingPatch); + return new NetworkReadStream(_url.c_str(), _headersList, _formFields, _formFiles, _keepAlive, _keepAliveIdle, _keepAliveInterval); + return new NetworkReadStream(_url.c_str(), _headersList, _postFields, _uploading, _usingPatch, _keepAlive, _keepAliveIdle, _keepAliveInterval); } void CurlRequest::handle() { @@ -137,6 +137,16 @@ void CurlRequest::usePut() { _uploading = true; } void CurlRequest::usePatch() { _usingPatch = true; } +void CurlRequest::connectionKeepAlive(long idle, long interval) { + _keepAlive = true; + _keepAliveIdle = idle; + _keepAliveInterval = interval; +} + +void CurlRequest::connectionClose() { + _keepAlive = false; +} + NetworkReadStreamResponse CurlRequest::execute() { if (!_stream) { _stream = makeStream(); diff --git a/backends/networking/curl/curlrequest.h b/backends/networking/curl/curlrequest.h index f8d71c4828..9bca05c771 100644 --- a/backends/networking/curl/curlrequest.h +++ b/backends/networking/curl/curlrequest.h @@ -50,6 +50,8 @@ protected: uint32 _bytesBufferSize; bool _uploading; //using PUT method bool _usingPatch; //using PATCH method + bool _keepAlive; + long _keepAliveIdle, _keepAliveInterval; virtual NetworkReadStream *makeStream(); @@ -85,6 +87,10 @@ public: /** Remembers to use PATCH method when it would create NetworkReadStream. */ virtual void usePatch(); + /** Remembers to use Connection: keep-alive or close. */ + virtual void connectionKeepAlive(long idle = 120, long interval = 60); + virtual void connectionClose(); + /** * Starts this Request with ConnMan. * @return its NetworkReadStream in NetworkReadStreamResponse. 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 formFields, Common::HashMap 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 formFields, Common::HashMap 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 formFields, Common::HashMap 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 formFields, Common::HashMap 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 formFields, Common::HashMap 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() { diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h index 468fce70a4..f8a49ea18f 100644 --- a/backends/networking/curl/networkreadstream.h +++ b/backends/networking/curl/networkreadstream.h @@ -37,16 +37,22 @@ namespace Networking { class NetworkReadStream: public Common::ReadStream { CURL *_easy; Common::MemoryReadWriteStream _backingStream; + bool _keepAlive; + long _keepAliveIdle, _keepAliveInterval; bool _eos, _requestComplete; char *_errorBuffer; const byte *_sendingContentsBuffer; uint32 _sendingContentsSize; uint32 _sendingContentsPos; - byte* _bufferCopy; // To use with old curl version where CURLOPT_COPYPOSTFIELDS is not available + byte *_bufferCopy; // To use with old curl version where CURLOPT_COPYPOSTFIELDS is not available Common::String _responseHeaders; uint64 _progressDownloaded, _progressTotal; - void init(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post); - void init(const char *url, curl_slist *headersList, Common::HashMap formFields, Common::HashMap formFiles); + + void resetStream(); + void initCurl(const char *url, curl_slist *headersList); + bool reuseCurl(const char *url, curl_slist *headersList); + void setupBufferContents(const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post); + void setupFormMultipart(Common::HashMap formFields, Common::HashMap formFiles); /** * Fills the passed buffer with _sendingContentsBuffer contents. @@ -70,16 +76,27 @@ class NetworkReadStream: public Common::ReadStream { static int curlProgressCallbackOlder(void *p, double dltotal, double dlnow, double ultotal, double ulnow); public: /** Send , using POST by default. */ - NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false, bool usingPatch = false); + NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false, bool usingPatch = false, bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60); /** Send , , using POST multipart/form. */ NetworkReadStream( const char *url, curl_slist *headersList, Common::HashMap formFields, - Common::HashMap formFiles); - /** Send formFiles, + bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60); + /** Send , using POST by default. */ + NetworkReadStream(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading = false, bool usingPatch = false, bool post = true, bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60); virtual ~NetworkReadStream(); + /** Send , using POST by default. */ + bool reuse(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false, bool usingPatch = false); + /** Send , , using POST multipart/form. */ + bool reuse( + const char *url, curl_slist *headersList, + Common::HashMap formFields, + Common::HashMap formFiles); + /** Send , using POST by default. */ + bool reuse(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading = false, bool usingPatch = false, bool post = true); + /** * Returns true if a read failed because the stream end has been reached. * This flag is cleared by clearErr(). @@ -150,6 +167,8 @@ public: /** Used in curl progress callback to pass current downloaded/total values. */ void setProgress(uint64 downloaded, uint64 total); + + bool keepAlive() const { return _keepAlive; } }; } // End of namespace Networking diff --git a/backends/networking/curl/session.cpp b/backends/networking/curl/session.cpp new file mode 100644 index 0000000000..260f6d85c8 --- /dev/null +++ b/backends/networking/curl/session.cpp @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/networking/curl/session.h" + +namespace Networking { + +Session::Session(Common::String prefix): + _prefix(prefix), _request(nullptr) {} + +Session::~Session() { + close(); +} + +SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback ecb) { + // check url prefix + if (!_prefix.empty()) { + if (url.contains("://")) { + if (url.size() < _prefix.size() || url.find(_prefix) != 0) { + warning("Session: given URL does not match the prefix!\n\t%s\n\t%s", url.c_str(), _prefix.c_str()); + return nullptr; + } + } else { + // if no schema given, just append to <_prefix> + Common::String newUrl = _prefix; + if (newUrl.lastChar() != '/' && (url.size() > 0 && url.firstChar() != '/')) + newUrl += "/"; + newUrl += url; + url = newUrl; + } + } + + // check if request has finished (ready to be replaced) + if (_request) { + if (!_request->complete()) { + warning("Session: can't reuse Request that is being processed"); + return nullptr; + } + } + + if (!_request) { + _request = new Networking::SessionRequest(url, cb, ecb); // automatically added to ConnMan + _request->connectionKeepAlive(); + } else { + _request->reuse(url, cb, ecb); + } + + return _request; +} + +void Session::close() { + if (_request) + _request->close(); +} + +} // End of namespace Networking diff --git a/backends/networking/curl/session.h b/backends/networking/curl/session.h new file mode 100644 index 0000000000..d3aa5807a7 --- /dev/null +++ b/backends/networking/curl/session.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_NETWORKING_CURL_SESSION_H +#define BACKENDS_NETWORKING_CURL_SESSION_H + +#include "backends/networking/curl/sessionrequest.h" + +namespace Networking { + +class Session { +protected: + Common::String _prefix; + SessionRequest *_request; + +public: + Session(Common::String prefix = ""); + ~Session(); + + SessionRequest *get(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr); + void close(); +}; + +} // End of namespace Networking + +#endif diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp index 5fe0e64aa1..42afd6387b 100644 --- a/backends/networking/curl/sessionrequest.cpp +++ b/backends/networking/curl/sessionrequest.cpp @@ -34,12 +34,32 @@ namespace Networking { SessionRequest::SessionRequest(Common::String url, DataCallback cb, ErrorCallback ecb): CurlRequest(cb, ecb, url), _contentsStream(DisposeAfterUse::YES), _buffer(new byte[CURL_SESSION_REQUEST_BUFFER_SIZE]), _text(nullptr), - _started(false), _complete(false), _success(false) {} + _started(false), _complete(false), _success(false) { + + // automatically go under ConnMan control so nobody would be able to leak the memory + // but, we don't need it to be working just yet + _state = PAUSED; + ConnMan.addRequest(this); +} SessionRequest::~SessionRequest() { delete[] _buffer; } +bool SessionRequest::reuseStream() { + if (!_stream) { + return false; + } + + if (_bytesBuffer) + return _stream->reuse(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, _uploading, _usingPatch, true); + + if (!_formFields.empty() || !_formFiles.empty()) + return _stream->reuse(_url.c_str(), _headersList, _formFields, _formFiles); + + return _stream->reuse(_url.c_str(), _headersList, _postFields, _uploading, _usingPatch); +} + char *SessionRequest::getPreparedContents() { //write one more byte in the end byte zero[1] = {0}; @@ -71,12 +91,29 @@ void SessionRequest::finishSuccess() { } void SessionRequest::start() { - if (_started) { + if (_state != PAUSED || _started) { warning("Can't start() SessionRequest as it is already started"); - } else { - _started = true; - ConnMan.addRequest(this); + return; } + + _state = PROCESSING; + _started = true; +} + +void SessionRequest::startAndWait() { + start(); + wait(); +} + +void SessionRequest::reuse(Common::String url, DataCallback cb, ErrorCallback ecb) { + _url = url; + + delete _callback; + delete _errorCallback; + _callback = cb; + _errorCallback = ecb; + + restart(); } void SessionRequest::handle() { @@ -95,13 +132,23 @@ void SessionRequest::handle() { } void SessionRequest::restart() { - if (_stream) - delete _stream; - _stream = nullptr; + if (_stream) { + bool deleteStream = true; + if (_keepAlive && reuseStream()) { + deleteStream = false; + } + + if (deleteStream) { + delete _stream; + _stream = nullptr; + } + } + _contentsStream = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES); _text = nullptr; _complete = false; _success = false; + _started = false; //with no stream available next handle() will create another one } @@ -109,11 +156,6 @@ void SessionRequest::close() { _state = FINISHED; } -void SessionRequest::startAndWait() { - start(); - wait(); -} - bool SessionRequest::complete() { return _complete; } diff --git a/backends/networking/curl/sessionrequest.h b/backends/networking/curl/sessionrequest.h index 590eee4a5a..fd2757fcd2 100644 --- a/backends/networking/curl/sessionrequest.h +++ b/backends/networking/curl/sessionrequest.h @@ -38,6 +38,8 @@ protected: char *_text; bool _started, _complete, _success; + bool reuseStream(); + /** Prepares raw bytes from _contentsStream. */ char *getPreparedContents(); @@ -48,14 +50,16 @@ public: SessionRequest(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr); virtual ~SessionRequest(); - virtual void start(); + void start(); + void startAndWait(); + + void reuse(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr); + virtual void handle(); virtual void restart(); /** This request DOES NOT delete automatically after calling callbacks. It gets PAUSED, and in order to make it FINISHED (i.e. delete), this method MUST be called. */ - virtual void close(); - - void startAndWait(); + void close(); bool complete(); bool success(); -- cgit v1.2.3