From ac76cdc4bbc50c4aaf4d4329b2705770651e41a3 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Tue, 9 Jun 2015 14:13:57 +0200 Subject: [PATCH 01/13] Fix gitignore syntax --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index df58d9de..979e8d65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -./build -./build64 \ No newline at end of file +/build +/build64 +/third_party \ No newline at end of file From 9dfd4760a7237b9b90316657f3eb9e6c54ef5d07 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Tue, 9 Jun 2015 14:15:05 +0200 Subject: [PATCH 02/13] Fixed #2: exception safety in SSL policy --- src/common/utils/cleaner.h | 24 +++++++++++++++++++ .../link_policies/ssl_policy.h | 22 ++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/common/utils/cleaner.h diff --git a/src/common/utils/cleaner.h b/src/common/utils/cleaner.h new file mode 100644 index 00000000..6f666934 --- /dev/null +++ b/src/common/utils/cleaner.h @@ -0,0 +1,24 @@ +#ifndef SSF_COMMON_UTILS_CLEANER_H_ +#define SSF_COMMON_UTILS_CLEANER_H_ + +#include + +class ScopeCleaner { + private: + typedef std::function Handler; + + public: + ScopeCleaner(Handler handler) : handler_(std::move(handler)) {} + ~ScopeCleaner() { + try { + handler_(); + } catch (...) { + // Swallows exceptions + } + } + + private: + Handler handler_; +}; + +#endif // SSF_COMMON_UTILS_CLEANER_H_ diff --git a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h index 8a5c1e67..bf307290 100644 --- a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h +++ b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h @@ -26,6 +26,7 @@ #include "common/config/config.h" #include "common/error/error.h" #include "common/boost/fiber/detail/io_ssl_read_op.hpp" +#include "common/utils/cleaner.h" namespace ssf { @@ -469,33 +470,42 @@ class BaseSSLPolicy { // If a new CA is provided, use it if (auth_cert.size()) { X509 *x509_ca = NULL; + ScopeCleaner cleaner([&x509_ca]() { + X509_free(x509_ca); + x509_ca = NULL; + }); + auto p_auth_cert = auth_cert.data(); d2i_X509(&x509_ca, (const unsigned char **)&p_auth_cert, (uint32_t)auth_cert.size()); X509_STORE *store = X509_STORE_new(); SSL_CTX_set_cert_store(p_ctx->native_handle(), store); X509_STORE_add_cert(store, x509_ca); - X509_free(x509_ca); - x509_ca = NULL; } { X509 *x509_cert = NULL; + ScopeCleaner cleaner([&x509_cert]() { + X509_free(x509_cert); + x509_cert = NULL; + }); + auto p_cert = cert.data(); d2i_X509(&x509_cert, (const unsigned char **)&p_cert, (uint32_t)cert.size()); SSL_CTX_use_certificate(p_ctx->native_handle(), x509_cert); - X509_free(x509_cert); - x509_cert = NULL; } { EVP_PKEY *RSA_key = NULL; + ScopeCleaner cleaner([&RSA_key]() { + EVP_PKEY_free(RSA_key); + RSA_key = NULL; + }); + auto p_key = key.data(); d2i_PrivateKey(EVP_PKEY_RSA, &RSA_key, (const unsigned char **)&p_key, (uint32_t)key.size()); SSL_CTX_use_PrivateKey(p_ctx->native_handle(), RSA_key); - EVP_PKEY_free(RSA_key); - RSA_key = NULL; } } From 8cb0aa3625174d7884d75192571a744d6f6fa5ff Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Wed, 30 Sep 2015 18:43:10 +0200 Subject: [PATCH 03/13] Refactor CMakeLists Remove unused file --- CMakeLists.txt | 178 +++++++++------------------ src/core/client/CMakeLists.txt | 18 +-- src/core/server/CMakeLists.txt | 17 +-- src/services/admin/admin_command.cpp | 7 -- src/tests/CMakeLists.txt | 55 ++------- 5 files changed, 73 insertions(+), 202 deletions(-) delete mode 100644 src/services/admin/admin_command.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d2228f3..2c8d2b68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,123 +33,67 @@ set(project_THIRDPARTY_DIR "${project_ROOT_DIR}/third_party") # --- Project files declaration set(VERSIONS_FILES "${project_BINARY_DIR}/versions.h") - -set(CORE_INIT_PACKETS - "${project_SRC_DIR}/core/transport_virtual_layer_policies/transport_protocol_policy.h" - "${project_SRC_DIR}/core/transport_virtual_layer_policies/init_packets/ssf_reply.h" - "${project_SRC_DIR}/core/transport_virtual_layer_policies/init_packets/ssf_reply.cpp" - "${project_SRC_DIR}/core/transport_virtual_layer_policies/init_packets/ssf_request.h" - "${project_SRC_DIR}/core/transport_virtual_layer_policies/init_packets/ssf_request.cpp") - -set(CORE_NETWORK_VIRTUAL_LAYER_POLICY - "${project_SRC_DIR}/core/network_virtual_layer_policies/bounce_protocol_policy.h" - "${project_SRC_DIR}/core/network_virtual_layer_policies/link_policies/ssl_policy.h" - "${project_SRC_DIR}/core/network_virtual_layer_policies/link_policies/tcp_policy.h" - "${project_SRC_DIR}/core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h") - -set(CORE_FACTORIES_FILES - "${project_SRC_DIR}/core/factories/command_factory.h" - "${project_SRC_DIR}/core/factory_manager/service_factory_manager.h" - "${project_SRC_DIR}/core/factories/service_factory.h" - "${project_SRC_DIR}/core/factories/service_option_factory.h" - "${project_SRC_DIR}/core/service_manager/service_manager.h") - -set(COMMON_BOOST_HEADER_FILES - "${project_SRC_DIR}/common/boost/fiber/detail/fiber_id.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/fiber_buffer.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/fiber_header.hpp" - "${project_SRC_DIR}/common/boost/fiber/stream_fiber.hpp" - "${project_SRC_DIR}/common/boost/fiber/basic_endpoint.hpp" - "${project_SRC_DIR}/common/boost/fiber/stream_fiber_service.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/basic_fiber_impl.hpp" - "${project_SRC_DIR}/common/boost/fiber/basic_fiber_demux.hpp" - "${project_SRC_DIR}/common/boost/fiber/basic_fiber_demux_service.hpp" - "${project_SRC_DIR}/common/boost/fiber/basic_fiber_demux_service.ipp" - "${project_SRC_DIR}/common/boost/fiber/detail/basic_fiber_demux_impl.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/io_fiber_accept_op.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/io_fiber_read_op.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/io_fiber_dgr_read_op.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/io_ssl_read_op.hpp" - "${project_SRC_DIR}/common/boost/fiber/detail/io_operation.hpp" - "${project_SRC_DIR}/common/boost/fiber/fiber_acceptor_service.hpp" - "${project_SRC_DIR}/common/boost/fiber/datagram_fiber_service.hpp" - "${project_SRC_DIR}/common/boost/fiber/datagram_fiber.hpp") - -set(COMMON_COMMAND_LINE_FILES - "${project_SRC_DIR}/core/command_line/command_line.h" - "${project_SRC_DIR}/core/command_line/command_line.cpp") - -set(COMMON_CONFIG_FILES - "${project_SRC_DIR}/common/config/config.h" - "${project_SRC_DIR}/common/config/config.cpp") - -set(COMMON_ERROR_FILES - "${project_SRC_DIR}/common/error/error.h" - "${project_SRC_DIR}/common/error/error.cpp") - -set(COMMON_NETWORK_HEADER_FILES - "${project_SRC_DIR}/common/network/base_session.h" - "${project_SRC_DIR}/common/network/datagram_link.h" - "${project_SRC_DIR}/common/network/datagram_link_operator.h" - "${project_SRC_DIR}/common/network/manager.h" - "${project_SRC_DIR}/common/network/network_policy_traits.h" - "${project_SRC_DIR}/common/network/session_forwarder.h" - "${project_SRC_DIR}/common/network/socket_link.h") - -set(SERVICES_ADMIN_SERVICE_FILES - "${project_SRC_DIR}/services/initialisation.h" - "${project_SRC_DIR}/services/base_service.h" - "${project_SRC_DIR}/services/admin/admin.h" - "${project_SRC_DIR}/services/admin/admin_command.h" - "${project_SRC_DIR}/services/admin/admin.ipp" - "${project_SRC_DIR}/services/admin/requests/create_service_request.h" - "${project_SRC_DIR}/services/admin/requests/service_status.h" - "${project_SRC_DIR}/services/admin/requests/stop_service_request.h") - -set(SERVICES_SOCKS_FILES - "${project_SRC_DIR}/services/socks/socks_server.h" - "${project_SRC_DIR}/services/socks/socks_version.h" - "${project_SRC_DIR}/services/socks/v4/reply.cpp" - "${project_SRC_DIR}/services/socks/v4/reply.h" - "${project_SRC_DIR}/services/socks/v4/request.cpp" - "${project_SRC_DIR}/services/socks/v4/request.h" - "${project_SRC_DIR}/services/socks/v4/session.h" - "${project_SRC_DIR}/services/socks/v4/session.ipp" - "${project_SRC_DIR}/services/socks/v5/reply.cpp" - "${project_SRC_DIR}/services/socks/v5/reply.h" - "${project_SRC_DIR}/services/socks/v5/request.cpp" - "${project_SRC_DIR}/services/socks/v5/request.h" - "${project_SRC_DIR}/services/socks/v5/reply_auth.cpp" - "${project_SRC_DIR}/services/socks/v5/reply_auth.h" - "${project_SRC_DIR}/services/socks/v5/request_auth.cpp" - "${project_SRC_DIR}/services/socks/v5/request_auth.h" - "${project_SRC_DIR}/services/socks/v5/session.h" - "${project_SRC_DIR}/services/socks/v5/session.ipp") - -set(SERVICES_USER_SERVICES_FILES - "${project_SRC_DIR}/services/user_services/base_user_service.h" - "${project_SRC_DIR}/services/user_services/port_forwarding.h" - "${project_SRC_DIR}/services/user_services/remote_port_forwarding.h" - "${project_SRC_DIR}/services/user_services/remote_socks.h" - "${project_SRC_DIR}/services/user_services/socks.h" - "${project_SRC_DIR}/services/user_services/udp_port_forwarding.h" - "${project_SRC_DIR}/services/user_services/udp_remote_port_forwarding.h") - -set(SERVICES_SOCKETS_TO_FIBERS_FILES - "${project_SRC_DIR}/services/sockets_to_fibers/sockets_to_fibers.h" - "${project_SRC_DIR}/services/sockets_to_fibers/sockets_to_fibers.ipp") - -set(SERVICES_DATAGRAMS_TO_FIBERS_FILES - "${project_SRC_DIR}/services/datagrams_to_fibers/datagrams_to_fibers.h" - "${project_SRC_DIR}/services/datagrams_to_fibers/datagrams_to_fibers.ipp") - -set(SERVICES_FIBERS_TO_SOCKETS_FILES - "${project_SRC_DIR}/services/fibers_to_sockets/fibers_to_sockets.h" - "${project_SRC_DIR}/services/fibers_to_sockets/fibers_to_sockets.ipp") - -set(SERVICES_FIBERS_TO_DATAGRAMS_FILES - "${project_SRC_DIR}/services/fibers_to_datagrams/fibers_to_datagrams.h" - "${project_SRC_DIR}/services/fibers_to_datagrams/fibers_to_datagrams.ipp") + +FILE(GLOB_RECURSE COMMON_BOOST_FIBER_FILES + "${project_SRC_DIR}/common/boost/fiber/*.hpp" + "${project_SRC_DIR}/common/boost/fiber/*.cpp") + +FILE(GLOB_RECURSE COMMON_COMMAND_LINE_FILES + "${project_SRC_DIR}/core/command_line/*.h" + "${project_SRC_DIR}/core/command_line/*.cpp") + +FILE(GLOB_RECURSE COMMON_CONFIG_FILES + "${project_SRC_DIR}/common/config/*.h" + "${project_SRC_DIR}/common/config/*.cpp") + +FILE(GLOB_RECURSE COMMON_ERROR_FILES + "${project_SRC_DIR}/common/error/*.h" + "${project_SRC_DIR}/common/error/*.cpp") + +FILE(GLOB_RECURSE COMMON_UTILS_FILES + "${project_SRC_DIR}/common/utils/*.h" + "${project_SRC_DIR}/common/utils/*.cpp" + "${project_SRC_DIR}/common/utils/*.ipp") + +FILE(GLOB_RECURSE CORE_TRANSPORT_POLICIES_FILES + "${project_SRC_DIR}/core/transport_virtual_layer_policies/*.h" + "${project_SRC_DIR}/core/transport_virtual_layer_policies/*.cpp" + "${project_SRC_DIR}/core/transport_virtual_layer_policies/*.ipp") + +FILE(GLOB_RECURSE CORE_NETWORK_VIRTUAL_LAYER_POLICIES_FILES + "${project_SRC_DIR}/core/network_virtual_layer_policies/*.h" + "${project_SRC_DIR}/core/network_virtual_layer_policies/*.cpp" + "${project_SRC_DIR}/core/network_virtual_layer_policies/*.ipp") + +FILE(GLOB_RECURSE CORE_FACTORIES_FILES + "${project_SRC_DIR}/core/factories/*.h" + "${project_SRC_DIR}/core/factories/*.cpp" + "${project_SRC_DIR}/core/factories/*.ipp" + "${project_SRC_DIR}/core/factory_manager/*.h" + "${project_SRC_DIR}/core/factory_manager/*.cpp" + "${project_SRC_DIR}/core/factory_manager/*.ipp" + "${project_SRC_DIR}/core/service_manager/*.h" + "${project_SRC_DIR}/core/service_manager/*.cpp" + "${project_SRC_DIR}/core/service_manager/*.ipp") + +FILE(GLOB_RECURSE SERVICES_FILES + "${project_SRC_DIR}/services/*.h" + "${project_SRC_DIR}/services/*.cpp" + "${project_SRC_DIR}/services/*.ipp") + +set(SSF_SOURCES + ${VERSIONS_FILES} + ${COMMON_BOOST_FIBER_FILES} + ${COMMON_COMMAND_LINE_FILES} + ${COMMON_CONFIG_FILES} + ${COMMON_ERROR_FILES} + ${COMMON_NETWORK_FILES} + ${COMMON_UTILS_FILES} + ${CORE_TRANSPORT_POLICIES_FILES} + ${CORE_NETWORK_VIRTUAL_LAYER_POLICIES_FILES} + ${CORE_FACTORIES_FILES} + ${SERVICES_FILES} +) set(BOOST_ROOT "${project_THIRDPARTY_DIR}/boost" CACHE PATH "Path of boost library") diff --git a/src/core/client/CMakeLists.txt b/src/core/client/CMakeLists.txt index e7c75bda..1b5b2d1c 100644 --- a/src/core/client/CMakeLists.txt +++ b/src/core/client/CMakeLists.txt @@ -16,24 +16,8 @@ add_target(${project_NAME} TYPE executable ${EXEC_FLAG} FILES - ${VERSIONS_FILES} ${CLIENT_FILES} - ${CORE_INIT_PACKETS} - ${CORE_NETWORK_VIRTUAL_LAYER_POLICY} - ${CORE_FACTORIES_FILES} - ${COMMON_BOOST_HEADER_FILES} - ${COMMON_NETWORK_HEADER_FILES} - ${COMMON_UTILS_HEADER_FILES} - ${COMMON_COMMAND_LINE_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${SERVICES_SOCKS_FILES} - ${SERVICES_USER_SERVICES_FILES} - ${SERVICES_SOCKETS_TO_FIBERS_FILES} - ${SERVICES_DATAGRAMS_TO_FIBERS_FILES} - ${SERVICES_FIBERS_TO_SOCKETS_FILES} - ${SERVICES_FIBERS_TO_DATAGRAMS_FILES} - ${SERVICES_ADMIN_SERVICE_FILES} + ${SSF_SOURCES} ${ICON_RC} PREFIX_SKIP ${project_SRC_DIR}) diff --git a/src/core/server/CMakeLists.txt b/src/core/server/CMakeLists.txt index cb6257fd..b5e9ff1b 100644 --- a/src/core/server/CMakeLists.txt +++ b/src/core/server/CMakeLists.txt @@ -16,23 +16,8 @@ add_target(${project_NAME} TYPE executable ${EXEC_FLAG} FILES - ${VERSIONS_FILES} ${SERVER_FILES} - ${CORE_INIT_PACKETS} - ${CORE_NETWORK_VIRTUAL_LAYER_POLICY} - ${CORE_FACTORIES_FILES} - ${SERVICES_SOCKS_FILES} - ${COMMON_BOOST_HEADER_FILES} - ${COMMON_NETWORK_HEADER_FILES} - ${COMMON_UTILS_HEADER_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${COMMON_COMMAND_LINE_FILES} - ${SERVICES_SOCKETS_TO_FIBERS_FILES} - ${SERVICES_DATAGRAMS_TO_FIBERS_FILES} - ${SERVICES_FIBERS_TO_SOCKETS_FILES} - ${SERVICES_FIBERS_TO_DATAGRAMS_FILES} - ${SERVICES_ADMIN_SERVICE_FILES} + ${SSF_SOURCES} ${ICON_RC} PREFIX_SKIP ${project_SRC_DIR}) diff --git a/src/services/admin/admin_command.cpp b/src/services/admin/admin_command.cpp deleted file mode 100644 index 097b9fce..00000000 --- a/src/services/admin/admin_command.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "services/admin/admin_command.h" - -namespace ssf { namespace services { namespace admin - -} // admin -} // services -} // ssf \ No newline at end of file diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index ab09def2..1e82530a 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -39,6 +39,7 @@ add_test( # --- Fiber asio tests set(fiber_asio_test_source_files "fiber_asio_tests.cpp" + ${COMMON_BOOST_FIBER_FILES} ${COMMON_ERROR_FILES} ) @@ -64,11 +65,7 @@ add_test( # --- SSF Client Server tests set(ssf_client_server_source_files "ssf_client_server_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${ssf_client_server_source_files}) @@ -93,11 +90,7 @@ add_test( # --- SSF Client Server cipher suites tests set(ssf_client_server_cipher_suites_source_files "ssf_client_server_cipher_suites_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${ssf_client_server_cipher_suites_source_files}) @@ -122,11 +115,7 @@ add_test( # --- Socks test set(socks_test_source_files "socks_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${socks_test_source_files}) @@ -151,11 +140,7 @@ add_test( # --- Remote socks test set(remote_socks_test_source_files "remote_socks_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${remote_socks_test_source_files}) @@ -180,11 +165,7 @@ add_test( # --- Stream forward test set(stream_forwarding_test_source_files "stream_forwarding_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${stream_forwarding_test_source_files}) @@ -209,11 +190,7 @@ add_test( # --- Remote stream forward test set(remote_stream_forwarding_test_source_files "remote_stream_forwarding_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${remote_stream_forwarding_test_source_files}) @@ -238,11 +215,7 @@ add_test( # --- UDP forward test set(udp_test_source_files "udp_forwarding_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${udp_test_source_files}) @@ -267,11 +240,7 @@ add_test( # --- Remote UDP forward test set(remote_udp_test_source_files "remote_udp_forwarding_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${remote_udp_test_source_files}) @@ -296,11 +265,7 @@ add_test( # --- Bouncing chain test set(bouncing_test_source_files "bouncing_tests.cpp" - ${VERSIONS_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${CORE_INIT_PACKETS} - ${SERVICES_SOCKS_FILES} + ${SSF_SOURCES} ) source_group ("Test Files" FILES ${bouncing_test_source_files}) From 29a119d3feede39bff2cabf1b3906ca0a657d508 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Wed, 30 Sep 2015 19:22:02 +0200 Subject: [PATCH 04/13] Fix exception throwing when resolving endpoint --- .../link_policies/ssl_policy.h | 15 +++++++++++++-- .../link_policies/tcp_policy.h | 12 +++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h index bf307290..2af7c177 100644 --- a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h +++ b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h @@ -515,8 +515,19 @@ class BaseSSLPolicy { boost::asio::ip::tcp::resolver resolver(io_service_); boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); - boost::asio::ip::tcp::resolver::iterator iterator( - resolver.resolve(query)); + + boost::system::error_code resolve_ec; + auto iterator = resolver.resolve(query, resolve_ec); + + if (resolve_ec) { + BOOST_LOG_TRIVIAL(error) << "link: could not resolve " << addr << ":" + << port; + boost::system::error_code ec(ssf::error::invalid_argument, + ssf::error::get_ssf_category()); + this->to_next_layer_handler(p_socket_type(nullptr), connect_callback, + ec); + return; + } auto p_socket = std::make_shared(io_service_, p_ctx); diff --git a/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h b/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h index 71e24e1f..95f41d0e 100644 --- a/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h +++ b/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h @@ -57,7 +57,17 @@ class TCPPolicy { boost::asio::ip::tcp::resolver resolver(io_service_); boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); - boost::asio::ip::tcp::resolver::iterator iterator(resolver.resolve(query)); + boost::system::error_code resolve_ec; + auto iterator = resolver.resolve(query, resolve_ec); + + if (resolve_ec) { + BOOST_LOG_TRIVIAL(error) << "link: could not resolve " << addr << ":" + << port; + boost::system::error_code ec(ssf::error::invalid_argument, + ssf::error::get_ssf_category()); + to_next_layer_handler(p_socket_type(nullptr), connect_callback, ec); + return; + } auto p_socket = std::make_shared(io_service_); From dd2ca533b7012cb89c4860a9e156fe908abef9db Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Wed, 30 Sep 2015 22:37:37 +0200 Subject: [PATCH 05/13] Improve command line parsing Print help with --help option on client and server Check port range (> 0, < 65536) --- src/core/client/main.cpp | 11 ++- src/core/command_line/command_line.cpp | 129 +++++++++++++------------ src/core/command_line/command_line.h | 3 +- src/core/server/main.cpp | 9 +- 4 files changed, 85 insertions(+), 67 deletions(-) diff --git a/src/core/client/main.cpp b/src/core/client/main.cpp index 210dec8c..a4abda96 100644 --- a/src/core/client/main.cpp +++ b/src/core/client/main.cpp @@ -96,7 +96,7 @@ int main(int argc, char** argv) { if (ec) { BOOST_LOG_TRIVIAL(error) << "client: wrong arguments" << std::endl; - return 0; + return 1; } for (const auto& parameter : parameters) { @@ -119,8 +119,13 @@ int main(int argc, char** argv) { } if (!cmd.IsAddrSet()) { - BOOST_LOG_TRIVIAL(error) << "client: no host address provided -- Exiting" << std::endl; - return 0; + BOOST_LOG_TRIVIAL(error) << "client: no hostname provided -- Exiting"; + return 1; + } + + if (!cmd.IsPortSet()) { + BOOST_LOG_TRIVIAL(error) << "client: no host port provided -- Exiting"; + return 1; } // Load SSF config if any diff --git a/src/core/command_line/command_line.cpp b/src/core/command_line/command_line.cpp index 3c9abb93..256cad53 100644 --- a/src/core/command_line/command_line.cpp +++ b/src/core/command_line/command_line.cpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -13,10 +14,11 @@ #include "common/error/error.h" -ssf::CommandLine::CommandLine(bool is_server): bounce_file_(""), - addr_set_(false), - port_set_(false), - is_server_(is_server) {} +ssf::CommandLine::CommandLine(bool is_server) + : bounce_file_(""), + addr_set_(false), + port_set_(false), + is_server_(is_server) {} std::map> ssf::CommandLine::parse( int argc, char* argv[], boost::system::error_code& ec) { @@ -25,94 +27,101 @@ std::map> ssf::CommandLine::parse( } std::map> ssf::CommandLine::parse( - int ac, char *av[], - const boost::program_options::options_description &services, - boost::system::error_code &ec) { + int ac, char* av[], + const boost::program_options::options_description& services, + boost::system::error_code& ec) { try { - uint16_t opt; + // clang-format off + int opt; boost::program_options::options_description desc("Basic options"); desc.add_options() - ("help,h", "produce help message") - ("version,v", "Version"); + ("help,h", "Produce help message"); boost::program_options::options_description options("Local options"); - options.add_options()( - "port,p", - boost::program_options::value(&opt)->default_value(8011), - "set port"); + boost::program_options::positional_options_description p; if (!is_server_) { - options.add_options()("host,H", boost::program_options::value(), - "host"); + options.add_options() + ("port,p", + boost::program_options::value(&opt)->default_value(8011), + "Set remote SSF server port"); + + options.add_options() + ("host,H", + boost::program_options::value(), + "Set host"); + + p.add("host", 1); + + options.add_options() + ("bounces,b", + boost::program_options::value(), + "Set bounce file"); + } else { + options.add_options() + ("port,p", + boost::program_options::value(&opt)->default_value(8011), + "Set local SSF server port"); } - boost::program_options::positional_options_description p; - p.add("host", -1); - - options.add_options()("bounces,b", - boost::program_options::value(), - "set bounce file"); - - options.add_options()("config,c", - boost::program_options::value(), - "set config file"); + options.add_options() + ("config,c", + boost::program_options::value(), + "Set config file"); + // clang-format on boost::program_options::options_description cmd_line; cmd_line.add(desc).add(options).add(services); boost::program_options::variables_map vm; boost::program_options::store( - boost::program_options::command_line_parser(ac, av) - .options(cmd_line) - .positional(p) - .run(), - vm); + boost::program_options::command_line_parser(ac, av) + .options(cmd_line) + .positional(p) + .run(), + vm); boost::program_options::notify(vm); + if (vm.count("help")) { + std::cout << cmd_line << std::endl; + } + ec.assign(ssf::error::success, ssf::error::get_ssf_category()); - return InternalParsing(vm); - } - catch (const std::exception&) { - ec.assign(ssf::error::invalid_argument, - ssf::error::get_ssf_category()); + return InternalParsing(vm, ec); + } catch (const std::exception&) { + ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); return std::map>(); } } -uint16_t ssf::CommandLine::port() { - return port_; -} +uint16_t ssf::CommandLine::port() { return port_; } -std::string ssf::CommandLine::addr() { - return addr_; -} +std::string ssf::CommandLine::addr() { return addr_; } -std::string ssf::CommandLine::bounce_file() { - return bounce_file_; -} +std::string ssf::CommandLine::bounce_file() { return bounce_file_; } -std::string ssf::CommandLine::config_file() { - return config_file_; -} +std::string ssf::CommandLine::config_file() { return config_file_; } -bool ssf::CommandLine::IsPortSet() { - return port_set_; -} +bool ssf::CommandLine::IsPortSet() { return port_set_; } -bool ssf::CommandLine::IsAddrSet() { - return addr_set_; -} +bool ssf::CommandLine::IsAddrSet() { return addr_set_; } -std::map> ssf::CommandLine::InternalParsing( - const boost::program_options::variables_map& vm) { +std::map> +ssf::CommandLine::InternalParsing( + const boost::program_options::variables_map& vm, + boost::system::error_code& ec) { std::map> result; for (auto& variable : vm) { if (variable.first == "help") { - } else if (variable.first == "version") { } else if (variable.first == "port") { - port_ = vm[variable.first].as(); - port_set_ = true; + int port = vm[variable.first].as(); + if (port > 0 && port < 65536) { + port_ = static_cast(port); + port_set_ = true; + } else { + ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); + } } else if (variable.first == "host") { addr_ = vm[variable.first].as(); addr_set_ = true; @@ -122,7 +131,7 @@ std::map> ssf::CommandLine::InternalParsin config_file_ = vm[variable.first].as(); } else { result[variable.first] = - vm[variable.first].as>(); + vm[variable.first].as>(); } } diff --git a/src/core/command_line/command_line.h b/src/core/command_line/command_line.h index cceda262..53876cb5 100644 --- a/src/core/command_line/command_line.h +++ b/src/core/command_line/command_line.h @@ -40,7 +40,8 @@ class CommandLine { private: std::map> InternalParsing( - const boost::program_options::variables_map& vm); + const boost::program_options::variables_map& vm, + boost::system::error_code& ec); uint16_t port_; std::string addr_; diff --git a/src/core/server/main.cpp b/src/core/server/main.cpp index 561ddf5f..0f3a2851 100644 --- a/src/core/server/main.cpp +++ b/src/core/server/main.cpp @@ -33,7 +33,8 @@ int main(int argc, char **argv){ ssf::BounceProtocolPolicy, ssf::TransportProtocolPolicy> Server; #endif - init(); + + init(); // The object used to parse the command line ssf::CommandLine cmd(true); @@ -45,7 +46,7 @@ int main(int argc, char **argv){ if (ec) { BOOST_LOG_TRIVIAL(error) << "server: wrong arguments" << std::endl; - return 0; + return 1; } // Load SSF config if any @@ -54,7 +55,7 @@ int main(int argc, char **argv){ if (ec_config) { BOOST_LOG_TRIVIAL(error) << "server: invalid config file format" << std::endl; - return 0; + return 1; } // Starting the asynchronous engine @@ -75,6 +76,8 @@ int main(int argc, char **argv){ threads.create_thread(lambda); } + BOOST_LOG_TRIVIAL(info) << "Start SSF server on port " << cmd.port(); + // Initiating and starting the server Server server(io_service, ssf_config, cmd.port()); From 19c4997ddbf3d348c54dbd4bbec3c077cdc9531d Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Wed, 30 Sep 2015 22:59:21 +0200 Subject: [PATCH 06/13] Coding style common error common config --- src/common/config/config.cpp | 8 ++- src/common/config/config.h | 32 +++++----- src/common/error/error.cpp | 105 +++++++++++++++++++------------- src/common/error/error.h | 12 ++-- src/tests/load_config_tests.cpp | 12 ++-- 5 files changed, 92 insertions(+), 77 deletions(-) diff --git a/src/common/config/config.cpp b/src/common/config/config.cpp index 9ec03d8d..8e1c7ff0 100644 --- a/src/common/config/config.cpp +++ b/src/common/config/config.cpp @@ -1,15 +1,16 @@ #include "common/config/config.h" +#include + #include #include #include #include -#include #include "common/error/error.h" ssf::Config ssf::LoadConfig(const std::string& filepath, - boost::system::error_code& ec) { + boost::system::error_code& ec) { using boost::property_tree::ptree; ptree pt; ssf::Config config; @@ -57,7 +58,8 @@ ssf::Config ssf::LoadConfig(const std::string& filepath, return config; } catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "config: error reading SSF config file : " << e.what(); + BOOST_LOG_TRIVIAL(error) + << "config: error reading SSF config file : " << e.what(); ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); return ssf::Config(); diff --git a/src/common/config/config.h b/src/common/config/config.h index 71661b40..691acdc8 100644 --- a/src/common/config/config.h +++ b/src/common/config/config.h @@ -1,24 +1,22 @@ #ifndef SSF_COMMON_CONFIG_CONFIG_H_ #define SSF_COMMON_CONFIG_CONFIG_H_ -#include #include +#include + namespace ssf { -struct Config -{ - Config() : tls() { - } - - struct Tls - { - Tls() : ca_cert_path("./certs/trusted/ca.crt"), - cert_path("./certs/certificate.crt"), - key_path("./certs/private.key"), - key_password(""), - dh_path("./certs/dh4096.pem"), - cipher_alg("DHE-RSA-AES256-GCM-SHA384") { - } +struct Config { + Config() : tls() {} + + struct Tls { + Tls() + : ca_cert_path("./certs/trusted/ca.crt"), + cert_path("./certs/certificate.crt"), + key_path("./certs/private.key"), + key_password(""), + dh_path("./certs/dh4096.pem"), + cipher_alg("DHE-RSA-AES256-GCM-SHA384") {} std::string ca_cert_path; std::string cert_path; @@ -30,8 +28,8 @@ struct Config Tls tls; }; -Config LoadConfig(const std::string& filepath, - boost::system::error_code& ec); +Config LoadConfig(const std::string& filepath, boost::system::error_code& ec); } // ssf + #endif // SSF_COMMON_CONFIG_CONFIG_H_ diff --git a/src/common/error/error.cpp b/src/common/error/error.cpp index 504c1449..84c2307f 100644 --- a/src/common/error/error.cpp +++ b/src/common/error/error.cpp @@ -1,50 +1,67 @@ #include "error.h" -#include -#include -#include - -const char* ssf::error::detail::ssf_category::name() const BOOST_SYSTEM_NOEXCEPT -{ +const char* ssf::error::detail::ssf_category::name() const + BOOST_SYSTEM_NOEXCEPT { return "ssf"; } std::string ssf::error::detail::ssf_category::message(int value) const { - if (value == error::success) - return "success"; - if (value == error::interrupted) - return "connection interrupted"; - if (value == error::bad_file_descriptor) - return "bad file descriptor"; - if (value == error::device_or_resource_busy) - return "device or resource busy"; - if (value == error::invalid_argument) - return "invalid argument"; - if (value == error::not_a_socket) - return "no socket could be created"; - if (value == error::broken_pipe) - return "broken pipe"; - if (value == error::filename_too_long) - return "filename too long"; - if (value == error::message_too_long) - return "message too long"; - if (value == error::connection_aborted) - return "connection aborted"; - if (value == error::connection_refused) - return "connection refused"; - if (value == error::connection_reset) - return "connection reset"; - if (value == error::not_connected) - return "not connected"; - if (value == error::protocol_error) - return "protocol error"; - if (value == error::wrong_protocol_type) - return "wrong protocol type"; - if (value == error::operation_canceled) - return "operation canceled"; - if (value == error::service_not_found) - return "service not found"; - if (value == error::out_of_range) - return "out of range"; - return "ssf error"; -} + switch (value) { + case error::success: + return "success"; + break; + case error::interrupted: + return "connection interrupted"; + break; + case error::bad_file_descriptor: + return "bad file descriptor"; + break; + case error::device_or_resource_busy: + return "device or resource busy"; + break; + case error::invalid_argument: + return "invalid argument"; + break; + case error::not_a_socket: + return "no socket could be created"; + break; + case error::broken_pipe: + return "broken pipe"; + break; + case error::filename_too_long: + return "filename too long"; + break; + case error::message_too_long: + return "message too long"; + break; + case error::connection_aborted: + return "connection aborted"; + break; + case error::connection_refused: + return "connection refused"; + break; + case error::connection_reset: + return "connection reset"; + break; + case error::not_connected: + return "not connected"; + break; + case error::protocol_error: + return "protocol error"; + break; + case error::wrong_protocol_type: + return "wrong protocol type"; + break; + case error::operation_canceled: + return "operation canceled"; + break; + case error::service_not_found: + return "service not found"; + break; + case error::out_of_range: + return "out of range"; + break; + default: + return "ssf error"; + } +} \ No newline at end of file diff --git a/src/common/error/error.h b/src/common/error/error.h index 5e02708a..63e1583c 100644 --- a/src/common/error/error.h +++ b/src/common/error/error.h @@ -1,10 +1,11 @@ #ifndef SSF_COMMON_ERROR_ERROR_H_ #define SSF_COMMON_ERROR_ERROR_H_ -#include -#include #include +#include +#include + namespace ssf { namespace error { @@ -30,9 +31,7 @@ enum errors { }; namespace detail { -class ssf_category : public boost::system::error_category -{ - +class ssf_category : public boost::system::error_category { public: const char* name() const BOOST_SYSTEM_NOEXCEPT; @@ -40,8 +39,7 @@ class ssf_category : public boost::system::error_category }; } // detail -inline const boost::system::error_category& get_ssf_category() -{ +inline const boost::system::error_category& get_ssf_category() { static detail::ssf_category instance; return instance; } diff --git a/src/tests/load_config_tests.cpp b/src/tests/load_config_tests.cpp index cb1d9351..b5bf5ed2 100644 --- a/src/tests/load_config_tests.cpp +++ b/src/tests/load_config_tests.cpp @@ -27,14 +27,14 @@ class LoadConfigTest : public ::testing::Test { TEST_F(LoadConfigTest, loadNoFile) { boost::system::error_code ec; ssf::LoadConfig("", ec); - ASSERT_TRUE(ec.value() == 0) << "Success if no file given"; + ASSERT_EQ(ec.value(), 0) << "Success if no file given"; } //----------------------------------------------------------------------------- TEST_F(LoadConfigTest, loadNonExistantFile) { boost::system::error_code ec; ssf::LoadConfig(filename_, ec); - ASSERT_TRUE(ec.value() > 0) << "No success if file not existant"; + ASSERT_NE(ec.value(), 0) << "No success if file not existant"; } //----------------------------------------------------------------------------- @@ -44,7 +44,7 @@ TEST_F(LoadConfigTest, loadEmptyFile) { file.open(filename_); file.close(); ssf::LoadConfig(filename_, ec); - ASSERT_TRUE(ec.value() > 0) << "No success if file empty"; + ASSERT_NE(ec.value(), 0) << "No success if file empty"; } //----------------------------------------------------------------------------- @@ -56,7 +56,7 @@ TEST_F(LoadConfigTest, loadWrongFormatFile) { file.close(); ssf::LoadConfig(filename_, ec); std::remove(filename_.c_str()); - ASSERT_TRUE(ec.value() > 0) << "No success if wrong file format"; + ASSERT_NE(ec.value(), 0) << "No success if wrong file format"; } //----------------------------------------------------------------------------- @@ -72,7 +72,7 @@ TEST_F(LoadConfigTest, loadPartialFile) { file.close(); ssf::Config config; config = ssf::LoadConfig(filename_, ec); - ASSERT_TRUE(ec.value() == 0) << "Success if partial file format"; + ASSERT_EQ(ec.value(), 0) << "Success if partial file format"; ASSERT_EQ(config.tls.ca_cert_path, "test_ca_path"); ASSERT_EQ(config.tls.cert_path, "./certs/certificate.crt"); ASSERT_EQ(config.tls.key_path, "test_key_path"); @@ -97,7 +97,7 @@ TEST_F(LoadConfigTest, loadCompleteFile) { file.close(); ssf::Config config; config = ssf::LoadConfig(filename_, ec); - ASSERT_TRUE(ec.value() == 0) << "Success if complete file format"; + ASSERT_EQ(ec.value(), 0) << "Success if complete file format"; ASSERT_EQ(config.tls.ca_cert_path, "test_ca_path"); ASSERT_EQ(config.tls.cert_path, "test_cert_path"); ASSERT_EQ(config.tls.key_path, "test_key_path"); From 5fcdf7dc5a2dabe168d98c34505977d29fe0f1f3 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Thu, 1 Oct 2015 16:28:01 +0200 Subject: [PATCH 07/13] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53a54640..bf9886cd 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Copy [the diff from OpenSSL Github](https://github.com/openssl/openssl/commit/77 ```bash mkdir PROJECT_PATH/build cd PROJECT_PATH/build - cmake -G "GENERATOR" -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ + cmake -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ ``` * Build project @@ -94,7 +94,7 @@ cp gtest-1.X.Y.zip PROJECT_PATH/third_party/gtest ```bash mkdir PROJECT_PATH/build cd PROJECT_PATH/build -cmake -G "GENERATOR" -DCMAKE_BUILD_TYPE=Release|Debug -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ +cmake -DCMAKE_BUILD_TYPE=Release|Debug -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ ``` * Build project @@ -134,7 +134,7 @@ cp gtest-1.X.Y.zip PROJECT_PATH/third_party/gtest ```bash mkdir PROJECT_PATH/build cd PROJECT_PATH/build -cmake -G "GENERATOR" -DCMAKE_BUILD_TYPE=Release|Debug -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ +cmake -DCMAKE_BUILD_TYPE=Release|Debug -DSSF_SECURITY:STRING="STANDARD|FORCE_TCP_ONLY" ../ ``` * Build project From b20db5c5796f93f62c64301804e7a7c18f154608 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Sat, 10 Oct 2015 18:26:05 +0200 Subject: [PATCH 08/13] Fix timer lifetime in datagram fiber demux --- src/common/boost/fiber/basic_fiber_demux_service.ipp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/boost/fiber/basic_fiber_demux_service.ipp b/src/common/boost/fiber/basic_fiber_demux_service.ipp index bc6a9d0c..5da1a9d3 100644 --- a/src/common/boost/fiber/basic_fiber_demux_service.ipp +++ b/src/common/boost/fiber/basic_fiber_demux_service.ipp @@ -403,7 +403,7 @@ void basic_fiber_demux_service::async_send_push(implementation_type impl, auto p_timer = std::make_shared(io_service_); p_timer->expires_from_now(boost::posix_time::milliseconds(10)); - auto lambda = [handler](const boost::system::error_code&) mutable { + auto lambda = [handler, p_timer](const boost::system::error_code&) mutable { handler(boost::system::error_code(), 0); }; @@ -444,7 +444,7 @@ void basic_fiber_demux_service::async_send_dgr(implementation_type impl, auto p_timer = std::make_shared(io_service_); p_timer->expires_from_now(boost::posix_time::milliseconds(10)); - auto lambda = [handler](const boost::system::error_code&) mutable { + auto lambda = [handler, p_timer](const boost::system::error_code&) mutable { handler(boost::system::error_code(), 0); }; @@ -554,8 +554,8 @@ boost::asio::fiber::detail::fiber_id::local_port_type basic_fiber_demux_service< rand_port = 0; boost::recursive_mutex::scoped_lock lock1(impl->used_ports_mutex); - boost::random::uniform_int_distribution dist(new_port, - std::numeric_limits::max()); + boost::random::uniform_int_distribution dist( + new_port, std::numeric_limits::max()); for (uint32_t i = 0; i < 100; ++i) { rand_port = dist(gen_); if (impl->used_ports.count(rand_port) == 0) { From 6c4273ad6bad43ba1ede953c8ff9d06d27f9594c Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Sat, 10 Oct 2015 19:28:40 +0200 Subject: [PATCH 09/13] Create a new user service : copy_file!service Copy file from client to server (data sources : stdin or file or file globbing) Copy file from server to file (data sources : file or file globbing) --- .../copy_file/fiber_to_file/fiber_to_file.h | 127 ++++++ .../fiber_to_file/fiber_to_ofstream_session.h | 177 ++++++++ .../copy_file/file_enquirer/file_enquirer.h | 141 +++++++ .../copy_file/file_to_fiber/file_to_fiber.h | 383 ++++++++++++++++++ .../file_to_fiber/istream_to_fiber_session.h | 180 ++++++++ src/services/copy_file/filename_buffer.cpp | 38 ++ src/services/copy_file/filename_buffer.h | 38 ++ .../copy_file/filesystem/filesystem.cpp | 19 + .../copy_file/filesystem/filesystem.h | 28 ++ .../filesystem/linux/unix_filesystem.cpp | 26 ++ .../filesystem/windows/win_filesystem.cpp | 33 ++ src/services/copy_file/packet/packet.cpp | 99 +++++ src/services/copy_file/packet/packet.h | 67 +++ .../user_services/copy_file_service.h | 183 +++++++++ 14 files changed, 1539 insertions(+) create mode 100644 src/services/copy_file/fiber_to_file/fiber_to_file.h create mode 100644 src/services/copy_file/fiber_to_file/fiber_to_ofstream_session.h create mode 100644 src/services/copy_file/file_enquirer/file_enquirer.h create mode 100644 src/services/copy_file/file_to_fiber/file_to_fiber.h create mode 100644 src/services/copy_file/file_to_fiber/istream_to_fiber_session.h create mode 100644 src/services/copy_file/filename_buffer.cpp create mode 100644 src/services/copy_file/filename_buffer.h create mode 100644 src/services/copy_file/filesystem/filesystem.cpp create mode 100644 src/services/copy_file/filesystem/filesystem.h create mode 100644 src/services/copy_file/filesystem/linux/unix_filesystem.cpp create mode 100644 src/services/copy_file/filesystem/windows/win_filesystem.cpp create mode 100644 src/services/copy_file/packet/packet.cpp create mode 100644 src/services/copy_file/packet/packet.h create mode 100644 src/services/user_services/copy_file_service.h diff --git a/src/services/copy_file/fiber_to_file/fiber_to_file.h b/src/services/copy_file/fiber_to_file/fiber_to_file.h new file mode 100644 index 00000000..5c9af465 --- /dev/null +++ b/src/services/copy_file/fiber_to_file/fiber_to_file.h @@ -0,0 +1,127 @@ +#ifndef SSF_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_FILE_H_ +#define SSF_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_FILE_H_ + +#include + +#include + +#include + +#include "core/factories/service_factory.h" +#include "services/admin/requests/create_service_request.h" +#include "services/copy_file/fiber_to_file/fiber_to_ofstream_session.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace fiber_to_file { + +template +class FiberToFile : public BaseService { + private: + using FiberToFilePtr = std::shared_ptr; + using SessionManager = ItemManager; + using Parameters = typename ssf::BaseService::Parameters; + using fiber_port = typename Demux::local_port_type; + using demux = typename ssf::BaseService::demux; + using fiber = typename ssf::BaseService::fiber; + using endpoint = typename ssf::BaseService::endpoint; + using fiber_acceptor = typename ssf::BaseService::fiber_acceptor; + + public: + enum { factory_id = 7, kServicePort = 40 }; + + public: + // Factory method to create the service + static FiberToFilePtr Create(boost::asio::io_service& io_service, + demux& fiber_demux, Parameters parameters) { + return FiberToFilePtr(new FiberToFile(io_service, fiber_demux)); + } + + virtual ~FiberToFile() {} + + // Start service and listen new fiber on demux port kServicePort + virtual void start(boost::system::error_code& ec) { + endpoint ep(this->get_demux(), kServicePort); + BOOST_LOG_TRIVIAL(info) + << "service fiber to file: start accept on fiber port " << kServicePort; + fiber_acceptor_.bind(ep, ec); + fiber_acceptor_.listen(boost::asio::socket_base::max_connections, ec); + if (ec) { + return; + } + StartAccept(); + } + + // Stop service + virtual void stop(boost::system::error_code& ec) { + BOOST_LOG_TRIVIAL(info) << "service fiber to file: stopping"; + manager_.stop_all(); + fiber_acceptor_.close(ec); + fiber_.close(ec); + } + + virtual uint32_t service_type_id() { return factory_id; } + + static void RegisterToServiceFactory( + std::shared_ptr> p_factory) { + p_factory->RegisterServiceCreator(factory_id, &FiberToFile::Create); + } + + static ssf::services::admin::CreateServiceRequest GetCreateRequest() { + ssf::services::admin::CreateServiceRequest create(factory_id); + + return create; + } + + private: + FiberToFile(boost::asio::io_service& io_service, demux& fiber_demux) + : BaseService(io_service, fiber_demux), + fiber_acceptor_(io_service), + fiber_(io_service) {} + + void StartAccept() { + if (fiber_acceptor_.is_open()) { + fiber_acceptor_.async_accept( + fiber_, Then(&FiberToFile::StartDataForwarderSessionHandler, + this->SelfFromThis())); + } + } + + // Create a session to transmit files for the new connection + void StartDataForwarderSessionHandler(const boost::system::error_code& ec) { + if (ec) { + BOOST_LOG_TRIVIAL(info) << "service fiber to file: fail accept fiber"; + return; + } + + auto p_session = FiberToOstreamSession::Create( + &manager_, std::move(fiber_)); + boost::system::error_code start_ec; + manager_.start(p_session, start_ec); + StartAccept(); + } + + template + auto Then(Handler handler, + This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { + return boost::bind(handler, me->SelfFromThis(), _1); + } + + std::shared_ptr SelfFromThis() { + return std::static_pointer_cast(this->shared_from_this()); + } + + private: + bool accept_; + fiber_acceptor fiber_acceptor_; + fiber fiber_; + SessionManager manager_; +}; + +} // fiber_to_file +} // copy_file +} // services +} // ssf + +#endif // SSF_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_FILE_H_ diff --git a/src/services/copy_file/fiber_to_file/fiber_to_ofstream_session.h b/src/services/copy_file/fiber_to_file/fiber_to_ofstream_session.h new file mode 100644 index 00000000..6cb2baf3 --- /dev/null +++ b/src/services/copy_file/fiber_to_file/fiber_to_ofstream_session.h @@ -0,0 +1,177 @@ +#ifndef SRC_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_OSTREAM_SESSION_H_ +#define SRC_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_OSTREAM_SESSION_H_ + +#include + +#include +#include +#include + +#include + +#include "common/network/base_session.h" // NOLINT + +#include "common/network/manager.h" +#include "common/network/base_session.h" + +#include "services/copy_file/filename_buffer.h" +#include "services/copy_file/packet/packet.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace fiber_to_file { + +template +class FiberToOstreamSession : public ssf::BaseSession { + public: + using StopHandler = std::function; + using FiberToOstreamSessionPtr = std::shared_ptr; + + // Type for the class managing the different forwarding links + using SessionManager = ItemManager; + // Buffer for the transiting data + using Packet = ssf::services::copy_file::packet::Packet; + + public: + template + static FiberToOstreamSessionPtr Create(Args&&... args) { + return std::shared_ptr( + new FiberToOstreamSession(std::forward(args)...)); + } + + // Start read from stream socket and write to output stream + virtual void start(boost::system::error_code&) { + ForwardData(boost::system::error_code(), 0); + } + + // Stop session + virtual void stop(boost::system::error_code& ec) { + BOOST_LOG_TRIVIAL(debug) << "session fiber to file : stopped"; + input_socket_stream_.close(ec); + // connection interrupted without prior notification (broken pipe) + // delete output file + if (output_stream_.is_open()) { + output_stream_.close(); + std::remove(request_.GetFilename().c_str()); + } + } + + private: + FiberToOstreamSession(SessionManager* p_manager, + InputSocketStream input_socket_stream) + : input_socket_stream_(std::move(input_socket_stream)), + p_manager_(p_manager), + output_stream_ok_(true) {} + +#include // NOLINT + // Read output filename + // Transfer data from fiber to file + void ForwardData(const boost::system::error_code& ec, std::size_t length) { + if (ec) { + boost::system::error_code stop_ec; + // connection interrupted without prior notification (broken pipe) + if (output_stream_.is_open()) { + output_stream_.close(); + std::remove(request_.GetFilename().c_str()); + } + p_manager_->stop(this->SelfFromThis(), stop_ec); + + return; + } + + reenter(coroutine_) { + // read filename_size from request + yield boost::asio::async_read( + input_socket_stream_, request_.GetFilenameSizeMutBuffers(), + boost::bind(&FiberToOstreamSession::ForwardData, this->SelfFromThis(), + _1, _2)); + + // read filename from request + yield boost::asio::async_read( + input_socket_stream_, request_.GetFilenameMutBuffers(), + boost::bind(&FiberToOstreamSession::ForwardData, this->SelfFromThis(), + _1, _2)); + + BOOST_LOG_TRIVIAL(info) + << "session fiber to file : start receiving data and writing in file " + << request_.GetFilename(); + + // open output_stream + output_stream_.open(request_.GetFilename(), std::ofstream::binary); + if (!output_stream_.is_open()) { + BOOST_LOG_TRIVIAL(error) << "session fiber to file : output file " + << request_.GetFilename() + << " could not be opened"; + boost::system::error_code stop_ec; + p_manager_->stop(this->SelfFromThis(), stop_ec); + + return; + } + + while (input_socket_stream_.is_open()) { + // Read type packet + yield boost::asio::async_read( + input_socket_stream_, packet_.GetTypeMutBuf(), + boost::bind(&FiberToOstreamSession::ForwardData, + this->SelfFromThis(), _1, _2)); + + if (packet_.IsDataPacket()) { + // Read size packet + yield boost::asio::async_read( + input_socket_stream_, packet_.GetSizeMutBuf(), + boost::bind(&FiberToOstreamSession::ForwardData, + this->SelfFromThis(), _1, _2)); + // Read binary data + yield boost::asio::async_read( + input_socket_stream_, packet_.GetPayloadMutBuf(), + boost::bind(&FiberToOstreamSession::ForwardData, + this->SelfFromThis(), _1, _2)); + // Write in input file + output_stream_.write(packet_.buffer().data(), packet_.size()); + } else { + yield boost::asio::async_read( + input_socket_stream_, packet_.GetSignalMutBuf(), + boost::bind(&FiberToOstreamSession::ForwardData, + this->SelfFromThis(), _1, _2)); + + // Close file handler + output_stream_.close(); + if (packet_.signal() == Packet::kInterrupted) { + // delete file -> transmission interrupted + std::remove(request_.GetFilename().c_str()); + } + break; + } + } + + // stop session + boost::system::error_code stop_ec; + p_manager_->stop(this->SelfFromThis(), stop_ec); + } + } +#include // NOLINT + + FiberToOstreamSessionPtr SelfFromThis() { + return std::static_pointer_cast( + this->shared_from_this()); + } + + private: + InputSocketStream input_socket_stream_; + SessionManager* p_manager_; + + // Coroutine variables + boost::asio::coroutine coroutine_; + bool output_stream_ok_; + std::ofstream output_stream_; + Packet packet_; + FilenameBuffer request_; +}; + +} // fiber_to_file +} // copy_file +} // services +} // ssf + +#endif // SRC_SERVICES_COPY_FILE_FIBER_TO_FILE_FIBER_TO_OSTREAM_SESSION_H_ diff --git a/src/services/copy_file/file_enquirer/file_enquirer.h b/src/services/copy_file/file_enquirer/file_enquirer.h new file mode 100644 index 00000000..812230a4 --- /dev/null +++ b/src/services/copy_file/file_enquirer/file_enquirer.h @@ -0,0 +1,141 @@ +#ifndef SSF_SERVICES_COPY_FILE_FILE_ENQUIRER_FILE_ENQUIRER_H_ +#define SSF_SERVICES_COPY_FILE_FILE_ENQUIRER_FILE_ENQUIRER_H_ + +#include + +#include "core/factories/service_factory.h" +#include "services/admin/requests/create_service_request.h" +#include "services/copy_file/file_to_fiber/file_to_fiber.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace file_enquirer { + +template +class FileEnquirer : public BaseService { + private: + using Endpoint = typename ssf::BaseService::endpoint; + using FileEnquirerPtr = std::shared_ptr; + using FiberPort = typename Demux::local_port_type; + using Fiber = typename ssf::BaseService::fiber; + using FiberPtr = std::shared_ptr; + using FilenameBuffer = ssf::services::copy_file::FilenameBuffer; + using Parameters = typename ssf::BaseService::Parameters; + + public: + enum { factory_id = 9 }; + + static FileEnquirerPtr Create(boost::asio::io_service& io_service, + Demux& fiber_demux, Parameters parameters) { + if (parameters.count("input_pattern") != 0 && + parameters.count("output_pattern") != 0) { + return FileEnquirerPtr(new FileEnquirer(io_service, fiber_demux, + parameters["input_pattern"], + parameters["output_pattern"])); + } + + return nullptr; + } + + virtual ~FileEnquirer() {} + + virtual void start(boost::system::error_code& ec) { + SendRequest(boost::system::error_code(), 0); + } + + virtual void stop(boost::system::error_code& ec) { fiber_.close(ec); } + + virtual uint32_t service_type_id() { return factory_id; } + + static void RegisterToServiceFactory( + std::shared_ptr> p_factory) { + p_factory->RegisterServiceCreator(factory_id, &FileEnquirer::Create); + } + + static ssf::services::admin::CreateServiceRequest GetCreateRequest( + const std::string& input_pattern, const std::string& output_pattern) { + ssf::services::admin::CreateServiceRequest create(factory_id); + create.add_parameter("input_pattern", input_pattern); + create.add_parameter("output_pattern", output_pattern); + + return create; + } + + private: + FileEnquirer(boost::asio::io_service& io_service, Demux& fiber_demux, + const std::string& input_pattern, + const std::string& output_pattern) + : BaseService(io_service, fiber_demux), + fiber_(io_service), + input_request_(input_pattern), + output_request_(output_pattern), + remote_endpoint_(fiber_demux, + ssf::services::copy_file::file_to_fiber::FileToFiber< + Demux>::kServicePort) {} + +#include + // Connect to remote file to fiber service and send input and output pattern + void SendRequest(const boost::system::error_code& ec, std::size_t length) { + if (ec) { + boost::system::error_code close_ec; + fiber_.close(close_ec); + return; + } + + reenter(coroutine_) { + BOOST_LOG_TRIVIAL(debug) + << "service file enquirer: connect to remote fiber acceptor port " + << remote_endpoint_.port(); + + yield fiber_.async_connect( + remote_endpoint_, + boost::bind(&FileEnquirer::SendRequest, this->SelfFromThis(), _1, 0)); + + // write input pattern size from request + yield boost::asio::async_write( + fiber_, input_request_.GetFilenameSizeConstBuffers(), + boost::bind(&FileEnquirer::SendRequest, this->SelfFromThis(), _1, + _2)); + + // write input pattern from request + yield boost::asio::async_write(fiber_, + input_request_.GetFilenameConstBuffers(), + boost::bind(&FileEnquirer::SendRequest, + this->SelfFromThis(), _1, _2)); + + // write output pattern size from request + yield boost::asio::async_write( + fiber_, output_request_.GetFilenameSizeConstBuffers(), + boost::bind(&FileEnquirer::SendRequest, this->SelfFromThis(), _1, + _2)); + + // write output pattern from request + yield boost::asio::async_write(fiber_, + output_request_.GetFilenameConstBuffers(), + boost::bind(&FileEnquirer::SendRequest, + this->SelfFromThis(), _1, _2)); + } + } +#include + + FileEnquirerPtr SelfFromThis() { + return std::static_pointer_cast(this->shared_from_this()); + } + + private: + Fiber fiber_; + + // coroutine variables + boost::asio::coroutine coroutine_; + FilenameBuffer input_request_; + FilenameBuffer output_request_; + Endpoint remote_endpoint_; +}; + +} // file_enquirer +} // copy_file +} // services +} // ssf + +#endif // SSF_SERVICES_COPY_FILE_FILE_ENQUIRER_FILE_ENQUIRER_H_ diff --git a/src/services/copy_file/file_to_fiber/file_to_fiber.h b/src/services/copy_file/file_to_fiber/file_to_fiber.h new file mode 100644 index 00000000..f90803a3 --- /dev/null +++ b/src/services/copy_file/file_to_fiber/file_to_fiber.h @@ -0,0 +1,383 @@ +#ifndef SSF_SERVICES_COPY_FILE_FILE_TO_FIBER_FILE_TO_FIBER_H_ +#define SSF_SERVICES_COPY_FILE_FILE_TO_FIBER_FILE_TO_FIBER_H_ + +#ifdef WIN32 +#include +#include +#endif + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "core/factories/service_factory.h" +#include "services/admin/requests/create_service_request.h" +#include "services/copy_file/file_to_fiber/istream_to_fiber_session.h" + +#include "services/copy_file/filename_buffer.h" +#include "services/copy_file/filesystem/filesystem.h" +#include "services/copy_file/fiber_to_file/fiber_to_file.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace file_to_fiber { + +template +class FileToFiber : public BaseService { + private: + using FileToFiberPtr = std::shared_ptr; + using SessionManager = ItemManager; + using Parameters = typename ssf::BaseService::Parameters; + using fiber_port = typename Demux::local_port_type; + using demux = typename ssf::BaseService::demux; + using fiber = typename ssf::BaseService::fiber; + using FiberPtr = std::shared_ptr; + using endpoint = typename ssf::BaseService::endpoint; + using fiber_acceptor = typename ssf::BaseService::fiber_acceptor; + using FilesList = std::list; + using FilesListPtr = std::shared_ptr; + using InputOutputFilesMap = std::map; + using StopSessionHandler = std::function; + using Filesystem = ssf::services::copy_file::filesystem::Filesystem; + using FilenameBuffer = ssf::services::copy_file::FilenameBuffer; + + public: + enum { factory_id = 8, kServicePort = 41 }; + + public: + // Factory method to create the service + static FileToFiberPtr Create(boost::asio::io_service& io_service, + demux& fiber_demux, Parameters parameters) { + if (parameters.count("accept") != 0) { + return FileToFiberPtr(new FileToFiber(io_service, fiber_demux)); + } + + if (parameters.count("from_stdin") != 0 && + parameters.count("input_pattern") != 0 && + parameters.count("output_pattern") != 0) { + return FileToFiberPtr(new FileToFiber( + io_service, fiber_demux, parameters["from_stdin"] == "true", + parameters["input_pattern"], parameters["output_pattern"])); + } + + return nullptr; + } + + virtual ~FileToFiber() {} + + // Start service + virtual void start(boost::system::error_code& ec) { +// set stdin in binary mode +#ifdef WIN32 + if (_setmode(_fileno(stdin), _O_BINARY) == -1) { + return; + } +#endif + + if (accept_) { + endpoint ep(this->get_demux(), kServicePort); + BOOST_LOG_TRIVIAL(info) + << "service fiber to file: start accept on fiber port " + << kServicePort; + fiber_acceptor_.bind(ep, ec); + fiber_acceptor_.listen(boost::asio::socket_base::max_connections, ec); + if (ec) { + return; + } + StartAccept(); + } else { + StartTransfer(); + } + } + + // Stop service + virtual void stop(boost::system::error_code& ec) { + BOOST_LOG_TRIVIAL(info) << "service file to fiber: stopping"; + manager_.stop_all(); + boost::system::error_code close_ec; + fiber_acceptor_.close(close_ec); + +// reset stdin in text mode +#ifdef WIN32 + if (_setmode(_fileno(stdin), _O_TEXT) == -1) { + return; + } +#endif + } + + virtual uint32_t service_type_id() { return factory_id; } + + static void RegisterToServiceFactory( + std::shared_ptr> p_factory) { + p_factory->RegisterServiceCreator(factory_id, &FileToFiber::Create); + } + + static ssf::services::admin::CreateServiceRequest GetCreateRequest( + bool server, bool from_stdin, const std::string& input_pattern, + const std::string& output_pattern) { + ssf::services::admin::CreateServiceRequest create(factory_id); + if (server) { + create.add_parameter("accept", "true"); + } else { + create.add_parameter("from_stdin", from_stdin ? "true" : "false"); + create.add_parameter("input_pattern", input_pattern); + create.add_parameter("output_pattern", output_pattern); + } + + return create; + } + + private: + FileToFiber(boost::asio::io_service& io_service, demux& fiber_demux) + : BaseService(io_service, fiber_demux), + accept_(true), + from_stdin_(false), + input_pattern_(""), + output_pattern_(""), + fiber_acceptor_(io_service) {} + + FileToFiber(boost::asio::io_service& io_service, demux& fiber_demux, + bool from_stdin, const std::string& input_pattern, + const std::string& output_pattern) + : BaseService(io_service, fiber_demux), + accept_(false), + from_stdin_(from_stdin), + input_pattern_(input_pattern), + output_pattern_(output_pattern), + fiber_acceptor_(io_service) {} + + // Start accepting new fiber (remote files to local) + // Input and output patterns will be given through the fiber + void StartAccept() { + if (fiber_acceptor_.is_open()) { + auto p_fiber = + std::make_shared(this->get_demux().get_io_service()); + fiber_acceptor_.async_accept( + *p_fiber, boost::bind(&FileToFiber::AcceptFiberHandler, + this->SelfFromThis(), _1, p_fiber)); + } + } + + void AcceptFiberHandler(const boost::system::error_code& ec, + FiberPtr p_fiber) { + if (!ec) { + StartAccept(); + ConfigureSessions(p_fiber, boost::system::error_code(), 0); + } + } + +#include + // Read input and output pattern from fiber + // Connect sessions to remote fiber to file service + void ConfigureSessions(FiberPtr p_fiber, const boost::system::error_code& ec, + std::size_t length) { + if (ec) { + boost::system::error_code close_ec; + p_fiber->close(close_ec); + return; + } + reenter(coroutine_) { + // read input pattern size from request + yield boost::asio::async_read( + *p_fiber, input_request_.GetFilenameSizeMutBuffers(), + boost::bind(&FileToFiber::ConfigureSessions, this->SelfFromThis(), + p_fiber, _1, _2)); + + // read input pattern from request + yield boost::asio::async_read( + *p_fiber, input_request_.GetFilenameMutBuffers(), + boost::bind(&FileToFiber::ConfigureSessions, this->SelfFromThis(), + p_fiber, _1, _2)); + + // read output pattern size from request + yield boost::asio::async_read( + *p_fiber, output_request_.GetFilenameSizeMutBuffers(), + boost::bind(&FileToFiber::ConfigureSessions, this->SelfFromThis(), + p_fiber, _1, _2)); + + // read output pattern from request + yield boost::asio::async_read( + *p_fiber, output_request_.GetFilenameMutBuffers(), + boost::bind(&FileToFiber::ConfigureSessions, this->SelfFromThis(), + p_fiber, _1, _2)); + + ProcessInputOutputPattern(input_request_.GetFilename(), + output_request_.GetFilename()); + } + } +#include + + // Start transfer data + void StartTransfer() { + if (!from_stdin_) { + ProcessInputOutputPattern(input_pattern_, output_pattern_); + } else { + auto p_output_files_list = std::make_shared(); + p_output_files_list->push_back(output_pattern_); + auto finish_callback = + boost::bind(&FileToFiber::FinishSentSession, this->SelfFromThis(), _1, + p_output_files_list); + AsyncConnectFileFiberSession(true, "", output_pattern_, finish_callback); + } + } + + // Get the file list and generate one transfer session per input file + void ProcessInputOutputPattern(const std::string& input_pattern, + const std::string& output_pattern) { + FilesList input_files_list; + auto p_output_files_list = std::make_shared(); + + InputOutputFilesMap input_output_files; + ParseInputOutputPatterns(input_pattern, output_pattern, + &input_output_files); + + for (auto& input_output_file_pair : input_output_files) { + p_output_files_list->push_back(input_output_file_pair.second); + } + + // If no file, callback finish handler + if (input_output_files.empty()) { + this->get_io_service().post(boost::bind(&FileToFiber::FinishSentSession, + this->SelfFromThis(), "", + p_output_files_list)); + return; + }; + + auto finish_callback = + boost::bind(&FileToFiber::FinishSentSession, this->SelfFromThis(), _1, + p_output_files_list); + + // Start one session per input file + for (auto& input_output_file_pair : input_output_files) { + AsyncConnectFileFiberSession(false, input_output_file_pair.first, + input_output_file_pair.second, + finish_callback); + } + } + + // Connect a new fiber to the fiber to file service and start an input stream + // to fiber session + void AsyncConnectFileFiberSession(bool from_stdin, + const std::string& input_file, + const std::string& output_file, + StopSessionHandler stop_handler) { + FiberPtr p_fiber = + std::make_shared(this->get_demux().get_io_service()); + + BOOST_LOG_TRIVIAL(debug) + << "service file to fiber: connect to remote fiber acceptor port " + << ssf::services::copy_file::fiber_to_file::FiberToFile< + Demux>::kServicePort; + + endpoint ep(this->get_demux(), + ssf::services::copy_file::fiber_to_file::FiberToFile< + Demux>::kServicePort); + + p_fiber->async_connect( + ep, boost::bind(&FileToFiber::StartDataForwarderSessionHandler, + this->SelfFromThis(), _1, p_fiber, from_stdin, + input_file, output_file, stop_handler)); + } + + // Start the data forward session + void StartDataForwarderSessionHandler(const boost::system::error_code& ec, + FiberPtr p_fiber, bool from_stdin, + const std::string& input_file, + const std::string& output_file, + StopSessionHandler stop_handler) { + if (ec) { + boost::system::error_code close_ec; + p_fiber->close(close_ec); + return; + } + + if (from_stdin) { + BOOST_LOG_TRIVIAL(info) + << "service file to fiber: start forward data from stdin to " + << output_file; + } else { + BOOST_LOG_TRIVIAL(info) + << "service file to fiber: start forward data from " << input_file + << " to " << output_file; + } + + if (!from_stdin) { + auto p_session = IstreamToFiberSession::Create( + &manager_, input_file, std::move(*p_fiber), + output_file, stop_handler); + boost::system::error_code start_ec; + manager_.start(p_session, start_ec); + } else { + auto p_session = IstreamToFiberSession::Create( + &manager_, std::move(*p_fiber), output_file, stop_handler); + boost::system::error_code start_ec; + manager_.start(p_session, start_ec); + } + } + + // This callback remove the output file from the file list and closes the + // demux service once the file list is empty + void FinishSentSession(const std::string output_file, + FilesListPtr p_files_list) { + boost::mutex::scoped_lock lock_files_set(files_set_mutex_); + p_files_list->remove(output_file); + + if (p_files_list->empty()) { + auto& demux = this->get_demux(); + auto close_demux_callback = [&demux]() { demux.close(); }; + this->get_demux().get_io_service().post(close_demux_callback); + } + } + + // Extract input filename from input pattern + // Generate output filename from input file and output_pattern + void ParseInputOutputPatterns(const std::string& input_pattern, + const std::string& output_pattern, + InputOutputFilesMap* p_input_output_files) { + auto input_files = filesystem::Filesystem::Glob(input_pattern); + for (auto& input_file : input_files) { + (*p_input_output_files)[input_file] = + output_pattern + Filesystem::GetFilename(input_file); + } + } + + template + auto Then(Handler handler, + This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { + return boost::bind(handler, me->SelfFromThis(), _1); + } + + std::shared_ptr SelfFromThis() { + return std::static_pointer_cast(this->shared_from_this()); + } + + private: + bool accept_; + bool from_stdin_; + std::string input_pattern_; + std::string output_pattern_; + SessionManager manager_; + fiber_acceptor fiber_acceptor_; + boost::mutex files_set_mutex_; + // Coroutine variables + boost::asio::coroutine coroutine_; + FilenameBuffer input_request_; + FilenameBuffer output_request_; +}; + +} // file_to_fiber +} // copy_file +} // services +} // ssf + +#endif // SSF_SERVICES_COPY_FILE_FILE_TO_FIBER_FILE_TO_FIBER_H_ diff --git a/src/services/copy_file/file_to_fiber/istream_to_fiber_session.h b/src/services/copy_file/file_to_fiber/istream_to_fiber_session.h new file mode 100644 index 00000000..dbc6f3f1 --- /dev/null +++ b/src/services/copy_file/file_to_fiber/istream_to_fiber_session.h @@ -0,0 +1,180 @@ +#ifndef SRC_SERVICES_COPY_FILE_FILE_TO_FIBER_ISTREAM_TO_FIBER_SESSION_H_ +#define SRC_SERVICES_COPY_FILE_FILE_TO_FIBER_ISTREAM_TO_FIBER_SESSION_H_ + +#include +#include +#include + +#include +#include +#include + +#include + +#include "common/network/base_session.h" + +#include "common/network/manager.h" +#include "common/network/base_session.h" + +#include "services/copy_file/filename_buffer.h" +#include "services/copy_file/packet/packet.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace file_to_fiber { + +template +class IstreamToFiberSession : public ssf::BaseSession { + public: + using IstreamToFiberSessionPtr = std::shared_ptr; + // Type for the class managing the different forwarding links + using SessionManager = ItemManager; + // Buffer for the transiting data + using FilenameBuffer = ssf::services::copy_file::FilenameBuffer; + using Packet = ssf::services::copy_file::packet::Packet; + using StopSessionHandler = std::function; + + public: + template + static IstreamToFiberSessionPtr Create(Args&&... args) { + return std::shared_ptr( + new IstreamToFiberSession(std::forward(args)...)); + } + + virtual ~IstreamToFiberSession() {} + + // Start read from input stream and write to output socket stream + virtual void start(boost::system::error_code& ec) { + if (!from_stdin_) { + input_stream_.open(input_file_, InputStream::binary); + if (!input_stream_.is_open() || !input_stream_.good()) { + BOOST_LOG_TRIVIAL(error) << "session istream to fiber : cannot open file " + << input_file_; + ec.assign(ssf::error::bad_file_descriptor, ssf::error::get_ssf_category()); + stop_handler_(output_file_); + + return; + } + } + + ForwardData(boost::system::error_code(), 0); + } + + // Stop session + virtual void stop(boost::system::error_code& ec) { + output_socket_stream_.close(ec); + input_stream_.close(); + } + + private: + IstreamToFiberSession(SessionManager* p_manager, const std::string& input_file, + OutputSocketStream&& output_socket_stream, + const std::string& output_file, + StopSessionHandler stop_handler) + : from_stdin_(false), + input_file_(input_file), + input_stream_(), + output_socket_stream_(std::move(output_socket_stream)), + output_file_(output_file), + p_manager_(p_manager), + stop_handler_(stop_handler), + output_request_(output_file) {} + + IstreamToFiberSession(SessionManager* p_manager, + OutputSocketStream&& output_socket_stream, + const std::string& output_file, + StopSessionHandler stop_handler) + : from_stdin_(true), + output_socket_stream_(std::move(output_socket_stream)), + output_file_(output_file), + p_manager_(p_manager), + stop_handler_(stop_handler), + output_request_(output_file) {} + +#include // NOLINT + // Write filename + // Forward file through fiber + void ForwardData(const boost::system::error_code& ec, std::size_t length) { + auto& input = from_stdin_ ? std::cin : input_stream_; + + if (ec) { + boost::system::error_code stop_ec; + p_manager_->stop(this->SelfFromThis(), stop_ec); + stop_handler_(output_file_); + + return; + } + + reenter(coroutine_) { + // async send output file name size + yield boost::asio::async_write( + output_socket_stream_, output_request_.GetFilenameSizeConstBuffers(), + boost::bind(&IstreamToFiberSession::ForwardData, this->SelfFromThis(), + _1, _2)); + + // async send output file name + yield boost::asio::async_write( + output_socket_stream_, output_request_.GetFilenameConstBuffers(), + boost::bind(&IstreamToFiberSession::ForwardData, this->SelfFromThis(), + _1, _2)); + + while (input.good()) { + packet_.set_type(Packet::kData); + input.read(packet_.buffer().data(), packet_.buffer().size()); + packet_.set_size(static_cast(input.gcount())); + + yield boost::asio::async_write( + output_socket_stream_, packet_.GetConstBuf(), + boost::bind(&IstreamToFiberSession::ForwardData, + this->SelfFromThis(), _1, _2)); + } + + if (input.eof()) { + packet_.set_type(Packet::kCtrl); + packet_.set_signal(Packet::kEof); + } else { + packet_.set_type(Packet::kCtrl); + packet_.set_signal(Packet::kInterrupted); + } + + yield boost::asio::async_write( + output_socket_stream_, packet_.GetConstBuf(), + boost::bind(&IstreamToFiberSession::ForwardData, this->SelfFromThis(), + _1, _2)); + + yield boost::asio::async_read( + output_socket_stream_, packet_.GetTypeMutBuf(), + boost::bind(&IstreamToFiberSession::ForwardData, this->SelfFromThis(), + _1, _2)); + } + } +#include // NOLINT + + IstreamToFiberSessionPtr SelfFromThis() { + return std::static_pointer_cast( + this->shared_from_this()); + } + + private: + bool from_stdin_; + std::string input_file_; + InputStream input_stream_; + OutputSocketStream output_socket_stream_; + std::string output_file_; + SessionManager* p_manager_; + StopSessionHandler stop_handler_; + + // Coroutine variables + boost::asio::coroutine coroutine_; + Packet packet_; + std::size_t file_read_length_; + FilenameBuffer output_request_; +}; + +} // file_to_fiber +} // copy_file +} // services +} // ssf + +#endif // SRC_SERVICES_COPY_FILE_FILE_TO_FIBER_ISTREAM_TO_FIBER_SESSION_H_ diff --git a/src/services/copy_file/filename_buffer.cpp b/src/services/copy_file/filename_buffer.cpp new file mode 100644 index 00000000..70ae06cb --- /dev/null +++ b/src/services/copy_file/filename_buffer.cpp @@ -0,0 +1,38 @@ +#include "services/copy_file/filename_buffer.h" + +namespace ssf { +namespace services { +namespace copy_file { + +FilenameBuffer::FilenameBuffer() : filename_size_(0), filename_() {} + +FilenameBuffer::FilenameBuffer(const std::string& filename) + : filename_size_(filename.length()), + filename_(filename.cbegin(), filename.cend()) {} + +std::string FilenameBuffer::GetFilename() const { + return std::string(filename_.cbegin(), filename_.cend()); +} + +boost::asio::const_buffers_1 FilenameBuffer::GetFilenameSizeConstBuffers() + const { + return boost::asio::const_buffers_1( + boost::asio::buffer(&filename_size_, sizeof(filename_size_))); +} + +boost::asio::mutable_buffers_1 FilenameBuffer::GetFilenameSizeMutBuffers() { + return boost::asio::buffer(&filename_size_, sizeof(filename_size_)); +} + +boost::asio::const_buffers_1 FilenameBuffer::GetFilenameConstBuffers() const { + return boost::asio::const_buffers_1(boost::asio::buffer(filename_)); +} + +boost::asio::mutable_buffers_1 FilenameBuffer::GetFilenameMutBuffers() { + filename_.resize(filename_size_); + return boost::asio::buffer(filename_); +} + +} // copy_file +} // services +} // ssf \ No newline at end of file diff --git a/src/services/copy_file/filename_buffer.h b/src/services/copy_file/filename_buffer.h new file mode 100644 index 00000000..530a8b5a --- /dev/null +++ b/src/services/copy_file/filename_buffer.h @@ -0,0 +1,38 @@ +#ifndef SSF_SERVICES_COPY_FILE_FILENAME_BUFFER_H_ +#define SSF_SERVICES_COPY_FILE_FILENAME_BUFFER_H_ + +#include + +#include +#include +#include + +#include + +namespace ssf { +namespace services { +namespace copy_file { + +class FilenameBuffer { + public: + FilenameBuffer(); + FilenameBuffer(const std::string& filename); + + std::string GetFilename() const; + + boost::asio::const_buffers_1 GetFilenameSizeConstBuffers() const; + boost::asio::mutable_buffers_1 GetFilenameSizeMutBuffers(); + + boost::asio::const_buffers_1 GetFilenameConstBuffers() const; + boost::asio::mutable_buffers_1 GetFilenameMutBuffers(); + + private: + uint32_t filename_size_; + std::vector filename_; +}; + +} // copy_file +} // services +} // ssf + +#endif // SSF_SERVICES_COPY_FILE_FILENAME_BUFFER_H_ diff --git a/src/services/copy_file/filesystem/filesystem.cpp b/src/services/copy_file/filesystem/filesystem.cpp new file mode 100644 index 00000000..ad39463e --- /dev/null +++ b/src/services/copy_file/filesystem/filesystem.cpp @@ -0,0 +1,19 @@ +#include "services/copy_file/filesystem/filesystem.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace filesystem { + +std::string Filesystem::GetFilename(const std::string& path) { + return path.substr(path.find_last_of("/\\") + 1); +} + +std::string Filesystem::GetParentPath(const std::string& path) { + return path.substr(0, path.find_last_of("/\\")); +} + +} // ssf +} // services +} // copy_file +} // ssf diff --git a/src/services/copy_file/filesystem/filesystem.h b/src/services/copy_file/filesystem/filesystem.h new file mode 100644 index 00000000..c7d37cbd --- /dev/null +++ b/src/services/copy_file/filesystem/filesystem.h @@ -0,0 +1,28 @@ +#ifndef SSF_SERVICES_COPY_FILE_FILESYSTEM_FILESYSTEM_H_ +#define SSF_SERVICES_COPY_FILE_FILESYSTEM_FILESYSTEM_H_ + +#include + +#include +#include + +namespace ssf { +namespace services { +namespace copy_file { +namespace filesystem { + +class Filesystem { + public: + static std::list Glob(const std::string& path); + + static std::string GetFilename(const std::string& path); + + static std::string GetParentPath(const std::string& path); +}; + +} // filesystem +} // copy_file +} // services +} // ssf + +#endif // SSF_SERVICES_COPY_FILE_FILESYSTEM_FILESYSTEM_H_ diff --git a/src/services/copy_file/filesystem/linux/unix_filesystem.cpp b/src/services/copy_file/filesystem/linux/unix_filesystem.cpp new file mode 100644 index 00000000..3efe46f8 --- /dev/null +++ b/src/services/copy_file/filesystem/linux/unix_filesystem.cpp @@ -0,0 +1,26 @@ +#include "services/copy_file/filesystem/filesystem.h" + +#include + +namespace ssf { +namespace services { +namespace copy_file { +namespace filesystem { + +std::list Filesystem::Glob(const std::string& path) { + std::list result; + + glob_t glob_result; + glob(path.c_str(), GLOB_TILDE, NULL, &glob_result); + for (uint32_t i = 0; i < glob_result.gl_pathc; ++i) { + result.push_back(std::string(glob_result.gl_pathv[i])); + } + globfree(&glob_result); + + return result; +} + +} // filesystem +} // copy_file +} // services +} // ssf diff --git a/src/services/copy_file/filesystem/windows/win_filesystem.cpp b/src/services/copy_file/filesystem/windows/win_filesystem.cpp new file mode 100644 index 00000000..4f1ba4dc --- /dev/null +++ b/src/services/copy_file/filesystem/windows/win_filesystem.cpp @@ -0,0 +1,33 @@ +#include "services/copy_file/filesystem/filesystem.h" + +#include + +#include + +#include + +namespace ssf { +namespace services { +namespace copy_file { +namespace filesystem { + +std::list Filesystem::Glob(const std::string& path) { + std::list result; + HANDLE file_handle; + WIN32_FIND_DATA data; + auto parent_dir_path = Filesystem::GetParentPath(path); + + file_handle = FindFirstFile(path.c_str(), &data); + if (file_handle != INVALID_HANDLE_VALUE) { + do { + result.push_back(parent_dir_path + '/' + data.cFileName); + } while (FindNextFile(file_handle, &data) != 0); + } + + return result; +} + +} // filesystem +} // copy_file +} // services +} // ssf diff --git a/src/services/copy_file/packet/packet.cpp b/src/services/copy_file/packet/packet.cpp new file mode 100644 index 00000000..c71a2447 --- /dev/null +++ b/src/services/copy_file/packet/packet.cpp @@ -0,0 +1,99 @@ +#include "services/copy_file/packet/packet.h" + +namespace ssf { +namespace services { +namespace copy_file { +namespace packet { + +Packet::Packet() : type_(kCtrl), signal_(kInterrupted), size_(0), buffer_() {} + +Packet::Type Packet::type() const { return type_; } + +void Packet::set_type(Type type) { type_ = type; } + +boost::asio::const_buffers_1 Packet::GetTypeConstBuf() const { + return boost::asio::const_buffers_1( + boost::asio::buffer(&type_, sizeof(type_))); +} + +boost::asio::mutable_buffers_1 Packet::GetTypeMutBuf() { + return boost::asio::buffer(&type_, sizeof(type_)); +} + +bool Packet::IsDataPacket() { return type_ == kData; } + +Packet::Size Packet::size() const { return size_; } + +void Packet::set_size(Size size) { size_ = size; } + +boost::asio::const_buffers_1 Packet::GetSizeConstBuf() const { + return boost::asio::const_buffers_1( + boost::asio::buffer(&size_, sizeof(size_))); +} + +boost::asio::mutable_buffers_1 Packet::GetSizeMutBuf() { + return boost::asio::buffer(&size_, sizeof(size_)); +} + +Packet::Signal Packet::signal() const { return signal_; } + +void Packet::set_signal(Signal signal) { signal_ = signal; } + +boost::asio::const_buffers_1 Packet::GetSignalConstBuf() const { + return boost::asio::const_buffers_1( + boost::asio::buffer(&signal_, sizeof(signal_))); +} + +boost::asio::mutable_buffers_1 Packet::GetSignalMutBuf() { + return boost::asio::buffer(&signal_, sizeof(signal_)); +} + +Packet::Buffer& Packet::buffer() { return buffer_; } + +Packet::ConstBufSeq Packet::GetConstBuf() const { + ConstBufSeq buf_seq; + auto header_buf = GetHeaderConstBuf(); + auto payload_buf = GetPayloadConstBuf(); + + buf_seq.insert(buf_seq.end(), header_buf.begin(), header_buf.end()); + buf_seq.insert(buf_seq.end(), payload_buf.begin(), payload_buf.end()); + + return buf_seq; +} + +Packet::ConstBufSeq Packet::GetHeaderConstBuf() const { + ConstBufSeq buf_seq; + buf_seq.push_back(boost::asio::buffer(&type_, sizeof(type_))); + if (type_ == kData) { + buf_seq.push_back(boost::asio::buffer(&size_, sizeof(size_))); + } + + return buf_seq; +} + +Packet::ConstBufSeq Packet::GetPayloadConstBuf() const { + ConstBufSeq buf_seq; + if (type_ == kCtrl) { + buf_seq.push_back(boost::asio::buffer(&signal_, sizeof(signal_))); + } else { + buf_seq.push_back(boost::asio::buffer(buffer_, size_)); + } + + return buf_seq; +} + +Packet::MutBufSeq Packet::GetPayloadMutBuf() { + MutBufSeq buf_seq; + if (type_ == kCtrl) { + buf_seq.push_back(boost::asio::buffer(&signal_, sizeof(signal_))); + } else { + buf_seq.push_back(boost::asio::buffer(buffer_, size_)); + } + + return buf_seq; +} + +} // packet +} // copy_file +} // services +} // ssf diff --git a/src/services/copy_file/packet/packet.h b/src/services/copy_file/packet/packet.h new file mode 100644 index 00000000..16a980c3 --- /dev/null +++ b/src/services/copy_file/packet/packet.h @@ -0,0 +1,67 @@ +#ifndef SRC_SERVICES_COPY_FILE_PACKET_PACKET_H_ +#define SRC_SERVICES_COPY_FILE_PACKET_PACKET_H_ + +#include + +#include + +#include + +namespace ssf { +namespace services { +namespace copy_file { +namespace packet { + +class Packet { + public: + using Size = uint32_t; + using Buffer = std::array; + + using ConstBufSeq = std::vector; + using MutBufSeq = std::vector; + + enum Type : uint8_t { kCtrl = 0, kData = 1 }; + + enum Signal : uint8_t { kEof = 0, kInterrupted = 1 }; + + public: + Packet(); + Type type() const; + void set_type(Type type); + boost::asio::const_buffers_1 GetTypeConstBuf() const; + boost::asio::mutable_buffers_1 GetTypeMutBuf(); + + bool IsDataPacket(); + + Size size() const; + void set_size(Size size); + boost::asio::const_buffers_1 GetSizeConstBuf() const; + boost::asio::mutable_buffers_1 GetSizeMutBuf(); + + Signal signal() const; + void set_signal(Signal signal); + boost::asio::const_buffers_1 GetSignalConstBuf() const; + boost::asio::mutable_buffers_1 GetSignalMutBuf(); + + Buffer& buffer(); + + ConstBufSeq GetConstBuf() const; + + ConstBufSeq GetHeaderConstBuf() const; + + ConstBufSeq GetPayloadConstBuf() const; + MutBufSeq GetPayloadMutBuf(); + + private: + Type type_; + Signal signal_; + Size size_; + Buffer buffer_; +}; + +} // packet +} // copy_file +} // services +} // ssf + +#endif // SRC_SERVICES_COPY_FILE_PACKET_PACKET_H_ diff --git a/src/services/user_services/copy_file_service.h b/src/services/user_services/copy_file_service.h new file mode 100644 index 00000000..dae663d2 --- /dev/null +++ b/src/services/user_services/copy_file_service.h @@ -0,0 +1,183 @@ +#ifndef SSF_SERVICES_USER_SERVICES_COPY_FILE_SERVICE_H_ +#define SSF_SERVICES_USER_SERVICES_COPY_FILE_SERVICE_H_ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "services/user_services/base_user_service.h" +#include "services/copy_file/file_enquirer/file_enquirer.h" +#include "services/copy_file/file_to_fiber/file_to_fiber.h" +#include "services/copy_file/fiber_to_file/fiber_to_file.h" + +namespace ssf { +namespace services { + +template +class CopyFileService : public BaseUserService { + public: + using ServiceId = uint32_t; + using ServideIdSet = std::set; + using UserParameters = std::map>; + using CopyFileServicePtr = std::shared_ptr; + + public: + // Create user service from parameters (factory method) + static std::shared_ptr CreateServiceFromParams( + bool from_stdin, bool from_local_to_remote, + const std::string& input_pattern, const std::string& output_pattern, + boost::system::error_code& ec) { + ec.assign(ssf::error::success, ssf::error::get_ssf_category()); + return CopyFileServicePtr(new CopyFileService( + from_stdin, from_local_to_remote, input_pattern, output_pattern)); + } + + virtual std::string GetName() { return "copy_file"; } + + virtual std::vector> + GetRemoteServiceCreateVector() { + std::vector> result; + result.push_back(GetRemoteServiceRequest()); + return result; + } + + virtual std::vector> + GetRemoteServiceStopVector(Demux& demux) { + std::vector> result; + + return result; + } + + virtual uint32_t CheckRemoteServiceStatus(Demux& demux) { + services::admin::CreateServiceRequest remote_service_request = + GetRemoteServiceRequest(); + + auto p_service_factory = + ServiceFactoryManager::GetServiceFactory(&demux); + auto status = p_service_factory->GetStatus( + remote_service_request.service_id(), + remote_service_request.parameters(), GetRemoteServiceId(demux)); + + return status; + } + + virtual bool StartLocalServices(Demux& demux) { + auto p_service_factory = + ServiceFactoryManager::GetServiceFactory(&demux); + boost::system::error_code ec; + + if (from_local_to_remote_) { + // Local to remote : file to fiber only + services::admin::CreateServiceRequest local_service_request; + local_service_request = services::copy_file::file_to_fiber::FileToFiber< + Demux>::GetCreateRequest(false, from_stdin_, input_pattern_, + output_pattern_); + + local_service_ids_.insert(p_service_factory->CreateRunNewService( + local_service_request.service_id(), + local_service_request.parameters(), ec)); + return !ec; + } + + // Remote to local : fiber to file, file enquirer + services::admin::CreateServiceRequest fiber_to_file_request = + services::copy_file::fiber_to_file::FiberToFile< + Demux>::GetCreateRequest(); + + services::admin::CreateServiceRequest file_enquirer_request = + services::copy_file::file_enquirer::FileEnquirer< + Demux>::GetCreateRequest(input_pattern_, output_pattern_); + + local_service_ids_.insert(p_service_factory->CreateRunNewService( + fiber_to_file_request.service_id(), fiber_to_file_request.parameters(), + ec)); + + local_service_ids_.insert(p_service_factory->CreateRunNewService( + file_enquirer_request.service_id(), file_enquirer_request.parameters(), + ec)); + + return !ec; + } + + virtual void StopLocalServices(Demux& demux) { + auto p_service_factory = + ServiceFactoryManager::GetServiceFactory(&demux); + for (auto& local_service_id : local_service_ids_) { + p_service_factory->StopService(local_service_id); + } + local_service_ids_.clear(); + } + + virtual ~CopyFileService() {} + + private: + CopyFileService(bool from_stdin, bool from_local_to_remote, + const std::string& input_pattern, + const std::string& output_pattern) + : from_stdin_(from_stdin), + from_local_to_remote_(from_local_to_remote || from_stdin), + input_pattern_(input_pattern), + output_pattern_(output_pattern), + remote_service_id_(0), + local_service_ids_() {} + + services::admin::CreateServiceRequest GetRemoteServiceRequest() { + services::admin::CreateServiceRequest remote_service_request; + if (from_local_to_remote_) { + remote_service_request = services::copy_file::fiber_to_file::FiberToFile< + Demux>::GetCreateRequest(); + } else { + remote_service_request = services::copy_file::file_to_fiber::FileToFiber< + Demux>::GetCreateRequest(true, false, "", ""); + } + return remote_service_request; + } + + services::admin::CreateServiceRequest GetLocalServiceRequest() { + services::admin::CreateServiceRequest local_service_request; + if (from_local_to_remote_) { + local_service_request = services::copy_file::file_to_fiber::FileToFiber< + Demux>::GetCreateRequest(false, from_stdin_, input_pattern_, + output_pattern_); + } else { + local_service_request = services::copy_file::fiber_to_file::FiberToFile< + Demux>::GetCreateRequest(); + } + return local_service_request; + } + + uint32_t GetRemoteServiceId(Demux& demux) { + if (remote_service_id_) { + return remote_service_id_; + } else { + auto remote_service_request = GetRemoteServiceRequest(); + + auto p_service_factory = + ServiceFactoryManager::GetServiceFactory(&demux); + auto id = p_service_factory->GetIdFromParameters( + remote_service_request.service_id(), + remote_service_request.parameters()); + remote_service_id_ = id; + return id; + } + } + + private: + bool from_stdin_; + bool from_local_to_remote_; + std::string input_pattern_; + std::string output_pattern_; + ServiceId remote_service_id_; + ServideIdSet local_service_ids_; +}; + +} // services +} // ssf + +#endif // SSF_SERVICES_USER_SERVICES_COPY_FILE_SERVICE_H_ From 772e25d4a8321a248f1f83ea236f923cff0d30dd Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Sat, 10 Oct 2015 20:39:49 +0200 Subject: [PATCH 10/13] Add copy file test Integrate copy service in SSF client and server Refactor CMakelists Change method naming in network and transport policies Coding style --- CMakeLists.txt | 148 ++++++--- cmake-ms/CMakeLists.txt | 11 + cmake-unix/CMakeLists.txt | 14 +- src/common/error/error.cpp | 3 + src/common/error/error.h | 3 +- src/common/network/session_forwarder.h | 11 +- src/common/network/socket_link.h | 8 +- src/core/client/client.h | 11 +- src/core/client/client.ipp | 100 ++++--- src/core/factories/service_factory.h | 14 +- src/core/factories/service_option_factory.h | 6 +- .../bounce_protocol_policy.h | 243 +++++++-------- .../null_link_authentication_policy.h | 26 +- .../link_policies/ssl_policy.h | 168 ++++++----- .../link_policies/tcp_policy.h | 71 +++-- src/core/parser/bounce_parser.cpp | 50 ++++ src/core/parser/bounce_parser.h | 25 ++ src/core/server/server.h | 41 ++- src/core/server/server.ipp | 95 +++--- .../transport_protocol_policy.h | 18 +- src/services/admin/admin.h | 114 ++++--- src/services/admin/admin.ipp | 39 +-- .../admin/requests/create_service_request.h | 5 +- src/services/base_service.h | 35 ++- .../fibers_to_sockets/fibers_to_sockets.h | 39 ++- .../fibers_to_sockets/fibers_to_sockets.ipp | 36 ++- src/services/initialisation.h | 3 +- .../sockets_to_fibers/sockets_to_fibers.h | 32 +- .../sockets_to_fibers/sockets_to_fibers.ipp | 40 +-- src/services/user_services/port_forwarding.h | 10 +- .../user_services/remote_port_forwarding.h | 14 +- src/services/user_services/remote_socks.h | 30 +- src/services/user_services/socks.h | 4 +- src/tests/CMakeLists.txt | 76 +++-- src/tests/bouncing_tests.cpp | 219 +------------- src/tests/copy_file_test_fixture.h | 283 ++++++++++++++++++ src/tests/file_copy_from_client_tests.cpp | 148 +++++++++ src/tests/files_to_copy/test_file1.txt | 3 + src/tests/files_to_copy/test_file2.txt | 3 + 39 files changed, 1308 insertions(+), 891 deletions(-) create mode 100644 src/core/parser/bounce_parser.cpp create mode 100644 src/core/parser/bounce_parser.h create mode 100644 src/tests/copy_file_test_fixture.h create mode 100644 src/tests/file_copy_from_client_tests.cpp create mode 100644 src/tests/files_to_copy/test_file1.txt create mode 100644 src/tests/files_to_copy/test_file2.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c8d2b68..d2f70208 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,11 +37,7 @@ set(VERSIONS_FILES FILE(GLOB_RECURSE COMMON_BOOST_FIBER_FILES "${project_SRC_DIR}/common/boost/fiber/*.hpp" "${project_SRC_DIR}/common/boost/fiber/*.cpp") - -FILE(GLOB_RECURSE COMMON_COMMAND_LINE_FILES - "${project_SRC_DIR}/core/command_line/*.h" - "${project_SRC_DIR}/core/command_line/*.cpp") - + FILE(GLOB_RECURSE COMMON_CONFIG_FILES "${project_SRC_DIR}/common/config/*.h" "${project_SRC_DIR}/common/config/*.cpp") @@ -49,12 +45,24 @@ FILE(GLOB_RECURSE COMMON_CONFIG_FILES FILE(GLOB_RECURSE COMMON_ERROR_FILES "${project_SRC_DIR}/common/error/*.h" "${project_SRC_DIR}/common/error/*.cpp") + +FILE(GLOB_RECURSE COMMON_NETWORK_FILES + "${project_SRC_DIR}/common/network/*.h" + "${project_SRC_DIR}/common/network/*.cpp") FILE(GLOB_RECURSE COMMON_UTILS_FILES "${project_SRC_DIR}/common/utils/*.h" "${project_SRC_DIR}/common/utils/*.cpp" "${project_SRC_DIR}/common/utils/*.ipp") +FILE(GLOB CORE_COMMAND_LINE_STANDARD_FILES + "${project_SRC_DIR}/core/command_line/standard/*.h" + "${project_SRC_DIR}/core/command_line/standard/*.cpp") + +FILE(GLOB CORE_COMMAND_LINE_COPY_FILES + "${project_SRC_DIR}/core/command_line/copy/*.h" + "${project_SRC_DIR}/core/command_line/copy/*.cpp") + FILE(GLOB_RECURSE CORE_TRANSPORT_POLICIES_FILES "${project_SRC_DIR}/core/transport_virtual_layer_policies/*.h" "${project_SRC_DIR}/core/transport_virtual_layer_policies/*.cpp" @@ -76,24 +84,76 @@ FILE(GLOB_RECURSE CORE_FACTORIES_FILES "${project_SRC_DIR}/core/service_manager/*.cpp" "${project_SRC_DIR}/core/service_manager/*.ipp") -FILE(GLOB_RECURSE SERVICES_FILES +FILE(GLOB BASE_SERVICE_FILES "${project_SRC_DIR}/services/*.h" "${project_SRC_DIR}/services/*.cpp" "${project_SRC_DIR}/services/*.ipp") -set(SSF_SOURCES - ${VERSIONS_FILES} - ${COMMON_BOOST_FIBER_FILES} - ${COMMON_COMMAND_LINE_FILES} - ${COMMON_CONFIG_FILES} - ${COMMON_ERROR_FILES} - ${COMMON_NETWORK_FILES} - ${COMMON_UTILS_FILES} - ${CORE_TRANSPORT_POLICIES_FILES} - ${CORE_NETWORK_VIRTUAL_LAYER_POLICIES_FILES} - ${CORE_FACTORIES_FILES} - ${SERVICES_FILES} -) +FILE(GLOB_RECURSE ADMIN_SERVICE_FILES + "${project_SRC_DIR}/services/admin/*.h" + "${project_SRC_DIR}/services/admin/*.cpp" + "${project_SRC_DIR}/services/admin/*.ipp") + +FILE(GLOB_RECURSE DATAGRAMS_TO_FIBERS_SERVICE_FILES + "${project_SRC_DIR}/services/datagrams_to_fibers/*.h" + "${project_SRC_DIR}/services/datagrams_to_fibers/*.cpp" + "${project_SRC_DIR}/services/datagrams_to_fibers/*.ipp") + +FILE(GLOB_RECURSE FIBERS_TO_DATAGRAMS_SERVICE_FILES + "${project_SRC_DIR}/services/fibers_to_datagrams/*.h" + "${project_SRC_DIR}/services/fibers_to_datagrams/*.cpp" + "${project_SRC_DIR}/services/fibers_to_datagrams/*.ipp") + +FILE(GLOB_RECURSE SOCKETS_TO_FIBERS_SERVICE_FILES + "${project_SRC_DIR}/services/datagrams_to_fibers/*.h" + "${project_SRC_DIR}/services/datagrams_to_fibers/*.cpp" + "${project_SRC_DIR}/services/datagrams_to_fibers/*.ipp") + +FILE(GLOB_RECURSE FIBERS_TO_SOCKETS_SERVICE_FILES + "${project_SRC_DIR}/services/fibers_to_datagrams/*.h" + "${project_SRC_DIR}/services/fibers_to_datagrams/*.cpp" + "${project_SRC_DIR}/services/fibers_to_datagrams/*.ipp") + +FILE(GLOB_RECURSE SOCKS_SERVICE_FILES + "${project_SRC_DIR}/services/socks/*.h" + "${project_SRC_DIR}/services/socks/*.cpp" + "${project_SRC_DIR}/services/socks/*.ipp") + +FILE(GLOB COPY_FILE_SERVICE_FILES + "${project_SRC_DIR}/services/copy_file/*.h" + "${project_SRC_DIR}/services/copy_file/*.cpp" + "${project_SRC_DIR}/services/copy_file/*.ipp" + "${project_SRC_DIR}/services/copy_file/fiber_to_file/*.h" + "${project_SRC_DIR}/services/copy_file/fiber_to_file/*.cpp" + "${project_SRC_DIR}/services/copy_file/fiber_to_file/*.ipp" + "${project_SRC_DIR}/services/copy_file/file_to_fiber/*.h" + "${project_SRC_DIR}/services/copy_file/file_to_fiber/*.cpp" + "${project_SRC_DIR}/services/copy_file/file_to_fiber/*.ipp" + "${project_SRC_DIR}/services/copy_file/file_enquirer/*.h" + "${project_SRC_DIR}/services/copy_file/file_enquirer/*.cpp" + "${project_SRC_DIR}/services/copy_file/file_enquirer/*.ipp" + "${project_SRC_DIR}/services/copy_file/packet/*.h" + "${project_SRC_DIR}/services/copy_file/packet/*.cpp" + "${project_SRC_DIR}/services/copy_file/packet/*.ipp" + "${project_SRC_DIR}/services/copy_file/filesystem/*.h" + "${project_SRC_DIR}/services/copy_file/filesystem/*.cpp") + +FILE(GLOB_RECURSE USER_SERVICE_FILES + "${project_SRC_DIR}/services/user_services/*.h" + "${project_SRC_DIR}/services/user_services/*.cpp" + "${project_SRC_DIR}/services/user_services/*.ipp") + +set(PARSER_FILES + "${project_SRC_DIR}/core/parser/bounce_parser.h" + "${project_SRC_DIR}/core/parser/bounce_parser.cpp") + +FILE(GLOB_RECURSE CLIENT_FILES + "${project_SRC_DIR}/core/client/*.h" + "${project_SRC_DIR}/core/client/*.ipp") + +FILE(GLOB_RECURSE SERVER_FILES + "${project_SRC_DIR}/core/server/*.h" + "${project_SRC_DIR}/core/server/*.ipp") set(BOOST_ROOT "${project_THIRDPARTY_DIR}/boost" CACHE PATH "Path of boost library") @@ -166,10 +226,40 @@ include_directories(${project_BINARY_DIR}) # --- Include source directory include_directories(${project_SRC_DIR}) + +# --- Set macro SSF service files +set(SERVICES_FILES + ${BASE_SERVICE_FILES} + ${ADMIN_SERVICE_FILES} + ${DATAGRAMS_TO_FIBERS_SERVICE_FILES} + ${FIBERS_TO_DATAGRAMS_SERVICE_FILES} + ${SOCKETS_TO_FIBERS_SERVICE_FILES} + ${FIBERS_TO_SOCKETS_SERVICE_FILES} + ${SOCKS_SERVICE_FILES} + ${USER_SERVICE_FILES} + ${COPY_FILE_SERVICE_FILES}) + +# --- Set macro SSF source files +set(SSF_SOURCES + ${VERSIONS_FILES} + ${COMMON_BOOST_FIBER_FILES} + ${COMMON_CONFIG_FILES} + ${COMMON_ERROR_FILES} + ${COMMON_NETWORK_FILES} + ${COMMON_UTILS_FILES} + ${CORE_TRANSPORT_POLICIES_FILES} + ${CORE_NETWORK_VIRTUAL_LAYER_POLICIES_FILES} + ${CORE_FACTORIES_FILES} + ${SERVICES_FILES} + ${PARSER_FILES} + ${CLIENT_FILES} + ${SERVER_FILES} +) + set (BUILD_UNIT_TESTS ON) if (BUILD_UNIT_TESTS) include(GTest) - + set(GTEST_ROOT_DIR "${project_THIRDPARTY_DIR}/gtest" CACHE PATH "Path of gtest library") @@ -180,25 +270,9 @@ if (BUILD_UNIT_TESTS) # --- Add GTest project add_subdirectory(${GTEST_ROOT_DIR}) - + # --- Add src test add_subdirectory("${project_SRC_DIR}/tests") - - # Group all tests in one directory - project_group( - "Unit tests" - load_config_tests - fiber_asio_tests - ssf_client_server_tests - ssf_client_server_cipher_suites_tests - socks_tests - remote_socks_tests - stream_forward_tests - remote_stream_forward_tests - udp_forward_tests - remote_udp_forward_tests - bouncing_tests - ) endif (BUILD_UNIT_TESTS) add_subdirectory("${project_SRC_DIR}/core") diff --git a/cmake-ms/CMakeLists.txt b/cmake-ms/CMakeLists.txt index cf23b3d8..87185f2a 100644 --- a/cmake-ms/CMakeLists.txt +++ b/cmake-ms/CMakeLists.txt @@ -5,6 +5,17 @@ if (WIN32) include(MSVCStaticRuntime) include(HelpersIdeTarget) + # --- Include windows impl + + # --- Filesystem globbing + FILE(GLOB_RECURSE COPY_FILE_SERVICE_WINDOWS_FILES + "${project_SRC_DIR}/services/copy_file/filesystem/windows/*.h" + "${project_SRC_DIR}/services/copy_file/filesystem/windows/*.cpp") + + set(COPY_FILE_SERVICE_FILES + ${COPY_FILE_SERVICE_FILES} + ${COPY_FILE_SERVICE_WINDOWS_FILES}) + # --- Icon path set(ICON_RC "${project_IMG_DIR}/icon.rc") set(EXEC_FLAG "") diff --git a/cmake-unix/CMakeLists.txt b/cmake-unix/CMakeLists.txt index 9a2299b8..834c603d 100644 --- a/cmake-unix/CMakeLists.txt +++ b/cmake-unix/CMakeLists.txt @@ -10,6 +10,18 @@ if (UNIX) set(EXEC_FLAG "MACOSX_BUNDLE") endif (APPLE) + + # --- Include linux/unix impl + + # --- Filesystem globbing + FILE(GLOB_RECURSE COPY_FILE_SERVICE_LINUX_FILES + "${project_SRC_DIR}/services/copy_file/filesystem/linux/*.h" + "${project_SRC_DIR}/services/copy_file/filesystem/linux/*.cpp") + + set(COPY_FILE_SERVICE_FILES + ${COPY_FILE_SERVICE_FILES} + ${COPY_FILE_SERVICE_LINUX_FILES}) + # --- Flags for compilation if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") set(CLANG_NO_BOOST_WARNINGS "-Wno-unneeded-internal-declaration -Wno-unused-variable") @@ -18,7 +30,7 @@ if (UNIX) set(PLATFORM_SPECIFIC_LIB_DEP "pthread") else() set(GCC_NO_BOOST_WARNINGS "-Wno-long-long -Wno-unused-value -Wno-unused-local-typedefs") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++0x ${GCC_NO_BOOST_WARNINGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++11 ${GCC_NO_BOOST_WARNINGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall -ggdb -std=c++0x ${GCC_NO_BOOST_WARNINGS}") set(PLATFORM_SPECIFIC_LIB_DEP "pthread" "rt" ${CMAKE_DL_LIBS}) endif () diff --git a/src/common/error/error.cpp b/src/common/error/error.cpp index 84c2307f..014c3411 100644 --- a/src/common/error/error.cpp +++ b/src/common/error/error.cpp @@ -58,6 +58,9 @@ std::string ssf::error::detail::ssf_category::message(int value) const { case error::service_not_found: return "service not found"; break; + case error::service_not_started: + return "service not started"; + break; case error::out_of_range: return "out of range"; break; diff --git a/src/common/error/error.h b/src/common/error/error.h index 63e1583c..dfc59122 100644 --- a/src/common/error/error.h +++ b/src/common/error/error.h @@ -27,7 +27,8 @@ enum errors { wrong_protocol_type = boost::system::errc::wrong_protocol_type, operation_canceled = boost::system::errc::operation_canceled, service_not_found = 10000, - out_of_range = 10001, + service_not_started = 10001, + out_of_range = 10002 }; namespace detail { diff --git a/src/common/network/session_forwarder.h b/src/common/network/session_forwarder.h index d8df3cbf..81fd1fcd 100644 --- a/src/common/network/session_forwarder.h +++ b/src/common/network/session_forwarder.h @@ -9,6 +9,7 @@ #include "common/network/base_session.h" // NOLINT #include "common/network/manager.h" +#include "common/network/socket_link.h" namespace ssf { @@ -80,11 +81,11 @@ class SessionForwarder : public ssf::BaseSession { private: /// The constructor is made private to ensure users only use create() - SessionForwarder(SessionManager* manager, InwardStream inbound, + SessionForwarder(SessionManager* p_manager, InwardStream inbound, ForwardStream outbound) : inbound_(std::move(inbound)), outbound_(std::move(outbound)), - manager_(manager) {} + p_manager_(p_manager) {} /// Start forwarding void DoForward() { @@ -101,7 +102,7 @@ class SessionForwarder : public ssf::BaseSession { /// Stop forwarding void StopHandler(const boost::system::error_code& ec) { boost::system::error_code e; - manager_->stop(SelfFromThis(), e); + p_manager_->stop(SelfFromThis(), e); } private: @@ -110,7 +111,7 @@ class SessionForwarder : public ssf::BaseSession { ForwardStream outbound_; /// The manager handling multiple SessionForwarder - SessionManager* manager_; + SessionManager* p_manager_; // One buffer for each Half Duplex Link buffer_type inwardBuffer_; @@ -119,4 +120,4 @@ class SessionForwarder : public ssf::BaseSession { }; } // ssf -#endif // SSF_COMMON_NETWORK_SESSION_FORWARDER_H \ No newline at end of file +#endif // SSF_COMMON_NETWORK_SESSION_FORWARDER_H diff --git a/src/common/network/socket_link.h b/src/common/network/socket_link.h index 285b8c93..200a0d6c 100644 --- a/src/common/network/socket_link.h +++ b/src/common/network/socket_link.h @@ -1,10 +1,10 @@ #ifndef SSF_COMMON_NETWORK_SOCKET_LINK_H_ #define SSF_COMMON_NETWORK_SOCKET_LINK_H_ -#include // NOLINT - -#include // NOLINT -#include // NOLINT +#include +#include +#include +#include namespace ssf { //----------------------------------------------------------------------------- diff --git a/src/core/client/client.h b/src/core/client/client.h index 6ccdc62d..de89f3f9 100644 --- a/src/core/client/client.h +++ b/src/core/client/client.h @@ -66,13 +66,14 @@ class SSFClient : public NetworkVirtualLayerPolicy class L, template class> class N, template class T> -SSFClient::SSFClient( - boost::asio::io_service& io_service, const std::string& remote_addr, - const std::string& port, const ssf::Config& ssf_config, - std::vector user_services, - client_callback_type callback) +SSFClient::SSFClient(boost::asio::io_service& io_service, + const std::string& remote_addr, + const std::string& port, + const ssf::Config& ssf_config, + std::vector user_services, + client_callback_type callback) : N(io_service, ssf_config), T( - boost::bind(&SSFClient::do_ssf_start, this, _1, _2)), + boost::bind(&SSFClient::DoSSFStart, this, _1, _2)), io_service_(io_service), fiber_demux_(io_service), user_services_(user_services), @@ -34,40 +36,30 @@ SSFClient::SSFClient( remote_port_(port), callback_(std::move(callback)) {} -template class L, +template class L, template class> class N, template class T> void SSFClient::run(Parameters& parameters) { - //parameters["remote_addr"] = remote_addr_; - //parameters["remote_port"] = remote_port_; - this->add_route(parameters, boost::bind(&SSFClient::network_to_transport, - this, _1, _2)); + this->AddRoute( + parameters, + boost::bind(&SSFClient::NetworkToTransport, this, _1, _2)); } -template class L, +template class L, template class> class N, template class T> void SSFClient::stop() { - auto p_service_factory = - ServiceFactoryManager::GetServiceFactory(&fiber_demux_); - if (p_service_factory) { - p_service_factory->Destroy(); - } - fiber_demux_.close(); } //------------------------------------------------------------------------------- -template class L, +template class L, template class> class N, template class T> -void SSFClient::network_to_transport(p_socket_type p_socket, - vector_error_code_type v_ec) { - if (print_ec_vector(v_ec)) { - this->do_ssf_initiate(p_socket); +void SSFClient::NetworkToTransport(p_socket_type p_socket, + vector_error_code_type v_ec) { + if (PrintErrorVector(v_ec)) { + this->DoSSFInitiate(p_socket); } else { if (p_socket) { boost::system::error_code ec; @@ -83,16 +75,14 @@ void SSFClient::network_to_transport(p_socket_type p_socket, } //------------------------------------------------------------------------------ -template class L, +template class L, template class> class N, template class T> -bool SSFClient::print_ec_vector(vector_error_code_type v_ec) { +bool SSFClient::PrintErrorVector(vector_error_code_type v_ec) { for (size_t i = 0; i < v_ec.size(); ++i) { - BOOST_LOG_TRIVIAL(info) << "client: node " << i - << " status: " << v_ec[i] - << " message: " << v_ec[i].message(); if (v_ec[i]) { + BOOST_LOG_TRIVIAL(error) << "client: node " << i << " status: " << v_ec[i] + << " message: " << v_ec[i].message(); return false; } } @@ -100,18 +90,17 @@ bool SSFClient::print_ec_vector(vector_error_code_type v_ec) { } //------------------------------------------------------------------------------ -template class L, +template class L, template class> class N, template class T> -void SSFClient::do_ssf_start(p_socket_type p_socket, - const boost::system::error_code& ec) { +void SSFClient::DoSSFStart(p_socket_type p_socket, + const boost::system::error_code& ec) { Notify(ssf::services::initialisation::NETWORK, nullptr, ec); if (!ec) { BOOST_LOG_TRIVIAL(trace) << "client: SSF reply ok"; boost::system::error_code ec2; - this->do_fiberize_(p_socket, ec2); + this->DoFiberize(p_socket, ec2); Notify(ssf::services::initialisation::TRANSPORT, nullptr, ec); } else { @@ -119,18 +108,18 @@ void SSFClient::do_ssf_start(p_socket_type p_socket, } } -template class L, +template class L, template class> class N, template class T> -void SSFClient::do_fiberize_(p_socket_type p_socket, - boost::system::error_code& ec) { +void SSFClient::DoFiberize(p_socket_type p_socket, + boost::system::error_code& ec) { // Register supported admin commands services::admin::CreateServiceRequest::RegisterToCommandFactory(); services::admin::StopServiceRequest::RegisterToCommandFactory(); services::admin::ServiceStatus::RegisterToCommandFactory(); - fiber_demux_.fiberize(std::move(*p_socket)); + auto close_demux_handler = [this]() { this->OnDemuxClose(); }; + fiber_demux_.fiberize(std::move(*p_socket), close_demux_handler); // Make a new service manager auto p_service_manager = std::make_shared>(); @@ -142,14 +131,20 @@ void SSFClient::do_fiberize_(p_socket_type p_socket, // Register supported micro services services::socks::SocksServer::RegisterToServiceFactory( p_service_factory); - services::fibers_to_sockets::RemoteForwarderService< - demux>::RegisterToServiceFactory(p_service_factory); - services::sockets_to_fibers::LocalForwarderService< - demux>::RegisterToServiceFactory(p_service_factory); + services::fibers_to_sockets::FibersToSockets::RegisterToServiceFactory( + p_service_factory); + services::sockets_to_fibers::SocketsToFibers::RegisterToServiceFactory( + p_service_factory); services::fibers_to_datagrams::FibersToDatagrams< demux>::RegisterToServiceFactory(p_service_factory); services::datagrams_to_fibers::DatagramsToFibers< demux>::RegisterToServiceFactory(p_service_factory); + services::copy_file::file_to_fiber::FileToFiber< + demux>::RegisterToServiceFactory(p_service_factory); + services::copy_file::fiber_to_file::FiberToFile< + demux>::RegisterToServiceFactory(p_service_factory); + services::copy_file::file_enquirer::FileEnquirer< + demux>::RegisterToServiceFactory(p_service_factory); // Start the admin micro service std::map empty_map; @@ -161,6 +156,19 @@ void SSFClient::do_fiberize_(p_socket_type p_socket, } //------------------------------------------------------------------------------ +template class L, + template class> class N, + template class T> +void SSFClient::OnDemuxClose() { + auto p_service_factory = + ServiceFactoryManager::GetServiceFactory(&fiber_demux_); + if (p_service_factory) { + p_service_factory->Destroy(); + } + Notify(ssf::services::initialisation::CLOSE, nullptr, + boost::system::error_code()); +} + } // ssf #endif // SSF_CORE_CLIENT_CLIENT_IPP_ diff --git a/src/core/factories/service_factory.h b/src/core/factories/service_factory.h index 8c199fbc..b39c872a 100644 --- a/src/core/factories/service_factory.h +++ b/src/core/factories/service_factory.h @@ -25,8 +25,8 @@ class ServiceFactory : public std::enable_shared_from_this typedef std::function ServiceCreatorType; - typedef std::map ServiceCreatorMap; + Parameters)> ServiceCreator; + typedef std::map ServiceCreatorMap; typedef std::shared_ptr> ServiceManagerPtr; @@ -47,8 +47,7 @@ class ServiceFactory : public std::enable_shared_from_this ~ServiceFactory() {} - bool RegisterServiceCreator(uint32_t index, - ServiceCreatorType creator) { + bool RegisterServiceCreator(uint32_t index, ServiceCreator creator) { boost::recursive_mutex::scoped_lock lock(service_creators_mutex_); if (service_creators_.count(index)) { return false; @@ -71,11 +70,16 @@ class ServiceFactory : public std::enable_shared_from_this demux_, parameters); if (p_service) { - return p_service_manager_->start(p_service, ec); + auto service_id = p_service_manager_->start(p_service, ec); + p_service->set_local_id(service_id); + + return service_id; } else { + ec.assign(ssf::error::service_not_started, ssf::error::get_ssf_category()); return 0; } } else { + ec.assign(ssf::error::service_not_found, ssf::error::get_ssf_category()); return 0; } } diff --git a/src/core/factories/service_option_factory.h b/src/core/factories/service_option_factory.h index 742be852..96f9c803 100644 --- a/src/core/factories/service_option_factory.h +++ b/src/core/factories/service_option_factory.h @@ -69,9 +69,9 @@ class ServiceOptionFactory { return desc; } - static std::shared_ptr> ParseServiceLine(std::string option, - std::string parameters, - boost::system::error_code& ec) { + static std::shared_ptr> + ParseServiceLine(std::string option, std::string parameters, + boost::system::error_code& ec) { boost::recursive_mutex::scoped_lock lock(service_options_mutex_); auto it = service_options_.find(option); diff --git a/src/core/network_virtual_layer_policies/bounce_protocol_policy.h b/src/core/network_virtual_layer_policies/bounce_protocol_policy.h index afe7ed47..705eb48a 100644 --- a/src/core/network_virtual_layer_policies/bounce_protocol_policy.h +++ b/src/core/network_virtual_layer_policies/bounce_protocol_policy.h @@ -11,7 +11,6 @@ #include #include - #include #include #include @@ -36,8 +35,9 @@ #include "common/network/base_session.h" #include "common/network/session_forwarder.h" -#include "versions.h" +#include "core/parser/bounce_parser.h" +#include "versions.h" namespace ssf { @@ -53,6 +53,7 @@ class BounceProtocolPolicy typedef std::map Parameters; private: + using BounceParser = ssf::parser::BounceParser; typedef std::shared_ptr p_uint32_t; typedef std::shared_ptr> p_vector_uint32_t; typedef std::vector vector_error_code_type; @@ -75,8 +76,8 @@ class BounceProtocolPolicy : LinkPolicy(io_service, ssf_config), io_service_(io_service) {} - void add_route(Parameters& parameters, callback_type callback) { - std::list bouncing_nodes = this->get_bouncing_nodes(parameters); + void AddRoute(Parameters& parameters, callback_type callback) { + std::list bouncing_nodes = this->GetBouncingNodes(parameters); parameters["local"] = "true"; size_t total_size = bouncing_nodes.size() + 1; @@ -84,7 +85,7 @@ class BounceProtocolPolicy auto handler = [this, parameters, p_ec_values, total_size]( p_uint32_t p_ec_value, p_socket_type p_socket, callback_type callback) { - this->get_all_ecs(parameters, p_ec_values, 0, (uint32_t)total_size, p_ec_value, p_socket, + this->GetAllEcs(parameters, p_ec_values, 0, (uint32_t)total_size, p_ec_value, p_socket, callback); }; @@ -93,26 +94,26 @@ class BounceProtocolPolicy const boost::system::error_code& ec) { if (!ec) { BOOST_LOG_TRIVIAL(trace) << "network: do add route"; - this->do_add_route(handler, parameters, callback); + this->DoAddRoute(handler, parameters, callback); } else { BOOST_LOG_TRIVIAL(trace) << "network: handler to add route end"; - this->protocol_end(nullptr, ec, callback); + this->ProtocolEnd(nullptr, ec, callback); } }; - this->get_credentials(parameters, handler_to_do_add_route, nullptr); + this->GetCredentials(parameters, handler_to_do_add_route, nullptr); } - void delete_route(socket_type& socket) { + void DeleteRoute(socket_type& socket) { BOOST_LOG_TRIVIAL(trace) << "network: delete route"; - this->close_link(socket); + this->CloseLink(socket); } - void accept_new_routes(uint16_t port, callback_type callback) { + void AcceptNewRoutes(uint16_t port, callback_type callback) { auto p_acceptor = std::make_shared(io_service_); boost::system::error_code ec; - init_acceptor(*p_acceptor, port, ec); + InitAcceptor(*p_acceptor, port, ec); if (!ec) { { @@ -120,17 +121,17 @@ class BounceProtocolPolicy acceptors_[port] = p_acceptor; } - this->accept_links( + this->AcceptLinks( p_acceptor, - boost::bind(&BounceProtocolPolicy::new_link_connected_handler, this, + boost::bind(&BounceProtocolPolicy::NewLinkConnectedHandler, this, callback, _1)); } else { auto p_socket = p_socket_type(nullptr); - this->protocol_end(p_socket, ec, callback); + this->ProtocolEnd(p_socket, ec, callback); } } - void stop_accepting_routes() { + void StopAcceptingRoutes() { boost::recursive_mutex::scoped_lock lock(acceptors_mutex_); for (auto& p_acceptor : acceptors_) { boost::system::error_code ec; @@ -143,7 +144,7 @@ class BounceProtocolPolicy //------------------------------------------------------- private: - static void init_acceptor(acceptor_type& acceptor, uint16_t port, + static void InitAcceptor(acceptor_type& acceptor, uint16_t port, boost::system::error_code& ec) { boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); boost::asio::socket_base::reuse_address option(true); @@ -173,7 +174,7 @@ class BounceProtocolPolicy } } - static void close_acceptor(acceptor_type& acceptor) { + static void CloseAcceptor(acceptor_type& acceptor) { boost::system::error_code ec; acceptor.cancel(ec); acceptor.close(ec); @@ -185,17 +186,17 @@ class BounceProtocolPolicy //------------------------------------------------------- template - void do_add_route(Handler handler, const Parameters& parameters, + void DoAddRoute(Handler handler, const Parameters& parameters, callback_type callback) { BOOST_LOG_TRIVIAL(trace) << "network: establish link"; - this->establish_link( + this->EstablishLink( parameters, - boost::bind(&BounceProtocolPolicy::link_established_handler, + boost::bind(&BounceProtocolPolicy::LinkEstablishedHandler, this, handler, parameters, callback, _1, _2)); } template - void link_established_handler(Handler handler, const Parameters& parameters, + void LinkEstablishedHandler(Handler handler, const Parameters& parameters, callback_type callback, p_socket_type p_socket, const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "network: link established handler"; @@ -205,20 +206,20 @@ class BounceProtocolPolicy boost::asio::async_read( *p_socket, boost::asio::buffer(p_version.get(), sizeof(*p_version)), boost::bind( - &BounceProtocolPolicy::bounce_version_received_handler, + &BounceProtocolPolicy::BounceVersionReceivedHandler, this, handler, parameters, callback, p_version, p_socket, _1, _2)); } else { if (p_socket) { - this->close_link(*p_socket); + this->CloseLink(*p_socket); } - this->protocol_end(nullptr, ec, callback); + this->ProtocolEnd(nullptr, ec, callback); return; } } template - void bounce_version_received_handler( + void BounceVersionReceivedHandler( Handler handler, const Parameters& parameters, callback_type callback, std::shared_ptr p_version, p_socket_type p_socket, const boost::system::error_code& ec, size_t length) { @@ -230,7 +231,7 @@ class BounceProtocolPolicy boost::asio::async_write( *p_socket, boost::asio::buffer(p_answer.get(), sizeof(*p_answer)), boost::bind( - &BounceProtocolPolicy::bounce_answer_sent_handler, + &BounceProtocolPolicy::BounceAnswerSentHandler, this, handler, parameters, callback, p_answer, p_socket, _1, _2)); } else { @@ -238,21 +239,21 @@ class BounceProtocolPolicy << *p_version; boost::system::error_code result_ec(ssf::error::wrong_protocol_type, ssf::error::get_ssf_category()); - this->close_link(*p_socket); - this->protocol_end(nullptr, result_ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, result_ec, callback); return; } } else { BOOST_LOG_TRIVIAL(error) << "network: bounce version NOT received " << ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, ec, callback); return; } } template - void bounce_answer_sent_handler(Handler handler, const Parameters& parameters, + void BounceAnswerSentHandler(Handler handler, const Parameters& parameters, callback_type callback, std::shared_ptr p_answer, p_socket_type p_socket, @@ -263,7 +264,7 @@ class BounceProtocolPolicy if (*p_answer) { BOOST_LOG_TRIVIAL(info) << "network: bounce answer OK"; - std::list bouncing_nodes = this->get_bouncing_nodes(parameters); + std::list bouncing_nodes = this->GetBouncingNodes(parameters); std::ostringstream ostrs; boost::archive::text_oarchive ar(ostrs); @@ -278,7 +279,7 @@ class BounceProtocolPolicy *p_socket, boost::asio::buffer(p_bounce_size.get(), sizeof(*p_bounce_size)), boost::bind( - &BounceProtocolPolicy::sent_bounce_size_handler, this, + &BounceProtocolPolicy::SentBounceSizeHandler, this, handler, result, bouncing_nodes.size(), p_bounce_size, p_socket, callback, _1, _2)); } else { @@ -286,21 +287,21 @@ class BounceProtocolPolicy ssf::error::get_ssf_category()); BOOST_LOG_TRIVIAL(error) << "network: bounce answer NOT ok " << result_ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, result_ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, result_ec, callback); return; } } else { BOOST_LOG_TRIVIAL(error) << "network: could NOT send Bounce answer " << ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, ec, callback); return; } } template - void sent_bounce_size_handler(Handler handler, std::string result, + void SentBounceSizeHandler(Handler handler, std::string result, size_t bounce_number, p_uint32_t p_bounce_size, p_socket_type p_socket, callback_type callback, const boost::system::error_code& ec, @@ -313,56 +314,56 @@ class BounceProtocolPolicy boost::asio::async_write( *p_socket, p_buf->data(), boost::bind( - &BounceProtocolPolicy::sent_bouncing_nodes_handler, this, + &BounceProtocolPolicy::SentBouncingNodesHandler, this, handler, bounce_number, p_buf, p_socket, callback, _1, _2)); } else { - this->close_link(*p_socket); - protocol_end(p_socket, ec, callback); + this->CloseLink(*p_socket); + ProtocolEnd(p_socket, ec, callback); } } template - void sent_bouncing_nodes_handler(Handler handler, size_t bounce_number, + void SentBouncingNodesHandler(Handler handler, size_t bounce_number, p_streambuf p_buf, p_socket_type p_socket, callback_type callback, const boost::system::error_code& ec, size_t length) { if (!ec) { - this->receive_one_ec(handler, p_socket, callback); + this->ReceiveOneEc(handler, p_socket, callback); } else { - this->close_link(*p_socket); - this->protocol_end(p_socket, ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(p_socket, ec, callback); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template - void receive_one_ec(Handler handler, p_socket_type p_socket, + void ReceiveOneEc(Handler handler, p_socket_type p_socket, callback_type callback) { auto p_ec_value = std::make_shared(0); BOOST_LOG_TRIVIAL(trace) << "network: bounce protocol receive one ec async read some"; boost::asio::async_read( *p_socket, boost::asio::buffer(p_ec_value.get(), sizeof(*p_ec_value)), - boost::bind(&BounceProtocolPolicy::received_one_ec_handler, this, + boost::bind(&BounceProtocolPolicy::ReceivedOneEcHandler, this, handler, p_ec_value, p_socket, callback, _1, _2)); } template - void received_one_ec_handler(Handler handler, p_uint32_t p_ec_value, + void ReceivedOneEcHandler(Handler handler, p_uint32_t p_ec_value, p_socket_type p_socket, callback_type callback, const boost::system::error_code& ec, size_t length) { if (!ec) { handler(p_ec_value, p_socket, callback); } else { - this->close_link(*p_socket); + this->CloseLink(*p_socket); *p_ec_value = ec.value(); handler(p_ec_value, p_socket_type(nullptr), callback); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - void get_all_ecs(const Parameters& parameters, p_vector_uint32_t p_ec_values, + void GetAllEcs(const Parameters& parameters, p_vector_uint32_t p_ec_values, uint32_t already_done, uint32_t total_size, p_uint32_t p_ec_value, p_socket_type p_socket, callback_type callback) { @@ -378,15 +379,15 @@ class BounceProtocolPolicy const Parameters& parameters, p_socket_type p_socket, const boost::system::error_code& ec) { if (!ec) { - this->receive_one_ec< + this->ReceiveOneEc< std::function>( - boost::bind(&BounceProtocolPolicy::get_all_ecs, this, + boost::bind(&BounceProtocolPolicy::GetAllEcs, this, parameters, p_ec_values, already_done + 1, total_size, _1, _2, _3), p_socket, callback); } else { (*p_ec_values)[already_done] = ec.value(); - this->protocol_end(p_socket, p_ec_values, callback); + this->ProtocolEnd(p_socket, p_ec_values, callback); } }; @@ -394,12 +395,12 @@ class BounceProtocolPolicy params["bouncing_nodes"] = parameters.find("bouncing_nodes")->second; params["node_id"] = std::to_string(already_done); - this->set_credentials(params, handler, p_socket); + this->SetCredentials(params, handler, p_socket); } else { - this->protocol_end(p_socket, p_ec_values, callback); + this->ProtocolEnd(p_socket, p_ec_values, callback); } } else { - this->protocol_end(p_socket, p_ec_values, callback); + this->ProtocolEnd(p_socket, p_ec_values, callback); } } @@ -410,33 +411,33 @@ class BounceProtocolPolicy //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template - void send_one_ec(Handler handler, p_uint32_t p_ec_value, + void SendOneEc(Handler handler, p_uint32_t p_ec_value, p_socket_type p_socket, callback_type callback) { boost::asio::async_write( *p_socket, boost::asio::buffer(p_ec_value.get(), sizeof(*p_ec_value)), - boost::bind(&BounceProtocolPolicy::sent_one_ec_handler, this, + boost::bind(&BounceProtocolPolicy::SentOneEcHandler, this, p_ec_value, p_socket, handler, callback, _1, _2)); } template - void sent_one_ec_handler(p_uint32_t p_ec_value, p_socket_type p_socket, + void SentOneEcHandler(p_uint32_t p_ec_value, p_socket_type p_socket, Handler handler, callback_type callback, const boost::system::error_code& ec, size_t length) { if (!ec) { handler(p_socket, callback); } else { - this->close_link(*p_socket); - this->protocol_end(p_socket, ec, callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(p_socket, ec, callback); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //------------------------------------------------------- - void new_link_connected_handler(callback_type callback, p_socket_type p_socket) { + void NewLinkConnectedHandler(callback_type callback, p_socket_type p_socket) { if (!p_socket) { boost::system::error_code ec(ssf::error::not_a_socket, ssf::error::get_ssf_category()); - this->protocol_end(nullptr, vector_error_code_type(1, ec), callback); + this->ProtocolEnd(nullptr, vector_error_code_type(1, ec), callback); return; } @@ -446,11 +447,11 @@ class BounceProtocolPolicy boost::asio::async_write( *p_socket, boost::asio::buffer(p_version.get(), sizeof(*p_version)), - boost::bind(&BounceProtocolPolicy::bounce_version_sent_handler, this, + boost::bind(&BounceProtocolPolicy::BounceVersionSentHandler, this, callback, p_version, p_socket, _1, _2)); } - void bounce_version_sent_handler(callback_type callback, + void BounceVersionSentHandler(callback_type callback, std::shared_ptr p_version, p_socket_type p_socket, const boost::system::error_code& ec, @@ -462,18 +463,18 @@ class BounceProtocolPolicy boost::asio::async_read( *p_socket, boost::asio::buffer(p_answer.get(), sizeof(*p_answer)), - boost::bind(&BounceProtocolPolicy::bounce_anwser_received_handler, + boost::bind(&BounceProtocolPolicy::BounceAnwserReceivedHandler, this, callback, p_answer, p_socket, _1, _2)); } else { BOOST_LOG_TRIVIAL(error) << "network: could NOT send the Bounce request " << ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, vector_error_code_type(1, ec), callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, vector_error_code_type(1, ec), callback); return; } } - void bounce_anwser_received_handler(callback_type callback, + void BounceAnwserReceivedHandler(callback_type callback, std::shared_ptr p_answer, p_socket_type p_socket, const boost::system::error_code& ec, @@ -488,27 +489,27 @@ class BounceProtocolPolicy boost::asio::async_read( *p_socket, boost::asio::buffer(p_bounce_size.get(), sizeof(*p_bounce_size)), - boost::bind(&BounceProtocolPolicy::received_bounce_size_handler, + boost::bind(&BounceProtocolPolicy::ReceivedBounceSizeHandler, this, p_bounce_size, p_socket, callback, _1, _2)); } else { boost::system::error_code result_ec(ssf::error::wrong_protocol_type, ssf::error::get_ssf_category()); BOOST_LOG_TRIVIAL(error) << "network: bounce anwser NOT ok " << ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, vector_error_code_type(1, result_ec), + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, vector_error_code_type(1, result_ec), callback); return; } } else { BOOST_LOG_TRIVIAL(error) << "network: could NOT receive the Bounce anwser " << ec.message(); - this->close_link(*p_socket); - this->protocol_end(nullptr, vector_error_code_type(1, ec), callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(nullptr, vector_error_code_type(1, ec), callback); return; } } - void received_bounce_size_handler(p_uint32_t p_bounce_size, + void ReceivedBounceSizeHandler(p_uint32_t p_bounce_size, p_socket_type p_socket, callback_type callback, const boost::system::error_code& ec, @@ -521,15 +522,15 @@ class BounceProtocolPolicy BOOST_LOG_TRIVIAL(trace) << "network: bounce protocol receive bounce size"; boost::asio::async_read( *p_socket, bufs, - boost::bind(&BounceProtocolPolicy::received_bouncing_nodes_handler, + boost::bind(&BounceProtocolPolicy::ReceivedBouncingNodesHandler, this, p_buffer, p_socket, callback, _1, _2)); } else { - this->close_link(*p_socket); - this->protocol_end(p_socket, vector_error_code_type(1, ec), callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(p_socket, vector_error_code_type(1, ec), callback); } } - void received_bouncing_nodes_handler(p_streambuf p_buf, + void ReceivedBouncingNodesHandler(p_streambuf p_buf, p_socket_type p_socket, callback_type callback, const boost::system::error_code& ec, @@ -545,14 +546,14 @@ class BounceProtocolPolicy auto p_ec_value = std::make_shared(ec.value()); - send_one_ec>( - boost::bind(&BounceProtocolPolicy::establish_route, this, + SendOneEc>( + boost::bind(&BounceProtocolPolicy::EstablishRoute, this, bouncing_nodes, _1, _2), p_ec_value, p_socket, callback); return; } catch (const std::exception&) { - this->close_link(*p_socket); - this->protocol_end( + this->CloseLink(*p_socket); + this->ProtocolEnd( p_socket, vector_error_code_type( 1, boost::system::error_code(ssf::error::protocol_error, @@ -561,31 +562,31 @@ class BounceProtocolPolicy return; } } else { - this->close_link(*p_socket); - this->protocol_end(p_socket, vector_error_code_type(1, ec), callback); + this->CloseLink(*p_socket); + this->ProtocolEnd(p_socket, vector_error_code_type(1, ec), callback); return; } } - void establish_route(const std::list& bouncing_nodes, + void EstablishRoute(const std::list& bouncing_nodes, p_socket_type p_socket, callback_type callback) { if (!bouncing_nodes.size()) { - this->protocol_end(p_socket, 0, callback); + this->ProtocolEnd(p_socket, 0, callback); } else { - this->forward_link(bouncing_nodes, p_socket); + this->ForwardLink(bouncing_nodes, p_socket); } } //------------------------------------------------------- - void forward_link(std::list bouncing_nodes, + void ForwardLink(std::list bouncing_nodes, p_socket_type p_socket_in) { - std::string remote_endpoint_string = this->pop_endpoint_string(bouncing_nodes); - std::string remote_addr = this->get_remote_addr(remote_endpoint_string); - std::string remote_port = this->get_remote_port(remote_endpoint_string); + std::string remote_endpoint_string = this->PopEndpointString(bouncing_nodes); + std::string remote_addr = BounceParser::GetRemoteAddress(remote_endpoint_string); + std::string remote_port = BounceParser::GetRemotePort(remote_endpoint_string); if (remote_addr == "" || remote_port == "") { - this->close_link(*p_socket_in); + this->CloseLink(*p_socket_in); return; } BOOST_LOG_TRIVIAL(trace) << "network: forward link " << remote_addr << ":" << remote_port; @@ -603,7 +604,7 @@ class BounceProtocolPolicy auto callback = [this, p_socket_in](p_socket_type p_socket_out, vector_error_code_type v_ec) { if (v_ec[0]) { - this->close_link(*p_socket_in); + this->CloseLink(*p_socket_in); } }; @@ -612,9 +613,9 @@ class BounceProtocolPolicy p_socket_type p_socket_in, callback_type) { if (p_socket_in && p_socket_out) { - this->establish_session(p_socket_in, p_socket_out); + this->EstablishSession(p_socket_in, p_socket_out); } else { - this->close_link(*p_socket_in); + this->CloseLink(*p_socket_in); } }; @@ -622,7 +623,7 @@ class BounceProtocolPolicy handler_to_establish_session]( p_uint32_t p_ec_value, p_socket_type p_socket_out, callback_type callback) { - this->send_one_ec>( + this->SendOneEc>( boost::bind(handler_to_establish_session, p_socket_out, _1, _2), p_ec_value, p_socket_in, callback); }; @@ -632,18 +633,18 @@ class BounceProtocolPolicy Parameters parameters, p_socket_type p_socket_in, const boost::system::error_code& ec) { if (!ec) { - this->do_add_route(handler_to_send_one_ec, parameters, callback); + this->DoAddRoute(handler_to_send_one_ec, parameters, callback); } else { auto p_ec_value = std::make_shared(ec.value()); handler_to_send_one_ec(p_ec_value, p_socket_type(nullptr), callback); - //this->protocol_end(p_socket_in, ec, callback); + //this->ProtocolEnd(p_socket_in, ec, callback); } }; - this->get_credentials(parameters, handler_to_do_add_route, p_socket_in); + this->GetCredentials(parameters, handler_to_do_add_route, p_socket_in); } - void establish_session(p_socket_type p_socket_in, p_socket_type p_socket_out) { + void EstablishSession(p_socket_type p_socket_in, p_socket_type p_socket_out) { boost::system::error_code ec; // ! Can't std::move ssl stream ! // @@ -653,19 +654,19 @@ class BounceProtocolPolicy } //------------------------------------------------------- - void protocol_end(p_socket_type p_socket, const boost::system::error_code& ec, + void ProtocolEnd(p_socket_type p_socket, const boost::system::error_code& ec, callback_type callback) { - this->protocol_end(p_socket, vector_error_code_type(1, ec), callback); + this->ProtocolEnd(p_socket, vector_error_code_type(1, ec), callback); } - void protocol_end(p_socket_type p_socket, uint32_t ec_value, + void ProtocolEnd(p_socket_type p_socket, uint32_t ec_value, callback_type callback) { boost::system::error_code ec(ec_value, boost::system::system_category()); - this->protocol_end(p_socket, ec, callback); + this->ProtocolEnd(p_socket, ec, callback); } - void protocol_end(p_socket_type p_socket, p_vector_uint32_t p_status, + void ProtocolEnd(p_socket_type p_socket, p_vector_uint32_t p_status, callback_type callback) { vector_error_code_type v_ec; for (size_t i = 0; i < p_status->size(); ++i) { @@ -673,10 +674,10 @@ class BounceProtocolPolicy (*p_status)[i], boost::system::system_category())); } - this->protocol_end(p_socket, v_ec, callback); + this->ProtocolEnd(p_socket, v_ec, callback); } - void protocol_end(p_socket_type p_socket, vector_error_code_type v_ec, + void ProtocolEnd(p_socket_type p_socket, vector_error_code_type v_ec, callback_type callback) { io_service_.post(boost::bind(callback, p_socket, v_ec)); } @@ -716,30 +717,6 @@ class BounceProtocolPolicy (serialization == boost::archive::BOOST_ARCHIVE_VERSION()); } - //------------------------------------------------------- - - std::string get_remote_addr(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(0, position); - } else { - return ""; - } - } - - std::string get_remote_port(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(position + 1); - } else { - return ""; - } - } - - //------------------------------------------------------- - private: boost::asio::io_service& io_service_; diff --git a/src/core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h b/src/core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h index f7dd4602..f5b6d8b4 100644 --- a/src/core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h +++ b/src/core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -28,33 +29,32 @@ class NullLinkAuthenticationPolicy { callback_type; public: - void get_credentials(Parameters& parameters, callback_type callback, - p_socket_type p_socket) { + void GetCredentials(Parameters& parameters, callback_type callback, + p_socket_type p_socket) { auto p_value = std::make_shared(0); if (parameters["local"] == "true") { callback(parameters, p_socket, boost::system::error_code()); } else { boost::asio::async_write( - *p_socket, - boost::asio::buffer(p_value.get(), sizeof(*p_value)), - boost::bind(&NullLinkAuthenticationPolicy:: - remote_connection_established_handler, - this, parameters, callback, p_value, p_socket, _1, _2)); + *p_socket, boost::asio::buffer(p_value.get(), sizeof(*p_value)), + boost::bind( + &NullLinkAuthenticationPolicy::RemoteConnectionEstablishedHandler, + this, parameters, callback, p_value, p_socket, _1, _2)); } } - void set_credentials(const Parameters& parameters, callback_type callback, + void SetCredentials(const Parameters& parameters, callback_type callback, p_socket_type p_socket) { auto p_value = std::make_shared(0); boost::asio::async_read( *p_socket, boost::asio::buffer(p_value.get(), sizeof(*p_value)), boost::bind( - &NullLinkAuthenticationPolicy::next_connection_established_handler, + &NullLinkAuthenticationPolicy::NextConnectionEstablishedHandler, this, parameters, callback, p_value, p_socket, _1, _2)); } - std::list get_bouncing_nodes(const Parameters& parameters) { + std::list GetBouncingNodes(const Parameters& parameters) { if (parameters.count("bouncing_nodes")) { auto serialized_list = parameters.find("bouncing_nodes")->second; @@ -73,7 +73,7 @@ class NullLinkAuthenticationPolicy { } } - std::string pop_endpoint_string(std::list& bouncing_nodes) { + std::string PopEndpointString(std::list& bouncing_nodes) { if (bouncing_nodes.size()) { auto first = bouncing_nodes.front(); bouncing_nodes.pop_front(); @@ -84,7 +84,7 @@ class NullLinkAuthenticationPolicy { } private: - void remote_connection_established_handler(const Parameters& parameters, + void RemoteConnectionEstablishedHandler(const Parameters& parameters, callback_type callback, p_uint32_t p_value, p_socket_type p_socket, @@ -93,7 +93,7 @@ class NullLinkAuthenticationPolicy { callback(parameters, p_socket, ec); } - void next_connection_established_handler(const Parameters& parameters, + void NextConnectionEstablishedHandler(const Parameters& parameters, callback_type callback, p_uint32_t p_value, p_socket_type p_socket, diff --git a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h index 2af7c177..70da68a0 100644 --- a/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h +++ b/src/core/network_virtual_layer_policies/link_policies/ssl_policy.h @@ -10,12 +10,14 @@ #include #include -#include -#include +#include +#include #include #include -#include +#include +#include #include +#include #include #include @@ -63,14 +65,14 @@ class SSLWrapperPuller } /// Start receiving data - void start_pulling() { + void StartPulling() { { boost::recursive_mutex::scoped_lock lock(pulling_mutex_); if (!pulling_) { pulling_ = true; BOOST_LOG_TRIVIAL(debug) << "link: SSLWrapperPuller pulling"; io_service_.post( - boost::bind(&SSLWrapperPuller::async_pull_packets, + boost::bind(&SSLWrapperPuller::AsyncPullPackets, this->shared_from_this())); } } @@ -99,7 +101,7 @@ class SSLWrapperPuller p.v = p.p = 0; io_service_.dispatch( - boost::bind(&SSLWrapperPuller::handle_data_n_ops, + boost::bind(&SSLWrapperPuller::HandleDataNOps, this->shared_from_this())); } else { auto lambda = @@ -114,12 +116,12 @@ class SSLWrapperPuller pulling_(false) {} /// Check if data is available for user requests - void handle_data_n_ops() { + void HandleDataNOps() { if (!status_) { { boost::recursive_mutex::scoped_lock lock(pulling_mutex_); if ((data_queue_.size() < lower_queue_size_bound) && !pulling_) { - this->start_pulling(); + this->StartPulling(); } } @@ -136,7 +138,7 @@ class SSLWrapperPuller io_service_.post(do_complete); io_service_.dispatch( - boost::bind(&SSLWrapperPuller::handle_data_n_ops, + boost::bind(&SSLWrapperPuller::HandleDataNOps, this->shared_from_this())); } } else { @@ -151,19 +153,19 @@ class SSLWrapperPuller io_service_.post(do_complete); io_service_.dispatch( - boost::bind(&SSLWrapperPuller::handle_data_n_ops, + boost::bind(&SSLWrapperPuller::HandleDataNOps, this->shared_from_this())); } } } /// Receive some data - void async_pull_packets() { - BOOST_LOG_TRIVIAL(trace) << "link: SSLWrapperPuller async_pull_packets"; + void AsyncPullPackets() { + BOOST_LOG_TRIVIAL(trace) << "link: SSLWrapperPuller AsyncPullPackets"; auto self = this->shared_from_this(); auto handler = [this, self](const boost::system::error_code &ec, size_t length) { - BOOST_LOG_TRIVIAL(trace) << "link: SSLWrapperPuller async_pull_packets handler"; + BOOST_LOG_TRIVIAL(trace) << "link: SSLWrapperPuller AsyncPullPackets handler"; if (!ec) { { boost::recursive_mutex::scoped_lock lock1(this->data_queue_mutex_); @@ -171,7 +173,7 @@ class SSLWrapperPuller } this->io_service_.dispatch( - boost::bind(&SSLWrapperPuller::async_pull_packets, + boost::bind(&SSLWrapperPuller::AsyncPullPackets, this->shared_from_this())); } else { this->status_ = ec; @@ -180,7 +182,7 @@ class SSLWrapperPuller } this->io_service_.dispatch( - boost::bind(&SSLWrapperPuller::handle_data_n_ops, + boost::bind(&SSLWrapperPuller::HandleDataNOps, this->shared_from_this())); }; @@ -277,7 +279,7 @@ template class SSLWrapper { auto do_user_handler = [this, handler](const boost::system::error_code &ec) { if (!ec) { - this->p_puller_->start_pulling(); + this->p_puller_->StartPulling(); } handler(ec); }; @@ -378,11 +380,11 @@ class BaseSSLPolicy { : io_service_(io_service), config_(ssf_config) {} private: - bool init_ssl_context(boost::asio::ssl::context &ctx, bool is_server) { + bool InitTLSContext(boost::asio::ssl::context &ctx, bool is_server) { // Set the callback to decipher the private key if (is_server || (config_.tls.key_password != "")) { ctx.set_password_callback( - boost::bind(&BaseSSLPolicy::get_password, this, _1, _2)); + boost::bind(&BaseSSLPolicy::GetPassword, this, _1, _2)); } // Set the mutual authentication @@ -440,13 +442,13 @@ class BaseSSLPolicy { public: /// Connect to a remote server - void establish_link(const Parameters ¶meters, + void EstablishLink(const Parameters ¶meters, const connect_callback_type &connect_callback) { - auto addr = get_remote_addr(parameters); - auto port = get_remote_port(parameters); - auto auth_cert = get_auth_cert_in_vector(parameters); - auto cert = get_cert_in_vector(parameters); - auto key = get_key_in_vector(parameters); + auto addr = GetRemoteAddr(parameters); + auto port = GetRemotePort(parameters); + auto auth_cert = GetAuthCertInVector(parameters); + auto cert = GetCertInVector(parameters); + auto key = GetKeyInVector(parameters); BOOST_LOG_TRIVIAL(info) << "link: connecting to " << addr << ":" << port; @@ -454,12 +456,14 @@ class BaseSSLPolicy { boost::asio::ssl::context::tlsv12); // Initialize the ssl context with enhanced security parameters - auto ctx_set = this->init_ssl_context(*p_ctx, false); + auto ctx_set = this->InitTLSContext(*p_ctx, false); if (!ctx_set) { + BOOST_LOG_TRIVIAL(error) << "TLS context not initialized"; + BOOST_LOG_TRIVIAL(error) << "Check your configuration"; boost::system::error_code ec(ssf::error::invalid_argument, ssf::error::get_ssf_category()); - this->to_next_layer_handler(p_socket_type(nullptr), connect_callback, ec); + this->ToNextLayerHandler(p_socket_type(nullptr), connect_callback, ec); return; } @@ -524,7 +528,7 @@ class BaseSSLPolicy { << port; boost::system::error_code ec(ssf::error::invalid_argument, ssf::error::get_ssf_category()); - this->to_next_layer_handler(p_socket_type(nullptr), connect_callback, + this->ToNextLayerHandler(p_socket_type(nullptr), connect_callback, ec); return; } @@ -532,19 +536,19 @@ class BaseSSLPolicy { auto p_socket = std::make_shared(io_service_, p_ctx); boost::asio::async_connect(p_socket->lowest_layer(), iterator, - boost::bind(&BaseSSLPolicy::connected_handler, + boost::bind(&BaseSSLPolicy::ConnectedHandler, this, p_socket, connect_callback, _1)); } else { boost::system::error_code ec(ssf::error::invalid_argument, ssf::error::get_ssf_category()); - this->to_next_layer_handler(p_socket_type(nullptr), connect_callback, ec); + this->ToNextLayerHandler(p_socket_type(nullptr), connect_callback, ec); return; } } /// Accept a new connection - void accept_links(p_acceptor_type p_acceptor, + void AcceptLinks(p_acceptor_type p_acceptor, const accept_callback_type &accept_callback) { if (!p_acceptor->is_open()) { @@ -555,10 +559,12 @@ class BaseSSLPolicy { boost::asio::ssl::context::tlsv12); // Initialize the ssl context with enhanced security parameters - auto ctx_set = this->init_ssl_context(*p_ctx, true); + auto ctx_set = this->InitTLSContext(*p_ctx, true); if (!ctx_set) { - this->to_next_layer_handler(nullptr, accept_callback); + BOOST_LOG_TRIVIAL(error) << "TLS context not initialized"; + BOOST_LOG_TRIVIAL(error) << "Check your configuration"; + this->ToNextLayerHandler(nullptr, accept_callback); return; } @@ -570,12 +576,12 @@ class BaseSSLPolicy { BOOST_LOG_TRIVIAL(trace) << "link: accepting"; p_acceptor->async_accept(p_socket->lowest_layer(), - boost::bind(&BaseSSLPolicy::accepted_handler, this, + boost::bind(&BaseSSLPolicy::AcceptedHandler, this, p_acceptor, p_socket, accept_callback, _1)); } - void close_link(socket_type &socket) { + void CloseLink(socket_type &socket) { boost::system::error_code ec; socket.socket().shutdown(ec); socket.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); @@ -584,7 +590,7 @@ class BaseSSLPolicy { } private: - void connected_handler(p_socket_type p_socket, + void ConnectedHandler(p_socket_type p_socket, const connect_callback_type &connect_callback, const boost::system::error_code &ec) { // Send version @@ -592,18 +598,18 @@ class BaseSSLPolicy { std::shared_ptr p_version = std::make_shared(GetVersion()); /*boost::asio::async_write(p_socket->socket().next_layer(), boost::asio::buffer(p_version.get(), sizeof(*p_version)), - boost::bind(&BaseSSLPolicy::handshake_handler, this, + boost::bind(&BaseSSLPolicy::HandshakeHandler, this, p_socket, p_version, connect_callback, _1, _2));*/ - handshake_handler(p_socket, p_version, connect_callback, ec, 0); + HandshakeHandler(p_socket, p_version, connect_callback, ec, 0); } else { BOOST_LOG_TRIVIAL(error) << "link: connection failed " << ec.message(); - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, connect_callback, ec); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, connect_callback, ec); } } - void handshake_handler(p_socket_type p_socket, + void HandshakeHandler(p_socket_type p_socket, std::shared_ptr p_version, const connect_callback_type &connect_callback, const boost::system::error_code &ec, size_t length) { @@ -611,37 +617,37 @@ class BaseSSLPolicy { BOOST_LOG_TRIVIAL(trace) << "link: connected"; p_socket->async_handshake( boost::asio::ssl::stream_base::client, - boost::bind(&BaseSSLPolicy::handshaked_connect_handler, this, + boost::bind(&BaseSSLPolicy::HandshakedConnectHandler, this, p_socket, connect_callback, _1)); } else { BOOST_LOG_TRIVIAL(error) << "link: exchange version failed " << ec.message(); - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, connect_callback, ec); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, connect_callback, ec); } } - void handshaked_connect_handler(p_socket_type p_socket, + void HandshakedConnectHandler(p_socket_type p_socket, const connect_callback_type &connect_callback, const boost::system::error_code &ec) { if (!ec) { BOOST_LOG_TRIVIAL(trace) << "link: authenticated"; - this->to_next_layer_handler(p_socket, connect_callback, ec); + this->ToNextLayerHandler(p_socket, connect_callback, ec); } else { BOOST_LOG_TRIVIAL(error) << "link: no handshake " << ec.message(); - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, connect_callback, ec); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, connect_callback, ec); } } - void to_next_layer_handler(p_socket_type p_socket, - const connect_callback_type &connect_callback, - const boost::system::error_code &ec) { + void ToNextLayerHandler(p_socket_type p_socket, + const connect_callback_type &connect_callback, + const boost::system::error_code &ec) { io_service_.post(boost::bind(connect_callback, p_socket, ec)); } /// Read ssl version - void accepted_handler(p_acceptor_type p_acceptor, p_socket_type p_socket, + void AcceptedHandler(p_acceptor_type p_acceptor, p_socket_type p_socket, const accept_callback_type &accept_callback, const boost::system::error_code &ec) { if (!ec) { @@ -649,30 +655,30 @@ class BaseSSLPolicy { /*std::shared_ptr p_version = std::make_shared(); boost::asio::async_read(p_socket->socket().next_layer(), boost::asio::buffer(p_version.get(), sizeof(*p_version)), - boost::bind(&BaseSSLPolicy::accepted_handshake_handler, this, + boost::bind(&BaseSSLPolicy::AcceptedHandshakeHandler, this, p_socket, p_version, accept_callback, _1, _2));*/ std::shared_ptr p_version = std::make_shared(GetVersion()); - accepted_handshake_handler(p_socket, p_version, accept_callback, ec, 0); - this->accept_links(p_acceptor, accept_callback); + AcceptedHandshakeHandler(p_socket, p_version, accept_callback, ec, 0); + this->AcceptLinks(p_acceptor, accept_callback); } else { - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, accept_callback); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, accept_callback); } } /// Operate the ssl handshake if version supported and no error - void accepted_handshake_handler(p_socket_type p_socket, - std::shared_ptr p_version, - const accept_callback_type &accept_callback, - const boost::system::error_code &ec, - size_t bytes_transferred) { + void AcceptedHandshakeHandler(p_socket_type p_socket, + std::shared_ptr p_version, + const accept_callback_type &accept_callback, + const boost::system::error_code &ec, + size_t bytes_transferred) { auto version_supported = IsVersionSupported(*p_version); if (!ec && version_supported) { BOOST_LOG_TRIVIAL(trace) << "link: version supported"; p_socket->async_handshake( boost::asio::ssl::stream_base::server, - boost::bind(&BaseSSLPolicy::handshaked_accept_handler, this, p_socket, + boost::bind(&BaseSSLPolicy::HandshakedAcceptHandler, this, p_socket, accept_callback, _1)); } else { if (!version_supported) { @@ -683,12 +689,12 @@ class BaseSSLPolicy { BOOST_LOG_TRIVIAL(error) << "link: error on read version " << "ec : " << ec.message(); } - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, accept_callback); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, accept_callback); } } - void handshaked_accept_handler(p_socket_type p_socket, + void HandshakedAcceptHandler(p_socket_type p_socket, const accept_callback_type &accept_callback, const boost::system::error_code &ec) { if (!ec) { @@ -698,16 +704,16 @@ class BaseSSLPolicy { << "link: cipher suite " << SSL_get_cipher(p_socket->socket().native_handle()); } - this->to_next_layer_handler(p_socket, accept_callback); + this->ToNextLayerHandler(p_socket, accept_callback); } else { BOOST_LOG_TRIVIAL(error) << "link: NOT Authenticated " << ec.message(); - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, accept_callback); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, accept_callback); } } - void to_next_layer_handler(p_socket_type p_socket, - const accept_callback_type &accept_callback) { + void ToNextLayerHandler(p_socket_type p_socket, + const accept_callback_type &accept_callback) { io_service_.post(boost::bind(accept_callback, p_socket)); } @@ -745,8 +751,8 @@ class BaseSSLPolicy { (serialization == boost::archive::BOOST_ARCHIVE_VERSION()); } - std::string get_password(std::size_t, - boost::asio::ssl::context::password_purpose) const { + std::string GetPassword(std::size_t, + boost::asio::ssl::context::password_purpose) const { return config_.tls.key_password; } @@ -770,7 +776,7 @@ class BaseSSLPolicy { return preverified; } - std::string get_remote_addr(const Parameters ¶meters) { + std::string GetRemoteAddr(const Parameters ¶meters) { if (parameters.count("remote_addr")) { return parameters.find("remote_addr")->second; } else { @@ -778,7 +784,7 @@ class BaseSSLPolicy { } } - std::string get_remote_port(const Parameters ¶meters) { + std::string GetRemotePort(const Parameters ¶meters) { if (parameters.count("remote_port")) { return parameters.find("remote_port")->second; } else { @@ -786,7 +792,7 @@ class BaseSSLPolicy { } } - std::vector get_deserialized_vector(const std::string &serialized) { + std::vector GetDeserializedVector(const std::string &serialized) { std::istringstream istrs(serialized); boost::archive::text_iarchive ar(istrs); std::vector deserialized; @@ -799,30 +805,30 @@ class BaseSSLPolicy { } } - std::vector get_auth_cert_in_vector(const Parameters ¶meters) { + std::vector GetAuthCertInVector(const Parameters ¶meters) { if (parameters.count("auth_cert_in_vector")) { auto serialized = parameters.find("auth_cert_in_vector")->second; - auto deserialized = get_deserialized_vector(serialized); + auto deserialized = GetDeserializedVector(serialized); return deserialized; } else { return std::vector(); } } - std::vector get_cert_in_vector(const Parameters ¶meters) { + std::vector GetCertInVector(const Parameters ¶meters) { if (parameters.count("cert_in_vector")) { auto serialized = parameters.find("cert_in_vector")->second; - auto deserialized = get_deserialized_vector(serialized); + auto deserialized = GetDeserializedVector(serialized); return deserialized; } else { return std::vector(); } } - std::vector get_key_in_vector(const Parameters ¶meters) { + std::vector GetKeyInVector(const Parameters ¶meters) { if (parameters.count("key_in_vector")) { auto serialized = parameters.find("key_in_vector")->second; - auto deserialized = get_deserialized_vector(serialized); + auto deserialized = GetDeserializedVector(serialized); return deserialized; } else { return std::vector(); diff --git a/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h b/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h index 95f41d0e..a95e20a2 100644 --- a/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h +++ b/src/core/network_virtual_layer_policies/link_policies/tcp_policy.h @@ -46,11 +46,10 @@ class TCPPolicy { const ssf::Config& ssf_config) : io_service_(io_service) { } - void establish_link(const Parameters& parameters, - connect_callback_type connect_callback) { - - auto addr = get_remote_addr(parameters); - auto port = get_remote_port(parameters); + void EstablishLink(const Parameters& parameters, + connect_callback_type connect_callback) { + auto addr = GetRemoteAddr(parameters); + auto port = GetRemotePort(parameters); BOOST_LOG_TRIVIAL(info) << "link: connecting " << addr << " " << port; if (addr != "" && port != "") { @@ -65,7 +64,7 @@ class TCPPolicy { << port; boost::system::error_code ec(ssf::error::invalid_argument, ssf::error::get_ssf_category()); - to_next_layer_handler(p_socket_type(nullptr), connect_callback, ec); + ToNextLayerHandler(p_socket_type(nullptr), connect_callback, ec); return; } @@ -73,17 +72,17 @@ class TCPPolicy { boost::asio::async_connect( *p_socket, iterator, - boost::bind(&TCPPolicy::connected_handler, this, p_socket, + boost::bind(&TCPPolicy::ConnectedHandler, this, p_socket, connect_callback, _1)); } else { boost::system::error_code ec(ssf::error::invalid_argument, ssf::error::get_ssf_category()); - to_next_layer_handler(p_socket_type(nullptr), connect_callback, ec); + ToNextLayerHandler(p_socket_type(nullptr), connect_callback, ec); } } /// Accept a new connection - void accept_links(p_acceptor_type p_acceptor, + void AcceptLinks(p_acceptor_type p_acceptor, accept_callback_type accept_callback) { if (!p_acceptor->is_open()) { @@ -94,11 +93,11 @@ class TCPPolicy { BOOST_LOG_TRIVIAL(trace) << "link: accepting"; p_acceptor->async_accept( - *p_socket, boost::bind(&TCPPolicy::accepted_handler, this, p_acceptor, + *p_socket, boost::bind(&TCPPolicy::AcceptedHandler, this, p_acceptor, p_socket, accept_callback, _1)); } - void close_link(socket_type& socket) { + void CloseLink(socket_type& socket) { boost::system::error_code ec; socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); socket.close(ec); @@ -106,73 +105,73 @@ class TCPPolicy { private: /// Write link version - void connected_handler(p_socket_type p_socket, + void ConnectedHandler(p_socket_type p_socket, connect_callback_type connect_callback, const boost::system::error_code& ec) { if (!ec) { auto p_version = std::make_shared(GetVersion()); /*boost::asio::async_write(*p_socket, boost::asio::buffer(p_version.get(), sizeof(*p_version)), - boost::bind(&TCPPolicy::write_version_handler, this, + boost::bind(&TCPPolicy::WriteVersionHandler, this, p_socket, p_version, connect_callback, _1, _2));*/ - write_version_handler(p_socket, p_version, connect_callback, ec, 0); + WriteVersionHandler(p_socket, p_version, connect_callback, ec, 0); } else { BOOST_LOG_TRIVIAL(error) << "link: connection failed " << ec.message(); - close_link(*p_socket); - this->to_next_layer_handler(nullptr, connect_callback, ec); + CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, connect_callback, ec); } } - void write_version_handler(p_socket_type p_socket, + void WriteVersionHandler(p_socket_type p_socket, std::shared_ptr p_version, connect_callback_type connect_callback, const boost::system::error_code& ec, size_t bytes_transferred) { if (!ec) { BOOST_LOG_TRIVIAL(info) << "link: connected"; - this->to_next_layer_handler(p_socket, connect_callback, ec); + this->ToNextLayerHandler(p_socket, connect_callback, ec); } else { BOOST_LOG_TRIVIAL(error) << "link: connection failed " << ec.message(); - close_link(*p_socket); - this->to_next_layer_handler(nullptr, connect_callback, ec); + CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, connect_callback, ec); } } - void to_next_layer_handler(p_socket_type p_socket, - connect_callback_type connect_callback, - const boost::system::error_code& ec) { + void ToNextLayerHandler(p_socket_type p_socket, + connect_callback_type connect_callback, + const boost::system::error_code& ec) { io_service_.post(boost::bind(connect_callback, p_socket, ec)); } /// Read link version - void accepted_handler(p_acceptor_type p_acceptor, p_socket_type p_socket, + void AcceptedHandler(p_acceptor_type p_acceptor, p_socket_type p_socket, accept_callback_type accept_callback, const boost::system::error_code& ec) { if (!ec) { /*std::shared_ptr p_version = std::make_shared(); boost::asio::async_read(*p_socket, boost::asio::buffer(p_version.get(), sizeof(*p_version)), - boost::bind(&TCPPolicy::read_version_handler, this, + boost::bind(&TCPPolicy::ReadVersionHandler, this, p_socket, p_version, accept_callback, _1, _2));*/ std::shared_ptr p_version = std::make_shared(GetVersion()); - read_version_handler(p_socket, p_version, accept_callback, ec, 0); - this->accept_links(p_acceptor, accept_callback); + ReadVersionHandler(p_socket, p_version, accept_callback, ec, 0); + this->AcceptLinks(p_acceptor, accept_callback); } else { BOOST_LOG_TRIVIAL(error) << "link: NOT Authenticated " << ec.message(); - this->close_link(*p_socket); - this->to_next_layer_handler(nullptr, accept_callback); + this->CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, accept_callback); } } - void read_version_handler(p_socket_type p_socket, + void ReadVersionHandler(p_socket_type p_socket, std::shared_ptr p_version, accept_callback_type accept_callback, const boost::system::error_code& ec, size_t bytes_transferred) { auto version_supported = IsVersionSupported(*p_version); if (!ec && version_supported) { - this->to_next_layer_handler(p_socket, accept_callback); + this->ToNextLayerHandler(p_socket, accept_callback); BOOST_LOG_TRIVIAL(trace) << "link: authenticated"; } else { if (!version_supported) { @@ -184,17 +183,17 @@ class TCPPolicy { << "ec : " << ec.message(); } BOOST_LOG_TRIVIAL(error) << "link: NOT Authenticated "; - close_link(*p_socket); - this->to_next_layer_handler(nullptr, accept_callback); + CloseLink(*p_socket); + this->ToNextLayerHandler(nullptr, accept_callback); } } - void to_next_layer_handler(p_socket_type p_socket, + void ToNextLayerHandler(p_socket_type p_socket, accept_callback_type accept_callback) { io_service_.post(boost::bind(accept_callback, p_socket)); } - std::string get_remote_addr(const Parameters& parameters) { + std::string GetRemoteAddr(const Parameters& parameters) { if (parameters.count("remote_addr")) { return parameters.find("remote_addr")->second; } else { @@ -202,7 +201,7 @@ class TCPPolicy { } } - std::string get_remote_port(const Parameters& parameters) { + std::string GetRemotePort(const Parameters& parameters) { if (parameters.count("remote_port")) { return parameters.find("remote_port")->second; } else { diff --git a/src/core/parser/bounce_parser.cpp b/src/core/parser/bounce_parser.cpp new file mode 100644 index 00000000..8b4b022a --- /dev/null +++ b/src/core/parser/bounce_parser.cpp @@ -0,0 +1,50 @@ +#include "core/parser/bounce_parser.h" + +#include + +namespace ssf { +namespace parser { + +BounceParser::BounceList BounceParser::ParseBounceFile( + const std::string& filepath) { + BounceList list; + + if (filepath != "") { + std::ifstream file(filepath); + + if (file.is_open()) { + std::string line; + + while (std::getline(file, line)) { + list.push_back(line); + } + + file.close(); + } + } + + return list; +} + +std::string BounceParser::GetRemoteAddress(const std::string& bounce_line) { + size_t position = bounce_line.find(":"); + + if (position != std::string::npos) { + return bounce_line.substr(0, position); + } else { + return ""; + } +} + +std::string BounceParser::GetRemotePort(const std::string& bounce_line) { + size_t position = bounce_line.find(":"); + + if (position != std::string::npos) { + return bounce_line.substr(position + 1); + } else { + return ""; + } +} + +} // parser +} // ssf \ No newline at end of file diff --git a/src/core/parser/bounce_parser.h b/src/core/parser/bounce_parser.h new file mode 100644 index 00000000..ef283a1e --- /dev/null +++ b/src/core/parser/bounce_parser.h @@ -0,0 +1,25 @@ +#ifndef SSF_CORE_PARSER_BOUNCE_PARSER_H_ +#define SSF_CORE_PARSER_BOUNCE_PARSER_H_ + +#include +#include + +namespace ssf { +namespace parser { + +class BounceParser { + public: + using BounceList = std::list; + + public: + static BounceList ParseBounceFile(const std::string& filepath); + + static std::string GetRemoteAddress(const std::string& bounce_line); + + static std::string GetRemotePort(const std::string& bounce_line); +}; + +} // parser +} // ssf + +#endif // SSF_CORE_PARSER_BOUNCE_PARSER_H_ diff --git a/src/core/server/server.h b/src/core/server/server.h index 6dfd70e8..d7fffe46 100644 --- a/src/core/server/server.h +++ b/src/core/server/server.h @@ -19,23 +19,24 @@ #include "services/sockets_to_fibers/sockets_to_fibers.h" #include "services/fibers_to_datagrams/fibers_to_datagrams.h" #include "services/datagrams_to_fibers/datagrams_to_fibers.h" +#include "services/copy_file/file_to_fiber/file_to_fiber.h" +#include "services/copy_file/fiber_to_file/fiber_to_file.h" #include "core/service_manager/service_manager.h" #include "services/base_service.h" #include "core/factories/service_factory.h" - namespace ssf { template class LinkAuthenticationPolicy, template class> - class NetworkVirtualLayerPolicy, + class NetworkVirtualLayerPolicy, template class TransportVirtualLayerPolicy> class SSFServer : public NetworkVirtualLayerPolicy, - public TransportVirtualLayerPolicy< - typename PhysicalVirtualLayer::socket_type> { + public TransportVirtualLayerPolicy< + typename PhysicalVirtualLayer::socket_type> { private: typedef typename PhysicalVirtualLayer::socket_type socket_type; typedef typename PhysicalVirtualLayer::p_socket_type p_socket_type; @@ -54,29 +55,22 @@ class SSFServer : public NetworkVirtualLayerPolicy socket_map; typedef std::map service_manager_map; -public: - SSFServer(boost::asio::io_service& io_service, - const ssf::Config& ssf_config, + public: + SSFServer(boost::asio::io_service& io_service, const ssf::Config& ssf_config, uint16_t local_port); void run(); void stop(); - void add_demux(p_demux p_fiber_demux, - p_ServiceManager p_service_manager); - - void remove_demux(p_demux p_fiber_demux); - void remove_all_demuxes(); - - void do_ssf_start(p_socket_type p_socket, const boost::system::error_code& ec); - -private: - void do_fiberize_(p_socket_type p_socket, boost::system::error_code& ec); - -private: - void network_to_transport(p_socket_type p_socket, vector_error_code_type v_ec); + private: + void AddDemux(p_demux p_fiber_demux, p_ServiceManager p_service_manager); + void RemoveDemux(p_demux p_fiber_demux); + void RemoveAllDemuxes(); + void DoSSFStart(p_socket_type p_socket, const boost::system::error_code& ec); + void DoFiberize(p_socket_type p_socket, boost::system::error_code& ec); + void NetworkToTransport(p_socket_type p_socket, vector_error_code_type v_ec); -private: + private: boost::asio::io_service& io_service_; uint16_t local_port_; @@ -85,11 +79,10 @@ class SSFServer : public NetworkVirtualLayerPolicy class L, +template class L, template class> class N, template class T> -SSFServer::SSFServer( - boost::asio::io_service& io_service, - const ssf::Config& ssf_config, - uint16_t local_port) - : N(io_service, ssf_config), - T( - boost::bind(&SSFServer::do_ssf_start, this, _1, _2)), - io_service_(io_service), - local_port_(local_port) {} +SSFServer::SSFServer(boost::asio::io_service& io_service, + const ssf::Config& ssf_config, + uint16_t local_port) + : N(io_service, ssf_config), + T( + boost::bind(&SSFServer::DoSSFStart, this, _1, _2)), + io_service_(io_service), + local_port_(local_port) {} /// Start accepting connections -template class L, +template class L, template class> class N, template class T> void SSFServer::run() { - this->accept_new_routes( + this->AcceptNewRoutes( local_port_, - boost::bind(&SSFServer::network_to_transport, this, _1, _2)); + boost::bind(&SSFServer::NetworkToTransport, this, _1, _2)); } /// Stop accepting connections and end all on going connections -template class L, +template class L, template class> class N, template class T> void SSFServer::stop() { - this->stop_accepting_routes(); - this->remove_all_demuxes(); + this->StopAcceptingRoutes(); + this->RemoveAllDemuxes(); } //------------------------------------------------------------------------------- -template class L, +template class L, template class> class N, template class T> -void SSFServer::network_to_transport(p_socket_type p_socket, - vector_error_code_type v_ec) { +void SSFServer::NetworkToTransport(p_socket_type p_socket, + vector_error_code_type v_ec) { if (!v_ec[0]) { - this->do_ssf_initiate_receive(p_socket); + this->DoSSFInitiateReceive(p_socket); } else { BOOST_LOG_TRIVIAL(error) << "server: network error: " << v_ec[0].message(); } @@ -59,27 +54,25 @@ void SSFServer::network_to_transport(p_socket_type p_socket, //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -template class L, +template class L, template class> class N, template class T> -void SSFServer::do_ssf_start(p_socket_type p_socket, +void SSFServer::DoSSFStart(p_socket_type p_socket, const boost::system::error_code& ec) { if (!ec) { BOOST_LOG_TRIVIAL(trace) << "server: SSF reply ok"; boost::system::error_code ec2; - this->do_fiberize_(p_socket, ec2); + this->DoFiberize(p_socket, ec2); } else { BOOST_LOG_TRIVIAL(error) << "server: SSF protocol error " << ec.message(); } } -template class L, +template class L, template class> class N, template class T> -void SSFServer::do_fiberize_(p_socket_type p_socket, - boost::system::error_code& ec) { +void SSFServer::DoFiberize(p_socket_type p_socket, + boost::system::error_code& ec) { // Register supported admin commands services::admin::CreateServiceRequest::RegisterToCommandFactory(); services::admin::StopServiceRequest::RegisterToCommandFactory(); @@ -87,16 +80,15 @@ void SSFServer::do_fiberize_(p_socket_type p_socket, // Make a new fiber demux and fiberize auto p_fiber_demux = std::make_shared(io_service_); - auto close_demux_handler = [this, p_fiber_demux]() { - this->remove_demux(p_fiber_demux); - }; + auto close_demux_handler = + [this, p_fiber_demux]() { this->RemoveDemux(p_fiber_demux); }; p_fiber_demux->fiberize(std::move(*p_socket), close_demux_handler); // Make a new service manager auto p_service_manager = std::make_shared>(); // Save the demux, the socket and the service manager - this->add_demux(p_fiber_demux, p_service_manager); + this->AddDemux(p_fiber_demux, p_service_manager); // Make a new service factory auto p_service_factory = ServiceFactory::Create( @@ -105,14 +97,18 @@ void SSFServer::do_fiberize_(p_socket_type p_socket, // Register supported micro services services::socks::SocksServer::RegisterToServiceFactory( p_service_factory); - services::fibers_to_sockets::RemoteForwarderService< - demux>::RegisterToServiceFactory(p_service_factory); - services::sockets_to_fibers::LocalForwarderService< - demux>::RegisterToServiceFactory(p_service_factory); + services::fibers_to_sockets::FibersToSockets::RegisterToServiceFactory( + p_service_factory); + services::sockets_to_fibers::SocketsToFibers::RegisterToServiceFactory( + p_service_factory); services::fibers_to_datagrams::FibersToDatagrams< demux>::RegisterToServiceFactory(p_service_factory); services::datagrams_to_fibers::DatagramsToFibers< demux>::RegisterToServiceFactory(p_service_factory); + services::copy_file::file_to_fiber::FileToFiber< + demux>::RegisterToServiceFactory(p_service_factory); + services::copy_file::fiber_to_file::FiberToFile< + demux>::RegisterToServiceFactory(p_service_factory); // Start the admin micro service std::map empty_map; @@ -124,11 +120,10 @@ void SSFServer::do_fiberize_(p_socket_type p_socket, } //------------------------------------------------------------------------------ -template class L, +template class L, template class> class N, template class T> -void SSFServer::add_demux(p_demux p_fiber_demux, +void SSFServer::AddDemux(p_demux p_fiber_demux, p_ServiceManager p_service_manager) { boost::recursive_mutex::scoped_lock lock(storage_mutex_); BOOST_LOG_TRIVIAL(trace) << "server: adding a new demux"; @@ -137,11 +132,10 @@ void SSFServer::add_demux(p_demux p_fiber_demux, p_service_managers_[p_fiber_demux] = p_service_manager; } -template class L, +template class L, template class> class N, template class T> -void SSFServer::remove_demux(p_demux p_fiber_demux) { +void SSFServer::RemoveDemux(p_demux p_fiber_demux) { boost::recursive_mutex::scoped_lock lock(storage_mutex_); BOOST_LOG_TRIVIAL(trace) << "server: removing a demux"; @@ -155,17 +149,16 @@ void SSFServer::remove_demux(p_demux p_fiber_demux) { } auto p_service_factory = - ServiceFactoryManager::GetServiceFactory(p_fiber_demux.get()); + ServiceFactoryManager::GetServiceFactory(p_fiber_demux.get()); if (p_service_factory) { p_service_factory->Destroy(); } } -template class L, +template class L, template class> class N, template class T> -void SSFServer::remove_all_demuxes() { +void SSFServer::RemoveAllDemuxes() { boost::recursive_mutex::scoped_lock lock(storage_mutex_); BOOST_LOG_TRIVIAL(trace) << "server: removing all demuxes"; @@ -180,7 +173,7 @@ void SSFServer::remove_all_demuxes() { } auto p_service_factory = - ServiceFactoryManager::GetServiceFactory(p_fiber_demux.get()); + ServiceFactoryManager::GetServiceFactory(p_fiber_demux.get()); if (p_service_factory) { p_service_factory->Destroy(); } diff --git a/src/core/transport_virtual_layer_policies/transport_protocol_policy.h b/src/core/transport_virtual_layer_policies/transport_protocol_policy.h index c1e87dae..3242284c 100644 --- a/src/core/transport_virtual_layer_policies/transport_protocol_policy.h +++ b/src/core/transport_virtual_layer_policies/transport_protocol_policy.h @@ -26,7 +26,7 @@ class TransportProtocolPolicy { public: TransportProtocolPolicy(callback_type callback) : callback_(callback) {} - void do_ssf_initiate(p_socket_type p_socket) { + void DoSSFInitiate(p_socket_type p_socket) { BOOST_LOG_TRIVIAL(info) << "transport: starting SSF protocol"; uint32_t version = GetVersion(); @@ -34,19 +34,19 @@ class TransportProtocolPolicy { boost::asio::async_write( *p_socket, p_ssf_request->const_buffer(), - boost::bind(&TransportProtocolPolicy::do_ssf_valid_receive, this, + boost::bind(&TransportProtocolPolicy::DoSSFValidReceive, this, p_ssf_request, p_socket, _1, _2)); } - void do_ssf_initiate_receive(p_socket_type p_socket) { + void DoSSFInitiateReceive(p_socket_type p_socket) { auto p_ssf_request = std::make_shared(); boost::asio::async_read( *p_socket, p_ssf_request->buffer(), - boost::bind(&TransportProtocolPolicy::do_ssf_valid, this, + boost::bind(&TransportProtocolPolicy::DoSSFValid, this, p_ssf_request, p_socket, _1, _2)); } - void do_ssf_valid(SSFRequestPtr p_ssf_request, p_socket_type p_socket, + void DoSSFValid(SSFRequestPtr p_ssf_request, p_socket_type p_socket, const boost::system::error_code& ec, size_t length) { if (!ec) { uint32_t version = p_ssf_request->version(); @@ -58,7 +58,7 @@ class TransportProtocolPolicy { boost::asio::async_write( *p_socket, p_ssf_reply->const_buffer(), boost::bind( - &TransportProtocolPolicy::do_ssf_protocol_finished, this, + &TransportProtocolPolicy::DoSSFProtocolFinished, this, p_ssf_reply, p_socket, _1, _2)); } else { BOOST_LOG_TRIVIAL(error) << "transport: SSF version NOT supported " << version; @@ -72,7 +72,7 @@ class TransportProtocolPolicy { } } - void do_ssf_valid_receive(SSFRequestPtr p_ssf_request, p_socket_type p_socket, + void DoSSFValidReceive(SSFRequestPtr p_ssf_request, p_socket_type p_socket, const boost::system::error_code& ec, size_t length) { if (!ec) { BOOST_LOG_TRIVIAL(info) << "transport: SSF request sent"; @@ -81,7 +81,7 @@ class TransportProtocolPolicy { boost::asio::async_read( *p_socket, p_ssf_reply->buffer(), - boost::bind(&TransportProtocolPolicy::do_ssf_protocol_finished, + boost::bind(&TransportProtocolPolicy::DoSSFProtocolFinished, this, p_ssf_reply, p_socket, _1, _2)); } else { BOOST_LOG_TRIVIAL(error) << "transport: could NOT send the SSF request " @@ -90,7 +90,7 @@ class TransportProtocolPolicy { } } - void do_ssf_protocol_finished(SSFReplyPtr p_ssf_reply, p_socket_type p_socket, + void DoSSFProtocolFinished(SSFReplyPtr p_ssf_reply, p_socket_type p_socket, const boost::system::error_code& ec, size_t length) { if (!ec) { diff --git a/src/services/admin/admin.h b/src/services/admin/admin.h index 1e893bbc..0e251dde 100644 --- a/src/services/admin/admin.h +++ b/src/services/admin/admin.h @@ -35,33 +35,29 @@ namespace ssf { namespace services { namespace admin { template class Admin : public BaseService { public: - typedef typename ssf::services::BaseUserService::BaseUserServicePtr - BaseUserServicePtr; - typedef std::function< - void(ssf::services::initialisation::type, - BaseUserServicePtr, - const boost::system::error_code&)> - AdminCallbackType; + typedef typename ssf::services::BaseUserService::BaseUserServicePtr + BaseUserServicePtr; + typedef std::function AdminCallbackType; private: typedef typename Demux::local_port_type local_port_type; typedef std::shared_ptr AdminPtr; typedef ItemManager::BaseServicePtr> - ServiceManager; + ServiceManager; typedef typename ssf::BaseService::Parameters Parameters; typedef typename ssf::BaseService::demux demux; typedef typename ssf::BaseService::endpoint endpoint; - typedef std::function HandlerType; - typedef std::map IdToHandlerMapType; + typedef std::function CommandHandler; + typedef std::map IdToCommandHandlerMap; public: static AdminPtr Create(boost::asio::io_service& io_service, - Demux& fiber_demux, - Parameters parameters) { - + Demux& fiber_demux, Parameters parameters) { return std::shared_ptr(new Admin(io_service, fiber_demux)); } @@ -101,29 +97,40 @@ class Admin : public BaseService { serial, request.command_id, (uint32_t)parameters_buff_to_send.size(), parameters_buff_to_send); - auto do_handler = [p_command](const boost::system::error_code& ec, - size_t length) {}; + auto do_handler = + [p_command](const boost::system::error_code& ec, size_t length) {}; async_SendCommand(*p_command, do_handler); } - void InsertHandler(uint32_t serial, HandlerType handler) { - boost::recursive_mutex::scoped_lock lock1(handlers_mutex_); - handlers[serial] = handler; + void InsertHandler(uint32_t serial, CommandHandler command_handler) { + boost::recursive_mutex::scoped_lock lock1(command_handlers_mutex_); + command_handlers_[serial] = command_handler; + } + + // execute handler bound to the command serial id if exists + void ExecuteAndRemoveCommandHandler(uint32_t serial) { + if (command_handlers_.count(command_serial_received_)) { + this->get_io_service().post(boost::bind( + command_handlers_[command_serial_received_], boost::system::error_code())); + this->EraseHandler(command_serial_received_); + } } void EraseHandler(uint32_t serial) { - boost::recursive_mutex::scoped_lock lock1(handlers_mutex_); - handlers.erase(serial); + boost::recursive_mutex::scoped_lock lock1(command_handlers_mutex_); + command_handlers_.erase(serial); } uint32_t GetAvailableSerial() { - boost::recursive_mutex::scoped_lock lock1(handlers_mutex_); - - for (uint32_t new_port = 3; new_port < std::numeric_limits::max(); ++new_port) { - if (handlers.count(new_port + !!is_server_) == 0) { - handlers[new_port + !!is_server_] = [](const boost::system::error_code&) {}; - return new_port + !!is_server_; + boost::recursive_mutex::scoped_lock lock1(command_handlers_mutex_); + + for (uint32_t serial = 3; serial < std::numeric_limits::max(); + ++serial) { + if (command_handlers_.count(serial + !!is_server_) == 0) { + command_handlers_[serial + !!is_server_] = + [](const boost::system::error_code&) {}; + return serial + !!is_server_; } } return 0; @@ -139,17 +146,16 @@ class Admin : public BaseService { void HandleStop(); void Initialize(); void StartRemoteService( - const admin::CreateServiceRequest& create_request, - const HandlerType& handler); - void StopRemoteService( - const admin::StopServiceRequest& stop_request, - const HandlerType& handler); - void Initialize_remote_services(const boost::system::error_code& ec); + const admin::CreateServiceRequest& create_request, + const CommandHandler& handler); + void StopRemoteService(const admin::StopServiceRequest& stop_request, + const CommandHandler& handler); + void InitializeRemoteServices(const boost::system::error_code& ec); void ListenForCommand(); - void DoAdmin(const boost::system::error_code& ec = boost::system::error_code(), - size_t length = 0); - void PostKeepAlive(const boost::system::error_code& ec, - size_t length); + void DoAdmin( + const boost::system::error_code& ec = boost::system::error_code(), + size_t length = 0); + void PostKeepAlive(const boost::system::error_code& ec, size_t length); void SendKeepAlive(const boost::system::error_code& ec); void ReceiveInstructionHeader(); void ReceiveInstructionParameters(); @@ -158,30 +164,24 @@ class Admin : public BaseService { void ShutdownServices(); template - void async_SendCommand(const AdminCommand& command, - Handler handler) { - - auto do_handler = [handler](const boost::system::error_code& ec, size_t length) { - handler(ec, length); - }; - - boost::asio::async_write(fiber_, - command.const_buffers(), - do_handler); + void async_SendCommand(const AdminCommand& command, Handler handler) { + auto do_handler = [handler](const boost::system::error_code& ec, + size_t length) { handler(ec, length); }; + boost::asio::async_write(fiber_, command.const_buffers(), do_handler); } void Notify(ssf::services::initialisation::type type, - BaseUserServicePtr p_user_service, - boost::system::error_code ec) { + BaseUserServicePtr p_user_service, boost::system::error_code ec) { if (callback_) { - this->get_io_service().post( - boost::bind(callback_, std::move(type), p_user_service, std::move(ec))); + this->get_io_service().post(boost::bind(callback_, std::move(type), + p_user_service, std::move(ec))); } } template - auto Then(Handler handler, This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { + auto Then(Handler handler, + This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { return boost::bind(handler, me->SelfFromThis(), _1); } @@ -214,8 +214,7 @@ class Admin : public BaseService { boost::asio::deadline_timer reserved_keep_alive_timer_; // List of user services - std::vector - user_services_; + std::vector user_services_; // Connection attempts uint8_t retries_; @@ -227,17 +226,16 @@ class Admin : public BaseService { // Initialize services boost::asio::coroutine coroutine_; size_t i_; - std::vector> - create_request_vector_; + std::vector> create_request_vector_; size_t j_; uint32_t remote_all_started_; uint16_t init_retries_; std::vector> stop_request_vector_; - bool local_all_starter_; + bool local_all_started_; boost::system::error_code init_ec_; - boost::recursive_mutex handlers_mutex_; - IdToHandlerMapType handlers; + boost::recursive_mutex command_handlers_mutex_; + IdToCommandHandlerMap command_handlers_; AdminCallbackType callback_; }; diff --git a/src/services/admin/admin.ipp b/src/services/admin/admin.ipp index bb3a0e28..6ea84692 100644 --- a/src/services/admin/admin.ipp +++ b/src/services/admin/admin.ipp @@ -115,8 +115,9 @@ void Admin::HandleConnect(const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "service admin: handle connect"; if (!fiber_.is_open() || ec) { - BOOST_LOG_TRIVIAL(error) << "service admin: no new connection: " << ec << " " - << ec.value(); + BOOST_LOG_TRIVIAL(error) + << "service admin: no new connection: " << ec.message() << " " + << ec.value(); // Retry to connect if failed to open the fiber if (retries_ < 50) { this->StartConnect(); @@ -125,7 +126,7 @@ void Admin::HandleConnect(const boost::system::error_code& ec) { return; } else { this->Initialize(); - this->Initialize_remote_services(boost::system::error_code()); + this->InitializeRemoteServices(boost::system::error_code()); } } @@ -144,7 +145,7 @@ void Admin::Initialize() { /// Initialize micro services (local and remote) asked by the client template -void Admin::Initialize_remote_services( +void Admin::InitializeRemoteServices( const boost::system::error_code& ec) { if (!ec) { reenter(coroutine_) { @@ -157,17 +158,18 @@ void Admin::Initialize_remote_services( // For each remote micro service to start for (j_ = 0; j_ < create_request_vector_.size(); ++j_) { - // Send a service creation request + // Start remove service and yield until server response comes back yield StartRemoteService( create_request_vector_[j_], - boost::bind(&Admin::Initialize_remote_services, + boost::bind(&Admin::InitializeRemoteServices, this->SelfFromThis(), _1)); } + // At this point, all remote services have responded with their statuses remote_all_started_ = user_services_[i_]->CheckRemoteServiceStatus(this->get_demux()); - // If something went wrong remote_all_started_ == 0 + // If something went wrong remote_all_started_ > 0 if (remote_all_started_) { BOOST_LOG_TRIVIAL(warning) << "service admin: remote could not start"; @@ -184,7 +186,7 @@ void Admin::Initialize_remote_services( // Send a service stop request yield StopRemoteService( stop_request_vector_[j_], - boost::bind(&Admin::Initialize_remote_services, + boost::bind(&Admin::InitializeRemoteServices, this->SelfFromThis(), _1)); } @@ -192,11 +194,11 @@ void Admin::Initialize_remote_services( } // Start local associated services - local_all_starter_ = + local_all_started_ = user_services_[i_]->StartLocalServices(this->get_demux()); - // If something went wrong local_all_starter_ != 0 - if (!local_all_starter_) { + // If something went wrong local_all_started_ == false + if (!local_all_started_) { BOOST_LOG_TRIVIAL(warning) << "service admin: local could not start"; Notify( @@ -212,7 +214,7 @@ void Admin::Initialize_remote_services( // Send a service stop request yield StopRemoteService( stop_request_vector_[j_], - boost::bind(&Admin::Initialize_remote_services, + boost::bind(&Admin::InitializeRemoteServices, this->SelfFromThis(), _1)); } // Stop local services @@ -361,6 +363,7 @@ void Admin::TreatInstructionId() { ssf::CommandFactory::GetReplyCommandIndex( command_id_received_); + // reply with command serial received (command handler execution) auto p_command = std::make_shared(command_serial_received_, *p_reply_command_index, (uint32_t)reply.size(), reply); @@ -370,11 +373,9 @@ void Admin::TreatInstructionId() { } } - if (handlers.count(command_serial_received_)) { - this->get_io_service().post(boost::bind(handlers[command_serial_received_], - boost::system::error_code())); - this->EraseHandler(command_serial_received_); - } + // Execute an handler bound to the serial command (e.g, callback after a + // service started) + this->ExecuteAndRemoveCommandHandler(command_serial_received_); this->ListenForCommand(); } @@ -383,7 +384,7 @@ void Admin::TreatInstructionId() { template void Admin::StartRemoteService( const admin::CreateServiceRequest& create_request, - const HandlerType& handler) { + const CommandHandler& handler) { this->Command(create_request, handler); } @@ -391,7 +392,7 @@ void Admin::StartRemoteService( template void Admin::StopRemoteService( const admin::StopServiceRequest& stop_request, - const HandlerType& handler) { + const CommandHandler& handler) { this->Command(stop_request, handler); } diff --git a/src/services/admin/requests/create_service_request.h b/src/services/admin/requests/create_service_request.h index d8d1b8b2..4d6f8bb8 100644 --- a/src/services/admin/requests/create_service_request.h +++ b/src/services/admin/requests/create_service_request.h @@ -64,8 +64,7 @@ class CreateServiceRequest { ServiceFactoryManager::GetServiceFactory(p_demux); auto id = p_service_factory->CreateRunNewService(request.service_id(), - request.parameters(), - ec); + request.parameters(), ec); BOOST_LOG_TRIVIAL(debug) << "service status: create " << "service unique id " << id @@ -87,7 +86,7 @@ class CreateServiceRequest { CreateServiceRequest request; try { - ar >> request; + ar >> request; } catch (const std::exception&) { return std::string(); } diff --git a/src/services/base_service.h b/src/services/base_service.h index a61ffe59..323e6b04 100644 --- a/src/services/base_service.h +++ b/src/services/base_service.h @@ -18,21 +18,24 @@ namespace ssf { /// Base class for services template class BaseService : public std::enable_shared_from_this> { -public: + public: typedef std::shared_ptr> BaseServicePtr; typedef typename Demux::socket_type socket_type; typedef typename boost::asio::fiber::stream_fiber::socket fiber; - typedef typename boost::asio::fiber::datagram_fiber::socket fiber_datagram; - typedef typename boost::asio::fiber::stream_fiber::acceptor fiber_acceptor; - typedef typename boost::asio::fiber::stream_fiber::endpoint endpoint; + typedef typename boost::asio::fiber::datagram_fiber::socket + fiber_datagram; + typedef typename boost::asio::fiber::stream_fiber::acceptor + fiber_acceptor; + typedef + typename boost::asio::fiber::stream_fiber::endpoint endpoint; typedef typename boost::asio::fiber::datagram_fiber::endpoint datagram_endpoint; typedef Demux demux; typedef std::map Parameters; -public: + public: virtual void start(boost::system::error_code&) = 0; virtual void stop(boost::system::error_code&) = 0; @@ -40,35 +43,35 @@ class BaseService : public std::enable_shared_from_this> { virtual ~BaseService() {} -protected: + void set_local_id(uint32_t local_id) { local_id_ = local_id; } + + uint32_t local_id() { return local_id_; } + + protected: /// Constructor /** * @param io_service the io_service used for all asynchronous operations * @param demux the demultiplexer used to send and receive data */ BaseService(boost::asio::io_service& io_service, demux& demux) - : io_service_(io_service), demux_(demux) {} + : io_service_(io_service), demux_(demux) {} /// Accessor for the io_service - boost::asio::io_service& get_io_service() { - return io_service_; - } + boost::asio::io_service& get_io_service() { return io_service_; } /// Accessor for the demultiplexer - demux& get_demux() { - return demux_; - } + demux& get_demux() { return demux_; } -private: + private: BaseService(const BaseService&) = delete; BaseService& operator=(const BaseService&) = delete; -private: + private: boost::asio::io_service& io_service_; demux& demux_; + uint32_t local_id_; }; - } // ssf #endif // SSF_SERVICES_BASE_SERVICE_H_ \ No newline at end of file diff --git a/src/services/fibers_to_sockets/fibers_to_sockets.h b/src/services/fibers_to_sockets/fibers_to_sockets.h index deb2a22f..f4ffc505 100644 --- a/src/services/fibers_to_sockets/fibers_to_sockets.h +++ b/src/services/fibers_to_sockets/fibers_to_sockets.h @@ -21,11 +21,11 @@ namespace ssf { namespace services { namespace fibers_to_sockets { template -class RemoteForwarderService : public BaseService { +class FibersToSockets : public BaseService { private: typedef typename Demux::local_port_type local_port_type; - typedef std::shared_ptr RemoteForwarderServicePtr; + typedef std::shared_ptr FibersToSocketsPtr; typedef ItemManager SessionManager; typedef typename ssf::BaseService::Parameters Parameters; typedef typename ssf::BaseService::demux demux; @@ -36,21 +36,17 @@ class RemoteForwarderService : public BaseService { typedef boost::asio::ip::tcp::socket socket; public: - static RemoteForwarderServicePtr create(boost::asio::io_service& io_service, - demux& fiber_demux, - Parameters parameters) { + static FibersToSocketsPtr create(boost::asio::io_service& io_service, + demux& fiber_demux, Parameters parameters) { if (!parameters.count("local_port") || !parameters.count("remote_ip") || !parameters.count("remote_port")) { - return RemoteForwarderServicePtr(nullptr); + return FibersToSocketsPtr(nullptr); } else { - return std::shared_ptr( - new RemoteForwarderService( - io_service, - fiber_demux, - std::stoul(parameters["local_port"]), - parameters["remote_ip"], - (uint16_t)std::stoul(parameters["remote_port"]))); + return std::shared_ptr(new FibersToSockets( + io_service, fiber_demux, std::stoul(parameters["local_port"]), + parameters["remote_ip"], + (uint16_t)std::stoul(parameters["remote_port"]))); } } @@ -61,7 +57,7 @@ class RemoteForwarderService : public BaseService { static void RegisterToServiceFactory( std::shared_ptr> p_factory) { p_factory->RegisterServiceCreator(factory_id, - &RemoteForwarderService::create); + &FibersToSockets::create); } virtual void start(boost::system::error_code& ec); @@ -79,11 +75,9 @@ class RemoteForwarderService : public BaseService { } private: - RemoteForwarderService(boost::asio::io_service& io_service, - demux& fiber_demux, - local_port_type local, - const std::string& ip, - uint16_t remote_port); + FibersToSockets(boost::asio::io_service& io_service, demux& fiber_demux, + local_port_type local, const std::string& ip, + uint16_t remote_port); private: //No check on prioror presence implemented @@ -94,12 +88,13 @@ class RemoteForwarderService : public BaseService { void SocketConnectHandler(const boost::system::error_code& ec); template - auto Then(Handler handler, This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { + auto Then(Handler handler, + This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { return boost::bind(handler, me->SelfFromThis(), _1); } - std::shared_ptr SelfFromThis() { - return std::static_pointer_cast(this->shared_from_this()); + std::shared_ptr SelfFromThis() { + return std::static_pointer_cast(this->shared_from_this()); } uint16_t remote_port_; diff --git a/src/services/fibers_to_sockets/fibers_to_sockets.ipp b/src/services/fibers_to_sockets/fibers_to_sockets.ipp index d6daf40f..f75a68b6 100644 --- a/src/services/fibers_to_sockets/fibers_to_sockets.ipp +++ b/src/services/fibers_to_sockets/fibers_to_sockets.ipp @@ -9,9 +9,11 @@ namespace ssf { namespace services { namespace fibers_to_sockets { template -RemoteForwarderService::RemoteForwarderService( - boost::asio::io_service& io_service, demux& fiber_demux, - local_port_type local_port, const std::string& ip, uint16_t remote_port) +FibersToSockets::FibersToSockets(boost::asio::io_service& io_service, + demux& fiber_demux, + local_port_type local_port, + const std::string& ip, + uint16_t remote_port) : ssf::BaseService::BaseService(io_service, fiber_demux), remote_port_(remote_port), ip_(ip), @@ -21,9 +23,10 @@ RemoteForwarderService::RemoteForwarderService( socket_(io_service) {} template -void RemoteForwarderService::start(boost::system::error_code& ec) { - BOOST_LOG_TRIVIAL(info) << "service fibers to sockets: starting relay on local port tcp " - << local_port_; +void FibersToSockets::start(boost::system::error_code& ec) { + BOOST_LOG_TRIVIAL(info) + << "service fibers to sockets: starting relay on local port tcp " + << local_port_; endpoint ep(this->get_demux(), local_port_); fiber_acceptor_.bind(ep, ec); @@ -43,7 +46,7 @@ void RemoteForwarderService::start(boost::system::error_code& ec) { } template -void RemoteForwarderService::stop(boost::system::error_code& ec) { +void FibersToSockets::stop(boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(info) << "service fibers to sockets: stopping"; ec.assign(ssf::error::success, ssf::error::get_ssf_category()); @@ -53,21 +56,21 @@ void RemoteForwarderService::stop(boost::system::error_code& ec) { } template -uint32_t RemoteForwarderService::service_type_id() { +uint32_t FibersToSockets::service_type_id() { return factory_id; } template -void RemoteForwarderService::StartAcceptFibers() { +void FibersToSockets::StartAcceptFibers() { BOOST_LOG_TRIVIAL(trace) << "service fibers to sockets: accepting new clients"; fiber_acceptor_.async_accept( - fiber_, - Then(&RemoteForwarderService::FiberAcceptHandler, this->SelfFromThis())); + fiber_, Then(&FibersToSockets::FiberAcceptHandler, this->SelfFromThis())); } template -void RemoteForwarderService::FiberAcceptHandler(const boost::system::error_code& ec) { +void FibersToSockets::FiberAcceptHandler( + const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "service fibers to sockets: accept handler"; if (!fiber_acceptor_.is_open()) { @@ -75,14 +78,15 @@ void RemoteForwarderService::FiberAcceptHandler(const boost::system::erro } if (!ec) { - socket_.async_connect( - endpoint_, - Then(&RemoteForwarderService::SocketConnectHandler, this->SelfFromThis())); + socket_.async_connect(endpoint_, + Then(&FibersToSockets::SocketConnectHandler, + this->SelfFromThis())); } } template -void RemoteForwarderService::SocketConnectHandler(const boost::system::error_code& ec) { +void FibersToSockets::SocketConnectHandler( + const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "service fibers to sockets: connect handler"; if (!ec) { diff --git a/src/services/initialisation.h b/src/services/initialisation.h index ceb0efd8..a8a7e80c 100644 --- a/src/services/initialisation.h +++ b/src/services/initialisation.h @@ -9,7 +9,8 @@ namespace initialisation { { NETWORK = 1, TRANSPORT = 2, - SERVICE = 3 + SERVICE = 3, + CLOSE = 4 }; } // initialisation diff --git a/src/services/sockets_to_fibers/sockets_to_fibers.h b/src/services/sockets_to_fibers/sockets_to_fibers.h index 31cb05ea..8907653d 100644 --- a/src/services/sockets_to_fibers/sockets_to_fibers.h +++ b/src/services/sockets_to_fibers/sockets_to_fibers.h @@ -21,11 +21,11 @@ namespace services { namespace sockets_to_fibers { template -class LocalForwarderService : public BaseService { +class SocketsToFibers : public BaseService { public: typedef typename Demux::remote_port_type remote_port_type; - typedef std::shared_ptr LocalForwarderServicePtr; + typedef std::shared_ptr SocketsToFibersPtr; typedef ItemManager SessionManager; typedef typename ssf::BaseService::Parameters Parameters; typedef typename ssf::BaseService::demux demux; @@ -36,19 +36,17 @@ class LocalForwarderService : public BaseService { typedef boost::asio::ip::tcp::acceptor socket_acceptor; public: - static LocalForwarderServicePtr Create(boost::asio::io_service& io_service, + static SocketsToFibersPtr Create(boost::asio::io_service& io_service, demux& fiber_demux, Parameters parameters) { if (!parameters.count("local_port") || !parameters.count("remote_port")) { - return LocalForwarderServicePtr(nullptr); + return SocketsToFibersPtr(nullptr); } else { - return std::shared_ptr( - new LocalForwarderService( - io_service, - fiber_demux, - (uint16_t)std::stoul(parameters["local_port"]), - std::stoul(parameters["remote_port"]))); + return std::shared_ptr( + new SocketsToFibers(io_service, fiber_demux, + (uint16_t)std::stoul(parameters["local_port"]), + std::stoul(parameters["remote_port"]))); } } @@ -59,7 +57,7 @@ class LocalForwarderService : public BaseService { static void RegisterToServiceFactory( std::shared_ptr> p_factory) { p_factory->RegisterServiceCreator(factory_id, - &LocalForwarderService::Create); + &SocketsToFibers::Create); } virtual void start(boost::system::error_code& ec); @@ -76,8 +74,8 @@ class LocalForwarderService : public BaseService { } private: - LocalForwarderService(boost::asio::io_service& io_service, demux& fiber_demux, - uint16_t local, remote_port_type remote_port); + SocketsToFibers(boost::asio::io_service& io_service, demux& fiber_demux, + uint16_t local, remote_port_type remote_port); private: void StartAcceptSockets(); @@ -86,14 +84,14 @@ class LocalForwarderService : public BaseService { void FiberConnectHandler(const boost::system::error_code& ec); - template - auto Then(Handler handler, This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { + auto Then(Handler handler, + This me) -> decltype(boost::bind(handler, me->SelfFromThis(), _1)) { return boost::bind(handler, me->SelfFromThis(), _1); } - std::shared_ptr SelfFromThis() { - return std::static_pointer_cast( + std::shared_ptr SelfFromThis() { + return std::static_pointer_cast( this->shared_from_this()); } diff --git a/src/services/sockets_to_fibers/sockets_to_fibers.ipp b/src/services/sockets_to_fibers/sockets_to_fibers.ipp index 34a55e09..ba1fff33 100644 --- a/src/services/sockets_to_fibers/sockets_to_fibers.ipp +++ b/src/services/sockets_to_fibers/sockets_to_fibers.ipp @@ -8,9 +8,9 @@ namespace ssf { namespace services { namespace sockets_to_fibers { template -LocalForwarderService::LocalForwarderService( - boost::asio::io_service& io_service, demux& fiber_demux, - uint16_t local_port, remote_port_type remote_port) +SocketsToFibers::SocketsToFibers(boost::asio::io_service& io_service, + demux& fiber_demux, uint16_t local_port, + remote_port_type remote_port) : ssf::BaseService::BaseService(io_service, fiber_demux), local_port_(local_port), remote_port_(remote_port), @@ -19,9 +19,10 @@ LocalForwarderService::LocalForwarderService( fiber_(io_service) {} template -void LocalForwarderService::start(boost::system::error_code& ec) { - BOOST_LOG_TRIVIAL(info) << "service sockets to fibers: starting relay on local port tcp " - << local_port_; +void SocketsToFibers::start(boost::system::error_code& ec) { + BOOST_LOG_TRIVIAL(info) + << "service sockets to fibers: starting relay on local port tcp " + << local_port_; boost::system::error_code close_ec; // Accept on all local interfaces @@ -58,23 +59,25 @@ void LocalForwarderService::start(boost::system::error_code& ec) { } template -void LocalForwarderService::stop(boost::system::error_code& ec) { +void SocketsToFibers::stop(boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(info) << "service sockets to fibers: stopping"; socket_acceptor_.close(ec); if (ec) { - BOOST_LOG_TRIVIAL(debug) << "service sockets to fibers: " << ec.message() << std::endl; + BOOST_LOG_TRIVIAL(debug) << "service sockets to fibers: " << ec.message() + << std::endl; } manager_.stop_all(); } template -uint32_t LocalForwarderService::service_type_id() { +uint32_t SocketsToFibers::service_type_id() { return factory_id; } template -void LocalForwarderService::StartAcceptSockets() { - BOOST_LOG_TRIVIAL(trace) << "service sockets to fibers: accepting new clients"; +void SocketsToFibers::StartAcceptSockets() { + BOOST_LOG_TRIVIAL(trace) + << "service sockets to fibers: accepting new clients"; if (!socket_acceptor_.is_open()) { return; @@ -82,11 +85,12 @@ void LocalForwarderService::StartAcceptSockets() { socket_acceptor_.async_accept( socket_, - Then(&LocalForwarderService::SocketAcceptHandler, this->SelfFromThis())); + Then(&SocketsToFibers::SocketAcceptHandler, this->SelfFromThis())); } template -void LocalForwarderService::SocketAcceptHandler(const boost::system::error_code& ec) { +void SocketsToFibers::SocketAcceptHandler( + const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "service sockets to fibers: accept handler"; if (!socket_acceptor_.is_open()) { @@ -97,18 +101,18 @@ void LocalForwarderService::SocketAcceptHandler(const boost::system::erro endpoint ep(this->get_demux(), remote_port_); fiber_.async_connect( ep, - Then(&LocalForwarderService::FiberConnectHandler, this->SelfFromThis())); + Then(&SocketsToFibers::FiberConnectHandler, this->SelfFromThis())); } } template -void LocalForwarderService::FiberConnectHandler(const boost::system::error_code& ec) { +void SocketsToFibers::FiberConnectHandler( + const boost::system::error_code& ec) { BOOST_LOG_TRIVIAL(trace) << "service sockets to fibers: connect handler"; if (!ec) { - auto session = SessionForwarder::create(&manager_, - std::move(socket_), - std::move(fiber_)); + auto session = SessionForwarder::create( + &manager_, std::move(socket_), std::move(fiber_)); boost::system::error_code e; manager_.start(session, e); } diff --git a/src/services/user_services/port_forwarding.h b/src/services/user_services/port_forwarding.h index d5b159e1..0518292e 100644 --- a/src/services/user_services/port_forwarding.h +++ b/src/services/user_services/port_forwarding.h @@ -109,7 +109,7 @@ class PortForwading : public BaseUserService std::vector> result; services::admin::CreateServiceRequest r_socks( - services::fibers_to_sockets::RemoteForwarderService< + services::fibers_to_sockets::FibersToSockets< Demux>::GetCreateRequest(relay_fiber_port_, remote_addr_, remote_port_)); @@ -133,8 +133,8 @@ class PortForwading : public BaseUserService virtual bool StartLocalServices(Demux& demux) { services::admin::CreateServiceRequest l_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(local_port_, relay_fiber_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + local_port_, relay_fiber_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); @@ -146,7 +146,7 @@ class PortForwading : public BaseUserService virtual uint32_t CheckRemoteServiceStatus(Demux& demux) { services::admin::CreateServiceRequest r_socks( - services::fibers_to_sockets::RemoteForwarderService< + services::fibers_to_sockets::FibersToSockets< Demux>::GetCreateRequest(relay_fiber_port_, remote_addr_, remote_port_)); auto p_service_factory = @@ -169,7 +169,7 @@ class PortForwading : public BaseUserService return remoteServiceId_; } else { services::admin::CreateServiceRequest r_forward( - services::fibers_to_sockets::RemoteForwarderService< + services::fibers_to_sockets::FibersToSockets< Demux>::GetCreateRequest(relay_fiber_port_, remote_addr_, remote_port_)); diff --git a/src/services/user_services/remote_port_forwarding.h b/src/services/user_services/remote_port_forwarding.h index 815890ee..76fc1d6b 100644 --- a/src/services/user_services/remote_port_forwarding.h +++ b/src/services/user_services/remote_port_forwarding.h @@ -109,8 +109,8 @@ class RemotePortForwading : public BaseUserService std::vector> result; services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, relay_fiber_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, relay_fiber_port_)); result.push_back(r_forward); @@ -132,7 +132,7 @@ class RemotePortForwading : public BaseUserService virtual bool StartLocalServices(Demux& demux) { services::admin::CreateServiceRequest l_forward( - services::fibers_to_sockets::RemoteForwarderService< + services::fibers_to_sockets::FibersToSockets< Demux>::GetCreateRequest(relay_fiber_port_, local_addr_, local_port_)); @@ -146,8 +146,8 @@ class RemotePortForwading : public BaseUserService virtual uint32_t CheckRemoteServiceStatus(Demux& demux) { services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, relay_fiber_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, relay_fiber_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); auto status = p_service_factory->GetStatus(r_forward.service_id(), @@ -169,8 +169,8 @@ class RemotePortForwading : public BaseUserService return remoteServiceId_; } else { services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, relay_fiber_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, relay_fiber_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); diff --git a/src/services/user_services/remote_socks.h b/src/services/user_services/remote_socks.h index 2ca4b08f..e0c664d4 100644 --- a/src/services/user_services/remote_socks.h +++ b/src/services/user_services/remote_socks.h @@ -23,7 +23,7 @@ template class RemoteSocks : public BaseUserService { private: RemoteSocks(uint16_t remote_port) - : remote_port_(remote_port), remoteServiceId_(0), localServiceId_(0) {} + : remote_port_(remote_port), remote_service_id_(0), local_service_id_(0) {} public: static std::string GetFullParseName() { @@ -65,12 +65,12 @@ class RemoteSocks : public BaseUserService { } virtual std::vector> - GetRemoteServiceCreateVector() { + GetRemoteServiceCreateVector() { std::vector> result; services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, remote_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, remote_port_)); result.push_back(r_forward); @@ -97,15 +97,15 @@ class RemoteSocks : public BaseUserService { auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); boost::system::error_code ec; - localServiceId_ = p_service_factory->CreateRunNewService( + local_service_id_ = p_service_factory->CreateRunNewService( l_socks.service_id(), l_socks.parameters(), ec); return !ec; } virtual uint32_t CheckRemoteServiceStatus(Demux& demux) { services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, remote_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, remote_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); auto status = p_service_factory->GetStatus(r_forward.service_id(), @@ -118,30 +118,30 @@ class RemoteSocks : public BaseUserService { virtual void StopLocalServices(Demux& demux) { auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); - p_service_factory->StopService(localServiceId_); + p_service_factory->StopService(local_service_id_); } private: uint32_t GetRemoteServiceId(Demux& demux) { - if (remoteServiceId_) { - return remoteServiceId_; + if (remote_service_id_) { + return remote_service_id_; } else { services::admin::CreateServiceRequest r_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(remote_port_, remote_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + remote_port_, remote_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); auto id = p_service_factory->GetIdFromParameters(r_forward.service_id(), r_forward.parameters()); - remoteServiceId_ = id; + remote_service_id_ = id; return id; } } uint16_t remote_port_; - uint32_t remoteServiceId_; - uint32_t localServiceId_; + uint32_t remote_service_id_; + uint32_t local_service_id_; }; } // services diff --git a/src/services/user_services/socks.h b/src/services/user_services/socks.h index f6830392..72db7b88 100644 --- a/src/services/user_services/socks.h +++ b/src/services/user_services/socks.h @@ -90,8 +90,8 @@ class Socks : public BaseUserService { virtual bool StartLocalServices(Demux& demux) { services::admin::CreateServiceRequest l_forward( - services::sockets_to_fibers::LocalForwarderService< - Demux>::GetCreateRequest(local_port_, local_port_)); + services::sockets_to_fibers::SocketsToFibers::GetCreateRequest( + local_port_, local_port_)); auto p_service_factory = ServiceFactoryManager::GetServiceFactory(&demux); diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 1e82530a..eca70c2c 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -17,8 +17,6 @@ set(load_config_test_source_files ${COMMON_ERROR_FILES} ) -source_group ("Test Files" FILES ${load_config_test_source_files}) - add_target("load_config_tests" TYPE executable @@ -43,8 +41,6 @@ set(fiber_asio_test_source_files ${COMMON_ERROR_FILES} ) -source_group ("Test Files" FILES ${fiber_asio_test_source_files}) - add_target("fiber_asio_tests" TYPE executable @@ -68,8 +64,6 @@ set(ssf_client_server_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${ssf_client_server_source_files}) - add_target("ssf_client_server_tests" TYPE executable @@ -93,8 +87,6 @@ set(ssf_client_server_cipher_suites_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${ssf_client_server_cipher_suites_source_files}) - add_target("ssf_client_server_cipher_suites_tests" TYPE executable @@ -118,8 +110,6 @@ set(socks_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${socks_test_source_files}) - add_target("socks_tests" TYPE executable @@ -143,8 +133,6 @@ set(remote_socks_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${remote_socks_test_source_files}) - add_target("remote_socks_tests" TYPE executable @@ -168,8 +156,6 @@ set(stream_forwarding_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${stream_forwarding_test_source_files}) - add_target("stream_forward_tests" TYPE executable @@ -193,8 +179,6 @@ set(remote_stream_forwarding_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${remote_stream_forwarding_test_source_files}) - add_target("remote_stream_forward_tests" TYPE executable @@ -218,8 +202,6 @@ set(udp_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${udp_test_source_files}) - add_target("udp_forward_tests" TYPE executable @@ -243,8 +225,6 @@ set(remote_udp_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${remote_udp_test_source_files}) - add_target("remote_udp_forward_tests" TYPE executable @@ -268,8 +248,6 @@ set(bouncing_test_source_files ${SSF_SOURCES} ) -source_group ("Test Files" FILES ${bouncing_test_source_files}) - add_target("bouncing_tests" TYPE executable @@ -285,4 +263,56 @@ add_target("bouncing_tests" target_link_libraries(bouncing_tests gtest gtest_main) add_test( NAME bouncing_tests - COMMAND $) \ No newline at end of file + COMMAND $) + + +# --- File copy from client test + +file(MAKE_DIRECTORY ${project_BINARY_DIR}/src/tests/files_to_copy) +file(MAKE_DIRECTORY ${project_BINARY_DIR}/src/tests/files_copied) + +FILE(GLOB_RECURSE TEST_FILES_TO_COPY + "${project_SRC_DIR}/tests/files_to_copy/*" +) + +file(COPY ${TEST_FILES_TO_COPY} DESTINATION ${project_BINARY_DIR}/src/tests/files_to_copy) + +set(file_copy_from_client_files + "file_copy_from_client_tests.cpp" + ${SSF_SOURCES} +) + +add_target("file_copy_from_client_tests" + TYPE + executable + LINKS + ${OpenSSL_LIBRARIES} + ${Boost_LIBRARIES} + ${PLATFORM_SPECIFIC_LIB_DEP} + PREFIX_SKIP .*/src + HEADER_FILTER "\\.h(h|m|pp|xx|\\+\\+)?" + FILES + ${file_copy_from_client_files} +) +target_link_libraries(file_copy_from_client_tests gtest gtest_main) +add_test( + NAME file_copy_from_client_tests + COMMAND $) + + +# --- Unit tests list +project_group( + "Unit tests" + load_config_tests + fiber_asio_tests + ssf_client_server_tests + ssf_client_server_cipher_suites_tests + socks_tests + remote_socks_tests + stream_forward_tests + remote_stream_forward_tests + udp_forward_tests + remote_udp_forward_tests + bouncing_tests + file_copy_from_client_tests +) \ No newline at end of file diff --git a/src/tests/bouncing_tests.cpp b/src/tests/bouncing_tests.cpp index f1d4a45d..72d3c792 100644 --- a/src/tests/bouncing_tests.cpp +++ b/src/tests/bouncing_tests.cpp @@ -19,214 +19,15 @@ #include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" #include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" #include "core/network_virtual_layer_policies/bounce_protocol_policy.h" +#include "core/parser/bounce_parser.h" #include "core/transport_virtual_layer_policies/transport_protocol_policy.h" #include "services/initialisation.h" #include "services/user_services/port_forwarding.h" -class DummyClient { - public: - DummyClient(size_t size) - : io_service_(), - p_worker_(new boost::asio::io_service::work(io_service_)), - socket_(io_service_), - size_(size) {} - - bool Run() { - t_ = boost::thread([&]() { io_service_.run(); }); - - boost::asio::ip::tcp::resolver r(io_service_); - boost::asio::ip::tcp::resolver::query q("127.0.0.1", "5454"); - boost::system::error_code ec; - boost::asio::connect(socket_, r.resolve(q), ec); - - if (ec) { - BOOST_LOG_TRIVIAL(error) << "dummy client : fail to connect " - << ec.value(); - return false; - } - - boost::asio::write(socket_, boost::asio::buffer(&size_, sizeof(size_t)), - ec); - - if (ec) { - BOOST_LOG_TRIVIAL(error) << "dummy client : fail to write " << ec.value(); - return false; - } - - size_t received(0); - size_t n(0); - while (received < size_) { - boost::system::error_code ec_read; - n = socket_.read_some(boost::asio::buffer(one_buffer_), ec_read); - - if (n == 0) { - return false; - } - - if (ec_read) { - return false; - } - - if (!CheckOneBuffer(n)) { - return false; - } - received += n; - } - - return received == size_; - } - - void Stop() { - boost::system::error_code ec; - socket_.close(ec); - - p_worker_.reset(); - - t_.join(); - io_service_.stop(); - } - - private: - bool CheckOneBuffer(size_t n) { - for (size_t i = 0; i < n; ++i) { - if (one_buffer_[i] != 1) { - return false; - } - } - - return true; - } - - boost::asio::io_service io_service_; - std::unique_ptr p_worker_; - boost::asio::ip::tcp::socket socket_; - boost::thread t_; - size_t size_; - std::array one_buffer_; -}; - -class DummyServer { - public: - DummyServer() - : io_service_(), - p_worker_(new boost::asio::io_service::work(io_service_)), - acceptor_(io_service_), - one_buffer_size_(10240), - one_buffer_(one_buffer_size_) { - for (size_t i = 0; i < one_buffer_size_; ++i) { - one_buffer_[i] = 1; - } - } - - void Run() { - for (uint8_t i = 1; i <= boost::thread::hardware_concurrency(); ++i) { - threads_.create_thread([&]() { io_service_.run(); }); - } - - boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 5354); - boost::asio::socket_base::reuse_address option(true); - - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(option); - acceptor_.bind(endpoint); - acceptor_.listen(); - - do_accept(); - } - - void Stop() { - boost::system::error_code ec; - acceptor_.close(ec); - - p_worker_.reset(); - - threads_.join_all(); - io_service_.stop(); - } - - private: - void do_accept() { - auto p_socket = std::make_shared(io_service_); - acceptor_.async_accept(*p_socket, boost::bind(&DummyServer::handle_accept, - this, p_socket, _1)); - } - - void handle_accept(std::shared_ptr p_socket, - const boost::system::error_code& ec) { - if (!ec) { - auto p_size = std::make_shared(0); - boost::asio::async_read(*p_socket, - boost::asio::buffer(p_size.get(), sizeof(size_t)), - boost::bind(&DummyServer::handle_send, this, - p_socket, p_size, true, _1, _2)); - do_accept(); - } else { - p_socket->close(); - } - } - - void handle_send(std::shared_ptr p_socket, - std::shared_ptr p_size, bool first, - const boost::system::error_code& ec, - size_t tranferred_bytes) { - if (!ec) { - if (!first) { - (*p_size) -= tranferred_bytes; - } - - if ((*p_size)) { - if ((*p_size) > one_buffer_size_) { - boost::asio::async_write( - *p_socket, boost::asio::buffer(one_buffer_, one_buffer_size_), - boost::bind(&DummyServer::handle_send, this, p_socket, p_size, - false, _1, _2)); - } else { - boost::asio::async_write( - *p_socket, boost::asio::buffer(one_buffer_, (*p_size)), - boost::bind(&DummyServer::handle_send, this, p_socket, p_size, - false, _1, _2)); - } - } else { - boost::asio::async_read(*p_socket, boost::asio::buffer(one_buffer_, 1), - [=](const boost::system::error_code&, - size_t) { p_socket->close(); }); - } - } else { - p_socket->close(); - } - } - - boost::asio::io_service io_service_; - std::unique_ptr p_worker_; - boost::asio::ip::tcp::acceptor acceptor_; - size_t one_buffer_size_; - std::vector one_buffer_; - boost::thread_group threads_; -}; - -std::string get_remote_addr(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(0, position); - } else { - return ""; - } -} - -std::string get_remote_port(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(position + 1); - } else { - return ""; - } -} - //----------------------------------------------------------------------------- TEST(BouncingTests, BouncingChain) { + using BounceParser = ssf::parser::BounceParser; using Server = ssf::SSFServer; @@ -298,17 +99,13 @@ TEST(BouncingTests, BouncingChain) { std::vector client_options; std::string error_msg; - //auto p_service = ssf::services::PortForwading::CreateServiceOptions( - // "5454:127.0.0.1:5354", &error_msg); - - //client_options.push_back(p_service); std::map params; auto first = bouncers.front(); bouncers.pop_front(); - params["remote_addr"] = get_remote_addr(first); - params["remote_port"] = get_remote_port(first); + params["remote_addr"] = BounceParser::GetRemoteAddress(first); + params["remote_port"] = BounceParser::GetRemotePort(first); std::ostringstream ostrs; boost::archive::text_oarchive ar(ostrs); @@ -338,13 +135,6 @@ TEST(BouncingTests, BouncingChain) { return; } - - /*if (type == ssf::services::initialisation::SERVICE && - p_user_service->GetName() == "forward") { - service_set.set_value(!ec); - - return; - }*/ }; Client client(client_io_service, "127.0.0.1", @@ -354,7 +144,6 @@ TEST(BouncingTests, BouncingChain) { network_set.get_future().wait(); transport_set.get_future().wait(); - //service_set.get_future().wait(); { boost::recursive_mutex::scoped_lock lock(mutex); } diff --git a/src/tests/copy_file_test_fixture.h b/src/tests/copy_file_test_fixture.h new file mode 100644 index 00000000..7c5b740b --- /dev/null +++ b/src/tests/copy_file_test_fixture.h @@ -0,0 +1,283 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common/config/config.h" + +#include "core/client/client.h" +#include "core/server/server.h" + +#include "core/network_virtual_layer_policies/link_policies/ssl_policy.h" +#include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" +#include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" +#include "core/network_virtual_layer_policies/bounce_protocol_policy.h" +#include "core/transport_virtual_layer_policies/transport_protocol_policy.h" + +#include "services/initialisation.h" +#include "services/user_services/copy_file_service.h" + +class CopyFileTestFixture : public ::testing::Test { + public: + typedef boost::asio::ip::tcp::socket socket; + typedef ssf::SSLWrapper<> ssl_socket; + typedef boost::asio::fiber::basic_fiber_demux demux; + typedef ssf::services::BaseUserService::BaseUserServicePtr + BaseUserServicePtr; + + protected: + CopyFileTestFixture() + : client_io_service_(), + p_client_worker_(new boost::asio::io_service::work(client_io_service_)), + server_io_service_(), + p_server_worker_(new boost::asio::io_service::work(server_io_service_)), + p_ssf_client_(nullptr), + p_ssf_server_(nullptr) {} + + ~CopyFileTestFixture() {} + + virtual void SetUp() { + StartServer(); + StartClient(); + } + + virtual void TearDown() { + StopClientThreads(); + StopServerThreads(); + + // Clean receiver path + boost::filesystem::path receiver_path(GetOutputPattern()); + if (boost::filesystem::is_directory(receiver_path)) { + for (boost::filesystem::directory_iterator end_it, it(receiver_path); + it != end_it; ++it) { + std::remove(it->path().string().c_str()); + } + return; + } + + if (boost::filesystem::is_regular_file(receiver_path)) { + std::remove(GetOutputPattern().c_str()); + } + } + + void StartServer() { + ssf::Config ssf_config; + + p_ssf_server_.reset( + new ssf::SSFServer(server_io_service_, + ssf_config, 8000)); + + StartServerThreads(); + p_ssf_server_->run(); + } + + virtual void StartClient() { + std::vector client_services; + boost::system::error_code ec; + auto p_service = + ssf::services::CopyFileService::CreateServiceFromParams( + GetFromStdin(), GetFromLocalToRemote(), GetInputPattern(), + GetOutputPattern(), ec); + + client_services.push_back(p_service); + + std::map params( + {{"remote_addr", "127.0.0.1"}, {"remote_port", "8000"}}); + + ssf::Config ssf_config; + + p_ssf_client_.reset(new ssf::SSFClient< + ssf::SSLPolicy, ssf::NullLinkAuthenticationPolicy, + ssf::BounceProtocolPolicy, ssf::TransportProtocolPolicy>( + client_io_service_, "127.0.0.1", "8000", ssf_config, client_services, + boost::bind(&CopyFileTestFixture::SSFClientCallback, this, _1, _2, + _3))); + StartClientThreads(); + p_ssf_client_->run(params); + } + + bool Wait() { + auto network_set_future = network_set_.get_future(); + auto service_set_future = service_set_.get_future(); + auto transport_set_future = transport_set_.get_future(); + + network_set_future.wait(); + service_set_future.wait(); + transport_set_future.wait(); + + return network_set_future.get() && service_set_future.get() && + transport_set_future.get(); + } + + bool WaitClose() { + auto close_future = close_set_.get_future(); + close_future.wait(); + return close_future.get(); + } + + virtual bool GetFromStdin() = 0; + virtual bool GetFromLocalToRemote() = 0; + virtual std::string GetInputPattern() = 0; + + virtual std::string GetOutputPattern() { return "files_copied/"; } + + void StartServerThreads() { + for (uint8_t i = 1; i <= boost::thread::hardware_concurrency(); ++i) { + server_threads_.create_thread([&]() { server_io_service_.run(); }); + } + } + + void StartClientThreads() { + for (uint8_t i = 1; i <= boost::thread::hardware_concurrency(); ++i) { + client_threads_.create_thread([&]() { client_io_service_.run(); }); + } + } + + void StopServerThreads() { + p_ssf_server_->stop(); + p_server_worker_.reset(); + server_threads_.join_all(); + server_io_service_.stop(); + } + + void StopClientThreads() { + p_client_worker_.reset(); + client_threads_.join_all(); + client_io_service_.stop(); + } + + void SSFClientCallback(ssf::services::initialisation::type type, + BaseUserServicePtr p_user_service, + const boost::system::error_code& ec) { + if (type == ssf::services::initialisation::NETWORK) { + network_set_.set_value(!ec); + if (ec) { + service_set_.set_value(false); + transport_set_.set_value(false); + } + return; + } + + if (type == ssf::services::initialisation::TRANSPORT) { + transport_set_.set_value(!ec); + return; + } + + if (type == ssf::services::initialisation::SERVICE && + p_user_service->GetName() == "copy_file") { + service_set_.set_value(!ec); + return; + } + + if (type == ssf::services::initialisation::CLOSE) { + close_set_.set_value(true); + return; + } + } + + protected: + boost::asio::io_service client_io_service_; + std::unique_ptr p_client_worker_; + boost::thread_group client_threads_; + + boost::asio::io_service server_io_service_; + std::unique_ptr p_server_worker_; + boost::thread_group server_threads_; + std::unique_ptr> p_ssf_client_; + std::unique_ptr> p_ssf_server_; + + std::promise network_set_; + std::promise transport_set_; + std::promise service_set_; + std::promise close_set_; +}; + +class CopyNoFileFromClientToRemoteTest : public CopyFileTestFixture { + public: + CopyNoFileFromClientToRemoteTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return false; } + + virtual bool GetFromLocalToRemote() { return true; } + + virtual std::string GetInputPattern() { + return "files_to_copy/test_filex.txt"; + } +}; + +class CopyUniqueFileFromClientToRemoteTest : public CopyFileTestFixture { + public: + CopyUniqueFileFromClientToRemoteTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return false; } + + virtual bool GetFromLocalToRemote() { return true; } + + virtual std::string GetInputPattern() { + return "files_to_copy/test_file1.txt"; + } +}; + +class CopyGlobFileFromClientToRemoteTest : public CopyFileTestFixture { + public: + CopyGlobFileFromClientToRemoteTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return false; } + + virtual bool GetFromLocalToRemote() { return true; } + + virtual std::string GetInputPattern() { return "files_to_copy/test_*.txt"; } +}; + +class CopyUniqueFileFromRemoteToClientTest : public CopyFileTestFixture { + public: + CopyUniqueFileFromRemoteToClientTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return false; } + + virtual bool GetFromLocalToRemote() { return false; } + + virtual std::string GetInputPattern() { + return "files_to_copy/test_file1.txt"; + } +}; + +class CopyGlobFileFromRemoteToClientTest : public CopyFileTestFixture { + public: + CopyGlobFileFromRemoteToClientTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return false; } + + virtual bool GetFromLocalToRemote() { return false; } + + virtual std::string GetInputPattern() { return "files_to_copy/test_*.txt"; } +}; + +class CopyStdinFromClientToRemoteTest : public CopyFileTestFixture { + public: + CopyStdinFromClientToRemoteTest() : CopyFileTestFixture() {} + + virtual bool GetFromStdin() { return true; } + + virtual bool GetFromLocalToRemote() { return true; } + + virtual std::string GetInputPattern() { return "files_to_copy/test_*.txt"; } + + virtual std::string GetOutputPattern() { + return "files_copied/test_file1.txt"; + } +}; diff --git a/src/tests/file_copy_from_client_tests.cpp b/src/tests/file_copy_from_client_tests.cpp new file mode 100644 index 00000000..a6408c23 --- /dev/null +++ b/src/tests/file_copy_from_client_tests.cpp @@ -0,0 +1,148 @@ +#include "tests/copy_file_test_fixture.h" + +#include +#include + +#include + +using Md5Digest = std::array; + +Md5Digest GetMd5Sum(const std::string& filepath, + boost::system::error_code& ec) { + using Buffer = std::array; + + Md5Digest md5 = {{0}}; + Buffer buf = {{0}}; + + std::ifstream file(filepath, std::ifstream::binary); + MD5_CTX md5_context; + + if (!file.is_open()) { + ec.assign(boost::system::errc::bad_file_descriptor, + boost::system::get_system_category()); + return md5; + } + + MD5_Init(&md5_context); + do { + file.read(buf.data(), buf.size()); + MD5_Update(&md5_context, buf.data(), + static_cast(file.gcount())); + } while (!file.eof()); + + MD5_Final(md5.data(), &md5_context); + + return md5; +} + +void FileExistsAndIdentical(const std::string& source_filepath, + const std::string& test_filepath) { + ASSERT_TRUE(boost::filesystem::is_regular_file(test_filepath)) + << "The file " << test_filepath << " should exist in files_copied"; + + // Test source_file is equal to test_file + // This test could fail due to the closing of fiber to file session after the + // execution of this test + boost::system::error_code ec; + Md5Digest source_digest = GetMd5Sum(source_filepath, ec); + ASSERT_EQ(ec.value(), 0) << "Source file could not be digested"; + Md5Digest test_digest = GetMd5Sum(test_filepath, ec); + ASSERT_EQ(ec.value(), 0) << "Test file could not be digested"; + + ASSERT_TRUE(std::equal(source_digest.begin(), source_digest.end(), + test_digest.begin())) + << "MD5 sum of file " << source_filepath << " and " << test_filepath + << " are different"; +} + +//----------------------------------------------------------------------------- +TEST_F(CopyNoFileFromClientToRemoteTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + // Check if file exists and content is equal + boost::filesystem::path copied_file("files_copied/test_filex.txt"); + ASSERT_FALSE(boost::filesystem::is_regular_file(copied_file)) + << "The file test_filex.txt should not exist in files_copied"; +} + +//----------------------------------------------------------------------------- +TEST_F(CopyUniqueFileFromClientToRemoteTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + FileExistsAndIdentical("files_to_copy/test_file1.txt", + "files_copied/test_file1.txt"); +} + +//----------------------------------------------------------------------------- +TEST_F(CopyGlobFileFromClientToRemoteTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + FileExistsAndIdentical("files_to_copy/test_file1.txt", + "files_copied/test_file1.txt"); + FileExistsAndIdentical("files_to_copy/test_file2.txt", + "files_copied/test_file2.txt"); +} + +//----------------------------------------------------------------------------- +TEST_F(CopyUniqueFileFromRemoteToClientTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + FileExistsAndIdentical("files_to_copy/test_file1.txt", + "files_copied/test_file1.txt"); +} + +//----------------------------------------------------------------------------- +TEST_F(CopyGlobFileFromRemoteToClientTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + FileExistsAndIdentical("files_to_copy/test_file1.txt", + "files_copied/test_file1.txt"); + FileExistsAndIdentical("files_to_copy/test_file2.txt", + "files_copied/test_file2.txt"); +} + +//----------------------------------------------------------------------------- +TEST_F(CopyStdinFromClientToRemoteTest, CopyTest) { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); + + // stdin as test_file1.txt filebuf + std::ifstream in("files_to_copy/test_file1.txt", std::ifstream::binary); + std::streambuf* cinbuf = std::cin.rdbuf(); + std::cin.rdbuf(in.rdbuf()); + + ASSERT_TRUE(Wait()); + + ASSERT_TRUE(WaitClose()); + + FileExistsAndIdentical("files_to_copy/test_file1.txt", + "files_copied/test_file1.txt"); + + // restore stdin + std::cin.rdbuf(cinbuf); +} \ No newline at end of file diff --git a/src/tests/files_to_copy/test_file1.txt b/src/tests/files_to_copy/test_file1.txt new file mode 100644 index 00000000..53ef9a9f --- /dev/null +++ b/src/tests/files_to_copy/test_file1.txt @@ -0,0 +1,3 @@ +This is test file 1 + +It contains dummy data \ No newline at end of file diff --git a/src/tests/files_to_copy/test_file2.txt b/src/tests/files_to_copy/test_file2.txt new file mode 100644 index 00000000..8a00e4d9 --- /dev/null +++ b/src/tests/files_to_copy/test_file2.txt @@ -0,0 +1,3 @@ +This is test file 2 + +It contains more dummy data \ No newline at end of file From 71abf0f0f971500fb1a87acb3b708727ba66c75c Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Sat, 10 Oct 2015 21:00:25 +0200 Subject: [PATCH 11/13] Create ssfcp and rename SSF_Client as ssfc and SSF_Server as ssfs --- src/core/client/CMakeLists.txt | 31 ++- src/core/client/main.cpp | 137 ++++------- src/core/client/main_cp.cpp | 165 +++++++++++++ src/core/command_line/copy/command_line.cpp | 225 ++++++++++++++++++ src/core/command_line/copy/command_line.h | 80 +++++++ .../{ => standard}/command_line.cpp | 31 ++- .../{ => standard}/command_line.h | 20 +- src/core/server/CMakeLists.txt | 7 +- src/core/server/main.cpp | 52 ++-- 9 files changed, 608 insertions(+), 140 deletions(-) create mode 100644 src/core/client/main_cp.cpp create mode 100644 src/core/command_line/copy/command_line.cpp create mode 100644 src/core/command_line/copy/command_line.h rename src/core/command_line/{ => standard}/command_line.cpp (82%) rename src/core/command_line/{ => standard}/command_line.h (66%) diff --git a/src/core/client/CMakeLists.txt b/src/core/client/CMakeLists.txt index 1b5b2d1c..fdc0a33e 100644 --- a/src/core/client/CMakeLists.txt +++ b/src/core/client/CMakeLists.txt @@ -1,23 +1,27 @@ cmake_minimum_required(VERSION 2.8) -set(project_NAME "SSF_Client") +set(project_NAME "ssfc") project(${project_NAME}) set(CLIENT_FILES - main.cpp - client.h - client.ipp) + main.cpp) + +set(CLIENT_CP_PROJECT_NAME "ssfcp") +set(CLIENT_CP_FILES + main_cp.cpp) include_directories( ${OpenSSL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) +# --- SSF_Client add_target(${project_NAME} TYPE executable ${EXEC_FLAG} FILES ${CLIENT_FILES} ${SSF_SOURCES} + ${CORE_COMMAND_LINE_STANDARD_FILES} ${ICON_RC} PREFIX_SKIP ${project_SRC_DIR}) @@ -28,3 +32,22 @@ if (APPLE) endif (APPLE) target_link_libraries(${project_NAME} ${Boost_LIBRARIES} ${OpenSSL_LIBRARIES} ${PLATFORM_SPECIFIC_LIB_DEP}) + +# --- SSF_Client_cp +add_target(${CLIENT_CP_PROJECT_NAME} + TYPE + executable ${EXEC_FLAG} + FILES + ${CLIENT_CP_FILES} + ${SSF_SOURCES} + ${CORE_COMMAND_LINE_COPY_FILES} + ${ICON_RC} + PREFIX_SKIP + ${project_SRC_DIR}) + +if (APPLE) + set_source_files_properties(${ICON_RC} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") + set_target_properties(${CLIENT_CP_PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_ICON_FILE ${ICON_NAME}) +endif (APPLE) + +target_link_libraries(${CLIENT_CP_PROJECT_NAME} ${Boost_LIBRARIES} ${OpenSSL_LIBRARIES} ${PLATFORM_SPECIFIC_LIB_DEP}) diff --git a/src/core/client/main.cpp b/src/core/client/main.cpp index a4abda96..e104e318 100644 --- a/src/core/client/main.cpp +++ b/src/core/client/main.cpp @@ -1,21 +1,23 @@ -#include "client.h" - #include -#include - -#include - -#include -#include - +#include #include -#include #include +#include +#include #include "common/config/config.h" -#include "core/command_line/command_line.h" +#include "core/client/client.h" + +#include "core/command_line/standard/command_line.h" +#include "core/parser/bounce_parser.h" +#include "core/factories/service_option_factory.h" +#include "core/network_virtual_layer_policies/bounce_protocol_policy.h" +#include "core/network_virtual_layer_policies/link_policies/ssl_policy.h" +#include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" +#include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" +#include "core/transport_virtual_layer_policies/transport_protocol_policy.h" #include "services/initialisation.h" #include "services/user_services/base_user_service.h" @@ -26,55 +28,28 @@ #include "services/user_services/udp_port_forwarding.h" #include "services/user_services/udp_remote_port_forwarding.h" -#include "core/factories/service_option_factory.h" - -#include "core/network_virtual_layer_policies/link_policies/ssl_policy.h" -#include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" -#include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" -#include "core/network_virtual_layer_policies/bounce_protocol_policy.h" -#include "core/transport_virtual_layer_policies/transport_protocol_policy.h" - -void init() { - boost::log::core::get()->set_filter( - boost::log::trivial::severity >= boost::log::trivial::info); -} - -std::string get_remote_addr(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(0, position); - } else { - return ""; - } -} - -std::string get_remote_port(const std::string& remote_endpoint_string) { - size_t position = remote_endpoint_string.find(":"); - - if (position != std::string::npos) { - return remote_endpoint_string.substr(position + 1); - } else { - return ""; - } +void Init() { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); } int main(int argc, char** argv) { #ifdef TLS_OVER_TCP_LINK - typedef ssf::SSFClient Client; + using Client = + ssf::SSFClient; #elif TCP_ONLY_LINK - typedef ssf::SSFClient Client; + using Client = + ssf::SSFClient; #endif - typedef Client::demux demux; + using demux = Client::demux; + using BaseUserServicePtr = + ssf::services::BaseUserService::BaseUserServicePtr; + using BounceParser = ssf::parser::BounceParser; - init(); - - typedef ssf::services::BaseUserService::BaseUserServicePtr - BaseUserServicePtr; + Init(); // Register user services supported ssf::services::Socks::RegisterToServiceOptionFactory(); @@ -82,38 +57,39 @@ int main(int argc, char** argv) { ssf::services::PortForwading::RegisterToServiceOptionFactory(); ssf::services::RemotePortForwading::RegisterToServiceOptionFactory(); ssf::services::UdpPortForwading::RegisterToServiceOptionFactory(); - ssf::services::UdpRemotePortForwading::RegisterToServiceOptionFactory(); + ssf::services::UdpRemotePortForwading< + demux>::RegisterToServiceOptionFactory(); boost::program_options::options_description options = ssf::ServiceOptionFactory::GetOptionDescriptions(); // Parse the command line - ssf::CommandLine cmd; - std::vector userServicesOptions; + ssf::command_line::standard::CommandLine cmd; + std::vector user_services; boost::system::error_code ec; auto parameters = cmd.parse(argc, argv, options, ec); if (ec) { - BOOST_LOG_TRIVIAL(error) << "client: wrong arguments" << std::endl; + BOOST_LOG_TRIVIAL(error) << "client: wrong command line arguments"; return 1; } + // Initialize requested user services (socks, port forwarding) for (const auto& parameter : parameters) { for (const auto& single_parameter : parameter.second) { boost::system::error_code ec; auto p_service_options = ssf::ServiceOptionFactory::ParseServiceLine( - parameter.first, single_parameter, ec); + parameter.first, single_parameter, ec); if (!ec) { - userServicesOptions.push_back(p_service_options); + user_services.push_back(p_service_options); } else { BOOST_LOG_TRIVIAL(error) << "client: wrong parameter " - << parameter.first << " : " - << single_parameter << " " - << ec << " : " << ec.message(); + << parameter.first << " : " << single_parameter + << " : " << ec.message(); } } } @@ -133,7 +109,8 @@ int main(int argc, char** argv) { ssf::Config ssf_config = ssf::LoadConfig(cmd.config_file(), ec_config); if (ec_config) { - BOOST_LOG_TRIVIAL(error) << "client: invalid config file format" << std::endl; + BOOST_LOG_TRIVIAL(error) << "client: invalid config file format" + << std::endl; return 0; } @@ -147,45 +124,32 @@ int main(int argc, char** argv) { boost::system::error_code ec; try { io_service.run(ec); - } - catch (std::exception e) { - BOOST_LOG_TRIVIAL(error) << "client: exception in io_service run " << e.what(); + } catch (std::exception e) { + BOOST_LOG_TRIVIAL(error) << "client: exception in io_service run " + << e.what(); } }; threads.create_thread(lambda); } - auto callback = [](ssf::services::initialisation::type, - BaseUserServicePtr, + auto callback = [](ssf::services::initialisation::type, BaseUserServicePtr, const boost::system::error_code&) {}; - // Initiating and starting the client + // Initiate and start client Client client(io_service, cmd.addr(), std::to_string(cmd.port()), ssf_config, - userServicesOptions, callback); + user_services, callback); std::map params; - std::list bouncers; - - if (cmd.bounce_file() != "") { - std::ifstream infile(cmd.bounce_file()); - if (infile.is_open()) { - std::string line; - - while (std::getline(infile, line)) { - bouncers.push_back(line); - } - - infile.close(); - } - } + std::list bouncers = + BounceParser::ParseBounceFile(cmd.bounce_file()); if (bouncers.size()) { auto first = bouncers.front(); bouncers.pop_front(); - params["remote_addr"] = get_remote_addr(first); - params["remote_port"] = get_remote_port(first); + params["remote_addr"] = BounceParser::GetRemoteAddress(first); + params["remote_port"] = BounceParser::GetRemotePort(first); bouncers.push_back(cmd.addr() + ":" + std::to_string(cmd.port())); } else { params["remote_addr"] = cmd.addr(); @@ -201,9 +165,10 @@ int main(int argc, char** argv) { client.run(params); getchar(); + client.stop(); - io_service.stop(); threads.join_all(); + io_service.stop(); return 0; } diff --git a/src/core/client/main_cp.cpp b/src/core/client/main_cp.cpp new file mode 100644 index 00000000..b7b531b8 --- /dev/null +++ b/src/core/client/main_cp.cpp @@ -0,0 +1,165 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "common/config/config.h" + +#include "core/client/client.h" + +#include "core/command_line/copy/command_line.h" +#include "core/parser/bounce_parser.h" +#include "core/factories/service_option_factory.h" +#include "core/network_virtual_layer_policies/bounce_protocol_policy.h" +#include "core/network_virtual_layer_policies/link_policies/ssl_policy.h" +#include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" +#include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" +#include "core/transport_virtual_layer_policies/transport_protocol_policy.h" + +#include "services/initialisation.h" +#include "services/user_services/base_user_service.h" +#include "services/user_services/copy_file_service.h" + +void Init() { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); +} + +int main(int argc, char** argv) { +#ifdef TLS_OVER_TCP_LINK + using Client = + ssf::SSFClient; +#elif TCP_ONLY_LINK + using Client = + ssf::SSFClient; +#endif + + using Demux = Client::demux; + using BaseUserServicePtr = + ssf::services::BaseUserService::BaseUserServicePtr; + using BounceParser = ssf::parser::BounceParser; + + Init(); + + // Parse the command line + ssf::command_line::copy::CommandLine cmd; + std::vector user_services; + + boost::system::error_code ec; + + cmd.parse(argc, argv, ec); + + if (ec) { + BOOST_LOG_TRIVIAL(error) << "client: wrong command line arguments"; + return 1; + } + + // Create and initialize copy user service + auto p_copy_service = + ssf::services::CopyFileService::CreateServiceFromParams( + cmd.from_stdin(), cmd.from_local_to_remote(), cmd.input_pattern(), + cmd.output_pattern(), ec); + + if (ec) { + BOOST_LOG_TRIVIAL(error) << "client: copy service could not be created"; + return 1; + } + + user_services.push_back(p_copy_service); + + if (!cmd.IsAddrSet()) { + BOOST_LOG_TRIVIAL(error) << "client: no remote host provided -- Exiting"; + return 1; + } + + if (!cmd.IsPortSet()) { + BOOST_LOG_TRIVIAL(error) << "client: no host port provided -- Exiting"; + return 1; + } + + // Load SSF config if any + boost::system::error_code ec_config; + ssf::Config ssf_config = ssf::LoadConfig(cmd.config_file(), ec_config); + + if (ec_config) { + BOOST_LOG_TRIVIAL(error) << "client: invalid config file format" + << std::endl; + return 0; + } + + // Initialize the asynchronous engine + boost::asio::io_service io_service; + std::unique_ptr p_worker( + new boost::asio::io_service::work(io_service)); + boost::thread_group threads; + std::promise closed; + + for (uint8_t i = 0; i < boost::thread::hardware_concurrency(); ++i) { + auto lambda = [&]() { + boost::system::error_code ec; + try { + io_service.run(ec); + } catch (std::exception e) { + BOOST_LOG_TRIVIAL(error) << "client: exception in io_service run " + << e.what(); + } + }; + + threads.create_thread(lambda); + } + + auto callback = + [&closed](ssf::services::initialisation::type type, BaseUserServicePtr, + const boost::system::error_code&) { + if (type == ssf::services::initialisation::CLOSE) { + closed.set_value(true); + return; + } + }; + + // Initiating and starting the client + Client client(io_service, cmd.addr(), std::to_string(cmd.port()), ssf_config, + user_services, callback); + + std::map params; + + std::list bouncers = + BounceParser::ParseBounceFile(cmd.bounce_file()); + + if (bouncers.size()) { + auto first = bouncers.front(); + bouncers.pop_front(); + params["remote_addr"] = BounceParser::GetRemoteAddress(first); + params["remote_port"] = BounceParser::GetRemotePort(first); + bouncers.push_back(cmd.addr() + ":" + std::to_string(cmd.port())); + } else { + params["remote_addr"] = cmd.addr(); + params["remote_port"] = std::to_string(cmd.port()); + } + + std::ostringstream ostrs; + boost::archive::text_oarchive ar(ostrs); + ar << BOOST_SERIALIZATION_NVP(bouncers); + + params["bouncing_nodes"] = ostrs.str(); + + client.run(params); + + // wait end transfer + closed.get_future().get(); + + p_worker.reset(); + + threads.join_all(); + + client.stop(); + io_service.stop(); + + return 0; +} diff --git a/src/core/command_line/copy/command_line.cpp b/src/core/command_line/copy/command_line.cpp new file mode 100644 index 00000000..e3cc015d --- /dev/null +++ b/src/core/command_line/copy/command_line.cpp @@ -0,0 +1,225 @@ +#include "core/command_line/copy/command_line.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/error/error.h" + +namespace ssf { +namespace command_line { +namespace copy { + +CommandLine::CommandLine() + : addr_(""), bounce_file_(""), addr_set_(false), port_set_(false) {} + +void CommandLine::parse(int argc, char* argv[], boost::system::error_code& ec) { + try { + // clang-format off + int opt; + boost::program_options::options_description desc("Basic options"); + desc.add_options() + ("help,h", "Produce help message"); + + boost::program_options::options_description options("Client options"); + options.add_options() + ("port,p", + boost::program_options::value(&opt)->default_value(8011), + "Set remote SSF server port") + ("bounces,b", + boost::program_options::value(), + "Set bounce file") + ("config,c", + boost::program_options::value(), + "Set config file"); + + boost::program_options::options_description copy_options("Copy options"); + copy_options.add_options() + ("stdin,t", boost::program_options::bool_switch()->default_value(false), "Input will be stdin") + ("arg1", + boost::program_options::value(), + "[host:]/absolute/path/file if host is present, the file will be copied from the remote host to local") + ("arg2", + boost::program_options::value(), + "[host:]/absolute/path/file if host is present, the file will be copied from local to host"); + // clang-format on + + boost::program_options::positional_options_description position_options; + position_options.add("arg1", 1); + position_options.add("arg2", 1); + + boost::program_options::options_description cmd_line; + cmd_line.add(desc).add(options).add(copy_options); + boost::program_options::variables_map vm; + boost::program_options::store( + boost::program_options::command_line_parser(argc, argv) + .options(cmd_line) + .positional(position_options) + .run(), + vm); + boost::program_options::notify(vm); + + if (vm.count("help")) { + std::cout << "usage : ssfcp [-p port] [-b bounces_file] [-c " + "config] [-h] [-t] arg1 [arg2]" << std::endl; + std::cout << cmd_line << std::endl; + } + + ec.assign(ssf::error::success, ssf::error::get_ssf_category()); + InternalParsing(vm, ec); + } catch (const std::exception&) { + ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); + } +} + +uint16_t CommandLine::port() const { return port_; } + +std::string CommandLine::addr() const { return addr_; } + +std::string CommandLine::bounce_file() const { return bounce_file_; } + +std::string CommandLine::config_file() const { return config_file_; } + +bool CommandLine::from_stdin() const { return from_stdin_; } + +bool CommandLine::from_local_to_remote() const { return from_local_to_remote_; } + +std::string CommandLine::input_pattern() const { return input_pattern_; } + +std::string CommandLine::output_pattern() const { return output_pattern_; } + +bool CommandLine::IsPortSet() const { return port_set_; } + +bool CommandLine::IsAddrSet() const { return addr_set_; } + +void CommandLine::InternalParsing( + const boost::program_options::variables_map& vm, + boost::system::error_code& ec) { + auto port_it = vm.find("port"); + if (port_it != vm.end()) { + ParsePort(port_it->second.as(), ec); + } + + auto stdin_it = vm.find("stdin"); + if (stdin_it != vm.end()) { + from_stdin_ = stdin_it->second.as(); + } + + auto bounces_file_it = vm.find("bounces"); + if (bounces_file_it != vm.end()) { + bounce_file_ = bounces_file_it->second.as(); + } + + auto config_it = vm.find("config"); + if (config_it != vm.end()) { + config_file_ = config_it->second.as(); + } + + auto first_arg_it = vm.find("arg1"); + if (first_arg_it != vm.end()) { + ParseFirstArgument(first_arg_it->second.as(), ec); + } else { + // there should always exist a first arg (input file, or host:input_file or + // host:output_file) + ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); + return; + } + + auto second_arg_it = vm.find("arg2"); + if (second_arg_it != vm.end()) { + ParseSecondArgument(second_arg_it->second.as(), ec); + } +} + +void CommandLine::ParsePort(int port, boost::system::error_code& parse_ec) { + if (port > 0 && port < 65536) { + port_ = static_cast(port); + port_set_ = true; + } else { + parse_ec.assign(ssf::error::invalid_argument, + ssf::error::get_ssf_category()); + } +} + +void CommandLine::ParseFirstArgument(const std::string& first_arg, + boost::system::error_code& parse_ec) { + if (from_stdin_) { + // expecting host:filepath syntax + ExtractHostPattern(first_arg, &addr_, &output_pattern_, parse_ec); + if (!parse_ec) { + addr_set_ = true; + from_local_to_remote_ = true; + } + } else { + // expecting host:dirpath or filepath syntax + boost::system::error_code extract_ec; + ExtractHostPattern(first_arg, &addr_, &input_pattern_, extract_ec); + if (!extract_ec) { + addr_set_ = true; + from_local_to_remote_ = false; + } else { + // not host:dirpath syntax so it is filepath syntax + input_pattern_ = first_arg; + from_local_to_remote_ = true; + } + } +} + +void CommandLine::ParseSecondArgument(const std::string& second_arg, + boost::system::error_code& parse_ec) { + if (from_stdin_) { + // no second arg should be provided + parse_ec.assign(ssf::error::invalid_argument, + ssf::error::get_ssf_category()); + } else { + // expecting host:filepath or filepath syntax + if (from_local_to_remote_) { + // expecting host:dirpath + ExtractHostPattern(second_arg, &addr_, &output_pattern_, parse_ec); + if (parse_ec) { + addr_set_ = false; + return; + } + + addr_set_ = true; + } else { + // expecting dirpath + output_pattern_ = second_arg; + } + + // Insert trailing slash if not present + auto last_slash_pos = output_pattern_.find_last_of('/'); + if (last_slash_pos != output_pattern_.size() - 1) { + output_pattern_ += '/'; + } + } +} + +void CommandLine::ExtractHostPattern(const std::string& string, + std::string* p_host, + std::string* p_pattern, + boost::system::error_code& ec) const { + std::size_t found = string.find_first_of(GetHostDirectorySeparator()); + if (found == std::string::npos || string.empty()) { + ec.assign(ssf::error::invalid_argument, ssf::error::get_ssf_category()); + return; + } + + *p_host = string.substr(0, found); + *p_pattern = string.substr(found + 1); + ec.assign(ssf::error::success, ssf::error::get_ssf_category()); +} + +char CommandLine::GetHostDirectorySeparator() const { return '@'; } + +} // copy +} // command_line +} // ssf diff --git a/src/core/command_line/copy/command_line.h b/src/core/command_line/copy/command_line.h new file mode 100644 index 00000000..858d8493 --- /dev/null +++ b/src/core/command_line/copy/command_line.h @@ -0,0 +1,80 @@ +#ifndef SSF_CORE_COMMAND_LINE_COPY_COMMAND_LINE_H_ +#define SSF_CORE_COMMAND_LINE_COPY_COMMAND_LINE_H_ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace ssf { +namespace command_line { +namespace copy { + +class CommandLine { + public: + CommandLine(); + + void parse(int argc, char* argv[], boost::system::error_code& ec); + + uint16_t port() const; + + std::string addr() const; + + std::string bounce_file() const; + + std::string config_file() const; + + bool from_stdin() const; + + bool from_local_to_remote() const; + + std::string input_pattern() const; + + std::string output_pattern() const; + + bool IsPortSet() const; + + bool IsAddrSet() const; + + private: + void InternalParsing(const boost::program_options::variables_map& vm, + boost::system::error_code& ec); + + void ParsePort(int port, boost::system::error_code& parse_ec); + + void ParseFirstArgument(const std::string& first_arg, + boost::system::error_code& parse_ec); + + void ParseSecondArgument(const std::string& second_arg, + boost::system::error_code& parse_ec); + + void ExtractHostPattern(const std::string& string, std::string* p_host, + std::string* p_pattern, + boost::system::error_code& ec) const; + + char GetHostDirectorySeparator() const; + + private: + uint16_t port_; + std::string addr_; + std::string bounce_file_; + std::string config_file_; + std::string input_pattern_; + std::string output_pattern_; + bool from_stdin_; + bool from_local_to_remote_; + bool addr_set_; + bool port_set_; +}; + +} // copy +} // command_line +} // ssf + +#endif // SSF_CORE_COMMAND_LINE_COPY_COMMAND_LINE_H_ diff --git a/src/core/command_line/command_line.cpp b/src/core/command_line/standard/command_line.cpp similarity index 82% rename from src/core/command_line/command_line.cpp rename to src/core/command_line/standard/command_line.cpp index 256cad53..b3fc025d 100644 --- a/src/core/command_line/command_line.cpp +++ b/src/core/command_line/standard/command_line.cpp @@ -1,4 +1,4 @@ -#include "command_line.h" +#include "core/command_line/standard/command_line.h" #include @@ -14,19 +14,23 @@ #include "common/error/error.h" -ssf::CommandLine::CommandLine(bool is_server) +namespace ssf { +namespace command_line { +namespace standard { + +CommandLine::CommandLine(bool is_server) : bounce_file_(""), addr_set_(false), port_set_(false), is_server_(is_server) {} -std::map> ssf::CommandLine::parse( +std::map> CommandLine::parse( int argc, char* argv[], boost::system::error_code& ec) { boost::program_options::options_description services; return parse(argc, argv, services, ec); } -std::map> ssf::CommandLine::parse( +std::map> CommandLine::parse( int ac, char* av[], const boost::program_options::options_description& services, boost::system::error_code& ec) { @@ -94,20 +98,19 @@ std::map> ssf::CommandLine::parse( } } -uint16_t ssf::CommandLine::port() { return port_; } +uint16_t CommandLine::port() { return port_; } -std::string ssf::CommandLine::addr() { return addr_; } +std::string CommandLine::addr() { return addr_; } -std::string ssf::CommandLine::bounce_file() { return bounce_file_; } +std::string CommandLine::bounce_file() { return bounce_file_; } -std::string ssf::CommandLine::config_file() { return config_file_; } +std::string CommandLine::config_file() { return config_file_; } -bool ssf::CommandLine::IsPortSet() { return port_set_; } +bool CommandLine::IsPortSet() { return port_set_; } -bool ssf::CommandLine::IsAddrSet() { return addr_set_; } +bool CommandLine::IsAddrSet() { return addr_set_; } -std::map> -ssf::CommandLine::InternalParsing( +std::map> CommandLine::InternalParsing( const boost::program_options::variables_map& vm, boost::system::error_code& ec) { std::map> result; @@ -137,3 +140,7 @@ ssf::CommandLine::InternalParsing( return result; } + +} // standard +} // command_line +} // ssf diff --git a/src/core/command_line/command_line.h b/src/core/command_line/standard/command_line.h similarity index 66% rename from src/core/command_line/command_line.h rename to src/core/command_line/standard/command_line.h index 53876cb5..a92950b1 100644 --- a/src/core/command_line/command_line.h +++ b/src/core/command_line/standard/command_line.h @@ -1,5 +1,5 @@ -#ifndef SSF_CORE_COMMAND_LINE_COMMAND_LINE_H -#define SSF_CORE_COMMAND_LINE_COMMAND_LINE_H +#ifndef SSF_CORE_COMMAND_LINE_STANDARD_COMMAND_LINE_H +#define SSF_CORE_COMMAND_LINE_STANDARD_COMMAND_LINE_H #include @@ -13,18 +13,20 @@ #include namespace ssf { +namespace command_line { +namespace standard { + class CommandLine { public: CommandLine(bool is_server = false); std::map> parse( - int argc, char* argv[], - boost::system::error_code& ec); + int argc, char* argv[], boost::system::error_code& ec); std::map> parse( - int ac, char *av[], - const boost::program_options::options_description &services, - boost::system::error_code &ec); + int ac, char* av[], + const boost::program_options::options_description& services, + boost::system::error_code& ec); uint16_t port(); @@ -52,6 +54,8 @@ class CommandLine { bool is_server_; }; +} // standard +} // command_line } // ssf -#endif // SSF_CORE_COMMAND_LINE_COMMAND_LINE_H \ No newline at end of file +#endif // SSF_CORE_COMMAND_LINE_STANDARD_COMMAND_LINE_H diff --git a/src/core/server/CMakeLists.txt b/src/core/server/CMakeLists.txt index b5e9ff1b..0fc2d339 100644 --- a/src/core/server/CMakeLists.txt +++ b/src/core/server/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 2.8) -set(project_NAME "SSF_Server") +set(project_NAME "ssfs") project(${project_NAME}) set(SERVER_FILES - main.cpp - server.h - server.ipp) + "${project_SRC_DIR}/core/server/main.cpp") include_directories( ${OpenSSL_INCLUDE_DIRS} @@ -17,6 +15,7 @@ add_target(${project_NAME} executable ${EXEC_FLAG} FILES ${SERVER_FILES} + ${CORE_COMMAND_LINE_STANDARD_FILES} ${SSF_SOURCES} ${ICON_RC} PREFIX_SKIP diff --git a/src/core/server/main.cpp b/src/core/server/main.cpp index 0f3a2851..102d7d0c 100644 --- a/src/core/server/main.cpp +++ b/src/core/server/main.cpp @@ -1,46 +1,44 @@ -#include "server.h" - #include +#include #include -#include #include +#include #include #include "common/config/config.h" -#include "core/command_line/command_line.h" +#include "core/command_line/standard/command_line.h" #include "core/network_virtual_layer_policies/link_policies/ssl_policy.h" #include "core/network_virtual_layer_policies/link_policies/tcp_policy.h" #include "core/network_virtual_layer_policies/link_authentication_policies/null_link_authentication_policy.h" #include "core/network_virtual_layer_policies/bounce_protocol_policy.h" +#include "core/server/server.h" #include "core/transport_virtual_layer_policies/transport_protocol_policy.h" -void init() -{ - boost::log::core::get()->set_filter( - boost::log::trivial::severity >= boost::log::trivial::info); +void Init() { + boost::log::core::get()->set_filter(boost::log::trivial::severity >= + boost::log::trivial::info); } -int main(int argc, char **argv){ +int main(int argc, char **argv) { #ifdef TLS_OVER_TCP_LINK - typedef ssf::SSFServer Server; + using Server = + ssf::SSFServer; #elif TCP_ONLY_LINK - typedef ssf::SSFServer Server; + using Server = + ssf::SSFServer; #endif - init(); + Init(); - // The object used to parse the command line - ssf::CommandLine cmd(true); + // The command line parser + ssf::command_line::standard::CommandLine cmd(true); - - // Parsing the command line + // Parse the command line boost::system::error_code ec; cmd.parse(argc, argv, ec); @@ -54,11 +52,12 @@ int main(int argc, char **argv){ ssf::Config ssf_config = ssf::LoadConfig(cmd.config_file(), ec_config); if (ec_config) { - BOOST_LOG_TRIVIAL(error) << "server: invalid config file format" << std::endl; + BOOST_LOG_TRIVIAL(error) << "server: invalid config file format" + << std::endl; return 1; } - // Starting the asynchronous engine + // Start the asynchronous engine boost::asio::io_service io_service; boost::asio::io_service::work worker(io_service); boost::thread_group threads; @@ -69,7 +68,8 @@ int main(int argc, char **argv){ try { io_service.run(ec); } catch (std::exception e) { - BOOST_LOG_TRIVIAL(error) << "server: exception in io_service run " << e.what(); + BOOST_LOG_TRIVIAL(error) << "server: exception in io_service run " + << e.what(); } }; @@ -78,15 +78,15 @@ int main(int argc, char **argv){ BOOST_LOG_TRIVIAL(info) << "Start SSF server on port " << cmd.port(); - // Initiating and starting the server + // Initiate and start the server Server server(io_service, ssf_config, cmd.port()); server.run(); - + getchar(); server.stop(); io_service.stop(); threads.join_all(); - + return 0; } \ No newline at end of file From cdf3d4e5fd18b00474f6239abe39cec957fa45be Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Thu, 15 Oct 2015 22:40:37 +0200 Subject: [PATCH 12/13] Add ssfcp in README.md Update CLI new naming (ssfc, ssfc) --- README.md | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bf9886cd..a3267b5d 100644 --- a/README.md +++ b/README.md @@ -227,10 +227,10 @@ The chain will be CLIENT -> SERVER1:PORT1 -> SERVER2:PORT2 -> SERVER3:PORT3 -> T ## How to use -### Command line +### Standard command line ```plaintext -SSF_[.exe] [-L loc:ip:dest] [-R rem:ip:dest] [-D port] [-F port] [-U loc:ip:dest] [-V rem:ip:dest] [-b bounce_file] [-c config_file] [-p port] [host] +ssf[.exe] [-h] [-L loc:ip:dest] [-R rem:ip:dest] [-D port] [-F port] [-U loc:ip:dest] [-V rem:ip:dest] [-b bounce_file] [-c config_file] [-p port] [host] ``` * host : the IP address or the name of the remote server to connect to. @@ -244,16 +244,52 @@ SSF_[.exe] [-L loc:ip:dest] [-R rem:ip:dest] [-D port] [-F port] * -b : *bounce_file* is the file containing the list of relays to use. * -c : *config_file* is the config file containing configuration for SSF (TLS configuration). -#### File example +### Copy command line -##### Bounce file (relay servers) +```plaintext +ssfcp[.exe] [-h] [-b bounce_file] [-c config_file] [-p port] [-t] [host@]path [[host@]path] +``` + +* -b : *bounce_file* is the file containing the list of relays to use. +* -c : *config_file* is the config file containing configuration for SSF (TLS configuration). +* -t : input from stdin + +#### Copy from local to remote destination : + +```plaintext +ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] path/to/file host@absolute/path/directory_destination +``` + +```plaintext +ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] path/to/file* host@absolute/path/directory_destination +``` + +#### From stdin to remote destination + +```plaintext +data_in_stdin | ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] -t host@path/to/destination/file_destination +``` + +#### Copy remote files to local destination : + +```plaintext +ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] remote_host@path/to/file absolute/path/directory_destination +``` + +```plaintext +ssfcp[.exe] [-b bounce_file] [-c config_file] [-p port] remote_host@path/to/file* absolute/path/directory_destination +``` + +### File example + +#### Bounce file (relay servers) ```plaintext 127.0.0.1:8002 127.0.0.1:8003 ``` -##### Config file +#### Config file ```plaintext { From 768576185d902f40bf86b81a6dd2f1e9ae382655 Mon Sep 17 00:00:00 2001 From: "ssf.developer" Date: Fri, 16 Oct 2015 16:41:11 +0200 Subject: [PATCH 13/13] Fix 64bit compilation warning issue --- src/services/copy_file/filename_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/copy_file/filename_buffer.cpp b/src/services/copy_file/filename_buffer.cpp index 70ae06cb..a247e4de 100644 --- a/src/services/copy_file/filename_buffer.cpp +++ b/src/services/copy_file/filename_buffer.cpp @@ -7,7 +7,7 @@ namespace copy_file { FilenameBuffer::FilenameBuffer() : filename_size_(0), filename_() {} FilenameBuffer::FilenameBuffer(const std::string& filename) - : filename_size_(filename.length()), + : filename_size_(static_cast(filename.length())), filename_(filename.cbegin(), filename.cend()) {} std::string FilenameBuffer::GetFilename() const {