CLOUD: Add OneDriveUploadRequest

Doesn't support server's requested ranges yet.

Commit also adds some PUT-related code in NetworkReadStream and
CurlRequest.
This commit is contained in:
Alexander Tkachev 2016-05-31 14:18:32 +06:00
parent eb63b50b7f
commit b39f46788a
14 changed files with 354 additions and 33 deletions

View file

@ -131,19 +131,6 @@ Networking::Request *DropboxStorage::upload(Common::String path, Common::Seekabl
return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback));
}
Networking::Request *DropboxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
Common::File *f = new Common::File();
if (!f->open(localPath)) {
warning("DropboxStorage: unable to open file to upload from");
if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1));
delete errorCallback;
delete callback;
delete f;
return nullptr;
}
return upload(remotePath, f, callback, errorCallback);
}
Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) {
Common::JSONObject jsonRequestParameters;
jsonRequestParameters.setVal("path", new Common::JSONValue(path));

View file

@ -75,7 +75,6 @@ public:
/** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback);
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
/** Returns pointer to Networking::NetworkReadStream. */
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);

View file

@ -24,8 +24,10 @@
#include "backends/cloud/onedrive/onedrivestorage.h"
#include "backends/cloud/onedrive/onedrivetokenrefresher.h"
#include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h"
#include "backends/cloud/onedrive/onedriveuploadrequest.h"
#include "backends/cloud/downloadrequest.h"
#include "backends/cloud/folderdownloadrequest.h"
#include "backends/cloud/savessyncrequest.h"
#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "common/cloudmanager.h"
@ -35,7 +37,6 @@
#include "common/json.h"
#include "common/system.h"
#include <curl/curl.h>
#include "../savessyncrequest.h"
namespace Cloud {
namespace OneDrive {
@ -168,6 +169,9 @@ Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDir
return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive));
}
Networking::Request *OneDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) {
return ConnMan.addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback));
}
Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) {
Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path;
@ -210,6 +214,13 @@ void OneDriveStorage::printBool(BoolResponse response) {
debug("bool: %s", response.value ? "true" : "false");
}
void OneDriveStorage::printFile(UploadResponse response) {
debug("\nuploaded file info:");
debug("\tpath: %s", response.value.path().c_str());
debug("\tsize: %u", response.value.size());
debug("\ttimestamp: %u", response.value.timestamp());
}
void OneDriveStorage::printErrorResponse(Networking::ErrorResponse error) {
debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode);
debug("%s", error.response.c_str());
@ -228,7 +239,11 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networkin
return ConnMan.addRequest(request);
*/
//return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback<OneDriveStorage, FileArrayResponse>(this, &OneDriveStorage::printFiles), false);
return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback<OneDriveStorage, BoolResponse>(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO
return Storage::upload(
"uploads/test.jpg", "test.jpg",
new Common::Callback<OneDriveStorage, UploadResponse>(this, &OneDriveStorage::printFile), getErrorPrintingCallback()
);
//return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback<OneDriveStorage, BoolResponse>(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO
}
OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {

View file

@ -53,6 +53,7 @@ class OneDriveStorage: public Cloud::Storage {
void fileDownloaded(BoolResponse response);
void printFiles(FileArrayResponse response);
void printBool(BoolResponse response);
void printFile(UploadResponse response);
void printErrorResponse(Networking::ErrorResponse error);
Networking::ErrorCallback getErrorPrintingCallback();
@ -80,8 +81,7 @@ public:
virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
/** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback);
/** Returns pointer to Networking::NetworkReadStream. */
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);

View file

@ -90,6 +90,8 @@ void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) {
irrecoverable = false;
}
if (code == "unauthenticated") irrecoverable = false;
if (irrecoverable) {
finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode
delete json;

View file

@ -0,0 +1,171 @@
/* 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/onedrive/onedriveuploadrequest.h"
#include "backends/cloud/onedrive/onedrivestorage.h"
#include "backends/cloud/iso8601.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/json.h"
#include "common/debug.h"
#include "onedrivetokenrefresher.h"
namespace Cloud {
namespace OneDrive {
OneDriveUploadRequest::OneDriveUploadRequest(OneDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
_workingRequest(nullptr), _ignoreCallback(false) {
start();
}
OneDriveUploadRequest::~OneDriveUploadRequest() {
_ignoreCallback = true;
if (_workingRequest) _workingRequest->finish();
delete _contentsStream;
delete _uploadCallback;
}
void OneDriveUploadRequest::start() {
_ignoreCallback = true;
if (_workingRequest) _workingRequest->finish();
if (!_contentsStream->seek(0)) {
warning("OneDriveUploadRequest: cannot restart because stream couldn't seek(0)");
finishError(Networking::ErrorResponse(this, false, true, "", -1));
}
_ignoreCallback = false;
uploadNextPart();
}
void OneDriveUploadRequest::uploadNextPart() {
const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024;
if (_uploadUrl == "" && _contentsStream->size() > UPLOAD_PER_ONE_REQUEST) {
Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+_savePath+":/upload.createSession"; //folder must exist
Networking::JsonCallback callback = new Common::Callback<OneDriveUploadRequest, Networking::JsonResponse>(this, &OneDriveUploadRequest::partUploadedCallback);
Networking::ErrorCallback failureCallback = new Common::Callback<OneDriveUploadRequest, Networking::ErrorResponse>(this, &OneDriveUploadRequest::partUploadedErrorCallback);
Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str());
request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->setBuffer(new byte[1], 0); //use POST
_workingRequest = ConnMan.addRequest(request);
return;
}
Common::String url;
if (_uploadUrl == "") {
url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+_savePath+":/content";
} else {
url = _uploadUrl;
}
Networking::JsonCallback callback = new Common::Callback<OneDriveUploadRequest, Networking::JsonResponse>(this, &OneDriveUploadRequest::partUploadedCallback);
Networking::ErrorCallback failureCallback = new Common::Callback<OneDriveUploadRequest, Networking::ErrorResponse>(this, &OneDriveUploadRequest::partUploadedErrorCallback);
Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str());
request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->usePut();
uint32 oldPos = _contentsStream->pos();
byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST];
uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST);
request->setBuffer(buffer, size);
//request->addHeader(Common::String::format("Content-Length: %u", size));
if (_uploadUrl != "")
request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos()-1, _contentsStream->size())); ;
_workingRequest = ConnMan.addRequest(request);
}
void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
Networking::ErrorResponse error(this, false, true, "", -1);
Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request;
if (rq && rq->getNetworkReadStream())
error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
Common::JSONValue *json = response.value;
if (json) {
if (json->isObject()) {
Common::JSONObject object = json->asObject();
if (object.contains("error")) {
warning("OneDrive returned error: %s", json->stringify(true).c_str());
delete json;
error.response = json->stringify(true);
finishError(error);
return;
}
if (object.contains("id") && object.contains("name")) {
//finished
Common::String path = _savePath; //object.getVal("name")->asString();; //object.getVal("id")->asString();
uint32 size = object.getVal("size")->asIntegerNumber();
uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString());
finishSuccess(StorageFile(path, size, timestamp, false));
return;
}
if (_uploadUrl == "") {
if (object.contains("uploadUrl"))
_uploadUrl = object.getVal("uploadUrl")->asString();
else
warning("no uploadUrl found in OneDrive's response");
}
}
if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) {
warning("no file info to return");
finishSuccess(StorageFile(_savePath, 0, 0, false));
} else {
uploadNextPart();
}
} else {
warning("null, not json");
finishError(error);
}
delete json;
}
void OneDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
finishError(error);
}
void OneDriveUploadRequest::handle() {}
void OneDriveUploadRequest::restart() { start(); }
void OneDriveUploadRequest::finishSuccess(StorageFile file) {
Request::finishSuccess();
if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file));
}
} // End of namespace OneDrive
} // End of namespace Cloud

View file

@ -0,0 +1,61 @@
/* 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_CLOUD_ONEDRIVE_ONEDRIVEUPLOADREQUEST_H
#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVEUPLOADREQUEST_H
#include "backends/cloud/storage.h"
#include "backends/networking/curl/curljsonrequest.h"
#include "backends/networking/curl/request.h"
#include "common/callback.h"
namespace Cloud {
namespace OneDrive {
class OneDriveStorage;
class OneDriveUploadRequest: public Networking::Request {
OneDriveStorage *_storage;
Common::String _savePath;
Common::SeekableReadStream *_contentsStream;
Storage::UploadCallback _uploadCallback;
Request *_workingRequest;
bool _ignoreCallback;
Common::String _uploadUrl;
void start();
void uploadNextPart();
void partUploadedCallback(Networking::JsonResponse response);
void partUploadedErrorCallback(Networking::ErrorResponse error);
void finishSuccess(StorageFile status);
public:
OneDriveUploadRequest(OneDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
virtual ~OneDriveUploadRequest();
virtual void handle();
virtual void restart();
};
} // End of namespace OneDrive
} // End of namespace Cloud
#endif

View file

@ -0,0 +1,42 @@
/* 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/file.h"
namespace Cloud {
Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
Common::File *f = new Common::File();
if (!f->open(localPath)) {
warning("Storage: unable to open file to upload from");
if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1));
delete errorCallback;
delete callback;
delete f;
return nullptr;
}
return upload(remotePath, f, callback, errorCallback);
}
} // End of namespace Cloud

View file

@ -77,7 +77,7 @@ public:
/** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
/** Returns pointer to Networking::NetworkReadStream. */
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0;

View file

@ -23,6 +23,7 @@ ifdef USE_CLOUD
MODULE_OBJS += \
cloud/iso8601.o \
cloud/manager.o \
cloud/storage.o \
cloud/storagefile.o \
cloud/downloadrequest.o \
cloud/folderdownloadrequest.o \
@ -32,7 +33,8 @@ MODULE_OBJS += \
cloud/dropbox/dropboxuploadrequest.o \
cloud/onedrive/onedrivestorage.o \
cloud/onedrive/onedrivetokenrefresher.o \
cloud/onedrive/onedrivelistdirectoryrequest.o
cloud/onedrive/onedrivelistdirectoryrequest.o \
cloud/onedrive/onedriveuploadrequest.o
endif
ifdef USE_LIBCURL

View file

@ -31,7 +31,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) {}
Request(cb, ecb), _url(url), _stream(nullptr), _headersList(nullptr), _bytesBuffer(nullptr), _bytesBufferSize(0), _uploading(false) {}
CurlRequest::~CurlRequest() {
delete _stream;
@ -40,8 +40,8 @@ CurlRequest::~CurlRequest() {
NetworkReadStream *CurlRequest::makeStream() {
if (_bytesBuffer)
return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, true);
return new NetworkReadStream(_url.c_str(), _headersList, _postFields);
return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, _uploading, true);
return new NetworkReadStream(_url.c_str(), _headersList, _postFields, _uploading);
}
@ -97,6 +97,8 @@ void CurlRequest::setBuffer(byte *buffer, uint32 size) {
_bytesBufferSize = size;
}
void CurlRequest::usePut() { _uploading = true; }
NetworkReadStreamResponse CurlRequest::execute() {
if (!_stream) {
_stream = makeStream();

View file

@ -44,6 +44,7 @@ protected:
Common::String _postFields;
byte *_bytesBuffer;
uint32 _bytesBufferSize;
bool _uploading; //using PUT method
virtual NetworkReadStream *makeStream();
@ -66,6 +67,9 @@ public:
/** Sets bytes buffer. */
virtual void setBuffer(byte *buffer, uint32 size);
/** Remembers to use PUT method when it would create NetworkReadStream. */
virtual void usePut();
/**
* Starts this Request with ConnMan.
* @return its NetworkReadStream in NetworkReadStreamResponse.

View file

@ -35,11 +35,17 @@ static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) {
return 0;
}
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields):
NetworkReadStream(url, headersList, (byte *)postFields.c_str(), postFields.size(), false) {}
static size_t curlReadDataCallback(char *d, size_t n, size_t l, void *p) {
NetworkReadStream *stream = (NetworkReadStream *)p;
if (stream) return stream->fillWithSendingContents(d, n*l);
return 0;
}
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool post) :
_easy(0), _eos(false), _requestComplete(false) {
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading):
NetworkReadStream(url, headersList, (byte *)postFields.c_str(), postFields.size(), uploading, false) {}
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool uploading, bool post):
_easy(0), _eos(false), _requestComplete(false), _sendingContentsBuffer(nullptr), _sendingContentsSize(0), _sendingContentsPos(0) {
_easy = curl_easy_init();
curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback);
curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us
@ -49,10 +55,18 @@ NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, b
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);
if (uploading) {
curl_easy_setopt(_easy, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(_easy, CURLOPT_READDATA, this);
curl_easy_setopt(_easy, CURLOPT_READFUNCTION, curlReadDataCallback);
_sendingContentsBuffer = buffer;
_sendingContentsSize = bufferSize;
} else {
if (post || bufferSize != 0) {
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, bufferSize);
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, buffer);
}
}
ConnMan.registerEasyHandle(_easy);
}
@ -87,4 +101,14 @@ long NetworkReadStream::httpResponseCode() const {
return responseCode;
}
uint32 NetworkReadStream::fillWithSendingContents(char *bufferToFill, uint32 maxSize) {
uint32 size = _sendingContentsSize - _sendingContentsPos;
if (size > maxSize) size = maxSize;
for (uint32 i = 0; i < size; ++i) {
bufferToFill[i] = _sendingContentsBuffer[_sendingContentsPos + i];
}
_sendingContentsPos += size;
return size;
}
} // End of namespace Cloud

View file

@ -35,10 +35,13 @@ namespace Networking {
class NetworkReadStream: public Common::MemoryReadWriteStream {
CURL *_easy;
bool _eos, _requestComplete;
byte *_sendingContentsBuffer;
uint32 _sendingContentsSize;
uint32 _sendingContentsPos;
public:
NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields);
NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool post = true);
NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false);
NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool uploading = false, bool post = true);
virtual ~NetworkReadStream();
/**
@ -82,6 +85,15 @@ public:
* @note This method should be called when eos() == true.
*/
long httpResponseCode() const;
/**
* Fills the passed buffer with _sendingContentsBuffer contents.
* It works similarly to read(), expect it's not for reading
* Stream's contents, but for sending our own data to the server.
*
* @returns how many bytes were actually read (filled in)
*/
uint32 fillWithSendingContents(char *bufferToFill, uint32 maxSize);
};
} // End of namespace Networking