First server executable
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
server
|
||||||
|
*.json
|
||||||
7
Makefile
Normal file
7
Makefile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
srcs += main.cpp
|
||||||
|
srcs += helpers.cpp
|
||||||
|
|
||||||
|
all:
|
||||||
|
g++ ${srcs} -o server
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
12
README.md
12
README.md
@@ -1,3 +1,15 @@
|
|||||||
|
# Required packages for building (Ubuntu 24.04)
|
||||||
|
`build-essential`
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
### Configuration
|
||||||
|
Use file named `config.json` in working directory or supply your own via first argument.
|
||||||
|
For configuration example see `config_example.json`.
|
||||||
|
|
||||||
|
### Devices
|
||||||
|
Use file named `devices.json` in working directory or supply your own via configuration file.
|
||||||
|
**Note: This file will be managed by the server when devices successfully register.**
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
|
|
||||||
### JSON
|
### JSON
|
||||||
|
|||||||
10
config_example.json
Normal file
10
config_example.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
// Required
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 0,
|
||||||
|
|
||||||
|
// Optional
|
||||||
|
"devices_filename": "devices.json",
|
||||||
|
"cert_file": "path/to/file",
|
||||||
|
"key_file": "path/to/file"
|
||||||
|
}
|
||||||
0
devices_example.json
Normal file
0
devices_example.json
Normal file
101
helpers.cpp
Normal file
101
helpers.cpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
using std::endl;
|
||||||
|
using std::ifstream;
|
||||||
|
using std::istream;
|
||||||
|
using std::ostream;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
bool read_config_json(json& cfg, const string& filename, ostream* log)
|
||||||
|
{
|
||||||
|
ifstream cfg_file(filename);
|
||||||
|
|
||||||
|
if (!cfg_file.is_open())
|
||||||
|
{
|
||||||
|
if (nullptr != log)
|
||||||
|
{
|
||||||
|
*log << "Could not open config file" << endl;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return read_config_json(cfg, cfg_file, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_config_json(json& cfg, istream& in, ostream* log)
|
||||||
|
{
|
||||||
|
// Parse with comments
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cfg = json::parse(in, nullptr, true, true);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
if (nullptr != log)
|
||||||
|
{
|
||||||
|
*log << e.what() << endl;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_extract(const json& j, const string& key, string& out)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (j.contains(key) && j[key].is_string())
|
||||||
|
{
|
||||||
|
out = j[key];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_extract(const json& j, const string& key, int& out)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (j.contains(key) && j[key].is_number_integer())
|
||||||
|
{
|
||||||
|
out = j[key];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_extract(const json& j, const string& key, bool& out)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (j.contains(key) && j[key].is_boolean())
|
||||||
|
{
|
||||||
|
out = j[key];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_extract(const json& j, const string& key, uint16_t& out)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (j.contains(key) && j[key].is_number_integer())
|
||||||
|
{
|
||||||
|
if ((j[key] >= 0) && (j[key] <= UINT16_MAX))
|
||||||
|
{
|
||||||
|
out = j[key];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
34
helpers.h
Normal file
34
helpers.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef HELPERS_H_
|
||||||
|
#define HELPERS_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
// Reads configuration json from supplied filename
|
||||||
|
// cfg - output json
|
||||||
|
// filename - filepath from which to read json
|
||||||
|
// log - ostream to log human readable errors to - can be nullptr
|
||||||
|
// Returns - true if read and parse is successful
|
||||||
|
bool read_config_json(nlohmann::json& cfg, const std::string& filename, std::ostream* log);
|
||||||
|
|
||||||
|
// Reads configuration json from supplied istream
|
||||||
|
// cfg - output json
|
||||||
|
// in - istream from which to read json
|
||||||
|
// log - ostream to log human readable errors to - can be nullptr
|
||||||
|
// Returns - true if read and parse is successful
|
||||||
|
bool read_config_json(nlohmann::json& cfg, std::istream& in, std::ostream* log);
|
||||||
|
|
||||||
|
// JSON Extraction Helpers
|
||||||
|
// out value is modified only if an extraction happened
|
||||||
|
// Returns - whether an extraction happened
|
||||||
|
bool json_extract(const nlohmann::json& j, const std::string& key, std::string& out);
|
||||||
|
bool json_extract(const nlohmann::json& j, const std::string& key, int& out);
|
||||||
|
bool json_extract(const nlohmann::json& j, const std::string& key, bool& out);
|
||||||
|
bool json_extract(const nlohmann::json& j, const std::string& key, uint16_t& out);
|
||||||
|
|
||||||
|
#endif // HELPERS_H_
|
||||||
79
main.cpp
Normal file
79
main.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "httplib.h"
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
string config_filename = "config.json";
|
||||||
|
string devices_filename = "devices.json";
|
||||||
|
string host = "";
|
||||||
|
string cert_file = "";
|
||||||
|
string key_file = "";
|
||||||
|
uint16_t port = 0;
|
||||||
|
shared_ptr<httplib::Server> server = nullptr;
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
json cfg;
|
||||||
|
|
||||||
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
config_filename = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = read_config_json(cfg, config_filename, &cout);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_extract(cfg, "devices_filename", devices_filename);
|
||||||
|
json_extract(cfg, "host", host);
|
||||||
|
json_extract(cfg, "port", port);
|
||||||
|
// json_extract(cfg, "cert_file", cert_file);
|
||||||
|
// json_extract(cfg, "key_file", cert_file);
|
||||||
|
|
||||||
|
if (host.empty())
|
||||||
|
{
|
||||||
|
cout << "host not provided" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == port)
|
||||||
|
{
|
||||||
|
cout << "port number not provided" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cert_file.empty() && !key_file.empty())
|
||||||
|
{
|
||||||
|
// TODO: Implement SSL Server Properly
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server = make_shared<httplib::Server>();
|
||||||
|
}
|
||||||
|
|
||||||
|
server->listen(host, port);
|
||||||
|
server->Get("/api/setup", [](const httplib::Request& req, httplib::Response& res)
|
||||||
|
{
|
||||||
|
cout << req.headers.size() << endl;
|
||||||
|
for (auto header : req.headers)
|
||||||
|
{
|
||||||
|
cout << header.first << ": " << header.second << endl;
|
||||||
|
}
|
||||||
|
res.status = 400;
|
||||||
|
});
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user