Initial re-upload of spice2x-24-08-24
This commit is contained in:
8
api/resources/cpp/README.md
Normal file
8
api/resources/cpp/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# SpiceAPI C++ Library
|
||||
This library is still a bit experimental and might contain bugs.
|
||||
|
||||
To include it into your project, it's recommended to just copy the
|
||||
files into your source directory.
|
||||
|
||||
To use the wrappers, RapidJSON is required and you might need to
|
||||
adjust the include paths for your project's build.
|
||||
24
api/resources/cpp/spiceapi/LICENSE
Normal file
24
api/resources/cpp/spiceapi/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
181
api/resources/cpp/spiceapi/connection.cpp
Normal file
181
api/resources/cpp/spiceapi/connection.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include <iostream>
|
||||
#include <ws2tcpip.h>
|
||||
#include "connection.h"
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
// settings
|
||||
static const size_t RECEIVE_BUFFER_SIZE = 64 * 1024;
|
||||
static const int RECEIVE_TIMEOUT = 1000;
|
||||
}
|
||||
|
||||
spiceapi::Connection::Connection(std::string host, uint16_t port, std::string password) {
|
||||
this->host = host;
|
||||
this->port = port;
|
||||
this->password = password;
|
||||
this->socket = INVALID_SOCKET;
|
||||
this->cipher = nullptr;
|
||||
|
||||
// WSA startup
|
||||
WSADATA wsa_data;
|
||||
int error = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if (error) {
|
||||
std::cerr << "Failed to start WSA: " << error << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
spiceapi::Connection::~Connection() {
|
||||
|
||||
// clean up
|
||||
if (this->cipher != nullptr)
|
||||
delete this->cipher;
|
||||
|
||||
// cleanup WSA
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
void spiceapi::Connection::cipher_alloc() {
|
||||
|
||||
// delete old cipher
|
||||
if (this->cipher != nullptr) {
|
||||
delete this->cipher;
|
||||
this->cipher = nullptr;
|
||||
}
|
||||
|
||||
// create new cipher if password is set
|
||||
if (this->password.length() > 0) {
|
||||
this->cipher = new RC4(
|
||||
(uint8_t *) this->password.c_str(),
|
||||
strlen(this->password.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
bool spiceapi::Connection::check() {
|
||||
int result = 0;
|
||||
|
||||
// check if socket is invalid
|
||||
if (this->socket == INVALID_SOCKET) {
|
||||
|
||||
// get all addresses
|
||||
addrinfo *addr_list;
|
||||
addrinfo hints{};
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
if ((result = getaddrinfo(
|
||||
this->host.c_str(),
|
||||
std::to_string(this->port).c_str(),
|
||||
&hints,
|
||||
&addr_list))) {
|
||||
std::cerr << "getaddrinfo failed: " << result << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check all addresses
|
||||
for (addrinfo *addr = addr_list; addr != NULL; addr = addr->ai_next) {
|
||||
|
||||
// try open socket
|
||||
this->socket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (this->socket == INVALID_SOCKET) {
|
||||
std::cerr << "socket failed: " << WSAGetLastError() << std::endl;
|
||||
freeaddrinfo(addr_list);
|
||||
return false;
|
||||
}
|
||||
|
||||
// try connect
|
||||
result = connect(this->socket, addr->ai_addr, (int) addr->ai_addrlen);
|
||||
if (result == SOCKET_ERROR) {
|
||||
closesocket(this->socket);
|
||||
this->socket = INVALID_SOCKET;
|
||||
continue;
|
||||
}
|
||||
|
||||
// configure socket
|
||||
int opt_val;
|
||||
opt_val = 1;
|
||||
setsockopt(this->socket, IPPROTO_TCP, TCP_NODELAY, (const char*) &opt_val, sizeof(opt_val));
|
||||
opt_val = RECEIVE_TIMEOUT;
|
||||
setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &opt_val, sizeof(opt_val));
|
||||
|
||||
// connection successful
|
||||
this->cipher_alloc();
|
||||
break;
|
||||
}
|
||||
|
||||
// check if successful
|
||||
freeaddrinfo(addr_list);
|
||||
if (this->socket == INVALID_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// socket probably still valid
|
||||
return true;
|
||||
}
|
||||
|
||||
void spiceapi::Connection::change_pass(std::string password) {
|
||||
this->password = password;
|
||||
this->cipher_alloc();
|
||||
}
|
||||
|
||||
std::string spiceapi::Connection::request(std::string json) {
|
||||
|
||||
// check connection
|
||||
if (!this->check())
|
||||
return "";
|
||||
|
||||
// crypt
|
||||
auto json_len = strlen(json.c_str()) + 1;
|
||||
uint8_t* json_data = new uint8_t[json_len];
|
||||
memcpy(json_data, json.c_str(), json_len);
|
||||
if (this->cipher != nullptr)
|
||||
this->cipher->crypt(json_data, json_len);
|
||||
|
||||
// send
|
||||
auto send_result = send(this->socket, (const char*) json_data, (int) json_len, 0);
|
||||
delete[] json_data;
|
||||
if (send_result == SOCKET_ERROR || send_result < (int) json_len) {
|
||||
closesocket(this->socket);
|
||||
this->socket = INVALID_SOCKET;
|
||||
return "";
|
||||
}
|
||||
|
||||
// receive
|
||||
uint8_t receive_data[RECEIVE_BUFFER_SIZE];
|
||||
size_t receive_data_len = 0;
|
||||
int receive_result;
|
||||
while ((receive_result = recv(
|
||||
this->socket,
|
||||
(char*) &receive_data[receive_data_len],
|
||||
sizeof(receive_data) - receive_data_len, 0)) > 0) {
|
||||
|
||||
// check for buffer overflow
|
||||
if (receive_data_len + receive_result >= sizeof(receive_data)) {
|
||||
closesocket(this->socket);
|
||||
this->socket = INVALID_SOCKET;
|
||||
return "";
|
||||
}
|
||||
|
||||
// crypt
|
||||
if (this->cipher != nullptr)
|
||||
this->cipher->crypt(&receive_data[receive_data_len], (size_t) receive_result);
|
||||
|
||||
// increase received data length
|
||||
receive_data_len += receive_result;
|
||||
|
||||
// check for message end
|
||||
if (receive_data[receive_data_len - 1] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// return resulting json
|
||||
if (receive_data_len > 0) {
|
||||
return std::string((const char *) &receive_data[0], receive_data_len - 1);
|
||||
} else {
|
||||
|
||||
// receive error
|
||||
this->socket = INVALID_SOCKET;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
31
api/resources/cpp/spiceapi/connection.h
Normal file
31
api/resources/cpp/spiceapi/connection.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SPICEAPI_CONNECTION_H
|
||||
#define SPICEAPI_CONNECTION_H
|
||||
|
||||
#include <string>
|
||||
#include <winsock2.h>
|
||||
#include "rc4.h"
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
class Connection {
|
||||
private:
|
||||
std::string host;
|
||||
uint16_t port;
|
||||
std::string password;
|
||||
SOCKET socket;
|
||||
RC4* cipher;
|
||||
|
||||
void cipher_alloc();
|
||||
|
||||
public:
|
||||
Connection(std::string host, uint16_t port, std::string password = "");
|
||||
~Connection();
|
||||
|
||||
bool check();
|
||||
void change_pass(std::string password);
|
||||
std::string request(std::string json);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_CONNECTION_H
|
||||
45
api/resources/cpp/spiceapi/rc4.cpp
Normal file
45
api/resources/cpp/spiceapi/rc4.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "rc4.h"
|
||||
#include <iterator>
|
||||
|
||||
spiceapi::RC4::RC4(uint8_t *key, size_t key_size) {
|
||||
|
||||
// initialize S-BOX
|
||||
for (size_t i = 0; i < std::size(s_box); i++)
|
||||
s_box[i] = (uint8_t) i;
|
||||
|
||||
// check key size
|
||||
if (!key_size)
|
||||
return;
|
||||
|
||||
// KSA
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < std::size(s_box); i++) {
|
||||
|
||||
// update
|
||||
j = (j + s_box[i] + key[i % key_size]) % std::size(s_box);
|
||||
|
||||
// swap
|
||||
auto tmp = s_box[i];
|
||||
s_box[i] = s_box[j];
|
||||
s_box[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void spiceapi::RC4::crypt(uint8_t *data, size_t size) {
|
||||
|
||||
// iterate all bytes
|
||||
for (size_t pos = 0; pos < size; pos++) {
|
||||
|
||||
// update
|
||||
a = (a + 1) % std::size(s_box);
|
||||
b = (b + s_box[a]) % std::size(s_box);
|
||||
|
||||
// swap
|
||||
auto tmp = s_box[a];
|
||||
s_box[a] = s_box[b];
|
||||
s_box[b] = tmp;
|
||||
|
||||
// crypt
|
||||
data[pos] ^= s_box[(s_box[a] + s_box[b]) % std::size(s_box)];
|
||||
}
|
||||
}
|
||||
21
api/resources/cpp/spiceapi/rc4.h
Normal file
21
api/resources/cpp/spiceapi/rc4.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef SPICEAPI_RC4_H
|
||||
#define SPICEAPI_RC4_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
class RC4 {
|
||||
private:
|
||||
uint8_t s_box[256];
|
||||
size_t a = 0, b = 0;
|
||||
|
||||
public:
|
||||
|
||||
RC4(uint8_t *key, size_t key_size);
|
||||
|
||||
void crypt(uint8_t *data, size_t size);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_RC4_H
|
||||
638
api/resources/cpp/spiceapi/wrappers.cpp
Normal file
638
api/resources/cpp/spiceapi/wrappers.cpp
Normal file
@@ -0,0 +1,638 @@
|
||||
#include "wrappers.h"
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
* RapidJSON dependency
|
||||
* You might need to adjust the paths when importing into your own project.
|
||||
*/
|
||||
#include "external/rapidjson/document.h"
|
||||
#include "external/rapidjson/writer.h"
|
||||
using namespace rapidjson;
|
||||
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
static inline std::string doc2str(Document &doc) {
|
||||
StringBuffer sb;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
|
||||
doc.Accept(writer);
|
||||
return sb.GetString();
|
||||
}
|
||||
|
||||
static inline Document request_gen(const char *module, const char *function) {
|
||||
|
||||
// create document
|
||||
Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
// add attributes
|
||||
auto &alloc = doc.GetAllocator();
|
||||
doc.AddMember("id", msg_gen_id(), alloc);
|
||||
doc.AddMember("module", StringRef(module), alloc);
|
||||
doc.AddMember("function", StringRef(function), alloc);
|
||||
|
||||
// add params
|
||||
Value noparam(kArrayType);
|
||||
doc.AddMember("params", noparam, alloc);
|
||||
|
||||
// return document
|
||||
return doc;
|
||||
}
|
||||
|
||||
static inline Document *response_get(std::string json) {
|
||||
|
||||
// parse document
|
||||
Document *doc = new Document();
|
||||
doc->Parse(json.c_str());
|
||||
|
||||
// check for parse error
|
||||
if (doc->HasParseError()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check id
|
||||
auto it_id = doc->FindMember("id");
|
||||
if (it_id == doc->MemberEnd() || !(*it_id).value.IsUint64()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check errors
|
||||
auto it_errors = doc->FindMember("errors");
|
||||
if (it_errors == doc->MemberEnd() || !(*it_errors).value.IsArray()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check error count
|
||||
if ((*it_errors).value.Size() > 0) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check data
|
||||
auto it_data = doc->FindMember("data");
|
||||
if (it_data == doc->MemberEnd() || !(*it_data).value.IsArray()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return document
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t spiceapi::msg_gen_id() {
|
||||
static uint64_t id_global = 0;
|
||||
|
||||
// check if global ID was initialized
|
||||
if (id_global == 0) {
|
||||
|
||||
// generate a new ID
|
||||
std::random_device rd;
|
||||
std::mt19937_64 gen(rd());
|
||||
std::uniform_int_distribution<uint64_t> dist(1, (uint64_t) std::llround(std::pow(2, 63)));
|
||||
id_global = dist(gen);
|
||||
|
||||
} else {
|
||||
|
||||
// increase by one
|
||||
id_global++;
|
||||
}
|
||||
|
||||
// return global ID
|
||||
return id_global;
|
||||
}
|
||||
|
||||
bool spiceapi::analogs_read(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
|
||||
auto req = request_gen("analogs", "read");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"];
|
||||
for (auto &val : data.GetArray()) {
|
||||
AnalogState state;
|
||||
state.name = val[0].GetString();
|
||||
state.value = val[1].GetFloat();
|
||||
states.push_back(state);
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::analogs_write(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
|
||||
auto req = request_gen("analogs", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
state_val.PushBack(state.value, alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::analogs_write_reset(spiceapi::Connection &con, std::vector<spiceapi::AnalogState> &states) {
|
||||
auto req = request_gen("analogs", "write_reset");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::buttons_read(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
|
||||
auto req = request_gen("buttons", "read");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"];
|
||||
for (auto &val : data.GetArray()) {
|
||||
ButtonState state;
|
||||
state.name = val[0].GetString();
|
||||
state.value = val[1].GetFloat();
|
||||
states.push_back(state);
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::buttons_write(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
|
||||
auto req = request_gen("buttons", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
state_val.PushBack(state.value, alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::buttons_write_reset(spiceapi::Connection &con, std::vector<spiceapi::ButtonState> &states) {
|
||||
auto req = request_gen("buttons", "write_reset");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::card_insert(spiceapi::Connection &con, size_t index, const char *card_id) {
|
||||
auto req = request_gen("card", "insert");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(index, alloc);
|
||||
params.PushBack(StringRef(card_id), alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::coin_get(Connection &con, int &coins) {
|
||||
auto req = request_gen("coin", "get");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
coins = (*res)["data"][0].GetInt();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::coin_set(Connection &con, int coins) {
|
||||
auto req = request_gen("coin", "set");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(coins, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::coin_insert(Connection &con, int coins) {
|
||||
auto req = request_gen("coin", "insert");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(coins, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::coin_blocker_get(Connection &con, bool &closed) {
|
||||
auto req = request_gen("coin", "blocker_get");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
closed = (*res)["data"][0].GetBool();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_raise(spiceapi::Connection &con, const char *signal) {
|
||||
auto req = request_gen("control", "raise");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(StringRef(signal), alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_exit(spiceapi::Connection &con) {
|
||||
auto req = request_gen("control", "exit");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_exit(spiceapi::Connection &con, int exit_code) {
|
||||
auto req = request_gen("control", "exit");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(exit_code, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_restart(spiceapi::Connection &con) {
|
||||
auto req = request_gen("control", "restart");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_session_refresh(spiceapi::Connection &con) {
|
||||
auto req = request_gen("control", "session_refresh");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto key = (*res)["data"][0].GetString();
|
||||
con.change_pass(key);
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_shutdown(spiceapi::Connection &con) {
|
||||
auto req = request_gen("control", "shutdown");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::control_reboot(spiceapi::Connection &con) {
|
||||
auto req = request_gen("control", "reboot");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::iidx_ticker_get(spiceapi::Connection &con, char *ticker) {
|
||||
auto req = request_gen("iidx", "ticker_get");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto data = (*res)["data"][0].GetString();
|
||||
strncpy(ticker, data, 9);
|
||||
ticker[9] = 0x00;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::iidx_ticker_set(spiceapi::Connection &con, const char *ticker) {
|
||||
auto req = request_gen("iidx", "ticker_set");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(StringRef(ticker), alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::iidx_ticker_reset(spiceapi::Connection &con) {
|
||||
auto req = request_gen("iidx", "ticker_reset");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::info_avs(spiceapi::Connection &con, spiceapi::InfoAvs &info) {
|
||||
auto req = request_gen("info", "avs");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"][0];
|
||||
info.model = data["model"].GetString();
|
||||
info.dest = data["dest"].GetString();
|
||||
info.spec = data["spec"].GetString();
|
||||
info.rev = data["rev"].GetString();
|
||||
info.ext = data["ext"].GetString();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::info_launcher(spiceapi::Connection &con, spiceapi::InfoLauncher &info) {
|
||||
auto req = request_gen("info", "launcher");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"][0];
|
||||
info.version = data["version"].GetString();
|
||||
info.compile_date = data["compile_date"].GetString();
|
||||
info.compile_time = data["compile_time"].GetString();
|
||||
info.system_time = data["system_time"].GetString();
|
||||
for (auto &arg : data["args"].GetArray())
|
||||
info.args.push_back(arg.GetString());
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::info_memory(spiceapi::Connection &con, spiceapi::InfoMemory &info) {
|
||||
auto req = request_gen("info", "memory");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"][0];
|
||||
info.mem_total = data["mem_total"].GetUint64();
|
||||
info.mem_total_used = data["mem_total_used"].GetUint64();
|
||||
info.mem_used = data["mem_used"].GetUint64();
|
||||
info.vmem_total = data["vmem_total"].GetUint64();
|
||||
info.vmem_total_used = data["vmem_total_used"].GetUint64();
|
||||
info.vmem_used = data["vmem_used"].GetUint64();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::keypads_write(spiceapi::Connection &con, unsigned int keypad, const char *input) {
|
||||
auto req = request_gen("keypads", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(keypad, alloc);
|
||||
params.PushBack(StringRef(input), alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::keypads_set(spiceapi::Connection &con, unsigned int keypad, std::vector<char> &keys) {
|
||||
auto req = request_gen("keypads", "set");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(keypad, alloc);
|
||||
for (auto &key : keys)
|
||||
params.PushBack(StringRef(&key, 1), alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::keypads_get(spiceapi::Connection &con, unsigned int keypad, std::vector<char> &keys) {
|
||||
auto req = request_gen("keypads", "get");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(keypad, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"];
|
||||
for (auto &val : data.GetArray())
|
||||
keys.push_back(val.GetString()[0]);
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::lights_read(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
|
||||
auto req = request_gen("lights", "read");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"];
|
||||
for (auto &val : data.GetArray()) {
|
||||
LightState state;
|
||||
state.name = val[0].GetString();
|
||||
state.value = val[1].GetFloat();
|
||||
states.push_back(state);
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::lights_write(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
|
||||
auto req = request_gen("lights", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
state_val.PushBack(state.value, alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::lights_write_reset(spiceapi::Connection &con, std::vector<spiceapi::LightState> &states) {
|
||||
auto req = request_gen("lights", "write_reset");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(StringRef(state.name.c_str()), alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::memory_write(spiceapi::Connection &con, const char *dll_name, const char *hex, uint32_t offset) {
|
||||
auto req = request_gen("memory", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(StringRef(dll_name), alloc);
|
||||
params.PushBack(StringRef(hex), alloc);
|
||||
params.PushBack(offset, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::memory_read(spiceapi::Connection &con, const char *dll_name, uint32_t offset, uint32_t size,
|
||||
std::string &hex) {
|
||||
auto req = request_gen("memory", "read");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(StringRef(dll_name), alloc);
|
||||
params.PushBack(offset, alloc);
|
||||
params.PushBack(size, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
hex = (*res)["data"][0].GetString();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::memory_signature(spiceapi::Connection &con, const char *dll_name, const char *signature,
|
||||
const char *replacement, uint32_t offset, uint32_t usage, uint32_t &file_offset) {
|
||||
auto req = request_gen("memory", "signature");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
params.PushBack(StringRef(dll_name), alloc);
|
||||
params.PushBack(StringRef(signature), alloc);
|
||||
params.PushBack(StringRef(replacement), alloc);
|
||||
params.PushBack(offset, alloc);
|
||||
params.PushBack(usage, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
file_offset = (*res)["data"][0].GetUint();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::touch_read(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
|
||||
auto req = request_gen("touch", "read");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"];
|
||||
for (auto &val : data.GetArray()) {
|
||||
TouchState state;
|
||||
state.id = val[0].GetUint64();
|
||||
state.x = val[1].GetInt64();
|
||||
state.y = val[2].GetInt64();
|
||||
states.push_back(state);
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::touch_write(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
|
||||
auto req = request_gen("touch", "write");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states) {
|
||||
Value state_val(kArrayType);
|
||||
state_val.PushBack(state.id, alloc);
|
||||
state_val.PushBack(state.x, alloc);
|
||||
state_val.PushBack(state.y, alloc);
|
||||
params.PushBack(state_val, alloc);
|
||||
}
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::touch_write_reset(spiceapi::Connection &con, std::vector<spiceapi::TouchState> &states) {
|
||||
auto req = request_gen("touch", "write_reset");
|
||||
auto &alloc = req.GetAllocator();
|
||||
Value params(kArrayType);
|
||||
for (auto &state : states)
|
||||
params.PushBack(state.id, alloc);
|
||||
req["params"] = params;
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spiceapi::lcd_info(spiceapi::Connection &con, spiceapi::LCDInfo &info) {
|
||||
auto req = request_gen("lcd", "info");
|
||||
auto res = response_get(con.request(doc2str(req)));
|
||||
if (!res)
|
||||
return false;
|
||||
auto &data = (*res)["data"][0];
|
||||
info.enabled = data["enabled"].GetBool();
|
||||
info.csm = data["csm"].GetString();
|
||||
info.bri = data["bri"].GetInt();
|
||||
info.con = data["con"].GetInt();
|
||||
info.bl = data["bl"].GetInt();
|
||||
info.red = data["red"].GetInt();
|
||||
info.green = data["green"].GetInt();
|
||||
info.blue = data["blue"].GetInt();
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
104
api/resources/cpp/spiceapi/wrappers.h
Normal file
104
api/resources/cpp/spiceapi/wrappers.h
Normal file
@@ -0,0 +1,104 @@
|
||||
#ifndef SPICEAPI_WRAPPERS_H
|
||||
#define SPICEAPI_WRAPPERS_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "connection.h"
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
struct AnalogState {
|
||||
std::string name;
|
||||
float value;
|
||||
};
|
||||
|
||||
struct ButtonState {
|
||||
std::string name;
|
||||
float value;
|
||||
};
|
||||
|
||||
struct LightState {
|
||||
std::string name;
|
||||
float value;
|
||||
};
|
||||
|
||||
struct InfoAvs {
|
||||
std::string model, dest, spec, rev, ext;
|
||||
};
|
||||
|
||||
struct InfoLauncher {
|
||||
std::string version;
|
||||
std::string compile_date, compile_time, system_time;
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
|
||||
struct InfoMemory {
|
||||
uint64_t mem_total, mem_total_used, mem_used;
|
||||
uint64_t vmem_total, vmem_total_used, vmem_used;
|
||||
};
|
||||
|
||||
struct TouchState {
|
||||
uint64_t id;
|
||||
int64_t x, y;
|
||||
};
|
||||
|
||||
struct LCDInfo {
|
||||
bool enabled;
|
||||
std::string csm;
|
||||
uint8_t bri, con, bl, red, green, blue;
|
||||
};
|
||||
|
||||
uint64_t msg_gen_id();
|
||||
|
||||
bool analogs_read(Connection &con, std::vector<AnalogState> &states);
|
||||
bool analogs_write(Connection &con, std::vector<AnalogState> &states);
|
||||
bool analogs_write_reset(Connection &con, std::vector<AnalogState> &states);
|
||||
|
||||
bool buttons_read(Connection &con, std::vector<ButtonState> &states);
|
||||
bool buttons_write(Connection &con, std::vector<ButtonState> &states);
|
||||
bool buttons_write_reset(Connection &con, std::vector<ButtonState> &states);
|
||||
|
||||
bool card_insert(Connection &con, size_t index, const char *card_id);
|
||||
|
||||
bool coin_get(Connection &con, int &coins);
|
||||
bool coin_set(Connection &con, int coins);
|
||||
bool coin_insert(Connection &con, int coins=1);
|
||||
bool coin_blocker_get(Connection &con, bool &closed);
|
||||
|
||||
bool control_raise(Connection &con, const char *signal);
|
||||
bool control_exit(Connection &con);
|
||||
bool control_exit(Connection &con, int exit_code);
|
||||
bool control_restart(Connection &con);
|
||||
bool control_session_refresh(Connection &con);
|
||||
bool control_shutdown(Connection &con);
|
||||
bool control_reboot(Connection &con);
|
||||
|
||||
bool iidx_ticker_get(Connection &con, char *ticker);
|
||||
bool iidx_ticker_set(Connection &con, const char *ticker);
|
||||
bool iidx_ticker_reset(Connection &con);
|
||||
|
||||
bool info_avs(Connection &con, InfoAvs &info);
|
||||
bool info_launcher(Connection &con, InfoLauncher &info);
|
||||
bool info_memory(Connection &con, InfoMemory &info);
|
||||
|
||||
bool keypads_write(Connection &con, unsigned int keypad, const char *input);
|
||||
bool keypads_set(Connection &con, unsigned int keypad, std::vector<char> &keys);
|
||||
bool keypads_get(Connection &con, unsigned int keypad, std::vector<char> &keys);
|
||||
|
||||
bool lights_read(Connection &con, std::vector<LightState> &states);
|
||||
bool lights_write(Connection &con, std::vector<LightState> &states);
|
||||
bool lights_write_reset(Connection &con, std::vector<LightState> &states);
|
||||
|
||||
bool memory_write(Connection &con, const char *dll_name, const char *hex, uint32_t offset);
|
||||
bool memory_read(Connection &con, const char *dll_name, uint32_t offset, uint32_t size, std::string &hex);
|
||||
bool memory_signature(Connection &con, const char *dll_name, const char *signature, const char *replacement,
|
||||
uint32_t offset, uint32_t usage, uint32_t &file_offset);
|
||||
|
||||
bool touch_read(Connection &con, std::vector<TouchState> &states);
|
||||
bool touch_write(Connection &con, std::vector<TouchState> &states);
|
||||
bool touch_write_reset(Connection &con, std::vector<TouchState> &states);
|
||||
|
||||
bool lcd_info(Connection &con, LCDInfo &info);
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_WRAPPERS_H
|
||||
Reference in New Issue
Block a user