First server executable

This commit is contained in:
2026-06-22 13:20:10 +03:00
parent ea99e81dbf
commit 6ff7c8a6cb
8 changed files with 245 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
server
*.json

7
Makefile Normal file
View File

@@ -0,0 +1,7 @@
srcs += main.cpp
srcs += helpers.cpp
all:
g++ ${srcs} -o server
.PHONY: all

View File

@@ -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
### JSON

10
config_example.json Normal file
View 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
View File

101
helpers.cpp Normal file
View 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
View 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
View 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;
}