cmake: Further refactoring and formatting

This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2020-01-23 01:51:15 +01:00
parent 3dd8e1e102
commit acd4d4b356
22 changed files with 235 additions and 224 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
# Basic Formatting # Basic Formatting
TabWidth: 8 TabWidth: 4
UseTab: ForIndentation UseTab: ForContinuationAndIndentation
ColumnLimit: 120 ColumnLimit: 120
# Language # Language
@@ -13,7 +13,7 @@ ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
IndentCaseLabels: false IndentCaseLabels: false
#IndentPPDirectives: true #IndentPPDirectives: true
IndentWidth: 8 IndentWidth: 4
IndentWrappedFunctionNames: true IndentWrappedFunctionNames: true
NamespaceIndentation: All NamespaceIndentation: All
@@ -30,7 +30,7 @@ SortIncludes: true
AlignAfterOpenBracket: true AlignAfterOpenBracket: true
AlignConsecutiveAssignments: true AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true AlignConsecutiveDeclarations: true
AlignEscapedNewlines: DontAlign AlignEscapedNewlines: Left
AlignOperands: true AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
DerivePointerAlignment: false DerivePointerAlignment: false
+10
View File
@@ -0,0 +1,10 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file.
[*]
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
indent_size = 4
+112 -96
View File
@@ -91,25 +91,26 @@ endif()
# Options # Options
#================================================================================# #================================================================================#
# Static or Dynamic? # Static or Dynamic?
option(${PropertyPrefix}MAKE_STATIC "Make Static Library" ON) option(${PropertyPrefix}MAKE_DYNAMIC "Create dynamically linked library instead of static library." OFF)
option(${PropertyPrefix}MAKE_DYNAMIC "Make Dynamic Library" OFF) option(${PropertyPrefix}MAKE_MODULE "Create dynamically linked module instead of dynamically linked library." OFF)
option(${PropertyPrefix}MAKE_MODULE "Make Module Library" OFF) option(${PropertyPrefix}BUILD_SAMPLES "Build Samples" ON)
#================================================================================# #================================================================================#
# Sources # Sources
option(${PropertyPrefix}BUILD_SAMPLES "Build Samples" ON) #================================================================================#
# Configure Version Header # Configure Version Header
configure_file( configure_file(
"${PROJECT_SOURCE_DIR}/cmake/version.hpp.in" "${PROJECT_SOURCE_DIR}/cmake/version.hpp.in"
"${PROJECT_BINARY_DIR}/include/version.hpp" "${PROJECT_BINARY_DIR}/generated/version.hpp"
) )
# Public (exported with module) # Source Files
set(PROJECT_PUBLIC set(PROJECT_PUBLIC "")
"include/bitmask.hpp" list(APPEND PROJECT_PUBLIC
"include/datapath.hpp" "include/datapath.hpp"
"include/error.hpp" "include/error.hpp"
"include/bitmask.hpp"
"include/event.hpp" "include/event.hpp"
"include/isocket.hpp" "include/isocket.hpp"
"include/iserver.hpp" "include/iserver.hpp"
@@ -119,27 +120,30 @@ set(PROJECT_PUBLIC
"include/threadpool.hpp" "include/threadpool.hpp"
) )
set(PROJECT_PUBLIC_GENERATED set(PROJECT_PRIVATE "")
"${PROJECT_BINARY_DIR}/include/version.hpp" list(APPEND PROJECT_PRIVATE
"source/threadpool.cpp"
) )
set(PROJECT_DATA set(PROJECT_TEMPLATES "")
list(APPEND PROJECT_TEMPLATES
"${PROJECT_SOURCE_DIR}/cmake/version.hpp.in"
)
set(PROJECT_GENERATED "")
list(APPEND PROJECT_GENERATED
"${PROJECT_BINARY_DIR}/generated/version.hpp"
)
set(PROJECT_DATA "")
list(APPEND PROJECT_DATA
"README.md" "README.md"
"LICENSE" "LICENSE"
) )
# Private (only compiled/used locally) set(PROJECT_LIBRARIES "")
set(PROJECT_PRIVATE
"source/threadpool.cpp"
)
# Libraries set(PROJECT_DEFINES "")
set(PROJECT_LIBRARIES
)
# Defines
set(PROJECT_DEFINES
)
# Platforms # Platforms
if(WIN32) if(WIN32)
@@ -150,48 +154,48 @@ if(WIN32)
list(APPEND PROJECT_DEFINES list(APPEND PROJECT_DEFINES
_CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_WARNINGS
WIN32_LEAN_AND_MEAN WIN32_LEAN_AND_MEAN
NOGPICAPMASKS NOGPICAPMASKS
NOVIRTUALKEYCODES NOVIRTUALKEYCODES
NOWINMESSAGES NOWINMESSAGES
NOWINSTYLES NOWINSTYLES
NOSYSMETRICS NOSYSMETRICS
NOMENUS NOMENUS
NOICONS NOICONS
NOKEYSTATES NOKEYSTATES
NOSYSCOMMANDS NOSYSCOMMANDS
NORASTEROPS NORASTEROPS
NOSHOWWINDOW NOSHOWWINDOW
NOATOM NOATOM
NOCLIPBOARD NOCLIPBOARD
NOCOLOR NOCOLOR
NOCTLMGR NOCTLMGR
NODRAWTEXT NODRAWTEXT
NOGDI NOGDI
NOKERNEL NOKERNEL
#NOUSER #NOUSER
#NONLS #NONLS
NOMB NOMB
NOMEMMGR NOMEMMGR
NOMETAFILE NOMETAFILE
NOMINMAX NOMINMAX
NOMSG NOMSG
NOOPENFILE NOOPENFILE
NOSCROLL NOSCROLL
NOSERVICE NOSERVICE
NOSOUND NOSOUND
NOTEXTMETRIC NOTEXTMETRIC
NOWH NOWH
NOWINOFFSETS NOWINOFFSETS
NOCOMM NOCOMM
NOKANJI NOKANJI
NOHELP NOHELP
NOPROFILER NOPROFILER
NODEFERWINDOWPOS NODEFERWINDOWPOS
NOMCX NOMCX
NOIME NOIME
NOMDI NOMDI
NOINOUT NOINOUT
) )
list(APPEND PROJECT_PRIVATE list(APPEND PROJECT_PRIVATE
@@ -225,45 +229,58 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
endif() endif()
# Grouping # Grouping
source_group("Data Files" FILES $PROJECT_DATA) source_group(TREE "${PROJECT_SOURCE_DIR}" PREFIX "Data Files" FILES ${PROJECT_DATA})
source_group(TREE "${PROJECT_SOURCE_DIR}/source" PREFIX "Source" FILES ${PROJECT_PRIVATE}) source_group(TREE "${PROJECT_SOURCE_DIR}/cmake" PREFIX "Template Files" FILES ${PROJECT_TEMPLATES})
source_group(TREE "${PROJECT_SOURCE_DIR}/include" PREFIX "Include" FILES ${PROJECT_PUBLIC}) source_group(TREE "${PROJECT_BINARY_DIR}/generated" PREFIX "Generated Files" FILES ${PROJECT_GENERATED})
source_group(TREE "${PROJECT_BINARY_DIR}" PREFIX "Generated" FILES ${PROJECT_PUBLIC_GENERATED}) source_group(TREE "${PROJECT_SOURCE_DIR}/include" PREFIX "Exported Files" FILES ${PROJECT_PUBLIC})
# Filter Sources
set(_TMP_SOURCE ${PROJECT_PRIVATE})
list(FILTER _TMP_SOURCE INCLUDE REGEX "\.(c|cpp)$")
source_group(TREE "${PROJECT_SOURCE_DIR}/source" PREFIX "Source Files" FILES ${_TMP_SOURCE})
# Filter Headers
set(_TMP_HEADER ${PROJECT_PRIVATE})
list(FILTER _TMP_HEADER INCLUDE REGEX "\.(h|hpp)$")
source_group(TREE "${PROJECT_SOURCE_DIR}/source" PREFIX "Header Files" FILES ${_TMP_HEADER})
#================================================================================# #================================================================================#
# Building # Building
#================================================================================# #================================================================================#
# Library definition # Library definition
if(${PropertyPrefix}MAKE_STATIC) set(_BUILD_TYPE)
add_library(${PROJECT_NAME} STATIC if(${PropertyPrefix}MAKE_DYNAMIC)
${PROJECT_PRIVATE} if(${PropertyPrefix}MAKE_MODULE)
${PROJECT_PUBLIC} set(_BUILD_TYPE MODULE)
${PROJECT_PUBLIC_GENERATED} else()
${PROJECT_DATA} set(_BUILD_TYPE SHARED)
) endif()
elseif(${PropertyPrefix}MAKE_DYNAMIC)
add_library(${PROJECT_NAME} SHARED
${PROJECT_PRIVATE}
${PROJECT_PUBLIC}
${PROJECT_PUBLIC_GENERATED}
${PROJECT_DATA}
)
elseif(${PropertyPrefix}MAKE_MODULE)
add_library(${PROJECT_NAME} MODULE
${PROJECT_PRIVATE}
${PROJECT_PUBLIC}
${PROJECT_PUBLIC_GENERATED}
${PROJECT_DATA}
)
else() else()
message(CRITICAL "Building nothing completed, aborting. Check MAKE_STATIC, MAKE_DYNAMIC and MAKE_DYNAMIC.") set(_BUILD_TYPE STATIC)
return() endif()
add_library(${PROJECT_NAME} ${_BUILD_TYPE}
${PROJECT_PUBLIC}
${PROJECT_PRIVATE}
${PROJECT_GENERATED}
${PROJECT_TEMPLATES}
${PROJECT_DATA}
)
# Clang
if("${PropertyPrefix}" STREQUAL "")
clang_format(
TARGETS ${PROJECT_NAME}
DEPENDENCY
VERSION 9.0.0
)
endif() endif()
# Includes # Includes
target_include_directories(${PROJECT_NAME} target_include_directories(${PROJECT_NAME}
PRIVATE source PRIVATE "source"
PUBLIC include PUBLIC "include"
) )
# Defines # Defines
@@ -297,10 +314,9 @@ else()
) )
endif() endif()
#================================================================================#
################################################################################
# Samples # Samples
################################################################################ #================================================================================#
if(${PropertyPrefix}BUILD_SAMPLES) if(${PropertyPrefix}BUILD_SAMPLES)
add_subdirectory(${PROJECT_SOURCE_DIR}/samples) add_subdirectory(${PROJECT_SOURCE_DIR}/samples)
endif() endif()
+2 -2
View File
@@ -38,8 +38,8 @@ typename std::enable_if<enable_bitmask_operators<Enum>::enable, Enum>::type oper
return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs)); return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
} }
#define ENABLE_BITMASK_OPERATORS(x) \ #define ENABLE_BITMASK_OPERATORS(x) \
template<> \ template<> \
struct enable_bitmask_operators<x> { \ struct enable_bitmask_operators<x> { \
static const bool enable = true; \ static const bool enable = true; \
}; };
+1 -1
View File
@@ -27,5 +27,5 @@ namespace datapath {
datapath::error connect(std::shared_ptr<datapath::isocket>& socket, std::string path); datapath::error connect(std::shared_ptr<datapath::isocket>& socket, std::string path);
datapath::error host(std::shared_ptr<datapath::iserver>& server, std::string path, datapath::error host(std::shared_ptr<datapath::iserver>& server, std::string path,
datapath::permissions permissions, size_t max_clients = 0); datapath::permissions permissions, size_t max_clients = 0);
} // namespace datapath } // namespace datapath
+17 -17
View File
@@ -24,10 +24,10 @@
namespace datapath { namespace datapath {
template<typename... _args> template<typename... _args>
class event { class event {
std::list<std::function<void(_args...)>> listeners; std::list<std::function<void(_args...)>> _listeners;
std::function<void()> listen_cb; std::function<void()> _listen_cb;
std::function<void()> silence_cb; std::function<void()> _silence_cb;
public /* functions */: public /* functions */:
@@ -40,20 +40,20 @@ namespace datapath {
// Add new listener. // Add new listener.
inline void add(std::function<void(_args...)> listener) inline void add(std::function<void(_args...)> listener)
{ {
if (listeners.size() == 0) { if (_listeners.size() == 0) {
if (listen_cb) { if (_listen_cb) {
listen_cb(); _listen_cb();
} }
} }
listeners.push_back(listener); _listeners.push_back(listener);
} }
// Remove existing listener. // Remove existing listener.
inline void remove(std::function<void(_args...)> listener) inline void remove(std::function<void(_args...)> listener)
{ {
listeners.remove(listener); _listeners.remove(listener);
if (listeners.size() == 0) { if (_listeners.size() == 0) {
if (silence_cb) { if (_silence_cb) {
silence_cb(); silence_cb();
} }
} }
@@ -62,15 +62,15 @@ namespace datapath {
// Check if empty / no listeners. // Check if empty / no listeners.
inline bool empty() inline bool empty()
{ {
return listeners.empty(); return _listeners.empty();
} }
// Remove all listeners. // Remove all listeners.
inline void clear() inline void clear()
{ {
listeners.clear(); _listeners.clear();
if (silence_cb) { if (_silence_cb) {
silence_cb(); _silence_cb();
} }
} }
@@ -80,7 +80,7 @@ namespace datapath {
template<typename... _largs> template<typename... _largs>
inline void operator()(_args... args) inline void operator()(_args... args)
{ {
for (auto& l : listeners) { for (auto& l : _listeners) {
l(args...); l(args...);
} }
} }
@@ -108,12 +108,12 @@ namespace datapath {
public /* events */: public /* events */:
void set_listen_callback(std::function<void()> cb) void set_listen_callback(std::function<void()> cb)
{ {
this->listen_cb = cb; this->_listen_cb = cb;
} }
void set_silence_callback(std::function<void()> cb) void set_silence_callback(std::function<void()> cb)
{ {
this->silence_cb = cb; this->_silence_cb = cb;
} }
}; };
}; // namespace datapath }; // namespace datapath
+1 -1
View File
@@ -33,7 +33,7 @@ namespace datapath {
* @param std::shared_ptr<datapath::isocket> Socket. * @param std::shared_ptr<datapath::isocket> Socket.
* @return void * @return void
*/ */
datapath::event<bool&, std::shared_ptr<datapath::isocket>> on_accept; datapath::event<bool&, std::shared_ptr<datapath::isocket>> _on_accept;
public: public:
virtual datapath::error close() = 0; virtual datapath::error close() = 0;
+2 -2
View File
@@ -24,9 +24,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
namespace datapath { namespace datapath {
class isocket { class isocket {
public /*events*/: public /*events*/:
datapath::event<const std::vector<char>&> on_message; datapath::event<const std::vector<char>&> _on_message;
datapath::event<> on_close; datapath::event<> _on_close;
public: public:
virtual bool good() = 0; virtual bool good() = 0;
+2 -2
View File
@@ -26,9 +26,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
namespace datapath { namespace datapath {
class itask : public waitable { class itask : public waitable {
public /*event*/: public /*event*/:
datapath::event<datapath::error> on_failure; datapath::event<datapath::error> _on_failure;
datapath::event<datapath::error, const std::vector<char>&> on_success; datapath::event<datapath::error, const std::vector<char>&> _on_success;
public: public:
virtual datapath::error cancel() = 0; virtual datapath::error cancel() = 0;
+1 -7
View File
@@ -21,12 +21,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "bitmask.hpp" #include "bitmask.hpp"
namespace datapath { namespace datapath {
enum class permissions : int8_t { enum class permissions : int8_t { None, User, Group, World, Reserved };
None,
User,
Group,
World,
Reserved
};
ENABLE_BITMASK_OPERATORS(datapath::permissions); ENABLE_BITMASK_OPERATORS(datapath::permissions);
} // namespace datapath } // namespace datapath
+3 -2
View File
@@ -19,6 +19,7 @@
#pragma once #pragma once
#include <condition_variable> #include <condition_variable>
#include <functional>
#include <list> #include <list>
#include <map> #include <map>
#include <mutex> #include <mutex>
@@ -28,7 +29,7 @@
namespace datapath { namespace datapath {
namespace threadpool { namespace threadpool {
typedef uint64_t affinity_t; typedef uint64_t affinity_t;
constexpr affinity_t default_mask = std::numeric_limits<affinity_t>::max(); constexpr affinity_t default_mask = std::numeric_limits<affinity_t>::max();
@@ -58,7 +59,7 @@ namespace datapath {
void push(std::shared_ptr<task> task); void push(std::shared_ptr<task> task);
}; };
std::map<affinity_t, std::shared_ptr<worker>> workers; std::map<affinity_t, std::shared_ptr<worker>> _workers;
public: public:
pool(); pool();
+7 -7
View File
@@ -25,9 +25,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
namespace datapath { namespace datapath {
class waitable { class waitable {
public /*events*/: public /*events*/:
datapath::event<datapath::error> on_wait_error; datapath::event<datapath::error> _on_wait_error;
datapath::event<datapath::error> on_wait_success; datapath::event<datapath::error> _on_wait_success;
public: public:
virtual void* get_waitable() = 0; virtual void* get_waitable() = 0;
@@ -40,22 +40,22 @@ namespace datapath {
public /*static*/: public /*static*/:
static datapath::error wait(datapath::waitable* obj, static datapath::error wait(datapath::waitable* obj,
std::chrono::nanoseconds duration = std::chrono::nanoseconds(0)); std::chrono::nanoseconds duration = std::chrono::nanoseconds(0));
static datapath::error wait(datapath::waitable** objs, size_t count, static datapath::error wait(datapath::waitable** objs, size_t count,
std::chrono::nanoseconds duration = std::chrono::nanoseconds(0)); std::chrono::nanoseconds duration = std::chrono::nanoseconds(0));
static inline datapath::error wait(std::vector<datapath::waitable*> objs, static inline datapath::error wait(std::vector<datapath::waitable*> objs,
std::chrono::nanoseconds duration = std::chrono::nanoseconds(0)) std::chrono::nanoseconds duration = std::chrono::nanoseconds(0))
{ {
return datapath::waitable::wait(objs.data(), objs.size(), duration); return datapath::waitable::wait(objs.data(), objs.size(), duration);
} }
static datapath::error wait_any(datapath::waitable** objs, size_t count, size_t& index, static datapath::error wait_any(datapath::waitable** objs, size_t count, size_t& index,
std::chrono::nanoseconds duration = std::chrono::nanoseconds(0)); std::chrono::nanoseconds duration = std::chrono::nanoseconds(0));
static inline datapath::error wait_any(std::vector<datapath::waitable*> objs, size_t& index, static inline datapath::error wait_any(std::vector<datapath::waitable*> objs, size_t& index,
std::chrono::nanoseconds duration = std::chrono::nanoseconds(0)) std::chrono::nanoseconds duration = std::chrono::nanoseconds(0))
{ {
return datapath::waitable::wait_any(objs.data(), objs.size(), index, duration); return datapath::waitable::wait_any(objs.data(), objs.size(), index, duration);
} }
+8 -9
View File
@@ -65,8 +65,7 @@ void datapath::threadpool::pool::worker::runner()
my_task.reset(); my_task.reset();
} }
if (this->queue.size() == 0) { if (this->queue.size() == 0) {
this->signal.wait(slock, this->signal.wait(slock, [this]() { return (this->should_stop) || (this->queue.size() > 0); });
[this]() { return (this->should_stop) || (this->queue.size() > 0); });
} }
} }
} }
@@ -94,13 +93,13 @@ datapath::threadpool::pool::pool()
uint64_t num_hw_concurrency = std::thread::hardware_concurrency(); uint64_t num_hw_concurrency = std::thread::hardware_concurrency();
for (uint64_t idx = 0; idx < num_hw_concurrency; idx++) { for (uint64_t idx = 0; idx < num_hw_concurrency; idx++) {
auto worker = std::make_shared<datapath::threadpool::pool::worker>(1 << idx); auto worker = std::make_shared<datapath::threadpool::pool::worker>(1 << idx);
this->workers.insert({idx, worker}); this->_workers.insert({idx, worker});
} }
} }
datapath::threadpool::pool::~pool() datapath::threadpool::pool::~pool()
{ {
this->workers.clear(); this->_workers.clear();
} }
bool datapath::threadpool::pool::push(std::shared_ptr<task> task) bool datapath::threadpool::pool::push(std::shared_ptr<task> task)
@@ -114,13 +113,13 @@ bool datapath::threadpool::pool::push(std::shared_ptr<task> task)
throw std::invalid_argument("task->function must not be nullptr"); throw std::invalid_argument("task->function must not be nullptr");
} }
/// Check for invalid affinity masks. /// Check for invalid affinity masks.
if ((task->mask & (this->workers.size() - 1)) == 0) { if ((task->mask & (this->_workers.size() - 1)) == 0) {
throw std::invalid_argument("mask does not fit any thread"); throw std::invalid_argument("mask does not fit any thread");
} }
affinity_t lowest_id; affinity_t lowest_id;
size_t lowest_count = std::numeric_limits<size_t>::max(); size_t lowest_count = std::numeric_limits<size_t>::max();
for (auto kv : workers) { for (auto kv : _workers) {
if ((kv.second->affinity & task->mask) == 0) { if ((kv.second->affinity & task->mask) == 0) {
continue; continue;
} }
@@ -135,18 +134,18 @@ bool datapath::threadpool::pool::push(std::shared_ptr<task> task)
return false; return false;
} }
this->workers[lowest_id]->push(task); this->_workers[lowest_id]->push(task);
return true; return true;
} }
void datapath::threadpool::pool::clear(affinity_t mask) void datapath::threadpool::pool::clear(affinity_t mask)
{ {
// Early-Exit tests. // Early-Exit tests.
if ((mask & (this->workers.size() - 1)) == 0) { if ((mask & (this->_workers.size() - 1)) == 0) {
throw std::invalid_argument("mask does not fit any thread"); throw std::invalid_argument("mask does not fit any thread");
} }
for (auto kv : workers) { for (auto kv : _workers) {
if ((kv.second->affinity & mask) == 0) { if ((kv.second->affinity & mask) == 0) {
continue; continue;
} }
+1 -1
View File
@@ -26,7 +26,7 @@ datapath::error datapath::connect(std::shared_ptr<datapath::isocket>& socket, st
} }
datapath::error datapath::host(std::shared_ptr<datapath::iserver>& server, std::string path, datapath::error datapath::host(std::shared_ptr<datapath::iserver>& server, std::string path,
datapath::permissions permissions, size_t max_clients) datapath::permissions permissions, size_t max_clients)
{ {
return datapath::windows::server::host(server, path, permissions, max_clients); return datapath::windows::server::host(server, path, permissions, max_clients);
} }
+13 -18
View File
@@ -26,7 +26,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define WIN_BACKLOG_NUM 8 #define WIN_BACKLOG_NUM 8
datapath::error datapath::windows::server::create(std::string path, datapath::permissions permissions, datapath::error datapath::windows::server::create(std::string path, datapath::permissions permissions,
size_t max_clients) size_t max_clients)
{ {
// If old sockets are available, close them. // If old sockets are available, close them.
this->close(); this->close();
@@ -84,8 +84,8 @@ HANDLE datapath::windows::server::_create_socket(std::string path, bool initial)
DWORD pipe_flags = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT; DWORD pipe_flags = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
HANDLE handle = CreateNamedPipeW(wpath.c_str(), file_flags, pipe_flags, PIPE_UNLIMITED_INSTANCES, HANDLE handle = CreateNamedPipeW(wpath.c_str(), file_flags, pipe_flags, PIPE_UNLIMITED_INSTANCES, WIN_BUFFER_SIZE,
WIN_BUFFER_SIZE, WIN_BUFFER_SIZE, WIN_WAIT_TIME, &this->security_attributes); WIN_BUFFER_SIZE, WIN_WAIT_TIME, &this->security_attributes);
return handle; return handle;
} }
@@ -105,7 +105,7 @@ void datapath::windows::server::_watcher()
} }
size_t index = 0; size_t index = 0;
datapath::error ec = datapath::waitable::wait_any(waits, index, std::chrono::milliseconds(0)); datapath::error ec = datapath::waitable::wait_any(waits, index, std::chrono::milliseconds(0));
if (ec != datapath::error::Success) { if (ec != datapath::error::Success) {
datapath::waitable::wait_any(waits, index, std::chrono::milliseconds(1)); datapath::waitable::wait_any(waits, index, std::chrono::milliseconds(1));
} }
@@ -122,7 +122,7 @@ void datapath::windows::server::_watcher()
auto ov = std::make_shared<datapath::windows::overlapped>(); auto ov = std::make_shared<datapath::windows::overlapped>();
ov->set_handle(handle); ov->set_handle(handle);
ov->set_data(this); ov->set_data(this);
ov->on_wait_success.add([this, &ovmap, &itr, &handle](datapath::error ec) { ov->_on_wait_success.add([this, &ovmap, &itr, &handle](datapath::error ec) {
std::unique_lock<std::mutex> ul(this->lock); std::unique_lock<std::mutex> ul(this->lock);
this->waiting_sockets.erase(itr); this->waiting_sockets.erase(itr);
this->pending_sockets.push_back(handle); this->pending_sockets.push_back(handle);
@@ -152,9 +152,8 @@ void datapath::windows::server::_watcher()
std::unique_lock<std::mutex> ul(this->lock); std::unique_lock<std::mutex> ul(this->lock);
std::list<HANDLE> to_kill; std::list<HANDLE> to_kill;
if (this->on_accept) { if (this->_on_accept) {
for (auto itr = this->pending_sockets.begin(); itr != this->pending_sockets.end(); for (auto itr = this->pending_sockets.begin(); itr != this->pending_sockets.end(); itr++) {
itr++) {
HANDLE handle = *itr; HANDLE handle = *itr;
bool accept = true; bool accept = true;
@@ -162,16 +161,14 @@ void datapath::windows::server::_watcher()
sock->_connect(handle); sock->_connect(handle);
auto isock = std::dynamic_pointer_cast<datapath::isocket>(sock); auto isock = std::dynamic_pointer_cast<datapath::isocket>(sock);
this->on_accept(accept, isock); this->_on_accept(accept, isock);
if (accept) { if (accept) {
to_kill.push_back(handle); to_kill.push_back(handle);
this->active_sockets.insert({handle, sock}); this->active_sockets.insert({handle, sock});
if ((this->waiting_sockets.size() + this->pending_sockets.size()) if ((this->waiting_sockets.size() + this->pending_sockets.size()) < WIN_BACKLOG_NUM) {
< WIN_BACKLOG_NUM) { if ((this->sockets.size() <= this->max_clients) && (this->max_clients > 0)) {
if ((this->sockets.size() <= this->max_clients)
&& (this->max_clients > 0)) {
HANDLE handle = _create_socket(this->path, false); HANDLE handle = _create_socket(this->path, false);
if (handle != INVALID_HANDLE_VALUE) { if (handle != INVALID_HANDLE_VALUE) {
this->sockets.push_back(handle); this->sockets.push_back(handle);
@@ -199,8 +196,7 @@ void datapath::windows::server::_watcher()
for (auto itr = this->active_sockets.begin(); itr != this->active_sockets.end(); itr++) { for (auto itr = this->active_sockets.begin(); itr != this->active_sockets.end(); itr++) {
if (itr->second.expired()) { if (itr->second.expired()) {
// Enforce backlog size // Enforce backlog size
if ((this->waiting_sockets.size() + this->pending_sockets.size()) if ((this->waiting_sockets.size() + this->pending_sockets.size()) < WIN_BACKLOG_NUM) {
< WIN_BACKLOG_NUM) {
this->waiting_sockets.push_back(itr->first); this->waiting_sockets.push_back(itr->first);
} else { } else {
DisconnectNamedPipe(itr->first); DisconnectNamedPipe(itr->first);
@@ -213,8 +209,7 @@ void datapath::windows::server::_watcher()
auto obj = itr->second.lock(); auto obj = itr->second.lock();
if (!obj->good()) { if (!obj->good()) {
// Enforce backlog size // Enforce backlog size
if ((this->waiting_sockets.size() + this->pending_sockets.size()) if ((this->waiting_sockets.size() + this->pending_sockets.size()) < WIN_BACKLOG_NUM) {
< WIN_BACKLOG_NUM) {
this->waiting_sockets.push_back(itr->first); this->waiting_sockets.push_back(itr->first);
} else { } else {
DisconnectNamedPipe(itr->first); DisconnectNamedPipe(itr->first);
@@ -299,7 +294,7 @@ datapath::error datapath::windows::server::close()
} }
datapath::error datapath::windows::server::host(std::shared_ptr<datapath::iserver>& server, std::string path, datapath::error datapath::windows::server::host(std::shared_ptr<datapath::iserver>& server, std::string path,
datapath::permissions permissions, size_t max_clients) datapath::permissions permissions, size_t max_clients)
{ {
if (!server) { if (!server) {
server = std::dynamic_pointer_cast<datapath::iserver>(std::make_shared<datapath::windows::server>()); server = std::dynamic_pointer_cast<datapath::iserver>(std::make_shared<datapath::windows::server>());
+1 -1
View File
@@ -65,7 +65,7 @@ namespace datapath {
public: public:
static datapath::error host(std::shared_ptr<datapath::iserver>& server, std::string path, static datapath::error host(std::shared_ptr<datapath::iserver>& server, std::string path,
datapath::permissions permissions, size_t max_clients); datapath::permissions permissions, size_t max_clients);
}; };
} // namespace windows } // namespace windows
} // namespace datapath } // namespace datapath
+30 -34
View File
@@ -39,8 +39,8 @@ void datapath::windows::socket::_connect(HANDLE handle)
void datapath::windows::socket::_disconnect() void datapath::windows::socket::_disconnect()
{ {
if (this->on_close) { if (this->_on_close) {
this->on_close(); this->_on_close();
} }
{ {
@@ -62,45 +62,42 @@ void datapath::windows::socket::_watcher()
std::vector<char> read_buffer; std::vector<char> read_buffer;
std::shared_ptr<datapath::windows::overlapped> read_header_ov = std::shared_ptr<datapath::windows::overlapped> read_header_ov = std::make_shared<datapath::windows::overlapped>();
std::make_shared<datapath::windows::overlapped>(); std::shared_ptr<datapath::windows::overlapped> read_content_ov = std::make_shared<datapath::windows::overlapped>();
std::shared_ptr<datapath::windows::overlapped> read_content_ov =
std::make_shared<datapath::windows::overlapped>();
std::shared_ptr<datapath::windows::overlapped> waitable; std::shared_ptr<datapath::windows::overlapped> waitable;
read_header_ov->on_wait_error.add([&state, &waitable](datapath::error ec) { read_header_ov->_on_wait_error.add([&state, &waitable](datapath::error ec) {
// There was an error waiting on the header. // There was an error waiting on the header.
state = readstate::Unknown; state = readstate::Unknown;
waitable.reset(); waitable.reset();
}); });
read_header_ov->on_wait_success.add( read_header_ov->_on_wait_success.add([this, &read_buffer, &read_content_ov, &state, &waitable](datapath::error ec) {
[this, &read_buffer, &read_content_ov, &state, &waitable](datapath::error ec) { read_content_ov->set_handle(this->socket_handle);
read_content_ov->set_handle(this->socket_handle); read_content_ov->set_data(this);
read_content_ov->set_data(this);
// ToDo: Add optional message size limit, messages above this size kill the connection for attempting DoS. // ToDo: Add optional message size limit, messages above this size kill the connection for attempting DoS.
size_t msg_size = reinterpret_cast<SIZE_ELEMENT&>(read_buffer[0]); size_t msg_size = reinterpret_cast<SIZE_ELEMENT&>(read_buffer[0]);
read_buffer.resize(msg_size); read_buffer.resize(msg_size);
// Read content. // Read content.
if (ReadFileEx(this->socket_handle, read_buffer.data(), DWORD(read_buffer.size()), if (ReadFileEx(this->socket_handle, read_buffer.data(), DWORD(read_buffer.size()),
read_content_ov->get_overlapped(), &datapath::windows::utility::def_io_completion_routine)) { read_content_ov->get_overlapped(), &datapath::windows::utility::def_io_completion_routine)) {
state = readstate::Content; state = readstate::Content;
waitable = read_content_ov; waitable = read_content_ov;
} else { } else {
state = readstate::Unknown; state = readstate::Unknown;
waitable.reset(); waitable.reset();
} }
}); });
read_content_ov->on_wait_error.add([&state, &waitable](datapath::error ec) { read_content_ov->_on_wait_error.add([&state, &waitable](datapath::error ec) {
// There was an error waiting on the content. // There was an error waiting on the content.
state = readstate::Unknown; state = readstate::Unknown;
waitable.reset(); waitable.reset();
}); });
read_content_ov->on_wait_success.add([this, &read_buffer, &state, &waitable](datapath::error ec) { read_content_ov->_on_wait_success.add([this, &read_buffer, &state, &waitable](datapath::error ec) {
// We have content! // We have content!
if (this->on_message) { if (this->_on_message) {
this->on_message(read_buffer); this->_on_message(read_buffer);
state = readstate::Unknown; state = readstate::Unknown;
} else { } else {
// We're buffering the message in read_buffer until there is a hook to on_message. // We're buffering the message in read_buffer until there is a hook to on_message.
@@ -127,8 +124,7 @@ void datapath::windows::socket::_watcher()
// Read content. // Read content.
if (ReadFileEx(this->socket_handle, read_buffer.data(), DWORD(read_buffer.size()), if (ReadFileEx(this->socket_handle, read_buffer.data(), DWORD(read_buffer.size()),
read_header_ov->get_overlapped(), read_header_ov->get_overlapped(), &datapath::windows::utility::def_io_completion_routine)) {
&datapath::windows::utility::def_io_completion_routine)) {
state = readstate::Header; state = readstate::Header;
waitable = read_header_ov; waitable = read_header_ov;
@@ -142,8 +138,8 @@ void datapath::windows::socket::_watcher()
// This logic is in the on_wait_success handler, and continued here. // This logic is in the on_wait_success handler, and continued here.
if (!waitable) { if (!waitable) {
// We currently have a message buffered, but there was no handler last time we checked. // We currently have a message buffered, but there was no handler last time we checked.
if (this->on_message) { if (this->_on_message) {
this->on_message(read_buffer); this->_on_message(read_buffer);
state = readstate::Unknown; state = readstate::Unknown;
} }
} }
@@ -197,7 +193,7 @@ datapath::error datapath::windows::socket::write(std::shared_ptr<datapath::itask
obj->_assign(data, ov); obj->_assign(data, ov);
BOOL suc = WriteFileEx(socket_handle, obj->data().data(), DWORD(obj->data().size()), ov->get_overlapped(), BOOL suc = WriteFileEx(socket_handle, obj->data().data(), DWORD(obj->data().size()), ov->get_overlapped(),
&datapath::windows::utility::def_io_completion_routine); &datapath::windows::utility::def_io_completion_routine);
if (suc) { if (suc) {
return datapath::error::Success; return datapath::error::Success;
} else { } else {
@@ -214,7 +210,7 @@ datapath::error datapath::windows::socket::connect(std::shared_ptr<datapath::iso
SetLastError(ERROR_SUCCESS); SetLastError(ERROR_SUCCESS);
HANDLE handle = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, HANDLE handle = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL);
if ((handle == INVALID_HANDLE_VALUE) || (GetLastError() != ERROR_SUCCESS)) { if ((handle == INVALID_HANDLE_VALUE) || (GetLastError() != ERROR_SUCCESS)) {
return datapath::error::Failure; return datapath::error::Failure;
} }
+1 -1
View File
@@ -60,7 +60,7 @@ namespace datapath {
virtual datapath::error close() override; virtual datapath::error close() override;
virtual datapath::error write(std::shared_ptr<datapath::itask>& task, virtual datapath::error write(std::shared_ptr<datapath::itask>& task,
const std::vector<char>& data) override; const std::vector<char>& data) override;
public: public:
static datapath::error connect(std::shared_ptr<datapath::isocket>& socket, std::string path); static datapath::error connect(std::shared_ptr<datapath::isocket>& socket, std::string path);
+5 -4
View File
@@ -20,17 +20,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#define SIZE_ELEMENT uint32_t #define SIZE_ELEMENT uint32_t
void datapath::windows::task::_assign(const std::vector<char>& data, std::shared_ptr<datapath::windows::overlapped> ov){ void datapath::windows::task::_assign(const std::vector<char>& data, std::shared_ptr<datapath::windows::overlapped> ov)
{
this->buffer.resize(data.size() + sizeof(SIZE_ELEMENT)); this->buffer.resize(data.size() + sizeof(SIZE_ELEMENT));
std::memcpy(buffer.data() + sizeof(SIZE_ELEMENT), data.data(), data.size()); std::memcpy(buffer.data() + sizeof(SIZE_ELEMENT), data.data(), data.size());
reinterpret_cast<SIZE_ELEMENT&>(buffer[0]) = SIZE_ELEMENT(data.size()); reinterpret_cast<SIZE_ELEMENT&>(buffer[0]) = SIZE_ELEMENT(data.size());
this->overlapped = ov; this->overlapped = ov;
} }
datapath::windows::task::task() datapath::windows::task::task()
{ {
this->on_wait_error.add([this](datapath::error ec) { this->on_failure(ec); }); this->_on_wait_error.add([this](datapath::error ec) { this->_on_failure(ec); });
this->on_wait_success.add([this](datapath::error ec) { this->on_success(ec, this->data()); }); this->_on_wait_success.add([this](datapath::error ec) { this->_on_success(ec, this->data()); });
} }
datapath::windows::task::~task() datapath::windows::task::~task()
+1 -1
View File
@@ -20,8 +20,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <memory> #include <memory>
#include "itask.hpp" #include "itask.hpp"
#include "overlapped.hpp" #include "overlapped.hpp"
#include "socket.hpp"
#include "server.hpp" #include "server.hpp"
#include "socket.hpp"
extern "C" { extern "C" {
#include <Windows.h> #include <Windows.h>
+3 -4
View File
@@ -50,13 +50,12 @@ namespace datapath {
return converter.from_bytes(string); return converter.from_bytes(string);
} }
static VOID CALLBACK def_io_completion_routine(_In_ DWORD dwErrorCode, static VOID CALLBACK def_io_completion_routine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered,
_In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
_Inout_ LPOVERLAPPED lpOverlapped)
{ {
SetEvent(lpOverlapped->hEvent); SetEvent(lpOverlapped->hEvent);
} }
} // namespace utility } // namespace utility
} // namespace windows } // namespace windows
} // namespace datapath } // namespace datapath
+10 -10
View File
@@ -42,16 +42,16 @@ datapath::error datapath::waitable::wait(datapath::waitable* obj, std::chrono::n
DWORD result = WaitForSingleObjectEx(handle, DWORD(timeout), TRUE); DWORD result = WaitForSingleObjectEx(handle, DWORD(timeout), TRUE);
switch (result) { switch (result) {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
obj->on_wait_success(datapath::error::Success); obj->_on_wait_success(datapath::error::Success);
return datapath::error::Success; return datapath::error::Success;
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
return datapath::error::TimedOut; return datapath::error::TimedOut;
case WAIT_ABANDONED: case WAIT_ABANDONED:
obj->on_wait_error(datapath::error::Closed); obj->_on_wait_error(datapath::error::Closed);
return datapath::error::Closed; return datapath::error::Closed;
case WAIT_IO_COMPLETION: case WAIT_IO_COMPLETION:
duration = (std::chrono::high_resolution_clock::now() - start); duration = (std::chrono::high_resolution_clock::now() - start);
timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
if (timeout <= 0) { if (timeout <= 0) {
timeout = 0; timeout = 0;
} }
@@ -96,19 +96,19 @@ datapath::error datapath::waitable::wait(datapath::waitable** objs, size_t count
DWORD result = WaitForMultipleObjectsEx(handles.size(), handles.data(), TRUE, DWORD(timeout), TRUE); DWORD result = WaitForMultipleObjectsEx(handles.size(), handles.data(), TRUE, DWORD(timeout), TRUE);
if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS))) { if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS))) {
for (auto idx : indexes) { for (auto idx : indexes) {
objs[idx]->on_wait_success(datapath::error::Success); objs[idx]->_on_wait_success(datapath::error::Success);
} }
return datapath::error::Success; return datapath::error::Success;
} else if ((result >= WAIT_ABANDONED_0) && (result < (WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS))) { } else if ((result >= WAIT_ABANDONED_0) && (result < (WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS))) {
for (auto idx : indexes) { for (auto idx : indexes) {
objs[idx]->on_wait_error(datapath::error::Closed); objs[idx]->_on_wait_error(datapath::error::Closed);
} }
return datapath::error::Closed; return datapath::error::Closed;
} else if (result == WAIT_TIMEOUT) { } else if (result == WAIT_TIMEOUT) {
return datapath::error::TimedOut; return datapath::error::TimedOut;
} else if (result == WAIT_IO_COMPLETION) { } else if (result == WAIT_IO_COMPLETION) {
duration = (std::chrono::high_resolution_clock::now() - start); duration = (std::chrono::high_resolution_clock::now() - start);
timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
if (timeout <= 0) { if (timeout <= 0) {
timeout = 0; timeout = 0;
} }
@@ -122,7 +122,7 @@ datapath::error datapath::waitable::wait(datapath::waitable** objs, size_t count
} }
datapath::error datapath::waitable::wait_any(datapath::waitable** objs, size_t count, size_t& index, datapath::error datapath::waitable::wait_any(datapath::waitable** objs, size_t count, size_t& index,
std::chrono::nanoseconds duration) std::chrono::nanoseconds duration)
{ {
assert(objs != nullptr); assert(objs != nullptr);
assert((count > 0) && (count <= MAXIMUM_WAIT_OBJECTS)); assert((count > 0) && (count <= MAXIMUM_WAIT_OBJECTS));
@@ -154,17 +154,17 @@ datapath::error datapath::waitable::wait_any(datapath::waitable** objs, size_t c
DWORD result = WaitForMultipleObjectsEx(handles.size(), handles.data(), FALSE, DWORD(timeout), TRUE); DWORD result = WaitForMultipleObjectsEx(handles.size(), handles.data(), FALSE, DWORD(timeout), TRUE);
if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS))) { if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS))) {
index = indexes[result - WAIT_OBJECT_0]; index = indexes[result - WAIT_OBJECT_0];
objs[index]->on_wait_success(datapath::error::Success); objs[index]->_on_wait_success(datapath::error::Success);
return datapath::error::Success; return datapath::error::Success;
} else if ((result >= WAIT_ABANDONED_0) && (result < (WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS))) { } else if ((result >= WAIT_ABANDONED_0) && (result < (WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS))) {
index = indexes[result - WAIT_OBJECT_0]; index = indexes[result - WAIT_OBJECT_0];
objs[index]->on_wait_error(datapath::error::Closed); objs[index]->_on_wait_error(datapath::error::Closed);
return datapath::error::Closed; return datapath::error::Closed;
} else if (result == WAIT_TIMEOUT) { } else if (result == WAIT_TIMEOUT) {
return datapath::error::TimedOut; return datapath::error::TimedOut;
} else if (result == WAIT_IO_COMPLETION) { } else if (result == WAIT_IO_COMPLETION) {
duration = (std::chrono::high_resolution_clock::now() - start); duration = (std::chrono::high_resolution_clock::now() - start);
timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
if (timeout <= 0) { if (timeout <= 0) {
timeout = 0; timeout = 0;
} }