From 6d385c1a3a8c97877a306918c37cda75a1f54eb0 Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Thu, 10 Jan 2019 15:10:28 -0800 Subject: [PATCH 1/7] Remove all the wait_all unused functions --- source/os/waitable.hpp | 10 ----- source/os/windows/waitable.cpp | 69 ---------------------------------- 2 files changed, 79 deletions(-) diff --git a/source/os/waitable.hpp b/source/os/waitable.hpp index 88189d2..2d42f6c 100644 --- a/source/os/waitable.hpp +++ b/source/os/waitable.hpp @@ -47,16 +47,6 @@ namespace os { static os::error wait_any(std::vector items, size_t &signalled_index, std::chrono::nanoseconds timeout); - - static os::error wait_all(waitable **items, size_t items_count, size_t &signalled_index); - - static os::error wait_all(waitable **items, size_t items_count, size_t &signalled_index, - std::chrono::nanoseconds timeout); - - static os::error wait_all(std::vector items, size_t &signalled_index); - - static os::error wait_all(std::vector items, size_t &signalled_index, - std::chrono::nanoseconds timeout); }; } // namespace os diff --git a/source/os/windows/waitable.cpp b/source/os/windows/waitable.cpp index 2596a39..a1df3c6 100644 --- a/source/os/windows/waitable.cpp +++ b/source/os/windows/waitable.cpp @@ -123,72 +123,3 @@ os::error os::waitable::wait_any(std::vector items, size_t &signalle os::error os::waitable::wait_any(std::vector items, size_t &signalled_index) { return wait_any(items.data(), items.size(), signalled_index); } - -os::error os::waitable::wait_all(waitable **items, size_t items_count, size_t &signalled_index, - std::chrono::nanoseconds timeout) { - if (items == nullptr) { - throw std::invalid_argument("'items' can't be nullptr."); - } else if (items_count >= MAXIMUM_WAIT_OBJECTS) { - throw std::invalid_argument("Too many items to wait for."); - } - - // Need to create a sequential array of HANDLEs here. - size_t valid_handles = 0; - std::vector handles(items_count); - std::vector idxToTrueIdx(items_count); - for (size_t idx = 0, eidx = items_count; idx < eidx; idx++) { - waitable *obj = items[idx]; - if (obj) { - handles[valid_handles] = (HANDLE)obj->get_waitable(); - idxToTrueIdx[idx] = valid_handles; - valid_handles++; - } - } - - int64_t ms_timeout = std::chrono::duration_cast(timeout).count(); - -wait_all_retry: - auto start = std::chrono::high_resolution_clock::now(); - if (ms_timeout < 0) { - ms_timeout = 0; - } - - DWORD result = WaitForMultipleObjectsEx(DWORD(valid_handles), handles.data(), true, DWORD(ms_timeout), TRUE); - if ((result >= WAIT_OBJECT_0) && result < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) { - signalled_index = result - WAIT_OBJECT_0; - - for (size_t idx = 0; idx < items_count; idx++) { - os::async_op *aop = dynamic_cast(items[idx]); - if (aop) { - aop->call_callback(); - } - } - - return os::error::Success; - } else if (result == WAIT_TIMEOUT) { - signalled_index = -1; - return os::error::TimedOut; - } else if ((result >= WAIT_ABANDONED_0) && result < (WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS)) { - signalled_index = result - WAIT_ABANDONED_0; - return os::error::Disconnected; // Disconnected Semaphore from original Owner - } else if (result == WAIT_IO_COMPLETION) { - ms_timeout -= - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start) - .count(); - goto wait_all_retry; - } - return os::error::Error; -} - -os::error os::waitable::wait_all(waitable **items, size_t items_count, size_t &signalled_index) { - return wait_all(items, items_count, signalled_index, std::chrono::milliseconds(INFINITE)); -} - -os::error os::waitable::wait_all(std::vector items, size_t &signalled_index, - std::chrono::nanoseconds timeout) { - return wait_all(items.data(), items.size(), signalled_index, timeout); -} - -os::error os::waitable::wait_all(std::vector items, size_t &signalled_index) { - return wait_all(items.data(), items.size(), signalled_index); -} From 1d69294b491673fbe44353b21870594341b8164b Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Fri, 11 Jan 2019 15:41:58 -0800 Subject: [PATCH 2/7] Remove unused files --- CMakeLists.txt | 11 ------- include/datalane-error.hpp | 41 ----------------------- include/datalane-socket.hpp | 55 ------------------------------- include/datalane.hpp | 29 ---------------- source/datalane-socket-client.cpp | 18 ---------- source/datalane-socket-client.hpp | 28 ---------------- source/datalane-socket-server.cpp | 18 ---------- source/datalane-socket-server.hpp | 27 --------------- source/datalane-socket.cpp | 22 ------------- source/datalane.cpp | 34 ------------------- 10 files changed, 283 deletions(-) delete mode 100644 include/datalane-error.hpp delete mode 100644 include/datalane-socket.hpp delete mode 100644 include/datalane.hpp delete mode 100644 source/datalane-socket-client.cpp delete mode 100644 source/datalane-socket-client.hpp delete mode 100644 source/datalane-socket-server.cpp delete mode 100644 source/datalane-socket-server.hpp delete mode 100644 source/datalane-socket.cpp delete mode 100644 source/datalane.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c0777f..e2c5e95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,19 +36,8 @@ ENDIF() ################################################################################ # Source ################################################################################ -SET(PROJECT_SOURCE_PUBLIC - "${PROJECT_SOURCE_DIR}/include/datalane.hpp" - "${PROJECT_SOURCE_DIR}/include/datalane-socket.hpp" - "${PROJECT_SOURCE_DIR}/include/datalane-error.hpp" -) SET(PROJECT_SOURCE_PRIVATE - "${PROJECT_SOURCE_DIR}/source/datalane.cpp" - "${PROJECT_SOURCE_DIR}/source/datalane-socket.cpp" - "${PROJECT_SOURCE_DIR}/source/datalane-socket-client.hpp" - "${PROJECT_SOURCE_DIR}/source/datalane-socket-client.cpp" - "${PROJECT_SOURCE_DIR}/source/datalane-socket-server.hpp" - "${PROJECT_SOURCE_DIR}/source/datalane-socket-server.cpp" "${PROJECT_SOURCE_DIR}/source/os/async_op.hpp" "${PROJECT_SOURCE_DIR}/source/os/async_op.cpp" "${PROJECT_SOURCE_DIR}/source/os/error.hpp" diff --git a/include/datalane-error.hpp b/include/datalane-error.hpp deleted file mode 100644 index 8c0b5c5..0000000 --- a/include/datalane-error.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DATALANE_ERROR_HPP -#define DATALANE_ERROR_HPP - -namespace datalane { - enum class error { - // Everything is fine. - Ok, - Success = Ok, - - // A generic error occurred. - Error, - - // A critical error occurred (unrecoverable, abort program). - CriticalError, - - // Disconnected - Disconnected, - - // Timed Out - TimedOut, - }; -} - -#endif // DATALANE_ERROR_HPP diff --git a/include/datalane-socket.hpp b/include/datalane-socket.hpp deleted file mode 100644 index ae9cabf..0000000 --- a/include/datalane-socket.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DATALANE_SOCKET_HPP -#define DATALANE_SOCKET_HPP - -#include -#include -#include "datalane-error.hpp" - -namespace datalane { - class socket { - public: - typedef std::function socket, void *data)> socket_connect_cb_t; - typedef std::function socket, void *data)> socket_disconnect_cb_t; - - public: - virtual size_t avail() = 0; - virtual size_t avail_total() = 0; - - virtual error write(void *buffer, size_t length, size_t &write_length) = 0; - virtual error read(void *buffer, size_t max_length, size_t &read_length) = 0; - - virtual bool connected() = 0; - virtual error disconnect() = 0; - - virtual bool good() = 0; - virtual bool bad(); - - virtual bool is_server() = 0; - - public: // Server only (listen()) - virtual bool pending() = 0; - virtual error accept(std::shared_ptr &socket) = 0; - - virtual void set_connect_cb(socket_connect_cb_t cb, void *data) = 0; - virtual void set_disconnect_cb(socket_disconnect_cb_t cb, void *data) = 0; - }; -} // namespace datalane - -#endif // DATALANE_SOCKET_HPP diff --git a/include/datalane.hpp b/include/datalane.hpp deleted file mode 100644 index a396381..0000000 --- a/include/datalane.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DATALANE_HPP -#define DATALANE_HPP - -#include -#include "datalane-socket.hpp" - -namespace datalane { - static std::shared_ptr listen(std::string socket, size_t backlog = -1); - static std::shared_ptr connect(std::string socket); -} // namespace datalane - -#endif // DATALANE_HPP diff --git a/source/datalane-socket-client.cpp b/source/datalane-socket-client.cpp deleted file mode 100644 index f152861..0000000 --- a/source/datalane-socket-client.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "datalane-socket-client.hpp" diff --git a/source/datalane-socket-client.hpp b/source/datalane-socket-client.hpp deleted file mode 100644 index 5048d18..0000000 --- a/source/datalane-socket-client.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DATALANE_SOCKET_CLIENT_HPP -#define DATALANE_SOCKET_CLIENT_HPP - -#include "datalane-socket.hpp" -#include "os-namedsocket.hpp" - -namespace datalane { - class client_socket : public datalane::socket {}; -} // namespace datalane - -#endif // DATALANE_SOCKET_CLIENT_HPP diff --git a/source/datalane-socket-server.cpp b/source/datalane-socket-server.cpp deleted file mode 100644 index 2291617..0000000 --- a/source/datalane-socket-server.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "datalane-socket-server.hpp" diff --git a/source/datalane-socket-server.hpp b/source/datalane-socket-server.hpp deleted file mode 100644 index e10876a..0000000 --- a/source/datalane-socket-server.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef DATALANE_SOCKET_SERVER_HPP -#define DATALANE_SOCKET_SERVER_HPP - -#include "datalane-socket.hpp" - -namespace datalane { - class server_socket : public datalane::socket {}; -} // namespace datalane - -#endif // DATALANE_SOCKET_SERVER_HPP diff --git a/source/datalane-socket.cpp b/source/datalane-socket.cpp deleted file mode 100644 index ca13fe4..0000000 --- a/source/datalane-socket.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "datalane-socket.hpp" - -bool datalane::socket::bad() { - return !good(); -} diff --git a/source/datalane.cpp b/source/datalane.cpp deleted file mode 100644 index 011113b..0000000 --- a/source/datalane.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "datalane-socket-client.hpp" -#include "datalane-socket-server.hpp" -#include "datalane.hpp" - -std::shared_ptr datalane::listen(std::string socket, size_t backlog /*= -1*/) { - throw std::exception("Not implemented yet."); - //std::shared_ptr sock = - // std::make_shared(socket, backlog); - //return std::dynamic_pointer_cast(sock); -} - -std::shared_ptr datalane::connect(std::string socket) { - throw std::exception("Not implemented yet."); - //std::shared_ptr sock = - // std::make_shared(socket); - //return std::dynamic_pointer_cast(sock); -} From b7fbcec36735bb6cbe8f89a5b6a8611d262ac309 Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Fri, 11 Jan 2019 15:44:46 -0800 Subject: [PATCH 3/7] Remove unused code --- source/os-namedsocket-win.cpp | 502 ----------------------- source/os-namedsocket-win.hpp | 118 ------ source/os-namedsocket.cpp | 204 --------- source/os-namedsocket.hpp | 159 ------- source/os-windows-overlapped-manager.cpp | 178 -------- source/os-windows-overlapped-manager.hpp | 72 ---- 6 files changed, 1233 deletions(-) delete mode 100644 source/os-namedsocket-win.cpp delete mode 100644 source/os-namedsocket-win.hpp delete mode 100644 source/os-namedsocket.cpp delete mode 100644 source/os-namedsocket.hpp delete mode 100644 source/os-windows-overlapped-manager.cpp delete mode 100644 source/os-windows-overlapped-manager.hpp diff --git a/source/os-namedsocket-win.cpp b/source/os-namedsocket-win.cpp deleted file mode 100644 index cfbaf5c..0000000 --- a/source/os-namedsocket-win.cpp +++ /dev/null @@ -1,502 +0,0 @@ -// Copyright(C) 2017-2018 Michael Fabian Dirks -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110 - 1301, USA. - -#include "os-namedsocket-win.hpp" -#include - -std::unique_ptr os::named_socket::create() { - return std::make_unique(); -} - -#pragma region NamedSocketWindows -#pragma region De-/Constructor -os::named_socket_win::named_socket_win() {} - -os::named_socket_win::~named_socket_win() { - close(); -} -#pragma endregion De-/Constructor - -#pragma region Listen/Connect/Close -bool os::named_socket_win::_listen(std::string path, size_t backlog) { - // Set Pipe Mode. - m_openMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED; - m_pipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE; - - // Validate and generate socket name - if (path.length() > 255) // Path can't be larger than 255 characters, limit set by WinAPI. - return false; // !TODO! Throw some kind of error to signal why it failed. - for (char& v : path) - if (v == '\\') - v = '/'; - m_pipeName = "\\\\.\\pipe\\" + path; - - // Create sockets. - try { - for (size_t n = 0; n <= backlog; n++) { - std::shared_ptr ptr; - if (n == 0) { - ptr = std::make_shared(this, m_pipeName, - m_openMode | FILE_FLAG_FIRST_PIPE_INSTANCE, m_pipeMode); - } else { - ptr = std::make_shared(this, m_pipeName, - m_openMode, m_pipeMode); - } - m_connections.push_back(ptr); - } - } catch (...) { - return false; - } - - return true; -} - -bool os::named_socket_win::_connect(std::string path) { - // Validate and generate socket name - if (path.length() > 255) // Path can't be larger than 255 characters, limit set by WinAPI. - return false; // !TODO! Throw some kind of error to signal why it failed. - for (char& v : path) - if (v == '\\') - v = '/'; - m_pipeName = "\\\\.\\pipe\\" + path; - - try { - std::shared_ptr ptr = - std::make_shared(this, m_pipeName); - m_connections.push_back(ptr); - } catch (...) { - return false; - } - - return true; -} - -bool os::named_socket_win::_close() { - m_connections.clear(); - return true; -} - - -#pragma endregion Listen/Connect/Close -#pragma endregion NamedSocketWindows - -#pragma region Named Socket Connection Windows -os::named_socket_connection_win::named_socket_connection_win(os::named_socket* parent, - std::string path, DWORD openFlags, DWORD pipeFlags) : m_parent(parent) { - if (parent == nullptr) // No parent - throw std::runtime_error("No parent"); - - if (path.length() > 0xFF) // Maximum total path name. - throw std::runtime_error("Path name too long."); - - // Convert pipe name to machine compatible format. -#ifdef UNICODE - std::wstring pipeNameWS = path; - LPCTSTR pipeName = pipeNameWS.c_str(); -#else - LPCTSTR pipeName = path.c_str(); -#endif - - // Security Attributes - m_isServer = true; - SECURITY_ATTRIBUTES m_securityAttributes; - memset(&m_securityAttributes, 0, sizeof(m_securityAttributes)); - - // Create Pipe - m_handle = CreateNamedPipe(pipeName, - openFlags, - pipeFlags, - PIPE_UNLIMITED_INSTANCES, - static_cast(parent->get_send_buffer_size()), - static_cast(parent->get_receive_buffer_size()), - static_cast(std::chrono::duration_cast(parent->get_wait_timeout()).count()), - &m_securityAttributes); - if (m_handle == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - throw std::runtime_error("Unable to create socket."); - } - - // Threading - m_stopWorkers = false; - m_managerThread = std::thread(thread_main, this); -} - -os::named_socket_connection_win::named_socket_connection_win(os::named_socket* parent, std::string path) - : m_parent(parent) { - if (parent == nullptr) // No parent - throw std::runtime_error("No parent"); - - if (path.length() > 0xFF) // Maximum total path name. - throw std::runtime_error("Path name too long."); - - // Convert pipe name to machine compatible format. -#ifdef UNICODE - std::wstring pipeNameWS = path; - LPCTSTR pipeName = pipeNameWS.c_str(); -#else - LPCTSTR pipeName = path.c_str(); -#endif - - m_isServer = false; - size_t attempts = 0; - for (size_t attempt = 0; attempt < 5; attempt++) { - m_handle = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (m_handle != INVALID_HANDLE_VALUE) - break; - DWORD err = GetLastError(); - if (err != ERROR_PIPE_BUSY) - throw std::runtime_error("Unable to create socket."); - - DWORD timeout = (DWORD)std::chrono::duration_cast( - parent->get_wait_timeout()).count(); - if (!WaitNamedPipe(pipeName, timeout)) { - if (attempt < 4) { - continue; - } else { - throw std::runtime_error("Unable to create socket."); - } - } - } - m_state = state::Connected; - - DWORD flags = PIPE_READMODE_MESSAGE | PIPE_WAIT; - if (!SetNamedPipeHandleState(m_handle, &flags, NULL, NULL)) { - // well, what do we do now? - } - - // Threading - m_stopWorkers = false; - m_managerThread = std::thread(thread_main, this); -} - -os::named_socket_connection_win::~named_socket_connection_win() { - // Stop Threading - m_stopWorkers = true; - m_managerThread.join(); - - CancelIo(m_handle); - if (m_isServer) - disconnect(); - else - CloseHandle(m_handle); -} - -bool os::named_socket_connection_win::is_waiting() { - return m_state == state::Waiting; -} - -bool os::named_socket_connection_win::is_connected() { - return m_state == state::Connected; -} - -bool os::named_socket_connection_win::connect() { - if (!m_isServer) - throw std::logic_error("Clients are automatically connected."); - - if (m_state != state::Waiting) - return false; - - m_state = state::Connected; - return true; -} - -bool os::named_socket_connection_win::disconnect() { - if (!m_isServer) - throw std::logic_error("Clients are automatically disconnected."); - - if (m_state != state::Connected) - return false; - - return !!DisconnectNamedPipe(m_handle); -} - -bool os::named_socket_connection_win::eof() { - return bad() || is_waiting() || (read_avail() == 0); -} - -bool os::named_socket_connection_win::good() { - ULONG pid; - - if (m_state != state::Connected) { - return false; - } - - return true; -} - -size_t os::named_socket_connection_win::read_avail() { - DWORD availBytes = 0; - PeekNamedPipe(m_handle, NULL, NULL, NULL, NULL, &availBytes); - return availBytes; -} - -size_t os::named_socket_connection_win::read_total() { - DWORD totalBytes = 0; - PeekNamedPipe(m_handle, NULL, NULL, NULL, &totalBytes, NULL); - return totalBytes; -} - -os::error os::named_socket_connection_win::read(char* buffer, size_t length, size_t& read_length) { - if (m_state != state::Connected) { - read_length = 0; - return os::error::Disconnected; - } - - DWORD bytesRead = 0; - DWORD errorCode = 0; - os::error returnCode = os::error::Ok; - std::shared_ptr ov = dynamic_cast(m_parent)->ovm.alloc(); - - // Attempt to read from the handle. - SetLastError(ERROR_SUCCESS); - ReadFile(m_handle, buffer, (DWORD)length, &bytesRead, ov.get()); - -test_error: - // Test for actual return code. - errorCode = GetLastError(); - if (errorCode == ERROR_SUCCESS) { - // ERROR_SUCCESS should mean that we immediately read everything. - if (!GetOverlappedResult(m_handle, ov.get(), &bytesRead, false)) { - // In case it didn't, just wait as normal. - goto resume_wait; - } - // In case it did, continue to success. - returnCode = os::error::Ok; - read_length = bytesRead; - goto read_success; - } else if (errorCode == ERROR_MORE_DATA) { - // ERROR_MORE_DATA means that there is additional data to be read. - GetOverlappedResult(m_handle, ov.get(), &bytesRead, false); - returnCode = os::error::MoreData; - read_length = bytesRead; - goto read_success; - } else if (errorCode == ERROR_BROKEN_PIPE) { - // Disconnected. - m_state = state::Disconnected; - returnCode = os::error::Disconnected; - goto read_fail; - } else if (errorCode != ERROR_IO_PENDING) { - // Any other code than ERROR_IO_PENDING means that there's nothing to read from. - returnCode = os::error::Error; - goto read_fail; - } - -resume_wait: - // Now wait until we actually have a result available. - DWORD waitTime = (DWORD)std::chrono::duration_cast( - m_parent->get_receive_timeout()).count(); - errorCode = WaitForSingleObjectEx(m_handle, waitTime, true); - if (errorCode == WAIT_TIMEOUT) { - if (!HasOverlappedIoCompleted(ov.get())) { - // If we timed out and it still hasn't completed, consider the request failed. - returnCode = os::error::TimedOut; - goto read_fail; - } else { - if (!GetOverlappedResult(m_handle, ov.get(), &bytesRead, false)) { - // Overlapped IO completed, but we can't get any result back. - errorCode = GetLastError(); - goto test_error; - } - } - } else if (errorCode == WAIT_ABANDONED) { - returnCode = os::error::Disconnected; - goto read_fail; - } else if (errorCode == WAIT_FAILED) { - errorCode = GetLastError(); - returnCode = os::error::Error; - goto read_fail; - } - read_length = bytesRead; - returnCode = os::error::Ok; - -read_success: - dynamic_cast(m_parent)->ovm.free(ov); - return returnCode; - -read_fail: - CancelIoEx(m_handle, ov.get()); - dynamic_cast(m_parent)->ovm.free(ov); - return returnCode; -} - -os::error os::named_socket_connection_win::write(char const* buffer, size_t const length, size_t& write_length) { - if (m_state != state::Connected) { - write_length = 0; - return os::error::Disconnected; - } - - DWORD bytesWritten = 0; - DWORD errorCode = ERROR_SUCCESS; - os::error returnCode = os::error::Ok; - std::shared_ptr ov = dynamic_cast(m_parent)->ovm.alloc(); - - SetLastError(ERROR_SUCCESS); - WriteFile(m_handle, buffer, (DWORD)length, &bytesWritten, ov.get()); - -write_test_error: - // Test for actual return code. - errorCode = GetLastError(); - switch (errorCode) { - case ERROR_SUCCESS: - // ERROR_SUCCESS should mean that we immediately read everything. - if (!GetOverlappedResult(m_handle, ov.get(), &bytesWritten, false)) { - // In case it didn't, just wait as normal. - goto write_resume_wait; - } - - // In case it did, continue to success. - returnCode = os::error::Ok; - write_length = bytesWritten; - goto write_success; - break; - case ERROR_IO_PENDING: - goto write_resume_wait; - break; - default: - goto write_fail; - } - -write_resume_wait: - // Now wait until we actually have a result available. - DWORD waitTime = (DWORD)std::chrono::duration_cast( - m_parent->get_send_timeout()).count(); - errorCode = WaitForSingleObjectEx(m_handle, waitTime, true); - if (errorCode == WAIT_TIMEOUT) { - if (!HasOverlappedIoCompleted(ov.get())) { - // If we timed out and it still hasn't completed, consider the request failed. - returnCode = os::error::TimedOut; - goto write_fail; - } else { - if (!GetOverlappedResult(m_handle, ov.get(), &bytesWritten, false)) { - // Overlapped IO completed, but we can't get any result back. - errorCode = GetLastError(); - goto write_test_error; - } - } - } else if (errorCode == WAIT_ABANDONED) { - returnCode = os::error::Disconnected; - goto write_fail; - } else if (errorCode == WAIT_FAILED) { - errorCode = GetLastError(); - returnCode = os::error::Error; - goto write_fail; - } - write_length = bytesWritten; - returnCode = os::error::Ok; - -write_success: - dynamic_cast(m_parent)->ovm.free(ov); - return returnCode; - -write_fail: - CancelIoEx(m_handle, ov.get()); - dynamic_cast(m_parent)->ovm.free(ov); - return returnCode; -} - -os::ClientId_t os::named_socket_connection_win::get_client_id() { - return static_cast(reinterpret_cast(m_handle)); -} - -void os::named_socket_connection_win::thread_main(void* ptr) { - reinterpret_cast(ptr)->threadlocal(); -} - -void os::named_socket_connection_win::threadlocal() { - OVERLAPPED ovWrite; - create_overlapped(ovWrite); - - bool pendingIO = false; - - while (!m_stopWorkers) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - if (m_state == state::Sleeping) { - if (!pendingIO) { - if (!ConnectNamedPipe(m_handle, &ovWrite)) { - DWORD err = GetLastError(); - switch (err) { - case ERROR_IO_PENDING: - pendingIO = true; - break; - case ERROR_PIPE_CONNECTED: - pendingIO = false; - m_state = state::Waiting; - break; - default: - pendingIO = false; - break; - } - } - } else { - DWORD timeout = (DWORD)std::chrono::duration_cast( - m_parent->get_wait_timeout()).count(); - DWORD res = WaitForSingleObjectEx(ovWrite.hEvent, timeout, true); - switch (res) { - case WAIT_OBJECT_0: - { - DWORD bytes; - BOOL success = GetOverlappedResult(m_handle, &ovWrite, &bytes, FALSE); - ResetEvent(ovWrite.hEvent); - if (success) { - m_state = state::Waiting; - } else { - // Error? - } - pendingIO = false; - } - break; - case WAIT_TIMEOUT: - break; - default: - pendingIO = false; - break; - } - } - } else if (m_state == state::Waiting) { - if (!PeekNamedPipe(m_handle, NULL, NULL, NULL, NULL, NULL)) { - DWORD err = GetLastError(); - err = err; - } - pendingIO = false; - } else if (m_state == state::Connected) { - if (m_isServer) { - if (!good()) { - m_state = state::Disconnected; - } - } - } else if (m_state == state::Disconnected) { - if (m_isServer) { - disconnect(); - m_state = state::Sleeping; - } - } - } - - destroy_overlapped(ovWrite); -} - -void os::named_socket_connection_win::create_overlapped(OVERLAPPED& ov) { - memset(&ov, 0, sizeof(OVERLAPPED)); - ov.hEvent = CreateEvent(NULL, true, false, NULL); -} - -void os::named_socket_connection_win::destroy_overlapped(OVERLAPPED& ov) { - CloseHandle(ov.hEvent); - memset(&ov, 0, sizeof(OVERLAPPED)); -} - -#pragma endregion Named Socket Connection Windows diff --git a/source/os-namedsocket-win.hpp b/source/os-namedsocket-win.hpp deleted file mode 100644 index 0301102..0000000 --- a/source/os-namedsocket-win.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files(the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ - -#ifndef OS_NAMEDSOCKET_WIN_HPP -#define OS_NAMEDSOCKET_WIN_HPP - -#include "os-namedsocket.hpp" -#include -#include -#include -#include -#include -extern "C" { // clang++ compatible -#define NOMINMAX -#define _WIN32_WINNT _WIN32_WINNT_WIN10 -#include -#include -#include -} - -#include "os-windows-overlapped-manager.hpp" - -namespace os { - - class named_socket_win : public named_socket { - public: - named_socket_win(); - virtual ~named_socket_win(); - - protected: - #pragma region Listen/Connect/Close - virtual bool _listen(std::string path, size_t backlog) override; - virtual bool _connect(std::string path) override; - virtual bool _close() override; - #pragma endregion Listen/Connect/Close - - // Private Memory - private: - std::string m_pipeName; - DWORD m_openMode; - DWORD m_pipeMode; - - protected: - os::windows::overlapped_manager ovm; - - friend class named_socket_connection_win; - }; - - class named_socket_connection_win : public named_socket_connection { - public: - named_socket_connection_win(os::named_socket* parent, std::string path, DWORD openFlags, DWORD pipeFlags); - named_socket_connection_win(os::named_socket* parent, std::string path); - virtual ~named_socket_connection_win(); - - // Status - virtual bool is_waiting() override; - virtual bool is_connected() override; - virtual bool connect() override; - virtual bool disconnect() override; - virtual bool eof() override; - virtual bool good() override; - - virtual size_t read_avail() override; - virtual size_t read_total() override; - virtual os::error read(char* buffer, size_t length, size_t& read_length) override; - virtual os::error write(char const* buffer, size_t const length, size_t& write_length) override; - - // Info - virtual ClientId_t get_client_id() override; - - private: - static void thread_main(void* ptr); - void threadlocal(); - static void create_overlapped(OVERLAPPED& ov); - static void destroy_overlapped(OVERLAPPED& ov); - - private: - os::named_socket* m_parent; - HANDLE m_handle; - - bool m_stopWorkers = false; - std::thread m_managerThread; - - std::mutex m_writeLock, m_readLock; - std::queue> - m_writeQueue, m_readQueue; - - // Status - bool m_isServer = false; - enum class state { - Sleeping, - Waiting, - Connected, - Disconnected - }; - state m_state = state::Sleeping; - }; -} - -#endif diff --git a/source/os-namedsocket.cpp b/source/os-namedsocket.cpp deleted file mode 100644 index dd5b9c8..0000000 --- a/source/os-namedsocket.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files(the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ - -#include "os-namedsocket.hpp" - -#define MINIMUM_TIMEOUT 1000 -#define MINIMUM_BUFFER_SIZE 32767 - -#pragma region Named Socket -os::named_socket::named_socket() { - // Socket is neither initialized or listening. - m_isInitialized = - m_isListening = false; - - // Timing out defaults to 5ms. - m_timeOutWait = std::chrono::milliseconds(5); - m_timeOutReceive = std::chrono::milliseconds(5); - m_timeOutSend = std::chrono::milliseconds(5); - - // Buffers default to 1 MB Size. - m_bufferReceiveSize = MINIMUM_BUFFER_SIZE; - m_bufferSendSize = MINIMUM_BUFFER_SIZE; -} - -os::named_socket::~named_socket() { - close(); -} - -#pragma region Options -bool os::named_socket::set_receive_buffer_size(size_t size) { - if (m_isInitialized) - return false; - if (size < MINIMUM_BUFFER_SIZE) - return false; - m_bufferReceiveSize = size; - return true; -} - -size_t os::named_socket::get_receive_buffer_size() { - return m_bufferReceiveSize; -} - -bool os::named_socket::set_send_buffer_size(size_t size) { - if (m_isInitialized) - return false; - if (size < MINIMUM_BUFFER_SIZE) - return false; - m_bufferSendSize = size; - return true; -} - -size_t os::named_socket::get_send_buffer_size() { - return m_bufferSendSize; -} - -bool os::named_socket::set_wait_timeout(std::chrono::nanoseconds time) { - if (m_isInitialized) - return false; - if (time < std::chrono::nanoseconds(MINIMUM_TIMEOUT)) - return false; - m_timeOutWait = time; - return true; -} - -std::chrono::nanoseconds os::named_socket::get_wait_timeout() { - return m_timeOutWait; -} - -bool os::named_socket::set_receive_timeout(std::chrono::nanoseconds time) { - if (m_isInitialized) - return false; - if (time < std::chrono::nanoseconds(MINIMUM_TIMEOUT)) - return false; - m_timeOutReceive = time; - return true; -} - -std::chrono::nanoseconds os::named_socket::get_receive_timeout() { - return m_timeOutReceive; -} - -bool os::named_socket::set_send_timeout(std::chrono::nanoseconds time) { - if (m_isInitialized) - return false; - if (time < std::chrono::nanoseconds(MINIMUM_TIMEOUT)) - return false; - m_timeOutSend = time; - return true; -} - -std::chrono::nanoseconds os::named_socket::get_send_timeout() { - return m_timeOutSend; -} -#pragma endregion Options - -#pragma region Listen/Connect/Close -bool os::named_socket::listen(std::string path, size_t backlog) { - if (m_isInitialized) - return false; - - if (backlog == 0) - backlog = 1; - - if (!_listen(path, backlog)) { - _close(); - return false; - } - - m_isInitialized = true; - m_isListening = true; - return true; -} - -bool os::named_socket::connect(std::string path) { - if (m_isInitialized) - return false; - - if (!_connect(path)) { - _close(); - return false; - } - - m_isInitialized = true; - m_isListening = false; - return true; -} - -bool os::named_socket::close() { - if (!m_isInitialized) - return false; - - if (!_close()) - return false; - - m_isInitialized = false; - return true; -} -#pragma endregion Listen/Connect/Close - -#pragma region Server & Client -bool os::named_socket::is_initialized() { - return m_isInitialized; -} - -bool os::named_socket::is_server() { - return m_isInitialized && m_isListening; -} - -bool os::named_socket::is_client() { - return m_isInitialized && !m_isListening; -} - -std::weak_ptr os::named_socket::accept() { - for (auto frnt = m_connections.begin(); frnt != m_connections.end(); frnt++) { - if ((*frnt)->is_waiting()) { - return std::weak_ptr(*frnt); - } - } - return {}; -} - -bool os::named_socket::accept(std::shared_ptr& conn) { - for (auto frnt = m_connections.begin(); frnt != m_connections.end(); frnt++) { - if ((*frnt)->is_waiting()) { - conn = *frnt; - return true; - } - } - return false; - -} - -#pragma endregion Server & Client - -#pragma region Client Only -std::shared_ptr os::named_socket::get_connection() { - return m_connections.front(); -} -#pragma endregion Client Only -#pragma endregion Named Socket - -#pragma region Named Socket Connection -bool os::named_socket_connection::bad() { - return !good(); -} -#pragma endregion Named Socket Connection diff --git a/source/os-namedsocket.hpp b/source/os-namedsocket.hpp deleted file mode 100644 index 033fdc4..0000000 --- a/source/os-namedsocket.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files(the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ - -#ifndef OS_NAMEDSOCKET_HPP -#define OS_NAMEDSOCKET_HPP - -#include -#include -#include -#include -#include -#include -#include "os/error.hpp" - -namespace os { - typedef int64_t ClientId_t; - - class named_socket_connection; - class named_socket { - bool is_ready; - - - public: - - - - - - public: - static std::unique_ptr create(); - typedef void(*connect_handler_t)(std::shared_ptr conn); - typedef void(*disconnect_handler_t)(std::shared_ptr conn); - - named_socket(); - virtual ~named_socket(); - - #pragma region Options - /// Adjust the incoming(receive) buffer size. - bool set_receive_buffer_size(size_t size); - size_t get_receive_buffer_size(); - - /// Adjust the outgoing(send) buffer size. - bool set_send_buffer_size(size_t size); - size_t get_send_buffer_size(); - - /// Adjust the timeout for waiting. - bool set_wait_timeout(std::chrono::nanoseconds time); - std::chrono::nanoseconds get_wait_timeout(); - - /// Adjust the timeout for receiving data. - bool set_receive_timeout(std::chrono::nanoseconds time); - std::chrono::nanoseconds get_receive_timeout(); - - /// Adjust the timeout for sending data. - bool set_send_timeout(std::chrono::nanoseconds time); - std::chrono::nanoseconds get_send_timeout(); - #pragma endregion Options - - #pragma region Listen/Connect/Close - // Listen to a Named Socket. - /// Listens on the specified path for connections of clients. These clients can be local or - /// on the network depending on what platform this is run on. - /// It will also attempt to keep a set amount of connections waiting for more clients, also - /// known as the backlog. A larger backlog can negatively impact performance while a lower - /// one means that less clients can connect simultaneously, resulting in delays. - bool listen(std::string path, size_t backlog); - - // Connect to a Named Socket. - /// Connects to an existing named socket (if possible), otherwise immediately returns false. - bool connect(std::string path); - - // Close the Named Socket. - /// Different behavior depending on Initialized mode: - /// - Create disconnects all clients and closes the socket. - /// - Connect just disconnects from the socket and closes it. - bool close(); - #pragma endregion Listen/Connect/Close - - #pragma region Server & Client - bool is_initialized(); - bool is_server(); - bool is_client(); - #pragma endregion Server & Client - - #pragma region Server Only - std::weak_ptr accept(); - bool accept(std::shared_ptr& conn); - #pragma endregion Server Only - - #pragma region Client Only - std::shared_ptr get_connection(); - #pragma endregion Client Only - - protected: - virtual bool _listen(std::string path, size_t backlog) = 0; - virtual bool _connect(std::string path) = 0; - virtual bool _close() = 0; - - private: - // Flags - bool m_isInitialized; - bool m_isListening; - - // Times for timing out. - std::chrono::nanoseconds m_timeOutWait; - std::chrono::nanoseconds m_timeOutReceive; - std::chrono::nanoseconds m_timeOutSend; - - // Buffers - size_t m_bufferReceiveSize; - size_t m_bufferSendSize; - - // IO - protected: - std::list> m_connections; - }; - - class named_socket_connection { - public: - - // Status - virtual bool is_waiting() = 0; - virtual bool is_connected() = 0; - virtual bool connect() = 0; - virtual bool disconnect() = 0; - virtual bool eof() = 0; - virtual bool good() = 0; - virtual bool bad(); - - // Reading - virtual size_t read_avail() = 0; - virtual size_t read_total() = 0; - virtual os::error read(char* buffer, size_t length, size_t& read_length) = 0; - virtual os::error write(char const* buffer, size_t const length, size_t& write_length) = 0; - - // Info - virtual ClientId_t get_client_id() = 0; - }; -} - -#endif diff --git a/source/os-windows-overlapped-manager.cpp b/source/os-windows-overlapped-manager.cpp deleted file mode 100644 index 6360b26..0000000 --- a/source/os-windows-overlapped-manager.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files(the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ - -#include "os-windows-overlapped-manager.hpp" - -void os::windows::overlapped_manager::create_overlapped(std::shared_ptr& ov) { - ov = std::make_shared(); - ov->Internal = ov->InternalHigh = ov->Offset = ov->OffsetHigh = 0; - ov->Pointer = nullptr; - ov->hEvent = CreateEventW(NULL, false, false, NULL); -} - -void os::windows::overlapped_manager::destroy_overlapped(std::shared_ptr& ov) { - CloseHandle(ov->hEvent); - ov = nullptr; -} - -void os::windows::overlapped_manager::append_create_overlapped() { - std::shared_ptr ov = nullptr; - create_overlapped(ov); - free_objects.push(ov); -} - -bool os::windows::overlapped_manager::create_security_attributes() { - DWORD dwRes; - - // Create a well-known SID for the Everyone group. - if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, - SECURITY_WORLD_RID, - 0, 0, 0, 0, 0, 0, 0, - &pEveryoneSID)) { - return false; - } - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow Everyone read access to the key. - ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); - ea[0].grfAccessPermissions = KEY_READ; - ea[0].grfAccessMode = SET_ACCESS; - ea[0].grfInheritance = NO_INHERITANCE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID; - - // Create a SID for the BUILTIN\Administrators group. - if (!AllocateAndInitializeSid(&SIDAuthNT, 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &pAdminSID)) { - return false; - } - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow the Administrators group full access to - // the key. - ea[1].grfAccessPermissions = KEY_ALL_ACCESS; - ea[1].grfAccessMode = SET_ACCESS; - ea[1].grfInheritance = NO_INHERITANCE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea[1].Trustee.ptstrName = (LPTSTR)pAdminSID; - - // Create a new ACL that contains the new ACEs. - dwRes = SetEntriesInAcl(2, ea, NULL, &pACL); - if (ERROR_SUCCESS != dwRes) { - return false; - } - - // Initialize a security descriptor. - pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, - SECURITY_DESCRIPTOR_MIN_LENGTH); - if (NULL == pSD) { - return false; - } - - if (!InitializeSecurityDescriptor(pSD, - SECURITY_DESCRIPTOR_REVISION)) { - return false; - } - - // Add the ACL to the security descriptor. - if (!SetSecurityDescriptorDacl(pSD, - TRUE, // bDaclPresent flag - pACL, - FALSE)) // not a default DACL - { - return false; - } - - // Initialize a security attributes structure. - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = pSD; - sa.bInheritHandle = FALSE; - return true; -} - -void os::windows::overlapped_manager::destroy_security_attributes() { - if (pEveryoneSID) - FreeSid(pEveryoneSID); - if (pAdminSID) - FreeSid(pAdminSID); - if (pACL) - LocalFree(pACL); - if (pSD) - LocalFree(pSD); -} - -os::windows::overlapped_manager::overlapped_manager() { - if (!create_security_attributes()) { - destroy_security_attributes(); - throw std::runtime_error("can't create security attributes"); - } - - // Prepare for 8 queued writes. - for (size_t idx = 0; idx < 8; idx++) { - append_create_overlapped(); - } -} - -os::windows::overlapped_manager::~overlapped_manager() { - std::shared_ptr ov = nullptr; - while (free_objects.size() > 0) { - ov = free_objects.front(); - free_objects.pop(); - destroy_overlapped(ov); - } - - while (used_objects.size() > 0) { - ov = used_objects.front(); - used_objects.pop_front(); - destroy_overlapped(ov); - } - - destroy_security_attributes(); -} - -std::shared_ptr os::windows::overlapped_manager::alloc() { - std::unique_lock ulock(objects_mtx); - if (free_objects.size() == 0) { - append_create_overlapped(); - } - - std::shared_ptr ov = free_objects.front(); - free_objects.pop(); - used_objects.push_back(ov); - return ov; -} - -void os::windows::overlapped_manager::free(std::shared_ptr ov) { - std::unique_lock ulock(objects_mtx); - for (auto itr = used_objects.begin(); itr != used_objects.end(); itr++) { - if (*itr == ov) { - used_objects.erase(itr); - } - } - ResetEvent(ov->hEvent); - free_objects.push(ov); -} - diff --git a/source/os-windows-overlapped-manager.hpp b/source/os-windows-overlapped-manager.hpp deleted file mode 100644 index fd92570..0000000 --- a/source/os-windows-overlapped-manager.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright(C) 2018 Michael Fabian Dirks -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files(the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -** IN THE SOFTWARE. -*/ - -#ifndef OS_WINDOWS_OVERLAPPED_MANAGER_HPP -#define OS_WINDOWS_OVERLAPPED_MANAGER_HPP - -extern "C" { // clang++ compatible -#define NOMINMAX -#define _WIN32_WINNT _WIN32_WINNT_WIN10 -#include -#include -#include -} - -#include -#include -#include -#include - -namespace os { - namespace windows { - class overlapped_manager { - // Security Descriptor Stuff - SECURITY_ATTRIBUTES sa; - PSECURITY_DESCRIPTOR pSD = NULL; - PSID pEveryoneSID = NULL, pAdminSID = NULL; - PACL pACL = NULL; - EXPLICIT_ACCESS ea[2]; - SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; - - // Overlapped Objects - std::queue> free_objects; - std::list> used_objects; - std::mutex objects_mtx; - - void create_overlapped(std::shared_ptr& ov); - void destroy_overlapped(std::shared_ptr& ov); - void append_create_overlapped(); - - bool create_security_attributes(); - void destroy_security_attributes(); - - public: - overlapped_manager(); - ~overlapped_manager(); - - std::shared_ptr alloc(); - void free(std::shared_ptr ov); - }; - } -} - -#endif From fb911eb3360d419561265ebb38c46c1fcc5b7314 Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Mon, 14 Jan 2019 11:36:11 -0800 Subject: [PATCH 4/7] Remove some of the semaphore unused code --- source/os/semaphore.hpp | 6 --- source/os/windows/semaphore.cpp | 92 --------------------------------- source/os/windows/semaphore.hpp | 5 -- 3 files changed, 103 deletions(-) diff --git a/source/os/semaphore.hpp b/source/os/semaphore.hpp index 46090b8..a89beb8 100644 --- a/source/os/semaphore.hpp +++ b/source/os/semaphore.hpp @@ -27,12 +27,6 @@ namespace os { class semaphore : public os::waitable { public: virtual os::error signal(uint32_t count = 1) = 0; - - public: - static std::shared_ptr construct(uint32_t value = 0); - static std::shared_ptr construct(os::create_only_t, std::string name, uint32_t value = 0); - static std::shared_ptr construct(os::create_or_open_t, std::string name, uint32_t value = 0); - static std::shared_ptr construct(os::open_only_t, std::string name); }; } // namespace os diff --git a/source/os/windows/semaphore.cpp b/source/os/windows/semaphore.cpp index f6509d0..3be0e54 100644 --- a/source/os/windows/semaphore.cpp +++ b/source/os/windows/semaphore.cpp @@ -20,51 +20,6 @@ #include #include "semaphore.hpp" -inline std::wstring make_wide_string(std::string name) { - std::wstring_convert> converter; - return converter.from_bytes(name); -} - -inline void validate_params(std::wstring name, int32_t initial_count, int32_t maximum_count) { - if (initial_count > maximum_count) { - throw std::invalid_argument("'initial_count' can't be larger than 'maximum_count'."); - } else if (initial_count < 0) { - throw std::invalid_argument("'initial_count' can't be negative."); - } else if (maximum_count == 0) { - throw std::invalid_argument("'maximum_count' can't be 0."); - } else if (maximum_count < 0) { - throw std::invalid_argument("'maximum_count' can't be negative."); - } else if (name.length() > 0) { - if (name.length() >= MAX_PATH) { - std::vector msg(2048); - sprintf_s(msg.data(), msg.size(), "'name' can't be longer than %lld characters.\0", uint64_t(MAX_PATH)); - throw std::invalid_argument(msg.data()); - } - } -} - -inline void create_semaphore_impl(HANDLE &handle, std::wstring name, DWORD initial_count, DWORD maximum_count) { - SetLastError(ERROR_SUCCESS); - handle = CreateSemaphoreW(NULL, initial_count, maximum_count, name.data()); - DWORD err = GetLastError(); - if (!handle || (err != ERROR_SUCCESS)) { - std::vector msg(2048); - sprintf_s(msg.data(), msg.size(), "Semaphore creation failed with error code %lX.\0", GetLastError()); - throw std::runtime_error(msg.data()); - } -} - -inline void open_semaphore_impl(HANDLE &handle, std::wstring name) { - SetLastError(ERROR_SUCCESS); - handle = OpenSemaphoreW(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, false, name.data()); - DWORD err = GetLastError(); - if (!handle || (err != ERROR_SUCCESS)) { - std::vector msg(2048); - sprintf_s(msg.data(), msg.size(), "Opening Semaphore failed with error code %lX.\0", GetLastError()); - throw std::runtime_error(msg.data()); - } -} - os::windows::semaphore::semaphore(int32_t initial_count /*= 0*/, int32_t maximum_count /*= UINT32_MAX*/) { if (initial_count > maximum_count) { throw std::invalid_argument("initial_count can't be larger than maximum_count"); @@ -81,31 +36,6 @@ os::windows::semaphore::semaphore(int32_t initial_count /*= 0*/, int32_t maximum } } -os::windows::semaphore::semaphore(os::create_only_t, std::string name, int32_t initial_count /*= 0*/, - int32_t maximum_count /*= UINT32_MAX*/) { - std::wstring wide_name = make_wide_string(name + '\0'); - validate_params(wide_name, initial_count, maximum_count); - create_semaphore_impl(handle, wide_name, initial_count, maximum_count); -} - -os::windows::semaphore::semaphore(os::create_or_open_t, std::string name, int32_t initial_count /*= 0*/, - int32_t maximum_count /*= UINT32_MAX*/) { - std::wstring wide_name = make_wide_string(name + '\0'); - validate_params(wide_name, initial_count, maximum_count); - try { - create_semaphore_impl(handle, wide_name, initial_count, maximum_count); - } catch (...) { - // There's technically two errors here, but the latter is likely to be more interesting. - open_semaphore_impl(handle, wide_name); - } -} - -os::windows::semaphore::semaphore(os::open_only_t, std::string name) { - std::wstring wide_name = make_wide_string(name + '\0'); - validate_params(wide_name, 0, 1); - open_semaphore_impl(handle, wide_name); -} - os::windows::semaphore::~semaphore() { if (handle) { CloseHandle(handle); @@ -128,25 +58,3 @@ os::error os::windows::semaphore::signal(uint32_t count /*= 1*/) { void *os::windows::semaphore::get_waitable() { return (void *)handle; } - -std::shared_ptr os::semaphore::construct(uint32_t value /*= 0*/) { - int32_t val = value <= uint32_t(std::numeric_limits::max()) ? int32_t(value) : std::numeric_limits::max(); - return std::make_shared(val); -} - -std::shared_ptr os::semaphore::construct(os::create_only_t, std::string name, uint32_t value /*= 0*/) { - int32_t val = - value <= uint32_t(std::numeric_limits::max()) ? int32_t(value) : std::numeric_limits::max(); - return std::make_shared(os::create_only, name, val); -} - -std::shared_ptr os::semaphore::construct(os::create_or_open_t, std::string name, - uint32_t value /*= 0*/) { - int32_t val = - value <= uint32_t(std::numeric_limits::max()) ? int32_t(value) : std::numeric_limits::max(); - return std::make_shared(os::create_or_open, name, val); -} - -std::shared_ptr os::semaphore::construct(os::open_only_t, std::string name) { - return std::make_shared(os::open_only, name); -} diff --git a/source/os/windows/semaphore.hpp b/source/os/windows/semaphore.hpp index 7313fff..1afea46 100644 --- a/source/os/windows/semaphore.hpp +++ b/source/os/windows/semaphore.hpp @@ -33,11 +33,6 @@ namespace os { public: semaphore(int32_t initial_count = 0, int32_t maximum_count = std::numeric_limits::max()); - semaphore(os::create_only_t, std::string name, int32_t initial_count = 0, - int32_t maximum_count = std::numeric_limits::max()); - semaphore(os::create_or_open_t, std::string name, int32_t initial_count = 0, - int32_t maximum_count = std::numeric_limits::max()); - semaphore(os::open_only_t, std::string name); virtual ~semaphore(); virtual os::error signal(uint32_t count = 1) override; From 9a7aad2072be28d88993dd99f3e02159af3c1ad7 Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Mon, 14 Jan 2019 12:07:47 -0800 Subject: [PATCH 5/7] Remove unused get_bytes_transferred function --- source/os/async_op.hpp | 2 -- source/os/windows/async_request.cpp | 14 -------------- source/os/windows/async_request.hpp | 2 -- 3 files changed, 18 deletions(-) diff --git a/source/os/async_op.hpp b/source/os/async_op.hpp index 9fea71b..d85ed5e 100644 --- a/source/os/async_op.hpp +++ b/source/os/async_op.hpp @@ -49,8 +49,6 @@ namespace os { virtual bool is_complete() = 0; - virtual size_t get_bytes_transferred() = 0; - virtual bool cancel() = 0; virtual void set_callback(async_op_cb_t u_callback); diff --git a/source/os/windows/async_request.cpp b/source/os/windows/async_request.cpp index 9d38889..953dd8f 100644 --- a/source/os/windows/async_request.cpp +++ b/source/os/windows/async_request.cpp @@ -72,20 +72,6 @@ bool os::windows::async_request::is_complete() { return HasOverlappedIoCompleted(this->get_overlapped_pointer()); } -size_t os::windows::async_request::get_bytes_transferred() { - if (!is_valid()) { - return 0; - } - - DWORD bytes = 0; - SetLastError(ERROR_SUCCESS); - GetOverlappedResult(handle, this->get_overlapped_pointer(), &bytes, false); - if (GetLastError() == ERROR_IO_INCOMPLETE) { - return 0; - } - return bytes; -} - bool os::windows::async_request::cancel() { if (!is_valid()) { return false; diff --git a/source/os/windows/async_request.hpp b/source/os/windows/async_request.hpp index d8671c4..bf46d9c 100644 --- a/source/os/windows/async_request.hpp +++ b/source/os/windows/async_request.hpp @@ -48,8 +48,6 @@ namespace os { virtual bool is_complete() override; - virtual size_t get_bytes_transferred() override; - virtual bool cancel() override; virtual void call_callback() override; From eb0960576c21b95b1e8ec1e62d7ca2c984caf6d1 Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Mon, 14 Jan 2019 14:11:34 -0800 Subject: [PATCH 6/7] Remove unused named-pipe code --- source/os/windows/named-pipe.cpp | 47 -------------------------------- source/os/windows/named-pipe.hpp | 7 ----- 2 files changed, 54 deletions(-) diff --git a/source/os/windows/named-pipe.cpp b/source/os/windows/named-pipe.cpp index 5edbc32..5527f9a 100644 --- a/source/os/windows/named-pipe.cpp +++ b/source/os/windows/named-pipe.cpp @@ -152,23 +152,6 @@ os::windows::named_pipe::named_pipe(os::create_only_t, std::string name, created = true; } -os::windows::named_pipe::named_pipe(os::create_or_open_t, std::string name, - size_t max_instances /*= PIPE_UNLIMITED_INSTANCES*/, - pipe_type type /*= pipe_type::Message*/, - pipe_read_mode mode /*= pipe_read_mode::Message*/, bool is_unique /*= false*/) - : named_pipe() { - validate_create_param(name, max_instances); - - std::wstring wide_name = make_wide_string(make_windows_compatible(name + '\0')); - try { - create_logic(handle, wide_name, max_instances, type, mode, is_unique, security_attributes); - created = true; - } catch (...) { - open_logic(handle, wide_name, mode); - set_connected(true); - } -} - os::windows::named_pipe::named_pipe(os::open_only_t, std::string name, pipe_read_mode mode /*= pipe_read_mode::Message*/) : named_pipe() { @@ -186,36 +169,6 @@ os::windows::named_pipe::~named_pipe() { } } -os::error os::windows::named_pipe::available(size_t &avail) { - DWORD bytes = 0; - SetLastError(ERROR_SUCCESS); - if (!PeekNamedPipe(handle, NULL, NULL, NULL, NULL, &bytes) || (GetLastError() != ERROR_SUCCESS)) { - switch (GetLastError()) { - case ERROR_BROKEN_PIPE: - return os::error::Disconnected; - default: - return os::error::Error; - } - } - avail = bytes; - return os::error::Success; -} - -os::error os::windows::named_pipe::total_available(size_t &avail) { - DWORD bytes = 0; - SetLastError(ERROR_SUCCESS); - if (!PeekNamedPipe(handle, NULL, NULL, NULL, &bytes, NULL) || (GetLastError() != ERROR_SUCCESS)) { - switch (GetLastError()) { - case ERROR_BROKEN_PIPE: - return os::error::Disconnected; - default: - return os::error::Error; - } - } - avail = bytes; - return os::error::Success; -} - os::error os::windows::named_pipe::read(char *buffer, size_t buffer_length, std::shared_ptr &op, os::async_op_cb_t cb) { os::error ec; diff --git a/source/os/windows/named-pipe.hpp b/source/os/windows/named-pipe.hpp index 8e88254..2a88679 100644 --- a/source/os/windows/named-pipe.hpp +++ b/source/os/windows/named-pipe.hpp @@ -64,16 +64,9 @@ namespace os { named_pipe(os::create_only_t, std::string name, size_t max_instances = PIPE_UNLIMITED_INSTANCES, pipe_type type = pipe_type::Message, pipe_read_mode mode = pipe_read_mode::Message, bool is_unique = false); - named_pipe(os::create_or_open_t, std::string name, size_t max_instances = PIPE_UNLIMITED_INSTANCES, - pipe_type type = pipe_type::Message, pipe_read_mode mode = pipe_read_mode::Message, - bool is_unique = false); named_pipe(os::open_only_t, std::string name, pipe_read_mode mode = pipe_read_mode::Message); ~named_pipe(); - os::error available(size_t &avail); - - os::error total_available(size_t &avail); - os::error read(char *buffer, size_t buffer_length, std::shared_ptr &op, os::async_op_cb_t cb); os::error write(const char *buffer, size_t buffer_length, std::shared_ptr &op, From 97a2ec85e381eb5410d7fb74754ab2f6b6592a4c Mon Sep 17 00:00:00 2001 From: eddyStreamlabs Date: Mon, 14 Jan 2019 14:27:04 -0800 Subject: [PATCH 7/7] Remove unused wait_any code --- source/os/waitable.hpp | 7 ------- source/os/windows/waitable.cpp | 13 ------------- 2 files changed, 20 deletions(-) diff --git a/source/os/waitable.hpp b/source/os/waitable.hpp index 2d42f6c..48b0434 100644 --- a/source/os/waitable.hpp +++ b/source/os/waitable.hpp @@ -38,15 +38,8 @@ namespace os { static os::error wait(waitable *item, std::chrono::nanoseconds timeout); - static os::error wait_any(waitable **items, size_t items_count, size_t &signalled_index); - static os::error wait_any(waitable **items, size_t items_count, size_t &signalled_index, std::chrono::nanoseconds timeout); - - static os::error wait_any(std::vector items, size_t &signalled_index); - - static os::error wait_any(std::vector items, size_t &signalled_index, - std::chrono::nanoseconds timeout); }; } // namespace os diff --git a/source/os/windows/waitable.cpp b/source/os/windows/waitable.cpp index a1df3c6..ff16c5e 100644 --- a/source/os/windows/waitable.cpp +++ b/source/os/windows/waitable.cpp @@ -110,16 +110,3 @@ os::error os::waitable::wait_any(waitable **items, size_t items_count, size_t &s } return os::error::Error; } - -os::error os::waitable::wait_any(waitable **items, size_t items_count, size_t &signalled_index) { - return wait_any(items, items_count, signalled_index, std::chrono::milliseconds(INFINITE)); -} - -os::error os::waitable::wait_any(std::vector items, size_t &signalled_index, - std::chrono::nanoseconds timeout) { - return wait_any(items.data(), items.size(), signalled_index, timeout); -} - -os::error os::waitable::wait_any(std::vector items, size_t &signalled_index) { - return wait_any(items.data(), items.size(), signalled_index); -}