mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Implemented basic authentication
Also fixed Tankers and AWACS which now operate as expected
This commit is contained in:
@@ -185,7 +185,7 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>include;..\..\third-party\base64\include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
||||
@@ -27,5 +27,7 @@ private:
|
||||
void task();
|
||||
|
||||
atomic<bool> runListener;
|
||||
|
||||
wstring password = L"";
|
||||
};
|
||||
|
||||
|
||||
@@ -96,14 +96,13 @@ public:
|
||||
void pushActivePathBack(Coords newActivePathBack);
|
||||
void popActivePathFront();
|
||||
void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));}
|
||||
void setIsTanker(bool newIsTanker) { isTanker = newIsTanker; addMeasure(L"isTanker", json::value(newIsTanker));}
|
||||
void setIsAWACS(bool newIsAWACS) { isAWACS = newIsAWACS; addMeasure(L"isAWACS", json::value(newIsAWACS));}
|
||||
void setTACANOn(bool newTACANOn);
|
||||
void setIsTanker(bool newIsTanker);
|
||||
void setIsAWACS(bool newIsAWACS);
|
||||
void setTACANChannel(int newTACANChannel);
|
||||
void setTACANXY(wstring newTACANXY);
|
||||
void setTACANCallsign(wstring newTACANCallsign);
|
||||
void setTACAN();
|
||||
void setRadioOn(bool newRadioOn);
|
||||
void setEPLRS(bool state);
|
||||
void setRadioFrequency(int newRadioFrequency);
|
||||
void setRadioCallsign(int newRadioCallsign);
|
||||
void setRadioCallsignNumber(int newRadioCallsignNumber);
|
||||
@@ -116,11 +115,9 @@ public:
|
||||
int getTargetID() { return targetID; }
|
||||
bool getIsTanker() { return isTanker; }
|
||||
bool getIsAWACS() { return isAWACS; }
|
||||
bool getTACANOn() { return TACANOn; }
|
||||
int getTACANChannel() { return TACANChannel; }
|
||||
wstring getTACANXY() { return TACANXY; }
|
||||
wstring getTACANCallsign() { return TACANCallsign; }
|
||||
bool getRadioOn() { return radioOn; }
|
||||
int getRadioFrequency() { return radioFrequency; }
|
||||
int getRadioCallsign() { return radioCallsign; }
|
||||
int getRadioCallsignNumber() { return radioCallsignNumber; }
|
||||
@@ -182,11 +179,9 @@ protected:
|
||||
int targetID = NULL;
|
||||
bool isTanker = false;
|
||||
bool isAWACS = false;
|
||||
bool TACANOn = false;
|
||||
int TACANChannel = 40;
|
||||
wstring TACANXY = L"X";
|
||||
wstring TACANCallsign = L"TKR";
|
||||
bool radioOn = false;
|
||||
int radioFrequency = 260000000; // MHz
|
||||
int radioCallsign = 1;
|
||||
int radioCallsignNumber = 1;
|
||||
|
||||
@@ -251,13 +251,11 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
unit->setIsTanker(value[L"isTanker"].as_bool());
|
||||
unit->setIsAWACS(value[L"isAWACS"].as_bool());
|
||||
|
||||
unit->setTACANOn(true); // TODO Remove
|
||||
unit->setTACANChannel(value[L"TACANChannel"].as_number().to_int32());
|
||||
unit->setTACANXY(value[L"TACANXY"].as_string());
|
||||
unit->setTACANCallsign(value[L"TACANCallsign"].as_string());
|
||||
unit->setTACAN();
|
||||
|
||||
unit->setRadioOn(true); // TODO Remove
|
||||
unit->setRadioFrequency(value[L"radioFrequency"].as_number().to_int32());
|
||||
unit->setRadioCallsign(value[L"radioCallsign"].as_number().to_int32());
|
||||
unit->setRadioCallsignNumber(value[L"radioCallsignNumber"].as_number().to_int32());
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
#include "luatools.h"
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include "base64.hpp"
|
||||
|
||||
#include <chrono>
|
||||
using namespace std::chrono;
|
||||
using namespace base64;
|
||||
|
||||
extern UnitsManager* unitsManager;
|
||||
extern Scheduler* scheduler;
|
||||
@@ -54,10 +56,10 @@ void Server::stop(lua_State* L)
|
||||
void Server::handle_options(http_request request)
|
||||
{
|
||||
http_response response(status_codes::OK);
|
||||
response.headers().add(U("Allow"), U("GET, POST, PUT, OPTIONS"));
|
||||
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
|
||||
|
||||
request.reply(response);
|
||||
}
|
||||
@@ -68,87 +70,102 @@ void Server::handle_get(http_request request)
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
http_response response(status_codes::OK);
|
||||
response.headers().add(U("Allow"), U("GET, POST, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
|
||||
string authorization = to_base64("admin:" + to_string(password));
|
||||
if (password == L"" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization)))
|
||||
{
|
||||
std::exception_ptr eptr;
|
||||
try {
|
||||
auto answer = json::value::object();
|
||||
auto path = uri::split_path(uri::decode(request.relative_uri().path()));
|
||||
|
||||
std::exception_ptr eptr;
|
||||
try {
|
||||
auto answer = json::value::object();
|
||||
auto path = uri::split_path(uri::decode(request.relative_uri().path()));
|
||||
|
||||
if (path.size() > 0)
|
||||
{
|
||||
if (path[0] == UNITS_URI)
|
||||
if (path.size() > 0)
|
||||
{
|
||||
map<utility::string_t, utility::string_t> query = request.relative_uri().split_query(request.relative_uri().query());
|
||||
long long time = 0;
|
||||
if (query.find(L"time") != query.end())
|
||||
if (path[0] == UNITS_URI)
|
||||
{
|
||||
try {
|
||||
time = stoll((*(query.find(L"time"))).second);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
time = 0;
|
||||
map<utility::string_t, utility::string_t> query = request.relative_uri().split_query(request.relative_uri().query());
|
||||
long long time = 0;
|
||||
if (query.find(L"time") != query.end())
|
||||
{
|
||||
try {
|
||||
time = stoll((*(query.find(L"time"))).second);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
time = 0;
|
||||
}
|
||||
}
|
||||
unitsManager->getData(answer, time);
|
||||
}
|
||||
unitsManager->getData(answer, time);
|
||||
}
|
||||
else if (path[0] == LOGS_URI)
|
||||
{
|
||||
auto logs = json::value::object();
|
||||
getLogsJSON(logs, 100); // By reference, for thread safety. Get the last 100 log entries
|
||||
answer[L"logs"] = logs;
|
||||
}
|
||||
else if (path[0] == AIRBASES_URI)
|
||||
answer[L"airbases"] = airbases;
|
||||
else if (path[0] == BULLSEYE_URI)
|
||||
answer[L"bullseyes"] = bullseyes;
|
||||
else if (path[0] == MISSION_URI)
|
||||
answer[L"mission"] = mission;
|
||||
else if (path[0] == LOGS_URI)
|
||||
{
|
||||
auto logs = json::value::object();
|
||||
getLogsJSON(logs, 100); // By reference, for thread safety. Get the last 100 log entries
|
||||
answer[L"logs"] = logs;
|
||||
}
|
||||
else if (path[0] == AIRBASES_URI)
|
||||
answer[L"airbases"] = airbases;
|
||||
else if (path[0] == BULLSEYE_URI)
|
||||
answer[L"bullseyes"] = bullseyes;
|
||||
else if (path[0] == MISSION_URI)
|
||||
answer[L"mission"] = mission;
|
||||
|
||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
||||
}
|
||||
|
||||
response.set_body(answer);
|
||||
}
|
||||
catch (...) {
|
||||
eptr = std::current_exception(); // capture
|
||||
}
|
||||
handle_eptr(eptr);
|
||||
}
|
||||
else {
|
||||
response = status_codes::Unauthorized;
|
||||
}
|
||||
|
||||
response.set_body(answer);
|
||||
}
|
||||
catch (...) {
|
||||
eptr = std::current_exception(); // capture
|
||||
}
|
||||
handle_eptr(eptr);
|
||||
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
|
||||
|
||||
request.reply(response);
|
||||
}
|
||||
|
||||
void Server::handle_request(http_request request, function<void(json::value const&, json::value&)> action)
|
||||
{
|
||||
auto answer = json::value::object();
|
||||
request.extract_json().then([&answer, &action](pplx::task<json::value> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const& jvalue = task.get();
|
||||
|
||||
if (!jvalue.is_null())
|
||||
{
|
||||
action(jvalue, answer);
|
||||
}
|
||||
}
|
||||
catch (http_exception const& e)
|
||||
{
|
||||
log(e.what());
|
||||
}
|
||||
}).wait();
|
||||
|
||||
http_response response(status_codes::OK);
|
||||
response.headers().add(U("Allow"), U("GET, POST, PUT, OPTIONS"));
|
||||
string authorization = to_base64("admin:" + to_string(password));
|
||||
if (password == L"" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization)))
|
||||
{
|
||||
auto answer = json::value::object();
|
||||
request.extract_json().then([&answer, &action](pplx::task<json::value> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const& jvalue = task.get();
|
||||
|
||||
if (!jvalue.is_null())
|
||||
{
|
||||
action(jvalue, answer);
|
||||
}
|
||||
}
|
||||
catch (http_exception const& e)
|
||||
{
|
||||
log(e.what());
|
||||
}
|
||||
}).wait();
|
||||
response.set_body(answer);
|
||||
}
|
||||
else {
|
||||
response = status_codes::Unauthorized;
|
||||
}
|
||||
|
||||
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
|
||||
response.set_body(answer);
|
||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
|
||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
|
||||
|
||||
request.reply(response);
|
||||
}
|
||||
|
||||
@@ -197,9 +214,15 @@ void Server::task()
|
||||
log(L"Starting server on " + address);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"Error reading configuration file. Starting server on " + address);
|
||||
|
||||
if (config.is_object() && config.has_object_field(L"authentication") &&
|
||||
config[L"authentication"].has_string_field(L"password"))
|
||||
{
|
||||
password = config[L"authentication"][L"password"].as_string();
|
||||
}
|
||||
else
|
||||
log(L"Error reading configuration file. No password set.");
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -337,9 +337,17 @@ void Unit::landAt(Coords loc) {
|
||||
setState(State::LAND);
|
||||
}
|
||||
|
||||
void Unit::setTACANOn(bool newTACANOn) {
|
||||
TACANOn = newTACANOn;
|
||||
addMeasure(L"TACANOn", json::value(newTACANOn));
|
||||
void Unit::setIsTanker(bool newIsTanker) {
|
||||
isTanker = newIsTanker;
|
||||
resetTask();
|
||||
addMeasure(L"isTanker", json::value(newIsTanker));
|
||||
}
|
||||
|
||||
void Unit::setIsAWACS(bool newIsAWACS) {
|
||||
isAWACS = newIsAWACS;
|
||||
resetTask();
|
||||
addMeasure(L"isAWACS", json::value(newIsAWACS));
|
||||
setEPLRS(true);
|
||||
}
|
||||
|
||||
void Unit::setTACANChannel(int newTACANChannel) {
|
||||
@@ -356,11 +364,6 @@ void Unit::setTACANCallsign(wstring newTACANCallsign) {
|
||||
addMeasure(L"TACANCallsign", json::value(newTACANCallsign));
|
||||
}
|
||||
|
||||
void Unit::setRadioOn(bool newRadioOn) {
|
||||
radioOn = newRadioOn;
|
||||
addMeasure(L"radioOn", json::value(newRadioOn));
|
||||
}
|
||||
|
||||
void Unit::setRadioFrequency(int newRadioFrequency) {
|
||||
radioFrequency = newRadioFrequency;
|
||||
addMeasure(L"radioFrequency", json::value(newRadioFrequency));
|
||||
@@ -376,6 +379,19 @@ void Unit::setRadioCallsignNumber(int newRadioCallsignNumber) {
|
||||
addMeasure(L"radioCallsignNumber", json::value(newRadioCallsignNumber));
|
||||
}
|
||||
|
||||
void Unit::setEPLRS(bool state)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS << "{"
|
||||
<< "id = 'EPLRS',"
|
||||
<< "params = {"
|
||||
<< "value = " << (state? "true": "false") << ", "
|
||||
<< "}"
|
||||
<< "}";
|
||||
Command* command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
|
||||
void Unit::setTACAN()
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
@@ -383,9 +399,9 @@ void Unit::setTACAN()
|
||||
<< "id = 'ActivateBeacon',"
|
||||
<< "params = {"
|
||||
<< "type = " << ((TACANXY.compare(L"X") == 0)? 4: 5) << ","
|
||||
<< "system = 4,"
|
||||
<< "name = Olympus_TACAN,"
|
||||
<< "callsign = " << TACANCallsign << ", "
|
||||
<< "system = 3,"
|
||||
<< "name = \"Olympus_TACAN\","
|
||||
<< "callsign = \"" << TACANCallsign << "\", "
|
||||
<< "frequency = " << TACANChannelToFrequency(TACANChannel, TACANXY) << ","
|
||||
<< "}"
|
||||
<< "}";
|
||||
|
||||
Reference in New Issue
Block a user