aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/networking/curl/curlrequest.cpp18
-rw-r--r--backends/networking/curl/curlrequest.h6
-rw-r--r--backends/networking/curl/networkreadstream.cpp123
-rw-r--r--backends/networking/curl/networkreadstream.h33
-rw-r--r--backends/networking/curl/session.cpp77
-rw-r--r--backends/networking/curl/session.h45
-rw-r--r--backends/networking/curl/sessionrequest.cpp68
-rw-r--r--backends/networking/curl/sessionrequest.h12
8 files changed, 302 insertions, 80 deletions
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<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() {
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<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> 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<Common::String, Common::String> formFields, Common::HashMap<Common::String, Common::String> 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 <postFields>, 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 <formFields>, <formFiles>, using POST multipart/form. */
NetworkReadStream(
const char *url, curl_slist *headersList,
Common::HashMap<Common::String, Common::String> formFields,
- Common::HashMap<Common::String, Common::String> formFiles);
- /** Send <buffer, 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);
+ Common::HashMap<Common::String, Common::String> formFiles,
+ bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60);
+ /** Send <buffer>, 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 <postFields>, using POST by default. */
+ bool reuse(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false, bool usingPatch = false);
+ /** Send <formFields>, <formFiles>, using POST multipart/form. */
+ bool reuse(
+ const char *url, curl_slist *headersList,
+ Common::HashMap<Common::String, Common::String> formFields,
+ Common::HashMap<Common::String, Common::String> formFiles);
+ /** Send <buffer>, 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 <url> 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();