aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/cloud/dropbox/dropboxstorage.cpp26
-rw-r--r--backends/cloud/dropbox/dropboxstorage.h8
-rw-r--r--backends/cloud/storage.cpp73
-rw-r--r--backends/cloud/storage.h19
-rw-r--r--backends/module.mk3
-rw-r--r--backends/networking/curl/connectionmanager.cpp63
-rw-r--r--backends/networking/curl/connectionmanager.h40
-rw-r--r--backends/networking/curl/curljsonrequest.cpp5
-rw-r--r--backends/networking/curl/curljsonrequest.h6
-rw-r--r--backends/networking/curl/networkreadstream.cpp2
-rw-r--r--backends/networking/curl/networkreadstream.h2
-rw-r--r--backends/networking/curl/request.h (renamed from backends/cloud/request.h)15
12 files changed, 123 insertions, 139 deletions
diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp
index add6bff54c..93f0eebcf6 100644
--- a/backends/cloud/dropbox/dropboxstorage.cpp
+++ b/backends/cloud/dropbox/dropboxstorage.cpp
@@ -22,6 +22,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "common/config-manager.h"
#include "common/debug.h"
@@ -76,8 +77,7 @@ DropboxStorage::~DropboxStorage() {
curl_global_cleanup();
}
-void DropboxStorage::listDirectory(Common::String path) {
- startTimer(1000000); //in one second
+void DropboxStorage::listDirectory(Common::String path) {
}
void DropboxStorage::syncSaves() {
@@ -88,7 +88,7 @@ void DropboxStorage::syncSaves() {
void DropboxStorage::printInfo() {
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(printJsonCallback, "https://api.dropboxapi.com/1/account/info");
request->addHeader("Authorization: Bearer " + _token);
- addRequest(request);
+ ConnMan.addRequest(request);
}
DropboxStorage *DropboxStorage::loadFromConfig() {
@@ -119,10 +119,10 @@ Common::String DropboxStorage::getAuthLink() {
return url;
}
-DropboxStorage *DropboxStorage::authThroughConsole() {
+void DropboxStorage::authThroughConsole() {
if (!ConfMan.hasKey("DROPBOX_KEY", "cloud") || !ConfMan.hasKey("DROPBOX_SECRET", "cloud")) {
warning("No Dropbox keys available, cannot do auth");
- return 0;
+ return;
}
KEY = ConfMan.get("DROPBOX_KEY", "cloud");
@@ -130,29 +130,25 @@ DropboxStorage *DropboxStorage::authThroughConsole() {
if (ConfMan.hasKey("dropbox_code", "cloud")) {
//phase 2: get access_token using specified code
- return getAccessToken(ConfMan.get("dropbox_code", "cloud"));
+ getAccessToken(ConfMan.get("dropbox_code", "cloud"));
+ return;
}
debug("Navigate to this URL and press \"Allow\":");
debug("%s\n", getAuthLink().c_str());
debug("Then, add dropbox_code key in [cloud] section of configuration file. You should copy the <code> value from URL and put it as value for that key.\n");
debug("Navigate to this URL to get more information on ScummVM's configuration files:");
- debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n");
- return 0;
+ debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n");
}
-DropboxStorage *DropboxStorage::getAccessToken(Common::String code) {
+void DropboxStorage::getAccessToken(Common::String code) {
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(saveAccessTokenCallback, "https://api.dropboxapi.com/1/oauth2/token");
request->addPostField("code=" + code);
request->addPostField("grant_type=authorization_code");
request->addPostField("client_id=" + KEY);
request->addPostField("client_secret=" + SECRET);
- request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
-
- //OK, that's not how I imagined that...
- DropboxStorage *storage = new DropboxStorage("", "");
- storage->addRequest(request);
- return storage;
+ request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
+ ConnMan.addRequest(request);
}
} //end of namespace Dropbox
diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h
index f2281f146f..0500db5d49 100644
--- a/backends/cloud/dropbox/dropboxstorage.h
+++ b/backends/cloud/dropbox/dropboxstorage.h
@@ -24,7 +24,7 @@
#define BACKENDS_CLOUD_DROPBOX_STORAGE_H
#include "backends/cloud/storage.h"
-#include "../manager.h"
+#include "backends/cloud/manager.h"
namespace Cloud {
namespace Dropbox {
@@ -37,7 +37,7 @@ class DropboxStorage: public Cloud::Storage {
/** This private constructor is called from loadFromConfig(). */
DropboxStorage(Common::String token, Common::String uid);
- static DropboxStorage *getAccessToken(Common::String code);
+ static void getAccessToken(Common::String code);
public:
virtual ~DropboxStorage();
@@ -58,10 +58,8 @@ public:
/**
* Show message with Dropbox auth instructions. (Temporary)
- * Returns temporary DropboxStorage, which does network requests
- * to get access token.
*/
- static DropboxStorage *authThroughConsole();
+ static void authThroughConsole();
};
} //end of namespace Dropbox
diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp
deleted file mode 100644
index d7217a57cd..0000000000
--- a/backends/cloud/storage.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/* 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.
-*
-*/
-
-#include "backends/cloud/storage.h"
-#include "common/debug.h"
-#include "common/system.h"
-#include "common/timer.h"
-
-namespace Cloud {
-
-void cloudThread(void *thread) {
- Storage *cloudThread = (Storage *)thread;
- cloudThread->handler();
-}
-
-Storage::Storage() : _timerStarted(false) {}
-
-void Storage::addRequest(Request *request) {
- _requests.push_back(request);
- if (!_timerStarted) startTimer();
-}
-
-void Storage::handler() {
- //TODO: lock mutex here (in case another handler() would be called before this one ends)
- debug("\nhandler's here");
- for (Common::Array<Request *>::iterator i = _requests.begin(); i != _requests.end();) {
- if ((*i)->handle(_connectionManager)) {
- delete (*i);
- _requests.erase(i);
- }
- else ++i;
- }
- if (_requests.empty()) stopTimer();
-
- _connectionManager.handle();
- //TODO: unlock mutex here
-}
-
-void Storage::startTimer(int interval) {
- Common::TimerManager *manager = g_system->getTimerManager();
- if (manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) {
- _timerStarted = true;
- } else {
- warning("Failed to create cloud thread");
- }
-}
-
-void Storage::stopTimer() {
- Common::TimerManager *manager = g_system->getTimerManager();
- manager->removeTimerProc(cloudThread);
- _timerStarted = false;
-}
-
-} //end of namespace Cloud
diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h
index a5d048d3af..9e23e97761 100644
--- a/backends/cloud/storage.h
+++ b/backends/cloud/storage.h
@@ -24,28 +24,13 @@
#define BACKENDS_CLOUD_STORAGE_H
#include "common/str.h"
-#include "common/array.h"
-#include "backends/cloud/request.h"
-#include "backends/networking/curl/connectionmanager.h"
namespace Cloud {
class Storage {
- friend void cloudThread(void *); //calls handler()
- bool _timerStarted;
-
-protected:
- Common::Array<Request *> _requests;
- Networking::ConnectionManager _connectionManager;
-
- virtual void addRequest(Request *request); //starts the timer if it's not started
- virtual void handler();
- virtual void startTimer(int interval = 1000000); //1 second is the default interval
- virtual void stopTimer();
-
public:
- Storage();
- virtual ~Storage() {};
+ Storage() {}
+ virtual ~Storage() {}
/**
* Lists given directory.
diff --git a/backends/module.mk b/backends/module.mk
index 72183f9563..0142531835 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -21,8 +21,7 @@ MODULE_OBJS := \
ifdef USE_CLOUD
MODULE_OBJS += \
- cloud/manager.o \
- cloud/storage.o \
+ cloud/manager.o \
cloud/dropbox/dropboxstorage.o
endif
diff --git a/backends/networking/curl/connectionmanager.cpp b/backends/networking/curl/connectionmanager.cpp
index d34eab23e8..31e99f989c 100644
--- a/backends/networking/curl/connectionmanager.cpp
+++ b/backends/networking/curl/connectionmanager.cpp
@@ -25,11 +25,16 @@
#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/debug.h"
+#include "common/system.h"
+#include "common/timer.h"
#include <curl/curl.h>
+using Common::Singleton;
+
+DECLARE_SINGLETON(Networking::ConnectionManager);
namespace Networking {
-ConnectionManager::ConnectionManager(): _multi(0) {
+ConnectionManager::ConnectionManager(): _multi(0), _timerStarted(false) {
curl_global_init(CURL_GLOBAL_ALL);
_multi = curl_multi_init();
}
@@ -39,13 +44,57 @@ ConnectionManager::~ConnectionManager() {
curl_global_cleanup();
}
-NetworkReadStream *ConnectionManager::makeRequest(const char *url, curl_slist *headersList, Common::String postFields) {
- NetworkReadStream *stream = new NetworkReadStream(url, headersList, postFields);
- curl_multi_add_handle(_multi, stream->getEasyHandle());
- return stream;
+void ConnectionManager::registerEasyHandle(CURL *easy) {
+ curl_multi_add_handle(_multi, easy);
+}
+
+void ConnectionManager::addRequest(Request *request) {
+ _requests.push_back(request);
+ if (!_timerStarted) startTimer();
+}
+
+//private goes here:
+
+void connectionsThread(void *ignored) {
+ ConnMan.handle();
+}
+
+void ConnectionManager::startTimer(int interval) {
+ Common::TimerManager *manager = g_system->getTimerManager();
+ if (manager->installTimerProc(connectionsThread, interval, 0, "Networking::ConnectionManager's Timer")) {
+ _timerStarted = true;
+ } else {
+ warning("Failed to install Networking::ConnectionManager's timer");
+ }
+}
+
+void ConnectionManager::stopTimer() {
+ Common::TimerManager *manager = g_system->getTimerManager();
+ manager->removeTimerProc(connectionsThread);
+ _timerStarted = false;
}
void ConnectionManager::handle() {
+ //TODO: lock mutex here (in case another handle() would be called before this one ends)
+ interateRequests();
+ processTransfers();
+ //TODO: unlock mutex here
+}
+
+void ConnectionManager::interateRequests() {
+ //call handle() of all running requests (so they can do their work)
+ debug("handler's here");
+ for (Common::Array<Request *>::iterator i = _requests.begin(); i != _requests.end();) {
+ if ((*i)->handle()) {
+ delete (*i);
+ _requests.erase(i);
+ } else ++i;
+ }
+ if (_requests.empty()) stopTimer();
+}
+
+void ConnectionManager::processTransfers() {
+ //check libcurl's transfers and notify requests of messages from queue (transfer completion or failure)
int transfersRunning;
curl_multi_perform(_multi, &transfersRunning);
@@ -59,9 +108,9 @@ void ConnectionManager::handle() {
if (stream) stream->finished();
if (curlMsg->msg == CURLMSG_DONE) {
- debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result));
+ debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result));
} else {
- debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg);
+ debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg);
}
curl_multi_remove_handle(_multi, easyHandle);
diff --git a/backends/networking/curl/connectionmanager.h b/backends/networking/curl/connectionmanager.h
index b83de6191a..ed726441c4 100644
--- a/backends/networking/curl/connectionmanager.h
+++ b/backends/networking/curl/connectionmanager.h
@@ -23,8 +23,12 @@
#ifndef BACKENDS_NETWORKING_CURL_CONNECTIONMANAGER_H
#define BACKENDS_NETWORKING_CURL_CONNECTIONMANAGER_H
+#include "backends/networking/curl/request.h"
#include "common/str.h"
+#include "common/singleton.h"
+#include "common/array.h"
+typedef void CURL;
typedef void CURLM;
struct curl_slist;
@@ -32,17 +36,43 @@ namespace Networking {
class NetworkReadStream;
-class ConnectionManager {
- CURLM *_multi;
+class ConnectionManager : public Common::Singleton<ConnectionManager> {
+ friend void connectionsThread(void *); //calls handle()
+
+ CURLM *_multi;
+ bool _timerStarted;
+ Common::Array<Request *> _requests;
+
+ void startTimer(int interval = 1000000); //1 second is the default interval
+ void stopTimer();
+ void handle();
+ void interateRequests();
+ void processTransfers();
public:
ConnectionManager();
virtual ~ConnectionManager();
- NetworkReadStream *makeRequest(const char *url, curl_slist *headersList, Common::String postFields);
- void handle();
+ /**
+ * All libcurl transfers are going through this ConnectionManager.
+ * So, if you want to start any libcurl transfer, you must create
+ * an easy handle and register it using this method.
+ */
+ void registerEasyHandle(CURL *easy);
+
+ /**
+ * Use this method to add new Request into manager's queue.
+ * Manager will periodically call handle() method of these
+ * Requests until they return true.
+ *
+ * @note This method starts the timer if it's not started yet.
+ */
+ void addRequest(Request *request);
};
-} //end of namespace Cloud
+/** Shortcut for accessing the connection manager. */
+#define ConnMan Networking::ConnectionManager::instance()
+
+} //end of namespace Networking
#endif
diff --git a/backends/networking/curl/curljsonrequest.cpp b/backends/networking/curl/curljsonrequest.cpp
index 0c6363467a..59bc830692 100644
--- a/backends/networking/curl/curljsonrequest.cpp
+++ b/backends/networking/curl/curljsonrequest.cpp
@@ -23,6 +23,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/networking/curl/curljsonrequest.h"
+#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/debug.h"
#include "common/json.h"
@@ -56,8 +57,8 @@ char *CurlJsonRequest::getPreparedContents() {
return (char *)result;
}
-bool CurlJsonRequest::handle(ConnectionManager &manager) {
- if (!_stream) _stream = manager.makeRequest(_url, _headersList, _postFields);
+bool CurlJsonRequest::handle() {
+ if (!_stream) _stream = new NetworkReadStream(_url, _headersList, _postFields);
if (_stream) {
const int kBufSize = 16*1024;
diff --git a/backends/networking/curl/curljsonrequest.h b/backends/networking/curl/curljsonrequest.h
index 17df9693f2..cbf3f6dd56 100644
--- a/backends/networking/curl/curljsonrequest.h
+++ b/backends/networking/curl/curljsonrequest.h
@@ -23,7 +23,7 @@
#ifndef BACKENDS_NETWORKING_CURL_CURLJSONREQUEST_H
#define BACKENDS_NETWORKING_CURL_CURLJSONREQUEST_H
-#include "backends/cloud/request.h"
+#include "backends/networking/curl/request.h"
#include "common/memstream.h"
struct curl_slist;
@@ -32,7 +32,7 @@ namespace Networking {
class NetworkReadStream;
-class CurlJsonRequest : public Cloud::Request {
+class CurlJsonRequest : public Request {
const char *_url;
NetworkReadStream *_stream;
curl_slist *_headersList;
@@ -46,7 +46,7 @@ public:
CurlJsonRequest(Callback cb, const char *url);
virtual ~CurlJsonRequest();
- virtual bool handle(ConnectionManager &manager);
+ virtual bool handle();
void addHeader(Common::String header);
diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp
index f2af4fd50c..8fd39d6884 100644
--- a/backends/networking/curl/networkreadstream.cpp
+++ b/backends/networking/curl/networkreadstream.cpp
@@ -23,6 +23,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/networking/curl/networkreadstream.h"
+#include "backends/networking/curl/connectionmanager.h"
#include "common/debug.h"
#include <curl/curl.h>
@@ -47,6 +48,7 @@ NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, C
curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList);
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, postFields.size());
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, postFields.c_str());
+ ConnMan.registerEasyHandle(_easy);
}
NetworkReadStream::~NetworkReadStream() {
diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h
index bc4b761ba7..6431a01fee 100644
--- a/backends/networking/curl/networkreadstream.h
+++ b/backends/networking/curl/networkreadstream.h
@@ -40,8 +40,6 @@ public:
NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields);
virtual ~NetworkReadStream();
- CURL *getEasyHandle() const { return _easy; }
-
/**
* Returns true if a read failed because the stream end has been reached.
* This flag is cleared by clearErr().
diff --git a/backends/cloud/request.h b/backends/networking/curl/request.h
index d85a68d570..4f901f7c94 100644
--- a/backends/cloud/request.h
+++ b/backends/networking/curl/request.h
@@ -20,21 +20,20 @@
*
*/
-#ifndef BACKENDS_CLOUD_REQUEST_H
-#define BACKENDS_CLOUD_REQUEST_H
+#ifndef BACKENDS_NETWORKING_CURL_REQUEST_H
+#define BACKENDS_NETWORKING_CURL_REQUEST_H
-#include "backends/networking/curl/connectionmanager.h"
-
-namespace Cloud {
+namespace Networking {
class Request {
protected:
+ typedef void(*Callback)(void *result);
+
/**
* Callback, which should be called before Request returns true in handle().
- * That's the way Requests pass the result to the code which asked to create this request.
+ * That's the way Requests pass the result to the code which asked to create this request.
*/
- typedef void(*Callback)(void *result);
Callback _callback;
public:
@@ -47,7 +46,7 @@ public:
* @return true if request's work is complete and it may be removed from Storage's list
*/
- virtual bool handle(Networking::ConnectionManager &manager) = 0;
+ virtual bool handle() = 0;
};
} //end of namespace Cloud