diff --git a/engine/server/application/CentralServer/src/shared/CentralServer.cpp b/engine/server/application/CentralServer/src/shared/CentralServer.cpp index 0b531b54..065fa9e8 100755 --- a/engine/server/application/CentralServer/src/shared/CentralServer.cpp +++ b/engine/server/application/CentralServer/src/shared/CentralServer.cpp @@ -124,7 +124,7 @@ #include "sharedFoundation/CrcConstexpr.hpp" -#include "webAPI.h" +#include "jsonWebAPI.h" namespace CentralServerNamespace { diff --git a/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp index dd5fd6d6..c1861af3 100755 --- a/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp +++ b/engine/server/application/CentralServer/src/shared/ConfigCentralServer.cpp @@ -128,7 +128,7 @@ void ConfigCentralServer::install(void) KEY_BOOL (requestDbSaveOnPlanetServerCrash, true); KEY_INT (maxTimeToWaitForPlanetServerStartSeconds, 5*60); // seconds KEY_STRING (metricsDataURL, ""); - KEY_INT (webUpdateIntervalSeconds, 0); + KEY_INT (webUpdateIntervalSeconds, 5); int index = 0; char const * result = 0; diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 857357c4..d88d7a53 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -22,6 +22,7 @@ #include "sharedFoundation/CrcConstexpr.hpp" #include "webAPI.h" +#include "jsonWebAPI.h" //----------------------------------------------------------------------- @@ -150,64 +151,91 @@ void ClientConnection::onReceive(const Archive::ByteStream &message) { // originally was used to validate station API credentials, now uses our custom api void ClientConnection::validateClient(const std::string & id, const std::string & key) { - // to avoid having to re-type this stupid var all over the place - // ideally we wouldn't copy this here, but it would be a huge pain - const std::string trimmedId = trim(id); - const std::string trimmedKey = trim(key); + // to avoid having to re-type this stupid var all over the place + // ideally we wouldn't copy this here, but it would be a huge pain + const std::string trimmedId = trim(id); + const std::string trimmedKey = trim(key); - // and to avoid funny business with atoi and casing - // make it a separate var than the one we send the auth server - std::string lcaseId; - lcaseId.resize(trimmedId.size()); + // and to avoid funny business with atoi and casing + // make it a separate var than the one we send the auth server + std::string lcaseId; + lcaseId.resize(trimmedId.size()); + std::transform(trimmedId.begin(),trimmedId.end(),lcaseId.begin(),::tolower); - std::transform(trimmedId.begin(),trimmedId.end(),lcaseId.begin(),::tolower); + // make sure username isn't too long + if (lcaseId.length() > MAX_ACCOUNT_NAME_LENGTH) { + ErrorMessage err("Login Failed", "Account name is too long!"); + this->send(err, true); + return; + } - StationId suid = atoi(lcaseId.c_str()); - int authOK = 0; + // hash username into station id + StationId suid = atoi(lcaseId.c_str()); + if (suid == 0) + { + std::hash h; + suid = h(lcaseId.c_str()); //lint !e603 // Symbol 'h' not initialized (it's a functor) + } - if (suid == 0) - { - std::hash h; - suid = h(lcaseId.c_str()); //lint !e603 // Symbol 'h' not initialized (it's a functor) - } - - LOG("LoginClientConnection", ("validateClient() for stationId (%lu) at IP (%s), id (%s)", m_stationId, getRemoteAddress().c_str(), lcaseId.c_str())); + LOG("LoginClientConnection", ("validateClient() for stationId (%lu) at IP (%s), id (%s)", m_stationId, getRemoteAddress().c_str(), lcaseId.c_str())); - std::string authURL(ConfigLoginServer::getExternalAuthUrl()); + int authOK = 0; + std::string authURL(ConfigLoginServer::getExternalAuthUrl()); + if (!authURL.empty()) + { + if(ConfigLoginServer::getUseJsonWebApi()) + { + StellaBellum::webAPI api(authURL); - if (!authURL.empty()) - { - StellaBellum::webAPI api(authURL); - - api.addJsonData("user_name", trimmedId); - api.addJsonData("user_password", trimmedKey); - api.addJsonData("ip", getRemoteAddress()); - - if (api.submit()) { - std::string msg(api.getString("message")); - - if(msg == "success") { - authOK = 1; - } else { - ErrorMessage err("Login Message", msg); - this->send(err, true); - } - } - else { - ErrorMessage err("Login Failed", "request failed"); - this->send(err, true); - } - } - else - { - authOK = 1; - } + api.addJsonData("user_name", trimmedId); + api.addJsonData("user_password", trimmedKey); + api.addJsonData("stationID", suid); + api.addJsonData("ip", getRemoteAddress()); - if (authOK) - { - LoginServer::getInstance().onValidateClient(suid, lcaseId, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); - } - // else this case will never be reached, noop + if (api.submit()) + { + std::string msg(api.getString("message")); + + if(msg == "success") { + authOK = 1; + } + else + { + ErrorMessage err("Login Message", msg); + this->send(err, true); + } + } + else + { + ErrorMessage err("Login Failed", "request failed"); + this->send(err, true); + } + } + else + { + std::ostringstream postBuf; + postBuf << "user_name=" << trimmedId << "&user_password=" << trimmedKey << "&stationID=" << suid << "&ip=" << getRemoteAddress(); + std::string response = webAPI::simplePost(authURL, std::string(postBuf.str()), ""); + + if (response == "success") { + authOK = 1; + } + else + { + ErrorMessage err("Login Failed", response); + this->send(err, true); + } + } + } + else + { + authOK = 1; + } + + if (authOK) + { + LoginServer::getInstance().onValidateClient(suid, lcaseId, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); + } } diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp index 938c99ea..74e4cbd6 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp @@ -115,6 +115,7 @@ void ConfigLoginServer::install(void) KEY_INT (populationLightThresholdPercent, 8); KEY_INT (csToolPort, 0); // use 10666 if you want to turn the tool on KEY_BOOL(requireSecureLoginForCsTool, true); + KEY_BOOL(useJsonWebApi, false); KEY_BOOL(useExternalAuth, false); KEY_STRING(externalAuthURL, ""); KEY_BOOL(useOldSuidGenerator, false); diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h index 15e46dae..c7730b8a 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h @@ -66,11 +66,11 @@ class ConfigLoginServer int csToolPort; bool requireSecureLoginForCsTool; - bool useExternalAuth; - + + bool useOldSuidGenerator; + bool useExternalAuth; + bool useJsonWebApi; const char * externalAuthURL; - - bool useOldSuidGenerator; }; static const uint16 getCentralServicePort(); @@ -135,8 +135,9 @@ class ConfigLoginServer static int getPopulationLightThresholdPercent(); static bool getUseExternalAuth(); + static bool getUseJsonWebApi(); static const char * getExternalAuthUrl(); - static bool getUseOldSuidGenerator(); + static bool getUseOldSuidGenerator(); // has character creation for this cluster been disabled through config option static bool isCharacterCreationDisabled(std::string const & cluster); @@ -486,6 +487,11 @@ inline const int ConfigLoginServer::getCSToolPort() return data->csToolPort; } +inline bool ConfigLoginServer::getUseJsonWebApi() +{ + return data->useJsonWebApi; +} + inline bool ConfigLoginServer::getUseExternalAuth() { return data->useExternalAuth; diff --git a/external/3rd/library/webAPI/CMakeLists.txt b/external/3rd/library/webAPI/CMakeLists.txt old mode 100644 new mode 100755 index 0c2a2f9f..8fac30a0 --- a/external/3rd/library/webAPI/CMakeLists.txt +++ b/external/3rd/library/webAPI/CMakeLists.txt @@ -5,6 +5,8 @@ project(webAPI) add_library(webAPI webAPI.h webAPI.cpp + jsonWebAPI.h + jsonWebAPI.cpp json.hpp ) diff --git a/external/3rd/library/webAPI/jsonWebAPI.cpp b/external/3rd/library/webAPI/jsonWebAPI.cpp new file mode 100755 index 00000000..5e5224e8 --- /dev/null +++ b/external/3rd/library/webAPI/jsonWebAPI.cpp @@ -0,0 +1,207 @@ +/* + * Version: 1.75 + * + * This code is just a simple wrapper around nlohmann's wonderful json lib + * (https://github.com/nlohmann/json) and libcurl. While originally included directly, + * we have come to realize that we may require web API functionality elsewhere in the future. + * + * As such, and in an effort to keep the code clean, we've broken it out into this simple little + * namespace/lib that is easy to include. Just make sure to link against curl when including, and + * make all the cmake modifications required to properly use it. + * + * (c) DarthArgus + * based on the original prototype by parz1val + * + * License: LGPL, don't be a dick please + */ + +#include "jsonWebAPI.h" + +using namespace StellaBellum; + +webAPI::webAPI(std::string endpoint, std::string userAgent) : uri(endpoint), userAgent(userAgent), statusCode(0) {} + +webAPI::~webAPI() { + requestData.clear(); + responseData.clear(); +} + +bool webAPI::setEndpoint(const std::string endpoint) { + uri = endpoint; + + return true; +} + +std::string webAPI::getRaw() { + return sResponse; +} + +bool webAPI::setData(std::string &data) { + if (!data.empty()) { + sRequest = data; + + return true; + } + + return false; +} + +std::string webAPI::getString(const std::string &slot) { + if (!responseData.empty() && !slot.empty() && responseData.count(slot) && !responseData[slot].is_null()) { + return responseData[slot].get(); + } + + return std::string(""); +} + +std::unordered_map webAPI::getStringMap(const std::string &slot) { + std::unordered_map ret = std::unordered_map(); + + if (!responseData.empty() && !slot.empty() && responseData.count(slot) && !responseData[slot].is_null()) { + + nlohmann::json j = responseData[slot]; + + for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { + int k = std::stoi(it.key()); + std::string val = it.value(); + + ret.insert({k, val}); + } + } + + return ret; +} + +bool webAPI::submit(const int &reqType, const int &getPost, const int &respType) { + if (reqType == DTYPE::JSON) // json request + { + if (!requestData.empty()) { + // serialize our data into sRequest + sRequest = requestData.dump(); + + // clear our the object for next time + requestData.clear(); + } + } + + if (fetch(getPost, respType) && !(sResponse.empty())) { + return true; + } + + sResponse.clear(); + + return false; +} + +bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for string +{ + bool fetchStatus = false; + + if (!uri.empty()) //data is allowed to be an empty string if we're doing a normal GET + { + CURL *curl = curl_easy_init(); // start up curl + + if (curl) { + std::string readBuffer = ""; // container for the remote response + struct curl_slist *slist = nullptr; + + // set the content type + if (mimeType == DTYPE::JSON) { + slist = curl_slist_append(slist, "Accept: application/json"); + slist = curl_slist_append(slist, "Content-Type: application/json"); + } else { + slist = curl_slist_append(slist, "Content-Type: application/x-www-form-urlencoded"); + } + + slist = curl_slist_append(slist, "charsets: utf-8"); + + CURLcode res = curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); + res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // place the data into readBuffer using writeCallback + res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // specify readBuffer as the container for data + res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); + + switch (getPost) { + case HTTP::GET: + res = curl_easy_setopt(curl, CURLOPT_URL, std::string(uri + "?" + sRequest).c_str()); + break; + case HTTP::POST: + res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, sRequest.c_str()); + res = curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); + break; + // want to do a put, or whatever other type? feel free to add here + } + + // I suggest leaving VERIFYPEER = 0 because system SSL stores tend to be outdated + //if (uri.find(vxENCRYPT("stellabellum").decrypt()) != std::string::npos) { + // the public one will verify but since this is pinned we don't care about the CA + // to grab/generate, see https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html + // under the PUBLIC KEY EXTRACTION heading + res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + + // if you want to pin to your own cert or cloudflares, learn how and use the below + // res = curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, vxENCRYPT("sha256//YOURKEYHERE").decrypt()); + //} + + if (res == CURLE_OK) { + res = curl_easy_perform(curl); // make the request! + } + + if (res == CURLE_OK) { + char *contentType; + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode); //get status code + curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &contentType); // get response mime type + + std::string conType(contentType); + + if (statusCode == 200 && !(readBuffer.empty())) // check it all out and parse + { + sResponse = readBuffer; + if (conType.find("application/json") != std::string::npos) { + fetchStatus = processJSON(); + } else { + responseData.clear(); + fetchStatus = true; + } + } + } + + curl_slist_free_all(slist); + curl_easy_cleanup(curl); // always wipe our butt + } + } + + if (!fetchStatus) { + sResponse.clear(); + responseData.clear(); + } + + return fetchStatus; +} + +// This is used by curl to grab the response and put it into a var +size_t webAPI::writeCallback(void *contents, size_t size, size_t nmemb, void *userp) { + ((std::string *) userp)->append((char *) contents, size * nmemb); + return size * nmemb; +} + +bool webAPI::processJSON() { + if (!(sResponse.empty())) // check it all out and parse + { + try { + responseData = nlohmann::json::parse(sResponse); + return true; + } catch (std::string &e) { + responseData["message"] = e; + responseData["status"] = "failure"; + } catch (...) { + responseData["message"] = "JSON parse error for endpoint."; + responseData["status"] = "failure"; + } + } else { + responseData["message"] = "Error fetching data from remote."; + responseData["status"] = "failure"; + } + + return false; +} \ No newline at end of file diff --git a/external/3rd/library/webAPI/jsonWebAPI.h b/external/3rd/library/webAPI/jsonWebAPI.h new file mode 100755 index 00000000..02cf3155 --- /dev/null +++ b/external/3rd/library/webAPI/jsonWebAPI.h @@ -0,0 +1,122 @@ +/* + * Version: 1.75 + * + * This code is just a simple wrapper around nlohmann's wonderful json lib + * (https://github.com/nlohmann/json) and libcurl. While originally included directly, + * we have come to realize that we may require web API functionality elsewhere in the future. + * + * As such, and in an effort to keep the code clean, we've broken it out into this simple little + * namespace/lib that is easy to include. Just make sure to link against curl when including, and + * make all the cmake modifications required to properly use it. + * + * (c) DarthArgus + * based on the original prototype by parz1val + * + * License: LGPL, don't be a dick please + */ + +#ifndef jsonWebAPI_H +#define jsonWebAPI_H + +#include "json.hpp" + +#ifdef WIN32 +#include +#else + +#include +#include + +#endif + +#include "../libLeff/libLeff.h" + +namespace StellaBellum { + enum HTTP { + GET = 0, POST = 1 + }; + enum DTYPE { + JSON = 0, RAW = 1 + }; + + class webAPI { + public: + // useragent + std::string userAgent; + + // constructor - can setup with the endpoint from the start + webAPI(std::string endpoint, std::string userAgent = "StellaBellum webAPI"); + + ~webAPI(); + + // submits the request + bool + submit(const int &reqType = DTYPE::JSON, const int &getPost = HTTP::POST, const int &respType = DTYPE::JSON); + + // set the endpoint after object creation...or change the target if needed + bool setEndpoint(const std::string endpoint); + + // get raw response + std::string getRaw(); + + // set a standard request string + bool setData(std::string &data); // all or nothing + + // get a string from a given slot + std::string getString(const std::string &slot); + + // get a vector of strings from a given slot + std::unordered_map getStringMap(const std::string &slot); + + // set json key and value for request + template bool addJsonData(const std::string &key, const T &value) { + if (!key.empty() && + responseData.count(key) == 0) // only alow one of a given key for now, unless we support nesting later + { + requestData[key] = value; + return true; + } + + return false; + } + + // get json response slot + template T getNullableValue(const std::string &slot) { + if (!responseData.empty() && !slot.empty() && responseData.count(slot)) { + return responseData[slot].get(); + } + + return 0; + } + + private: + // json request data - object is serialized before sending, used with above setter template + nlohmann::json requestData; + + // json response, stored so we can use the getter template above + nlohmann::json responseData; + + // raw response + std::string sResponse; + + // raw request string + std::string sRequest; + + // API endpoint + std::string uri; + + // fetcher - returns raw response direct from remote + bool fetch(const int &getPost = HTTP::POST, const int &mimeType = DTYPE::JSON); + + // cURL writeback callback + static size_t writeCallback(void *contents, size_t size, size_t nmemb, void *userp); + + // json processor - string to json + bool processJSON(); + + protected: + // http response code (200, 404, etc) + long statusCode; + }; +} +#endif diff --git a/external/3rd/library/webAPI/webAPI.cpp b/external/3rd/library/webAPI/webAPI.cpp old mode 100644 new mode 100755 index 5931d3b6..b9637b03 --- a/external/3rd/library/webAPI/webAPI.cpp +++ b/external/3rd/library/webAPI/webAPI.cpp @@ -1,207 +1,123 @@ /* - * Version: 1.75 - * - * This code is just a simple wrapper around nlohmann's wonderful json lib - * (https://github.com/nlohmann/json) and libcurl. While originally included directly, - * we have come to realize that we may require web API functionality elsewhere in the future. - * - * As such, and in an effort to keep the code clean, we've broken it out into this simple little - * namespace/lib that is easy to include. Just make sure to link against curl when including, and - * make all the cmake modifications required to properly use it. - * - * (c) DarthArgus - * based on the original prototype by parz1val - * - * License: LGPL, don't be a dick please - */ +This code is just a simple wrapper around nlohmann's wonderful json lib +(https://github.com/nlohmann/json) and libcurl. While originally included directly, +we have come to realize that we may require web API functionality elsewhere in the future. + +As such, and in an effort to keep the code clean, we've broken it out into this simple little +namespace/lib that is easy to include. Just make sure to link against curl when including, and +make all the cmake modifications required to properly use it. + +(c) stellabellum/swgilluminati (combined crews), written by DA with help from DC +based on the original prototype by parz1val + +License: what's a license? we're a bunch of dirty pirates! +*/ #include "webAPI.h" -using namespace StellaBellum; +using namespace std; -webAPI::webAPI(std::string endpoint, std::string userAgent) : uri(endpoint), userAgent(userAgent), statusCode(0) {} - -webAPI::~webAPI() { - requestData.clear(); - responseData.clear(); -} - -bool webAPI::setEndpoint(const std::string endpoint) { - uri = endpoint; - - return true; -} - -std::string webAPI::getRaw() { - return sResponse; -} - -bool webAPI::setData(std::string &data) { - if (!data.empty()) { - sRequest = data; - - return true; - } - - return false; -} - -std::string webAPI::getString(const std::string &slot) { - if (!responseData.empty() && !slot.empty() && responseData.count(slot) && !responseData[slot].is_null()) { - return responseData[slot].get(); - } - - return std::string(""); -} - -std::unordered_map webAPI::getStringMap(const std::string &slot) { - std::unordered_map ret = std::unordered_map(); - - if (!responseData.empty() && !slot.empty() && responseData.count(slot) && !responseData[slot].is_null()) { - - nlohmann::json j = responseData[slot]; - - for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { - int k = std::stoi(it.key()); - std::string val = it.value(); - - ret.insert({k, val}); - } - } - - return ret; -} - -bool webAPI::submit(const int &reqType, const int &getPost, const int &respType) { - if (reqType == DTYPE::JSON) // json request - { - if (!requestData.empty()) { - // serialize our data into sRequest - sRequest = requestData.dump(); - - // clear our the object for next time - requestData.clear(); - } - } - - if (fetch(getPost, respType) && !(sResponse.empty())) { - return true; - } - - sResponse.clear(); - - return false; -} - -bool webAPI::fetch(const int &getPost, const int &mimeType) // 0 for json 1 for string +// if status == success, returns "success", or slotName's contents if specified... +// otherwise returns the "message" if no success +string webAPI::simplePost(string endpoint, string data, string slotName) { - bool fetchStatus = false; + // declare our output and go ahead and attempt to get data from remote + nlohmann::json response = request(endpoint, data, 1); + string output; - if (!uri.empty()) //data is allowed to be an empty string if we're doing a normal GET - { - CURL *curl = curl_easy_init(); // start up curl + // if we got data back... + if (response.count("status") && response["status"].get() == "success") + { + // use custom slot if specified (not "") + if (!(slotName.empty()) && response.count(slotName)) + { + output = response[slotName].get(); + } + else + { + output = "success"; + } + } + else //default message is an error, the other end always assumes "success" or the specified slot + { + if (response.count("message")) + { + output = response["message"].get(); + } + else + { + output = "Message not provided by remote."; + } + } - if (curl) { - std::string readBuffer = ""; // container for the remote response - struct curl_slist *slist = nullptr; + return output; +} - // set the content type - if (mimeType == DTYPE::JSON) { - slist = curl_slist_append(slist, "Accept: application/json"); - slist = curl_slist_append(slist, "Content-Type: application/json"); - } else { - slist = curl_slist_append(slist, "Content-Type: application/x-www-form-urlencoded"); - } +// this can be broken out to separate the json bits later if we need raw or other http type requests +// all it does is fetch via get or post, and if the status is 200 returns the json, else error json +nlohmann::json webAPI::request(string endpoint, string data, int reqType) +{ + nlohmann::json response; - slist = curl_slist_append(slist, "charsets: utf-8"); + if (!endpoint.empty()) //data is allowed to be an empty string if we're doing a normal GET + { + CURL *curl = curl_easy_init(); // start up curl - CURLcode res = curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); - res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // place the data into readBuffer using writeCallback - res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // specify readBuffer as the container for data - res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); - - switch (getPost) { - case HTTP::GET: - res = curl_easy_setopt(curl, CURLOPT_URL, std::string(uri + "?" + sRequest).c_str()); - break; - case HTTP::POST: - res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, sRequest.c_str()); - res = curl_easy_setopt(curl, CURLOPT_URL, uri.c_str()); - break; - // want to do a put, or whatever other type? feel free to add here - } - - // I suggest leaving VERIFYPEER = 0 because system SSL stores tend to be outdated - //if (uri.find(vxENCRYPT("stellabellum").decrypt()) != std::string::npos) { - // the public one will verify but since this is pinned we don't care about the CA - // to grab/generate, see https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html - // under the PUBLIC KEY EXTRACTION heading - res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - - // if you want to pin to your own cert or cloudflares, learn how and use the below - // res = curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, vxENCRYPT("sha256//YOURKEYHERE").decrypt()); - //} - - if (res == CURLE_OK) { - res = curl_easy_perform(curl); // make the request! - } - - if (res == CURLE_OK) { - char *contentType; - - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode); //get status code - curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &contentType); // get response mime type - - std::string conType(contentType); - - if (statusCode == 200 && !(readBuffer.empty())) // check it all out and parse + if (curl) { - sResponse = readBuffer; - if (conType.find("application/json") != std::string::npos) { - fetchStatus = processJSON(); - } else { - responseData.clear(); - fetchStatus = true; - } - } - } + string readBuffer; // container for the remote response + long http_code = 0; // we get this after performing the get or post - curl_slist_free_all(slist); - curl_easy_cleanup(curl); // always wipe our butt - } - } + curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str()); // endpoint is always specified by caller + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // place the data into readBuffer using writeCallback + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // specify readBuffer as the container for data - if (!fetchStatus) { - sResponse.clear(); - responseData.clear(); - } + if (reqType == 1) + { + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); + } - return fetchStatus; + CURLcode res = curl_easy_perform(curl); // make the request! + + curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code); //get status code + + if (res == CURLE_OK && http_code == 200 && !(readBuffer.empty())) // check it all out and parse + { + try { + response = nlohmann::json::parse(readBuffer); + } catch (string e) { + response["message"] = e; + response["status"] = "failure"; + } catch (...) { + response["message"] = "JSON parse error for endpoint."; + response["status"] = "failure"; + } + } + else + { + response["message"] = "Error fetching data from remote."; + response["status"] = "failure"; + } + curl_easy_cleanup(curl); // always wipe our butt + } + else //default err messages below + { + response["message"] = "Failed to initialize cURL."; + response["status"] = "failure"; + } + } + else + { + response["message"] = "Invalid endpoint URL."; + response["status"] = "failure"; + } + + return response; } // This is used by curl to grab the response and put it into a var -size_t webAPI::writeCallback(void *contents, size_t size, size_t nmemb, void *userp) { - ((std::string *) userp)->append((char *) contents, size * nmemb); - return size * nmemb; +size_t webAPI::writeCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + ((string*)userp)->append((char*)contents, size * nmemb); + return size * nmemb; } - -bool webAPI::processJSON() { - if (!(sResponse.empty())) // check it all out and parse - { - try { - responseData = nlohmann::json::parse(sResponse); - return true; - } catch (std::string &e) { - responseData["message"] = e; - responseData["status"] = "failure"; - } catch (...) { - responseData["message"] = "JSON parse error for endpoint."; - responseData["status"] = "failure"; - } - } else { - responseData["message"] = "Error fetching data from remote."; - responseData["status"] = "failure"; - } - - return false; -} \ No newline at end of file diff --git a/external/3rd/library/webAPI/webAPI.h b/external/3rd/library/webAPI/webAPI.h old mode 100644 new mode 100755 index c45f99aa..51e60a2c --- a/external/3rd/library/webAPI/webAPI.h +++ b/external/3rd/library/webAPI/webAPI.h @@ -1,122 +1,35 @@ /* - * Version: 1.75 - * - * This code is just a simple wrapper around nlohmann's wonderful json lib - * (https://github.com/nlohmann/json) and libcurl. While originally included directly, - * we have come to realize that we may require web API functionality elsewhere in the future. - * - * As such, and in an effort to keep the code clean, we've broken it out into this simple little - * namespace/lib that is easy to include. Just make sure to link against curl when including, and - * make all the cmake modifications required to properly use it. - * - * (c) DarthArgus - * based on the original prototype by parz1val - * - * License: LGPL, don't be a dick please - */ +This code is just a simple wrapper around nlohmann's wonderful json lib +(https://github.com/nlohmann/json) and libcurl. While originally included directly, +we have come to realize that we may require web API functionality elsewhere in the future. + +As such, and in an effort to keep the code clean, we've broken it out into this simple little +namespace/lib that is easy to include. Just make sure to link against curl when including, and +make all the cmake modifications required to properly use it. + +(c) stellabellum/swgilluminati (combined crews), written by DA with help from DC +based on the original prototype by parz1val + +License: what's a license? we're a bunch of dirty pirates! +*/ #ifndef webAPI_H #define webAPI_H #include "json.hpp" - -#ifdef WIN32 -#include -#else - -#include #include -#endif - -#include "../libLeff/libLeff.h" - -namespace StellaBellum { - enum HTTP { - GET = 0, POST = 1 - }; - enum DTYPE { - JSON = 0, RAW = 1 - }; - - class webAPI { - public: - // useragent - std::string userAgent; - - // constructor - can setup with the endpoint from the start - webAPI(std::string endpoint, std::string userAgent = "StellaBellum webAPI"); - - ~webAPI(); - - // submits the request - bool - submit(const int &reqType = DTYPE::JSON, const int &getPost = HTTP::POST, const int &respType = DTYPE::JSON); - - // set the endpoint after object creation...or change the target if needed - bool setEndpoint(const std::string endpoint); - - // get raw response - std::string getRaw(); - - // set a standard request string - bool setData(std::string &data); // all or nothing - - // get a string from a given slot - std::string getString(const std::string &slot); - - // get a vector of strings from a given slot - std::unordered_map getStringMap(const std::string &slot); - - // set json key and value for request - template bool addJsonData(const std::string &key, const T &value) { - if (!key.empty() && - responseData.count(key) == 0) // only alow one of a given key for now, unless we support nesting later - { - requestData[key] = value; - return true; - } - - return false; - } - - // get json response slot - template T getNullableValue(const std::string &slot) { - if (!responseData.empty() && !slot.empty() && responseData.count(slot)) { - return responseData[slot].get(); - } - - return 0; - } - - private: - // json request data - object is serialized before sending, used with above setter template - nlohmann::json requestData; - - // json response, stored so we can use the getter template above - nlohmann::json responseData; - - // raw response - std::string sResponse; - - // raw request string - std::string sRequest; - - // API endpoint - std::string uri; - - // fetcher - returns raw response direct from remote - bool fetch(const int &getPost = HTTP::POST, const int &mimeType = DTYPE::JSON); - - // cURL writeback callback - static size_t writeCallback(void *contents, size_t size, size_t nmemb, void *userp); - - // json processor - string to json - bool processJSON(); - - protected: - // http response code (200, 404, etc) - long statusCode; - }; -} +namespace webAPI +{ + using namespace std; + + string simplePost(string endpoint, string data, string slotName); + //std::string simpleGet(char* endpoint, char* data); + //nlohmann::json post(char* endpoint, char* data); + //nlohmann::json get(char* endpoint, char* data); + + nlohmann::json request(string endpoint, string data, int reqType); // 1 for post, 0 for get + size_t writeCallback(void *contents, size_t size, size_t nmemb, void *userp); +}; + #endif diff --git a/game/server/database/sqlnet.log b/game/server/database/sqlnet.log new file mode 100644 index 00000000..5eee3742 --- /dev/null +++ b/game/server/database/sqlnet.log @@ -0,0 +1,19 @@ + + +*********************************************************************** +Fatal NI connect error 12537, connecting to: + (DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=XE)(CID=(PROGRAM=sqlplus@swgvm)(HOST=swgvm)(USER=swg)))(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.50)(PORT=1521))) + + VERSION INFORMATION: + TNS for Linux: Version 10.2.0.4.0 - Production + TCP/IP NT Protocol Adapter for Linux: Version 10.2.0.4.0 - Production + Time: 13-MAR-2019 03:01:43 + Tracing not turned on. + Tns error struct: + ns main err code: 12537 + TNS-12537: Message 12537 not found; No message file for product=network, facility=TNS + ns secondary err code: 12560 + nt main err code: 507 + TNS-00507: Message 507 not found; No message file for product=network, facility=TNS + nt secondary err code: 0 + nt OS err code: 0