CLOUD: Add CurlJsonRequest

Now we can do REST API request by creating CurlJsonRequest and waiting
for it to call our callback. Passed pointer is Common::JSONValue.

This commit also does some minor variable renaming fixes.
This commit is contained in:
Alexander Tkachev 2016-05-17 01:19:49 +06:00
parent 9c22b7cc64
commit 03217cd5c3
7 changed files with 63 additions and 59 deletions

View File

@ -22,15 +22,23 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/cloud/dropbox/dropboxstorage.h"
#include "backends/cloud/dropbox/curlrequest.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "common/debug.h"
#include "common/json.h"
#include <curl/curl.h>
namespace Cloud {
namespace Dropbox {
static void curlCallback(void *ptr) {
debug("--- curl request is complete ---");
static void curlJsonCallback(void *ptr) {
Common::JSONValue *json = (Common::JSONValue *)ptr;
if (json) {
debug("curlJsonCallback:");
debug("%s", json->stringify(true).c_str());
delete json;
} else {
debug("curlJsonCallback: got NULL instead of JSON!");
}
}
DropboxStorage::DropboxStorage() {
@ -45,9 +53,9 @@ void DropboxStorage::listDirectory(Common::String path) {
startTimer(1000000); //in one second
}
void DropboxStorage::syncSaves() {
addRequest(new CurlRequest(curlCallback, "tkachov.ru"));
addRequest(new CurlRequest(curlCallback, "scummvm.org"));
void DropboxStorage::syncSaves() {
//not so Dropbox, just testing JSON requesting & parsing:
addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=205387401"));
}
} //end of namespace Dropbox

View File

@ -23,14 +23,14 @@ ifdef USE_CLOUD
MODULE_OBJS += \
cloud/manager.o \
cloud/storage.o \
cloud/dropbox/dropboxstorage.o \
cloud/dropbox/curlrequest.o
cloud/dropbox/dropboxstorage.o
endif
ifdef USE_LIBCURL
MODULE_OBJS += \
networking/curl/connectionmanager.o \
networking/curl/networkreadstream.o
networking/curl/networkreadstream.o \
networking/curl/curljsonrequest.o
endif
ifdef USE_ELF_LOADER

View File

@ -46,25 +46,25 @@ NetworkReadStream *ConnectionManager::makeRequest(const char *url) {
}
void ConnectionManager::handle() {
int U;
curl_multi_perform(_multi, &U);
int transfersRunning;
curl_multi_perform(_multi, &transfersRunning);
int Q;
int messagesInQueue;
CURLMsg *curlMsg;
while ((curlMsg = curl_multi_info_read(_multi, &Q))) {
while ((curlMsg = curl_multi_info_read(_multi, &messagesInQueue))) {
CURL *easyHandle = curlMsg->easy_handle;
NetworkReadStream *stream;
curl_easy_getinfo(easyHandle, CURLINFO_PRIVATE, &stream);
if (stream) stream->done(); //I'm not sure it's OK to notify "done()" on failure
if (curlMsg->msg == CURLMSG_DONE) {
CURL *e = curlMsg->easy_handle;
NetworkReadStream *stream;
curl_easy_getinfo(e, CURLINFO_PRIVATE, &stream);
if (stream) stream->done();
debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result));
curl_multi_remove_handle(_multi, e);
debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result));
} else {
debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg);
//TODO: notify stream on this case also
debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg);
}
curl_multi_remove_handle(_multi, easyHandle);
}
}

View File

@ -22,37 +22,38 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/cloud/dropbox/curlrequest.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/debug.h"
#include "common/json.h"
#include <curl/curl.h>
namespace Cloud {
namespace Dropbox {
namespace Networking {
CurlRequest::CurlRequest(Callback cb, const char *url) : Request(cb), _firstTime(true), _stream(0) {
CurlJsonRequest::CurlJsonRequest(Callback cb, const char *url) : Request(cb), _stream(0) {
_url = url;
}
CurlRequest::~CurlRequest() {
CurlJsonRequest::~CurlJsonRequest() {
if (_stream) delete _stream;
}
bool CurlRequest::handle(Networking::ConnectionManager &manager) {
if (_firstTime) {
_stream = manager.makeRequest(_url);
_firstTime = false;
}
bool CurlJsonRequest::handle(ConnectionManager &manager) {
if (!_stream) _stream = manager.makeRequest(_url);
if (_stream) {
const int kBufSize = 10000;
const int kBufSize = 16*1024;
char buf[kBufSize+1];
uint32 readBytes = _stream->read(buf, kBufSize);
debug("%d", readBytes);
//if(readBytes != 0) debug("%s", buf);
if(_stream->eos()) {
_callback(0);
if (readBytes != 0) _contents += Common::String(buf, readBytes);
if (_stream->eos()) {
//TODO: check that stream's CURL easy handle's HTTP response code is 200 OK
debug("CurlJsonRequest: contents:\n%s", _contents.c_str());
if (_callback) {
Common::JSONValue *json = Common::JSON::parse(_contents.c_str()); //TODO: somehow fix JSON to work with UTF-8
debug("CurlJsonRequest: JSONValue pointer = %p", json);
_callback(json); //potential memory leak, free it in your callbacks!
}
return true;
}
}
@ -60,5 +61,4 @@ bool CurlRequest::handle(Networking::ConnectionManager &manager) {
return false;
}
} //end of namespace Dropbox
} //end of namespace Cloud
} //end of namespace Networking

View File

@ -20,31 +20,27 @@
*
*/
#ifndef BACKENDS_CLOUD_DROPBOX_CURLREQUEST_H
#define BACKENDS_CLOUD_DROPBOX_CURLREQUEST_H
#ifndef BACKENDS_NETWORKING_CURL_CURLJSONREQUEST_H
#define BACKENDS_NETWORKING_CURL_CURLJSONREQUEST_H
#include "backends/cloud/request.h"
namespace Networking {
class NetworkReadStream;
}
namespace Cloud {
namespace Dropbox {
class CurlRequest : public Cloud::Request {
bool _firstTime;
class CurlJsonRequest : public Cloud::Request {
const char *_url;
Networking::NetworkReadStream *_stream;
NetworkReadStream *_stream;
Common::String _contents;
public:
CurlRequest(Callback cb, const char *url);
virtual ~CurlRequest();
CurlJsonRequest(Callback cb, const char *url);
virtual ~CurlJsonRequest();
virtual bool handle(Networking::ConnectionManager &manager);
virtual bool handle(ConnectionManager &manager);
};
} //end of namespace Dropbox
} //end of namespace Cloud
} //end of namespace Networking
#endif

View File

@ -160,8 +160,8 @@ void OSystem_SDL::init() {
#endif
#if defined(USE_CLOUD)
if (_cloudThread == 0)
_cloudThread = new Cloud::Manager();
if (_cloudManager == 0)
_cloudManager = new Cloud::Manager();
#endif
}

View File

@ -185,7 +185,7 @@ protected:
*
* @note _cloudThread is deleted by the OSystem destructor.
*/
Common::CloudManager *_cloudThread;
Common::CloudManager *_cloudManager;
#endif
/**
@ -1134,7 +1134,7 @@ public:
* @return the CloudManager for the current architecture
*/
virtual Common::CloudManager *getCloudManager() {
return _cloudThread;
return _cloudManager;
}
#endif