[impl] Support for online activation
This commit is contained in:
parent
564dda8539
commit
c27d732655
@ -1,4 +1,4 @@
|
|||||||
# CMakeList.txt : CMake project for CMakeProject1, include source and define
|
# CMakeList.txt : CMake project for CCEngineServer, include source and define
|
||||||
# project specific logic here.
|
# project specific logic here.
|
||||||
#
|
#
|
||||||
cmake_minimum_required (VERSION 3.8)
|
cmake_minimum_required (VERSION 3.8)
|
||||||
@ -30,8 +30,19 @@ else(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Add source to this project's executable.
|
# Add source to this project's executable.
|
||||||
add_executable (CMakeProject1 "CCServer.cpp" "CCServer.h" "CryptoUtils.cpp" "CryptoUtils.h" "CMakeProject1.cpp" "CMakeProject1.h" "HashUtils.cpp" "HashUtils.h" "JSONSerialization.cpp" "JSONSerialization.h" "LicenseClient.cpp" "LicenseClient.h" "SystemParams.cpp" "SystemParams.h" "SystemParamsProvider.h" "SystemParamsProvider_win.cpp" "SystemParamsProvider_win.h" "SystemParamsProvider_linux.cpp" "SystemParamsProvider_win.cpp" "OSUtils.h" "OSUtils_win.cpp")
|
add_executable (
|
||||||
|
CCEngineServer
|
||||||
|
"CCServer.cpp" "CCServer.h"
|
||||||
|
"CryptoUtils.cpp" "CryptoUtils.h"
|
||||||
|
"HashUtils.cpp" "HashUtils.h"
|
||||||
|
"HTTPClient.cpp" "HTTPClient.h"
|
||||||
|
"JSONSerialization.cpp" "JSONSerialization.h"
|
||||||
|
"LicenseClient.cpp" "LicenseClient.h"
|
||||||
|
"SystemParams.cpp" "SystemParams.h"
|
||||||
|
"SystemParamsProvider.h" "SystemParamsProvider_win.cpp" "SystemParamsProvider_win.h" "SystemParamsProvider_linux.cpp" "SystemParamsProvider_win.cpp"
|
||||||
|
"OSUtils.h" "OSUtils_win.cpp"
|
||||||
|
"main.cpp" "version.h")
|
||||||
|
|
||||||
target_link_libraries(CMakeProject1 ${CONAN_LIBS})
|
target_link_libraries(CCEngineServer ${CONAN_LIBS})
|
||||||
|
|
||||||
# TODO: Add tests and install targets if needed.
|
# TODO: Add tests and install targets if needed.
|
||||||
321
CCEngineServer/HTTPClient.cpp
Normal file
321
CCEngineServer/HTTPClient.cpp
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
#include "HTTPClient.h"
|
||||||
|
|
||||||
|
struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
static
|
||||||
|
void dump(const char *text,
|
||||||
|
FILE *stream, unsigned char *ptr, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int width = 0x10;
|
||||||
|
|
||||||
|
fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
|
||||||
|
text, (long)size, (long)size);
|
||||||
|
|
||||||
|
fwrite(ptr, 1, size, stream);
|
||||||
|
fputc('\n', stream); // newline
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int my_trace(CURL *handle, curl_infotype type,
|
||||||
|
char *data, size_t size,
|
||||||
|
void *userp)
|
||||||
|
{
|
||||||
|
const char *text;
|
||||||
|
(void)handle; /* prevent compiler warning */
|
||||||
|
(void)userp;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case CURLINFO_TEXT:
|
||||||
|
fprintf(stderr, "== Info: %s", data);
|
||||||
|
default: /* in case a new one is introduced to shock us */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case CURLINFO_HEADER_OUT:
|
||||||
|
text = "=> Send header";
|
||||||
|
break;
|
||||||
|
case CURLINFO_DATA_OUT:
|
||||||
|
text = "=> Send data";
|
||||||
|
break;
|
||||||
|
case CURLINFO_SSL_DATA_OUT:
|
||||||
|
text = "=> Send SSL data";
|
||||||
|
break;
|
||||||
|
case CURLINFO_HEADER_IN:
|
||||||
|
text = "<= Recv header";
|
||||||
|
break;
|
||||||
|
case CURLINFO_DATA_IN:
|
||||||
|
text = "<= Recv data";
|
||||||
|
break;
|
||||||
|
case CURLINFO_SSL_DATA_IN:
|
||||||
|
text = "<= Recv SSL data";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(text, stderr, (unsigned char *)data, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t reader(char *ptr, size_t size, size_t nmemb, std::istream *is)
|
||||||
|
{
|
||||||
|
std::streamsize totalRead = 0;
|
||||||
|
if (*is)
|
||||||
|
{
|
||||||
|
is->read(&ptr[totalRead], size * nmemb - totalRead);
|
||||||
|
// is->read(&ptr[totalRead], 1);
|
||||||
|
totalRead = is->gcount();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<size_t>(totalRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t writer(char *data, size_t size, size_t nmemb, std::ostream *os)
|
||||||
|
{
|
||||||
|
if (os == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
os->write(data, size*nmemb);
|
||||||
|
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CURLDeleter
|
||||||
|
{
|
||||||
|
void operator() (CURL* ptr)
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
curl_easy_cleanup(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct curl_slist_deleter
|
||||||
|
{
|
||||||
|
void operator() (curl_slist* ptr)
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
curl_slist_free_all(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DownloadSession
|
||||||
|
{
|
||||||
|
char errorBuffer[CURL_ERROR_SIZE] = { 0 };
|
||||||
|
std::unique_ptr<CURL, CURLDeleter> conn;
|
||||||
|
std::unique_ptr<curl_slist, curl_slist_deleter> extraHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
DownloadSession initCurlRequest(const std::string& url, std::ostream &os)
|
||||||
|
{
|
||||||
|
DownloadSession result;
|
||||||
|
CURLcode code;
|
||||||
|
|
||||||
|
std::unique_ptr<CURL, CURLDeleter> conn(curl_easy_init());
|
||||||
|
|
||||||
|
if (!conn)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to create CURL connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_ERRORBUFFER, result.errorBuffer);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set error buffer [" << code << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* errorBuffer = result.errorBuffer;
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_URL, url.c_str());
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set URL [" << errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set redirect option [" << errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_MAXREDIRS, 5L);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set maximum number of redirects [" << errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_WRITEFUNCTION, writer);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set write function [" << errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_WRITEDATA, &os);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set write data [" << errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_DEBUGFUNCTION, my_trace);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set debug function";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(conn.get(), CURLOPT_VERBOSE, 1);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set verbose mode";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
#endif // !NDEBUG
|
||||||
|
|
||||||
|
result.conn = std::move(conn);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadSession initCurlPostJsonRequest(const std::string& url, std::istream& is, size_t length, std::ostream &os)
|
||||||
|
{
|
||||||
|
DownloadSession result = initCurlRequest(url, os);
|
||||||
|
CURLcode code;
|
||||||
|
|
||||||
|
auto contentLengthHeader = std::string("Content-Length: ") + std::to_string(length);
|
||||||
|
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
headers = curl_slist_append(headers, "Accept: application/json");
|
||||||
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
|
headers = curl_slist_append(headers, contentLengthHeader.c_str());
|
||||||
|
headers = curl_slist_append(headers, "Charsets: utf-8");
|
||||||
|
result.extraHeaders.reset(headers);
|
||||||
|
|
||||||
|
code = curl_easy_setopt(result.conn.get(), CURLOPT_POST, 1L);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set post option [" << result.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(result.conn.get(), CURLOPT_HTTPHEADER, result.extraHeaders.get());
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set http headers [" << result.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(result.conn.get(), CURLOPT_READFUNCTION, reader);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set read function [" << result.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(result.conn.get(), CURLOPT_READDATA, &is);
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to set read data [" << result.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
HTTPClient::HTTPClient()
|
||||||
|
{
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPClient::get(const std::string& url, std::ostream& dstStream)
|
||||||
|
{
|
||||||
|
auto session = initCurlRequest(url, dstStream);
|
||||||
|
|
||||||
|
auto code = curl_easy_perform(session.conn.get());
|
||||||
|
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
session.conn.release();
|
||||||
|
if (code == CURLE_COULDNT_CONNECT)
|
||||||
|
{
|
||||||
|
throw CouldNotConnectException();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to get '" << url << "' [" << session.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long http_code = 0;
|
||||||
|
curl_easy_getinfo(session.conn.get(), CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
|
if (http_code >= 400)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to get '" << url << "' [HTTP code: " << http_code << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPClient::postJson(const std::string& url, std::istream& json, size_t length, std::ostream& dstStream)
|
||||||
|
{
|
||||||
|
auto session = initCurlPostJsonRequest(url, json, length, dstStream);
|
||||||
|
|
||||||
|
auto code = curl_easy_perform(session.conn.get());
|
||||||
|
|
||||||
|
if (code != CURLE_OK)
|
||||||
|
{
|
||||||
|
session.conn.release();
|
||||||
|
if (code == CURLE_COULDNT_CONNECT)
|
||||||
|
{
|
||||||
|
throw CouldNotConnectException();
|
||||||
|
}
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to post '" << url << "' [" << session.errorBuffer << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long http_code = 0;
|
||||||
|
curl_easy_getinfo(session.conn.get(), CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
|
if (http_code >= 400)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to get '" << url << "' [HTTP code: " << http_code << "]";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPClient::postJson(const std::string& url, const std::string& json, std::ostream& dstStream)
|
||||||
|
{
|
||||||
|
std::istringstream is(json);
|
||||||
|
return postJson(url, is, json.size(), dstStream);
|
||||||
|
}
|
||||||
24
CCEngineServer/HTTPClient.h
Normal file
24
CCEngineServer/HTTPClient.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
class CouldNotConnectException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CouldNotConnectException()
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual ~CouldNotConnectException() throw () {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HTTPClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HTTPClient();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void get(const std::string& url, std::ostream& dstStream);
|
||||||
|
void postJson(const std::string& url, std::istream& json, size_t length, std::ostream& dstStream);
|
||||||
|
void postJson(const std::string& url, const std::string& json, std::ostream& dstStream);
|
||||||
|
};
|
||||||
@ -58,6 +58,7 @@ namespace
|
|||||||
{
|
{
|
||||||
|
|
||||||
static const std::string productId = "cocserver";
|
static const std::string productId = "cocserver";
|
||||||
|
static const std::string serverPath = "https://license.apis.sk/api/v1";
|
||||||
|
|
||||||
static const uint32_t initializationVectorSize = AES::BLOCKSIZE;
|
static const uint32_t initializationVectorSize = AES::BLOCKSIZE;
|
||||||
static const uint32_t macTagSize = 16;
|
static const uint32_t macTagSize = 16;
|
||||||
@ -228,7 +229,15 @@ void serialize(std::ostream& os, const ActivationRequest& a)
|
|||||||
|
|
||||||
void deserialize(const pt::ptree& tree, ActivationResponse& a)
|
void deserialize(const pt::ptree& tree, ActivationResponse& a)
|
||||||
{
|
{
|
||||||
deserialize(tree.get_child("success"), a.success);
|
auto successNode = tree.get_child_optional("success");
|
||||||
|
if (successNode)
|
||||||
|
{
|
||||||
|
deserialize(successNode.value(), a.success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a.success = false;
|
||||||
|
}
|
||||||
auto licenseFileOpt = tree.get_child_optional("licenseFile");
|
auto licenseFileOpt = tree.get_child_optional("licenseFile");
|
||||||
if (licenseFileOpt)
|
if (licenseFileOpt)
|
||||||
{
|
{
|
||||||
@ -277,7 +286,7 @@ void LicenseClient::init()
|
|||||||
loadActivationData();
|
loadActivationData();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LicenseClient::buildActivationRequest()
|
std::string LicenseClient::buildOfflineActivationRequest()
|
||||||
{
|
{
|
||||||
PreactivationRequest req{ productId, m_systemParams };
|
PreactivationRequest req{ productId, m_systemParams };
|
||||||
|
|
||||||
@ -324,6 +333,74 @@ std::string LicenseClient::buildActivationRequest()
|
|||||||
std::string("-----END ACTIVATION REQUEST-----\n");
|
std::string("-----END ACTIVATION REQUEST-----\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LicenseClient::tryPreactivate(HTTPClient &httpClient)
|
||||||
|
{
|
||||||
|
PreactivationRequest req{ productId, m_systemParams };
|
||||||
|
|
||||||
|
std::string jsonReq;
|
||||||
|
{
|
||||||
|
std::ostringstream ss1;
|
||||||
|
serialize(ss1, req);
|
||||||
|
jsonReq = ss1.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string jsonRes;
|
||||||
|
{
|
||||||
|
std::ostringstream ss2;
|
||||||
|
httpClient.postJson(serverPath + "/activate0", jsonReq, ss2);
|
||||||
|
jsonRes = ss2.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivationResponse activationResponse;
|
||||||
|
pt::ptree root;
|
||||||
|
std::istringstream ss2(jsonRes);
|
||||||
|
pt::read_json(ss2, root);
|
||||||
|
deserialize(root, activationResponse);
|
||||||
|
if (activationResponse.success)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto& licenseData = activationResponse.licenseFile.value();
|
||||||
|
std::ofstream os(m_licenseFile, std::ofstream::binary);
|
||||||
|
os.write(licenseData.data(), licenseData.size());
|
||||||
|
}
|
||||||
|
return loadActivationData();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LicenseClient::activate(HTTPClient &httpClient, const std::string & licenseNumber)
|
||||||
|
{
|
||||||
|
auto validLicenseKey = validateLicenseKey(licenseNumber);
|
||||||
|
if (!validLicenseKey)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream ss1;
|
||||||
|
|
||||||
|
ActivationRequest req{ productId, m_systemParams, validLicenseKey.value() };
|
||||||
|
serialize(ss1, req);
|
||||||
|
|
||||||
|
std::stringstream ss2;
|
||||||
|
httpClient.postJson(serverPath + "/activate", ss1.str() , ss2);
|
||||||
|
|
||||||
|
ActivationResponse activationResponse;
|
||||||
|
pt::ptree root;
|
||||||
|
pt::read_json(ss2, root);
|
||||||
|
deserialize(root, activationResponse);
|
||||||
|
if (activationResponse.success)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const auto& licenseData = activationResponse.licenseFile.value();
|
||||||
|
std::ofstream os(m_licenseFile, std::ofstream::binary);
|
||||||
|
os.write(licenseData.data(), licenseData.size());
|
||||||
|
}
|
||||||
|
return loadActivationData();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LicenseClient::loadActivationData()
|
bool LicenseClient::loadActivationData()
|
||||||
{
|
{
|
||||||
if (fs::is_regular_file(m_licenseFile))
|
if (fs::is_regular_file(m_licenseFile))
|
||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "HTTPClient.h"
|
||||||
#include "SystemParamsProvider.h"
|
#include "SystemParamsProvider.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -25,9 +26,11 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
std::string buildActivationRequest();
|
std::string buildOfflineActivationRequest();
|
||||||
bool isActivated() const { return m_activationData.has_value(); }
|
bool isActivated() const { return m_activationData.has_value(); }
|
||||||
std::optional<std::string> activationNumber() const { return m_activationData.has_value() ? m_activationData->activationId : std::optional<std::string>(); }
|
std::optional<std::string> activationNumber() const { return m_activationData.has_value() ? m_activationData->activationId : std::optional<std::string>(); }
|
||||||
|
bool tryPreactivate(HTTPClient &httpClient);
|
||||||
|
bool activate(HTTPClient &httpClient, const std::string& licenseNumber );
|
||||||
auto licensedModules() { if (!isActivated()) { throw std::runtime_error("Not active"); } return m_activationData->licensedModules; }
|
auto licensedModules() { if (!isActivated()) { throw std::runtime_error("Not active"); } return m_activationData->licensedModules; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1,6 +1,7 @@
|
|||||||
[requires]
|
[requires]
|
||||||
boost/1.76.0
|
boost/1.77.0
|
||||||
cryptopp/8.5.0
|
cryptopp/8.5.0
|
||||||
|
libcurl/7.79.1
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
cmake
|
cmake
|
||||||
@ -8,3 +9,5 @@ cmake
|
|||||||
[options]
|
[options]
|
||||||
boost:shared=False
|
boost:shared=False
|
||||||
cryptopp:shared=False
|
cryptopp:shared=False
|
||||||
|
libcurl:shared=False
|
||||||
|
libcurl:with_ssl=openssl
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "LicenseClient.h"
|
#include "LicenseClient.h"
|
||||||
#include "SystemParamsProvider.h"
|
#include "SystemParamsProvider.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
#include <boost/log/core.hpp>
|
#include <boost/log/core.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
@ -26,7 +27,7 @@ namespace keywords = boost::log::keywords;
|
|||||||
volatile bool signalCaught = false;
|
volatile bool signalCaught = false;
|
||||||
|
|
||||||
void signalHandler(int signum) {
|
void signalHandler(int signum) {
|
||||||
std::cout << "Interrupt signal (" << signum << ") received.\n";
|
BOOST_LOG_TRIVIAL(info) << "Interrupt signal (" << signum << ") received.";
|
||||||
|
|
||||||
signalCaught = true;
|
signalCaught = true;
|
||||||
}
|
}
|
||||||
@ -60,6 +61,13 @@ int main(int argc, const char* argv[])
|
|||||||
po::options_description generalOptions("General options");
|
po::options_description generalOptions("General options");
|
||||||
generalOptions.add_options()
|
generalOptions.add_options()
|
||||||
("help", "produce help message")
|
("help", "produce help message")
|
||||||
|
("version", "print application version")
|
||||||
|
("activate_online", "activate online")
|
||||||
|
("activate_offline", "start offline activation process")
|
||||||
|
#ifndef WIN32
|
||||||
|
("set_uid", po::value<uid_t>()->default_value(0), "Switch UID after successfull startup")
|
||||||
|
("set_gid", po::value<gid_t>()->default_value(0), "Switch GID after successfull startup")
|
||||||
|
#endif
|
||||||
("bind_ip", po::value<std::string>()->default_value("0.0.0.0"), "ip address to listen for connections")
|
("bind_ip", po::value<std::string>()->default_value("0.0.0.0"), "ip address to listen for connections")
|
||||||
("port", po::value<uint16_t>()->default_value(8080), "port")
|
("port", po::value<uint16_t>()->default_value(8080), "port")
|
||||||
("data_root", po::value<std::string>()->default_value("."), "root directory with data")
|
("data_root", po::value<std::string>()->default_value("."), "root directory with data")
|
||||||
@ -80,7 +88,14 @@ int main(int argc, const char* argv[])
|
|||||||
po::notify(vm);
|
po::notify(vm);
|
||||||
|
|
||||||
if (vm.count("help")) {
|
if (vm.count("help")) {
|
||||||
std::cout << generalOptions << "\n";
|
std::cout << "CCEngineServer - Catalogue of Currencies serving solution" << std::endl;
|
||||||
|
std::cout << COPYRIGHT_NOTICE << std::endl << std::endl;
|
||||||
|
std::cout << generalOptions << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("version")) {
|
||||||
|
std::cout << VERSION << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,11 +112,82 @@ int main(int argc, const char* argv[])
|
|||||||
LicenseClient licenseClient(systemParamsProvider, "license.dat");
|
LicenseClient licenseClient(systemParamsProvider, "license.dat");
|
||||||
licenseClient.init();
|
licenseClient.init();
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
auto gidToSet = vm["set_gid"].as<gid_t>();
|
||||||
|
if (gidToSet > 0 && setgid(gidToSet) != 0) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to set group id: " << gidToSet;
|
||||||
|
return -11;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto uidToSet = vm["set_uid"].as<uid_t>();
|
||||||
|
if (uidToSet > 0 && setuid(uidToSet) != 0) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to set user id: " << uidToSet;
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (vm.count("activate_online")) {
|
||||||
|
HTTPClient httpClient;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (licenseClient.tryPreactivate(httpClient)) {
|
||||||
|
std::cout << "Pre-activation successfull. Please go ahead with normal application start" << std::endl;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CouldNotConnectException& e){
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Connection to server failed. Please check your internet"
|
||||||
|
<< "connection.If the problem persists, please contact customer support.";
|
||||||
|
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
catch (std::runtime_error &e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Pre-activate failed. Please retry and if the problem persists, please contact customer support.";
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << e.what();
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Automatic pre-activation failed. Requesting license number...";
|
||||||
|
|
||||||
|
std::string licenseNumber;
|
||||||
|
std::cout << "Please enter license number (format XXXX-XXXX-XXXX-XXXX-XXXX-XXXX):" << std::endl;
|
||||||
|
std::getline(std::cin, licenseNumber);
|
||||||
|
|
||||||
|
std::cout << "Sending activation request to server..." << std::endl;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!licenseClient.activate(httpClient, licenseNumber)) {
|
||||||
|
std::cerr << "Activation failed" << std::endl;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CouldNotConnectException& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Connection to server failed. Please check your internet"
|
||||||
|
<< "connection.If the problem persists, please contact customer support.";
|
||||||
|
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
catch (std::runtime_error& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Activation failed. Please retry and if the problem persists, please contact customer support.";
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << e.what();
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Activation successfull. Please go ahead with normal application start" << std::endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("activate_offline")) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Offline activation was requested";
|
||||||
|
std::cout << "Offline activation was requested";
|
||||||
|
std::cout << "Copy following activation request and refer to the manual: " << std::endl
|
||||||
|
<< licenseClient.buildOfflineActivationRequest() << std::endl;
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
if (!licenseClient.isActivated()) {
|
if (!licenseClient.isActivated()) {
|
||||||
const std::string msg = "Application is not activated. Please contact Catalogue of Currencies support.";
|
BOOST_LOG_TRIVIAL(warning) << "Application is not activated. Please contact customer support.";
|
||||||
BOOST_LOG_TRIVIAL(error) << msg << " Exiting...";
|
BOOST_LOG_TRIVIAL(info) << "Exiting...";
|
||||||
std::cout << msg << std::endl;
|
|
||||||
std::cout << "Activation request: " << std::endl << licenseClient.buildActivationRequest() << std::endl;
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
2
CCEngineServer/version.h
Normal file
2
CCEngineServer/version.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#define VERSION "21.45"
|
||||||
|
#define COPYRIGHT_NOTICE "©2021 Apis spol. s r.o."
|
||||||
@ -7,11 +7,11 @@ if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
|
|||||||
set (CMAKE_SYSTEM_VERSION 8.1 CACHE TYPE INTERNAL FORCE) #Force 8.1 SDK, to keep it compatible with win7
|
set (CMAKE_SYSTEM_VERSION 8.1 CACHE TYPE INTERNAL FORCE) #Force 8.1 SDK, to keep it compatible with win7
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project ("CMakeProject1")
|
project ("CCEngineServer")
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
ADD_DEFINITIONS(/bigobj)
|
ADD_DEFINITIONS(/bigobj)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
# Include sub-projects.
|
# Include sub-projects.
|
||||||
add_subdirectory ("CMakeProject1")
|
add_subdirectory ("CCEngineServer")
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
// CMakeProject1.h : Include file for standard system include files,
|
|
||||||
// or project specific include files.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// TODO: Reference additional headers your program requires here.
|
|
||||||
Loading…
Reference in New Issue
Block a user