Changeset View
Changeset View
Standalone View
Standalone View
source/rdb/RdbClient.h
/* Copyright (C) 2018 Wildfire Games. | |||||
* This file is part of 0 A.D. | |||||
* | |||||
* 0 A.D. 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. | |||||
* | |||||
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef XXRDBCLIENT_H | |||||
#define XXRDBCLIENT_H | |||||
#include "IRdbClient.h" | |||||
#include "Enums.h" | |||||
#include <thread> | |||||
#include <vector> | |||||
#include <memory> | |||||
#include <deque> | |||||
#include <utility> | |||||
#include <boost/asio.hpp> | |||||
#include <boost/asio/ssl.hpp> | |||||
#include <rapidjson/document.h> | |||||
class ScriptInterface; | |||||
struct Message | |||||
{ | |||||
virtual ~Message() {} | |||||
virtual RdbEnums::MessageType type() = 0; | |||||
virtual std::string encode() = 0; | |||||
static std::shared_ptr<Message> decode(std::string json); | |||||
}; | |||||
namespace MessageStructs { | |||||
struct ReplayData { | |||||
uint64_t m_id; | |||||
uint64_t m_submitterId; | |||||
boost::optional<uint64_t> m_submissionDate; | |||||
boost::optional<std::string> m_title; | |||||
boost::optional<std::string> m_msgBody; | |||||
RdbEnums::ReplayReviewStatus m_reviewStatus; | |||||
boost::optional<std::string> m_metadata; | |||||
boost::optional<std::string> m_replayDataEdgeLines; | |||||
boost::optional<std::string> m_replayDataFull; | |||||
}; | |||||
struct ReplayDatas : public Message { | |||||
ReplayDatas(rapidjson::Document& doc); | |||||
ReplayDatas() {} | |||||
virtual inline RdbEnums::MessageType type() { return RdbEnums::MessageType::ReplayDatas; } | |||||
virtual std::string encode(); | |||||
JS::Value toJS(const ScriptInterface& scriptInterface); | |||||
std::vector<ReplayData> m_replays; | |||||
}; | |||||
struct Error : public Message | |||||
{ | |||||
Error(rapidjson::Document& doc); | |||||
Error() {} | |||||
virtual inline RdbEnums::MessageType type() { return RdbEnums::MessageType::Error; } | |||||
virtual std::string encode(); | |||||
inline std::string error() { return m_msg; } | |||||
std::string m_msg; | |||||
}; | |||||
struct Success : public Message | |||||
{ | |||||
virtual inline RdbEnums::MessageType type() { return RdbEnums::MessageType::Success; } | |||||
virtual std::string encode(); | |||||
}; | |||||
struct QueryForReplayList : public Message | |||||
{ | |||||
QueryForReplayList() {} | |||||
virtual inline RdbEnums::MessageType type() { return RdbEnums::MessageType::QueryForReplayList; } | |||||
virtual std::string encode(); | |||||
uint64_t m_offset; | |||||
uint64_t m_numb; | |||||
boost::optional<uint64_t> m_replayId; | |||||
RdbEnums::SortMethod m_sortMethod; | |||||
bool m_dirAccending; | |||||
bool m_singleplayer; | |||||
bool m_multiplayer; | |||||
bool m_ratedGame; | |||||
bool m_unratedGame; | |||||
boost::optional<std::string> m_timestampDay; | |||||
boost::optional<std::string> m_submitter; | |||||
boost::optional<std::string> m_players; | |||||
boost::optional<std::string> m_mapName; | |||||
boost::optional<uint16_t> m_sizeMin; | |||||
boost::optional<uint16_t> m_sizeMax; | |||||
boost::optional<uint16_t> m_populationMin; | |||||
boost::optional<uint16_t> m_populationMax; | |||||
boost::optional<uint32_t> m_durationMin; | |||||
boost::optional<uint32_t> m_durationMax; | |||||
boost::optional<std::string> m_victoryCondition; | |||||
std::string m_engineVersion; | |||||
std::vector<std::vector<std::string>> m_mods; | |||||
bool m_getReplayTitle; | |||||
bool m_getReplayMsg; | |||||
bool m_getMetadata; | |||||
bool m_getReplayDataFull; | |||||
bool m_getReplayDataEdgeLines; | |||||
bool m_getReplaySubmissionDate; | |||||
}; | |||||
struct QueryForReplayDatas : public Message | |||||
{ | |||||
QueryForReplayDatas() {} | |||||
virtual inline RdbEnums::MessageType type() { return RdbEnums::MessageType::QueryForReplayDatas; } | |||||
virtual std::string encode(); | |||||
std::vector<uint64_t> m_replayIds; | |||||
bool m_getReplayTitle; | |||||
bool m_getReplayMsg; | |||||
bool m_getMetadata; | |||||
bool m_getReplayDataFull; | |||||
bool m_getReplayDataEdgeLines; | |||||
bool m_getReplaySubmissionDate; | |||||
}; | |||||
struct Login : public Message | |||||
{ | |||||
Login(rapidjson::Document& doc, bool regOpt); | |||||
Login() {} | |||||
virtual inline RdbEnums::MessageType type() { return m_regOpt ? RdbEnums::MessageType::Register : RdbEnums::MessageType::Login; } | |||||
virtual std::string encode(); | |||||
std::string m_username; | |||||
std::string m_password; | |||||
bool m_regOpt; | |||||
uint64_t m_version; | |||||
}; | |||||
} | |||||
class RdbConnection | |||||
{ | |||||
NONCOPYABLE(RdbConnection); | |||||
private: | |||||
boost::asio::io_service& m_ioService; | |||||
boost::asio::ssl::context m_context{boost::asio::ssl::context::tlsv12_client}; | |||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> m_socket; | |||||
std::deque<std::shared_ptr<Message>> m_sendingMsgs; | |||||
std::vector<uint8_t> m_curSendMsg; | |||||
std::deque<std::shared_ptr<Message>> m_sentMsgs; | |||||
std::deque<std::shared_ptr<Message>> m_recvMsgs; | |||||
bool m_startSending = false; | |||||
bool m_closing = false; | |||||
bool m_paniced = false; | |||||
std::vector<uint64_t> m_nextSize; | |||||
std::vector<uint8_t> m_nextDataBuf; | |||||
public: | |||||
RdbConnection( | |||||
boost::asio::io_service& ioService, | |||||
boost::asio::ip::tcp::resolver::iterator endpointIter | |||||
); | |||||
void close(); | |||||
void send(std::shared_ptr<Message>); | |||||
bool requestComplete(int numb); | |||||
std::pair< | |||||
std::shared_ptr<Message>, | |||||
std::vector<std::shared_ptr<Message>> | |||||
> requestResponce(); | |||||
inline bool hasPaniced() { return m_paniced; } | |||||
private: | |||||
void panic(std::string err); | |||||
bool panicIfError(const boost::system::error_code& ec, std::size_t len, int line); | |||||
/* Start */ | |||||
void doConnect(boost::asio::ip::tcp::resolver::iterator endpointIter); | |||||
/* Send msgs */ | |||||
void doSends(); | |||||
/* Read msgs */ | |||||
void doRead(); | |||||
}; | |||||
class RdbClient : public IRdbClient | |||||
{ | |||||
NONCOPYABLE(RdbClient); | |||||
private: | |||||
boost::asio::io_service m_ioService; | |||||
boost::asio::ip::tcp::resolver m_resolver; | |||||
RdbConnection m_conn; | |||||
std::thread m_ioThread; | |||||
bool m_logingIn = true; | |||||
public: | |||||
// Basic | |||||
RdbClient(const std::string& username, const std::string& password, const bool regOpt = false); | |||||
virtual ~RdbClient(); | |||||
/* Messages */ | |||||
struct GUIMessage | |||||
{ | |||||
std::string m_type; | |||||
std::string m_level; | |||||
std::string m_property1Name; | |||||
std::string m_property1Value; | |||||
std::string m_property2Name; | |||||
std::string m_property2Value; | |||||
std::time_t m_time; | |||||
}; | |||||
JS::Value guiPollNewMessage(const ScriptInterface& scriptInterface); | |||||
void queryForReplayList( | |||||
uint64_t offset, | |||||
uint64_t numb, | |||||
boost::optional<uint64_t> replayId, | |||||
RdbEnums::SortMethod sortMethod, | |||||
bool dirAccending, | |||||
bool singleplayer, | |||||
bool multiplayer, | |||||
bool ratedGame, | |||||
bool unratedGame, | |||||
boost::optional<std::string> timestampDay, | |||||
boost::optional<std::string> submitter, | |||||
boost::optional<std::string> players, | |||||
boost::optional<std::string> mapName, | |||||
boost::optional<uint16_t> sizeMin, | |||||
boost::optional<uint16_t> sizeMax, | |||||
boost::optional<uint16_t> populationMin, | |||||
boost::optional<uint16_t> populationMax, | |||||
boost::optional<uint32_t> durationMin, | |||||
boost::optional<uint32_t> durationMax, | |||||
boost::optional<std::string> victoryCondition, | |||||
std::string engineVersion, | |||||
std::vector<std::vector<std::string>> mods, | |||||
bool getReplayTitle, | |||||
bool getReplayMsg, | |||||
bool getMetadata, | |||||
bool getReplayDataFull, | |||||
bool getReplayDataEdgeLines, | |||||
bool getReplaySubmissionDate | |||||
); | |||||
void queryForReplayDatas( | |||||
std::vector<uint64_t> replayIds, | |||||
bool getReplayTitle, | |||||
bool getReplayMsg, | |||||
bool getMetadata, | |||||
bool getReplayDataFull, | |||||
bool getReplayDataEdgeLines, | |||||
bool getReplaySubmissionDate | |||||
); | |||||
private: | |||||
JS::Value guiMessageToJSVal(const ScriptInterface& scriptInterface, const GUIMessage& message); | |||||
GUIMessage createGUIMessage( | |||||
const std::string& type, | |||||
const std::string& level = "", | |||||
const std::string& property1Name = "", | |||||
const std::string& property1Value = "", | |||||
const std::string& property2Name = "", | |||||
const std::string& property2Value = "", | |||||
const std::time_t time = std::time(nullptr)); | |||||
}; | |||||
#endif // XXRDBCLIENT_H |
Wildfire Games · Phabricator