Initial import
This commit is contained in:
commit
d2051dcb28
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/out/
|
||||
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# CMakeList.txt : Top-level CMake project file, do global configuration
|
||||
# and include sub-projects here.
|
||||
#
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
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
|
||||
endif()
|
||||
|
||||
project ("CMakeProject1")
|
||||
|
||||
IF(WIN32)
|
||||
ADD_DEFINITIONS(/bigobj)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# Include sub-projects.
|
||||
add_subdirectory ("CMakeProject1")
|
||||
857
CMakeProject1/CCServer.cpp
Normal file
857
CMakeProject1/CCServer.cpp
Normal file
@ -0,0 +1,857 @@
|
||||
#include "CCServer.h"
|
||||
|
||||
#include "CryptoUtils.h"
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Based on Beast example: Advanced server
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/crc.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <shared_mutex>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace fs = boost::filesystem; // from <boost/filesystem.hpp>
|
||||
|
||||
namespace beast = boost::beast; // from <boost/beast.hpp>
|
||||
namespace http = beast::http; // from <boost/beast/http.hpp>
|
||||
namespace net = boost::asio; // from <boost/asio.hpp>
|
||||
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
static constexpr auto APIS_UINT8_MIN = std::numeric_limits<uint8_t>::min();
|
||||
static constexpr auto APIS_UINT8_MAX = std::numeric_limits<uint8_t>::max();
|
||||
|
||||
#define MAXHESLO 225
|
||||
#define MAX_DEKODHESLO (MAXHESLO-3)
|
||||
|
||||
#define KodcharToChar(znak2,poloha,posun) static_cast<uint8_t>(-(password[poloha])+(~(znak2))-(posun))
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static const std::string cryptFileHeader("##CAPISF## Copyright (c) 2003 APIS spol. s r.o. SLOVAKIA~");
|
||||
//static const std::string passReal("flckdscwjregfvfgbujvbnqajmadmgfjmhfmghplgghesrrhsufservvysfidgfysdnmsybsaftoprecofoplyrmnfsvcapridssedalenttrmfusposvresalbostreqnnapswolnfrdweneplmnzcavsfgusqootrpqaressnvclpacfdrgesklojphsdqtyczvxcbfhtryntinokusgkhjgchtx");
|
||||
static const uint8_t passHidden2[] = { 0x89, 0xdb, 0x2c, 0x79, 0xd6, 0xa5, 0x7a, 0x7b, 0x6d, 0xae, 0x67, 0xee, 0xb2, 0x9a, 0x2c, 0xbe, 0xb7, 0xac, 0x6a, 0x56, 0xe8, 0xb2, 0xda, 0xde, 0xaa, 0x79, 0xda, 0xa6, 0xcc, 0x28, 0x96, 0x77, 0xeb, 0x77, 0x07, 0xa7, 0x7a, 0x99, 0x66, 0x9f, 0x37, 0x1a, 0xbe, 0xc7, 0xe0, 0xba, 0xca, 0xa8, 0xa2, 0xda, 0xe9, 0xa9, 0xaa, 0xde, 0xb2, 0xc9, 0xef, 0x72, 0x5a, 0x5a, 0x71, 0xf7, 0x6b, 0x81, 0xeb, 0x24, 0x96, 0x88, 0xe9, 0x86, 0xc7, 0x6a, 0xb7, 0x27, 0x33, 0xbf, 0x17, 0x1b, 0x7e, 0x1b, 0x6b, 0xca, 0x7b, 0x62, 0x9e, 0x89, 0x2e, 0xb2, 0x09, 0x21, 0x8e, 0x07, 0x21, 0xb7, 0x10, 0x34 };
|
||||
|
||||
class apis_read_filter
|
||||
{
|
||||
public:
|
||||
typedef char char_type;
|
||||
explicit apis_read_filter(size_t initialPosition)
|
||||
: m_position(initialPosition)
|
||||
{ }
|
||||
|
||||
struct category
|
||||
: boost::iostreams::input
|
||||
, boost::iostreams::filter_tag
|
||||
, boost::iostreams::multichar_tag
|
||||
, boost::iostreams::optimally_buffered_tag
|
||||
{};
|
||||
|
||||
std::streamsize optimal_buffer_size() const { return 0; }
|
||||
|
||||
template<typename Source>
|
||||
std::streamsize read(Source& src, char_type* s, std::streamsize n)
|
||||
{
|
||||
std::streamsize result = boost::iostreams::read(src, s, n);
|
||||
if (result == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dwPacketPos = ((m_position / MAX_DEKODHESLO) % 29) + 2;
|
||||
int iPoloha = m_position % MAX_DEKODHESLO;
|
||||
|
||||
m_position += static_cast<size_t>(result);
|
||||
|
||||
for (int i = 0; i < result; i++)
|
||||
{
|
||||
if (iPoloha == MAX_DEKODHESLO)
|
||||
{
|
||||
iPoloha = 0;
|
||||
dwPacketPos++;
|
||||
}
|
||||
if (dwPacketPos >= 31)
|
||||
{
|
||||
dwPacketPos = 2;
|
||||
}
|
||||
|
||||
static const uint8_t passHidden[] = { 0x7e, 0x57, 0x24, 0x76, 0xc7, 0x30, 0x8e, 0xb7, 0xa0, 0x7e, 0xf7, 0xe0, 0x6e, 0xe8, 0xef, 0x6e, 0x7a, 0x9a, 0x8e, 0x66, 0x9d, 0x9a, 0x07, 0xe3, 0x9a, 0x17, 0xe6, 0x82, 0x1a, 0x65, 0x82, 0x08, 0x5e, 0xb2, 0xba, 0xe1, 0xb2, 0xe7, 0xec, 0x7a, 0xbb, 0xef, 0xca, 0xc7, 0xe2, 0x76, 0x07, 0xf2, 0xb1, 0xd9, 0xe6, 0xb3, 0x26, 0xec, 0x69, 0xfb, 0x68, 0xa6, 0xb7, 0x9c, 0xa1, 0xfa, 0x29, 0x97, 0x2a, 0xe6, 0x9d, 0xfb, 0x2f, 0x71, 0xaa, 0x6b };
|
||||
if (iPoloha < sizeof(passHidden) * 4 / 3)
|
||||
{
|
||||
static const auto password = base64Encode(passHidden, sizeof(passHidden));
|
||||
s[i] = KodcharToChar(s[i], iPoloha, iPoloha + dwPacketPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const auto password = base64Encode(passHidden2, sizeof(passHidden2));
|
||||
s[i] = KodcharToChar(s[i], iPoloha - sizeof(passHidden) * 4 / 3, iPoloha + dwPacketPos);
|
||||
}
|
||||
++iPoloha;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
size_t m_position;
|
||||
};
|
||||
|
||||
void decryptBuffer(std::vector<uint8_t>& buffer)
|
||||
{
|
||||
bool encrypted = false;
|
||||
if (buffer.size() >= cryptFileHeader.size())
|
||||
{
|
||||
encrypted = std::equal(cryptFileHeader.begin(), cryptFileHeader.end(), buffer.begin());
|
||||
}
|
||||
if (!encrypted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boost::iostreams::array_source src{ (const char*)buffer.data() + cryptFileHeader.size(), buffer.size() - cryptFileHeader.size()};
|
||||
boost::iostreams::filtering_istream is;
|
||||
is.push(apis_read_filter({ cryptFileHeader.size() }));
|
||||
is.push(src);
|
||||
|
||||
std::vector<uint8_t> decrypted(buffer.size() - cryptFileHeader.size());
|
||||
is.read((char*)decrypted.data(), decrypted.size());
|
||||
if (decrypted.size() > sizeof(uint32_t))
|
||||
{
|
||||
auto headerLen = reinterpret_cast<uint32_t*>(decrypted.data())[0];
|
||||
if (decrypted.size() > headerLen)
|
||||
{
|
||||
decrypted.erase(decrypted.begin(), decrypted.begin() + headerLen);
|
||||
}
|
||||
}
|
||||
buffer = decrypted;
|
||||
}
|
||||
|
||||
class etag_cache
|
||||
{
|
||||
public:
|
||||
void insert(boost::beast::string_view path, boost::beast::string_view etag)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||
map_.emplace(path, etag);
|
||||
}
|
||||
|
||||
bool check_path(boost::beast::string_view path, boost::beast::string_view etag) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lock(mutex_);
|
||||
auto it = map_.find(static_cast<std::string>(path));
|
||||
if (it != map_.end() && it->second == etag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(mutex_);
|
||||
map_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex mutex_;
|
||||
std::unordered_map<std::string, std::string> map_;
|
||||
};
|
||||
|
||||
// Return a reasonable mime type based on the extension of a file.
|
||||
beast::string_view
|
||||
mime_type(beast::string_view path)
|
||||
{
|
||||
using beast::iequals;
|
||||
auto const ext = [&path]
|
||||
{
|
||||
auto const pos = path.rfind(".");
|
||||
if (pos == beast::string_view::npos)
|
||||
return beast::string_view{};
|
||||
return path.substr(pos);
|
||||
}();
|
||||
if (iequals(ext, ".htm")) return "text/html";
|
||||
if (iequals(ext, ".html")) return "text/html";
|
||||
if (iequals(ext, ".php")) return "text/html";
|
||||
if (iequals(ext, ".css")) return "text/css";
|
||||
if (iequals(ext, ".txt")) return "text/plain";
|
||||
if (iequals(ext, ".js")) return "application/javascript";
|
||||
if (iequals(ext, ".json")) return "application/json";
|
||||
if (iequals(ext, ".xml")) return "application/xml";
|
||||
if (iequals(ext, ".swf")) return "application/x-shockwave-flash";
|
||||
if (iequals(ext, ".flv")) return "video/x-flv";
|
||||
if (iequals(ext, ".png")) return "image/png";
|
||||
if (iequals(ext, ".jpe")) return "image/jpeg";
|
||||
if (iequals(ext, ".jpeg")) return "image/jpeg";
|
||||
if (iequals(ext, ".jpg")) return "image/jpeg";
|
||||
if (iequals(ext, ".gif")) return "image/gif";
|
||||
if (iequals(ext, ".bmp")) return "image/bmp";
|
||||
if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
|
||||
if (iequals(ext, ".tiff")) return "image/tiff";
|
||||
if (iequals(ext, ".tif")) return "image/tiff";
|
||||
if (iequals(ext, ".svg")) return "image/svg+xml";
|
||||
if (iequals(ext, ".svgz")) return "image/svg+xml";
|
||||
return "application/text";
|
||||
}
|
||||
|
||||
// Append an HTTP rel-path to a local filesystem path.
|
||||
// The returned path is normalized for the platform.
|
||||
std::string
|
||||
path_cat(
|
||||
beast::string_view base,
|
||||
beast::string_view path)
|
||||
{
|
||||
if (base.empty())
|
||||
return std::string(path);
|
||||
std::string result(base);
|
||||
#ifdef BOOST_MSVC
|
||||
char constexpr path_separator = '\\';
|
||||
if (result.back() == path_separator)
|
||||
result.resize(result.size() - 1);
|
||||
result.append(path.data(), path.size());
|
||||
for (auto& c : result)
|
||||
if (c == '/')
|
||||
c = path_separator;
|
||||
#else
|
||||
char constexpr path_separator = '/';
|
||||
if (result.back() == path_separator)
|
||||
result.resize(result.size() - 1);
|
||||
result.append(path.data(), path.size());
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function produces an HTTP response for the given
|
||||
// request. The type of the response object depends on the
|
||||
// contents of the request, so the interface requires the
|
||||
// caller to pass a generic lambda for receiving the response.
|
||||
template<
|
||||
class Body, class Allocator,
|
||||
class Send>
|
||||
void
|
||||
handle_request(
|
||||
beast::string_view doc_root,
|
||||
etag_cache& cache,
|
||||
http::request<Body, http::basic_fields<Allocator>>&& req,
|
||||
Send&& send)
|
||||
{
|
||||
// Returns a bad request response
|
||||
auto const bad_request =
|
||||
[&req](beast::string_view why)
|
||||
{
|
||||
http::response<http::string_body> res{ http::status::bad_request, req.version() };
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = std::string(why);
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a not found response
|
||||
auto const not_found =
|
||||
[&req](beast::string_view target)
|
||||
{
|
||||
http::response<http::string_body> res{ http::status::not_found, req.version() };
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "The resource '" + std::string(target) + "' was not found.";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a server error response
|
||||
auto const server_error =
|
||||
[&req](beast::string_view what)
|
||||
{
|
||||
http::response<http::string_body> res{ http::status::internal_server_error, req.version() };
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "An error occurred: '" + std::string(what) + "'";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a not modified response
|
||||
auto const not_modified =
|
||||
[&req](boost::beast::string_view etag)
|
||||
{
|
||||
http::response<http::empty_body> res{ http::status::not_modified, req.version() };
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::etag, etag);
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Make sure we can handle the method
|
||||
if (req.method() != http::verb::get &&
|
||||
req.method() != http::verb::head)
|
||||
return send(bad_request("Unknown HTTP-method"));
|
||||
|
||||
// Request path must be absolute and not contain "..".
|
||||
if (req.target().empty() ||
|
||||
req.target()[0] != '/' ||
|
||||
req.target().find("..") != beast::string_view::npos)
|
||||
return send(bad_request("Illegal request-target"));
|
||||
|
||||
auto it = req.find(http::field::if_none_match);
|
||||
if (it != req.end())
|
||||
{
|
||||
auto etags = std::string(it->value());
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char>> Tokenizer;
|
||||
boost::char_separator<char> sep(", ");
|
||||
Tokenizer tok{ etags, sep };
|
||||
for (Tokenizer::iterator tokIt = tok.begin(); tokIt != tok.end(); ++tokIt)
|
||||
{
|
||||
std::string etag(*tokIt);
|
||||
boost::string_view checksum(etag);
|
||||
if (checksum.front() == '"')
|
||||
{
|
||||
checksum.remove_prefix(1);
|
||||
checksum.remove_suffix(1);
|
||||
}
|
||||
|
||||
if (cache.check_path(req.target(), checksum))
|
||||
{
|
||||
return send(not_modified(etag));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the path to the requested file
|
||||
beast::string_view targetPath = req.target();
|
||||
auto pos = targetPath.find_first_of('?');
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
targetPath = targetPath.substr(0, pos);
|
||||
}
|
||||
std::string path = path_cat(doc_root, targetPath);
|
||||
if (targetPath.back() == '/')
|
||||
path.append("index.htm");
|
||||
|
||||
// Attempt to open the file
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
{
|
||||
return send(not_found(req.target()));
|
||||
}
|
||||
|
||||
std::ifstream body(path, std::ifstream::binary);
|
||||
|
||||
body.seekg(0, std::ios::end);
|
||||
auto size = static_cast<size_t>(body.tellg());
|
||||
std::vector<uint8_t> buffer(size, 0);
|
||||
body.seekg(0);
|
||||
body.read((char*)buffer.data(), size);
|
||||
body.close();
|
||||
|
||||
decryptBuffer(buffer);
|
||||
size = buffer.size();
|
||||
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(buffer.data(), buffer.size());
|
||||
std::ostringstream checksum;
|
||||
checksum << std::hex << result.checksum();
|
||||
|
||||
auto etag = std::string("\"") + checksum.str() + "\"";
|
||||
cache.insert(req.target(), checksum.str());
|
||||
|
||||
// Respond to HEAD request
|
||||
if (req.method() == http::verb::head)
|
||||
{
|
||||
http::response<http::empty_body> res{ http::status::ok, req.version() };
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, mime_type(path));
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
|
||||
// Respond to GET request
|
||||
// TODO: replace this by decryption
|
||||
http::response<http::buffer_body> res{ http::status::ok, req.version() };
|
||||
res.set(http::field::server, "Based on " BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, mime_type(path));
|
||||
res.set(http::field::etag, etag);
|
||||
res.body().data = buffer.data();
|
||||
res.body().size = buffer.size();
|
||||
res.body().more = false;
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
{
|
||||
std::cerr << what << ": " << ec.message() << "\n";
|
||||
}
|
||||
|
||||
|
||||
// Handles an HTTP server connection
|
||||
class http_session : public std::enable_shared_from_this<http_session>
|
||||
{
|
||||
// This queue is used for HTTP pipelining.
|
||||
class queue
|
||||
{
|
||||
enum
|
||||
{
|
||||
// Maximum number of responses we will queue
|
||||
limit = 8
|
||||
};
|
||||
|
||||
// The type-erased, saved work item
|
||||
struct work
|
||||
{
|
||||
virtual ~work() = default;
|
||||
virtual void operator()() = 0;
|
||||
};
|
||||
|
||||
http_session& self_;
|
||||
std::vector<std::unique_ptr<work>> items_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
queue(http_session& self)
|
||||
: self_(self)
|
||||
{
|
||||
static_assert(limit > 0, "queue limit must be positive");
|
||||
items_.reserve(limit);
|
||||
}
|
||||
|
||||
// Returns `true` if we have reached the queue limit
|
||||
bool
|
||||
is_full() const
|
||||
{
|
||||
return items_.size() >= limit;
|
||||
}
|
||||
|
||||
// Called when a message finishes sending
|
||||
// Returns `true` if the caller should initiate a read
|
||||
bool
|
||||
on_write()
|
||||
{
|
||||
BOOST_ASSERT(!items_.empty());
|
||||
auto const was_full = is_full();
|
||||
items_.erase(items_.begin());
|
||||
if (!items_.empty())
|
||||
(*items_.front())();
|
||||
return was_full;
|
||||
}
|
||||
|
||||
// Called by the HTTP handler to send a response.
|
||||
template<bool isRequest, class Body, class Fields>
|
||||
void
|
||||
operator()(http::message<isRequest, Body, Fields>&& msg)
|
||||
{
|
||||
// This holds a work item
|
||||
struct work_impl : work
|
||||
{
|
||||
http_session& self_;
|
||||
http::message<isRequest, Body, Fields> msg_;
|
||||
|
||||
work_impl(
|
||||
http_session& self,
|
||||
http::message<isRequest, Body, Fields>&& msg)
|
||||
: self_(self)
|
||||
, msg_(std::move(msg))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
http::async_write(
|
||||
self_.stream_,
|
||||
msg_,
|
||||
beast::bind_front_handler(
|
||||
&http_session::on_write,
|
||||
self_.shared_from_this(),
|
||||
msg_.need_eof()));
|
||||
}
|
||||
};
|
||||
|
||||
// Allocate and store the work
|
||||
items_.push_back(
|
||||
boost::make_unique<work_impl>(self_, std::move(msg)));
|
||||
|
||||
// If there was no previous work, start this one
|
||||
if (items_.size() == 1)
|
||||
(*items_.front())();
|
||||
}
|
||||
};
|
||||
|
||||
beast::tcp_stream stream_;
|
||||
beast::flat_buffer buffer_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
etag_cache& etag_cache_;
|
||||
queue queue_;
|
||||
|
||||
// The parser is stored in an optional container so we can
|
||||
// construct it from scratch it at the beginning of each new message.
|
||||
boost::optional<http::request_parser<http::string_body>> parser_;
|
||||
|
||||
public:
|
||||
// Take ownership of the socket
|
||||
http_session(
|
||||
tcp::socket&& socket,
|
||||
std::shared_ptr<std::string const> const& doc_root,
|
||||
etag_cache& etag_cache)
|
||||
: stream_(std::move(socket))
|
||||
, doc_root_(doc_root)
|
||||
, etag_cache_(etag_cache)
|
||||
, queue_(*this)
|
||||
{
|
||||
}
|
||||
|
||||
// Start the session
|
||||
void
|
||||
run()
|
||||
{
|
||||
// We need to be executing within a strand to perform async operations
|
||||
// on the I/O objects in this session. Although not strictly necessary
|
||||
// for single-threaded contexts, this example code is written to be
|
||||
// thread-safe by default.
|
||||
net::dispatch(
|
||||
stream_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&http_session::do_read,
|
||||
this->shared_from_this()));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void
|
||||
do_read()
|
||||
{
|
||||
// Construct a new parser for each message
|
||||
parser_.emplace();
|
||||
|
||||
// Apply a reasonable limit to the allowed size
|
||||
// of the body in bytes to prevent abuse.
|
||||
parser_->body_limit(10000);
|
||||
|
||||
// Set the timeout.
|
||||
stream_.expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Read a request using the parser-oriented interface
|
||||
http::async_read(
|
||||
stream_,
|
||||
buffer_,
|
||||
*parser_,
|
||||
beast::bind_front_handler(
|
||||
&http_session::on_read,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_read(beast::error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
boost::ignore_unused(bytes_transferred);
|
||||
|
||||
if (ec == beast::error::timeout)
|
||||
return;
|
||||
|
||||
// This means they closed the connection
|
||||
if (ec == http::error::end_of_stream)
|
||||
return do_close();
|
||||
|
||||
if (ec)
|
||||
return fail(ec, "read");
|
||||
|
||||
// Send the response
|
||||
handle_request(*doc_root_, etag_cache_, parser_->release(), queue_);
|
||||
|
||||
// If we aren't at the queue limit, try to pipeline another request
|
||||
if (!queue_.is_full())
|
||||
do_read();
|
||||
}
|
||||
|
||||
void
|
||||
on_write(bool close, beast::error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
boost::ignore_unused(bytes_transferred);
|
||||
|
||||
if (ec == beast::error::timeout)
|
||||
return;
|
||||
|
||||
if (ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
if (close)
|
||||
{
|
||||
// This means we should close the connection, usually because
|
||||
// the response indicated the "Connection: close" semantic.
|
||||
return do_close();
|
||||
}
|
||||
|
||||
// Inform the queue that a write completed
|
||||
if (queue_.on_write())
|
||||
{
|
||||
// Read another request
|
||||
do_read();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_close()
|
||||
{
|
||||
// Send a TCP shutdown
|
||||
beast::error_code ec;
|
||||
stream_.socket().shutdown(tcp::socket::shutdown_send, ec);
|
||||
|
||||
// At this point the connection is closed gracefully
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Accepts incoming connections and launches the sessions
|
||||
class listener : public std::enable_shared_from_this<listener>
|
||||
{
|
||||
net::io_context& ioc_;
|
||||
tcp::acceptor acceptor_;
|
||||
std::shared_ptr<std::string const> doc_root_;
|
||||
etag_cache& etag_cache_;
|
||||
|
||||
public:
|
||||
listener(
|
||||
net::io_context& ioc,
|
||||
tcp::endpoint endpoint,
|
||||
std::shared_ptr<std::string const> const& doc_root,
|
||||
etag_cache& etagCache)
|
||||
: ioc_(ioc)
|
||||
, acceptor_(net::make_strand(ioc))
|
||||
, doc_root_(doc_root)
|
||||
, etag_cache_(etagCache)
|
||||
{
|
||||
beast::error_code ec;
|
||||
|
||||
// Open the acceptor
|
||||
acceptor_.open(endpoint.protocol(), ec);
|
||||
if (ec)
|
||||
{
|
||||
fail(ec, "open");
|
||||
return;
|
||||
}
|
||||
|
||||
// // Allow address reuse
|
||||
// acceptor_.set_option(net::socket_base::reuse_address(true), ec);
|
||||
// if (ec)
|
||||
// {
|
||||
// fail(ec, "set_option");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Bind to the server address
|
||||
acceptor_.bind(endpoint, ec);
|
||||
if (ec)
|
||||
{
|
||||
fail(ec, "bind");
|
||||
return;
|
||||
}
|
||||
|
||||
// Start listening for connections
|
||||
acceptor_.listen(
|
||||
net::socket_base::max_listen_connections, ec);
|
||||
if (ec)
|
||||
{
|
||||
fail(ec, "listen");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Start accepting incoming connections
|
||||
void
|
||||
run()
|
||||
{
|
||||
// We need to be executing within a strand to perform async operations
|
||||
// on the I/O objects in this session. Although not strictly necessary
|
||||
// for single-threaded contexts, this example code is written to be
|
||||
// thread-safe by default.
|
||||
net::dispatch(
|
||||
acceptor_.get_executor(),
|
||||
beast::bind_front_handler(
|
||||
&listener::do_accept,
|
||||
this->shared_from_this()));
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
do_accept()
|
||||
{
|
||||
// The new connection gets its own strand
|
||||
acceptor_.async_accept(
|
||||
net::make_strand(ioc_),
|
||||
beast::bind_front_handler(
|
||||
&listener::on_accept,
|
||||
shared_from_this()));
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(beast::error_code ec, tcp::socket socket)
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
fail(ec, "accept");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the http session and run it
|
||||
std::make_shared<http_session>(
|
||||
std::move(socket),
|
||||
doc_root_,
|
||||
etag_cache_)->run();
|
||||
}
|
||||
|
||||
// Accept another connection
|
||||
do_accept();
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class CCServerImpl final
|
||||
{
|
||||
public:
|
||||
CCServerImpl(const std::string& addressToListen, uint16_t portToListen, const std::string& docRoot, int threads)
|
||||
: m_maxThreads{std::max(1, threads)}
|
||||
, m_docRoot{ docRoot }
|
||||
, m_etagCache{}
|
||||
, m_endpoint{ boost::asio::ip::make_address(addressToListen), portToListen }
|
||||
, m_ioc{ m_maxThreads }
|
||||
, m_threads{}
|
||||
{
|
||||
}
|
||||
|
||||
~CCServerImpl()
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
std::lock_guard<std::mutex> scopeGuard(m_mutex);
|
||||
// Create and launch a listening port
|
||||
std::make_shared<listener>(
|
||||
m_ioc,
|
||||
m_endpoint,
|
||||
std::make_shared<std::string>(m_docRoot),
|
||||
m_etagCache)->run();
|
||||
|
||||
// Run the I/O service on the requested number of threads
|
||||
m_threads.reserve(m_maxThreads);
|
||||
for (auto i = m_maxThreads - 1; i >= 0; --i)
|
||||
{
|
||||
m_threads.emplace_back([&]()
|
||||
{
|
||||
m_ioc.run();
|
||||
if (i == 0)
|
||||
{
|
||||
m_onStopped();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> scopeGuard(m_mutex);
|
||||
m_ioc.stop();
|
||||
for (auto& t : m_threads)
|
||||
{
|
||||
t.join();
|
||||
}
|
||||
m_threads.clear();
|
||||
}
|
||||
|
||||
bool isRunning() const
|
||||
{
|
||||
return m_ioc.stopped();
|
||||
}
|
||||
|
||||
void clearCache()
|
||||
{
|
||||
m_etagCache.clear();
|
||||
}
|
||||
|
||||
boost::signals2::connection connectOnStopped(const boost::signals2::signal<void()>::slot_type& slot)
|
||||
{
|
||||
return m_onStopped.connect(slot);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex m_mutex;
|
||||
int m_maxThreads;
|
||||
std::string m_docRoot;
|
||||
etag_cache m_etagCache;
|
||||
tcp::endpoint m_endpoint;
|
||||
boost::asio::io_context m_ioc;
|
||||
std::vector<std::thread> m_threads;
|
||||
boost::signals2::signal<void()> m_onStopped;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
CCServer::CCServer(const std::string& addressToListen, uint16_t portToListen, const std::string& docRoot, int threads)
|
||||
: m_impl(std::make_unique<detail::CCServerImpl>(addressToListen, portToListen, docRoot, threads))
|
||||
{}
|
||||
|
||||
|
||||
CCServer::~CCServer()
|
||||
{}
|
||||
|
||||
void CCServer::shutdown()
|
||||
{
|
||||
m_impl->shutdown();
|
||||
}
|
||||
|
||||
void CCServer::clearCache()
|
||||
{
|
||||
m_impl->clearCache();
|
||||
}
|
||||
|
||||
boost::signals2::connection CCServer::connectOnStopped(const boost::signals2::signal<void()>::slot_type & slot)
|
||||
{
|
||||
return m_impl->connectOnStopped(slot);
|
||||
}
|
||||
|
||||
void CCServer::run()
|
||||
{
|
||||
m_impl->run();
|
||||
}
|
||||
|
||||
bool CCServer::isRunning() const
|
||||
{
|
||||
return m_impl->isRunning();
|
||||
}
|
||||
27
CMakeProject1/CCServer.h
Normal file
27
CMakeProject1/CCServer.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class CCServerImpl;
|
||||
}
|
||||
|
||||
class CCServer final
|
||||
{
|
||||
public:
|
||||
CCServer(const std::string& addressToListen, uint16_t portToListen, const std::string& docRoot, int threads);
|
||||
~CCServer();
|
||||
|
||||
public:
|
||||
void run();
|
||||
bool isRunning() const;
|
||||
void shutdown();
|
||||
void clearCache();
|
||||
boost::signals2::connection connectOnStopped(const boost::signals2::signal<void()>::slot_type& slot);
|
||||
|
||||
private:
|
||||
std::unique_ptr<detail::CCServerImpl> m_impl;
|
||||
};
|
||||
30
CMakeProject1/CMakeLists.txt
Normal file
30
CMakeProject1/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
# CMakeList.txt : CMake project for CMakeProject1, include source and define
|
||||
# project specific logic here.
|
||||
#
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
# Download automatically, you can also just copy the conan.cmake file
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.16.1/conan.cmake"
|
||||
"${CMAKE_BINARY_DIR}/conan.cmake"
|
||||
EXPECTED_HASH SHA256=396e16d0f5eabdc6a14afddbcfff62a54a7ee75c6da23f32f7a31bc85db23484
|
||||
TLS_VERIFY ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
|
||||
conan_cmake_run(CONANFILE conanfile.txt
|
||||
BUILD missing
|
||||
BASIC_SETUP)
|
||||
|
||||
# Add source to this project's executable.
|
||||
add_executable (CMakeProject1 "CCServer.cpp" "CCServer.h" "CryptoUtils.cpp" "CryptoUtils.h" "CMakeProject1.cpp" "CMakeProject1.h")
|
||||
|
||||
target_link_libraries(CMakeProject1 ${CONAN_LIBS})
|
||||
|
||||
# TODO: Add tests and install targets if needed.
|
||||
62
CMakeProject1/CMakeProject1.cpp
Normal file
62
CMakeProject1/CMakeProject1.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "CCServer.h"
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
namespace net = boost::asio; // from <boost/asio.hpp>
|
||||
|
||||
volatile bool signalCaught = false;
|
||||
|
||||
void signalHandler(int signum) {
|
||||
std::cout << "Interrupt signal (" << signum << ") received.\n";
|
||||
|
||||
signalCaught = true;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
// Declare the supported options.
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help", "produce help message")
|
||||
("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")
|
||||
("data_root", po::value<std::string>()->default_value("."), "root directory with data")
|
||||
("threads", po::value<int>()->default_value(4), "port")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
std::cout << desc << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("port")) {
|
||||
std::cout << "Port "
|
||||
<< vm["port"].as<uint16_t>() << ".\n";
|
||||
}
|
||||
|
||||
auto addressToListen = vm["bind_ip"].as<std::string>();
|
||||
auto portToListen = vm["port"].as<uint16_t>();
|
||||
auto docRoot = vm["data_root"].as<std::string>();
|
||||
auto threads = vm["threads"].as<int>();
|
||||
|
||||
|
||||
auto ccServer = std::make_unique<CCServer>(addressToListen, portToListen, docRoot, threads);
|
||||
ccServer->run();
|
||||
while (!signalCaught)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
ccServer->shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
CMakeProject1/CMakeProject1.h
Normal file
8
CMakeProject1/CMakeProject1.h
Normal file
@ -0,0 +1,8 @@
|
||||
// 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.
|
||||
92
CMakeProject1/CryptoUtils.cpp
Normal file
92
CMakeProject1/CryptoUtils.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "CryptoUtils.h"
|
||||
|
||||
#include <cryptopp/base64.h>
|
||||
#include <cryptopp/base32.h>
|
||||
|
||||
using CryptoPP::Base64Decoder;
|
||||
using CryptoPP::Base64Encoder;
|
||||
using CryptoPP::Base32Decoder;
|
||||
using CryptoPP::Base32Encoder;
|
||||
using CryptoPP::StringSource;
|
||||
using CryptoPP::StringSink;
|
||||
using CryptoPP::byte;
|
||||
|
||||
namespace
|
||||
{
|
||||
static const byte base32Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
}
|
||||
|
||||
std::string base64Decode(const std::string& encoded)
|
||||
{
|
||||
std::string decoded;
|
||||
|
||||
StringSource ss(encoded, true,
|
||||
new Base64Decoder(
|
||||
new StringSink(decoded)
|
||||
)
|
||||
);
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::string base64Encode(const std::string& source)
|
||||
{
|
||||
std::string encoded;
|
||||
|
||||
StringSource ss(source, true,
|
||||
new Base64Encoder(
|
||||
new StringSink(encoded),
|
||||
false /* no line breaks */
|
||||
)
|
||||
);
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> base64Encode(const uint8_t* source, size_t sourceSize)
|
||||
{
|
||||
auto encoded = std::make_unique<uint8_t[]>((sourceSize*4/3 + 3) & ~3);
|
||||
|
||||
CryptoPP::ArraySource ss(source, sourceSize, true,
|
||||
new Base64Encoder(
|
||||
new CryptoPP::ArraySink(encoded.get(), sourceSize * 4 / 3),
|
||||
false /* no line breaks */
|
||||
)
|
||||
);
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::string base32Decode(const std::string& encoded)
|
||||
{
|
||||
// Decoder
|
||||
int lookup[256] = { 0 };
|
||||
Base64Decoder::InitializeDecodingLookupArray(lookup, base32Alphabet, 32, true);
|
||||
|
||||
Base32Decoder decoder;
|
||||
CryptoPP::AlgorithmParameters params = CryptoPP::MakeParameters(CryptoPP::Name::DecodingLookupArray(), (const int *)lookup);
|
||||
decoder.IsolatedInitialize(params);
|
||||
std::string decoded;
|
||||
|
||||
decoder.Attach(new StringSink(decoded));
|
||||
decoder.Put((const byte*)encoded.data(), encoded.size());
|
||||
decoder.MessageEnd();
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::string base32Encode(const std::string& data)
|
||||
{
|
||||
// Encoder
|
||||
Base32Encoder encoder;
|
||||
CryptoPP::AlgorithmParameters params = CryptoPP::MakeParameters(CryptoPP::Name::EncodingLookupArray(), (const byte *)base32Alphabet);
|
||||
encoder.IsolatedInitialize(params);
|
||||
|
||||
std::string encoded;
|
||||
|
||||
encoder.Attach(new StringSink(encoded));
|
||||
encoder.Put((const byte*)data.data(), data.size());
|
||||
encoder.MessageEnd();
|
||||
|
||||
return encoded;
|
||||
}
|
||||
10
CMakeProject1/CryptoUtils.h
Normal file
10
CMakeProject1/CryptoUtils.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
std::string base64Decode(const std::string& encoded);
|
||||
std::string base64Encode(const std::string& source);
|
||||
std::unique_ptr<uint8_t[]> base64Encode(const uint8_t * source, size_t sourceSize);
|
||||
std::string base32Decode(const std::string& encoded);
|
||||
std::string base32Encode(const std::string& data);
|
||||
180
CMakeProject1/Makefile
Normal file
180
CMakeProject1/Makefile
Normal file
@ -0,0 +1,180 @@
|
||||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Unix Makefiles" Generator, CMake Version 3.16
|
||||
|
||||
# Default target executed when no arguments are given to make.
|
||||
default_target: all
|
||||
|
||||
.PHONY : default_target
|
||||
|
||||
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
|
||||
.NOTPARALLEL:
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets provided by cmake.
|
||||
|
||||
# Disable implicit rules so canonical targets will work.
|
||||
.SUFFIXES:
|
||||
|
||||
|
||||
# Remove some rules from gmake that .SUFFIXES does not remove.
|
||||
SUFFIXES =
|
||||
|
||||
.SUFFIXES: .hpux_make_needs_suffix_list
|
||||
|
||||
|
||||
# Suppress display of executed commands.
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
|
||||
# A target that is always out of date.
|
||||
cmake_force:
|
||||
|
||||
.PHONY : cmake_force
|
||||
|
||||
#=============================================================================
|
||||
# Set environment variables for the build.
|
||||
|
||||
# The shell in which to execute make rules.
|
||||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/bin/cmake -E remove -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
||||
# The top-level source directory on which CMake was run.
|
||||
CMAKE_SOURCE_DIR = /mnt/c/Users/petos/source/repos/CMakeProject1
|
||||
|
||||
# The top-level build directory on which CMake was run.
|
||||
CMAKE_BINARY_DIR = /mnt/c/Users/petos/source/repos/CMakeProject1
|
||||
|
||||
#=============================================================================
|
||||
# Targets provided globally by CMake.
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/usr/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
|
||||
/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache/fast: edit_cache
|
||||
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(CMAKE_COMMAND) -E cmake_progress_start /mnt/c/Users/petos/source/repos/CMakeProject1/CMakeFiles /mnt/c/Users/petos/source/repos/CMakeProject1/CMakeProject1/CMakeFiles/progress.marks
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeFiles/Makefile2 CMakeProject1/all
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /mnt/c/Users/petos/source/repos/CMakeProject1/CMakeFiles 0
|
||||
.PHONY : all
|
||||
|
||||
# The main clean target
|
||||
clean:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeFiles/Makefile2 CMakeProject1/clean
|
||||
.PHONY : clean
|
||||
|
||||
# The main clean target
|
||||
clean/fast: clean
|
||||
|
||||
.PHONY : clean/fast
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall: all
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeFiles/Makefile2 CMakeProject1/preinstall
|
||||
.PHONY : preinstall
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall/fast:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeFiles/Makefile2 CMakeProject1/preinstall
|
||||
.PHONY : preinstall/fast
|
||||
|
||||
# clear depends
|
||||
depend:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
|
||||
.PHONY : depend
|
||||
|
||||
# Convenience name for target.
|
||||
CMakeProject1/CMakeFiles/CMakeProject1.dir/rule:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeFiles/Makefile2 CMakeProject1/CMakeFiles/CMakeProject1.dir/rule
|
||||
.PHONY : CMakeProject1/CMakeFiles/CMakeProject1.dir/rule
|
||||
|
||||
# Convenience name for target.
|
||||
CMakeProject1: CMakeProject1/CMakeFiles/CMakeProject1.dir/rule
|
||||
|
||||
.PHONY : CMakeProject1
|
||||
|
||||
# fast build rule for target.
|
||||
CMakeProject1/fast:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeProject1/CMakeFiles/CMakeProject1.dir/build.make CMakeProject1/CMakeFiles/CMakeProject1.dir/build
|
||||
.PHONY : CMakeProject1/fast
|
||||
|
||||
CMakeProject1.o: CMakeProject1.cpp.o
|
||||
|
||||
.PHONY : CMakeProject1.o
|
||||
|
||||
# target to build an object file
|
||||
CMakeProject1.cpp.o:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeProject1/CMakeFiles/CMakeProject1.dir/build.make CMakeProject1/CMakeFiles/CMakeProject1.dir/CMakeProject1.cpp.o
|
||||
.PHONY : CMakeProject1.cpp.o
|
||||
|
||||
CMakeProject1.i: CMakeProject1.cpp.i
|
||||
|
||||
.PHONY : CMakeProject1.i
|
||||
|
||||
# target to preprocess a source file
|
||||
CMakeProject1.cpp.i:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeProject1/CMakeFiles/CMakeProject1.dir/build.make CMakeProject1/CMakeFiles/CMakeProject1.dir/CMakeProject1.cpp.i
|
||||
.PHONY : CMakeProject1.cpp.i
|
||||
|
||||
CMakeProject1.s: CMakeProject1.cpp.s
|
||||
|
||||
.PHONY : CMakeProject1.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
CMakeProject1.cpp.s:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(MAKE) -f CMakeProject1/CMakeFiles/CMakeProject1.dir/build.make CMakeProject1/CMakeFiles/CMakeProject1.dir/CMakeProject1.cpp.s
|
||||
.PHONY : CMakeProject1.cpp.s
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
@echo "The following are some of the valid targets for this Makefile:"
|
||||
@echo "... all (the default if no target is provided)"
|
||||
@echo "... clean"
|
||||
@echo "... depend"
|
||||
@echo "... rebuild_cache"
|
||||
@echo "... edit_cache"
|
||||
@echo "... CMakeProject1"
|
||||
@echo "... CMakeProject1.o"
|
||||
@echo "... CMakeProject1.i"
|
||||
@echo "... CMakeProject1.s"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets to cleanup operation of make.
|
||||
|
||||
# Special rule to run CMake to check the build system integrity.
|
||||
# No rule that depends on this can have commands that come from listfiles
|
||||
# because they might be regenerated.
|
||||
cmake_check_build_system:
|
||||
cd /mnt/c/Users/petos/source/repos/CMakeProject1 && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
.PHONY : cmake_check_build_system
|
||||
|
||||
10
CMakeProject1/conanfile.txt
Normal file
10
CMakeProject1/conanfile.txt
Normal file
@ -0,0 +1,10 @@
|
||||
[requires]
|
||||
boost/1.76.0
|
||||
cryptopp/8.5.0
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
|
||||
[options]
|
||||
boost:shared=False
|
||||
cryptopp:shared=False
|
||||
88
CMakeSettings.json
Normal file
88
CMakeSettings.json
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_SYSTEM_VERSION",
|
||||
"value": "8.1",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "WSL-GCC-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeExecutable": "cmake",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "linux_x64" ],
|
||||
"wslPath": "${defaultWSLPath}"
|
||||
},
|
||||
{
|
||||
"name": "WSL-GCC-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeExecutable": "cmake",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "linux_x64" ],
|
||||
"wslPath": "${defaultWSLPath}",
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS_RELEASE",
|
||||
"value": "-O3 -DNDEBUG -DBOOST_EXCEPTION_DISABLE=1 -DBOOST_NO_RTTI=1 -flto",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELEASE",
|
||||
"value": "-s -flto -Wl,-rpath=.",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "CMAKE_SYSTEM_VERSION",
|
||||
"value": "8.1",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELEASE",
|
||||
"value": "/INCREMENTAL:NO /ASSEMBLYDEBUG:DISABLE /OPT:REF /DEBUG:NONE /PDBSTRIPPED:YES",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS_RELEASE",
|
||||
"value": "/MD /O2 /Ob2 /DNDEBUG /DBOOST_EXCEPTION_DISABLE=1",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user