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