Skip to content

Commit

Permalink
make valijson optional via define
Browse files Browse the repository at this point in the history
also minor docs cleanup
  • Loading branch information
black-sliver committed Feb 2, 2024
1 parent addadfe commit deb1234
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 12 deletions.
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ C++ Archipelago multiworld randomizer client library. See [archipelago.gg](https
* add dependencies to your project
* [nlohmann/json](https://github.com/nlohmann/json)
* [tristanpenman/valijson](https://github.com/tristanpenman/valijson)
(unless disabled, see [Build Configuration](#build-configuration))
* [black-sliver/wswrap](https://github.com/black-sliver/wswrap)
* for desktop: [zaphoyd/websocketpp](https://github.com/zaphoyd/websocketpp)
* for desktop: asio (and define ASIO_STANDALONE) or boost::asio
Expand All @@ -42,16 +43,29 @@ C++ Archipelago multiworld randomizer client library. See [archipelago.gg](https
* remove calls to `save_data_package` and don't save data package in `set_data_package_changed_handler`
* you can still use `set_data_package` or `set_data_package_from_file` during migration to make use of the old cache
(they are marked as deprecated and will go away in the next version)
* see [ap-soeclient](https://github.com/black-sliver/ap-soeclient) for an example
* see [Implementations](#implementations) for examples
* see [Gotchas](#gotchas)


## Additional Configuration
## Build Configuration

* use `-DWSWRAP_SEND_EXCEPTIONS` or `#define WSWRAP_SEND_EXCEPTIONS` before including anything to get exceptions when
a send fails
* use `-DAP_NO_DEFAULT_DATA_PACKAGE_STORE` or `#define AP_NO_DEFAULT_DATA_PACKAGE_STORE` before including to not use
DefaultDataPackageStore automatically.
Some features/behaviors can be disabled/switched using compile time definitions.

Use
`-D<definition>` (gcc, clang),
`add_compile_definitions(<definition>)` (cmake),
`project properties -> C/C++ -> Preprocessor -> Preprocessor Definitions` (VS),
`/D<definition>` (vc command line) or
`#define <definition>` (in code, before include).

* `ASIO_STANDALONE` to use asio/`asio.hpp` directly, not via boost.
* `APCLIENT_DEBUG` write debug output to stdout.
* `AP_NO_DEFAULT_DATA_PACKAGE_STORE` to not use DefaultDataPackageStore automatically.
* `AP_NO_SCHEMA` disables schema validation.
It's not required, shrinks the built binary and removes dependency on valijson.
* `AP_PREFER_UNENCRYPTED` try unencrypted connection first. Only useful for testing.
* `WSWRAP_SEND_EXCEPTIONS` to get exceptions when a send fails.
* `WSWRAP_NO_SSL` to disable SSL support. Only recommended for testing.


## When using Visual Studio for building
Expand All @@ -63,7 +77,8 @@ C++ Archipelago multiworld randomizer client library. See [archipelago.gg](https
* Add subprojects\websocketpp
* Add subprojects\wswrap\include
* Add subprojects\json\include
* Add subprojects\valijson\include
* Add subprojects\valijson\include
(unless disabled, see [Build Configuration](#build-configuration))
* Add `/Zc:__cplusplus` to the command line
* project properties -> C/C++ -> Command Line -> Additional Options
* Add `_WIN32_WINNT=0x0600` (or higher) to Preprocessor Definitions
Expand Down
26 changes: 21 additions & 5 deletions apclient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#endif


//#define APCLIENT_DEBUG // to get debug output
//#define AP_NO_DEFAULT_DATA_PACKAGE_STORE // to disable auto-construction of data package store
//#define AP_NO_SCHEMA // to disable schema checking
//#define AP_PREFER_UNENCRYPTED // try unencrypted connection first, then encrypted


#include <wswrap.hpp>
#include <string>
#include <list>
Expand All @@ -36,10 +42,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#endif

#include <nlohmann/json.hpp>
#ifndef AP_NO_SCHEMA
#include <valijson/adapters/nlohmann_json_adapter.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validator.hpp>
#endif
#include <chrono>
#include <stdint.h>
#include <inttypes.h>
Expand All @@ -52,10 +60,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#endif


//#define APCLIENT_DEBUG // to get debug output
//#define AP_NO_DEFAULT_DATA_PACKAGE_STORE // to disable auto-construction of data package store


/**
* Abstract data package storage handler.
*
Expand Down Expand Up @@ -89,8 +93,10 @@ class APDataPackageStore {
class APClient {
protected:
typedef nlohmann::json json;
typedef valijson::adapters::NlohmannJsonAdapter JsonSchemaAdapter;
typedef wswrap::WS WS;
#ifndef AP_NO_SCHEMA
typedef valijson::adapters::NlohmannJsonAdapter JsonSchemaAdapter;
#endif

static int64_t stoi64(const std::string& s) {
return std::stoll(s);
Expand Down Expand Up @@ -176,10 +182,14 @@ class APClient {
{"version", -1},
{"games", json(json::value_t::object)},
};

#ifndef AP_NO_SCHEMA
valijson::SchemaParser parser;
parser.populateSchema(JsonSchemaAdapter(_packetSchemaJson), _packetSchema);
parser.populateSchema(JsonSchemaAdapter(_retrievedSchemaJson), _commandSchemas["Retrieved"]);
parser.populateSchema(JsonSchemaAdapter(_setReplySchemaJson), _commandSchemas["SetReply"]);
#endif

connect_socket();
}

Expand Down Expand Up @@ -1182,20 +1192,24 @@ class APClient {
{
try {
json packet = json::parse(s);
#ifndef AP_NO_SCHEMA
valijson::Validator validator;
JsonSchemaAdapter packetAdapter(packet);
if (!validator.validate(_packetSchema, packetAdapter, nullptr)) {
throw std::runtime_error("Packet validation failed");
}
#endif
for (auto& command: packet) {
std::string cmd = command["cmd"];
#ifndef AP_NO_SCHEMA
JsonSchemaAdapter commandAdapter(command);
auto schemaIt = _commandSchemas.find(cmd);
if (schemaIt != _commandSchemas.end()) {
if (!validator.validate(schemaIt->second, commandAdapter, nullptr)) {
throw std::runtime_error("Command validation failed");
}
}
#endif
#ifdef APCLIENT_DEBUG
const size_t maxDumpLen = 512;
auto dump = command.dump().substr(0, maxDumpLen);
Expand Down Expand Up @@ -1644,6 +1658,7 @@ class APClient {
#endif
std::map<int, NetworkSlot> _slotInfo;

#ifndef AP_NO_SCHEMA
const json _packetSchemaJson = R"({
"type": "array",
"items": {
Expand Down Expand Up @@ -1671,6 +1686,7 @@ class APClient {
"required": [ "key", "value" ]
})"_json;
std::map<std::string, valijson::Schema> _commandSchemas;
#endif
};

#endif // _APCLIENT_HPP

0 comments on commit deb1234

Please sign in to comment.