diff --git a/CMakeLists.txt b/CMakeLists.txt index 8893c32b..70e78739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_SUPPRESS_REGENERATION ON) project(Bytecoin) -include_directories(include src contrib/epee/include external "${CMAKE_BINARY_DIR}/version") +include_directories(include src external "${CMAKE_BINARY_DIR}/version") if(APPLE) include_directories(SYSTEM /usr/include/malloc) enable_language(ASM) @@ -140,7 +140,6 @@ else() endif() endif() -add_subdirectory(contrib) add_subdirectory(external) add_subdirectory(src) add_subdirectory(tests) diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index dcda199d..e3a4f0b2 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -1,3 +1,11 @@ +Release notes 1.0.5 + +- High-level API for blockchain explorer +- Full network layer refactoring +- Transactions pool synchronization +- list_transactions method for RPC Wallet +- Various improvements + Release notes 1.0.4 - Bytecoin RPC Wallet diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt deleted file mode 100644 index 7222cce5..00000000 --- a/contrib/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB_RECURSE EPEE epee/include/*) - -source_group(epee FILES ${EPEE}) - -add_library(epee ${EPEE}) - -set_property(TARGET epee PROPERTY FOLDER "external") diff --git a/contrib/epee/LICENSE.txt b/contrib/epee/LICENSE.txt deleted file mode 100644 index 4a6b529e..00000000 --- a/contrib/epee/LICENSE.txt +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Andrey N. Sabelnikov nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL Andrey N. Sabelnikov BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/contrib/epee/README.md b/contrib/epee/README.md deleted file mode 100644 index a69884f5..00000000 --- a/contrib/epee/README.md +++ /dev/null @@ -1 +0,0 @@ -epee - is a small library of helpers, wrappers, tools and and so on, used to make my life easier. \ No newline at end of file diff --git a/contrib/epee/demo/.gitignore b/contrib/epee/demo/.gitignore deleted file mode 100644 index d9b4f015..00000000 --- a/contrib/epee/demo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/contrib/epee/demo/CMakeLists.txt b/contrib/epee/demo/CMakeLists.txt deleted file mode 100644 index b4ac2cc8..00000000 --- a/contrib/epee/demo/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -set(Boost_USE_MULTITHREADED ON) -#set(Boost_DEBUG 1) -find_package(Boost COMPONENTS system filesystem thread date_time chrono regex ) - -include_directories( ${Boost_INCLUDE_DIRS} ) - - -IF (MSVC) - add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" ) -ELSE() - # set stuff for other systems - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder -D_GNU_SOURCE") -ENDIF() - - -include_directories(.) -include_directories(../include) -include_directories(iface) - - -# Add folders to filters -file(GLOB_RECURSE LEVIN_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.cpp) - -file(GLOB_RECURSE HTTP_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.cpp) - - - -source_group(general FILES ${LEVIN_GENERAL_SECTION} FILES ${HTTP_GENERAL_SECTION}) -#source_group(general FILES ${HTTP_GENERAL_SECTION}) - -add_executable(demo_http_server ${HTTP_GENERAL_SECTION} ) -add_executable(demo_levin_server ${LEVIN_GENERAL_SECTION} ) - -target_link_libraries( demo_http_server ${Boost_LIBRARIES} ) -target_link_libraries( demo_levin_server ${Boost_LIBRARIES} ) - -IF (NOT WIN32) - target_link_libraries (demo_http_server rt) - target_link_libraries (demo_levin_server rt) -ENDIF() - - diff --git a/contrib/epee/demo/README.txt b/contrib/epee/demo/README.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/contrib/epee/demo/demo_http_server/demo_http_server.cpp b/contrib/epee/demo/demo_http_server/demo_http_server.cpp deleted file mode 100644 index 85547e4c..00000000 --- a/contrib/epee/demo/demo_http_server/demo_http_server.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "stdafx.h" -#include "console_handler.h" -#include "demo_http_server.h" -#include "net/http_client.h" -#include "storages/http_abstract_invoke.h" - - -template -bool communicate(const std::string url, t_request& req, t_response& rsp, const std::string& ip, const std::string& port, bool use_json, bool use_jrpc = false) -{ - epee::net_utils::http::http_simple_client http_client; - bool r = http_client.connect(ip, port, 1000); - CHECK_AND_ASSERT_MES(r, false, "failed to connect"); - if(use_json) - { - if(use_jrpc) - { - epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); - req_t.jsonrpc = "2.0"; - req_t.id = epee::serialization::storage_entry(10); - req_t.method = "command_example_1"; - req_t.params = req; - epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); - if(!epee::net_utils::invoke_http_json_remote_command2("/request_json_rpc", req_t, resp_t, http_client)) - { - return false; - } - rsp = resp_t.result; - return true; - }else - return epee::net_utils::invoke_http_json_remote_command2(url, req, rsp, http_client); - } - else - return epee::net_utils::invoke_http_bin_remote_command2(url, req, rsp, http_client); -} - - -int main(int argc, char* argv[]) -{ - TRY_ENTRY(); - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - - LOG_PRINT("Demo server starting ...", LOG_LEVEL_0); - - - demo::demo_http_server srv; - - start_default_console(&srv, "#"); - - std::string bind_param = "0.0.0.0"; - std::string port = "83"; - - if(!srv.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - //log loop - srv.run(); - size_t count = 0; - while (!srv.is_stop()) - { - - demo::COMMAND_EXAMPLE_1::request req; - req.sub = demo::get_test_data(); - demo::COMMAND_EXAMPLE_1::response rsp; - bool r = false; - if(count%2) - {//invoke json - r = communicate("/request_api_json_1", req, rsp, "127.0.0.1", port, true, true); - }else{ - r = communicate("/request_api_bin_1", req, rsp, "127.0.0.1", port, false); - } - CHECK_AND_ASSERT_MES(r, false, "failed to invoke http request"); - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - //misc_utils::sleep_no_w(1000); - ++count; - } - bool r = srv.wait_stop(); - CHECK_AND_ASSERT_MES(r, 1, "failed to wait server stop"); - srv.deinit(); - - LOG_PRINT("Demo server stoped.", LOG_LEVEL_0); - return 1; - - CATCH_ENTRY_L0("main", 1); -} - -/************************************************************************/ -/* */ -/************************************************************************/ -namespace demo -{ - bool demo_http_server::init(const std::string& bind_port, const std::string& bind_ip) - { - - - //set self as callback handler - m_net_server.get_config_object().m_phandler = this; - - //here set folder for hosting reqests - m_net_server.get_config_object().m_folder = ""; - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool demo_http_server::run() - { - m_stop = false; - //here you can set worker threads count - int thrds_count = 4; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count, false)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - return true; - } - - bool demo_http_server::deinit() - { - return m_net_server.deinit_server(); - } - - bool demo_http_server::send_stop_signal() - { - m_stop = true; - m_net_server.send_stop_signal(); - return true; - } - - bool demo_http_server::on_requestr_uri_1(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - return true; - } - - - bool demo_http_server::on_requestr_uri_2(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - return true; - } - - - bool demo_http_server::on_hosting_request( const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - //read file from filesystem here - return true; - } - - bool demo_http_server::on_request_api_1(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, connection_context& ctxt) - { - CHECK_AND_ASSERT_MES(req.sub == demo::get_test_data(), false, "wrong request"); - res.m_success = true; - res.subs.push_back(req.sub); - return true; - } - - bool demo_http_server::on_request_api_1_with_error(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, epee::json_rpc::error& error_resp, connection_context& ctxt) - { - error_resp.code = 232432; - error_resp.message = "bla bla bla"; - return false; - } - - bool demo_http_server::on_request_api_2(const COMMAND_EXAMPLE_2::request& req, COMMAND_EXAMPLE_2::response& res, connection_context& ctxt) - { - return true; - } -} diff --git a/contrib/epee/demo/demo_http_server/demo_http_server.h b/contrib/epee/demo/demo_http_server/demo_http_server.h deleted file mode 100644 index 088ead54..00000000 --- a/contrib/epee/demo/demo_http_server/demo_http_server.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "net/http_server_cp2.h" -#include "transport_defs.h" -#include "net/http_server_handlers_map2.h" - -using namespace epee; - -namespace demo -{ - - class demo_http_server: public net_utils::http::i_http_server_handler - { - public: - typedef epee::net_utils::connection_context_base connection_context; - - demo_http_server():m_stop(false){} - bool run(); - bool init(const std::string& bind_port = "11112", const std::string& bind_ip = "0.0.0.0"); - bool deinit(); - bool send_stop_signal(); - bool is_stop(){return m_stop;} - bool wait_stop(){return m_net_server.timed_wait_server_stop(100000);} - private: - - - CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map - - BEGIN_URI_MAP2() - MAP_URI2("/requestr_uri_1", on_requestr_uri_1) - MAP_URI2("/requestr_uri_2", on_requestr_uri_1) - //MAP_URI_AUTO_XML2("/request_api_xml_1", on_request_api_1, COMMAND_EXAMPLE_1) - //MAP_URI_AUTO_XML2("/request_api_xml_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_URI_AUTO_JON2("/request_api_json_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_URI_AUTO_JON2("/request_api_json_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_URI_AUTO_BIN2("/request_api_bin_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_URI_AUTO_BIN2("/request_api_bin_2", on_request_api_2, COMMAND_EXAMPLE_2) - BEGIN_JSON_RPC_MAP("/request_json_rpc") - MAP_JON_RPC("command_example_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_JON_RPC("command_example_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_JON_RPC_WE("command_example_1_we", on_request_api_1_with_error, COMMAND_EXAMPLE_1) - END_JSON_RPC_MAP() - CHAIN_URI_MAP2(on_hosting_request) - END_URI_MAP2() - - - - bool on_requestr_uri_1(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - - bool on_requestr_uri_2(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - - - - bool on_hosting_request( const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - bool on_request_api_1(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, connection_context& ctxt); - bool on_request_api_2(const COMMAND_EXAMPLE_2::request& req, COMMAND_EXAMPLE_2::response& res, connection_context& ctxt); - - bool on_request_api_1_with_error(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, epee::json_rpc::error& error_resp, connection_context& ctxt); - - net_utils::boosted_http_server_custum_handling m_net_server; - std::atomic m_stop; - }; -} - diff --git a/contrib/epee/demo/demo_http_server/stdafx.cpp b/contrib/epee/demo/demo_http_server/stdafx.cpp deleted file mode 100644 index ecec2465..00000000 --- a/contrib/epee/demo/demo_http_server/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// demo_http_server.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/contrib/epee/demo/demo_http_server/stdafx.h b/contrib/epee/demo/demo_http_server/stdafx.h deleted file mode 100644 index e2888320..00000000 --- a/contrib/epee/demo/demo_http_server/stdafx.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" - - diff --git a/contrib/epee/demo/demo_http_server/targetver.h b/contrib/epee/demo/demo_http_server/targetver.h deleted file mode 100644 index 6fe8eb79..00000000 --- a/contrib/epee/demo/demo_http_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp b/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp deleted file mode 100644 index a99a1f56..00000000 --- a/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "stdafx.h" -#include "demo_levin_server.h" -#include "console_handler.h" - - -template -bool communicate(net_utils::boosted_levin_async_server& transport, int id, t_request& req, const std::string& ip, const std::string& port, bool use_async) -{ - if(use_async) - { - //IMPORTANT: do not pass local parameters from stack by reference! connect_async returns immediately, and callback will call in any thread later - transport.connect_async(ip, port, 10000, [&transport, id, req, ip, port](net_utils::connection_context_base& ctx, const boost::system::error_code& ec_) - { - if(!!ec_) - { - LOG_ERROR("Failed to connect to " << ip << ":" << port); - }else - {//connected ok! - - epee::net_utils::async_invoke_remote_command2(ctx.m_connection_id, id, req, transport.get_config_object(), [&transport, ip, port](int res_code, demo::COMMAND_EXAMPLE_1::response& rsp, net_utils::connection_context_base& ctx) - { - if(res_code < 0) - { - LOG_ERROR("Failed to invoke to " << ip << ":" << port); - }else - {//invoked ok - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 async invoked ok", LOG_LEVEL_0); - } - transport.get_config_object().close(ctx.m_connection_id); - return true; - }); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 async invoke requested", LOG_LEVEL_0); - } - }); - }else - { - net_utils::connection_context_base ctx = AUTO_VAL_INIT(ctx); - bool r = transport.connect(ip, port, 10000, ctx); - CHECK_AND_ASSERT_MES(r, false, "failed to connect to " << ip << ":" << port); - demo::COMMAND_EXAMPLE_1::response rsp = AUTO_VAL_INIT(rsp); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 sync invoke requested", LOG_LEVEL_0); - r = epee::net_utils::invoke_remote_command2(ctx.m_connection_id, id, req, rsp, transport.get_config_object()); - CHECK_AND_ASSERT_MES(r, false, "failed to invoke levin request"); - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - transport.get_config_object().close(ctx.m_connection_id); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 sync invoked ok", LOG_LEVEL_0); - } - return true; -} - - -int main(int argc, char* argv[]) -{ - TRY_ENTRY(); - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - - LOG_PRINT("Demo server starting ...", LOG_LEVEL_0); - - - demo::demo_levin_server srv; - - start_default_console(&srv, "#"); - - std::string bind_param = "0.0.0.0"; - std::string port = "12345"; - - if(!srv.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv.run(); - - size_t c = 1; - while (!srv.is_stop()) - { - - demo::COMMAND_EXAMPLE_1::request req; - req.sub = demo::get_test_data(); - bool r = communicate(srv.get_server(), demo::COMMAND_EXAMPLE_1::ID, req, "127.0.0.1", port, (c%2 == 0)); - misc_utils::sleep_no_w(1000); - ++c; - } - bool r = srv.wait_stop(); - CHECK_AND_ASSERT_MES(r, 1, "failed to wait server stop"); - - - srv.deinit(); - - LOG_PRINT("Demo server stoped.", LOG_LEVEL_0); - return 1; - - CATCH_ENTRY_L0("main", 1); -} - -/************************************************************************/ -/* */ -/************************************************************************/ -namespace demo -{ - bool demo_levin_server::init(const std::string& bind_port, const std::string& bind_ip) - { - m_net_server.get_config_object().m_pcommands_handler = this; - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool demo_levin_server::run() - { - m_stop = false; - //here you can set worker threads count - int thrds_count = 4; - m_net_server.get_config_object().m_invoke_timeout = 10000; - m_net_server.get_config_object().m_pcommands_handler = this; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count, false)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool demo_levin_server::deinit() - { - return m_net_server.deinit_server(); - } - - bool demo_levin_server::send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - int demo_levin_server::handle_command_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context) - { - CHECK_AND_ASSERT_MES(arg.sub == demo::get_test_data(), false, "wrong request"); - rsp.m_success = true; - rsp.subs.push_back(arg.sub); - LOG_PRINT_GREEN("Server COMMAND_EXAMPLE_1 ok", LOG_LEVEL_0); - return 1; - } - int demo_levin_server::handle_command_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - return 1; - } - int demo_levin_server::handle_notify_1(int command, COMMAND_EXAMPLE_1::request& arg, const net_utils::connection_context_base& context) - { - return 1; - } - int demo_levin_server::handle_notify_2(int command, COMMAND_EXAMPLE_2::request& arg, const net_utils::connection_context_base& context) - { - return 1; - } -} diff --git a/contrib/epee/demo/demo_levin_server/demo_levin_server.h b/contrib/epee/demo/demo_levin_server/demo_levin_server.h deleted file mode 100644 index 5a6f68f2..00000000 --- a/contrib/epee/demo/demo_levin_server/demo_levin_server.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "net/levin_server_cp2.h" -#include "transport_defs.h" -#include "storages/levin_abstract_invoke2.h" - -using namespace epee; - -namespace demo -{ - - class demo_levin_server: public levin::levin_commands_handler<> - { - public: - bool run(); - bool init(const std::string& bind_port = "11112", const std::string& bind_ip = "0.0.0.0"); - bool deinit(); - bool send_stop_signal(); - bool is_stop(){return m_stop;} - bool wait_stop(){return m_net_server.timed_wait_server_stop(100000);} - net_utils::boosted_levin_async_server& get_server(){return m_net_server;} - private: - - - CHAIN_LEVIN_INVOKE_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP2(demo_levin_server) - HANDLE_INVOKE_T2(COMMAND_EXAMPLE_1, &demo_levin_server::handle_command_1) - HANDLE_INVOKE_T2(COMMAND_EXAMPLE_2, &demo_levin_server::handle_command_2) - HANDLE_NOTIFY_T2(COMMAND_EXAMPLE_1, &demo_levin_server::handle_notify_1) - HANDLE_NOTIFY_T2(COMMAND_EXAMPLE_2, &demo_levin_server::handle_notify_2) - END_INVOKE_MAP2() - - //----------------- commands handlers ---------------------------------------------- - int handle_command_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context); - int handle_command_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context); - int handle_notify_1(int command, COMMAND_EXAMPLE_1::request& arg, const net_utils::connection_context_base& context); - int handle_notify_2(int command, COMMAND_EXAMPLE_2::request& arg, const net_utils::connection_context_base& context); - //---------------------------------------------------------------------------------- - net_utils::boosted_levin_async_server m_net_server; - std::atomic m_stop; - - }; -} - diff --git a/contrib/epee/demo/demo_levin_server/stdafx.cpp b/contrib/epee/demo/demo_levin_server/stdafx.cpp deleted file mode 100644 index d6ea1c6f..00000000 --- a/contrib/epee/demo/demo_levin_server/stdafx.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "stdafx.h" - diff --git a/contrib/epee/demo/demo_levin_server/stdafx.h b/contrib/epee/demo/demo_levin_server/stdafx.h deleted file mode 100644 index cc455843..00000000 --- a/contrib/epee/demo/demo_levin_server/stdafx.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" diff --git a/contrib/epee/demo/demo_levin_server/targetver.h b/contrib/epee/demo/demo_levin_server/targetver.h deleted file mode 100644 index 6fe8eb79..00000000 --- a/contrib/epee/demo/demo_levin_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/contrib/epee/demo/generate_gcc.sh b/contrib/epee/demo/generate_gcc.sh deleted file mode 100644 index fcd0a8a7..00000000 --- a/contrib/epee/demo/generate_gcc.sh +++ /dev/null @@ -1,4 +0,0 @@ -mkdir build -cd build -cmake .. -#cmake -DBOOST_ROOT=/usr/local/proj/boost_1_49_0 -DBOOST_LIBRARYDIR=/usr/local/proj/boost_1_49_0/stage/lib .. diff --git a/contrib/epee/demo/generate_vc_proj.bat b/contrib/epee/demo/generate_vc_proj.bat deleted file mode 100644 index 11140598..00000000 --- a/contrib/epee/demo/generate_vc_proj.bat +++ /dev/null @@ -1,7 +0,0 @@ -mkdir build - -cd build - -cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" .. -cd .. -pause \ No newline at end of file diff --git a/contrib/epee/demo/iface/transport_defs.h b/contrib/epee/demo/iface/transport_defs.h deleted file mode 100644 index 8463eb90..00000000 --- a/contrib/epee/demo/iface/transport_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -#pragma once - -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_base.h" - -namespace demo -{ - - struct some_test_subdata - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - END_KV_SERIALIZE_MAP() - }; - - struct some_test_data - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - std::list m_list_of_str; - std::list m_list_of_uint64_t; - std::list m_list_of_uint32_t; - std::list m_list_of_uint16_t; - std::list m_list_of_uint8_t; - std::list m_list_of_int64_t; - std::list m_list_of_int32_t; - std::list m_list_of_int16_t; - std::list m_list_of_int8_t; - std::list m_list_of_double; - std::list m_list_of_bool; - some_test_subdata m_subobj; - std::list m_list_of_self; - epee::serialization::storage_entry m_storage_entry_int; - epee::serialization::storage_entry m_storage_entry_string; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - KV_SERIALIZE(m_uint64) - KV_SERIALIZE(m_uint32) - KV_SERIALIZE(m_uint16) - KV_SERIALIZE(m_uint8) - KV_SERIALIZE(m_int64) - KV_SERIALIZE(m_int32) - KV_SERIALIZE(m_int16) - KV_SERIALIZE(m_int8) - KV_SERIALIZE(m_double) - KV_SERIALIZE(m_bool) - KV_SERIALIZE(m_subobj) - KV_SERIALIZE(m_list_of_str) - KV_SERIALIZE(m_list_of_uint64_t) - KV_SERIALIZE(m_list_of_uint32_t) - KV_SERIALIZE(m_list_of_uint16_t) - KV_SERIALIZE(m_list_of_uint8_t) - KV_SERIALIZE(m_list_of_int64_t) - KV_SERIALIZE(m_list_of_int32_t) - KV_SERIALIZE(m_list_of_int16_t) - KV_SERIALIZE(m_list_of_int8_t) - KV_SERIALIZE(m_list_of_double) - KV_SERIALIZE(m_list_of_bool) - KV_SERIALIZE(m_list_of_self) - KV_SERIALIZE(m_storage_entry_int) - KV_SERIALIZE(m_storage_entry_string) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request - { - std::string example_string_data; - some_test_data sub; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data) - KV_SERIALIZE(sub) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - bool m_success; - std::list subs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - KV_SERIALIZE(subs) - END_KV_SERIALIZE_MAP() - }; - }; - - - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request - { - std::string example_string_data2; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data2) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - bool m_success; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - END_KV_SERIALIZE_MAP() - }; - }; - - - //------------------------------------------------------------------------------------- - //------------------------------------------------------------------------------------- - //in debug purpose - bool operator != (const some_test_subdata& a, const some_test_subdata& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const some_test_data& a, const some_test_data& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - || b.m_storage_entry_int.which() != a.m_storage_entry_int.which() - || b.m_storage_entry_string.which() != a.m_storage_entry_string.which() - ) - return false; - return true; - } - - inline some_test_data get_test_data() - { - some_test_data s; - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - s.m_storage_entry_int = epee::serialization::storage_entry(uint64_t(22222));; - s.m_storage_entry_string = epee::serialization::storage_entry(std::string("sdsvsdvs")); - return s; - } -} \ No newline at end of file diff --git a/contrib/epee/include/ado_db_helper.h b/contrib/epee/include/ado_db_helper.h deleted file mode 100644 index ed4e5b30..00000000 --- a/contrib/epee/include/ado_db_helper.h +++ /dev/null @@ -1,1095 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _DB_ADO_HELPER_H_ -#define _DB_ADO_HELPER_H_ - -#include -#include -#include "string_coding.h" -#include "math_helper.h" -#include "file_io_utils.h" -#include "global_stream_operators.h" - - - -#define BEGIN_TRY_SECTION() try { - -#define CATCH_TRY_SECTION(ret_val) CATCH_TRY_SECTION_MESS(ret_val, "") - -#define CATCH_TRY_SECTION_MESS(ret_val, mess_where) }\ - catch(const std::exception&ex)\ - {\ - LOG_PRINT_J("DB_ERROR: " << ex.what(), LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(const _com_error& comm_err)\ - {\ - const TCHAR* pstr = comm_err.Description();\ - std::string descr = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - const TCHAR* pmessage = comm_err.ErrorMessage();\ - pstr = comm_err.Source();\ - std::string source = string_encoding::convert_to_ansii(pstr?pstr:TEXT(""));\ - LOG_PRINT_J("COM_ERROR " << mess_where << ":\n\tDescriprion:" << descr << ", \n\t Message: " << string_encoding::convert_to_ansii(pmessage) << "\n\t Source: " << source, LOG_LEVEL_0);\ - return ret_val;\ - }\ - catch(...)\ - {\ - LOG_PRINT_J("..._ERROR: Unknown error.", LOG_LEVEL_0);\ - return ret_val;\ - }\ - -namespace epee -{ -namespace ado_db_helper -{ - - struct profile_entry - { - profile_entry():m_call_count(0), m_max_time(0), m_min_time(0) - {} - //std::string m_sql; - math_helper::average m_avrg; - size_t m_call_count; - DWORD m_max_time; - DWORD m_min_time; - }; - - class profiler_manager - { - public: - typedef std::map sqls_map; - profiler_manager(){} - - static bool sort_by_timing(const sqls_map::iterator& a, const sqls_map::iterator& b) - { - return a->second.m_avrg.get_avg() > b->second.m_avrg.get_avg(); - } - - bool flush_log(const std::string& path) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - std::stringstream strm; - strm << "SQL PROFILE:\r\nStatements: " << m_sqls.size() << "\r\n"; - std::list m_sorted_by_time_sqls; - for(std::map::iterator it = m_sqls.begin();it!=m_sqls.end();it++) - m_sorted_by_time_sqls.push_back(it); - - m_sorted_by_time_sqls.sort(sort_by_timing); - - for(std::list::iterator it = m_sorted_by_time_sqls.begin();it!=m_sorted_by_time_sqls.end();it++) - { - strm << "---------------------------------------------------------------------------------------------------------\r\nSQL: " << (*it)->first << "\r\n"; - strm << "\tavrg: " << (*it)->second.m_avrg.get_avg() << "\r\n\tmax: " << (*it)->second.m_max_time << "\r\n\tmin: " << (*it)->second.m_min_time << "\r\n\tcount: " << (*it)->second.m_call_count << "\r\n"; - } - - return file_io_utils::save_string_to_file(path.c_str(), strm.str()); - CRITICAL_REGION_END(); - } - - bool push_entry(const std::string sql, DWORD time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - profile_entry& entry_ref = m_sqls[sql]; - entry_ref.m_avrg.push(time); - entry_ref.m_call_count++; - if(time > entry_ref.m_max_time) entry_ref.m_max_time = time; - if(time < entry_ref.m_min_time || entry_ref.m_min_time == 0) entry_ref.m_min_time = time; - CRITICAL_REGION_END(); - return true; - } - - bool get_entry_avarege(const std::string sql, DWORD& time) - { - CRITICAL_REGION_BEGIN(m_sqls_lock); - sqls_map::iterator it = m_sqls.find(sql); - if(it==m_sqls.end()) - return false; - - time = static_cast(it->second.m_avrg.get_avg()); - CRITICAL_REGION_END(); - return true; - } - - private: - - sqls_map m_sqls; - critical_section m_sqls_lock; - }; -inline - profiler_manager* get_set_profiler(bool need_to_set = false, profiler_manager** pprofiler = NULL) - { - static profiler_manager* pmanager = NULL; - if(need_to_set) - pmanager = *pprofiler; - //else - // *pprofiler = pmanager; - - return pmanager; - } -inline - bool init() // INIT and DEINIT are NOT THREAD SAFE operations, CALL it BEFOR u start using this wrapper. - { - profiler_manager* pmanager = new profiler_manager(); - get_set_profiler(true, &pmanager); - return true; - } -inline - bool deinit() - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - delete pmanager; - return true; - } - inline bool push_timing(const std::string sql, DWORD time) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->push_entry(sql, time); - return true; - } - - inline bool flush_profiler(const std::string path) - { - profiler_manager* pmanager = get_set_profiler(); - //get_set_profiler(false, &pmanager); - if(pmanager) - return pmanager->flush_log(path); - return true; - } - - class timing_guard - { - DWORD m_start_time; - std::string m_sql; - - public: - timing_guard(const std::string& sql) - { - m_start_time = ::GetTickCount(); - m_sql = sql; - } - - ~timing_guard() - { - DWORD timing = ::GetTickCount() - m_start_time; - push_timing(m_sql, timing); - } - }; -#define PROFILE_SQL(sql) timing_guard local_timing(sql) - - - typedef std::vector > table; - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::string& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarChar, ADODB::adParamInput, static_cast(parametr.size()+1), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::wstring& parametr) - { - _variant_t param(parametr.c_str()); - ADODB::ADO_LONGPTR size = sizeof(parametr); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("", ADODB::adVarWChar, ADODB::adParamInput, static_cast(parametr.size()+2), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBigInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned __int64 parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedBigInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, const unsigned int parametr) - { - _variant_t param(parametr); - ADODB::ADO_LONGPTR size = static_cast(sizeof(parametr)); - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adUnsignedInt, ADODB::adParamInput, static_cast(size), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, float parametr) - { - _variant_t param; - param.ChangeType(VT_R4); - param.fltVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adSingle, ADODB::adParamInput, static_cast(sizeof(float)), param); - cmd->Parameters->Append(param_obj); - return true; - } - - inline bool add_parametr(ADODB::_CommandPtr cmd, bool parametr) - { - _variant_t param; - param = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adBoolean, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr(ADODB::_CommandPtr cmd, _variant_t parametr) - { - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBTimeStamp, ADODB::adParamInput, sizeof(parametr), parametr); - cmd->Parameters->Append(param_obj); - return true; - } - - - inline bool add_parametr_as_double(ADODB::_CommandPtr cmd, const DATE parametr) - { - _variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj); - return true; - } - - template - inline bool add_parametr(ADODB::_CommandPtr cmd, const std::list params) - { - for(std::list::const_iterator it = params.begin(); it!=params.end(); it++) - if(!add_parametr(cmd, *it)) - return false; - return true; - } - - /* - inline bool add_parametr(ADODB::_CommandPtr cmd, const size_t parametr) - { - _variant_t param; - param.ChangeType(VT_I4); - param.intVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adInteger, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - return true; - }*/ - - - inline bool add_parametr(ADODB::_CommandPtr cmd, const DATE parametr) - { - /*_variant_t param; - param.ChangeType(VT_R8); - param.dblVal = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDouble, ADODB::adParamInput, sizeof(float), param); - cmd->Parameters->Append(param_obj);*/ - - _variant_t param; - param.ChangeType(VT_DATE); - param.date = parametr; - ADODB::_ParameterPtr param_obj = cmd->CreateParameter("parametr", ADODB::adDBDate, ADODB::adParamInput, sizeof(parametr), param); - cmd->Parameters->Append(param_obj); - - return true; - } - - - inline bool execute_helper(ADODB::_CommandPtr cmd, _variant_t* pcount_processed = NULL) - { - //BEGIN_TRY_SECTION(); - - cmd->Execute(pcount_processed, NULL, ADODB::adExecuteNoRecords); - - - //CATCH_TRY_SECTION(false); - - return true; - } - - - inline bool select_helper(ADODB::_CommandPtr cmd, table& result_vector) - { - result_vector.clear(); - //BEGIN_TRY_SECTION(); - - ADODB::_RecordsetPtr precordset = cmd->Execute(NULL, NULL, NULL); - if(!precordset) - { - LOG_ERROR("DB_ERROR: cmd->Execute returned NULL!!!"); - return false; - } - - //if(precordset->EndOfFile == EOF) - //{ - // return true; - //} - /*try - { - if(precordset->MoveFirst()!= S_OK) - { - LOG_ERROR("DB_ERROR: Filed to move first!!!"); - return false; - } - } - catch (...) - { - return true; - }*/ - - size_t current_record_index = 0; - while(precordset->EndOfFile != EOF) - { - result_vector.push_back(table::value_type()); - size_t fields_count = precordset->Fields->Count; - result_vector[current_record_index].resize(fields_count); - for(size_t current_field_index = 0; current_field_index < fields_count; current_field_index++) - { - _variant_t var; - var.ChangeType(VT_I2); - var.intVal = static_cast(current_field_index); - result_vector[current_record_index][current_field_index] = precordset->Fields->GetItem(var)->Value; - } - precordset->MoveNext(); - current_record_index++; - } - //CATCH_TRY_SECTION(false); - return true; - } - - - template - struct adapter_zero - { - - }; - - template - struct adapter_single - { - TParam1 tparam1; - }; - template - struct adapter_double - { - TParam1 tparam1; - TParam2 tparam2; - }; - - - template - struct adapter_triple - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - }; - - template - struct adapter_quad - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - }; - - template - struct adapter_quanto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - }; - - template - struct adapter_sixto - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - }; - - template - struct adapter_sevento - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - }; - - template - struct adapter_nine - { - TParam1 tparam1; - TParam2 tparam2; - TParam3 tparam3; - TParam4 tparam4; - TParam5 tparam5; - TParam6 tparam6; - TParam7 tparam7; - TParam8 tparam8; - TParam9 tparam9; - }; - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_zero& params) - { - return true; - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_single& params) - { - return add_parametr(cmd, params.tparam1); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_double& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - return add_parametr(cmd, params.tparam2); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_triple& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - return add_parametr(cmd, params.tparam3); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quad& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - return add_parametr(cmd, params.tparam4); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_quanto& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - return add_parametr(cmd, params.tparam5); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sixto& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - return add_parametr(cmd, params.tparam6); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_sevento& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - return add_parametr(cmd, params.tparam7); - } - - template - bool add_parametrs_multi(ADODB::_CommandPtr cmd, const adapter_nine& params) - { - if(!add_parametr(cmd, params.tparam1)) return false; - if(!add_parametr(cmd, params.tparam2)) return false; - if(!add_parametr(cmd, params.tparam3)) return false; - if(!add_parametr(cmd, params.tparam4)) return false; - if(!add_parametr(cmd, params.tparam5)) return false; - if(!add_parametr(cmd, params.tparam6)) return false; - if(!add_parametr(cmd, params.tparam7)) return false; - if(!add_parametr(cmd, params.tparam8)) return false; - return add_parametr(cmd, params.tparam9); - } - - template - std::string print_parameters_multi(const adapter_sevento& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_nine& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6 << ", " << params.tparam7 << ", " << params.tparam8 << ", " << params.tparam9; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_sixto& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5 << ", " << params.tparam6; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_quanto& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4 << ", " << params.tparam5; - return strm.str(); - } - - - template - std::string print_parameters_multi(const adapter_quad& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3 << ", " << params.tparam4; - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_triple& params) - { - std::stringstream strm; - strm << params.tparam1 << ", " << params.tparam2 << ", " << params.tparam3; - return strm.str(); - } - - template - std::string get_str_param(const TParam& prm) - { - std::stringstream strm; - strm << prm; - return strm.str(); - } - - template - std::string get_str_param(const std::list& prm_lst) - { - std::stringstream strm; - for(std::list::const_iterator it = prm_lst.begin();it!=prm_lst.end();it++) - strm << get_str_param(*it) << ", "; - return strm.str(); - } - - - template - std::string print_parameters_multi(const adapter_double& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1) << ", " << get_str_param(params.tparam2); - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_single& params) - { - std::stringstream strm; - strm << get_str_param(params.tparam1); - return strm.str(); - } - - template - std::string print_parameters_multi(const adapter_zero& params) - { - std::stringstream strm; - strm << "(no parametrs)"; - return strm.str(); - } - - - template - bool execute_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, _variant_t* pcount_processed = NULL) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = execute_helper(cmd, pcount_processed); - - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template - inline - bool select_helper_multiparam(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - if(!add_parametrs_multi(cmd, parametrs)) - return false; - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - CATCH_TRY_SECTION_MESS(false, "while statment: " << sql_statment << " [params]: " << print_parameters_multi(parametrs)); - return res; - } - - - template - inline - bool select_helper_param_container(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParams& parametrs, table& result_vector) - { - PROFILE_SQL(sql_statment); - bool res = false; - BEGIN_TRY_SECTION(); - ADODB::_CommandPtr cmd; - cmd.CreateInstance(__uuidof(ADODB::Command)); - cmd->CommandText = _bstr_t(sql_statment.c_str()); - - - for(TParams::const_iterator it = parametrs.begin(); it!=parametrs.end(); it++) - { - add_parametr(cmd, *it); - } - - cmd->ActiveConnection = pconnection; - res = select_helper(cmd, result_vector); - - CATCH_TRY_SECTION(false); - return res; - } - - - inline - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, _variant_t* pvt = NULL) - { - adapter_zero params; - return execute_helper_multiparam(pconnection, sql_statment, params, pvt); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr) - { - adapter_single params; - params.tparam1 = parametr; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2) - { - adapter_double params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return execute_helper_multiparam(pconnection, sql_statment, params); - - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3) - { - adapter_triple params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4) - { - adapter_quad params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5) - { - adapter_quanto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6) - { - adapter_sixto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - - template - bool execute_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1& parametr1, const TParam2& parametr2, const TParam3& parametr3, const TParam4& parametr4, const TParam5& parametr5, const TParam6& parametr6, const TParam7& parametr7) - { - adapter_sevento params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return execute_helper_multiparam(pconnection, sql_statment, params); - } - - inline - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, table& result_vector) - { - adapter_zero params; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam& parametr, table& result_vector) - { - adapter_single params; - params.tparam1 = parametr; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, table& result_vector) - { - adapter_double params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, table& result_vector) - { - adapter_triple params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, table& result_vector) - { - adapter_quad params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, table& result_vector) - { - adapter_quanto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, table& result_vector) - { - adapter_sixto params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7, table& result_vector) - { - adapter_sevento params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - template - bool select_helper(ADODB::_ConnectionPtr pconnection, const std::string& sql_statment, const TParam1 parametr1, const TParam2 parametr2, const TParam3 parametr3, const TParam4 parametr4, const TParam5 parametr5, const TParam6 parametr6, const TParam7 parametr7,const TParam8 parametr8,const TParam9 parametr9, table& result_vector) - { - adapter_nine params; - params.tparam1 = parametr1; - params.tparam2 = parametr2; - params.tparam3 = parametr3; - params.tparam4 = parametr4; - params.tparam5 = parametr5; - params.tparam6 = parametr6; - params.tparam7 = parametr7; - params.tparam8 = parametr8; - params.tparam9 = parametr9; - return select_helper_multiparam(pconnection, sql_statment, params, result_vector); - } - - - - - /************************************************************************/ - /* */ - /************************************************************************/ - - class per_thread_connection_pool - { - public: - bool init(const std::string& connection_string, const std::string& login, const std::string& pass) - { - m_connection_string = connection_string; - m_login = login; - m_password = pass; - if(!get_db_connection().GetInterfacePtr()) - return false; - - return true; - } - - ADODB::_ConnectionPtr& get_db_connection() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[::GetCurrentThreadId()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new ADODB::_ConnectionPtr()); - ADODB::_ConnectionPtr& conn = *conn_ptr.get(); - //init new connection - - BEGIN_TRY_SECTION(); - //_bstr_t str = _bstr_t("Provider=SQLOLEDB;Data Source=SRV1;Integrated Security=SSPI;Initial Catalog=dispatcher;"); - - if(S_OK != conn.CreateInstance(__uuidof(ADODB::Connection))) - { - LOG_ERROR("Failed to Create, instance, was CoInitialize called ???!"); - return conn; - } - - HRESULT res = conn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_ERROR("Failed to connect do DB, connection str:" << m_connection_string); - return conn; - } - CATCH_TRY_SECTION_MESS(conn, "while creating another connection"); - LOG_PRINT("New DB Connection added for threadid=" << ::GetCurrentThreadId(), LOG_LEVEL_0); - ado_db_helper::execute_helper(conn, "set enable_seqscan=false;"); - return conn; - } - - return *conn_ptr.get(); - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - ADODB::_ConnectionPtr& rconn = get_db_connection(); - if(!ado_db_helper::execute_helper(rconn, "SET CLIENT_ENCODING TO 'SQL_ASCII'")) - { - - try{ - HRESULT res = rconn->Close(); - } - catch(...) - { - - }; - BEGIN_TRY_SECTION(); - - HRESULT res = rconn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); - if(res != S_OK) - { - LOG_PRINT("Failed to restore connection to local AI DB", LOG_LEVEL_1); - return false; - } - CATCH_TRY_SECTION(false); - } - - return true; - } - - protected: - private: - std::map > m_db_connections; - critical_section m_db_connections_lock; - std::string m_connection_string; - std::string m_login; - std::string m_password; - }; - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, t_conn& c) - { - ado_db_helper::adapter_single params; - params.tparam1 = parametr_1; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, t_conn& c) - { - ado_db_helper::adapter_double params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, t_conn& c) - { - ado_db_helper::adapter_triple params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template - bool find_or_add_t(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParam1 parametr_1, TParam2 parametr_2, TParam3 parametr_3, TParam4 parametr_4, t_conn& c) - { - ado_db_helper::adapter_quad params; - params.tparam1 = parametr_1; - params.tparam2 = parametr_2; - params.tparam3 = parametr_3; - params.tparam4 = parametr_4; - return find_or_add_t_multiparametred(sql_select_statment, sql_insert_statment, id, new_object_added, params, c); - } - - template - bool find_or_add_t_multiparametred(const std::string& sql_select_statment, const std::string& sql_insert_statment, OUT default_id_type& id, OUT bool& new_object_added, TParams params, t_conn& c) - { - - //CHECK_CONNECTION(false); - - new_object_added = false; - ado_db_helper::table result_table; - - bool res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - if(!result_table.size()) - { - res = select_helper_multiparam(c.get_db_connection(), sql_insert_statment, params, result_table); - if(!res || !result_table.size()) - { - //last time try to select - res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - CHECK_AND_ASSERT_MES(res, false, "Failed to execute statment: " << sql_select_statment); - CHECK_AND_ASSERT_MES(result_table.size(), false, "No records returned from statment: " << sql_select_statment); - }else - { - new_object_added = true; - } - } - - BEGIN_TRY_SECTION() - id = result_table[0][0]; - CATCH_TRY_SECTION_MESS(false, "while converting returned value [find_or_add_t_multiparametred()]"); - - return true; - } - -} -} -#endif //!_DB_HELPER_H_ diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h deleted file mode 100644 index 39bd0ae4..00000000 --- a/contrib/epee/include/console_handler.h +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -#include "include_base_utils.h" -#include "string_tools.h" - -namespace epee -{ - class async_stdin_reader - { - public: - async_stdin_reader() - : m_run(true) - , m_has_read_request(false) - , m_read_status(state_init) - { - m_reader_thread = std::thread(std::bind(&async_stdin_reader::reader_thread_func, this)); - } - - ~async_stdin_reader() - { - stop(); - } - - // Not thread safe. Only one thread can call this method at once. - bool get_line(std::string& line) - { - if (!start_read()) - return false; - - std::unique_lock lock(m_response_mutex); - while (state_init == m_read_status) - { - m_response_cv.wait(lock); - } - - bool res = false; - if (state_success == m_read_status) - { - line = m_line; - res = true; - } - - m_read_status = state_init; - - return res; - } - - void stop() - { - if (m_run) - { - m_run.store(false, std::memory_order_relaxed); - -#if defined(WIN32) - ::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE)); -#endif - - m_request_cv.notify_one(); - m_reader_thread.join(); - } - } - - private: - bool start_read() - { - std::unique_lock lock(m_request_mutex); - if (!m_run.load(std::memory_order_relaxed) || m_has_read_request) - return false; - - m_has_read_request = true; - m_request_cv.notify_one(); - return true; - } - - bool wait_read() - { - std::unique_lock lock(m_request_mutex); - while (m_run.load(std::memory_order_relaxed) && !m_has_read_request) - { - m_request_cv.wait(lock); - } - - if (m_has_read_request) - { - m_has_read_request = false; - return true; - } - - return false; - } - - bool wait_stdin_data() - { -#if !defined(WIN32) - int stdin_fileno = ::fileno(stdin); - - while (m_run.load(std::memory_order_relaxed)) - { - fd_set read_set; - FD_ZERO(&read_set); - FD_SET(stdin_fileno, &read_set); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100 * 1000; - - int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv); - if (retval < 0) - return false; - else if (0 < retval) - return true; - } -#endif - - return true; - } - - void reader_thread_func() - { - while (true) - { - if (!wait_read()) - break; - - std::string line; - bool read_ok = true; - if (wait_stdin_data()) - { - if (m_run.load(std::memory_order_relaxed)) - { - std::getline(std::cin, line); - read_ok = !std::cin.eof() && !std::cin.fail(); - } - } - else - { - read_ok = false; - } - - { - std::unique_lock lock(m_response_mutex); - if (m_run.load(std::memory_order_relaxed)) - { - m_line = std::move(line); - m_read_status = read_ok ? state_success : state_error; - } - else - { - m_read_status = state_cancelled; - } - m_response_cv.notify_one(); - } - } - } - - enum t_state - { - state_init, - state_success, - state_error, - state_cancelled - }; - - private: - std::thread m_reader_thread; - std::atomic m_run; - - std::string m_line; - bool m_has_read_request; - t_state m_read_status; - - std::mutex m_request_mutex; - std::mutex m_response_mutex; - std::condition_variable m_request_cv; - std::condition_variable m_response_cv; - }; - - - template - bool empty_commands_handler(t_server* psrv, const std::string& command) - { - return true; - } - - - class async_console_handler - { - public: - async_console_handler() - { - } - - template - bool run(t_server* psrv, chain_handler ch_handler, const std::string& prompt = "#", const std::string& usage = "") - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(psrv, cmd); }, [&] { psrv->send_stop_signal(); }); - } - - template - bool run(chain_handler ch_handler, const std::string& prompt = "#", const std::string& usage = "") - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(cmd); }, [] { }); - } - - void stop() - { - m_stdin_reader.stop(); - } - - private: - template - bool run(const std::string& prompt, const std::string& usage, const t_cmd_handler& cmd_handler, const t_exit_handler& exit_handler) - { - TRY_ENTRY(); - bool continue_handle = true; - while(continue_handle) - { - if (!prompt.empty()) - { - epee::log_space::set_console_color(epee::log_space::console_color_yellow, true); - std::cout << prompt; - if (' ' != prompt.back()) - std::cout << ' '; - epee::log_space::reset_console_color(); - std::cout.flush(); - } - - std::string command; - if(!m_stdin_reader.get_line(command)) - { - LOG_PRINT("Failed to read line. Stopping...", LOG_LEVEL_0); - continue_handle = false; - break; - } - string_tools::trim(command); - - LOG_PRINT_L2("Read command: " << command); - if(0 == command.compare("exit") || 0 == command.compare("q")) - { - continue_handle = false; - }else if (command.empty()) - { - continue; - } - else if(cmd_handler(command)) - { - continue; - } else - { - std::cout << "unknown command: " << command << std::endl; - std::cout << usage; - } - } - exit_handler(); - return true; - CATCH_ENTRY_L0("console_handler", false); - } - - private: - async_stdin_reader m_stdin_reader; - }; - - - template - bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - std::shared_ptr console_handler = std::make_shared(); - std::thread([=](){console_handler->run(ptsrv, handlr, prompt, usage);}).detach(); - return true; - } - - template - bool start_default_console(t_server* ptsrv, const std::string& prompt, const std::string& usage = "") - { - return start_default_console(ptsrv, empty_commands_handler, prompt, usage); - } - - template - bool no_srv_param_adapter(t_server* ptsrv, const std::string& cmd, t_handler handlr) - { - return handlr(cmd); - } - - template - bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - async_console_handler console_handler; - return console_handler.run(ptsrv, std::bind(no_srv_param_adapter, std::placeholders::_1, std::placeholders::_2, handlr), prompt, usage); - } - - template - bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - std::thread( std::bind(run_default_console_handler_no_srv_param, ptsrv, handlr, prompt, usage) ); - return true; - } - - /************************************************************************/ - /* */ - /************************************************************************/ - class console_handlers_binder - { - typedef std::function &)> console_command_handler; - typedef std::map > command_handlers_map; - std::unique_ptr m_console_thread; - command_handlers_map m_command_handlers; - async_console_handler m_console_handler; - public: - std::string get_usage() - { - std::stringstream ss; - size_t max_command_len = 0; - for(auto& x:m_command_handlers) - if(x.first.size() > max_command_len) - max_command_len = x.first.size(); - - for(auto& x:m_command_handlers) - { - ss.width(max_command_len + 3); - ss << std::left << x.first << x.second.second << ENDL; - } - return ss.str(); - } - void set_handler(const std::string& cmd, const console_command_handler& hndlr, const std::string& usage = "") - { - command_handlers_map::mapped_type & vt = m_command_handlers[cmd]; - vt.first = hndlr; - vt.second = usage; - } - bool process_command_vec(const std::vector& cmd) - { - if(!cmd.size()) - return false; - auto it = m_command_handlers.find(cmd.front()); - if(it == m_command_handlers.end()) - return false; - std::vector cmd_local(cmd.begin()+1, cmd.end()); - return it->second.first(cmd_local); - } - - bool process_command_str(const std::string& cmd) - { - std::vector cmd_v; - boost::split(cmd_v,cmd,boost::is_any_of(" "), boost::token_compress_on); - return process_command_vec(cmd_v); - } - - bool start_handling(const std::string& prompt, const std::string& usage_string = "") - { - m_console_thread.reset(new std::thread(std::bind(&console_handlers_binder::run_handling, this, prompt, usage_string))); - m_console_thread->detach(); - return true; - } - - void stop_handling() - { - m_console_handler.stop(); - } - - bool run_handling(const std::string& prompt, const std::string& usage_string) - { - return m_console_handler.run(std::bind(&console_handlers_binder::process_command_str, this, std::placeholders::_1), prompt, usage_string); - } - }; - - /* work around because of broken boost bind */ - template - class srv_console_handlers_binder: public console_handlers_binder - { - bool process_command_str(t_server* /*psrv*/, const std::string& cmd) - { - return console_handlers_binder::process_command_str(cmd); - } - public: - bool start_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string = "") - { - std::thread(std::bind(&srv_console_handlers_binder::run_handling, this, psrv, prompt, usage_string)).detach(); - return true; - } - - bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) - { - return m_console_handler.run(psrv, std::bind(&srv_console_handlers_binder::process_command_str, this, - std::placeholders::_1, std::placeholders::_2), prompt, usage_string); - } - - void stop_handling() - { - m_console_handler.stop(); - } - - private: - async_console_handler m_console_handler; - }; -} diff --git a/contrib/epee/include/copyable_atomic.h b/contrib/epee/include/copyable_atomic.h deleted file mode 100644 index 6b5691ab..00000000 --- a/contrib/epee/include/copyable_atomic.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -namespace epee -{ - class copyable_atomic: public std::atomic - { - public: - copyable_atomic() - {}; - copyable_atomic(const copyable_atomic& a):std::atomic(a.load()) - {} - copyable_atomic& operator= (const copyable_atomic& a) - { - store(a.load()); - return *this; - } - uint32_t operator++() - { - return std::atomic::operator++(); - } - uint32_t operator++(int fake) - { - return std::atomic::operator++(fake); - } - }; -} \ No newline at end of file diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h deleted file mode 100644 index 01d70db3..00000000 --- a/contrib/epee/include/file_io_utils.h +++ /dev/null @@ -1,452 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _FILE_IO_UTILS_H_ -#define _FILE_IO_UTILS_H_ - -#include -#include -#include - - -#ifndef MAKE64 - #define MAKE64(low,high) ((__int64)(((DWORD)(low)) | ((__int64)((DWORD)(high))) << 32)) -#endif - -#ifdef WINDOWS_PLATFORM -#include -#include -#include -#include - -#endif - - - -namespace epee -{ -namespace file_io_utils -{ -#ifdef WINDOWS_PLATFORM - - inline - std::string get_temp_file_name_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - - char sz_temp_file[MAX_PATH*2] = {0}; - if(!::GetTempFileNameA( sz_temp, "mail", 0, sz_temp_file)) - return str_result; - sz_temp_file[sizeof(sz_temp_file)-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } - - -#ifdef BOOST_LEXICAL_CAST_INCLUDED - inline - bool get_not_used_filename(const std::string& folder, std::string& result_name) - { - DWORD folder_attr = ::GetFileAttributesA(folder.c_str()); - if(folder_attr == INVALID_FILE_ATTRIBUTES) - return false; - if(!(folder_attr&FILE_ATTRIBUTE_DIRECTORY)) - return false; - - - std::string base_name = folder + "\\tmp"; - std::string tmp_name; - bool name_found = false; - int current_index = 0; - tmp_name = base_name + boost::lexical_cast(current_index) + ".tmp"; - while(!name_found) - { - if(INVALID_FILE_ATTRIBUTES == ::GetFileAttributesA(tmp_name.c_str())) - name_found = true; - else - { - current_index++; - tmp_name = base_name + boost::lexical_cast(current_index) + ".tmp"; - } - } - result_name = tmp_name; - return true; - } -#endif - - inline - std::string get_temp_folder_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - sz_temp[(sizeof(sz_temp)/sizeof(sz_temp[0])) -1] = 0; - str_result = sz_temp; - return str_result; - } - - std::string convert_from_device_path_to_standart(const std::string& path) - { - - - STRSAFE_LPSTR pszFilename = (STRSAFE_LPSTR)path.c_str(); - - // Translate path with device name to drive letters. - char szTemp[4000] = {0}; - - if (::GetLogicalDriveStringsA(sizeof(szTemp)-1, szTemp)) - { - char szName[MAX_PATH]; - char szDrive[3] = " :"; - BOOL bFound = FALSE; - char* p = szTemp; - - do - { - // Copy the drive letter to the template string - *szDrive = *p; - - // Look up each device name - if (::QueryDosDeviceA(szDrive, szName, sizeof(szName))) - { - UINT uNameLen = strlen(szName); - - if (uNameLen < MAX_PATH) - { - bFound = _mbsnbicmp((const unsigned char*)pszFilename, (const unsigned char*)szName, - uNameLen) == 0; - - if (bFound) - { - // Reconstruct pszFilename using szTempFile - // Replace device path with DOS path - char szTempFile[MAX_PATH] = {0}; - StringCchPrintfA(szTempFile, - MAX_PATH, - "%s%s", - szDrive, - pszFilename+uNameLen); - return szTempFile; - //::StringCchCopyNA(pszFilename, MAX_PATH+1, szTempFile, strlen(szTempFile)); - } - } - } - - // Go to the next NULL character. - while (*p++); - } while (!bFound && *p); // end of string - } - - return ""; - } - - inline - std::string get_process_path_by_pid(DWORD pid) - { - std::string res; - - HANDLE hprocess = 0; - if( hprocess = ::OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid) ) - { - char buff[MAX_PATH]= {0}; - if(!::GetModuleFileNameExA( hprocess, 0, buff, MAX_PATH - 1 )) - res = "Unknown_b"; - else - { - buff[MAX_PATH - 1]=0; //be happy! - res = buff; - std::string::size_type a = res.rfind( '\\' ); - if ( a != std::string::npos ) - res.erase( 0, a+1); - - } - ::CloseHandle( hprocess ); - }else - res = "Unknown_a"; - - return res; - } - - - - - - inline - std::wstring get_temp_file_name_w() - { - std::wstring str_result; - wchar_t sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathW( sizeof(sz_temp)/sizeof(sz_temp[0]), sz_temp )) - return str_result; - - wchar_t sz_temp_file[MAX_PATH+1] = {0}; - if(!::GetTempFileNameW( sz_temp, L"mail", 0, sz_temp_file)) - return str_result; - - sz_temp_file[(sizeof(sz_temp_file)/sizeof(sz_temp_file[0]))-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } -#endif - inline - bool is_file_exist(const std::string& path) - { - boost::filesystem::path p(path); - return boost::filesystem::exists(p); - } - - /* - inline - bool save_string_to_handle(HANDLE hfile, const std::string& str) - { - - - - if( INVALID_HANDLE_VALUE != hfile ) - { - DWORD dw; - if( !::WriteFile( hfile, str.data(), (DWORD) str.size(), &dw, NULL) ) - { - int err_code = GetLastError(); - //LOG_PRINT("Failed to write to file handle: " << hfile<< " Last error code:" << err_code << " : " << log_space::get_win32_err_descr(err_code), LOG_LEVEL_2); - return false; - } - ::CloseHandle(hfile); - return true; - }else - { - //LOG_WIN32_ERROR(::GetLastError()); - return false; - } - - return false; - }*/ - - - - inline - bool save_string_to_file(const std::string& path_to_file, const std::string& str) - { - - try - { - std::ofstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); - fstream << str; - fstream.close(); - return true; - } - - catch(...) - { - return false; - } - } - - /* - inline - bool load_form_handle(HANDLE hfile, std::string& str) - { - if( INVALID_HANDLE_VALUE != hfile ) - { - bool res = true; - DWORD dw = 0; - DWORD fsize = ::GetFileSize(hfile, &dw); - if(fsize > 300000000) - { - ::CloseHandle(hfile); - return false; - } - if(fsize) - { - str.resize(fsize); - if(!::ReadFile( hfile, (LPVOID)str.data(), (DWORD)str.size(), &dw, NULL)) - res = false; - } - ::CloseHandle(hfile); - return res; - } - return false; - } - */ - inline - bool get_file_time(const std::string& path_to_file, time_t& ft) - { - boost::system::error_code ec; - ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec); - if(!ec) - return true; - else - return false; - } - - inline - bool set_file_time(const std::string& path_to_file, const time_t& ft) - { - boost::system::error_code ec; - boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec); - if(!ec) - return true; - else - return false; - } - - - inline - bool load_file_to_string(const std::string& path_to_file, std::string& target_str) - { - try - { - std::ifstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate); - - std::ifstream::pos_type file_size = fstream.tellg(); - - if(file_size > 1000000000) - return false;//don't go crazy - size_t file_size_t = static_cast(file_size); - - target_str.resize(file_size_t); - - fstream.seekg (0, std::ios::beg); - fstream.read((char*)target_str.data(), target_str.size()); - fstream.close(); - return true; - } - - catch(...) - { - return false; - } - } - - inline - bool append_string_to_file(const std::string& path_to_file, const std::string& str) - { - try - { - std::ofstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app); - fstream << str; - fstream.close(); - return true; - } - - catch(...) - { - return false; - } - } - - /* - bool remove_dir_and_subirs(const char* path_to_dir); - - inline - bool clean_dir(const char* path_to_dir) - { - if(!path_to_dir) - return false; - - std::string folder = path_to_dir; - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((folder + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - if(find_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - if(!remove_dir_and_subirs((folder + "\\" + find_data.cFileName).c_str())) - return false; - }else - { - if(!::DeleteFileA((folder + "\\" + find_data.cFileName).c_str())) - return false; - } - - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } - */ -#ifdef WINDOWS_PLATFORM - inline bool get_folder_content(const std::string& path, std::list& target_list) - { - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((path + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - target_list.push_back(find_data); - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } -#endif - inline bool get_folder_content(const std::string& path, std::list& target_list, bool only_files = false) - { - try - { - - boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end - for ( boost::filesystem::directory_iterator itr( path ); itr != end_itr; ++itr ) - { - if ( only_files && boost::filesystem::is_directory(itr->status()) ) - { - continue; - } - target_list.push_back(itr->path().filename().string()); - } - - } - - catch(...) - { - return false; - } - return true; - } -} -} - -#endif //_FILE_IO_UTILS_H_ diff --git a/contrib/epee/include/global_stream_operators.h b/contrib/epee/include/global_stream_operators.h deleted file mode 100644 index 6fbdbc2e..00000000 --- a/contrib/epee/include/global_stream_operators.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -std::stringstream& operator<<(std::stringstream& out, const std::wstring& ws) -{ - std::string as = string_encoding::convert_to_ansii(ws); - out << as; - return out; -} diff --git a/contrib/epee/include/gzip_encoding.h b/contrib/epee/include/gzip_encoding.h deleted file mode 100644 index 2be51e77..00000000 --- a/contrib/epee/include/gzip_encoding.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _GZIP_ENCODING_H_ -#define _GZIP_ENCODING_H_ -#include "net/http_client_base.h" -#include "zlib/zlib.h" -//#include "http.h" - - -namespace epee -{ -namespace net_utils -{ - - - - class content_encoding_gzip: public i_sub_handler - { - public: - /*! \brief - * Function content_encoding_gzip : Constructor - * - */ - inline - content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false):m_powner_filter(powner_filter), - m_is_stream_ended(false), - m_is_deflate_mode(is_deflate_mode), - m_is_first_update_in(true) - { - memset(&m_zstream_in, 0, sizeof(m_zstream_in)); - memset(&m_zstream_out, 0, sizeof(m_zstream_out)); - int ret = 0; - if(is_deflate_mode) - { - ret = inflateInit(&m_zstream_in); - ret = deflateInit(&m_zstream_out, Z_DEFAULT_COMPRESSION); - }else - { - ret = inflateInit2(&m_zstream_in, 0x1F); - ret = deflateInit2(&m_zstream_out, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY); - } - } - /*! \brief - * Function content_encoding_gzip : Destructor - * - */ - inline - ~content_encoding_gzip() - { - inflateEnd(& m_zstream_in ); - deflateEnd(& m_zstream_out ); - } - /*! \brief - * Function update_in : Entry point for income data - * - */ - inline - virtual bool update_in( std::string& piece_of_transfer) - { - - bool is_first_time_here = m_is_first_update_in; - m_is_first_update_in = false; - - if(m_pre_decode.size()) - m_pre_decode += piece_of_transfer; - else - m_pre_decode.swap(piece_of_transfer); - piece_of_transfer.clear(); - - std::string decode_summary_buff; - - size_t ungzip_size = m_pre_decode.size() * 0x30; - std::string current_decode_buff(ungzip_size, 'X'); - - //Here the cycle is introduced where we unpack the buffer, the cycle is required - //because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error - bool continue_unpacking = true; - bool first_step = true; - while(m_pre_decode.size() && continue_unpacking) - { - - //fill buffers - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - m_zstream_in.next_out = (Bytef*)current_decode_buff.data(); - m_zstream_in.avail_out = (uInt)ungzip_size; - - int flag = Z_SYNC_FLUSH; - int ret = inflate(&m_zstream_in, flag); - CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " << ret); - - if(Z_STREAM_END == ret) - m_is_stream_ended = true; - else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step) - { - // some servers (notably Apache with mod_deflate) don't generate zlib headers - // insert a dummy header and try again - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - inflateReset(&m_zstream_in); - m_zstream_in.next_in = (Bytef*) dummy_head; - m_zstream_in.avail_in = sizeof(dummy_head); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - } - - - //leave only unpacked part in the output buffer to start with it the next time - m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in); - //if decoder gave nothing to return, then everything is ahead, now simply break - if(ungzip_size == m_zstream_in.avail_out) - break; - - //decode_buff currently stores data parts that were unpacked, fix this size - current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_size); - first_step = false; - } - - //Process these data if required - bool res = true; - - res = m_powner_filter->handle_target_data(decode_summary_buff); - - return true; - - } - /*! \brief - * Function stop : Entry point for stop signal and flushing cached data buffer. - * - */ - inline - virtual void stop(std::string& OUT collect_remains) - { - } - protected: - private: - /*! \brief - * Pointer to parent HTTP-parser - */ - i_target_handler* m_powner_filter; - /*! \brief - * ZLIB object for income stream - */ - z_stream m_zstream_in; - /*! \brief - * ZLIB object for outcome stream - */ - z_stream m_zstream_out; - /*! \brief - * Data that could not be unpacked immediately, left to wait for the next packet of data - */ - std::string m_pre_decode; - /*! \brief - * The data are accumulated for a package in the buffer to send the web client - */ - std::string m_pre_encode; - /*! \brief - * Signals that stream looks like ended - */ - bool m_is_stream_ended; - /*! \brief - * If this flag is set, income data is in HTTP-deflate mode - */ - bool m_is_deflate_mode; - /*! \brief - * Marks that it is a first data packet - */ - bool m_is_first_update_in; - }; -} -} - - - -#endif //_GZIP_ENCODING_H_ diff --git a/contrib/epee/include/hmac-md5.h b/contrib/epee/include/hmac-md5.h deleted file mode 100644 index 2a4e0d40..00000000 --- a/contrib/epee/include/hmac-md5.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* hmac-md5.h -- HMAC_MD5 functions - */ - -/* - * $Id: hmac-md5.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -#ifndef HMAC_MD5_H -#define HMAC_MD5_H 1 - -namespace md5 -{ - - - -#define HMAC_MD5_SIZE 16 - - /* intermediate MD5 context */ - typedef struct HMAC_MD5_CTX_s { - MD5_CTX ictx, octx; - } HMAC_MD5_CTX; - - /* intermediate HMAC state - * values stored in network byte order (Big Endian) - */ - typedef struct HMAC_MD5_STATE_s { - UINT4 istate[4]; - UINT4 ostate[4]; - } HMAC_MD5_STATE; - - /* One step hmac computation - * - * digest may be same as text or key - */ - void hmac_md5(const unsigned char *text, int text_len, - const unsigned char *key, int key_len, - unsigned char digest[HMAC_MD5_SIZE]); - - /* create context from key - */ - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, int key_len); - - /* precalculate intermediate state from key - */ - void hmac_md5_precalc(HMAC_MD5_STATE *hmac, - const unsigned char *key, int key_len); - - /* initialize context from intermediate state - */ - void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); - -#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) - - /* finish hmac from intermediate result. Intermediate result is zeroed. - */ - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac); - -} - -#endif /* HMAC_MD5_H */ diff --git a/contrib/epee/include/include_base_utils.h b/contrib/epee/include/include_base_utils.h deleted file mode 100644 index 8412a008..00000000 --- a/contrib/epee/include/include_base_utils.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING - -#include "misc_log_ex.h" - - diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h deleted file mode 100644 index 11faa976..00000000 --- a/contrib/epee/include/math_helper.h +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - - -#include -#include -#include -#include -#include - -#include "misc_os_dependent.h" -#include "pragma_comp_defs.h" - -namespace epee -{ -namespace math_helper -{ - - template - class average - { - public: - - average() - { - m_base = default_base; - m_last_avg_val = 0; - } - - bool set_base() - { - CRITICAL_REGION_LOCAL(m_lock); - - m_base = default_base; - if(m_list.size() > m_base) - m_list.resize(m_base); - - return true; - } - - typedef val value_type; - - void push(const value_type& vl) - { - CRITICAL_REGION_LOCAL(m_lock); - -//#ifndef DEBUG_STUB - m_list.push_back(vl); - if(m_list.size() > m_base ) - m_list.pop_front(); -//#endif - } - - double update(const value_type& vl) - { - CRITICAL_REGION_LOCAL(m_lock); -//#ifndef DEBUG_STUB - push(vl); -//#endif - - return get_avg(); - } - - double get_avg() - { - CRITICAL_REGION_LOCAL(m_lock); - - value_type vl = std::accumulate(m_list.begin(), m_list.end(), value_type(0)); - if(m_list.size()) - return m_last_avg_val = (double)(vl/m_list.size()); - - return m_last_avg_val = (double)vl; - } - - value_type get_last_val() - { - CRITICAL_REGION_LOCAL(m_lock); - if(m_list.size()) - return m_list.back(); - - return 0; - } - - private: - unsigned int m_base; - double m_last_avg_val; - std::list m_list; - critical_section m_lock; - }; - - -#ifdef WINDOWS_PLATFORM - - /************************************************************************/ - /* */ - /************************************************************************/ - class timing_guard_base - { - public: - virtual ~timing_guard_base(){}; - }; - - template - class timing_guard: public timing_guard_base - { - public: - timing_guard(T& avrg):m_avrg(avrg) - { - m_start_ticks = ::GetTickCount(); - } - - ~timing_guard() - { - m_avrg.push(::GetTickCount()-m_start_ticks); - } - - private: - T& m_avrg; - DWORD m_start_ticks; - }; - - template - timing_guard_base* create_timing_guard(t_timing& timing){return new timing_guard(timing);} - -#define BEGIN_TIMING_ZONE(timing_var) { boost::shared_ptr local_timing_guard_ptr(math_helper::create_timing_guard(timing_var)); -#define END_TIMING_ZONE() } -#endif - -//#ifdef WINDOWS_PLATFORM_EX - template - class speed - { - public: - - speed() - { - m_time_window = default_time_window; - m_last_speed_value = 0; - } - bool chick() - { -#ifndef DEBUG_STUB - uint64_t ticks = misc_utils::get_tick_count(); - CRITICAL_REGION_BEGIN(m_lock); - m_chicks.push_back(ticks); - CRITICAL_REGION_END(); - //flush(ticks); -#endif - return true; - } - - bool chick(size_t count) - { - for(size_t s = 0; s != count; s++) - chick(); - - return true; - } - - - size_t get_speed() - { - flush(misc_utils::get_tick_count()); - return m_last_speed_value = m_chicks.size(); - } - private: - - bool flush(uint64_t ticks) - { - CRITICAL_REGION_BEGIN(m_lock); - std::list::iterator it = m_chicks.begin(); - while(it != m_chicks.end()) - { - if(*it + m_time_window < ticks) - m_chicks.erase(it++); - else - break; - } - CRITICAL_REGION_END(); - return true; - } - - std::list m_chicks; - uint64_t m_time_window; - size_t m_last_speed_value; - critical_section m_lock; - }; -//#endif - - template - void randomize_list(tlist& t_list) - { - for(typename tlist::iterator it = t_list.begin();it!=t_list.end();it++) - { - size_t offset = rand()%t_list.size(); - typename tlist::iterator it_2 = t_list.begin(); - for(size_t local_offset = 0;local_offset!=offset;local_offset++) - it_2++; - if(it_2 == it) - continue; - std::swap(*it_2, *it); - } - - } -PRAGMA_WARNING_PUSH -PRAGMA_GCC("GCC diagnostic ignored \"-Wstrict-aliasing\"") - inline - uint64_t generated_random_uint64() - { - boost::uuids::uuid id___ = boost::uuids::random_generator()(); - return *reinterpret_cast(&id___.data[0]); //(*reinterpret_cast(&id___.data[0]) ^ *reinterpret_cast(&id___.data[8])); - } -PRAGMA_WARNING_POP - template - class once_a_time_seconds - { - public: - once_a_time_seconds():m_interval(default_interval) - { - m_last_worked_time = 0; - if(!start_immediate) - time(&m_last_worked_time); - } - - template - bool do_call(functor_t functr) - { - time_t current_time = 0; - time(¤t_time); - - if(current_time - m_last_worked_time > m_interval) - { - bool res = functr(); - time(&m_last_worked_time); - return res; - } - return true; - } - - private: - time_t m_last_worked_time; - time_t m_interval; - }; -} -} \ No newline at end of file diff --git a/contrib/epee/include/md5_l.h b/contrib/epee/include/md5_l.h deleted file mode 100644 index fe4c67db..00000000 --- a/contrib/epee/include/md5_l.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5.h,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ - */ - -/* MD5.H - header file for MD5C.C - */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. -These notices must be retained in any copies of any part of this -documentation and/or software. - */ -#ifndef MD5_H -#define MD5_H - - -#include "md5global.h" - -namespace md5 -{ - /* MD5 context. */ - typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ - } MD5_CTX; - - static void MD5Init(MD5_CTX * context); - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ); - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ); - static void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest); - - - inline bool md5( unsigned char *input, int ilen, unsigned char output[16] ) - { - MD5_CTX ctx; - - MD5Init( &ctx ); - MD5Update( &ctx, input, ilen ); - MD5Final( output, &ctx); - - memset( &ctx, 0, sizeof( MD5_CTX) ); - return true; - } - - -} - -#include "md5_l.inl" - -#endif diff --git a/contrib/epee/include/md5_l.inl b/contrib/epee/include/md5_l.inl deleted file mode 100644 index c3da1a3b..00000000 --- a/contrib/epee/include/md5_l.inl +++ /dev/null @@ -1,563 +0,0 @@ -/* -* libEtPan! -- a mail stuff library -* -* Copyright (C) 2001, 2005 - DINH Viet Hoa -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the libEtPan! project nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -* SUCH DAMAGE. -*/ - -/* -* $Id: md5.c,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ -*/ - -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -*/ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. -*/ - -/* do i need all of this just for htonl()? damn. */ -//#include -//#include -//#include -//#include - - - -#include "md5global.h" -#include "md5_l.h" -#include "hmac-md5.h" - -namespace md5 -{ - /* Constants for MD5Transform routine. - */ - -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - - /* - static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); - static void Encode PROTO_LIST - ((unsigned char *, UINT4 *, unsigned int)); - static void Decode PROTO_LIST - ((UINT4 *, unsigned char *, unsigned int)); - static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); - static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); - */ - - static void MD5_memcpy (POINTER output, POINTER input, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - output[i] = input[i]; - } - - /* Note: Replace "for loop" with standard memset if possible. - */ - - static void MD5_memset (POINTER output, int value, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; - } - - static void MD5Transform (UINT4 state[4], unsigned char block[64]); - - static unsigned char* PADDING() - { - static unsigned char local_PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - return local_PADDING; - - } - - - - /* F, G, H and I are basic MD5 functions. - - */ -#ifdef I - /* This might be defined via NANA */ -#undef I -#endif - -#define MD5_M_F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define MD5_M_G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define MD5_M_H(x, y, z) ((x) ^ (y) ^ (z)) -#define MD5_M_I(x, y, z) ((y) ^ ((x) | (~z))) - - /* ROTATE_LEFT rotates x left n bits. - - */ - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - - /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. - Rotation is separate from addition to prevent recomputation. - */ - -#define FF(a, b, c, d, x, s, ac) { (a) += MD5_M_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define GG(a, b, c, d, x, s, ac) { (a) += MD5_M_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define HH(a, b, c, d, x, s, ac) { (a) += MD5_M_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define II(a, b, c, d, x, s, ac) { (a) += MD5_M_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } - - /* MD5 initialization. Begins an MD5 operation, writing a new context. - */ - - static void MD5Init(MD5_CTX * context) - { - context->count[0] = context->count[1] = 0; - - /* Load magic initialization constants. - - */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; - } - - /* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the context. - */ - - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ) - { - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3)) - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. - - */ - if (inputLen >= partLen) - { - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)input, partLen ); - MD5Transform( context->state, context->buffer ); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, (unsigned char*)&input[i]); - - index = 0; - } - else - i = 0; - - /* Buffer remaining input */ - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i ); - - } - - /* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - - */ - - static void Encode (unsigned char *output, UINT4 *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } - } - - /* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - - */ - - static void Decode (UINT4 *output, unsigned char *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) - | (((UINT4)input[j+3]) << 24); - } - - /* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. - - */ - - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ) - { - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. - - */ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (context, PADDING(), padLen); - - /* Append length (before padding) */ - MD5Update (context, bits, 8); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. - - */ - MD5_memset ((POINTER)context, 0, sizeof (*context)); - } - - /* MD5 basic transformation. Transforms state based on block. - - */ - - static void MD5Transform (UINT4 state[4], unsigned char block[64]) - { - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. - */ - MD5_memset ((POINTER)x, 0, sizeof (x)); - } - - /* Note: Replace "for loop" with standard memcpy if possible. - - */ - inline - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, - int key_len) - { - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - MD5Init(&hmac->ictx); /* init inner context */ - MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ - - MD5Init(&hmac->octx); /* init outer context */ - MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ - - /* scrub the pads and key context (if used) */ - MD5_memset( (POINTER)&k_ipad, 0, sizeof(k_ipad)); - MD5_memset( (POINTER)&k_opad, 0, sizeof(k_opad)); - MD5_memset( (POINTER)&tk, 0, sizeof(tk)); - - /* and we're done. */ - } - - /* The precalc and import routines here rely on the fact that we pad - * the key out to 64 bytes and use that to initialize the md5 - * contexts, and that updating an md5 context with 64 bytes of data - * leaves nothing left over; all of the interesting state is contained - * in the state field, and none of it is left over in the count and - * buffer fields. So all we have to do is save the state field; we - * can zero the others when we reload it. Which is why the decision - * was made to pad the key out to 64 bytes in the first place. */ - inline - void hmac_md5_precalc(HMAC_MD5_STATE *state, - const unsigned char *key, - int key_len) - { - HMAC_MD5_CTX hmac; - unsigned lupe; - - hmac_md5_init(&hmac, key, key_len); - for (lupe = 0; lupe < 4; lupe++) { - state->istate[lupe] = htonl(hmac.ictx.state[lupe]); - state->ostate[lupe] = htonl(hmac.octx.state[lupe]); - } - MD5_memset( (POINTER)&hmac, 0, sizeof(hmac)); - } - - - inline - void hmac_md5_import(HMAC_MD5_CTX *hmac, - HMAC_MD5_STATE *state) - { - unsigned lupe; - MD5_memset( (POINTER)hmac, 0, sizeof(HMAC_MD5_CTX)); - for (lupe = 0; lupe < 4; lupe++) { - hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); - hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); - } - /* Init the counts to account for our having applied - * 64 bytes of key; this works out to 0x200 (64 << 3; see - * MD5Update above...) */ - hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; - } - - inline - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac) - { - MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ - MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ - MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ - } - - - void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest) - { - MD5_CTX context; - - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ - - MD5Init(&context); /* init context for 1st - * pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final(digest, &context); /* finish up 1st pass */ - - /* - * perform outer MD5 - */ - MD5Init(&context); /* init context for 2nd - * pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st - * hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ - - } -} \ No newline at end of file diff --git a/contrib/epee/include/md5global.h b/contrib/epee/include/md5global.h deleted file mode 100644 index afc22901..00000000 --- a/contrib/epee/include/md5global.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -/* GLOBAL.H - RSAREF types and constants - */ - -#ifndef MD5GLOBAL_H -#define MD5GLOBAL_H - -namespace md5 -{ - - - /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. - The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. - */ -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif - - /* POINTER defines a generic pointer type */ - typedef unsigned char *POINTER; - - /* UINT2 defines a two byte word */ - typedef unsigned short int UINT2; - - /* UINT4 defines a four byte word */ - //typedef unsigned long int UINT4; - typedef unsigned int UINT4; - - /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. - If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. - */ -#if PROTOTYPES -#define PROTO_LIST(list) list -#else -#define PROTO_LIST(list) () -#endif - -} - -#endif diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h deleted file mode 100644 index d5157365..00000000 --- a/contrib/epee/include/misc_language.h +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include -namespace epee -{ -#define STD_TRY_BEGIN() try { - -#define STD_TRY_CATCH(where_, ret_val) \ - } \ - catch (const std::exception &e) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ << ", mes: "<< e.what()); \ - return ret_val; \ - } \ - catch (...) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ ); \ - return ret_val; \ - } - - - -#define AUTO_VAL_INIT(v) boost::value_initialized() - -namespace misc_utils -{ - template - t_type get_max_t_val(t_type t) - { - return (std::numeric_limits::max)(); - } - - - template - t_iterator move_it_forward(t_iterator it, size_t count) - { - while(count--) - it++; - return it; - } - - template - t_iterator move_it_backward(t_iterator it, size_t count) - { - while(count--) - it--; - return it; - } - - - // TEMPLATE STRUCT less - template - struct less_as_pod - : public std::binary_function<_Ty, _Ty, bool> - { // functor for operator< - bool operator()(const _Ty& _Left, const _Ty& _Right) const - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - }; - - template - bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right) - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - - - inline - bool sleep_no_w(long ms ) - { - boost::this_thread::sleep( - boost::get_system_time() + - boost::posix_time::milliseconds( std::max(ms,0) ) ); - - return true; - } - - template - type_vec_type median(std::vector &v) - { - if(v.empty()) - return boost::value_initialized(); - if(v.size() == 1) - return v[0]; - - size_t n = (v.size()) / 2; - std::sort(v.begin(), v.end()); - //nth_element(v.begin(), v.begin()+n-1, v.end()); - if(v.size()%2) - {//1, 3, 5... - return v[n]; - }else - {//2, 4, 6... - return (v[n-1] + v[n])/2; - } - - } - - /************************************************************************/ - /* */ - /************************************************************************/ - - struct call_befor_die_base - { - virtual ~call_befor_die_base(){} - }; - - typedef boost::shared_ptr auto_scope_leave_caller; - - - template - struct call_befor_die: public call_befor_die_base - { - t_scope_leave_handler m_func; - call_befor_die(t_scope_leave_handler f):m_func(f) - {} - ~call_befor_die() - { - m_func(); - } - }; - - template - auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f) - { - auto_scope_leave_caller slc(new call_befor_die(f)); - return slc; - } - -} -} diff --git a/contrib/epee/include/misc_log_ex.cpp b/contrib/epee/include/misc_log_ex.cpp deleted file mode 100644 index 0c0b441b..00000000 --- a/contrib/epee/include/misc_log_ex.cpp +++ /dev/null @@ -1,1029 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "misc_log_ex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(WIN32) -#include -#else -#include -#endif - -#include "static_initializer.h" -#include "string_tools.h" -#include "time_helper.h" -#include "misc_os_dependent.h" - -#include "syncobj.h" - - -#define LOG_LEVEL_SILENT -1 -#define LOG_LEVEL_0 0 -#define LOG_LEVEL_1 1 -#define LOG_LEVEL_2 2 -#define LOG_LEVEL_3 3 -#define LOG_LEVEL_4 4 -#define LOG_LEVEL_MIN LOG_LEVEL_SILENT -#define LOG_LEVEL_MAX LOG_LEVEL_4 - - -#define LOGGER_NULL 0 -#define LOGGER_FILE 1 -#define LOGGER_DEBUGGER 2 -#define LOGGER_CONSOLE 3 -#define LOGGER_DUMP 4 - - -#ifndef LOCAL_ASSERT -#include -#if (defined _MSC_VER) -#define LOCAL_ASSERT(expr) {if(epee::debug::get_set_enable_assert()){_ASSERTE(expr);}} -#else -#define LOCAL_ASSERT(expr) -#endif - -#endif - -namespace epee { -namespace log_space { - //---------------------------------------------------------------------------- - bool is_stdout_a_tty() - { - static std::atomic initialized(false); - static std::atomic is_a_tty(false); - - if (!initialized.load(std::memory_order_acquire)) - { -#if defined(WIN32) - is_a_tty.store(0 != _isatty(_fileno(stdout)), std::memory_order_relaxed); -#else - is_a_tty.store(0 != isatty(fileno(stdout)), std::memory_order_relaxed); -#endif - initialized.store(true, std::memory_order_release); - } - - return is_a_tty.load(std::memory_order_relaxed); - } - //---------------------------------------------------------------------------- - void set_console_color(int color, bool bright) - { - if (!is_stdout_a_tty()) - return; - - switch(color) - { - case console_color_default: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE| (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;37m"; - else - std::cout << "\033[0m"; -#endif - } - break; - case console_color_white: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;37m"; - else - std::cout << "\033[0;37m"; -#endif - } - break; - case console_color_red: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;31m"; - else - std::cout << "\033[0;31m"; -#endif - } - break; - case console_color_green: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;32m"; - else - std::cout << "\033[0;32m"; -#endif - } - break; - - case console_color_blue: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_INTENSITY);//(bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;34m"; - else - std::cout << "\033[0;34m"; -#endif - } - break; - - case console_color_cyan: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;36m"; - else - std::cout << "\033[0;36m"; -#endif - } - break; - - case console_color_magenta: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;35m"; - else - std::cout << "\033[0;35m"; -#endif - } - break; - - case console_color_yellow: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;33m"; - else - std::cout << "\033[0;33m"; -#endif - } - break; - - } - } - //---------------------------------------------------------------------------- - void reset_console_color() { - if (!is_stdout_a_tty()) - return; - -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); -#else - std::cout << "\033[0m"; - std::cout.flush(); -#endif - } - //---------------------------------------------------------------------------- - bool rotate_log_file(const char* pfile_path) - { -#ifdef _MSC_VER - if(!pfile_path) - return false; - - std::string file_path = pfile_path; - std::string::size_type a = file_path .rfind('.'); - if ( a != std::string::npos ) - file_path .erase( a, file_path .size()); - - ::DeleteFileA( (file_path + ".0").c_str() ); - ::MoveFileA( (file_path + ".log").c_str(), (file_path + ".0").c_str() ); -#else - return false;//not implemented yet -#endif - return true; - } - //---------------------------------------------------------------------------- -#ifdef _MSC_VER - bool debug_output_stream::out_buffer( const char* buffer, int buffer_len , int log_level, int color, const char* plog_name/* = NULL*/) - { - for ( int i = 0; i < buffer_len; i = i + max_dbg_str_len ) - { - std::string s( buffer + i, buffer_len- i < max_dbg_str_len ? - buffer_len - i : max_dbg_str_len ); - - ::OutputDebugStringA( s.c_str() ); - } - return true; - } -#endif - //---------------------------------------------------------------------------- - console_output_stream::console_output_stream() - { -#ifdef _MSC_VER - - if(!::GetStdHandle(STD_OUTPUT_HANDLE)) - m_have_to_kill_console = true; - else - m_have_to_kill_console = false; - - ::AllocConsole(); -#endif - } - //---------------------------------------------------------------------------- - console_output_stream::~console_output_stream() - { -#ifdef _MSC_VER - if(m_have_to_kill_console) - ::FreeConsole(); -#endif - } - //---------------------------------------------------------------------------- - bool console_output_stream::out_buffer( const char* buffer, int buffer_len , int log_level, int color, const char* plog_name/* = NULL*/) - { - if(plog_name) - return true; //skip alternative logs from console - - set_console_color(color, log_level < 1); - -#ifdef _MSC_VER - const char* ptarget_buf = NULL; - char* pallocated_buf = NULL; - - // - int i = 0; - for(; i < buffer_len; i++) - if(buffer[i] == '\a') break; - if(i == buffer_len) - ptarget_buf = buffer; - else - { - pallocated_buf = new char[buffer_len]; - ptarget_buf = pallocated_buf; - for(i = 0; i < buffer_len; i++) - { - if(buffer[i] == '\a') - pallocated_buf[i] = '^'; - else - pallocated_buf[i] = buffer[i]; - } - } - - //uint32_t b = 0; - //::WriteConsoleA(::GetStdHandle(STD_OUTPUT_HANDLE), ptarget_buf, buffer_len, (DWORD*)&b, 0); - std::cout << ptarget_buf; - if(pallocated_buf) delete [] pallocated_buf; -#else - std::string buf(buffer, buffer_len); - for(size_t i = 0; i!= buf.size(); i++) - { - if(buf[i] == 7 || buf[i] == -107) - buf[i] = '^'; - } - - std::cout << buf; -#endif - reset_console_color(); - return true; - } - //---------------------------------------------------------------------------- - file_output_stream::file_output_stream(std::string default_log_file_name, std::string log_path) - { - m_default_log_filename = default_log_file_name; - m_max_logfile_size = 0; - m_default_log_path = log_path; - m_pdefault_file_stream = add_new_stream_and_open(default_log_file_name.c_str()); - } - //---------------------------------------------------------------------------- - file_output_stream::~file_output_stream() - { - for(named_log_streams::iterator it = m_log_file_names.begin(); it!=m_log_file_names.end(); it++) - { - if ( it->second->is_open() ) - { - it->second->flush(); - it->second->close(); - } - delete it->second; - } - } - //---------------------------------------------------------------------------- - std::ofstream* file_output_stream::add_new_stream_and_open(const char* pstream_name) - { - //log_space::rotate_log_file((m_default_log_path + "\\" + pstream_name).c_str()); - - std::ofstream* pstream = (m_log_file_names[pstream_name] = new std::ofstream); - std::string target_path = m_default_log_path + "/" + pstream_name; - pstream->open( target_path.c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */); - if(pstream->fail()) - return NULL; - return pstream; - } - //---------------------------------------------------------------------------- - bool file_output_stream::set_max_logfile_size(uint64_t max_size) - { - m_max_logfile_size = max_size; - return true; - } - //---------------------------------------------------------------------------- - bool file_output_stream::set_log_rotate_cmd(const std::string& cmd) - { - m_log_rotate_cmd = cmd; - return true; - } - //---------------------------------------------------------------------------- - bool file_output_stream::out_buffer(const char* buffer, int buffer_len, int log_level, int color, const char* plog_name/* = NULL*/) - { - std::ofstream* m_target_file_stream = m_pdefault_file_stream; - if(plog_name) - { //find named stream - named_log_streams::iterator it = m_log_file_names.find(plog_name); - if(it == m_log_file_names.end()) - m_target_file_stream = add_new_stream_and_open(plog_name); - else - m_target_file_stream = it->second; - } - if(!m_target_file_stream || !m_target_file_stream->is_open()) - return false;//TODO: add assert here - - m_target_file_stream->write(buffer, buffer_len ); - m_target_file_stream->flush(); - - if(m_max_logfile_size) - { - std::ofstream::pos_type pt = m_target_file_stream->tellp(); - uint64_t current_sz = pt; - if(current_sz > m_max_logfile_size) - { - std::cout << "current_sz= " << current_sz << " m_max_logfile_size= " << m_max_logfile_size << std::endl; - std::string log_file_name; - if(!plog_name) - log_file_name = m_default_log_filename; - else - log_file_name = plog_name; - - m_target_file_stream->close(); - std::string new_log_file_name = log_file_name; - - time_t tm = 0; - time(&tm); - - int err_count = 0; - boost::system::error_code ec; - do - { - new_log_file_name = string_tools::cut_off_extension(log_file_name); - if(err_count) - new_log_file_name += misc_utils::get_time_str_v2(tm) + "(" + boost::lexical_cast(err_count) + ")" + ".log"; - else - new_log_file_name += misc_utils::get_time_str_v2(tm) + ".log"; - - err_count++; - }while(boost::filesystem::exists(m_default_log_path + "/" + new_log_file_name, ec)); - - std::string new_log_file_path = m_default_log_path + "/" + new_log_file_name; - boost::filesystem::rename(m_default_log_path + "/" + log_file_name, new_log_file_path, ec); - if(ec) - { - std::cout << "Filed to rename, ec = " << ec.message() << std::endl; - } - - if(m_log_rotate_cmd.size()) - { - - std::string m_log_rotate_cmd_local_copy = m_log_rotate_cmd; - //boost::replace_all(m_log_rotate_cmd, "[*SOURCE*]", new_log_file_path); - boost::replace_all(m_log_rotate_cmd_local_copy, "[*TARGET*]", new_log_file_path); - - misc_utils::call_sys_cmd(m_log_rotate_cmd_local_copy); - } - - m_target_file_stream->open( (m_default_log_path + "/" + log_file_name).c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */); - if(m_target_file_stream->fail()) - return false; - } - } - - return true; - } - //---------------------------------------------------------------------------- - log_stream_splitter::~log_stream_splitter() - { - //free pointers - std::for_each(m_log_streams.begin(), m_log_streams.end(), delete_ptr()); - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::set_max_logfile_size(uint64_t max_size) - { - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - it->first->set_max_logfile_size(max_size); - return true; - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::set_log_rotate_cmd(const std::string& cmd) - { - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - it->first->set_log_rotate_cmd(cmd); - return true; - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::do_log_message(const std::string& rlog_mes, int log_level, int color, const char* plog_name/* = NULL*/) - { - std::string str_mess = rlog_mes; - size_t str_len = str_mess.size(); - const char* pstr = str_mess.c_str(); - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - if(it->second >= log_level) - it->first->out_buffer(pstr, (int)str_len, log_level, color, plog_name); - return true; - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::add_logger(int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit/* = LOG_LEVEL_4*/) - { - ibase_log_stream* ls = NULL; - - switch( type ) - { - case LOGGER_FILE: - ls = new file_output_stream( pdefault_file_name, pdefault_log_folder ); - break; - - case LOGGER_DEBUGGER: -#ifdef _MSC_VER - ls = new debug_output_stream( ); -#else - return false;//not implemented yet -#endif - break; - case LOGGER_CONSOLE: - ls = new console_output_stream( ); - break; - } - - if ( ls ) { - m_log_streams.push_back(streams_container::value_type(ls, log_level_limit)); - return true; - } - return ls ? true:false; - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::add_logger(ibase_log_stream* pstream, int log_level_limit/* = LOG_LEVEL_4*/) - { - m_log_streams.push_back(streams_container::value_type(pstream, log_level_limit) ); - return true; - } - //---------------------------------------------------------------------------- - bool log_stream_splitter::remove_logger(int type) - { - streams_container::iterator it = m_log_streams.begin(); - for(;it!=m_log_streams.end(); it++) - { - if(it->first->get_type() == type) - { - delete it->first; - m_log_streams.erase(it); - return true; - } - } - return false; - } - //---------------------------------------------------------------------------- - std::string get_daytime_string2() - { - boost::posix_time::ptime p = boost::posix_time::microsec_clock::local_time(); - return misc_utils::get_time_str_v3(p); - } - //---------------------------------------------------------------------------- - std::string get_day_time_string() - { - return get_daytime_string2(); - //time_t tm = 0; - //time(&tm); - //return misc_utils::get_time_str(tm); - } - //---------------------------------------------------------------------------- - std::string get_time_string() - { - return get_daytime_string2(); - } - //---------------------------------------------------------------------------- -#ifdef _MSC_VER - std::string get_time_string_adv(SYSTEMTIME* pst/* = NULL*/) - { - SYSTEMTIME st = {0}; - if(!pst) - { - pst = &st; - GetSystemTime(&st); - } - std::stringstream str_str; - str_str.fill('0'); - str_str << std::setw(2) << pst->wHour << "_" - << std::setw(2) << pst->wMinute << "_" - << std::setw(2) << pst->wSecond << "_" - << std::setw(3) << pst->wMilliseconds; - return str_str.str(); - } -#endif - //---------------------------------------------------------------------------- - logger::logger() - { - CRITICAL_REGION_BEGIN(m_critical_sec); - init(); - CRITICAL_REGION_END(); - } - //---------------------------------------------------------------------------- - bool logger::set_max_logfile_size(uint64_t max_size) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.set_max_logfile_size(max_size); - CRITICAL_REGION_END(); - return true; - } - //---------------------------------------------------------------------------- - bool logger::set_log_rotate_cmd(const std::string& cmd) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.set_log_rotate_cmd(cmd); - CRITICAL_REGION_END(); - return true; - } - //---------------------------------------------------------------------------- - bool logger::take_away_journal(std::list& journal) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - m_journal.swap(journal); - CRITICAL_REGION_END(); - return true; - } - //---------------------------------------------------------------------------- - bool logger::do_log_message(const std::string& rlog_mes, int log_level, int color, bool add_to_journal/* = false*/, const char* plog_name/* = NULL*/) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.do_log_message(rlog_mes, log_level, color, plog_name); - if(add_to_journal) - m_journal.push_back(rlog_mes); - - return true; - CRITICAL_REGION_END(); - } - //---------------------------------------------------------------------------- - bool logger::add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit/* = LOG_LEVEL_4*/) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.add_logger( type, pdefault_file_name, pdefault_log_folder, log_level_limit); - CRITICAL_REGION_END(); - } - //---------------------------------------------------------------------------- - bool logger::add_logger( ibase_log_stream* pstream, int log_level_limit/* = LOG_LEVEL_4*/) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.add_logger(pstream, log_level_limit); - CRITICAL_REGION_END(); - } - //---------------------------------------------------------------------------- - bool logger::remove_logger(int type) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.remove_logger(type); - CRITICAL_REGION_END(); - } - //---------------------------------------------------------------------------- - bool logger::set_thread_prefix(const std::string& prefix) - { - CRITICAL_REGION_BEGIN(m_critical_sec); - m_thr_prefix_strings[misc_utils::get_thread_string_id()] = prefix; - CRITICAL_REGION_END(); - return true; - } - //---------------------------------------------------------------------------- - bool logger::init() - { - m_process_name = string_tools::get_current_module_name(); - - init_log_path_by_default(); - - //init default set of loggers - init_default_loggers(); - - std::stringstream ss; - ss << get_time_string() << " Init logging. Level=" << get_set_log_detalisation_level() - << " Log path=" << m_default_log_folder << std::endl; - this->do_log_message(ss.str(), console_color_white, LOG_LEVEL_0); - return true; - } - //---------------------------------------------------------------------------- - bool logger::init_default_loggers() - { - return true; - } - //---------------------------------------------------------------------------- - bool logger::init_log_path_by_default() - { - //load process name - m_default_log_folder = string_tools::get_current_module_folder(); - - m_default_log_file = m_process_name; - std::string::size_type a = m_default_log_file.rfind('.'); - if ( a != std::string::npos ) - m_default_log_file.erase( a, m_default_log_file.size()); - m_default_log_file += ".log"; - - return true; - } - //---------------------------------------------------------------------------- - int log_singletone::get_log_detalisation_level() - { - get_or_create_instance();//to initialize logger, if it not initialized - return get_set_log_detalisation_level(); - } - //---------------------------------------------------------------------------- - bool log_singletone::is_filter_error(int error_code) - { - return false; - } - //---------------------------------------------------------------------------- - bool log_singletone::do_log_message(const std::string& rlog_mes, int log_level, int color, bool keep_in_journal, const char* plog_name/* = NULL*/) - { - logger* plogger = get_or_create_instance(); - bool res = false; - if(plogger) - res = plogger->do_log_message(rlog_mes, log_level, color, keep_in_journal, plog_name); - else - { //globally uninitialized, create new logger for each call of do_log_message() and then delete it - plogger = new logger(); - //TODO: some extra initialization - res = plogger->do_log_message(rlog_mes, log_level, color, keep_in_journal, plog_name); - delete plogger; - plogger = NULL; - } - return res; - } - //---------------------------------------------------------------------------- - bool log_singletone::take_away_journal(std::list& journal) - { - logger* plogger = get_or_create_instance(); - bool res = false; - if(plogger) - res = plogger->take_away_journal(journal); - - return res; - } - //---------------------------------------------------------------------------- - bool log_singletone::set_max_logfile_size(uint64_t file_size) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_max_logfile_size(file_size); - } - //---------------------------------------------------------------------------- - bool log_singletone::set_log_rotate_cmd(const std::string& cmd) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_log_rotate_cmd(cmd); - } - //---------------------------------------------------------------------------- - bool log_singletone::add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit/* = LOG_LEVEL_4*/) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->add_logger(type, pdefault_file_name, pdefault_log_folder, log_level_limit); - } - //---------------------------------------------------------------------------- - std::string log_singletone::get_default_log_file() - { - logger* plogger = get_or_create_instance(); - if(plogger) - return plogger->get_default_log_file(); - - return ""; - } - //---------------------------------------------------------------------------- - std::string log_singletone::get_default_log_folder() - { - logger* plogger = get_or_create_instance(); - if(plogger) - return plogger->get_default_log_folder(); - - return ""; - } - //---------------------------------------------------------------------------- - bool log_singletone::add_logger(ibase_log_stream* pstream, int log_level_limit/* = LOG_LEVEL_4*/) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->add_logger(pstream, log_level_limit); - } - //---------------------------------------------------------------------------- - bool log_singletone::remove_logger(int type) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->remove_logger(type); - } - //---------------------------------------------------------------------------- -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - int log_singletone::get_set_log_detalisation_level(bool is_need_set/* = false*/, int log_level_to_set/* = LOG_LEVEL_1*/) - { - static int log_detalisation_level = LOG_LEVEL_1; - if(is_need_set) - log_detalisation_level = log_level_to_set; - return log_detalisation_level; - } -POP_WARNINGS - //---------------------------------------------------------------------------- - int log_singletone::get_set_time_level(bool is_need_set/* = false*/, int time_log_level/* = LOG_LEVEL_0*/) - { - static int val_time_log_level = LOG_LEVEL_0; - if(is_need_set) - val_time_log_level = time_log_level; - - return val_time_log_level; - } - //---------------------------------------------------------------------------- - int log_singletone::get_set_process_level(bool is_need_set/* = false*/, int process_log_level/* = LOG_LEVEL_0*/) - { - static int val_process_log_level = LOG_LEVEL_0; - if(is_need_set) - val_process_log_level = process_log_level; - - return val_process_log_level; - } - //---------------------------------------------------------------------------- - bool log_singletone::get_set_need_thread_id(bool is_need_set/* = false*/, bool is_need_val/* = false*/) - { - static bool is_need = false; - if(is_need_set) - is_need = is_need_val; - - return is_need; - } - //---------------------------------------------------------------------------- - bool log_singletone::get_set_need_proc_name(bool is_need_set/* = false*/, bool is_need_val/* = false*/) - { - static bool is_need = true; - if(is_need_set) - is_need = is_need_val; - - return is_need; - } - //---------------------------------------------------------------------------- - uint64_t log_singletone::get_set_err_count(bool is_need_set/* = false*/, uint64_t err_val/* = false*/) - { - static uint64_t err_count = 0; - if(is_need_set) - err_count = err_val; - - return err_count; - } - //---------------------------------------------------------------------------- -#ifdef _MSC_VER - void log_singletone::SetThreadName( DWORD dwThreadID, const char* threadName) - { -#define MS_VC_EXCEPTION 0x406D1388 - -#pragma pack(push,8) - typedef struct tagTHREADNAME_INFO - { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. - } THREADNAME_INFO; -#pragma pack(pop) - - Sleep(10); - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = (char*)threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try - { - RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - } -#endif - //---------------------------------------------------------------------------- - bool log_singletone::set_thread_log_prefix(const std::string& prefix) - { -#ifdef _MSC_VER - SetThreadName(-1, prefix.c_str()); -#endif - - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_thread_prefix(prefix); - } - //---------------------------------------------------------------------------- - std::string log_singletone::get_prefix_entry() - { - std::stringstream str_prefix; - //write time entry - if ( get_set_time_level() <= get_set_log_detalisation_level() ) - str_prefix << get_day_time_string() << " "; - - //write process info - logger* plogger = get_or_create_instance(); - //bool res = false; - if(!plogger) - { //globally uninitialized, create new logger for each call of get_prefix_entry() and then delete it - plogger = new logger(); - } - - //if ( get_set_need_proc_name() && get_set_process_level() <= get_set_log_detalisation_level() ) - // str_prefix << "[" << plogger->m_process_name << " (id=" << GetCurrentProcessId() << ")] "; -//#ifdef _MSC_VER_EX - if ( get_set_need_thread_id() /*&& get_set_tid_level() <= get_set_log_detalisation_level()*/ ) - str_prefix << "tid:" << misc_utils::get_thread_string_id() << " "; -//#endif - - if(plogger->m_thr_prefix_strings.size()) - { - CRITICAL_REGION_LOCAL(plogger->m_critical_sec); - std::string thr_str = misc_utils::get_thread_string_id(); - std::map::iterator it = plogger->m_thr_prefix_strings.find(thr_str); - if(it!=plogger->m_thr_prefix_strings.end()) - { - str_prefix << it->second; - } - } - - if(get_set_is_uninitialized()) - delete plogger; - - return str_prefix.str(); - } - //---------------------------------------------------------------------------- - bool log_singletone::init() - { - return true;/*do nothing here*/ - } - //---------------------------------------------------------------------------- - bool log_singletone::un_init() - { - //delete object - logger* plogger = get_set_instance_internal(); - if(plogger) delete plogger; - //set uninitialized - get_set_is_uninitialized(true, true); - get_set_instance_internal(true, NULL); - return true; - } - //---------------------------------------------------------------------------- - logger* log_singletone::get_or_create_instance() - { - logger* plogger = get_set_instance_internal(); - if(!plogger) - if(!get_set_is_uninitialized()) - get_set_instance_internal(true, plogger = new logger); - - return plogger; - } - //---------------------------------------------------------------------------- - logger* log_singletone::get_set_instance_internal(bool is_need_set/* = false*/, logger* pnew_logger_val/* = NULL*/) - { - static logger* val_plogger = NULL; - - if(is_need_set) - val_plogger = pnew_logger_val; - - return val_plogger; - } - //---------------------------------------------------------------------------- - bool log_singletone::get_set_is_uninitialized(bool is_need_set/* = false*/, bool is_uninitialized/* = false*/) - { - static bool val_is_uninitialized = false; - - if(is_need_set) - val_is_uninitialized = is_uninitialized; - - return val_is_uninitialized; - } - //---------------------------------------------------------------------------- - log_frame::log_frame(const std::string& name, int dlevel/* = LOG_LEVEL_2*/, const char* plog_name/* = NULL*/) - { -#ifdef _MSC_VER - int lasterr=::GetLastError(); -#endif - m_plog_name = plog_name; - if ( dlevel <= log_singletone::get_log_detalisation_level() ) - { - m_name = name; - std::stringstream ss; - ss << log_space::log_singletone::get_prefix_entry() << "-->>" << m_name << std::endl; - log_singletone::do_log_message(ss.str(), dlevel, console_color_default, false, m_plog_name); - } - m_level = dlevel; -#ifdef _MSC_VER - ::SetLastError(lasterr); -#endif - } - //---------------------------------------------------------------------------- - log_frame::~log_frame() - { -#ifdef _MSC_VER - int lasterr=::GetLastError(); -#endif - - if (m_level <= log_singletone::get_log_detalisation_level() ) - { - std::stringstream ss; - ss << log_space::log_singletone::get_prefix_entry() << "<<--" << m_name << std::endl; - log_singletone::do_log_message(ss.str(), m_level, console_color_default, false,m_plog_name); - } -#ifdef _MSC_VER - ::SetLastError(lasterr); -#endif - } - //---------------------------------------------------------------------------- - std::string get_win32_err_descr(int err_no) - { -#ifdef _MSC_VER - LPVOID lpMsgBuf; - - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - err_no, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (char*) &lpMsgBuf, - 0, NULL ); - - std::string fix_sys_message = "(null)"; - if(lpMsgBuf) fix_sys_message = (char*)lpMsgBuf; - std::string::size_type a; - if ( (a = fix_sys_message.rfind( '\n' )) != std::string::npos ) - fix_sys_message.erase(a); - if ( (a = fix_sys_message.rfind( '\r' )) != std::string::npos ) - fix_sys_message.erase(a); - - LocalFree(lpMsgBuf); - return fix_sys_message; -#else - return "Not implemented yet"; -#endif - } - //---------------------------------------------------------------------------- - bool getwin32_err_text(std::stringstream& ref_message, int error_no) - { - ref_message << "win32 error:" << get_win32_err_descr(error_no); - return true; - } -} -} diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h deleted file mode 100644 index 918bfcf2..00000000 --- a/contrib/epee/include/misc_log_ex.h +++ /dev/null @@ -1,507 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#ifndef _MISC_LOG_EX_H_ -#define _MISC_LOG_EX_H_ - -#if defined(WIN32) -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN -#endif -#endif - -#include -#include -#include -#include -#include - -#include "misc_os_dependent.h" -#include "static_initializer.h" -#include "syncobj.h" -#include "warnings.h" - - -#define LOG_LEVEL_SILENT -1 -#define LOG_LEVEL_0 0 -#define LOG_LEVEL_1 1 -#define LOG_LEVEL_2 2 -#define LOG_LEVEL_3 3 -#define LOG_LEVEL_4 4 -#define LOG_LEVEL_MIN LOG_LEVEL_SILENT -#define LOG_LEVEL_MAX LOG_LEVEL_4 - - -#define LOGGER_NULL 0 -#define LOGGER_FILE 1 -#define LOGGER_DEBUGGER 2 -#define LOGGER_CONSOLE 3 -#define LOGGER_DUMP 4 - - -#ifndef LOCAL_ASSERT -#include -#if (defined _MSC_VER) -#define LOCAL_ASSERT(expr) {if(epee::debug::get_set_enable_assert()){_ASSERTE(expr);}} -#else -#define LOCAL_ASSERT(expr) -#endif - -#endif - -namespace epee -{ -namespace debug -{ - inline bool get_set_enable_assert(bool set = false, bool v = false) - { - static bool e = true; - if(set) - e = v; - return e; - } -} -namespace log_space -{ - class logger; - class log_message; - class log_singletone; - - /************************************************************************/ - /* */ - /************************************************************************/ - enum console_colors - { - console_color_default, - console_color_white, - console_color_red, - console_color_green, - console_color_blue, - console_color_cyan, - console_color_magenta, - console_color_yellow - }; - - - struct ibase_log_stream - { - ibase_log_stream() {} - virtual ~ibase_log_stream() {} - virtual bool out_buffer(const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL)=0; - virtual int get_type() const { return 0; } - - virtual bool set_max_logfile_size(uint64_t max_size) { return true; } - virtual bool set_log_rotate_cmd(const std::string& cmd) { return true; } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct delete_ptr - { - template - void operator() (P p) - { - delete p.first; - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - bool is_stdout_a_tty(); - void set_console_color(int color, bool bright); - void reset_console_color(); - bool rotate_log_file(const char* pfile_path); - - //------------------------------------------------------------------------ -#define max_dbg_str_len 80 -#ifdef _MSC_VER - class debug_output_stream: public ibase_log_stream - { - virtual bool out_buffer(const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL) override; - }; -#endif - - class console_output_stream: public ibase_log_stream - { -#ifdef _MSC_VER - bool m_have_to_kill_console; -#endif - - public: - console_output_stream(); - virtual ~console_output_stream(); - - virtual int get_type() const override { return LOGGER_CONSOLE; } - virtual bool out_buffer(const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL) override; - }; - - //--------------------------------------------------------------------------// - class file_output_stream : public ibase_log_stream - { - public: - typedef std::map named_log_streams; - - file_output_stream(std::string default_log_file_name, std::string log_path); - ~file_output_stream(); - - private: - named_log_streams m_log_file_names; - std::string m_default_log_path; - std::ofstream* m_pdefault_file_stream; - std::string m_log_rotate_cmd; - std::string m_default_log_filename; - uint64_t m_max_logfile_size; - - virtual int get_type() const override { return LOGGER_FILE; } - virtual bool out_buffer(const char* buffer, int buffer_len, int log_level, int color, const char* plog_name = NULL) override; - virtual bool set_max_logfile_size(uint64_t max_size) override; - virtual bool set_log_rotate_cmd(const std::string& cmd) override; - - std::ofstream* add_new_stream_and_open(const char* pstream_name); - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class log_stream_splitter - { - public: - typedef std::list > streams_container; - - log_stream_splitter() { } - ~log_stream_splitter(); - - bool set_max_logfile_size(uint64_t max_size); - bool set_log_rotate_cmd(const std::string& cmd); - bool do_log_message(const std::string& rlog_mes, int log_level, int color, const char* plog_name = NULL); - bool add_logger(int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit = LOG_LEVEL_4); - bool add_logger(ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4); - bool remove_logger(int type); - - private: - streams_container m_log_streams; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - int get_set_log_detalisation_level(bool is_need_set = false, int log_level_to_set = LOG_LEVEL_1); - int get_set_time_level(bool is_need_set = false, int time_log_level = LOG_LEVEL_0); - bool get_set_need_thread_id(bool is_need_set = false, bool is_need_val = false); - bool get_set_need_proc_name(bool is_need_set = false, bool is_need_val = false); - - std::string get_daytime_string2(); - std::string get_day_time_string(); - std::string get_time_string(); - -#ifdef _MSC_VER - inline std::string get_time_string_adv(SYSTEMTIME* pst = NULL); -#endif - - class logger - { - public: - friend class log_singletone; - - logger(); - ~logger() { } - - bool set_max_logfile_size(uint64_t max_size); - bool set_log_rotate_cmd(const std::string& cmd); - bool take_away_journal(std::list& journal); - bool do_log_message(const std::string& rlog_mes, int log_level, int color, bool add_to_journal = false, const char* plog_name = NULL); - bool add_logger(int type, const char* pdefault_file_name, const char* pdefault_log_folder , int log_level_limit = LOG_LEVEL_4); - bool add_logger(ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4); - bool remove_logger(int type); - bool set_thread_prefix(const std::string& prefix); - std::string get_default_log_file() { return m_default_log_file; } - std::string get_default_log_folder() { return m_default_log_folder; } - - private: - bool init(); - bool init_default_loggers(); - bool init_log_path_by_default(); - - log_stream_splitter m_log_target; - - std::string m_default_log_folder; - std::string m_default_log_file; - std::string m_process_name; - std::map m_thr_prefix_strings; - std::list m_journal; - critical_section m_critical_sec; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class log_singletone - { - public: - friend class initializer; - friend class logger; - - static int get_log_detalisation_level(); - static bool is_filter_error(int error_code); - static bool do_log_message(const std::string& rlog_mes, int log_level, int color, bool keep_in_journal, const char* plog_name = NULL); - static bool take_away_journal(std::list& journal); - static bool set_max_logfile_size(uint64_t file_size); - static bool set_log_rotate_cmd(const std::string& cmd); - static bool add_logger(int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit = LOG_LEVEL_4); - static std::string get_default_log_file(); - static std::string get_default_log_folder(); - static bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4); - static bool remove_logger(int type); - -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - static int get_set_log_detalisation_level(bool is_need_set = false, int log_level_to_set = LOG_LEVEL_1); -POP_WARNINGS - - static int get_set_time_level(bool is_need_set = false, int time_log_level = LOG_LEVEL_0); - static int get_set_process_level(bool is_need_set = false, int process_log_level = LOG_LEVEL_0); - static bool get_set_need_thread_id(bool is_need_set = false, bool is_need_val = false); - static bool get_set_need_proc_name(bool is_need_set = false, bool is_need_val = false); - static uint64_t get_set_err_count(bool is_need_set = false, uint64_t err_val = false); - -#ifdef _MSC_VER - static void SetThreadName( DWORD dwThreadID, const char* threadName); -#endif - - static bool set_thread_log_prefix(const std::string& prefix); - static std::string get_prefix_entry(); - - private: - log_singletone() { } //restric to create an instance - //static initializer m_log_initializer;//must be in one .cpp file (for example main.cpp) via DEFINE_LOGGING macro - - static bool init(); - static bool un_init(); - - static logger* get_or_create_instance(); - static logger* get_set_instance_internal(bool is_need_set = false, logger* pnew_logger_val = NULL); - static bool get_set_is_uninitialized(bool is_need_set = false, bool is_uninitialized = false); - }; - - const static initializer log_initializer; - - class log_frame - { - std::string m_name; - int m_level; - const char* m_plog_name; - - public: - log_frame(const std::string& name, int dlevel = LOG_LEVEL_2 , const char* plog_name = NULL); - ~log_frame(); - }; - - inline int get_set_time_level(bool is_need_set, int time_log_level) - { - return log_singletone::get_set_time_level(is_need_set, time_log_level); - } - inline int get_set_log_detalisation_level(bool is_need_set, int log_level_to_set) - { - return log_singletone::get_set_log_detalisation_level(is_need_set, log_level_to_set); - } - inline std::string get_prefix_entry() - { - return log_singletone::get_prefix_entry(); - } - inline bool get_set_need_thread_id(bool is_need_set, bool is_need_val) - { - return log_singletone::get_set_need_thread_id(is_need_set, is_need_val); - } - inline bool get_set_need_proc_name(bool is_need_set, bool is_need_val ) - { - return log_singletone::get_set_need_proc_name(is_need_set, is_need_val); - } - - inline std::string get_win32_err_descr(int err_no); - inline bool getwin32_err_text(std::stringstream& ref_message, int error_no); -} - -#if defined(_DEBUG) || defined(__GNUC__) - #define ENABLE_LOGGING_INTERNAL -#endif - -#if defined(ENABLE_RELEASE_LOGGING) - #define ENABLE_LOGGING_INTERNAL -#endif - - -#if defined(ENABLE_LOGGING_INTERNAL) - -#define LOG_PRINT_NO_PREFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);}} - -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} - - -#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} - - -#define LOG_PRINT2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);}} - -#define LOG_PRINT_COLOR2(log_name, x, y, color) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name);}} - - -#define LOG_PRINT2_JORNAL(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);}} - - -#define LOG_ERROR2(log_name, x) { \ - std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "ERROR " << __FILE__ << ":" << __LINE__ << " " << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name);LOCAL_ASSERT(0); epee::log_space::log_singletone::get_set_err_count(true, epee::log_space::log_singletone::get_set_err_count()+1);} - -#define LOG_FRAME2(log_name, x, y) epee::log_space::log_frame frame(x, y, log_name) - -#define LOG_WARNING2(log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() )\ - {std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "WARNING " << __FILE__ << ":" << __LINE__ << " " << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_red, true, log_name);LOCAL_ASSERT(0); epee::log_space::log_singletone::get_set_err_count(true, epee::log_space::log_singletone::get_set_err_count()+1);}} - -#else - - -#define LOG_PRINT_NO_PREFIX2(log_name, x, y) - -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) - -#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) - -#define LOG_PRINT_COLOR2(log_name, x, y, color) - -#define LOG_PRINT2_JORNAL(log_name, x, y) - -#define LOG_PRINT2(log_name, x, y) - -#define LOG_ERROR2(log_name, x) - - -#define LOG_FRAME2(log_name, x, y) - -#define LOG_WARNING2(log_name, x, level) - - -#endif - - -#ifndef LOG_DEFAULT_TARGET - #define LOG_DEFAULT_TARGET NULL -#endif - - -#define LOG_PRINT_NO_POSTFIX(mess, level) LOG_PRINT_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT_NO_PREFIX(mess, level) LOG_PRINT_NO_PREFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX(mess, level) LOG_PRINT_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT(mess, level) LOG_PRINT2(LOG_DEFAULT_TARGET, mess, level) - -#define LOG_PRINT_COLOR(mess, level, color) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, color) -#define LOG_PRINT_RED(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_red) -#define LOG_PRINT_GREEN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_green) -#define LOG_PRINT_BLUE(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_blue) -#define LOG_PRINT_YELLOW(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_yellow) -#define LOG_PRINT_CYAN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_cyan) -#define LOG_PRINT_MAGENTA(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_magenta) - -#define LOG_PRINT_RED_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_red) - -#define LOG_PRINT_L0(mess) LOG_PRINT(mess, LOG_LEVEL_0) -#define LOG_PRINT_L1(mess) LOG_PRINT(mess, LOG_LEVEL_1) -#define LOG_PRINT_L2(mess) LOG_PRINT(mess, LOG_LEVEL_2) -#define LOG_PRINT_L3(mess) LOG_PRINT(mess, LOG_LEVEL_3) -#define LOG_PRINT_L4(mess) LOG_PRINT(mess, LOG_LEVEL_4) -#define LOG_PRINT_J(mess, level) LOG_PRINT2_JORNAL(LOG_DEFAULT_TARGET, mess, level) - -#define LOG_ERROR(mess) LOG_ERROR2(LOG_DEFAULT_TARGET, mess) -#define LOG_FRAME(mess, level) LOG_FRAME2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_VALUE(mess, level) LOG_VALUE2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_ARRAY(mess, level) LOG_ARRAY2(LOG_DEFAULT_TARGET, mess, level) -//#define LOGWIN_PLATFORM_ERROR(err_no) LOGWINDWOS_PLATFORM_ERROR2(LOG_DEFAULT_TARGET, err_no) -#define LOG_SOCKET_ERROR(err_no) LOG_SOCKET_ERROR2(LOG_DEFAULT_TARGET, err_no) -//#define LOGWIN_PLATFORM_ERROR_UNCRITICAL(mess) LOGWINDWOS_PLATFORM_ERROR_UNCRITICAL2(LOG_DEFAULT_TARGET, mess) -#define LOG_WARNING(mess, level) LOG_WARNING2(LOG_DEFAULT_TARGET, mess, level) - -#define ENDL std::endl - -#define TRY_ENTRY() try { -#define CATCH_ENTRY(location, return_val) } \ - catch(const std::exception& ex) \ -{ \ - (void)(ex); \ - LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ - return return_val; \ -}\ - catch(...)\ -{\ - LOG_ERROR("Exception at [" << location << "], generic exception \"...\"");\ - return return_val; \ -} - -#define CATCH_ENTRY_L0(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L1(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L2(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L3(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L4(lacation, return_val) CATCH_ENTRY(lacation, return_val) - - -#define ASSERT_MES_AND_THROW(message) {LOG_ERROR(message); std::stringstream ss; ss << message; throw std::runtime_error(ss.str());} -#define CHECK_AND_ASSERT_THROW_MES(expr, message) {if(!(expr)) ASSERT_MES_AND_THROW(message);} - - -#ifndef CHECK_AND_ASSERT -#define CHECK_AND_ASSERT(expr, fail_ret_val) do{if(!(expr)){LOCAL_ASSERT(expr); return fail_ret_val;};}while(0) -#endif - -#define NOTHING - -#ifndef CHECK_AND_ASSERT_MES -#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_ERROR(message); return fail_ret_val;};}while(0) -#endif - -#ifndef CHECK_AND_NO_ASSERT_MES -#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_PRINT_L0(message); /*LOCAL_ASSERT(expr);*/ return fail_ret_val;};}while(0) -#endif - - -#ifndef CHECK_AND_ASSERT_MES_NO_RET -#define CHECK_AND_ASSERT_MES_NO_RET(expr, message) do{if(!(expr)) {LOG_ERROR(message); return;};}while(0) -#endif - - -#ifndef CHECK_AND_ASSERT_MES2 -#define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0) -#endif - -} -#endif //_MISC_LOG_EX_H_ diff --git a/contrib/epee/include/misc_os_dependent.cpp b/contrib/epee/include/misc_os_dependent.cpp deleted file mode 100644 index 3bff6585..00000000 --- a/contrib/epee/include/misc_os_dependent.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "misc_os_dependent.h" - -#include - -#include - -#ifdef __MACH__ -#include -#include -#endif - -namespace epee -{ -namespace misc_utils -{ - - uint64_t get_tick_count() - { -#if defined(_MSC_VER) - return ::GetTickCount64(); -#elif defined(__MACH__) - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - return (mts.tv_sec * 1000) + (mts.tv_nsec/1000000); -#else - struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - return (ts.tv_sec * 1000) + (ts.tv_nsec/1000000); -#endif - } - - int call_sys_cmd(const std::string& cmd) - { - std::cout << "# " << cmd << std::endl; - - FILE * fp ; - //char tstCommand[] ="ls *"; - char path[1000] = {0}; -#if !defined(__GNUC__) - fp = _popen(cmd.c_str(), "r"); -#else - fp = popen(cmd.c_str(), "r"); -#endif - while ( fgets( path, 1000, fp ) != NULL ) - std::cout << path; - -#if !defined(__GNUC__) - _pclose(fp); -#else - pclose(fp); -#endif - return 0; - } - - std::string get_thread_string_id() - { -#if defined(_MSC_VER) - return boost::lexical_cast(GetCurrentThreadId()); -#elif defined(__GNUC__) - return boost::lexical_cast(pthread_self()); -#endif - } -} -} diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h deleted file mode 100644 index eb4a3a8a..00000000 --- a/contrib/epee/include/misc_os_dependent.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -#ifdef WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - - #if !defined(NOMINMAX) - #define NOMINMAX 1 - #endif // !defined(NOMINMAX) - - #include -#endif - -namespace epee -{ -namespace misc_utils -{ - uint64_t get_tick_count(); - int call_sys_cmd(const std::string& cmd); - std::string get_thread_string_id(); -} -} diff --git a/contrib/epee/include/net/abstract_tcp_server.h b/contrib/epee/include/net/abstract_tcp_server.h deleted file mode 100644 index c74444c8..00000000 --- a/contrib/epee/include/net/abstract_tcp_server.h +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _ABSTRACT_TCP_SERVER_H_ -#define _ABSTRACT_TCP_SERVER_H_ - -#include -#include -#include -#include "winobj.h" -//#include "threads_helper.h" -#include "net_utils_base.h" - -#pragma comment(lib, "Ws2_32.lib") - -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class soket_sender: public i_service_endpoint - { - public: - soket_sender(SOCKET sock):m_sock(sock){} - private: - virtual bool handle_send(const void* ptr, size_t cb) - { - if(cb != send(m_sock, (char*)ptr, (int)cb, 0)) - { - int sock_err = WSAGetLastError(); - LOG_ERROR("soket_sender: Failed to send " << cb << " bytes, Error=" << sock_err); - return false; - } - return true; - - } - - SOCKET m_sock; - }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class abstract_tcp_server - { - public: - abstract_tcp_server(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(); - bool send_stop_signal(); - - typename THandler::config_type& get_config_object(){return m_config;} - - private: - bool invoke_connection(SOCKET hnew_sock, long ip_from, int post_from); - static unsigned __stdcall ConnectionHandlerProc(void* lpParameter); - - class thread_context; - typedef std::list connections_container; - typedef typename connections_container::iterator connections_iterator; - - struct thread_context - { - HANDLE m_htread; - SOCKET m_socket; - abstract_tcp_server* powner; - connection_context m_context; - typename connections_iterator m_self_it; - }; - - SOCKET m_listen_socket; - int m_port; - bool m_initialized; - volatile LONG m_stop_server; - volatile LONG m_threads_count; - typename THandler::config_type m_config; - connections_container m_connections; - critical_section m_connections_lock; - }; - - template - unsigned __stdcall abstract_tcp_server::ConnectionHandlerProc(void* lpParameter) - { - - thread_context* pthread_context = (thread_context*)lpParameter; - if(!pthread_context) - return 0; - abstract_tcp_server* pthis = pthread_context->powner; - - ::InterlockedIncrement(&pthis->m_threads_count); - - ::CoInitialize(NULL); - - - LOG_PRINT("Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2); - int res = 0; - - soket_sender sndr(pthread_context->m_socket); - THandler srv(&sndr, pthread_context->powner->m_config, pthread_context->m_context); - - - srv.after_init_connection(); - - char buff[1000] = {0}; - std::string ansver; - while ( (res = recv(pthread_context->m_socket, (char*)buff, 1000, 0)) > 0) - { - LOG_PRINT("Data in, " << res << " bytes", LOG_LEVEL_3); - if(!srv.handle_recv(buff, res)) - break; - } - shutdown(pthread_context->m_socket, SD_BOTH); - closesocket(pthread_context->m_socket); - - abstract_tcp_server* powner = pthread_context->powner; - LOG_PRINT("Handler thread with socket=" << pthread_context->m_socket << " STOPPED", LOG_LEVEL_2); - powner->m_connections_lock.lock(); - ::CloseHandle(pthread_context->m_htread); - pthread_context->powner->m_connections.erase(pthread_context->m_self_it); - powner->m_connections_lock.unlock(); - CoUninitialize(); - ::InterlockedDecrement(&pthis->m_threads_count); - return 1; - } - //---------------------------------------------------------------------------------------- - template - abstract_tcp_server::abstract_tcp_server():m_listen_socket(INVALID_SOCKET), - m_initialized(false), - m_stop_server(0), m_port(0), m_threads_count(0) - { - - } - - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::init_server(int port_no) - { - m_port = port_no; - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - int opt = 1; - setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast(&opt), sizeof(int)); - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(port_no); - - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - deinit_server(); - return false; - } - - ::InterlockedExchange(&m_stop_server, 0); - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::deinit_server() - { - - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::send_stop_signal() - { - InterlockedExchange(&m_stop_server, 1); - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::run_server() - { - int err = listen(m_listen_socket, 10000); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - LOG_PRINT("Listening port "<< m_port << "...." , LOG_LEVEL_2); - - while(!m_stop_server) - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - fd_set read_fs = {0}; - read_fs.fd_count = 1; - read_fs.fd_array[0] = m_listen_socket; - TIMEVAL tv = {0}; - tv.tv_usec = 100; - int select_res = select(0, &read_fs, NULL, NULL, &tv); - if(!select_res) - continue; - SOCKET new_sock = WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, NULL, NULL); - LOG_PRINT("Accepted connection on socket=" << new_sock, LOG_LEVEL_2); - invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - deinit_server(); - -#define ABSTR_TCP_SRV_WAIT_COUNT_MAX 5000 -#define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL 1000 - - int wait_count = 0; - - while(m_threads_count && wait_count*1000 < ABSTR_TCP_SRV_WAIT_COUNT_MAX) - { - ::Sleep(ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL); - wait_count++; - } - LOG_PRINT("abstract_tcp_server exit with wait count=" << wait_count*ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL << "(max=" << ABSTR_TCP_SRV_WAIT_COUNT_MAX <<")", LOG_LEVEL_0); - - return true; - } - //---------------------------------------------------------------------------------------- - template - bool abstract_tcp_server::invoke_connection(SOCKET hnew_sock, long ip_from, int post_from) - { - m_connections_lock.lock(); - m_connections.push_back(thread_context()); - m_connections_lock.unlock(); - m_connections.back().m_socket = hnew_sock; - m_connections.back().powner = this; - m_connections.back().m_self_it = --m_connections.end(); - m_connections.back().m_context.m_remote_ip = ip_from; - m_connections.back().m_context.m_remote_port = post_from; - m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); - - return true; - } - //---------------------------------------------------------------------------------------- - - //---------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------- -} -} -#endif //_ABSTRACT_TCP_SERVER_H_ diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h deleted file mode 100644 index b8e291c3..00000000 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _ABSTRACT_TCP_SERVER2_H_ -#define _ABSTRACT_TCP_SERVER2_H_ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "net_utils_base.h" -#include "syncobj.h" - - -#define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 100 - -namespace epee -{ -namespace net_utils -{ - - struct i_connection_filter - { - virtual bool is_remote_ip_allowed(uint32_t adress)=0; - protected: - virtual ~i_connection_filter(){} - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - /// Represents a single connection from a client. - template - class connection - : public boost::enable_shared_from_this >, - private boost::noncopyable, - public i_service_endpoint - { - public: - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter * &pfilter); - - virtual ~connection(); - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - bool start(bool is_income, bool is_multithreaded); - - void get_context(t_connection_context& context_){context_ = context;} - - void call_back_starter(); - private: - //----------------- i_service_endpoint --------------------- - virtual bool do_send(const void* ptr, size_t cb); - virtual bool close(); - virtual bool call_run_once_service_io(); - virtual bool request_callback(); - virtual boost::asio::io_service& get_io_service(); - virtual bool add_ref(); - virtual bool release(); - //------------------------------------------------------ - boost::shared_ptr > safe_shared_from_this(); - bool shutdown(); - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e, size_t cb); - - /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// Buffer for incoming data. - boost::array buffer_; - - t_connection_context context; - volatile uint32_t m_want_close_connection; - std::atomic m_was_shutdown; - critical_section m_send_que_lock; - std::list m_send_que; - volatile uint32_t& m_ref_sockets_count; - i_connection_filter* &m_pfilter; - volatile bool m_is_multithreaded; - - //this should be the last one, because it could be wait on destructor, while other activities possible on other threads - t_protocol_handler m_protocol_handler; - //typename t_protocol_handler::config_type m_dummy_config; - std::list > > m_self_refs; // add_ref/release support - critical_section m_self_refs_lock; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class boosted_tcp_server - : private boost::noncopyable - { - public: - typedef boost::shared_ptr > connection_ptr; - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - boosted_tcp_server(); - explicit boosted_tcp_server(boost::asio::io_service& external_io_service); - ~boosted_tcp_server(); - - bool init_server(uint32_t port, const std::string address = "0.0.0.0"); - bool init_server(const std::string port, const std::string& address = "0.0.0.0"); - - /// Run the server's io_service loop. - bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes()); - - /// wait for service workers stop - bool timed_wait_server_stop(uint64_t wait_mseconds); - - /// Stop the server. - void send_stop_signal(); - - bool is_stop_signal_sent(); - - void set_threads_prefix(const std::string& prefix_name); - - bool deinit_server(){return true;} - - size_t get_threads_count(){return m_threads_count;} - - void set_connection_filter(i_connection_filter* pfilter); - - bool connect(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_connection_context& cn, const std::string& bind_ip = "0.0.0.0"); - template - bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_callback cb, const std::string& bind_ip = "0.0.0.0"); - - typename t_protocol_handler::config_type& get_config_object(){return m_config;} - - int get_binded_port(){return m_port;} - - boost::asio::io_service& get_io_service(){return io_service_;} - - struct idle_callback_conext_base - { - virtual ~idle_callback_conext_base(){} - - virtual bool call_handler(){return true;} - - idle_callback_conext_base(boost::asio::io_service& io_serice): - m_timer(io_serice) - {} - boost::asio::deadline_timer m_timer; - uint64_t m_period; - }; - - template - struct idle_callback_conext: public idle_callback_conext_base - { - idle_callback_conext(boost::asio::io_service& io_serice, t_handler& h, uint64_t period): - idle_callback_conext_base(io_serice), - m_handler(h) - {this->m_period = period;} - - t_handler m_handler; - virtual bool call_handler() - { - return m_handler(); - } - }; - - template - bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms) - { - boost::shared_ptr ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); - //needed call handler here ?... - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr ptr) - { - //if handler return false - he don't want to be called anymore - if(!ptr->call_handler()) - return true; - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - template - bool async_call(t_handler t_callback) - { - io_service_.post(t_callback); - return true; - } - - protected: - typename t_protocol_handler::config_type m_config; - - private: - /// Run the server's io_service loop. - bool worker_thread(); - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - bool is_thread_worker(); - - /// The io_service used to perform asynchronous operations. - std::unique_ptr m_io_service_local_instance; - boost::asio::io_service& io_service_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - std::atomic m_stop_signal_sent; - uint32_t m_port; - volatile uint32_t m_sockets_count; - std::string m_address; - std::string m_thread_name_prefix; - size_t m_threads_count; - i_connection_filter* m_pfilter; - std::vector > m_threads; - boost::thread::id m_main_thread_id; - critical_section m_threads_lock; - volatile uint32_t m_thread_index; - }; -} -} - -#include "abstract_tcp_server2.inl" - -#endif diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl deleted file mode 100644 index 1b34425b..00000000 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ /dev/null @@ -1,817 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "net_utils_base.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "include_base_utils.h" -#include "misc_language.h" -#include "pragma_comp_defs.h" - -PRAGMA_WARNING_PUSH -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ -PRAGMA_WARNING_DISABLE_VS(4355) - - template - connection::connection(boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter* &pfilter) - : strand_(io_service), - socket_(io_service), - m_want_close_connection(0), - m_was_shutdown(0), - m_ref_sockets_count(sock_count), - m_pfilter(pfilter), - m_protocol_handler(this, config, context) - { - boost::interprocess::ipcdetail::atomic_inc32(&m_ref_sockets_count); - } -PRAGMA_WARNING_DISABLE_VS(4355) - //--------------------------------------------------------------------------------- - template - connection::~connection() - { - if(!m_was_shutdown) - { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Socket destroyed without shutdown."); - shutdown(); - } - - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Socket destroyed"); - boost::interprocess::ipcdetail::atomic_dec32(&m_ref_sockets_count); - } - //--------------------------------------------------------------------------------- - template - boost::asio::ip::tcp::socket& connection::socket() - { - return socket_; - } - //--------------------------------------------------------------------------------- - template - boost::shared_ptr > connection::safe_shared_from_this() - { - try - { - return connection::shared_from_this(); - } - catch (const boost::bad_weak_ptr&) - { - // It happens when the connection is being deleted - return boost::shared_ptr >(); - } - } - //--------------------------------------------------------------------------------- - template - bool connection::start(bool is_income, bool is_multithreaded) - { - TRY_ENTRY(); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - - m_is_multithreaded = is_multithreaded; - - boost::system::error_code ec; - auto remote_ep = socket_.remote_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value()); - - auto local_ep = socket_.local_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value()); - - context = boost::value_initialized(); - long ip_ = boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong()); - - context.set_details(boost::uuids::random_generator()(), ip_, remote_ep.port(), is_income); - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << - " to " << local_ep.address().to_string() << ':' << local_ep.port() << - ", total sockets objects " << m_ref_sockets_count); - - if(m_pfilter && !m_pfilter->is_remote_ip_allowed(context.m_remote_ip)) - { - LOG_PRINT_L2("[sock " << socket_.native_handle() << "] ip denied " << string_tools::get_ip_string_from_int32(context.m_remote_ip) << ", shutdowning connection"); - close(); - return false; - } - - m_protocol_handler.after_init_connection(); - - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, self, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - - return true; - - CATCH_ENTRY_L0("connection::start()", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::request_callback() - { - TRY_ENTRY(); - LOG_PRINT_L2("[" << print_connection_context_short(context) << "] request_callback"); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - - strand_.post(boost::bind(&connection::call_back_starter, self)); - CATCH_ENTRY_L0("connection::request_callback()", false); - return true; - } - //--------------------------------------------------------------------------------- - template - boost::asio::io_service& connection::get_io_service() - { - return socket_.get_io_service(); - } - //--------------------------------------------------------------------------------- - template - bool connection::add_ref() - { - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] add_ref"); - CRITICAL_REGION_LOCAL(m_self_refs_lock); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - if(m_was_shutdown) - return false; - m_self_refs.push_back(self); - return true; - CATCH_ENTRY_L0("connection::add_ref()", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::release() - { - TRY_ENTRY(); - boost::shared_ptr > back_connection_copy; - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] release"); - CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection::release() call"); - //erasing from container without additional copy can cause start deleting object, including m_self_refs - back_connection_copy = m_self_refs.back(); - m_self_refs.pop_back(); - CRITICAL_REGION_END(); - return true; - CATCH_ENTRY_L0("connection::release()", false); - } - //--------------------------------------------------------------------------------- - template - void connection::call_back_starter() - { - TRY_ENTRY(); - LOG_PRINT_L2("[" << print_connection_context_short(context) << "] fired_callback"); - m_protocol_handler.handle_qued_callback(); - CATCH_ENTRY_L0("connection::call_back_starter()", void()); - } - //--------------------------------------------------------------------------------- - template - void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) - { - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Async read calledback."); - - if (!e) - { - LOG_PRINT("[sock " << socket_.native_handle() << "] RECV " << bytes_transferred, LOG_LEVEL_4); - context.m_last_recv = time(NULL); - context.m_recv_cnt += bytes_transferred; - bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred); - if(!recv_res) - { - LOG_PRINT("[sock " << socket_.native_handle() << "] protocol_want_close", LOG_LEVEL_4); - - //some error in protocol, protocol handler ask to close connection - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(!m_send_que.size()) - do_shutdown = true; - CRITICAL_REGION_END(); - if(do_shutdown) - shutdown(); - }else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, connection::shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "]Async read requested."); - } - }else - { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Some not success at read: " << e.message() << ':' << e.value()); - if(e.value() != 2) - { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value()); - shutdown(); - } - } - // If an error occurs then no new asynchronous operations are started. This - // means that all shared_ptr references to the connection object will - // disappear and the object will be destroyed automatically after this - // handler returns. The connection class's destructor closes the socket. - CATCH_ENTRY_L0("connection::handle_read", void()); - } - //--------------------------------------------------------------------------------- - template - bool connection::call_run_once_service_io() - { - TRY_ENTRY(); - if(!m_is_multithreaded) - { - //single thread model, we can wait in blocked call - size_t cnt = socket_.get_io_service().run_one(); - if(!cnt)//service is going to quit - return false; - }else - { - //multi thread model, we can't(!) wait in blocked call - //so we make non blocking call and releasing CPU by calling sleep(0); - //if no handlers were called - //TODO: Maybe we need to have have critical section + event + callback to upper protocol to - //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = socket_.get_io_service().poll_one(); - if(!cnt) - misc_utils::sleep_no_w(0); - } - - return true; - CATCH_ENTRY_L0("connection::call_run_once_service_io", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::do_send(const void* ptr, size_t cb) - { - TRY_ENTRY(); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - if(m_was_shutdown) - return false; - - LOG_PRINT("[sock " << socket_.native_handle() << "] SEND " << cb, LOG_LEVEL_4); - context.m_last_send = time(NULL); - context.m_send_cnt += cb; - //some data should be wrote to stream - //request complete - - epee::critical_region_t send_guard(m_send_que_lock); - if(m_send_que.size() > ABSTRACT_SERVER_SEND_QUE_MAX_COUNT) - { - send_guard.unlock(); - LOG_WARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection", LOG_LEVEL_2); - close(); - return false; - } - - m_send_que.resize(m_send_que.size()+1); - m_send_que.back().assign((const char*)ptr, cb); - - if(m_send_que.size() > 1) - { - //active operation should be in progress, nothing to do, just wait last operation callback - }else - { - //no active operation - if(m_send_que.size()!=1) - { - LOG_ERROR("Looks like no active operations, but send que size != 1!!"); - return false; - } - - boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), m_send_que.front().size()), - //strand_.wrap( - boost::bind(&connection::handle_write, self, _1, _2) - //) - ); - - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size()); - } - - return true; - - CATCH_ENTRY_L0("connection::do_send", false); - } - //--------------------------------------------------------------------------------- - template - bool connection::shutdown() - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_was_shutdown = true; - m_protocol_handler.release_protocol(); - return true; - } - //--------------------------------------------------------------------------------- - template - bool connection::close() - { - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Que Shutdown called."); - size_t send_que_size = 0; - CRITICAL_REGION_BEGIN(m_send_que_lock); - send_que_size = m_send_que.size(); - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - if(!send_que_size) - { - shutdown(); - } - - return true; - CATCH_ENTRY_L0("connection::close", false); - } - //--------------------------------------------------------------------------------- - template - void connection::handle_write(const boost::system::error_code& e, size_t cb) - { - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Async send calledback " << cb); - - if (e) - { - LOG_PRINT_L0("[sock " << socket_.native_handle() << "] Some problems at write: " << e.message() << ':' << e.value()); - shutdown(); - return; - } - - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(m_send_que.empty()) - { - LOG_ERROR("[sock " << socket_.native_handle() << "] m_send_que.size() == 0 at handle_write!"); - return; - } - - m_send_que.pop_front(); - if(m_send_que.empty()) - { - if(boost::interprocess::ipcdetail::atomic_read32(&m_want_close_connection)) - { - do_shutdown = true; - } - }else - { - //have more data to send - boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), m_send_que.front().size()), - //strand_.wrap( - boost::bind(&connection::handle_write, connection::shared_from_this(), _1, _2)); - //); - } - CRITICAL_REGION_END(); - - if(do_shutdown) - { - shutdown(); - } - CATCH_ENTRY_L0("connection::handle_write", void()); - } - /************************************************************************/ - /* */ - /************************************************************************/ - template - boosted_tcp_server::boosted_tcp_server(): - m_io_service_local_instance(new boost::asio::io_service()), - io_service_(*m_io_service_local_instance.get()), - acceptor_(io_service_), - new_connection_(new connection(io_service_, m_config, m_sockets_count, m_pfilter)), - m_stop_signal_sent(false), m_port(0), m_sockets_count(0), m_threads_count(0), m_pfilter(NULL), m_thread_index(0) - { - m_thread_name_prefix = "NET"; - } - - template - boosted_tcp_server::boosted_tcp_server(boost::asio::io_service& extarnal_io_service): - io_service_(extarnal_io_service), - acceptor_(io_service_), - new_connection_(new connection(io_service_, m_config, m_sockets_count, m_pfilter)), - m_stop_signal_sent(false), m_port(0), m_sockets_count(0), m_threads_count(0), m_pfilter(NULL), m_thread_index(0) - { - m_thread_name_prefix = "NET"; - } - //--------------------------------------------------------------------------------- - template - boosted_tcp_server::~boosted_tcp_server() - { - this->send_stop_signal(); - timed_wait_server_stop(10000); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::init_server(uint32_t port, const std::string address) - { - TRY_ENTRY(); - m_stop_signal_sent = false; - m_port = port; - m_address = address; - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast(port)); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint(); - m_port = binded_endpoint.port(); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - return true; - CATCH_ENTRY_L0("boosted_tcp_server::init_server", false); - } - //----------------------------------------------------------------------------- -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - template - bool boosted_tcp_server::init_server(const std::string port, const std::string& address) - { - uint32_t p = 0; - - if (port.size() && !string_tools::get_xtype_from_string(p, port)) { - LOG_ERROR("Failed to convert port no = " << port); - return false; - } - return this->init_server(p, address); - } -POP_WARNINGS - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::worker_thread() - { - TRY_ENTRY(); - uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - std::string thread_name = std::string("[") + m_thread_name_prefix; - thread_name += boost::to_string(local_thr_index) + "]"; - log_space::log_singletone::set_thread_log_prefix(thread_name); - while(!m_stop_signal_sent) - { - try - { - io_service_.run(); - } - catch(const std::exception& ex) - { - LOG_ERROR("Exception at server worker thread, what=" << ex.what()); - } - catch(...) - { - LOG_ERROR("Exception at server worker thread, unknown execption"); - } - } - LOG_PRINT_L4("Worker thread finished"); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::worker_thread", false); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::set_threads_prefix(const std::string& prefix_name) - { - m_thread_name_prefix = prefix_name; - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::set_connection_filter(i_connection_filter* pfilter) - { - m_pfilter = pfilter; - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::run_server(size_t threads_count, bool wait, const boost::thread::attributes& attrs) - { - TRY_ENTRY(); - m_threads_count = threads_count; - m_main_thread_id = boost::this_thread::get_id(); - log_space::log_singletone::set_thread_log_prefix("[SRV_MAIN]"); - while(!m_stop_signal_sent) - { - - // Create a pool of threads to run all of the io_services. - CRITICAL_REGION_BEGIN(m_threads_lock); - for (std::size_t i = 0; i < threads_count; ++i) - { - boost::shared_ptr thread(new boost::thread( - attrs, boost::bind(&boosted_tcp_server::worker_thread, this))); - m_threads.push_back(thread); - } - CRITICAL_REGION_END(); - // Wait for all threads in the pool to exit. - if(wait) - { - for (std::size_t i = 0; i < m_threads.size(); ++i) - m_threads[i]->join(); - m_threads.clear(); - - }else - { - return true; - } - - if(wait && !m_stop_signal_sent) - { - //some problems with the listening socket ?.. - LOG_PRINT_L0("Net service stopped without stop request, restarting..."); - if(!this->init_server(m_port, m_address)) - { - LOG_PRINT_L0("Reiniting service failed, exit."); - return false; - }else - { - LOG_PRINT_L0("Reiniting OK."); - } - } - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::run_server", false); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::is_thread_worker() - { - TRY_ENTRY(); - CRITICAL_REGION_LOCAL(m_threads_lock); - BOOST_FOREACH(boost::shared_ptr& thp, m_threads) - { - if(thp->get_id() == boost::this_thread::get_id()) - return true; - } - if(m_threads_count == 1 && boost::this_thread::get_id() == m_main_thread_id) - return true; - return false; - CATCH_ENTRY_L0("boosted_tcp_server::is_thread_worker", false); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::timed_wait_server_stop(uint64_t wait_mseconds) - { - TRY_ENTRY(); - boost::chrono::milliseconds ms(wait_mseconds); - for (std::size_t i = 0; i < m_threads.size(); ++i) - { - if(m_threads[i]->joinable() && !m_threads[i]->try_join_for(ms)) - { - LOG_PRINT_L0("Interrupting thread " << m_threads[i]->native_handle()); - m_threads[i]->interrupt(); - } - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::timed_wait_server_stop", false); - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::send_stop_signal() - { - m_stop_signal_sent = true; - TRY_ENTRY(); - io_service_.stop(); - CATCH_ENTRY_L0("boosted_tcp_server::send_stop_signal()", void()); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::is_stop_signal_sent() - { - return m_stop_signal_sent; - } - //--------------------------------------------------------------------------------- - template - void boosted_tcp_server::handle_accept(const boost::system::error_code& e) - { - TRY_ENTRY(); - if (!e) - { - connection_ptr conn(std::move(new_connection_)); - - new_connection_.reset(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - bool r = conn->start(true, 1 < m_threads_count); - if (!r) - LOG_ERROR("[sock " << conn->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sockets_count); - }else - { - LOG_ERROR("Some problems at accept: " << e.message() << ", connections_count = " << m_sockets_count); - } - CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); - } - //--------------------------------------------------------------------------------- - template - bool boosted_tcp_server::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip) - { - TRY_ENTRY(); - - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sockets_count, m_pfilter) ); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - /* - NOTICE: be careful to make sync connection from event handler: in case if all threads suddenly do sync connect, there will be no thread to dispatch events from io service. - */ - - boost::system::error_code ec = boost::asio::error::would_block; - - //have another free thread(s), work in wait mode, without event handling - struct local_async_context - { - boost::system::error_code ec; - boost::mutex connect_mut; - boost::condition_variable cond; - }; - - boost::shared_ptr local_shared_context(new local_async_context()); - local_shared_context->ec = boost::asio::error::would_block; - boost::unique_lock lock(local_shared_context->connect_mut); - auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr shared_context) - { - shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->connect_mut.unlock(); shared_context->cond.notify_one(); - }; - - sock_.async_connect(remote_endpoint, boost::bind(connect_callback, _1, local_shared_context)); - while(local_shared_context->ec == boost::asio::error::would_block) - { - bool r = local_shared_context->cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(conn_timeout)); - if(local_shared_context->ec == boost::asio::error::would_block && !r) - { - //timeout - sock_.close(); - LOG_PRINT_L3("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")"); - return false; - } - } - ec = local_shared_context->ec; - - if (ec || !sock_.is_open()) - { - LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); - return false; - } - - LOG_PRINT_L3("Connected success to " << adr << ':' << port); - - bool r = new_connection_l->start(false, 1 < m_threads_count); - if (r) - { - new_connection_l->get_context(conn_context); - //new_connection_l.reset(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - } - else - { - LOG_ERROR("[sock " << new_connection_->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sockets_count); - } - - return r; - - CATCH_ENTRY_L0("boosted_tcp_server::connect", false); - } - //--------------------------------------------------------------------------------- - template template - bool boosted_tcp_server::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_callback cb, const std::string& bind_ip) - { - TRY_ENTRY(); - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sockets_count, m_pfilter) ); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - boost::shared_ptr sh_deadline(new boost::asio::deadline_timer(io_service_)); - //start deadline - sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout)); - sh_deadline->async_wait([=](const boost::system::error_code& error) - { - if(error != boost::asio::error::operation_aborted) - { - LOG_PRINT_L3("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")"); - new_connection_l->socket().close(); - } - }); - //start async connect - sock_.async_connect(remote_endpoint, [=](const boost::system::error_code& ec_) - { - t_connection_context conn_context = AUTO_VAL_INIT(conn_context); - boost::system::error_code ignored_ec; - boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket().local_endpoint(ignored_ec); - if(!ec_) - {//success - if(!sh_deadline->cancel()) - { - cb(conn_context, boost::asio::error::operation_aborted);//this mean that deadline timer already queued callback with cancel operation, rare situation - }else - { - LOG_PRINT_L3("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port << - " from " << lep.address().to_string() << ':' << lep.port()); - bool r = new_connection_l->start(false, 1 < m_threads_count); - if (r) - { - new_connection_l->get_context(conn_context); - cb(conn_context, ec_); - } - else - { - LOG_PRINT_L3("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection to " << adr << ':' << port); - cb(conn_context, boost::asio::error::fault); - } - } - }else - { - LOG_PRINT_L3("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port << - " from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value()); - cb(conn_context, ec_); - } - }); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::connect_async", false); - } -} -} -PRAGMA_WARNING_POP diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.h b/contrib/epee/include/net/abstract_tcp_server_cp.h deleted file mode 100644 index b6410e12..00000000 --- a/contrib/epee/include/net/abstract_tcp_server_cp.h +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _LEVIN_CP_SERVER_H_ -#define _LEVIN_CP_SERVER_H_ - -#include -#include -#include -#include -#include - -#include "misc_log_ex.h" -//#include "threads_helper.h" -#include "syncobj.h" -#define ENABLE_PROFILING -#include "profile_tools.h" -#include "net_utils_base.h" -#include "pragma_comp_defs.h" - -#define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000 - -namespace epee -{ -namespace net_utils -{ - - template - class cp_server_impl//: public abstract_handler - { - public: - cp_server_impl(/*abstract_handler* phandler = NULL*/); - virtual ~cp_server_impl(); - - bool init_server(int port_no); - bool deinit_server(); - bool run_server(int threads_count = 0); - bool send_stop_signal(); - bool is_stop_signal(); - virtual bool on_net_idle(){return true;} - size_t get_active_connections_num(); - typename TProtocol::config_type& get_config_object(){return m_config;} - private: - enum overlapped_operation_type - { - op_type_recv, - op_type_send, - op_type_stop - }; - - struct io_data_base - { - OVERLAPPED m_overlapped; - WSABUF DataBuf; - overlapped_operation_type m_op_type; - DWORD TotalBuffBytes; - volatile LONG m_is_in_use; - char Buffer[1]; - }; - -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4355) - template - struct connection: public net_utils::i_service_endpoint - { - connection(typename TProtocol::config_type& ref_config):m_sock(INVALID_SOCKET), m_tprotocol_handler(this, ref_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - { - } - - //connection():m_sock(INVALID_SOCKET), m_tprotocol_handler(this, m_dummy_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0) - //{ - //} - - connection& operator=(const connection& obj) - { - return *this; - } - - bool init_buffers() - { - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_psend_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - m_precv_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1]; - m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - return true; - } - - bool query_shutdown() - { - if(!::InterlockedCompareExchange(&m_asked_to_shutdown, 1, 0)) - { - m_psend_data->m_op_type = op_type_stop; - ::PostQueuedCompletionStatus(m_completion_port, 0, (ULONG_PTR)this, &m_psend_data->m_overlapped); - } - return true; - } - - //bool set_config(typename TProtocol::config_type& config) - //{ - // this->~connection(); - // new(this) connection(config); - // return true; - //} - ~connection() - { - if(m_psend_data) - delete m_psend_data; - - if(m_precv_data) - delete m_precv_data; - } - virtual bool handle_send(const void* ptr, size_t cb) - { - PROFILE_FUNC("[handle_send]"); - if(m_psend_data->TotalBuffBytes < cb) - resize_send_buff((DWORD)cb); - - ZeroMemory(&m_psend_data->m_overlapped, sizeof(OVERLAPPED)); - m_psend_data->DataBuf.len = (u_long)cb;//m_psend_data->TotalBuffBytes; - m_psend_data->DataBuf.buf = m_psend_data->Buffer; - memcpy(m_psend_data->DataBuf.buf, ptr, cb); - m_psend_data->m_op_type = op_type_send; - InterlockedExchange(&m_psend_data->m_is_in_use, 1); - DWORD bytes_sent = 0; - DWORD flags = 0; - int res = 0; - { - PROFILE_FUNC("[handle_send] ::WSASend"); - res = ::WSASend(m_sock, &(m_psend_data->DataBuf), 1, &bytes_sent, flags, &(m_psend_data->m_overlapped), NULL); - } - - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - return true; - } - LOG_ERROR("BIG FAIL: WSASend error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - query_shutdown(); - //closesocket(m_psend_data); - return false; - }else if(0 == res) - { - ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); - if(!bytes_sent || bytes_sent != cb) - { - int err = ::WSAGetLastError(); - LOG_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res=" << res << " last_err=" << err); - query_shutdown(); - return false; - }else - { - return true; - } - } - - return true; - } - bool resize_send_buff(DWORD new_size) - { - if(m_psend_data->TotalBuffBytes >= new_size) - return true; - - delete m_psend_data; - m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + new_size-1]; - m_psend_data->TotalBuffBytes = new_size; - LOG_PRINT("Connection buffer resized up to " << new_size, LOG_LEVEL_3); - return true; - } - - - SOCKET m_sock; - net_utils::connection_context_base context; - TProtocol m_tprotocol_handler; - typename TProtocol::config_type m_dummy_config; - io_data_base* m_precv_data; - io_data_base* m_psend_data; - HANDLE m_completion_port; - volatile LONG m_asked_to_shutdown; - volatile LONG m_connection_shutwoned; - }; -PRAGMA_WARNING_POP - - bool worker_thread_member(); - static unsigned CALLBACK worker_thread(void* param); - - bool add_new_connection(SOCKET new_sock, long ip_from, int port_from); - bool shutdown_connection(connection* pconn); - - - typedef std::map > > connections_container; - SOCKET m_listen_socket; - HANDLE m_completion_port; - connections_container m_connections; - critical_section m_connections_lock; - int m_port; - volatile LONG m_stop; - //abstract_handler* m_phandler; - bool m_initialized; - volatile LONG m_worker_thread_counter; - typename TProtocol::config_type m_config; - }; -} -} -#include "abstract_tcp_server_cp.inl" - - -#endif //_LEVIN_SERVER_H_ diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.inl b/contrib/epee/include/net/abstract_tcp_server_cp.inl deleted file mode 100644 index 5673c50b..00000000 --- a/contrib/epee/include/net/abstract_tcp_server_cp.inl +++ /dev/null @@ -1,605 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma comment(lib, "Ws2_32.lib") - -namespace epee -{ -namespace net_utils -{ -template -cp_server_impl::cp_server_impl(): - m_port(0), m_stop(false), - m_worker_thread_counter(0), m_listen_socket(INVALID_SOCKET) -{ -} -//------------------------------------------------------------- -template -cp_server_impl::~cp_server_impl() -{ - deinit_server(); -} -//------------------------------------------------------------- -template -bool cp_server_impl::init_server(int port_no) -{ - m_port = port_no; - - WSADATA wsad = {0}; - int err = ::WSAStartup(MAKEWORD(2,2), &wsad); - if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 ) - { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - m_initialized = true; - - m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); - if(INVALID_SOCKET == m_listen_socket) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - - int opt = 1; - err = setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast(&opt), sizeof(int)); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to setsockopt(SO_REUSEADDR), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - sockaddr_in adr = {0}; - adr.sin_family = AF_INET; - adr.sin_addr.s_addr = htonl(INADDR_ANY); - adr.sin_port = (u_short)htons(m_port); - - //binding - err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr )); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - m_completion_port = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - if(INVALID_HANDLE_VALUE == m_completion_port) - { - err = ::WSAGetLastError(); - LOG_PRINT("Failed to CreateIoCompletionPort, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1); - deinit_server(); - return false; - } - - - return true; -} -//------------------------------------------------------------- - -//------------------------------------------------------------- -static int CALLBACK CPConditionFunc( - IN LPWSABUF lpCallerId, - IN LPWSABUF lpCallerData, - IN OUT LPQOS lpSQOS, - IN OUT LPQOS lpGQOS, - IN LPWSABUF lpCalleeId, - OUT LPWSABUF lpCalleeData, - OUT GROUP FAR *g, - IN DWORD_PTR dwCallbackData - ) -{ - - /*cp_server_impl* pthis = (cp_server_impl*)dwCallbackData; - if(!pthis) - return CF_REJECT;*/ - /*if(pthis->get_active_connections_num()>=FD_SETSIZE-1) - { - LOG_PRINT("Maximum connections count overfull.", LOG_LEVEL_2); - return CF_REJECT; - }*/ - - return CF_ACCEPT; -} -//------------------------------------------------------------- -template -size_t cp_server_impl::get_active_connections_num() -{ - return m_connections.size(); -} -//------------------------------------------------------------- -template -unsigned CALLBACK cp_server_impl::worker_thread(void* param) -{ - if(!param) - return 0; - - cp_server_impl* pthis = (cp_server_impl*)param; - pthis->worker_thread_member(); - return 1; -} -//------------------------------------------------------------- -template -bool cp_server_impl::worker_thread_member() -{ - LOG_PRINT("Worker thread STARTED", LOG_LEVEL_1); - bool stop_handling = false; - while(!stop_handling) - { - PROFILE_FUNC("[worker_thread]Worker Loop"); - DWORD bytes_transfered = 0; - connection* pconnection = 0; - io_data_base* pio_data = 0; - - { - PROFILE_FUNC("[worker_thread]GetQueuedCompletionStatus"); - BOOL res = ::GetQueuedCompletionStatus (m_completion_port, &bytes_transfered , (PULONG_PTR)&pconnection, (LPOVERLAPPED *)&pio_data, INFINITE); - if (res == 0) - { - // check return code for error - int err = GetLastError(); - LOG_PRINT("GetQueuedCompletionStatus failed with error " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - continue; - } - } - - if(pio_data) - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - - - - if(!bytes_transfered && !pconnection && !pio_data) - { - //signal to stop - break; - } - if(!pconnection || !pio_data) - { - LOG_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection=" << pconnection << " pio_data=" << pio_data, LOG_LEVEL_0); - break; - } - - - - if(::InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)) - { - LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)"); - //DebugBreak(); - } - - if(pio_data->m_op_type == op_type_stop) - { - if(!pconnection) - { - LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!"); - continue; - } - shutdown_connection(pconnection); - continue;// - } - else if(pio_data->m_op_type == op_type_send) - { - continue; - //do nothing, just queuing request - }else if(pio_data->m_op_type == op_type_recv) - { - PROFILE_FUNC("[worker_thread]m_tprotocol_handler.handle_recv"); - if(bytes_transfered) - { - bool res = pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_transfered); - if(!res) - pconnection->query_shutdown(); - } - else - { - pconnection->query_shutdown(); - continue; - } - - } - - //preparing new request, - - { - PROFILE_FUNC("[worker_thread]RECV Request small loop"); - int res = 0; - while(true) - { - LOG_PRINT("Prepearing data for WSARecv....", LOG_LEVEL_3); - ZeroMemory(&pio_data->m_overlapped, sizeof(OVERLAPPED)); - pio_data->DataBuf.len = pio_data->TotalBuffBytes; - pio_data->DataBuf.buf = pio_data->Buffer; - pio_data->m_op_type = op_type_recv; - //calling WSARecv() and go to completion waiting - DWORD bytes_recvd = 0; - DWORD flags = 0; - - LOG_PRINT("Calling WSARecv....", LOG_LEVEL_3); - ::InterlockedExchange(&pio_data->m_is_in_use, 1); - res = WSARecv(pconnection->m_sock, &(pio_data->DataBuf), 1, &bytes_recvd , &flags, &(pio_data->m_overlapped), NULL); - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - {//go pending, ok - LOG_PRINT("WSARecv return WSA_IO_PENDING", LOG_LEVEL_3); - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - pconnection->query_shutdown(); - break; - } - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - ::InterlockedExchange(&pio_data->m_is_in_use, 0); - LOG_PRINT("WSARecv return 0, bytes_recvd=0, graceful close.", LOG_LEVEL_3); - int err = ::WSAGetLastError(); - //LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); - //pconnection->query_shutdown(); - break; - }else - { - LOG_PRINT("WSARecv return immediatily 0, bytes_recvd=" << bytes_recvd, LOG_LEVEL_3); - //pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd); - } - }*/ - } - } - } - - - LOG_PRINT("Worker thread STOPED", LOG_LEVEL_1); - ::InterlockedDecrement(&m_worker_thread_counter); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::shutdown_connection(connection* pconn) -{ - PROFILE_FUNC("[shutdown_connection]"); - - if(!pconn) - { - LOG_ERROR("Attempt to remove null pptr connection!"); - return false; - } - else - { - LOG_PRINT("Shutting down connection ("<< pconn << ")", LOG_LEVEL_3); - } - m_connections_lock.lock(); - connections_container::iterator it = m_connections.find(pconn->m_sock); - m_connections_lock.unlock(); - if(it == m_connections.end()) - { - LOG_ERROR("Failed to find closing socket=" << pconn->m_sock); - return false; - } - SOCKET sock = it->second->m_sock; - { - PROFILE_FUNC("[shutdown_connection] shutdown, close"); - ::shutdown(it->second->m_sock, SD_SEND ); - } - size_t close_sock_wait_count = 0; - { - LOG_PRINT("Entered to 'in_use wait zone'", LOG_LEVEL_3); - PROFILE_FUNC("[shutdown_connection] wait for in_use"); - while(::InterlockedCompareExchange(&it->second->m_precv_data->m_is_in_use, 1, 1)) - { - - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("First step to 'in_use wait zone'", LOG_LEVEL_3); - - - while(::InterlockedCompareExchange(&it->second->m_psend_data->m_is_in_use, 1, 1)) - { - Sleep(100); - close_sock_wait_count++; - } - LOG_PRINT("Leaved 'in_use wait zone'", LOG_LEVEL_3); - } - - ::closesocket(it->second->m_sock); - - ::InterlockedExchange(&it->second->m_connection_shutwoned, 1); - m_connections_lock.lock(); - m_connections.erase(it); - m_connections_lock.unlock(); - LOG_PRINT("Socked " << sock << " closed, wait_count=" << close_sock_wait_count, LOG_LEVEL_2); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::run_server(int threads_count = 0) -{ - int err = listen(m_listen_socket, 100); - if(SOCKET_ERROR == err ) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - - if(!threads_count) - { - SYSTEM_INFO si = {0}; - ::GetSystemInfo(&si); - threads_count = si.dwNumberOfProcessors + 2; - } - for(int i = 0; i != threads_count; i++) - { - boost::thread(boost::bind(&cp_server_impl::worker_thread_member, this)); - //HANDLE h_thread = threads_helper::create_thread(worker_thread, this); - InterlockedIncrement(&m_worker_thread_counter); - //::CloseHandle(h_thread); - } - - LOG_PRINT("Numbers of worker threads started: " << threads_count, LOG_LEVEL_1); - - m_stop = false; - while(!m_stop) - { - PROFILE_FUNC("[run_server] main_loop"); - TIMEVAL tv = {0}; - tv.tv_sec = 0; - tv.tv_usec = 100; - fd_set sock_set; - sock_set.fd_count = 1; - sock_set.fd_array[0] = m_listen_socket; - int select_res = 0; - { - PROFILE_FUNC("[run_server] select"); - select_res = select(0, &sock_set, &sock_set, NULL, &tv); - } - - if(SOCKET_ERROR == select_res) - { - err = ::WSAGetLastError(); - LOG_ERROR("Failed to select, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - return false; - } - if(!select_res) - { - on_net_idle(); - continue; - } - else - { - sockaddr_in adr_from = {0}; - int adr_len = sizeof(adr_from); - SOCKET new_sock = INVALID_SOCKET; - { - PROFILE_FUNC("[run_server] WSAAccept"); - new_sock = ::WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, CPConditionFunc, (DWORD_PTR)this); - } - - if(INVALID_SOCKET == new_sock) - { - if(m_stop) - break; - int err = ::WSAGetLastError(); - LOG_PRINT("Failed to WSAAccept, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - continue; - } - LOG_PRINT("Accepted connection (new socket=" << new_sock << ")", LOG_LEVEL_2); - { - PROFILE_FUNC("[run_server] Add new connection"); - add_new_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); - } - - } - - } - LOG_PRINT("Closing connections("<< m_connections.size() << ") and waiting...", LOG_LEVEL_2); - m_connections_lock.lock(); - for(connections_container::iterator it = m_connections.begin(); it != m_connections.end(); it++) - { - ::shutdown(it->second->m_sock, SD_BOTH); - ::closesocket(it->second->m_sock); - } - m_connections_lock.unlock(); - size_t wait_count = 0; - while(m_connections.size() && wait_count < 100) - { - ::Sleep(100); - wait_count++; - } - LOG_PRINT("Connections closed OK (wait_count=" << wait_count << ")", LOG_LEVEL_2); - - - LOG_PRINT("Stopping worker threads("<< m_worker_thread_counter << ").", LOG_LEVEL_2); - for(int i = 0; i > ptr; - ptr.reset(new connection(m_config)); - - connection& conn = *ptr.get(); - m_connections[new_sock] = ptr; - LOG_PRINT("Add new connection zone: leaving lock", LOG_LEVEL_3); - m_connections_lock.unlock(); - conn.init_buffers(); - conn.m_sock = new_sock; - conn.context.m_remote_ip = ip_from; - conn.context.m_remote_port = port_from; - conn.m_completion_port = m_completion_port; - { - PROFILE_FUNC("[add_new_connection] CreateIoCompletionPort"); - ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0); - } - - //if(NULL == ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0)) - //{ - // int err = ::GetLastError(); - // LOG_PRINT("Failed to CreateIoCompletionPort(associate socket and completion port), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); - // return false; - //} - - conn.m_tprotocol_handler.after_init_connection(); - { - PROFILE_FUNC("[add_new_connection] starting loop"); - int res = 0; - while(true)//res!=SOCKET_ERROR) - { - PROFILE_FUNC("[add_new_connection] in loop time"); - conn.m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE; - ZeroMemory(&conn.m_precv_data->m_overlapped, sizeof(OVERLAPPED)); - conn.m_precv_data->DataBuf.len = conn.m_precv_data->TotalBuffBytes; - conn.m_precv_data->DataBuf.buf = conn.m_precv_data->Buffer; - conn.m_precv_data->m_op_type = op_type_recv; - InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - DWORD bytes_recvd = 0; - DWORD flags = 0; - - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1); - { - PROFILE_FUNC("[add_new_connection] ::WSARecv"); - res = ::WSARecv(conn.m_sock, &(conn.m_precv_data->DataBuf), 1, &bytes_recvd , &flags, &(conn.m_precv_data->m_overlapped), NULL); - } - if(res == SOCKET_ERROR ) - { - int err = ::WSAGetLastError(); - if(WSA_IO_PENDING == err ) - { - break; - } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err << " " << log_space::get_win32_err_descr(err)); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - } - - - break; - /*else if(0 == res) - { - if(!bytes_recvd) - { - PROFILE_FUNC("[add_new_connection] shutdown_connection"); - ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); - conn.query_shutdown(); - //shutdown_connection(&conn); - break; - }else - { - PROFILE_FUNC("[add_new_connection] handle_recv"); - } - }*/ - } - } - - - - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::deinit_server() -{ - if(!m_initialized) - return true; - - if(INVALID_SOCKET != m_listen_socket) - { - shutdown(m_listen_socket, SD_BOTH); - int res = closesocket(m_listen_socket); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_listen_socket = INVALID_SOCKET; - } - - int res = ::WSACleanup(); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - } - m_initialized = false; - - return true; -} - -//------------------------------------------------------------- -template -bool cp_server_impl::send_stop_signal() -{ - ::InterlockedExchange(&m_stop, 1); - return true; -} -//------------------------------------------------------------- -template -bool cp_server_impl::is_stop_signal() -{ - return m_stop?true:false; -} -//------------------------------------------------------------- -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h deleted file mode 100644 index 49b0839b..00000000 --- a/contrib/epee/include/net/http_base.h +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "string_tools.h" -namespace epee -{ -namespace net_utils -{ - namespace http - { - - enum http_method{ - http_method_get, - http_method_post, - http_method_put, - http_method_head, - http_method_etc, - http_method_unknown - }; - - enum http_content_type - { - http_content_type_text_html, - http_content_type_image_gif, - http_content_type_other, - http_content_type_not_set - }; - - typedef std::list > fields_list; - - inline - std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields) - { - fields_list::const_iterator it = fields.begin(); - for(; it != fields.end(); it++) - if(!string_tools::compare_no_case(param_name, it->first)) - break; - - if(it==fields.end()) - return std::string(); - - return it->second; - } - - - inline - std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri) - { - std::string buff = "([\\?|&])"; - buff += param_name + "=([^&]*)"; - boost::regex match_param(buff.c_str(), boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(boost::regex_search(uri, result, match_param, boost::match_default) && result[0].matched) - { - return result[2]; - } - return std::string(); - } - - - - struct http_header_info - { - std::string m_connection; //"Connection:" - std::string m_referer; //"Referer:" - std::string m_content_length; //"Content-Length:" - std::string m_content_type; //"Content-Type:" - std::string m_transfer_encoding;//"Transfer-Encoding:" - std::string m_content_encoding; //"Content-Encoding:" - std::string m_host; //"Host:" - std::string m_cookie; //"Cookie:" - fields_list m_etc_fields; - - void clear() - { - m_connection.clear(); - m_referer.clear(); - m_content_length.clear(); - m_content_type.clear(); - m_transfer_encoding.clear(); - m_content_encoding.clear(); - m_host.clear(); - m_cookie.clear(); - m_etc_fields.clear(); - } - }; - - struct uri_content - { - std::string m_path; - std::string m_query; - std::string m_fragment; - std::list > m_query_params; - }; - - struct url_content - { - std::string schema; - std::string host; - std::string uri; - uint64_t port; - uri_content m_uri_content; - }; - - - struct http_request_info - { - http_request_info():m_http_method(http_method_unknown), - m_http_ver_hi(0), - m_http_ver_lo(0), - m_have_to_block(false) - {} - - http_method m_http_method; - std::string m_URI; - std::string m_http_method_str; - std::string m_full_request_str; - std::string m_replace_html; - std::string m_request_head; - int m_http_ver_hi; - int m_http_ver_lo; - bool m_have_to_block; - http_header_info m_header_info; - uri_content m_uri_content; - size_t m_full_request_buf_size; - std::string m_body; - - void clear() - { - this->~http_request_info(); - new(this) http_request_info(); - } - }; - - - struct http_response_info - { - int m_response_code; - std::string m_response_comment; - fields_list m_additional_fields; - std::string m_body; - std::string m_mime_tipe; - http_header_info m_header_info; - int m_http_ver_hi;// OUT paramter only - int m_http_ver_lo;// OUT paramter only - - void clear() - { - this->~http_response_info(); - new(this) http_response_info(); - } - }; - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h deleted file mode 100644 index 5897a017..00000000 --- a/contrib/epee/include/net/http_client.h +++ /dev/null @@ -1,875 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -//#include -#include -#include -#include - -#include "net_helper.h" -#include "http_client_base.h" - -#ifdef HTTP_ENABLE_GZIP -#include "gzip_encoding.h" -#endif - -#include "string_tools.h" -#include "reg_exp_definer.h" -#include "http_base.h" -#include "to_nonconst_iterator.h" -#include "net_parse_helpers.h" - -//#include "shlwapi.h" - -//#pragma comment(lib, "shlwapi.lib") - -extern epee::critical_section gregexp_lock; - - -namespace epee -{ -namespace net_utils -{ - -using namespace std; - - /*struct url - { - public: - void parse(const std::string& url_s) - { - const string prot_end("://"); - string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - ptr_fun(tolower)); // host is icase - string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); - } - - std::string protocol_; - std::string host_; - std::string path_; - std::string query_; - };*/ - - - - - //--------------------------------------------------------------------------- - static inline const char* get_hex_vals() - { - static char hexVals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - return hexVals; - } - - static inline const char* get_unsave_chars() - { - //static char unsave_chars[] = "\"<>%\\^[]`+$,@:;/!#?=&"; - static char unsave_chars[] = "\"<>%\\^[]`+$,@:;!#&"; - return unsave_chars; - } - - static inline bool is_unsafe(unsigned char compare_char) - { - if(compare_char <= 32 || compare_char >= 123) - return true; - - const char* punsave = get_unsave_chars(); - - for(int ichar_pos = 0; 0!=punsave[ichar_pos] ;ichar_pos++) - if(compare_char == punsave[ichar_pos]) - return true; - - return false; - } - - static inline - std::string dec_to_hex(char num, int radix) - { - int temp=0; - std::string csTmp; - int num_char; - - num_char = (int) num; - if (num_char < 0) - num_char = 256 + num_char; - - while (num_char >= radix) - { - temp = num_char % radix; - num_char = (int)floor((float)num_char / (float)radix); - csTmp = get_hex_vals()[temp]; - } - - csTmp += get_hex_vals()[num_char]; - - if(csTmp.size() < 2) - { - csTmp += '0'; - } - - std::reverse(csTmp.begin(), csTmp.end()); - //_mbsrev((unsigned char*)csTmp.data()); - - return csTmp; - } - - static inline std::string convert(char val) - { - std::string csRet; - csRet += "%"; - csRet += dec_to_hex(val, 16); - return csRet; - } - static inline std::string conver_to_url_format(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - if(is_unsafe(uri[i])) - result += convert(uri[i]); - else - result += uri[i]; - - } - - return result; - } - - static inline std::string convert_to_url_format_force_all(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - result += convert(uri[i]); - } - - return result; - } - - - - - - namespace http - { - - class http_simple_client: public i_target_handler - { - public: - - - private: - enum reciev_machine_state - { - reciev_machine_state_header, - reciev_machine_state_body_content_len, - reciev_machine_state_body_connection_close, - reciev_machine_state_body_chunked, - reciev_machine_state_done, - reciev_machine_state_error - }; - - - - enum chunked_state{ - http_chunked_state_chunk_head, - http_chunked_state_chunk_body, - http_chunked_state_done, - http_chunked_state_undefined - }; - - - blocked_mode_client m_net_client; - std::string m_host_buff; - std::string m_port; - unsigned int m_timeout; - std::string m_header_cache; - http_response_info m_response_info; - size_t m_len_in_summary; - size_t m_len_in_remain; - //std::string* m_ptarget_buffer; - boost::shared_ptr m_pcontent_encoding_handler; - reciev_machine_state m_state; - chunked_state m_chunked_state; - std::string m_chunked_cache; - critical_section m_lock; - - public: - void set_host_name(const std::string& name) - { - CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = name; - } - bool connect(const std::string& host, int port, unsigned int timeout) - { - return connect(host, std::to_string(port), timeout); - } - bool connect(const std::string& host, const std::string& port, unsigned int timeout) - { - CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = host; - m_port = port; - m_timeout = timeout; - - return m_net_client.connect(host, port, timeout, timeout); - } - //--------------------------------------------------------------------------- - bool disconnect() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.disconnect(); - } - //--------------------------------------------------------------------------- - bool is_connected() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.is_connected(); - } - //--------------------------------------------------------------------------- - virtual bool handle_target_data(std::string& piece_of_transfer) - { - CRITICAL_REGION_LOCAL(m_lock); - m_response_info.m_body += piece_of_transfer; - piece_of_transfer.clear(); - return true; - } - //--------------------------------------------------------------------------- - inline - bool invoke_get(const std::string& uri, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "GET", body, ppresponse_info, additional_params); - } - - //--------------------------------------------------------------------------- - inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!is_connected()) - { - LOG_PRINT("Reconnecting...", LOG_LEVEL_3); - if(!connect(m_host_buff, m_port, m_timeout)) - { - LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_3); - return false; - } - } - m_response_info.clear(); - std::string req_buff = method + " "; - req_buff += uri + " HTTP/1.1\r\n" + - "Host: "+ m_host_buff +"\r\n" + "Content-Length: " + boost::lexical_cast(body.size()) + "\r\n"; - - - //handle "additional_params" - for(fields_list::const_iterator it = additional_params.begin(); it!=additional_params.end(); it++) - req_buff += it->first + ": " + it->second + "\r\n"; - req_buff += "\r\n"; - //-- - - bool res = m_net_client.send(req_buff); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - if(body.size()) - res = m_net_client.send(body); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - - if(ppresponse_info) - *ppresponse_info = &m_response_info; - - m_state = reciev_machine_state_header; - return handle_reciev(); - } - //--------------------------------------------------------------------------- - inline bool invoke_post(const std::string& uri, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "POST", body, ppresponse_info, additional_params); - } - private: - //--------------------------------------------------------------------------- - inline bool handle_reciev() - { - CRITICAL_REGION_LOCAL(m_lock); - bool keep_handling = true; - bool need_more_data = true; - std::string recv_buffer; - while(keep_handling) - { - if(need_more_data) - { - if(!m_net_client.recv(recv_buffer)) - { - LOG_PRINT("Unexpected reciec fail", LOG_LEVEL_3); - m_state = reciev_machine_state_error; - } - if(!recv_buffer.size()) - { - //connection is going to be closed - if(reciev_machine_state_body_connection_close != m_state) - { - m_state = reciev_machine_state_error; - } - } - need_more_data = false; - } - switch(m_state) - { - case reciev_machine_state_header: - keep_handling = handle_header(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_content_len: - keep_handling = handle_body_content_len(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_connection_close: - keep_handling = handle_body_connection_close(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_chunked: - keep_handling = handle_body_body_chunked(recv_buffer, need_more_data); - break; - case reciev_machine_state_done: - keep_handling = false; - break; - case reciev_machine_state_error: - keep_handling = false; - break; - } - - } - m_header_cache.clear(); - if(m_state != reciev_machine_state_error) - { - if(m_response_info.m_header_info.m_connection.size() && !string_tools::compare_no_case("close", m_response_info.m_header_info.m_connection)) - disconnect(); - - return true; - } - else - { - LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state); - return false; - } - } - //--------------------------------------------------------------------------- - inline - bool handle_header(std::string& recv_buff, bool& need_more_data) - { - - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_ERROR("Connection closed at handle_header"); - m_state = reciev_machine_state_error; - return false; - } - - m_header_cache += recv_buff; - recv_buff.clear(); - std::string::size_type pos = m_header_cache.find("\r\n\r\n"); - if(pos != std::string::npos) - { - recv_buff.assign(m_header_cache.begin()+pos+4, m_header_cache.end()); - m_header_cache.erase(m_header_cache.begin()+pos+4, m_header_cache.end()); - - analize_cached_header_and_invoke_state(); - m_header_cache.clear(); - if(!recv_buff.size() && (m_state != reciev_machine_state_error && m_state != reciev_machine_state_done)) - need_more_data = true; - - return true; - }else - need_more_data = true; - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_content_len(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_PRINT("Warning: Content-Len mode, but connection unexpectedly closed", LOG_LEVEL_3); - m_state = reciev_machine_state_done; - return true; - } - CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); - m_len_in_remain -= recv_buff.size(); - m_pcontent_encoding_handler->update_in(recv_buff); - - if(m_len_in_remain == 0) - m_state = reciev_machine_state_done; - else - need_more_data = true; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_connection_close(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - m_state = reciev_machine_state_done; - return true; - } - need_more_data = true; - m_pcontent_encoding_handler->update_in(recv_buff); - - - return true; - } - //--------------------------------------------------------------------------- - inline bool is_hex_symbol(char ch) - { - - if( (ch >= '0' && ch <='9')||(ch >= 'A' && ch <='F')||(ch >= 'a' && ch <='f')) - return true; - else - return false; - } - //--------------------------------------------------------------------------- - inline - bool get_len_from_chunk_head(const std::string &chunk_head, size_t& result_size) - { - std::stringstream str_stream; - str_stream << std::hex; - if(!(str_stream << chunk_head && str_stream >> result_size)) - return false; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool get_chunk_head(std::string& buff, size_t& chunk_size, bool& is_matched) - { - is_matched = false; - size_t offset = 0; - for(std::string::iterator it = buff.begin(); it!= buff.end(); it++, offset++) - { - if(!is_hex_symbol(*it)) - { - if(*it == '\r' || *it == ' ' ) - { - offset--; - continue; - } - else if(*it == '\n') - { - std::string chunk_head = buff.substr(0, offset); - if(!get_len_from_chunk_head(chunk_head, chunk_size)) - return false; - - if(0 == chunk_size) - { - //Here is a small confusion - //In breif - if the chunk is the last one we need to get terminating sequence - //along with the cipher, generally in the "ddd\r\n\r\n" form - - for(it++;it != buff.end(); it++) - { - if('\r' == *it) - continue; - else if('\n' == *it) - break; - else - { - LOG_ERROR("http_stream_filter: Wrong last chunk terminator"); - return false; - } - } - - if(it == buff.end()) - return true; - } - - buff.erase(buff.begin(), ++it); - - is_matched = true; - return true; - } - else - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_body_chunked(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_PRINT("Warning: CHUNKED mode, but connection unexpectedly closed", LOG_LEVEL_3); - m_state = reciev_machine_state_done; - return true; - } - m_chunked_cache += recv_buff; - recv_buff.clear(); - bool is_matched = false; - - while(true) - { - if(!m_chunked_cache.size()) - { - need_more_data = true; - break; - } - - switch(m_chunked_state) - { - case http_chunked_state_chunk_head: - if(m_chunked_cache[0] == '\n' || m_chunked_cache[0] == '\r') - { - //optimize a bit - if(m_chunked_cache[0] == '\r' && m_chunked_cache.size()>1 && m_chunked_cache[1] == '\n') - m_chunked_cache.erase(0, 2); - else - m_chunked_cache.erase(0, 1); - break; - } - if(!get_chunk_head(m_chunked_cache, m_len_in_remain, is_matched)) - { - LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head:" << m_chunked_cache); - m_state = reciev_machine_state_error; - return false; - } - - if(!is_matched) - { - need_more_data = true; - return true; - }else - { - m_chunked_state = http_chunked_state_chunk_body; - if(m_len_in_remain == 0) - {//last chunk, let stop the stream and fix the chunk queue. - m_state = reciev_machine_state_done; - return true; - } - m_chunked_state = http_chunked_state_chunk_body; - break; - } - break; - case http_chunked_state_chunk_body: - { - std::string chunk_body; - if(m_len_in_remain >= m_chunked_cache.size()) - { - m_len_in_remain -= m_chunked_cache.size(); - chunk_body.swap(m_chunked_cache); - }else - { - chunk_body.assign(m_chunked_cache, 0, m_len_in_remain); - m_chunked_cache.erase(0, m_len_in_remain); - m_len_in_remain = 0; - } - - m_pcontent_encoding_handler->update_in(chunk_body); - - if(!m_len_in_remain) - m_chunked_state = http_chunked_state_chunk_head; - } - break; - case http_chunked_state_done: - m_state = reciev_machine_state_done; - return true; - case http_chunked_state_undefined: - default: - LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state" << m_chunked_state); - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline - bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process) - { - LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_4); - - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)" - // 12 3 4 5 6 7 8 9 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //10 1112 13 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = m_cache_to_process.begin(); - std::string::const_iterator it_end_bound = m_cache_to_process.end(); - - - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 12; - //const size_t field_etc_name = 10; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Connection" - body_info.m_connection = result[field_val]; - else if(result[i++].matched)//"Referrer" - body_info.m_referer = result[field_val]; - else if(result[i++].matched)//"Content-Length" - body_info.m_content_length = result[field_val]; - else if(result[i++].matched)//"Content-Type" - body_info.m_content_type = result[field_val]; - else if(result[i++].matched)//"Transfer-Encoding" - body_info.m_transfer_encoding = result[field_val]; - else if(result[i++].matched)//"Content-Encoding" - body_info.m_content_encoding = result[field_val]; - else if(result[i++].matched)//"Host" - { body_info.m_host = result[field_val]; - string_tools::trim(body_info.m_host); - } - else if(result[i++].matched)//"Cookie" - body_info.m_cookie = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - {;} - else - {CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<(result[1]); - m_response_info.m_http_ver_lo = boost::lexical_cast(result[2]); - m_response_info.m_response_code = boost::lexical_cast(result[3]); - - m_header_cache.erase(to_nonsonst_iterator(m_header_cache, result[0].first), to_nonsonst_iterator(m_header_cache, result[0].second)); - return true; - }else - { - LOG_ERROR("http_stream_filter::handle_invoke_reply_line(): Failed to match first response line:" << m_header_cache); - return false; - } - - } - inline - bool set_reply_content_encoder() - { - STATIC_REGEXP_EXPR_1(rexp_match_gzip, "^.*?((gzip)|(deflate))", boost::regex::icase | boost::regex::normal); - boost::smatch result; // 12 3 - if(boost::regex_search( m_response_info.m_header_info.m_content_encoding, result, rexp_match_gzip, boost::match_default) && result[0].matched) - { -#ifdef HTTP_ENABLE_GZIP - m_pcontent_encoding_handler.reset(new content_encoding_gzip(this, result[3].matched)); -#else - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - LOG_ERROR("GZIP encoding not supported in this build, please add zlib to your project and define HTTP_ENABLE_GZIP"); - return false; -#endif - } - else - { - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - } - - return true; - } - inline - bool analize_cached_header_and_invoke_state() - { - m_response_info.clear(); - analize_first_response_line(); - std::string fake_str; //gcc error workaround - - bool res = parse_header(m_response_info.m_header_info, m_header_cache); - CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " << m_header_cache); - - set_reply_content_encoder(); - - m_len_in_summary = 0; - bool content_len_valid = false; - if(m_response_info.m_header_info.m_content_length.size()) - content_len_valid = string_tools::get_xtype_from_string(m_len_in_summary, m_response_info.m_header_info.m_content_length); - - - - if(!m_len_in_summary && ((m_response_info.m_response_code>=100&&m_response_info.m_response_code<200) - || 204 == m_response_info.m_response_code - || 304 == m_response_info.m_response_code) ) - {//There will be no response body, server will display the local page with error - m_state = reciev_machine_state_done; - return true; - }else if(m_response_info.m_header_info.m_transfer_encoding.size()) - { - string_tools::trim(m_response_info.m_header_info.m_transfer_encoding); - if(string_tools::compare_no_case(m_response_info.m_header_info.m_transfer_encoding, "chunked")) - { - LOG_ERROR("Wrong Transfer-Encoding:" << m_response_info.m_header_info.m_transfer_encoding); - m_state = reciev_machine_state_error; - return false; - } - m_state = reciev_machine_state_body_chunked; - m_chunked_state = http_chunked_state_chunk_head; - return true; - } - else if(!m_response_info.m_header_info.m_content_length.empty()) - { - //In the response header the length was specified - if(!content_len_valid) - { - LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<(u_c.port), timeout); - CHECK_AND_ASSERT_MES(res, false, "failed to connect " << u_c.host << ":" << u_c.port); - } - - return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params); - } - - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_client_abstract_invoke.h b/contrib/epee/include/net/http_client_abstract_invoke.h deleted file mode 100644 index 425a355e..00000000 --- a/contrib/epee/include/net/http_client_abstract_invoke.h +++ /dev/null @@ -1,98 +0,0 @@ - -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "storages/serializeble_struct_helper.h" - -namespace epee -{ - namespace net_utils - { - namespace http - { - template - bool invoke_http_json_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - StorageNamed::InMemStorageSpace::json::store_t_to_json(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return StorageNamed::InMemStorageSpace::json::load_t_from_json(result_struct, pri->m_body); - } - - - - template - bool invoke_http_bin_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - epee::StorageNamed::save_struct_as_storage_to_buff(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return epee::StorageNamed::load_struct_from_storage_buff(result_struct, pri->m_body); - } - - - } - } -} diff --git a/contrib/epee/include/net/http_client_base.h b/contrib/epee/include/net/http_client_base.h deleted file mode 100644 index 571e27f7..00000000 --- a/contrib/epee/include/net/http_client_base.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace epee -{ - namespace net_utils - { - struct i_sub_handler - { - virtual ~i_sub_handler(){} - - virtual bool update_in( std::string& piece_of_transfer)=0; - virtual void stop(std::string& OUT collect_remains)=0; - virtual bool update_and_stop(std::string& OUT collect_remains, bool& is_changed) - { - is_changed = true; - bool res = this->update_in(collect_remains); - if(res) - this->stop(collect_remains); - return res; - } - }; - - - struct i_target_handler - { - virtual ~i_target_handler(){} - virtual bool handle_target_data( std::string& piece_of_transfer)=0; - }; - - - class do_nothing_sub_handler: public i_sub_handler - { - public: - do_nothing_sub_handler(i_target_handler* powner_filter):m_powner_filter(powner_filter) - {} - virtual bool update_in( std::string& piece_of_transfer) - { - return m_powner_filter->handle_target_data(piece_of_transfer); - } - virtual void stop(std::string& OUT collect_remains) - { - - } - i_target_handler* m_powner_filter; - }; - } -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_client_via_api_helper.h b/contrib/epee/include/net/http_client_via_api_helper.h deleted file mode 100644 index 45a70993..00000000 --- a/contrib/epee/include/net/http_client_via_api_helper.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#pragma comment(lib, "Wininet.lib") - -namespace epee -{ -namespace net_utils -{ - inline - bool http_ssl_invoke(const std::string& url, const std::string usr, const std::string psw, std::string& http_response_body, bool use_post = false) - { - bool final_res = false; - - ATL::CUrl url_obj; - BOOL crack_rss = url_obj.CrackUrl(string_encoding::convert_to_t >(url).c_str()); - - HINTERNET hinet = ::InternetOpenA(SHARED_JOBSCOMMON_HTTP_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(!hinet) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - DWORD dwFlags = 0; - DWORD dwBuffLen = sizeof(dwFlags); - - if(usr.size()) - { - dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID| - INTERNET_FLAG_PRAGMA_NOCACHE | SECURITY_FLAG_IGNORE_UNKNOWN_CA|INTERNET_FLAG_SECURE; - }else - { - dwFlags |= INTERNET_FLAG_PRAGMA_NOCACHE; - } - - - int port = url_obj.GetPortNumber(); - BOOL res = FALSE; - - HINTERNET hsession = ::InternetConnectA(hinet, string_encoding::convert_to_ansii(url_obj.GetHostName()).c_str(), port/*INTERNET_DEFAULT_HTTPS_PORT*/, usr.c_str(), psw.c_str(), INTERNET_SERVICE_HTTP, dwFlags, NULL); - if(hsession) - { - const std::string uri = string_encoding::convert_to_ansii(url_obj.GetUrlPath()) + string_encoding::convert_to_ansii(url_obj.GetExtraInfo()); - - HINTERNET hrequest = ::HttpOpenRequestA(hsession, use_post?"POST":NULL, uri.c_str(), NULL, NULL,NULL, dwFlags, NULL); - if(hrequest) - { - while(true) - { - res = ::HttpSendRequestA(hrequest, NULL, 0, NULL, 0); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - - DWORD code = 0; - DWORD buf_len = sizeof(code); - DWORD index = 0; - res = ::HttpQueryInfo(hrequest, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &code, &buf_len, &index); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(code < 200 || code > 299) - { - LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code , LOG_LEVEL_0); - break; - } - - - char buff[100000] = {0}; - DWORD readed = 0; - while(true) - { - res = ::InternetReadFile(hrequest, buff, sizeof(buff), &readed); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(readed) - { - http_response_body.append(buff, readed); - } - else - break; - } - - if(!res) - break; - - - //we success - final_res = true; - - res = ::InternetCloseHandle(hrequest); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - break; - } - } - else - { - //ERROR_INTERNET_INVALID_CA - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - res = ::InternetCloseHandle(hsession); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - }else - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - - - res = ::InternetCloseHandle(hinet); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - return final_res; - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h deleted file mode 100644 index 72b4b575..00000000 --- a/contrib/epee/include/net/http_protocol_handler.h +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_H_ -#define _HTTP_SERVER_H_ - -#include -#include "include_base_utils.h" -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct http_server_config - { - std::string m_folder; - critical_section m_lock; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class simple_http_connection_handler - { - public: - typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context; - typedef http_server_config config_type; - - simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config); - virtual ~simple_http_connection_handler(){} - - bool release_protocol() - { - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb); - virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response); - - private: - enum machine_state{ - http_state_retriving_comand_line, - http_state_retriving_header, - http_state_retriving_body, - http_state_connection_close, - http_state_error - }; - - enum body_transfer_type{ - http_body_transfer_chunked, - http_body_transfer_measure,//mean "Content-Length" valid - http_body_transfer_chunked_instead_measure, - http_body_transfer_connection_close, - http_body_transfer_multipart, - http_body_transfer_undefined - }; - - bool handle_buff_in(std::string& buf); - - bool analize_cached_request_header_and_invoke_state(size_t pos); - - bool handle_invoke_query_line(); - bool parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos); - std::string::size_type match_end_of_header(const std::string& buf); - bool get_len_from_content_lenght(const std::string& str, size_t& len); - bool handle_retriving_query_body(); - bool handle_query_measure(); - bool set_ready_state(); - bool slash_to_back_slash(std::string& str); - std::string get_file_mime_tipe(const std::string& path); - std::string get_response_header(const http_response_info& response); - - //major function - inline bool handle_request_and_send_response(const http::http_request_info& query_info); - - - std::string get_not_found_response_body(const std::string& URI); - - std::string m_root_path; - std::string m_cache; - machine_state m_state; - body_transfer_type m_body_transfer_type; - bool m_is_stop_handling; - http::http_request_info m_query_info; - size_t m_len_summary, m_len_remain; - config_type& m_config; - bool m_want_close; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - template - struct i_http_server_handler - { - virtual ~i_http_server_handler(){} - virtual bool handle_http_request(const http_request_info& query_info, - http_response_info& response, - t_connection_context& m_conn_context) = 0; - virtual bool init_server_thread(){return true;} - virtual bool deinit_server_thread(){return true;} - }; - - template - struct custum_handler_config: public http_server_config - { - i_http_server_handler* m_phandler; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class http_custom_handler: public simple_http_connection_handler - { - public: - typedef custum_handler_config config_type; - - http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context) - : simple_http_connection_handler(psnd_hndlr, config), - m_config(config), - m_conn_context(conn_context) - {} - inline bool handle_request(const http_request_info& query_info, http_response_info& response) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - //fill with default values - response.m_mime_tipe = "text/plain"; - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_body.clear(); - return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context); - } - - virtual bool thread_init() - { - return m_config.m_phandler->init_server_thread();; - } - - virtual bool thread_deinit() - { - return m_config.m_phandler->deinit_server_thread(); - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - - private: - //simple_http_connection_handler::config_type m_stub_config; - config_type& m_config; - t_connection_context& m_conn_context; - }; - } -} -} - -#include "http_protocol_handler.inl" - -#endif //_HTTP_SERVER_H_ diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl deleted file mode 100644 index fc091a21..00000000 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ /dev/null @@ -1,682 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#include -#include -#include "http_protocol_handler.h" -#include "include_base_utils.h" -#include "reg_exp_definer.h" -#include "string_tools.h" -#include "time_helper.h" -#include "file_io_utils.h" -#include "net_parse_helpers.h" - -#define HTTP_MAX_URI_LEN 9000 -#define HTTP_MAX_HEADER_LEN 100000 - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - struct multipart_entry - { - std::list > m_etc_header_fields; - std::string m_content_disposition; - std::string m_content_type; - std::string m_body; - }; - - inline - bool match_boundary(const std::string& content_type, std::string& boundary) - { - STATIC_REGEXP_EXPR_1(rexp_match_boundary, "boundary=(.*?)(($)|([;\\s,]))", boost::regex::icase | boost::regex::normal); - // 1 - boost::smatch result; - if(boost::regex_search(content_type, result, rexp_match_boundary, boost::match_default) && result[0].matched) - { - boundary = result[1]; - return true; - } - - return false; - } - - inline - bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Content-Disposition)|(Content-Type)" - // 12 3 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //4 56 7 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = it_begin; - std::string::const_iterator it_end_bound = it_end; - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 6; - const size_t field_etc_name = 4; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Content-Disposition" - entry.m_content_disposition = result[field_val]; - else if(result[i++].matched)//"Content-Type" - entry.m_content_type = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - entry.m_etc_header_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:"<& out_values) - { - //bool res = file_io_utils::load_file_to_string("C:\\public\\multupart_data", body); - - std::string boundary; - if(!match_boundary(content_type, boundary)) - { - LOG_PRINT("Failed to match boundary in content type: " << content_type, LOG_LEVEL_0); - return false; - } - - boundary+="\r\n"; - bool is_stop = false; - bool first_step = true; - - std::string::const_iterator it_begin = body.begin(); - std::string::const_iterator it_end; - while(!is_stop) - { - std::string::size_type pos = body.find(boundary, std::distance(body.begin(), it_begin)); - - if(std::string::npos == pos) - { - is_stop = true; - boundary.erase(boundary.size()-2, 2); - boundary+= "--"; - pos = body.find(boundary, std::distance(body.begin(), it_begin)); - if(std::string::npos == pos) - { - LOG_PRINT("Error: Filed to match closing multipart tag", LOG_LEVEL_0); - it_end = body.end(); - }else - { - it_end = body.begin() + pos; - } - }else - it_end = body.begin() + pos; - - - if(first_step && !is_stop) - { - first_step = false; - it_begin = it_end + boundary.size(); - std::string temp = "\r\n--"; - boundary = temp + boundary; - continue; - } - - out_values.push_back(multipart_entry()); - if(!handle_part_of_multipart(it_begin, it_end, out_values.back())) - { - LOG_PRINT("Failed to handle_part_of_multipart", LOG_LEVEL_0); - return false; - } - - it_begin = it_end + boundary.size(); - } - - return true; - } - - - - - //-------------------------------------------------------------------------------------------- - template - simple_http_connection_handler::simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config): - m_state(http_state_retriving_comand_line), - m_body_transfer_type(http_body_transfer_undefined), - m_is_stop_handling(false), - m_len_summary(0), - m_len_remain(0), - m_config(config), - m_want_close(false), - m_psnd_hndlr(psnd_hndlr) - { - - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::set_ready_state() - { - m_is_stop_handling = false; - m_state = http_state_retriving_comand_line; - m_body_transfer_type = http_body_transfer_undefined; - m_query_info.clear(); - m_len_summary = 0; - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf); - //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast(ptr), std::string((const char*)ptr, cb)); - - bool res = handle_buff_in(buf); - if(m_want_close/*m_state == http_state_connection_close || m_state == http_state_error*/) - return false; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_buff_in(std::string& buf) - { - - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while(!m_is_stop_handling) - { - switch(m_state) - { - case http_state_retriving_comand_line: - //The HTTP protocol does not place any a priori limit on the length of a URI. (c)RFC2616 - //but we forebly restirct it len to HTTP_MAX_URI_LEN to make it more safely - if(!m_cache.size()) - break; - - //check_and_handle_fake_response(); - if((m_cache[0] == '\r' || m_cache[0] == '\n')) - { - //some times it could be that before query line cold be few line breaks - //so we have to be calm without panic with assers - m_cache.erase(0, 1); - break; - } - - if(std::string::npos != m_cache.find('\n', 0)) - handle_invoke_query_line(); - else - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_URI_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line"); - m_state = http_state_error; - return false; - } - } - break; - case http_state_retriving_header: - { - std::string::size_type pos = match_end_of_header(m_cache); - if(std::string::npos == pos) - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_HEADER_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area"); - m_state = http_state_error; - return false; - } - break; - } - analize_cached_request_header_and_invoke_state(pos); - break; - } - case http_state_retriving_body: - return handle_retriving_query_body(); - case http_state_connection_close: - return false; - default: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state); - return false; - case http_state_error: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!"); - return false; - } - - if(!m_cache.size()) - m_is_stop_handling = true; - } - - return true; - } - //-------------------------------------------------------------------------------------------- - inline bool analize_http_method(const boost::smatch& result, http::http_method& method, int& http_ver_major, int& http_ver_minor) - { - CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); - http_ver_major = boost::lexical_cast(result[11]); - http_ver_minor = boost::lexical_cast(result[12]); - if(result[4].matched) - method = http::http_method_get; - else if(result[5].matched) - method = http::http_method_head; - else if(result[6].matched) - method = http::http_method_post; - else if(result[7].matched) - method = http::http_method_put; - else - method = http::http_method_etc; - - return true; - } - - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_invoke_query_line() - { - LOG_FRAME("simple_http_connection_handler::handle_recognize_protocol_out(*)", LOG_LEVEL_3); - - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+).(\\d+))\r?\n", boost::regex::icase | boost::regex::normal); - // 123 4 5 6 7 8 9 10 11 12 - //size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi); - m_query_info.m_URI = result[10]; - parse_uri(m_query_info.m_URI, m_query_info.m_uri_content); - m_query_info.m_http_method_str = result[2]; - m_query_info.m_full_request_str = result[0]; - - m_cache.erase(m_cache.begin(), to_nonsonst_iterator(m_cache, result[0].second)); - - m_state = http_state_retriving_header; - - return true; - }else - { - m_state = http_state_error; - LOG_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: " << m_cache); - return false; - } - - return false; - } - //-------------------------------------------------------------------------------------------- - template - std::string::size_type simple_http_connection_handler::match_end_of_header(const std::string& buf) - { - - //Here we returning head size, including terminating sequence (\r\n\r\n or \n\n) - std::string::size_type res = buf.find("\r\n\r\n"); - if(std::string::npos != res) - return res+4; - res = buf.find("\n\n"); - if(std::string::npos != res) - return res+2; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::analize_cached_request_header_and_invoke_state(size_t pos) - { - //LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos)); - - LOG_FRAME("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(*)", LOG_LEVEL_3); - - m_query_info.m_full_request_buf_size = pos; - m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos); - - if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache); - m_state = http_state_error; - } - - m_cache.erase(0, pos); - - std::string req_command_str = m_query_info.m_full_request_str; - //if we have POST or PUT command, it is very possible tha we will get body - //but now, we suppose than we have body only in case of we have "ContentLength" - if(m_query_info.m_header_info.m_content_length.size()) - { - m_state = http_state_retriving_body; - m_body_transfer_type = http_body_transfer_measure; - if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="< - bool simple_http_connection_handler::handle_retriving_query_body() - { - switch(m_body_transfer_type) - { - case http_body_transfer_measure: - return handle_query_measure(); - case http_body_transfer_chunked: - case http_body_transfer_connection_close: - case http_body_transfer_multipart: - case http_body_transfer_undefined: - default: - LOG_ERROR("simple_http_connection_handler::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type); - m_state = http_state_error; - return false; - } - - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_query_measure() - { - - if(m_len_remain >= m_cache.size()) - { - m_len_remain -= m_cache.size(); - m_query_info.m_body += m_cache; - m_cache.clear(); - }else - { - m_query_info.m_body.append(m_cache.begin(), m_cache.begin() + m_len_remain); - m_cache.erase(0, m_len_remain); - m_len_remain = 0; - } - - if(!m_len_remain) - { - if(handle_request_and_send_response(m_query_info)) - set_ready_state(); - else - m_state = http_state_error; - } - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos) - { - LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_3); - - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)" - // 12 3 4 5 6 7 8 9 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //10 1112 13 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = m_cache_to_process.begin(); - std::string::const_iterator it_end_bound = m_cache_to_process.begin()+pos; - - body_info.clear(); - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 12; - const size_t field_etc_name = 10; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Connection" - body_info.m_connection = result[field_val]; - else if(result[i++].matched)//"Referer" - body_info.m_referer = result[field_val]; - else if(result[i++].matched)//"Content-Length" - body_info.m_content_length = result[field_val]; - else if(result[i++].matched)//"Content-Type" - body_info.m_content_type = result[field_val]; - else if(result[i++].matched)//"Transfer-Encoding" - body_info.m_transfer_encoding = result[field_val]; - else if(result[i++].matched)//"Content-Encoding" - body_info.m_content_encoding = result[field_val]; - else if(result[i++].matched)//"Host" - body_info.m_host = result[field_val]; - else if(result[i++].matched)//"Cookie" - body_info.m_cookie = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - body_info.m_etc_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_cached_header() not matched last entry in:"< - bool simple_http_connection_handler::get_len_from_content_lenght(const std::string& str, size_t& OUT len) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, "\\d+", boost::regex::normal); - std::string res; - boost::smatch result; - if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched)) - return false; - - len = boost::lexical_cast(result[0]); - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request_and_send_response(const http::http_request_info& query_info) - { - http_response_info response; - bool res = handle_request(query_info, response); - //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); - - std::string response_data = get_response_header(response); - - //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body); - LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - if(response.m_body.size()) - m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size()); - return res; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request(const http::http_request_info& query_info, http_response_info& response) - { - - std::string uri_to_path = query_info.m_uri_content.m_path; - if("/" == uri_to_path) - uri_to_path = "/index.html"; - - //slash_to_back_slash(uri_to_path); - m_config.m_lock.lock(); - std::string destination_file_path = m_config.m_folder + uri_to_path; - m_config.m_lock.unlock(); - if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body)) - { - LOG_PRINT("URI \""<< query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size()-2) << "\" [" << destination_file_path << "] Not Found (404 )" , LOG_LEVEL_1); - response.m_body = get_not_found_response_body(query_info.m_URI); - response.m_response_code = 404; - response.m_response_comment = "Not found"; - response.m_mime_tipe = "text/html"; - return true; - } - - LOG_PRINT(" -->> " << query_info.m_full_request_str << "\r\n<<--OK" , LOG_LEVEL_3); - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_mime_tipe = get_file_mime_tipe(uri_to_path); - - - return true; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_response_header(const http_response_info& response) - { - std::string buf = "HTTP/1.1 "; - buf += boost::lexical_cast(response.m_response_code) + " " + response.m_response_comment + "\r\n" + - "Server: Epee-based\r\n" - "Content-Length: "; - buf += boost::lexical_cast(response.m_body.size()) + "\r\n"; - buf += "Content-Type: "; - buf += response.m_mime_tipe + "\r\n"; - - buf += "Last-Modified: "; - time_t tm; - time(&tm); - buf += misc_utils::get_internet_time_str(tm) + "\r\n"; - buf += "Accept-Ranges: bytes\r\n"; - //Wed, 01 Dec 2010 03:27:41 GMT" - - string_tools::trim(m_query_info.m_header_info.m_connection); - if(m_query_info.m_header_info.m_connection.size()) - { - if(!string_tools::compare_no_case("close", m_query_info.m_header_info.m_connection)) - { - //closing connection after sending - buf += "Connection: close\r\n"; - m_state = http_state_connection_close; - m_want_close = true; - } - } - //add additional fields, if it is - for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++) - buf += it->first + ":" + it->second + "\r\n"; - - buf+="\r\n"; - - return buf; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_file_mime_tipe(const std::string& path) - { - std::string result; - std::string ext = string_tools::get_extension(path); - if(!string_tools::compare_no_case(ext, "gif")) - result = "image/gif"; - else if(!string_tools::compare_no_case(ext, "jpg")) - result = "image/jpeg"; - else if(!string_tools::compare_no_case(ext, "html")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "htm")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "js")) - result = "application/x-javascript"; - else if(!string_tools::compare_no_case(ext, "css")) - result = "text/css"; - else if(!string_tools::compare_no_case(ext, "xml")) - result = "application/xml"; - else if(!string_tools::compare_no_case(ext, "svg")) - result = "image/svg+xml"; - - - return result; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_not_found_response_body(const std::string& URI) - { - std::string body = - "\r\n" - "\r\n" - "404 Not Found\r\n" - "\r\n" - "

Not Found

\r\n" - "

The requested URL \r\n"; - body += URI; - body += "was not found on this server.

\r\n" - "\r\n"; - - return body; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::slash_to_back_slash(std::string& str) - { - for(std::string::iterator it = str.begin(); it!=str.end(); it++) - if('/' == *it) - *it = '\\'; - return true; - } - } -} -} - -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/contrib/epee/include/net/http_server_cp.h b/contrib/epee/include/net/http_server_cp.h deleted file mode 100644 index bbb167f9..00000000 --- a/contrib/epee/include/net/http_server_cp.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "http_server.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_http_server_file_system; - typedef cp_server_impl cp_http_server_custum_handling; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/http_server_cp2.h b/contrib/epee/include/net/http_server_cp2.h deleted file mode 100644 index 1a503a4d..00000000 --- a/contrib/epee/include/net/http_server_cp2.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP2_H_ -#define _HTTP_SERVER_CP2_H_ - -#include "abstract_tcp_server2.h" -#include "http_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_http_server_file_system; - typedef boosted_tcp_server > boosted_http_server_custum_handling; -} -} - - -#endif - - diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h deleted file mode 100644 index 12ad9d97..00000000 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "http_base.h" -#include "jsonrpc_structs.h" -#include "misc_os_dependent.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - - -#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response, \ - context_type& m_conn_context) \ -{\ - LOG_PRINT_L2("HTTP [" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ - response.m_response_code = 200; \ - response.m_response_comment = "Ok"; \ - if(!handle_http_request_map(query_info, response, m_conn_context)) \ - {response.m_response_code = 404;response.m_response_comment = "Not found";} \ - return true; \ -} - - -#define BEGIN_URI_MAP2() template bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response_info, \ - t_context& m_conn_context) { \ - bool handled = false; \ - if(false) return true; //just a stub to have "else if" - -#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context); - -#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format - -#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) \ - else if(query_info.m_URI == s_pattern) \ - { \ - handled = true; \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool parse_res = epee::serialization::load_t_from_json(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - if(!callback_f(static_cast(req), static_cast(resp), m_conn_context)) \ - { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ - response_info.m_response_code = 500; \ - response_info.m_response_comment = "Internal Server Error"; \ - return true; \ - } \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - LOG_PRINT( s_pattern << " processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ - } - -#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ - else if(query_info.m_URI == s_pattern) \ - { \ - handled = true; \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool parse_res = epee::serialization::load_t_from_binary(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - if(!callback_f(static_cast(req), static_cast(resp), m_conn_context)) \ - { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ - response_info.m_response_code = 500; \ - response_info.m_response_comment = "Internal Server Error"; \ - return true; \ - } \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_binary(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = " application/octet-stream"; \ - response_info.m_header_info.m_content_type = " application/octet-stream"; \ - LOG_PRINT( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ - } - -#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);handled = true;} - -#define END_URI_MAP2() return handled;} - - -#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \ - { \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if(!ps.load_from_json(query_info.m_body)) \ - { \ - boost::value_initialized rsp; \ - static_cast(rsp).error.code = -32700; \ - static_cast(rsp).error.message = "Parse error"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - ps.get_value("id", id_, nullptr); \ - std::string callback_name; \ - if(!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::json_rpc::error_response rsp; \ - rsp.jsonrpc = "2.0"; \ - rsp.error.code = -32600; \ - rsp.error.message = "Invalid Request"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - if(false) return true; //just a stub to have "else if" - - -#define PREPARE_OBJECTS_FROM_JSON(command_type) \ - handled = true; \ - boost::value_initialized > req_; \ - epee::json_rpc::request& req = static_cast&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32602; \ - fail_resp.error.message = "Invalid params"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized > resp_; \ - epee::json_rpc::response& resp = static_cast &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - LOG_PRINT( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); - -#define MAP_JON_RPC_WE(method_name, callback_f, command_type) \ - else if(callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \ - else if(callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC(method_name, callback_f, command_type) \ - else if(callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - if(!callback_f(req.params, resp.result, m_conn_context)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32603; \ - fail_resp.error.message = "Internal error"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define END_JSON_RPC_MAP() \ - epee::json_rpc::error_response rsp; \ - rsp.id = id_; \ - rsp.jsonrpc = "2.0"; \ - rsp.error.code = -32601; \ - rsp.error.message = "Method not found"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ -} - - diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h deleted file mode 100644 index c02475c3..00000000 --- a/contrib/epee/include/net/http_server_impl_base.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - - -#include -#include - -#include "net/http_server_cp2.h" -#include "net/http_server_handlers_map2.h" - -namespace epee -{ - - template - class http_server_impl_base: public net_utils::http::i_http_server_handler - { - - public: - http_server_impl_base() - : m_net_server() - {} - - explicit http_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0") - { - - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast(this); - - //here set folder for hosting reqests - m_net_server.get_config_object().m_folder = ""; - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if(!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - protected: - net_utils::boosted_tcp_server > m_net_server; - }; -} \ No newline at end of file diff --git a/contrib/epee/include/net/http_server_thread_per_connect.h b/contrib/epee/include/net/http_server_thread_per_connect.h deleted file mode 100644 index bec43b72..00000000 --- a/contrib/epee/include/net/http_server_thread_per_connect.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server.h" -#include "http_server.h" - -namespace epee -{ -namespace net_utils -{ - typedef abstract_tcp_server mt_http_server_file_system; - typedef abstract_tcp_server mt_http_server_custum_handling; - -} -} - - -#endif - - diff --git a/contrib/epee/include/net/jsonrpc_protocol_handler.h b/contrib/epee/include/net/jsonrpc_protocol_handler.h deleted file mode 100644 index b224c342..00000000 --- a/contrib/epee/include/net/jsonrpc_protocol_handler.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef JSONRPC_PROTOCOL_HANDLER_H -#define JSONRPC_PROTOCOL_HANDLER_H - -#include -#include - -#include "net/net_utils_base.h" -#include "jsonrpc_structs.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ -namespace net_utils -{ - namespace jsonrpc2 - { - inline - std::string& make_error_resp_json(int64_t code, const std::string& message, - std::string& response_data, - const epee::serialization::storage_entry& id = nullptr) - { - epee::json_rpc::error_response rsp; - rsp.id = id; - rsp.jsonrpc = "2.0"; - rsp.error.code = code; - rsp.error.message = message; - epee::serialization::store_t_to_json(static_cast(rsp), response_data, 0, false); - response_data += "\n"; - return response_data; - } - - template - struct i_jsonrpc2_server_handler - { - virtual ~i_jsonrpc2_server_handler() - {} - virtual bool handle_rpc_request(const std::string& req_data, - std::string& resp_data, - t_connection_context& conn_context) = 0; - virtual bool init_server_thread() - { return true; } - virtual bool deinit_server_thread() - { return true; } - }; - - template - struct jsonrpc2_server_config - { - i_jsonrpc2_server_handler* m_phandler; - critical_section m_lock; - }; - - template - class jsonrpc2_connection_handler - { - public: - typedef t_connection_context connection_context; - typedef jsonrpc2_server_config config_type; - - jsonrpc2_connection_handler(i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context) - : m_psnd_hndlr(psnd_hndlr), - m_config(config), - m_conn_context(conn_context), - m_is_stop_handling(false) - {} - virtual ~jsonrpc2_connection_handler() - {} - - bool release_protocol() - { - return true; - } - virtual bool thread_init() - { - return true; - } - virtual bool thread_deinit() - { - return true; - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" << buf); - - bool res = handle_buff_in(buf); - return res; - } - private: - bool handle_buff_in(std::string& buf) - { - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while (!m_is_stop_handling) { - std::string::size_type pos = match_end_of_request(m_cache); - if (std::string::npos == pos) { - m_is_stop_handling = true; - if (m_cache.size() > 4096) { - LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request"); - return false; - } - break; - } else { - extract_cached_request_and_handle(pos); - } - - if (!m_cache.size()) { - m_is_stop_handling = true; - } - } - - return true; - } - bool extract_cached_request_and_handle(std::string::size_type pos) - { - std::string request_data(m_cache.begin(), m_cache.begin() + pos); - m_cache.erase(0, pos); - return handle_request_and_send_response(request_data); - } - bool handle_request_and_send_response(const std::string& request_data) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - std::string response_data; - - LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" << request_data); - bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context); - LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - return rpc_result; - } - std::string::size_type match_end_of_request(const std::string& buf) - { - std::string::size_type res = buf.find("\n"); - if(std::string::npos != res) { - return res + 2; - } - return res; - } - - protected: - i_service_endpoint* m_psnd_hndlr; - - private: - config_type& m_config; - t_connection_context& m_conn_context; - std::string m_cache; - bool m_is_stop_handling; - }; - } -} -} - -#endif /* JSONRPC_PROTOCOL_HANDLER_H */ diff --git a/contrib/epee/include/net/jsonrpc_server_handlers_map.h b/contrib/epee/include/net/jsonrpc_server_handlers_map.h deleted file mode 100644 index 8c747d1a..00000000 --- a/contrib/epee/include/net/jsonrpc_server_handlers_map.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef JSONRPC_SERVER_HANDLERS_MAP_H -#define JSONRPC_SERVER_HANDLERS_MAP_H - -#include -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "storages/portable_storage_base.h" -#include "jsonrpc_structs.h" -#include "jsonrpc_protocol_handler.h" - -#define BEGIN_JSONRPC2_MAP(t_connection_context) \ -bool handle_rpc_request(const std::string& req_data, \ - std::string& resp_data, \ - t_connection_context& m_conn_context) \ -{ \ - bool handled = false; \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if (!ps.load_from_json(req_data)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32700, "Parse error", resp_data); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - if (!ps.get_value("id", id_, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data); \ - return true; \ - } \ - std::string callback_name; \ - if (!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data, id_); \ - return true; \ - } \ - if (false) return true; //just a stub to have "else if" - - - -#define PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - handled = true; \ - boost::value_initialized > req_; \ - epee::json_rpc::request& req = static_cast&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32602, "Invalid params", resp_data, req.id); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized > resp_; \ - epee::json_rpc::response& resp = static_cast &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, resp_data, 0, false); \ - resp_data += "\n"; \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - LOG_PRINT("[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); - - -#define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \ - else if (callback_name == method_name) \ - { \ - PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), resp_data, 0, false); \ - resp_data += "\n"; \ - return true; \ - } \ - FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \ - return true; \ - } - -#define END_JSONRPC2_MAP() \ - epee::net_utils::jsonrpc2::make_error_resp_json(-32601, "Method not found", resp_data, id_); \ - return true; \ -} - -#endif /* JSONRPC_SERVER_HANDLERS_MAP_H */ diff --git a/contrib/epee/include/net/jsonrpc_server_impl_base.h b/contrib/epee/include/net/jsonrpc_server_impl_base.h deleted file mode 100644 index 8a5a9a5b..00000000 --- a/contrib/epee/include/net/jsonrpc_server_impl_base.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef JSONRPC_SERVER_IMPL_BASE_H -#define JSONRPC_SERVER_IMPL_BASE_H - -#include -#include - -#include "net/jsonrpc_protocol_handler.h" -#include "net/jsonrpc_server_handlers_map.h" -#include "net/abstract_tcp_server2.h" - -namespace epee -{ - -template - class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler - { - - public: - jsonrpc_server_impl_base() - : m_net_server() - {} - - explicit jsonrpc_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0") - { - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast(this); - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if (!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - protected: - net_utils::boosted_tcp_server > m_net_server; - }; - -} - -#endif /* JSONRPC_SERVER_IMPL_BASE_H */ - diff --git a/contrib/epee/include/net/jsonrpc_structs.h b/contrib/epee/include/net/jsonrpc_structs.h deleted file mode 100644 index 9df9e259..00000000 --- a/contrib/epee/include/net/jsonrpc_structs.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef JSONRPC_STRUCTS_H -#define JSONRPC_STRUCTS_H - -#include -#include -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_base.h" - -namespace epee -{ - namespace json_rpc - { - template - struct request - { - std::string jsonrpc; - std::string method; - epee::serialization::storage_entry id; - t_param params; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(method) - KV_SERIALIZE(params) - END_KV_SERIALIZE_MAP() - }; - - struct error - { - int64_t code; - std::string message; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(code) - KV_SERIALIZE(message) - END_KV_SERIALIZE_MAP() - }; - - struct dummy_error - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct dummy_result - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - t_error error; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_error error; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - typedef response error_response; - } -} - -#endif /* JSONRPC_STRUCTS_H */ diff --git a/contrib/epee/include/net/levin_base.h b/contrib/epee/include/net/levin_base.h deleted file mode 100644 index d630bff1..00000000 --- a/contrib/epee/include/net/levin_base.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_BASE_H_ -#define _LEVIN_BASE_H_ - -#include "net_utils_base.h" - -#define LEVIN_SIGNATURE 0x0101010101012101LL //Bender's nightmare - -namespace epee -{ -namespace levin -{ -#pragma pack(push) -#pragma pack(1) - struct bucket_head - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_reservedA; //probably some flags in future - uint32_t m_reservedB; //probably some check sum in future - }; -#pragma pack(pop) - - -#pragma pack(push) -#pragma pack(1) - struct bucket_head2 - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_flags; - uint32_t m_protocol_version; - }; -#pragma pack(pop) - - -#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED 0 -#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default - -#define LEVIN_PACKET_REQUEST 0x00000001 -#define LEVIN_PACKET_RESPONSE 0x00000002 - - -#define LEVIN_PROTOCOL_VER_0 0 -#define LEVIN_PROTOCOL_VER_1 1 - - template - struct levin_commands_handler - { - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, t_connection_context& context)=0; - virtual int notify(int command, const std::string& in_buff, t_connection_context& context)=0; - virtual void callback(t_connection_context& context){}; - - virtual void on_connection_new(t_connection_context& context){}; - virtual void on_connection_close(t_connection_context& context){}; - - }; - -#define LEVIN_OK 0 -#define LEVIN_ERROR_CONNECTION -1 -#define LEVIN_ERROR_CONNECTION_NOT_FOUND -2 -#define LEVIN_ERROR_CONNECTION_DESTROYED -3 -#define LEVIN_ERROR_CONNECTION_TIMEDOUT -4 -#define LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL -5 -#define LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED -6 -#define LEVIN_ERROR_FORMAT -7 - -#define DESCRIBE_RET_CODE(code) case code: return #code; - inline - const char* get_err_descr(int err) - { - switch(err) - { - DESCRIBE_RET_CODE(LEVIN_OK); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NOT_FOUND); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_DESTROYED); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_TIMEDOUT); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED); - DESCRIBE_RET_CODE(LEVIN_ERROR_FORMAT); - default: - return "unknown code"; - } - } - - -} -} - - -#endif //_LEVIN_BASE_H_ diff --git a/contrib/epee/include/net/levin_client.h b/contrib/epee/include/net/levin_client.h deleted file mode 100644 index 335f6ba0..00000000 --- a/contrib/epee/include/net/levin_client.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - - -#ifndef _LEVIN_CLIENT_H_ -#define _LEVIN_CLIENT_H_ - -#include "net_helper.h" -#include "levin_base.h" - - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace epee -{ -namespace levin -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl - { - public: - levin_client_impl(); - virtual ~levin_client_impl(); - - bool connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool is_connected(); - bool disconnect(); - - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out); - virtual int notify(int command, const std::string& in_buff); - - protected: - net_utils::blocked_mode_client m_transport; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl2: public levin_client_impl - { - public: - - int invoke(int command, const std::string& in_buff, std::string& buff_out); - int notify(int command, const std::string& in_buff); - }; - -} -namespace net_utils -{ - typedef levin::levin_client_impl levin_client; - typedef levin::levin_client_impl2 levin_client2; -} -} - -#include "levin_client.inl" - -#endif //_LEVIN_CLIENT_H_ diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl deleted file mode 100644 index ae159da6..00000000 --- a/contrib/epee/include/net/levin_client.inl +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -#include "string_tools.h" -namespace epee -{ -namespace levin -{ -inline -bool levin_client_impl::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline - bool levin_client_impl::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(addr, port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::is_connected() -{ - return m_transport.is_connected(); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::disconnect() -{ - return m_transport.disconnect(); -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::levin_client_impl() -{ -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::~levin_client_impl() -{ - disconnect(); -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = command; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head))) - return -1; - - head = *(bucket_head*)local_buff.data(); - - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_PRINT_L0("Signature missmatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head2))) - return -1; - - head = *(bucket_head2*)local_buff.data(); - - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_PRINT_L0("Signature missmatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -} -} -//------------------------------------------------------------------------------ \ No newline at end of file diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h deleted file mode 100644 index 9e76cd50..00000000 --- a/contrib/epee/include/net/levin_client_async.h +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "" -#include "net_helper.h" -#include "levin_base.h" - - -namespace epee -{ -namespace levin -{ - - /************************************************************************ - * levin_client_async - probably it is not really fast implementation, - * each handler thread could make up to 30 ms latency. - * But, handling events in reader thread will cause dead locks in - * case of recursive call (call invoke() to the same connection - * on reader thread on remote invoke() handler) - ***********************************************************************/ - - - class levin_client_async - { - levin_commands_handler* m_pcommands_handler; - volatile uint32_t m_is_stop; - volatile uint32_t m_threads_count; - ::critical_section m_send_lock; - - std::string m_local_invoke_buff; - ::critical_section m_local_invoke_buff_lock; - volatile int m_invoke_res; - - volatile uint32_t m_invoke_data_ready; - volatile uint32_t m_invoke_is_active; - - boost::mutex m_invoke_event; - boost::condition_variable m_invoke_cond; - size_t m_timeout; - - ::critical_section m_recieved_packets_lock; - struct packet_entry - { - bucket_head m_hd; - std::string m_body; - uint32_t m_connection_index; - }; - std::list m_recieved_packets; - /* - m_current_connection_index needed when some connection was broken and reconnected - in this - case we could have some received packets in que, which shoud not be handled - */ - volatile uint32_t m_current_connection_index; - ::critical_section m_invoke_lock; - ::critical_section m_reciev_packet_lock; - ::critical_section m_connection_lock; - net_utils::blocked_mode_client m_transport; - public: - levin_client_async():m_pcommands_handler(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - levin_client_async(const levin_client_async& /*v*/):m_pcommands_handler(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - ~levin_client_async() - { - boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1); - disconnect(); - - - while(boost::interprocess::ipcdetail::atomic_read32(&m_threads_count)) - ::Sleep(100); - } - - void set_handler(levin_commands_handler* phandler) - { - m_pcommands_handler = phandler; - } - - bool connect(uint32_t ip, uint32_t port, uint32_t timeout) - { - loop_call_guard(); - critical_region cr(m_connection_lock); - - m_timeout = timeout; - bool res = false; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock); - CRITICAL_REGION_BEGIN(m_send_lock); - res = levin_client_impl::connect(ip, port, timeout); - boost::interprocess::ipcdetail::atomic_inc32(&m_current_connection_index); - CRITICAL_REGION_END(); - CRITICAL_REGION_END(); - if(res && !boost::interprocess::ipcdetail::atomic_read32(&m_threads_count) ) - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 0);//m_is_stop = false; - boost::thread( boost::bind(&levin_duplex_client::reciever_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - } - - return res; - } - bool is_connected() - { - loop_call_guard(); - critical_region cr(m_cs); - return levin_client_impl::is_connected(); - } - - inline - bool check_connection() - { - loop_call_guard(); - critical_region cr(m_cs); - - if(!is_connected()) - { - if( !reconnect() ) - { - LOG_ERROR("Reconnect Failed. Failed to invoke() becouse not connected!"); - return false; - } - } - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, char* pbuff, size_t cb) - { - while(cb) - { - int res = ::recv(m_socket, pbuff, (int)cb, 0); - - if(SOCKET_ERROR == res) - { - if(!m_connected) - return false; - - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - //reconnect(); - return false; - }else if(res == 0) - { - disconnect(); - //reconnect(); - return false; - } - LOG_PRINT_L4("[" << m_socket <<"] RECV " << res); - cb -= res; - pbuff += res; - } - - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, std::string& buff) - { - size_t cb_remain = buff.size(); - char* m_current_ptr = (char*)buff.data(); - return recv_n(s, m_current_ptr, cb_remain); - } - - bool disconnect() - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);//m_is_stop = true; - loop_call_guard(); - critical_region cr(m_cs); - levin_client_impl::disconnect(); - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.clear(); - m_invoke_res = LEVIN_ERROR_CONNECTION_DESTROYED; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - return true; - } - - void loop_call_guard() - { - - } - - void on_leave_invoke() - { - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 0); - } - - int invoke(const GUID& target, int command, const std::string& in_buff, std::string& buff_out) - { - - critical_region cr_invoke(m_invoke_lock); - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 1); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 0); - misc_utils::destr_ptr hdlr = misc_utils::add_exit_scope_handler(boost::bind(&levin_duplex_client::on_leave_invoke, this)); - - loop_call_guard(); - - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - LOG_PRINT("[" << m_socket <<"] Sending invoke data", LOG_LEVEL_4); - - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - //hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles. - boost::system_time timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - size_t timeout_count = 0; - boost::unique_lock lock(m_invoke_event); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_data_ready)) - { - if(!m_invoke_cond.timed_wait(lock, timeout)) - { - if(timeout_count < 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - ++timeout_count; - continue; - }else if(timeout_count == 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::minutes(10); - ++timeout_count; - continue; - }else - { - LOG_PRINT("[" << m_socket <<"] Timeout on waiting invoke result. ", LOG_LEVEL_0); - //disconnect(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - } - } - - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - buff_out.swap(m_local_invoke_buff); - m_local_invoke_buff.clear(); - CRITICAL_REGION_END(); - return m_invoke_res; - } - - int notify(const GUID& target, int command, const std::string& in_buff) - { - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - return 1; - } - - - private: - bool have_some_data(SOCKET sock, int interval = 1) - { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdse; - FD_ZERO(&fdse); - FD_SET(sock, &fdse); - - - timeval tv; - tv.tv_sec = interval; - tv.tv_usec = 0; - - int sel_res = select(0, &fds, 0, &fdse, &tv); - if(0 == sel_res) - return false; - else if(sel_res == SOCKET_ERROR) - { - if(m_is_stop) - return false; - int err_code = ::WSAGetLastError(); - LOG_ERROR("Filed to call select, err code = " << err_code); - disconnect(); - }else - { - if(fds.fd_array[0]) - {//some read operations was performed - return true; - }else if(fdse.fd_array[0]) - {//some error was at the socket - return true; - } - } - return false; - } - - - bool reciev_and_process_incoming_data() - { - bucket_head head = {0}; - uint32_t conn_index = 0; - bool is_request = false; - std::string local_buff; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock);//to protect from socket reconnect between head and body - - if(!recv_n(m_socket, (char*)&head, sizeof(head))) - { - if(m_is_stop) - return false; - LOG_ERROR("Failed to recv_n"); - return false; - } - - conn_index = boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index); - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_ERROR("Signature missmatch in response"); - return false; - } - - is_request = (head.m_protocol_version == LEVIN_PROTOCOL_VER_1 && head.m_flags&LEVIN_PACKET_REQUEST); - - - local_buff.resize((size_t)head.m_cb); - if(!recv_n(m_socket, local_buff)) - { - if(m_is_stop) - return false; - LOG_ERROR("Filed to reciev"); - return false; - } - CRITICAL_REGION_END(); - - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - if(is_request) - { - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - m_recieved_packets.resize(m_recieved_packets.size() + 1); - m_recieved_packets.back().m_hd = head; - m_recieved_packets.back().m_body.swap(local_buff); - m_recieved_packets.back().m_connection_index = conn_index; - CRITICAL_REGION_END(); - /* - - */ - }else - {//this is some response - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.swap(local_buff); - m_invoke_res = head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - - } - return true; - } - - bool reciever_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - if(!m_connected) - { - Sleep(100); - continue; - } - - if(have_some_data(m_socket, 1)) - { - if(!reciev_and_process_incoming_data()) - { - if(m_is_stop) - { - break;//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //return true; - } - LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); - //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //disconnect_no_wait(); - //break; - } - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - - bool process_recieved_packet(bucket_head& head, const std::string& local_buff, uint32_t conn_index) - { - - net_utils::connection_context_base conn_context; - conn_context.m_remote_ip = m_ip; - conn_context.m_remote_port = m_port; - if(head.m_have_to_return_data) - { - std::string return_buff; - if(m_pcommands_handler) - head.m_return_code = m_pcommands_handler->invoke(head.m_id, head.m_command, local_buff, return_buff, conn_context); - else - head.m_return_code = LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; - - - - head.m_cb = return_buff.size(); - head.m_have_to_return_data = false; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_RESPONSE; - - std::string send_buff((const char*)&head, sizeof(head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(conn_index != boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index)) - {//there was reconnect, send response back is not allowed - return true; - } - int res = ::send(m_socket, (const char*)send_buff.data(), send_buff.size(), 0); - if(res == SOCKET_ERROR) - { - int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); - return false; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - } - else - { - if(m_pcommands_handler) - m_pcommands_handler->notify(head.m_id, head.m_command, local_buff, conn_context); - } - - return true; - } - - bool handler_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - bool have_some_work = false; - std::string local_buff; - bucket_head bh = {0}; - uint32_t conn_index = 0; - - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - if(m_recieved_packets.size()) - { - bh = m_recieved_packets.begin()->m_hd; - conn_index = m_recieved_packets.begin()->m_connection_index; - local_buff.swap(m_recieved_packets.begin()->m_body); - have_some_work = true; - m_recieved_packets.pop_front(); - } - CRITICAL_REGION_END(); - - if(have_some_work) - { - process_recieved_packet(bh, local_buff, conn_index); - }else - { - //Idle when no work - Sleep(30); - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - }; - -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/levin_client_async.inl b/contrib/epee/include/net/levin_client_async.inl deleted file mode 100644 index e69de29b..00000000 diff --git a/contrib/epee/include/net/levin_helper.h b/contrib/epee/include/net/levin_helper.h deleted file mode 100644 index a8406103..00000000 --- a/contrib/epee/include/net/levin_helper.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "levin_base.h" -#include "serializeble_struct_helper.h" - -namespace epee -{ -namespace levin -{ - template - bool pack_struct_to_levin_message(const t_struct& t, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - std::string buff_strg; - if(!StorageNamed::save_struct_as_storage_to_buff_t(t, buff_strg)) - return false; - - head.m_cb = buff_strg.size(); - buff.append(buff_strg); - return true; - } - - - bool pack_data_to_levin_message(const std::string& data, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - head.m_cb = data.size(); - buff.append(data); - return true; - } - - bool load_levin_data_from_levin_message(std::string& levin_data, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_PRINT_L3("sizes missmatch, at load_struct_from_levin_message"); - return false; - } - - //std::string buff_strg; - levin_data.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - command = head.m_command; - return true; - } - - template - bool load_struct_from_levin_message(t_struct& t, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_ERROR("sizes missmatch, at load_struct_from_levin_message"); - return false; - } - - std::string buff_strg; - buff_strg.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - - if(!StorageNamed::load_struct_from_storage_buff_t(t, buff_strg)) - { - LOG_ERROR("Failed to read storage, at load_struct_from_levin_message"); - return false; - } - command = head.m_command; - return true; - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/levin_protocol_handler.h b/contrib/epee/include/net/levin_protocol_handler.h deleted file mode 100644 index 512ba1c3..00000000 --- a/contrib/epee/include/net/levin_protocol_handler.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_PROTOCOL_HANDLER_H_ -#define _LEVIN_PROTOCOL_HANDLER_H_ - -#include -#include "levin_base.h" - -namespace epee -{ -namespace levin -{ - template - struct protocl_handler_config - { - levin_commands_handler* m_pcommands_handler; - }; - - template - class protocol_handler - { - public: - typedef t_connection_context connection_context; - typedef protocl_handler_config config_type; - - protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context); - virtual ~protocol_handler(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - enum connection_data_state - { - conn_state_reading_head, - conn_state_reading_body - }; - - - config_type& m_config; - t_connection_context& m_conn_context; - net_utils::i_service_endpoint* m_psnd_hndlr; - std::string m_cach_in_buffer; - connection_data_state m_state; - bucket_head m_current_head; - }; - - template - protocol_handler::protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context): - m_config(config), - m_conn_context(conn_context), - m_psnd_hndlr(psnd_hndlr), - m_state(conn_state_reading_head), - m_current_head(bucket_head()) - {} - - template - bool protocol_handler::handle_recv(const void* ptr, size_t cb) - { - if(!m_config.m_pcommands_handler) - { - LOG_ERROR("Command handler not set!"); - return false; - } - m_cach_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case conn_state_reading_head: - if(m_cach_in_buffer.size() < sizeof(bucket_head)) - { - if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) - { - LOG_ERROR("Signature missmatch on accepted connection"); - return false; - } - is_continue = false; - break; - } - { - bucket_head* phead = (bucket_head*)m_cach_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_ERROR("Signature missmatch on accepted connection"); - return false; - } - m_current_head = *phead; - } - m_cach_in_buffer.erase(0, sizeof(bucket_head)); - m_state = conn_state_reading_body; - break; - case conn_state_reading_body: - if(m_cach_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - break; - } - { - std::string buff_to_invoke; - if(m_cach_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cach_in_buffer); - else - { - buff_to_invoke.assign(m_cach_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cach_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke(m_current_head.m_command, buff_to_invoke, return_buff, m_conn_context); - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - - if(!m_psnd_hndlr->do_send(send_buff.data(), send_buff.size())) - return false; - - } - else - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_conn_context); - } - m_state = conn_state_reading_head; - break; - default: - LOG_ERROR("Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } - - - - - - - -} -} - - - - -#endif //_LEVIN_PROTOCOL_HANDLER_H_ - diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h deleted file mode 100644 index 406d92b2..00000000 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ /dev/null @@ -1,779 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include -#include -#include -#include - -#include - -#include "levin_base.h" -#include "misc_language.h" - - -namespace epee -{ -namespace levin -{ - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler; - -template -class async_protocol_handler_config -{ - typedef std::map* > connections_map; - critical_section m_connects_lock; - connections_map m_connects; - - void add_connection(async_protocol_handler* pc); - void del_connection(async_protocol_handler* pc); - - async_protocol_handler* find_connection(boost::uuids::uuid connection_id) const; - int find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph); - - friend class async_protocol_handler; - -public: - typedef t_connection_context connection_context; - levin_commands_handler* m_pcommands_handler; - uint64_t m_max_packet_size; - uint64_t m_invoke_timeout; - - int invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id); - template - int invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, callback_t cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED); - - int notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id); - bool close(boost::uuids::uuid connection_id); - bool update_connection_context(const t_connection_context& contxt); - bool request_callback(boost::uuids::uuid connection_id); - template - bool foreach_connection(callback_t cb); - size_t get_connections_count(); - - async_protocol_handler_config():m_pcommands_handler(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE) - {} -}; - - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler -{ -public: - typedef t_connection_context connection_context; - typedef async_protocol_handler_config config_type; - - enum stream_state - { - stream_state_head, - stream_state_body - }; - - std::atomic m_deletion_initiated; - std::atomic m_protocol_released; - volatile uint32_t m_invoke_buf_ready; - - volatile int m_invoke_result_code; - - critical_section m_local_inv_buff_lock; - std::string m_local_inv_buff; - - critical_section m_send_lock; - critical_section m_call_lock; - - volatile uint32_t m_wait_count; - volatile uint32_t m_close_called; - bucket_head2 m_current_head; - net_utils::i_service_endpoint* m_pservice_endpoint; - config_type& m_config; - t_connection_context& m_connection_context; - - std::string m_cache_in_buffer; - stream_state m_state; - - int32_t m_oponent_protocol_ver; - bool m_connection_initialized; - - struct invoke_response_handler_base - { - virtual bool handle(int res, const std::string& buff, connection_context& context)=0; - virtual bool is_timer_started() const=0; - virtual void cancel()=0; - virtual bool cancel_timer()=0; - }; - template - struct anvoke_handler: invoke_response_handler_base - { - anvoke_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command) - :m_cb(cb), m_con(con), m_timer(con.m_pservice_endpoint->get_io_service()), m_timer_started(false), - m_cancel_timer_called(false), m_timer_cancelled(false), m_command(command) - { - if(m_con.start_outer_call()) - { - m_timer.expires_from_now(boost::posix_time::milliseconds(timeout)); - m_timer.async_wait([&con, command, cb](const boost::system::error_code& ec) - { - if(ec == boost::asio::error::operation_aborted) - return; - LOG_PRINT_CC(con.get_context_ref(), "Timeout on invoke operation happened, command: " << command, LOG_LEVEL_2); - std::string fake; - cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); - con.close(); - con.finish_outer_call(); - }); - m_timer_started = true; - } - } - virtual ~anvoke_handler() - {} - callback_t m_cb; - async_protocol_handler& m_con; - boost::asio::deadline_timer m_timer; - bool m_timer_started; - bool m_cancel_timer_called; - bool m_timer_cancelled; - int m_command; - virtual bool handle(int res, const std::string& buff, typename async_protocol_handler::connection_context& context) - { - if(!cancel_timer()) - return false; - m_cb(res, buff, context); - m_con.finish_outer_call(); - return true; - } - virtual bool is_timer_started() const - { - return m_timer_started; - } - virtual void cancel() - { - if(cancel_timer()) - { - std::string fake; - m_cb(LEVIN_ERROR_CONNECTION_DESTROYED, fake, m_con.get_context_ref()); - m_con.finish_outer_call(); - } - } - virtual bool cancel_timer() - { - if(!m_cancel_timer_called) - { - m_cancel_timer_called = true; - boost::system::error_code ignored_ec; - m_timer_cancelled = 1 == m_timer.cancel(ignored_ec); - } - return m_timer_cancelled; - } - }; - critical_section m_invoke_response_handlers_lock; - std::list > m_invoke_response_handlers; - - template - bool add_invoke_response_handler(callback_t cb, uint64_t timeout, async_protocol_handler& con, int command) - { - CRITICAL_REGION_LOCAL(m_invoke_response_handlers_lock); - boost::shared_ptr handler(boost::make_shared>(cb, timeout, con, command)); - m_invoke_response_handlers.push_back(handler); - return handler->is_timer_started(); - } - template friend struct anvoke_handler; -public: - async_protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context): - m_current_head(bucket_head2()), - m_pservice_endpoint(psnd_hndlr), - m_config(config), - m_connection_context(conn_context), - m_state(stream_state_head) - { - m_close_called = 0; - m_deletion_initiated = false; - m_protocol_released = false; - m_wait_count = 0; - m_oponent_protocol_ver = 0; - m_connection_initialized = false; - } - virtual ~async_protocol_handler() - { - m_deletion_initiated = true; - if(m_connection_initialized) - { - m_config.del_connection(this); - } - - for (size_t i = 0; i < 60 * 1000 / 100 && 0 != boost::interprocess::ipcdetail::atomic_read32(&m_wait_count); ++i) - { - misc_utils::sleep_no_w(100); - } - CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); - - LOG_PRINT_CC(m_connection_context, "~async_protocol_handler()", LOG_LEVEL_4); - } - - bool start_outer_call() - { - LOG_PRINT_CC_L4(m_connection_context, "[levin_protocol] -->> start_outer_call"); - if(!m_pservice_endpoint->add_ref()) - { - LOG_PRINT_CC_RED(m_connection_context, "[levin_protocol] -->> start_outer_call failed", LOG_LEVEL_4); - return false; - } - boost::interprocess::ipcdetail::atomic_inc32(&m_wait_count); - return true; - } - bool finish_outer_call() - { - LOG_PRINT_CC_L4(m_connection_context, "[levin_protocol] <<-- finish_outer_call"); - boost::interprocess::ipcdetail::atomic_dec32(&m_wait_count); - m_pservice_endpoint->release(); - return true; - } - - bool release_protocol() - { - decltype(m_invoke_response_handlers) local_invoke_response_handlers; - CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock); - local_invoke_response_handlers.swap(m_invoke_response_handlers); - m_protocol_released = true; - CRITICAL_REGION_END(); - - // Never call callback inside critical section, that can cause deadlock. Callback can be called when - // invoke_response_handler_base is cancelled - std::for_each(local_invoke_response_handlers.begin(), local_invoke_response_handlers.end(), [](const boost::shared_ptr& pinv_resp_hndlr) { - pinv_resp_hndlr->cancel(); - }); - - return true; - } - - bool close() - { - boost::interprocess::ipcdetail::atomic_inc32(&m_close_called); - - m_pservice_endpoint->close(); - return true; - } - - void update_connection_context(const connection_context& contxt) - { - m_connection_context = contxt; - } - - void request_callback() - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - m_pservice_endpoint->request_callback(); - } - - void handle_qued_callback() - { - m_config.m_pcommands_handler->callback(m_connection_context); - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - if(boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - return false; //closing connections - - if(!m_config.m_pcommands_handler) - { - LOG_ERROR_CC(m_connection_context, "Commands handler not set!"); - return false; - } - - if(m_cache_in_buffer.size() + cb > m_config.m_max_packet_size) - { - LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet received " << m_cache_in_buffer.size() + cb - << ", connection will be closed."); - return false; - } - - m_cache_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case stream_state_body: - if(m_cache_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - break; - } - { - std::string buff_to_invoke; - if(m_cache_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cache_in_buffer); - else - { - buff_to_invoke.assign(m_cache_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cache_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE); - - LOG_PRINT_CC_L4(m_connection_context, "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", v=" << m_current_head.m_protocol_version); - - if(is_response) - {//response to some invoke - - epee::critical_region_t invoke_response_handlers_guard(m_invoke_response_handlers_lock); - if(!m_invoke_response_handlers.empty()) - {//async call scenario - boost::shared_ptr response_handler = m_invoke_response_handlers.front(); - bool timer_cancelled = response_handler->cancel_timer(); - // Don't pop handler, to avoid destroying it - if(timer_cancelled) - m_invoke_response_handlers.pop_front(); - invoke_response_handlers_guard.unlock(); - - if(timer_cancelled) - response_handler->handle(m_current_head.m_command, buff_to_invoke, m_connection_context); - } - else - { - invoke_response_handlers_guard.unlock(); - //use sync call scenario - if(!boost::interprocess::ipcdetail::atomic_read32(&m_wait_count) && !boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - { - LOG_ERROR_CC(m_connection_context, "no active invoke when response came, wtf?"); - return false; - }else - { - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_to_invoke.swap(m_local_inv_buff); - buff_to_invoke.clear(); - m_invoke_result_code = m_current_head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1); - } - } - }else - { - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke( - m_current_head.m_command, - buff_to_invoke, - return_buff, - m_connection_context); - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - m_current_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - m_current_head.m_flags = LEVIN_PACKET_RESPONSE; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) - return false; - CRITICAL_REGION_END(); - LOG_PRINT_CC_L4(m_connection_context, "LEVIN_PACKET_SENT. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", ver=" << m_current_head.m_protocol_version); - } - else - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context); - } - } - m_state = stream_state_head; - break; - case stream_state_head: - { - if(m_cache_in_buffer.size() < sizeof(bucket_head2)) - { - if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) - { - LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); - return false; - } - is_continue = false; - break; - } - - bucket_head2* phead = (bucket_head2*)m_cache_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); - return false; - } - m_current_head = *phead; - - m_cache_in_buffer.erase(0, sizeof(bucket_head2)); - m_state = stream_state_body; - m_oponent_protocol_ver = m_current_head.m_protocol_version; - if(m_current_head.m_cb > m_config.m_max_packet_size) - { - LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet header received " << m_current_head.m_cb - << ", connection will be closed."); - return false; - } - } - break; - default: - LOG_ERROR_CC(m_connection_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } - - bool after_init_connection() - { - if (!m_connection_initialized) - { - m_connection_initialized = true; - m_config.add_connection(this); - } - return true; - } - - template - bool async_invoke(int command, const std::string& in_buff, callback_t cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(timeout == LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - timeout = m_config.m_invoke_timeout; - - int err_code = LEVIN_OK; - do - { - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - CRITICAL_REGION_LOCAL1(m_invoke_response_handlers_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { -// LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - - if(!add_invoke_response_handler(cb, timeout, *this, command)) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - CRITICAL_REGION_END(); - } while (false); - - if (LEVIN_OK != err_code) - { - std::string stub_buff; - // Never call callback inside critical section, that can cause deadlock - cb(err_code, stub_buff, m_connection_context); - return false; - } - - return true; - } - - int invoke(int command, const std::string& in_buff, std::string& buff_out) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - CRITICAL_REGION_END(); - - LOG_PRINT_CC_L4(m_connection_context, "LEVIN_PACKET_SENT. [len=" << head.m_cb - << ", f=" << head.m_flags - << ", r?=" << head.m_have_to_return_data - << ", cmd = " << head.m_command - << ", ver=" << head.m_protocol_version); - - uint64_t ticks_start = misc_utils::get_tick_count(); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_deletion_initiated && !m_protocol_released) - { - if(misc_utils::get_tick_count() - ticks_start > m_config.m_invoke_timeout) - { - LOG_PRINT_CC_L2(m_connection_context, "invoke timeout (" << m_config.m_invoke_timeout << "), closing connection "); - close(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - if(!m_pservice_endpoint->call_run_once_service_io()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - - if(m_deletion_initiated || m_protocol_released) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_out.swap(m_local_inv_buff); - m_local_inv_buff.clear(); - CRITICAL_REGION_END(); - - return m_invoke_result_code; - } - - int notify(int command, const std::string& in_buff) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_have_to_return_data = false; - head.m_cb = in_buff.size(); - - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { -// LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); - return -1; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR("Failed to do_send()"); - return -1; - } - CRITICAL_REGION_END(); - LOG_PRINT_CC_L4(m_connection_context, "LEVIN_PACKET_SENT. [len=" << head.m_cb << - ", f=" << head.m_flags << - ", r?=" << head.m_have_to_return_data << - ", cmd = " << head.m_command << - ", ver=" << head.m_protocol_version); - - return 1; - } - //------------------------------------------------------------------------------------------ - boost::uuids::uuid get_connection_id() {return m_connection_context.m_connection_id;} - //------------------------------------------------------------------------------------------ - t_connection_context& get_context_ref() {return m_connection_context;} -}; -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::del_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - m_connects.erase(pconn->get_connection_id()); - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_close(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::add_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - m_connects[pconn->get_connection_id()] = pconn; - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_new(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -async_protocol_handler* async_protocol_handler_config::find_connection(boost::uuids::uuid connection_id) const -{ - auto it = m_connects.find(connection_id); - return it == m_connects.end() ? 0 : it->second; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - aph = find_connection(connection_id); - if(0 == aph) - return LEVIN_ERROR_CONNECTION_NOT_FOUND; - if(!aph->start_outer_call()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - return LEVIN_OK; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->invoke(command, in_buff, buff_out) : r; -} -//------------------------------------------------------------------------------------------ -template template -int async_protocol_handler_config::invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, callback_t cb, size_t timeout) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->async_invoke(command, in_buff, cb, timeout) : r; -} -//------------------------------------------------------------------------------------------ -template template -bool async_protocol_handler_config::foreach_connection(callback_t cb) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - for(auto& c: m_connects) - { - async_protocol_handler* aph = c.second; - if(!cb(aph->get_context_ref())) - return false; - } - return true; -} -//------------------------------------------------------------------------------------------ -template -size_t async_protocol_handler_config::get_connections_count() -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - return m_connects.size(); -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->notify(command, in_buff) : r; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::close(boost::uuids::uuid connection_id) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(connection_id); - return 0 != aph ? aph->close() : false; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::update_connection_context(const t_connection_context& contxt) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(contxt.m_connection_id); - if(0 == aph) - return false; - aph->update_connection_context(contxt); - return true; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::request_callback(boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - if(LEVIN_OK == r) - { - aph->request_callback(); - return true; - } - else - { - return false; - } -} -} -} diff --git a/contrib/epee/include/net/levin_server_cp.h b/contrib/epee/include/net/levin_server_cp.h deleted file mode 100644 index 8ece3505..00000000 --- a/contrib/epee/include/net/levin_server_cp.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "levin_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_levin_server; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/levin_server_cp2.h b/contrib/epee/include/net/levin_server_cp2.h deleted file mode 100644 index b29d49bf..00000000 --- a/contrib/epee/include/net/levin_server_cp2.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server2.h" -#include "levin_protocol_handler.h" -#include "levin_protocol_handler_async.h" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_levin_server; - typedef boosted_tcp_server > boosted_levin_async_server; -} -} - - - -#endif - - diff --git a/contrib/epee/include/net/local_ip.h b/contrib/epee/include/net/local_ip.h deleted file mode 100644 index 0d458963..00000000 --- a/contrib/epee/include/net/local_ip.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -namespace epee -{ - namespace net_utils - { - inline - bool is_ip_local(uint32_t ip) - { - /* - local ip area - 10.0.0.0 — 10.255.255.255 - 172.16.0.0 — 172.31.255.255 - 192.168.0.0 — 192.168.255.255 - */ - if( (ip | 0xffffff00) == 0xffffff0a) - return true; - - if( (ip | 0xffff0000) == 0xffffa8c0) - return true; - - if( (ip | 0xffffff00) == 0xffffffac) - { - uint32_t second_num = (ip << 8) & 0xff000000; - if(second_num >= 16 && second_num <= 31 ) - return true; - } - return false; - } - inline - bool is_ip_loopback(uint32_t ip) - { - if( (ip | 0xffffff00) == 0xffffff7f) - return true; - //MAKE_IP - /* - loopback ip - 127.0.0.0 — 127.255.255.255 - */ - return false; - } - - } -} - diff --git a/contrib/epee/include/net/multiprotocols_server.h b/contrib/epee/include/net/multiprotocols_server.h deleted file mode 100644 index 4807a442..00000000 --- a/contrib/epee/include/net/multiprotocols_server.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MULTIPROTOCOLS_SERVER_H_ -#define _MULTIPROTOCOLS_SERVER_H_ - -//#include "abstract_tcp_server_cp.h" -#include "protocol_switcher.h" -#include "abstract_tcp_server2.h" - -namespace epee -{ -namespace net_utils -{ - //typedef cp_server_impl multiprotocol_server; - typedef boosted_tcp_server boosted_multiprotocol_server; -} -} - - -#endif //_MULTIPROTOCOLS_SERVER_H_ - diff --git a/contrib/epee/include/net/munin_connection_handler.h b/contrib/epee/include/net/munin_connection_handler.h deleted file mode 100644 index 8579339c..00000000 --- a/contrib/epee/include/net/munin_connection_handler.h +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_CONNECTION_HANDLER_H_ -#define _MUNIN_CONNECTION_HANDLER_H_ - -#include -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" -#include "reg_exp_definer.h" - -#define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n" -#define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n" -#define MUNIN_TITLE(title_str) "graph_title " title_str "\n" -#define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n" -#define MUNIN_INFO(info_str) "graph_info " info_str "\n" -#define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" -#define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n" -#define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n" -#define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) { -#define END_MUNIN_SERVICE() } -#define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast(variable) + "\n" - - - - -namespace epee -{ -namespace net_utils -{ - namespace munin - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct munin_service; - - struct munin_service_data_provider - { - virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0; - }; - - struct munin_service - { - std::string m_service_name; - std::string m_service_config_string; - munin_service_data_provider* m_pdata_provider; - }; - - struct node_server_config - { - std::list m_services; - //TODO: - }; - - struct fake_send_handler: public i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb) - { - m_cache += std::string((const char*)ptr, cb); - return true; - } - public: - - std::string m_cache; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class munin_node_server_connection_handler - { - public: - typedef node_server_config config_type; - typedef connection_context_base connection_context; - - munin_node_server_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, const connection_context_base& context):m_psnd_hndlr(psnd_hndlr), - m_machine_state(http_state_retriving_comand_line), - m_config(config) - { - init(); - } - virtual ~munin_node_server_connection_handler() - { - - } - - bool release_protocol() - { - return true; - } - bool after_init_connection() - { - std::string hello_str = "# munin node at "; - hello_str += m_host_name + "\n"; - send_hook(hello_str); - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - - void handle_qued_callback() - { - - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - - const char* pbuff = (const char*)ptr; - std::string recvd_buff(pbuff, cb); - LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3); - - m_cache += recvd_buff; - - bool stop_handling = false; - while(!stop_handling) - { - switch(m_machine_state) - { - case http_state_retriving_comand_line: - { - - std::string::size_type fpos = m_cache.find('\n'); - if(std::string::npos != fpos ) - { - bool res = handle_command(m_cache); - if(!res) - return false; - m_cache.erase(0, fpos+1); - continue; - } - stop_handling = true; - } - break; - case http_state_error: - stop_handling = true; - return false; - default: - LOG_ERROR("Error in munin state machine! Unkonwon state=" << m_machine_state); - stop_handling = true; - m_machine_state = http_state_error; - return false; - } - - } - - return true; - } - - private: - - - bool init() - { - char hostname[64] = {0}; - int res = gethostname(hostname, 64); - hostname[63] = 0;//be happy - m_host_name = hostname; - return true; - } - bool handle_command(const std::string& command) - { - // list, nodes, config, fetch, version or quit - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal); - // 12 3 4 5 6 7 8 9 - size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - if(result[2].matched) - {//list command - return handle_list_command(); - }else if(result[3].matched) - {//nodes command - return handle_nodes_command(); - }else if(result[4].matched) - {//config command - if(result[9].matched) - return handle_config_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[5].matched) - {//fetch command - if(result[9].matched) - return handle_fetch_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[6].matched) - {//version command - return handle_version_command(); - }else if(result[7].matched) - {//quit command - return handle_quit_command(); - } - else - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n"); - } - - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");; - } - - bool handle_list_command() - { - std::string buff_to_send; - for(std::list::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++) - { - buff_to_send += it->m_service_name + " "; - } - buff_to_send+='\n'; - return send_hook(buff_to_send); - } - bool handle_nodes_command() - { - //supports only one node - host name - send_hook(m_host_name + "\n.\n"); - return true; - } - bool handle_config_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - - return send_hook(psrv->m_service_config_string + ".\n"); - } - - bool handle_fetch_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - std::string buff; - psrv->m_pdata_provider->update_service_data(psrv, buff); - - buff += ".\n"; - return send_hook(buff); - } - bool handle_version_command() - { - return send_hook("Munin node component by Andrey Sabelnikov\n"); - } - bool handle_quit_command() - { - return false; - } - - bool send_hook(const std::string& buff) - { - LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3); - - if(m_psnd_hndlr) - return m_psnd_hndlr->do_send(buff.data(), buff.size()); - else - return false; - } - - - munin_service* get_service_by_name(const std::string& srv_name) - { - std::list::iterator it = m_config.m_services.begin(); - for(; it!=m_config.m_services.end(); it++) - if(it->m_service_name == srv_name) - break; - - if(it==m_config.m_services.end()) - return NULL; - - return &(*it); - } - - enum machine_state{ - http_state_retriving_comand_line, - http_state_error - }; - - - config_type& m_config; - machine_state m_machine_state; - std::string m_cache; - std::string m_host_name; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - - inline bool test_self() - { - /*WSADATA w; - ::WSAStartup(MAKEWORD(1, 1), &w); - node_server_config sc; - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service"; - - sc.m_services.back().m_service_config_string = - "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n" - "graph_title REPORTS STATICTICS\n" - "graph_category bind\n" - "graph_info This graph shows how many reports came in fixed time period.\n" - "graph_order apps free swap\n" - "apps.label apps\n" - "apps.draw AREA\n" - "apps.info Memory used by user-space applications.\n" - "swap.label swap\n" - "swap.draw STACK\n" - "swap.info Swap space used.\n" - "free.label unused\n" - "free.draw STACK\n" - "free.info Wasted memory. Memory that is not used for anything at all.\n" - "committed.label committed\n" - "committed.draw LINE2\n" - "committed.warn 625410048\n" - "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n"; - - - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service1"; - fake_send_handler fh; - munin_node_server_connection_handler mh(&fh, sc); - - std::string buff = "list\n"; - mh.handle_recv(buff.data(), buff.size()); - - - buff = "nodes\n"; - mh.handle_recv(buff.data(), buff.size()); -*/ - return true; - } - - } -} -} -#endif//!_MUNIN_CONNECTION_HANDLER_H_ \ No newline at end of file diff --git a/contrib/epee/include/net/munin_node_server.h b/contrib/epee/include/net/munin_node_server.h deleted file mode 100644 index 07637f55..00000000 --- a/contrib/epee/include/net/munin_node_server.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_NODE_SERVER_H_ -#define _MUNIN_NODE_SERVER_H_ - -#include -//#include "net_utils_base.h" -#include "munin_connection_handler.h" -//#include "abstract_tcp_server.h" -//#include "abstract_tcp_server_cp.h" -#include "abstract_tcp_server2.h" -namespace epee -{ -namespace net_utils -{ - namespace munin - { - typedef boosted_tcp_server munin_node_server; - //typedef cp_server_impl munin_node_cp_server; - } -} -} -#endif//!_MUNIN_NODE_SERVER_H_ \ No newline at end of file diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h deleted file mode 100644 index 4f7ebfa0..00000000 --- a/contrib/epee/include/net/net_helper.h +++ /dev/null @@ -1,683 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "net/net_utils_base.h" -#include "misc_language.h" -//#include "profile_tools.h" -#include "../string_tools.h" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - - -namespace epee -{ -namespace net_utils -{ - - class blocked_mode_client - { - - - struct handler_obj - { - handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred) - {} - handler_obj(const handler_obj& other_obj):ref_error(other_obj.ref_error), ref_bytes_transferred(other_obj.ref_bytes_transferred) - {} - - boost::system::error_code& ref_error; - size_t& ref_bytes_transferred; - - void operator()(const boost::system::error_code& error, // Result of operation. - std::size_t bytes_transferred // Number of bytes read. - ) - { - ref_error = error; - ref_bytes_transferred = bytes_transferred; - } - }; - - public: - inline - blocked_mode_client():m_socket(m_io_service), - m_initialized(false), - m_connected(false), - m_deadline(m_io_service), - m_shutdowned(0) - { - - - m_initialized = true; - - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - - } - inline - ~blocked_mode_client() - { - //profile_tools::local_coast lc("~blocked_mode_client()", 3); - shutdown(); - } - - inline void set_recv_timeout(int reciev_timeout) - { - m_reciev_timeout = reciev_timeout; - } - - inline - bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") - { - return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip); - } - - inline - bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") - { - m_connect_timeout = connect_timeout; - m_reciev_timeout = reciev_timeout; - m_connected = false; - if(!m_reciev_timeout) - m_reciev_timeout = m_connect_timeout; - - try - { - m_socket.close(); - // Get a list of endpoints corresponding to the server name. - - - ////////////////////////////////////////////////////////////////////////// - - boost::asio::ip::tcp::resolver resolver(m_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::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << addr); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - - m_socket.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); - m_socket.bind(local_endpoint); - } - - - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout)); - - - boost::system::error_code ec = boost::asio::error::would_block; - - //m_socket.connect(remote_endpoint); - m_socket.async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (!ec && m_socket.is_open()) - { - m_connected = true; - m_deadline.expires_at(boost::posix_time::pos_infin); - return true; - }else - { - LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); - return false; - } - - } - catch(const boost::system::system_error& er) - { - LOG_PRINT("Some problems at connect, message: " << er.what(), LOG_LEVEL_4); - return false; - } - catch(...) - { - LOG_PRINT("Some fatal problems.", LOG_LEVEL_4); - return false; - } - - return true; - } - - - inline - bool disconnect() - { - try - { - if(m_connected) - { - m_connected = false; - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); - - } - } - - catch(const boost::system::system_error& /*er*/) - { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); - return false; - } - catch(...) - { - //LOG_ERROR("Some fatal problems."); - return false; - } - return true; - } - - - inline - bool send(const std::string& buff) - { - - try - { - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(buff), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - */ - boost::system::error_code ec; - - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); - - - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at send, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - bool is_connected() - { - return m_connected && m_socket.is_open(); - //TRY_ENTRY() - //return m_socket.is_open(); - //CATCH_ENTRY_L0("is_connected", false) - } - - inline - bool recv(std::string& buff) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - handler_obj hndlr(ec, bytes_transfered); - - char local_buff[10000] = {0}; - //m_socket.async_read_some(boost::asio::buffer(local_buff, sizeof(local_buff)), hndlr); - boost::asio::async_read(m_socket, boost::asio::buffer(local_buff, sizeof(local_buff)), boost::asio::transfer_at_least(1), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - - if (ec) - { - LOG_PRINT_L4("READ ENDS: Connection err_code " << ec.value()); - if(ec == boost::asio::error::eof) - { - LOG_PRINT_L4("Connection err_code eof."); - //connection closed there, empty - return true; - } - - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - LOG_PRINT_L4("READ ENDS: Success. bytes_tr: " << bytes_transfered); - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - /*if(!bytes_transfered) - return false;*/ - - buff.assign(local_buff, bytes_transfered); - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - - } - - inline bool recv_n(std::string& buff, int64_t sz) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - buff.resize(static_cast(sz)); - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - - handler_obj hndlr(ec, bytes_transfered); - - //char local_buff[10000] = {0}; - boost::asio::async_read(m_socket, boost::asio::buffer((char*)buff.data(), buff.size()), boost::asio::transfer_at_least(buff.size()), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - if(bytes_transfered != buff.size()) - { - LOG_ERROR("Transferred missmatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); - return false; - } - - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - } - - bool shutdown() - { - m_deadline.cancel(); - boost::system::error_code ignored_ec; - m_socket.cancel(ignored_ec); - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_socket.close(ignored_ec); - boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); - m_connected = false; - return true; - } - - void set_connected(bool connected) - { - m_connected = connected; - } - boost::asio::io_service& get_io_service() - { - return m_io_service; - } - - boost::asio::ip::tcp::socket& get_socket() - { - return m_socket; - } - - private: - - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_connected = false; - m_socket.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_deadline.async_wait(boost::bind(&blocked_mode_client::check_deadline, this)); - } - - - - protected: - boost::asio::io_service m_io_service; - boost::asio::ip::tcp::socket m_socket; - int m_connect_timeout; - int m_reciev_timeout; - bool m_initialized; - bool m_connected; - boost::asio::deadline_timer m_deadline; - volatile uint32_t m_shutdowned; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class async_blocked_mode_client: public blocked_mode_client - { - public: - async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service) - { - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_send_deadline(); - } - ~async_blocked_mode_client() - { - m_send_deadline.cancel(); - } - - bool shutdown() - { - blocked_mode_client::shutdown(); - m_send_deadline.cancel(); - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while(ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - }*/ - - boost::system::error_code ec; - - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - return false; - }else - { - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - - private: - - boost::asio::deadline_timer m_send_deadline; - - void check_send_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_socket.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this)); - } - }; -} -} diff --git a/contrib/epee/include/net/net_parse_helpers.h b/contrib/epee/include/net/net_parse_helpers.h deleted file mode 100644 index 40c3d935..00000000 --- a/contrib/epee/include/net/net_parse_helpers.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "http_base.h" -#include "include_base_utils.h" -#include "reg_exp_definer.h" - - -namespace epee -{ -namespace net_utils -{ - - inline bool parse_uri_query(const std::string& query, std::list >& params) - { - enum state - { - st_param_name, - st_param_val - }; - state st = st_param_name; - std::string::const_iterator start_it = query.begin(); - std::pair e; - for(std::string::const_iterator it = query.begin(); it != query.end(); it++) - { - switch(st) - { - case st_param_name: - if(*it == '=') - { - e.first.assign(start_it, it); - start_it = it;++start_it; - st = st_param_val; - } - break; - case st_param_val: - if(*it == '&') - { - e.second.assign(start_it, it); - start_it = it;++start_it; - params.push_back(e); - e.first.clear();e.second.clear(); - st = st_param_name; - } - break; - default: - LOG_ERROR("Unknown state " << (int)st); - return false; - } - } - if(st == st_param_name) - { - if(start_it != query.end()) - { - e.first.assign(start_it, query.end()); - params.push_back(e); - } - }else - { - if(start_it != query.end()) - e.second.assign(start_it, query.end()); - - if(e.first.size()) - params.push_back(e); - } - return true; - } - - inline - bool parse_uri(const std::string uri, http::uri_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - content.m_query_params.clear(); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - - boost::smatch result; - if(!boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched) - { - LOG_PRINT_L0("[PARSE URI] regex not matched for uri: " << uri); - content.m_path = uri; - return true; - } - if(result[1].matched) - { - content.m_path = result[1]; - } - if(result[3].matched) - { - content.m_query = result[3]; - } - if(result[5].matched) - { - content.m_fragment = result[5]; - } - if(content.m_query.size()) - { - parse_uri_query(content.m_query, content.m_query_params); - } - return true; - } - - - inline - bool parse_url(const std::string url_str, http::url_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - //STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal); - // 12 34 5 6 7 - content.port = 0; - boost::smatch result; - if(!boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched) - { - LOG_PRINT_L0("[PARSE URI] regex not matched for uri: " << rexp_match_uri); - //content.m_path = uri; - return true; - } - if(result[2].matched) - { - content.schema = result[2]; - } - if(result[4].matched) - { - content.host = result[4]; - } - if(result[6].matched) - { - content.port = boost::lexical_cast(result[6]); - } - if(result[7].matched) - { - content.uri = result[7]; - return parse_uri(result[7], content.m_uri_content); - } - - return true; - } - -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h deleted file mode 100644 index b0e44f5d..00000000 --- a/contrib/epee/include/net/net_utils_base.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _NET_UTILS_BASE_H_ -#define _NET_UTILS_BASE_H_ - -#include -#include "string_tools.h" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace boost { - namespace asio { - class io_service; - } -} - -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct connection_context_base - { - const boost::uuids::uuid m_connection_id; - const uint32_t m_remote_ip; - const uint32_t m_remote_port; - const bool m_is_income; - const time_t m_started; - time_t m_last_recv; - time_t m_last_send; - uint64_t m_recv_cnt; - uint64_t m_send_cnt; - - connection_context_base(boost::uuids::uuid connection_id, - long remote_ip, int remote_port, bool is_income, - time_t last_recv = 0, time_t last_send = 0, - uint64_t recv_cnt = 0, uint64_t send_cnt = 0): - m_connection_id(connection_id), - m_remote_ip(remote_ip), - m_remote_port(remote_port), - m_is_income(is_income), - m_started(time(NULL)), - m_last_recv(last_recv), - m_last_send(last_send), - m_recv_cnt(recv_cnt), - m_send_cnt(send_cnt) - {} - - connection_context_base(): m_connection_id(), - m_remote_ip(0), - m_remote_port(0), - m_is_income(false), - m_started(time(NULL)), - m_last_recv(0), - m_last_send(0), - m_recv_cnt(0), - m_send_cnt(0) - {} - - connection_context_base& operator=(const connection_context_base& a) - { - set_details(a.m_connection_id, a.m_remote_ip, a.m_remote_port, a.m_is_income); - return *this; - } - - private: - template - friend class connection; - void set_details(boost::uuids::uuid connection_id, long remote_ip, int remote_port, bool is_income) - { - this->~connection_context_base(); - new(this) connection_context_base(connection_id, remote_ip, remote_port, is_income); - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb)=0; - virtual bool close()=0; - virtual bool call_run_once_service_io()=0; - virtual bool request_callback()=0; - virtual boost::asio::io_service& get_io_service()=0; - //protect from deletion connection object(with protocol instance) during external call "invoke" - virtual bool add_ref()=0; - virtual bool release()=0; - protected: - virtual ~i_service_endpoint(){} - }; - - - //some helpers - - - inline - std::string print_connection_context(const connection_context_base& ctx) - { - std::stringstream ss; - ss << epee::string_tools::get_ip_string_from_int32(ctx.m_remote_ip) << ":" << ctx.m_remote_port << " " << epee::string_tools::get_str_from_guid_a(ctx.m_connection_id) << (ctx.m_is_income ? " INC":" OUT"); - return ss.str(); - } - - inline - std::string print_connection_context_short(const connection_context_base& ctx) - { - std::stringstream ss; - ss << epee::string_tools::get_ip_string_from_int32(ctx.m_remote_ip) << ":" << ctx.m_remote_port << (ctx.m_is_income ? " INC":" OUT"); - return ss.str(); - } - -#define LOG_PRINT_CC(ct, message, log_level) LOG_PRINT("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_GREEN(ct, message, log_level) LOG_PRINT_GREEN("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_RED(ct, message, log_level) LOG_PRINT_RED("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_BLUE(ct, message, log_level) LOG_PRINT_BLUE("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_YELLOW(ct, message, log_level) LOG_PRINT_YELLOW("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_CYAN(ct, message, log_level) LOG_PRINT_CYAN("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_PRINT_CC_MAGENTA(ct, message, log_level) LOG_PRINT_MAGENTA("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message, log_level) -#define LOG_ERROR_CC(ct, message) LOG_ERROR("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) - -#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) -#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) -#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) -#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) -#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4("[" << epee::net_utils::print_connection_context_short(ct) << "]" << message) - -#define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message) -#define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message) -#define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message) -#define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message) -#define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message) - -#define LOG_PRINT_CCONTEXT_GREEN(message, log_level) LOG_PRINT_CC_GREEN(context, message, log_level) -#define LOG_PRINT_CCONTEXT_RED(message, log_level) LOG_PRINT_CC_RED(context, message, log_level) -#define LOG_PRINT_CCONTEXT_BLUE(message, log_level) LOG_PRINT_CC_BLUE(context, message, log_level) -#define LOG_PRINT_CCONTEXT_YELLOW(message, log_level) LOG_PRINT_CC_YELLOW(context, message, log_level) -#define LOG_PRINT_CCONTEXT_CYAN(message, log_level) LOG_PRINT_CC_CYAN(context, message, log_level) -#define LOG_PRINT_CCONTEXT_MAGENTA(message, log_level) LOG_PRINT_CC_MAGENTA(context, message, log_level) - -#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message) - -} -} - -#endif //_NET_UTILS_BASE_H_ diff --git a/contrib/epee/include/net/protocol_switcher.h b/contrib/epee/include/net/protocol_switcher.h deleted file mode 100644 index ca0ce6f9..00000000 --- a/contrib/epee/include/net/protocol_switcher.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _PROTOCOL_SWITCHER_H_ -#define _PROTOCOL_SWITCHER_H_ - -#include "levin_base.h" -#include "http_server.h" -#include "levin_protocol_handler.h" -//#include "abstract_tcp_server.h" - -namespace epee -{ -namespace net_utils -{ - struct protocl_switcher_config - { - http::http_custom_handler::config_type m_http_config; - levin::protocol_handler::config_type m_levin_config; - }; - - - struct i_protocol_handler - { - virtual bool handle_recv(const void* ptr, size_t cb)=0; - }; - - template - class t_protocol_handler: public i_protocol_handler - { - public: - typedef t t_type; - t_protocol_handler(i_service_endpoint* psnd_hndlr, typename t_type::config_type& config, const connection_context& conn_context):m_hadler(psnd_hndlr, config, conn_context) - {} - private: - bool handle_recv(const void* ptr, size_t cb) - { - return m_hadler.handle_recv(ptr, cb); - } - t_type m_hadler; - }; - - - class protocol_switcher - { - public: - typedef protocl_switcher_config config_type; - - protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context); - virtual ~protocol_switcher(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - t_protocol_handler m_http_handler; - t_protocol_handler m_levin_handler; - i_protocol_handler* pcurrent_handler; - - std::string m_cached_buff; - }; - - protocol_switcher::protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context):m_http_handler(psnd_hndlr, config.m_http_config, conn_context), m_levin_handler(psnd_hndlr, config.m_levin_config, conn_context), pcurrent_handler(NULL) - {} - - bool protocol_switcher::handle_recv(const void* ptr, size_t cb) - { - if(pcurrent_handler) - return pcurrent_handler->handle_recv(ptr, cb); - else - { - m_cached_buff.append((const char*)ptr, cb); - if(m_cached_buff.size() < sizeof(uint64_t)) - return true; - - if(*((uint64_t*)&m_cached_buff[0]) == LEVIN_SIGNATURE) - { - pcurrent_handler = &m_levin_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - } - if(m_cached_buff.substr(0, 4) == "GET " || m_cached_buff.substr(0, 4) == "POST") - { - pcurrent_handler = &m_http_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - }else - { - LOG_ERROR("Wrong protocol accepted on port..."); - return false; - } - } - - return true; - } -} -} -#endif //_PROTOCOL_SWITCHER_H_ \ No newline at end of file diff --git a/contrib/epee/include/net/rpc_method_name.h b/contrib/epee/include/net/rpc_method_name.h deleted file mode 100644 index c226639c..00000000 --- a/contrib/epee/include/net/rpc_method_name.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - - -#define RPC_METHOD_NAME(name) static inline const char* methodname(){return name;} \ No newline at end of file diff --git a/contrib/epee/include/net/smtp.h b/contrib/epee/include/net/smtp.h deleted file mode 100644 index d2e8598f..00000000 --- a/contrib/epee/include/net/smtp.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - using boost::asio::ip::tcp; - using namespace boost::archive::iterators; - typedef base64_from_binary > base64_text; - - /************************************************************************/ - /* */ - /************************************************************************/ - class smtp_client - { - public: - smtp_client(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword): - mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService) - { - tcp::resolver::query qry(mServer,boost::lexical_cast( mPort )); - mResolver.async_resolve(qry,boost::bind(&smtp_client::handleResolve,this,boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); - } - bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage) - { - mHasError = true; - mFrom=pFrom; - mTo=pTo; - mSubject=pSubject; - mMessage=pMessage; - mIOService.run(); - return !mHasError; - } - private: - std::string encodeBase64(std::string pData) - { - std::stringstream os; - size_t sz=pData.size(); - std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),std::ostream_iterator(os)); - return os.str(); - } - void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if(!err) - { - tcp::endpoint endpoint=*endpoint_iterator; - mSocket.async_connect(endpoint, - boost::bind(&smtp_client::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator)); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - void writeLine(std::string pData) - { - std::ostream req_strm(&mRequest); - req_strm << pData << "\r\n"; - boost::asio::write(mSocket,mRequest); - req_strm.clear(); - } - void readLine(std::string& pData) - { - boost::asio::streambuf response; - boost::asio::read_until(mSocket, response, "\r\n"); - std::istream response_stream(&response); - response_stream >> pData; - } - void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if (!err) - { - std::string read_buff; - // The connection was successful. Send the request. - std::ostream req_strm(&mRequest); - writeLine("EHLO "+mServer); - readLine(read_buff);//220 - writeLine("AUTH LOGIN"); - readLine(read_buff);// - writeLine(encodeBase64(mUserName)); - readLine(read_buff); - writeLine(encodeBase64(mPassword)); - readLine(read_buff); - writeLine( "MAIL FROM:<"+mFrom+">"); - writeLine( "RCPT TO:<"+mTo+">"); - writeLine( "DATA"); - writeLine( "SUBJECT:"+mSubject); - writeLine( "From:"+mFrom); - writeLine( "To:"+mTo); - writeLine( ""); - writeLine( mMessage ); - writeLine( "\r\n.\r\n"); - readLine(read_buff); - if(read_buff == "250") - mHasError = false; - writeLine( "QUIT"); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - std::string mServer; - std::string mUserName; - std::string mPassword; - std::string mFrom; - std::string mTo; - std::string mSubject; - std::string mMessage; - unsigned int mPort; - boost::asio::io_service mIOService; - tcp::resolver mResolver; - tcp::socket mSocket; - boost::asio::streambuf mRequest; - boost::asio::streambuf mResponse; - bool mHasError; - std::string mErrorMsg; - }; - - - bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_email, /*"STIL CRAWLER",*/ - const std::string& maillist, const std::string& subject, const std::string& body) - { - STD_TRY_BEGIN(); - //smtp_client mailc("yoursmtpserver.com",25,"user@yourdomain.com","password"); - //mailc.Send("from@yourdomain.com","to@somewhere.com","subject","Hello from C++ SMTP Client!"); - smtp_client mailc(server,port,login,pass); - return mailc.Send(from_email,maillist,subject,body); - STD_TRY_CATCH("at send_mail", false); - } - - } -} -} - -//#include "smtp.inl" \ No newline at end of file diff --git a/contrib/epee/include/net/smtp.inl b/contrib/epee/include/net/smtp.inl deleted file mode 100644 index d42c8b95..00000000 --- a/contrib/epee/include/net/smtp.inl +++ /dev/null @@ -1,1569 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "md5.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - - ////////////////////////////////////////////////////////////////////////// - inline char * convert_hex( unsigned char *in, int len ) - { - static char hex[] = "0123456789abcdef"; - char * out; - int i; - - out = (char *) malloc(len * 2 + 1); - if (out == NULL) - return NULL; - - for (i = 0; i < len; i++) { - out[i * 2] = hex[in[i] >> 4]; - out[i * 2 + 1] = hex[in[i] & 15]; - } - - out[i*2] = 0; - - return out; - } - - ////////////////////////////////////////////////////////////////////////// - inline char * hash_md5(const char * sec_key, const char * data, int len) - { - char key[65], digest[24]; - char * hash_hex; - - int sec_len, i; - - sec_len = strlen(sec_key); - - if (sec_len < 64) { - memcpy(key, sec_key, sec_len); - for (i = sec_len; i < 64; i++) { - key[i] = 0; - } - } else { - memcpy(key, sec_key, 64); - } - - md5::hmac_md5( (const unsigned char*)data, len, (const unsigned char*)key, 64, (unsigned char*)digest ); - hash_hex = convert_hex( (unsigned char*)digest, 16 ); - - return hash_hex; - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::CSMTPClient(void) - { - m_dwSupportedAuthModesCount = 0; - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - m_pErrorText = NULL; - - // Initialize WinSock - WORD wVer = MAKEWORD( 2, 2 ); - if ( WSAStartup( wVer, &m_wsaData ) != NO_ERROR ) - { - SetErrorText( "WSAStartup.", WSAGetLastError() ); - throw; - } - if ( LOBYTE( m_wsaData.wVersion ) != 2 || HIBYTE( m_wsaData.wVersion ) != 2 ) - { - SetErrorText( "Can't find a useable WinSock DLL." ); - WSACleanup(); - throw; - } - } - - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::~CSMTPClient(void) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - if ( m_bConnected ) - ServerDisconnect(); - - // Cleanup - WSACleanup(); - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::SetErrorText( LPCSTR szErrorText, DWORD dwErrorCode ) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - LPVOID lpMsgBuf = NULL; - if ( dwErrorCode ) - { - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &lpMsgBuf, - 0, NULL ); - } - - if ( szErrorText && strlen( szErrorText ) ) - { - m_pErrorText = (LPBYTE)malloc( strlen( szErrorText ) + 1 ); - strcpy( (char*)m_pErrorText, szErrorText ); - - if ( lpMsgBuf ) - { - strcat( (char*)m_pErrorText, " " ); - strcpy( (char*)m_pErrorText, (char*)lpMsgBuf ); - - LocalFree( lpMsgBuf ); - } - } - } - - inline void CSMTPClient::SetErrorText( PBYTE szErrorText, DWORD dwErrorCode ) - { - SetErrorText( (LPCSTR)szErrorText, dwErrorCode ); - } - - ////////////////////////////////////////////////////////////////////////// - inline char* CSMTPClient::GetLastErrorText() - { - return (char*)m_pErrorText; - } - - ////////////////////////////////////////////////////////////////////////// - inline DWORD CSMTPClient::ReceiveData( SOCKET hSocket, PBYTE pReceiveBuffer, DWORD dwReceiveBufferSize ) - { - DWORD dwReceivedDataSize = 0; - - if ( hSocket != INVALID_SOCKET && pReceiveBuffer && dwReceiveBufferSize ) - { - int iReceived = 0; - int iLength = 0; - - iLength = recv( hSocket, (LPSTR)pReceiveBuffer + iReceived, dwReceiveBufferSize - iReceived, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iReceived += iLength; - - dwReceivedDataSize = iReceived; - - pReceiveBuffer[ iReceived ] = 0; - } - - return dwReceivedDataSize; - } - - inline ////////////////////////////////////////////////////////////////////////// - DWORD CSMTPClient::SendData( SOCKET hSocket, PBYTE pSendBuffer, DWORD dwSendBufferSize ) - { - DWORD dwSended = 0; - - if ( hSocket != INVALID_SOCKET && pSendBuffer && dwSendBufferSize ) - { - int iSended = 0; - int iLength = 0; - - while ( iLength != SOCKET_ERROR && dwSendBufferSize - iSended > 0 ) - { - iLength = send( hSocket, (LPSTR)pSendBuffer + iSended, dwSendBufferSize - iSended, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iSended += iLength; - } - - dwSended = iSended; - } - - //if ( dwSended ) - // printf( "C: %s", pSendBuffer ); - - return dwSended; - } - - ////////////////////////////////////////////////////////////////////////// - inline unsigned short CSMTPClient::GetResponseCode( LPBYTE pBuffer, DWORD dwBufferSize ) - { - unsigned short iCode = 0; - - if ( dwBufferSize >= 3 ) - { - CHAR szResponseCode[ 4 ] = { 0 }; - memcpy( szResponseCode, pBuffer, 3 ); - szResponseCode[ 3 ] = 0; - iCode = atoi( szResponseCode ); - } - - return iCode; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ParseESMTPExtensions( LPBYTE pBuffer, DWORD dwBufferSize ) - { - const char *szSubstring = strstr( (const char*)pBuffer, "250-AUTH " ); - if ( !szSubstring ) - { - szSubstring = strstr( (const char*)pBuffer, "250 AUTH " ); - } - - if ( szSubstring ) - { - const char *szSubstringEnd = strstr( (const char*)szSubstring, "\r\n" ); - if ( szSubstringEnd ) - { - szSubstring += 9; - char szAuthMode[ 256 ] = { 0 }; - for ( ; szSubstring < szSubstringEnd + 1 ; szSubstring++ ) - { - if ( *szSubstring == ' ' || *szSubstring == '\r' ) - { - if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_PLAIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_PLAIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_LOGIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_LOGIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_CRAM_MD5 ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_CRAM_MD5; - m_dwSupportedAuthModesCount++; - } - - szAuthMode[ 0 ] = 0; - - if ( m_dwSupportedAuthModesCount == MAX_AUTH_MODES_COUND ) - break; - } - else - { - szAuthMode[ strlen( szAuthMode ) + 1 ] = 0; - szAuthMode[ strlen( szAuthMode ) ] = *szSubstring; - } - } - } - } - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - if ( m_bConnected ) - ServerDisconnect(); - - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - - m_hSocket = _connectServerSocket( szServerAddress, iPortNumber ); - - if ( m_hSocket != INVALID_SOCKET ) - { - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 220 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 220 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error. ", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // EHLO / HELO - BYTE szHelloBuffer[ 256 ]; - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_EHLO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 500 ) - { - SetErrorText( pReceiveBuffer ); - - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_HELO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // Parse AUTH supported modes - ParseESMTPExtensions( pReceiveBuffer, iReceived ); - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - free( pReceiveBuffer ); - } - } - else - { - return FALSE; - } - - m_bConnected = TRUE; - - return TRUE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber, LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - bSuccess = ServerConnect( szServerAddress, iPortNumber ); - if ( bSuccess ) - { - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline SOCKET CSMTPClient::_connectServerSocket( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - int nConnect; - short nProtocolPort = iPortNumber; - LPHOSTENT lpHostEnt; - SOCKADDR_IN sockAddr; - - SOCKET hServerSocket = INVALID_SOCKET; - - lpHostEnt = gethostbyname( szServerAddress ); - if (lpHostEnt) - { - hServerSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (hServerSocket != INVALID_SOCKET) - { - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons( nProtocolPort ); - sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list); - - nConnect = connect( hServerSocket, (PSOCKADDR)&sockAddr, - sizeof(sockAddr) ); - - if ( nConnect != 0 ) - { - SetErrorText( "connect error.", WSAGetLastError() ); - hServerSocket = INVALID_SOCKET; - } - } - else - { - SetErrorText( "Invalid socket." ); - throw; - } - } - else - { - SetErrorText( "Error retrieving host by name.", WSAGetLastError() ); - } - - return hServerSocket ; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ServerDisconnect() - { - if ( m_hSocket != INVALID_SOCKET ) - { - if ( SendData( m_hSocket, (PBYTE)SMTP_COMMAND_QUIT, strlen( SMTP_COMMAND_QUIT ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - - if ( iReceived ) - SetErrorText( pReceiveBuffer ); - - free( pReceiveBuffer ); - } - - m_hSocket = INVALID_SOCKET; - } - - m_bConnected = FALSE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::GetAuthModeIsSupported( int iMode ) - { - BOOL bSupported = FALSE; - - for ( int i = 0 ; i < m_dwSupportedAuthModesCount ; i++ ) - { - if ( m_aSupportedAuthModes[ i ] == iMode ) - { - bSupported = TRUE; - break; - } - } - - return bSupported; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword, int iAuthMode ) - { - BOOL bSuccess = FALSE; - - if ( iAuthMode == AUTH_MODE_PLAIN ) - { - bSuccess = ServerLoginMethodPlain( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_LOGIN ) - { - bSuccess = ServerLoginMethodLogin( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_CRAM_MD5 ) - { - bSuccess = ServerLoginMethodCramMD5( szUsername, szPassword ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodPlain( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_PLAIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - // Encode. - DWORD dwLoginBuffer = strlen( szUsername ) + strlen( szPassword ) + 3; - char *pLoginBuffer = (char*)malloc( dwLoginBuffer ); - if ( pLoginBuffer ) - { - ZeroMemory( pLoginBuffer, dwLoginBuffer ); - strcpy( pLoginBuffer + 1, szUsername ); - strcpy( pLoginBuffer + 1 + strlen( szUsername ) + 1, szPassword ); - - Base64Coder coder; - coder.Encode( (const PBYTE)pLoginBuffer, dwLoginBuffer - 1 ); - LPCSTR szLoginBufferEncoded = coder.EncodedMessage(); - - if ( szLoginBufferEncoded && strlen( szLoginBufferEncoded ) > 0 ) - { - DWORD dwSendBufferSize = strlen( szLoginBufferEncoded ) + 4; - char* pSendBuffer = (char*)malloc( dwSendBufferSize ); - if ( pSendBuffer ) - { - strcpy( pSendBuffer, szLoginBufferEncoded ); - strcat( pSendBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)pSendBuffer, strlen( (const char*)pSendBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pSendBuffer ); - free( pLoginBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pSendBuffer ); - } - } - - free( pLoginBuffer ); - - // check result - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_LOGIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest = coder.DecodedMessage(); - if ( szRequest && strlen( szRequest ) > 0 ) - { - if ( strcmpi( szRequest, "Username:" ) == 0 ) - { - coder.Encode( (const PBYTE)szUsername, strlen( szUsername ) ); - LPCSTR szUsernameEncoded = coder.EncodedMessage(); - - char* szLoginUsernameBuffer = (char*)malloc( strlen( szUsernameEncoded ) + 4 ); - if ( szLoginUsernameBuffer ) - { - strcpy( szLoginUsernameBuffer, szUsernameEncoded ); - strcat( szLoginUsernameBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginUsernameBuffer, strlen( (const char*)szLoginUsernameBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginUsernameBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest2 = coder.DecodedMessage(); - if ( szRequest2 && strlen( szRequest2 ) > 0 ) - { - if ( strcmpi( szRequest2, "Password:" ) == 0 ) - { - coder.Encode( (const PBYTE)szPassword, strlen( szPassword ) ); - LPCSTR szPasswordEncoded = coder.EncodedMessage(); - - char* szLoginPasswordBuffer = (char*)malloc( strlen( szPasswordEncoded ) + 4 ); - if ( szLoginPasswordBuffer ) - { - strcpy( szLoginPasswordBuffer, szPasswordEncoded ); - strcat( szLoginPasswordBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginPasswordBuffer, strlen( (const char*)szLoginPasswordBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginPasswordBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodCramMD5( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_CRAM_MD5 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szResponse = coder.DecodedMessage(); - if ( szResponse && strlen( szResponse ) > 0 ) - { - char *auth_hex = hash_md5( szPassword, szResponse, strlen(szResponse) ); - if ( !auth_hex ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szCommand = (char*)malloc( strlen( szUsername ) + strlen( auth_hex ) + 5 ); - if ( szCommand ) - { - sprintf( szCommand, "%s %s", szUsername, auth_hex ); - - free( auth_hex ); - - coder.Encode( (const PBYTE)szCommand, strlen( szCommand ) ); - - free( szCommand ); - - LPCSTR szAuthEncoded = coder.EncodedMessage(); - if ( szAuthEncoded == NULL ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szAuthCommand = (char*)malloc( strlen( szAuthEncoded ) + 4 ); - if ( szAuthCommand ) - { - strcpy( szAuthCommand, szAuthEncoded ); - strcat( szAuthCommand, "\r\n" ); - - // Send auth data - if ( SendData( m_hSocket, (PBYTE)szAuthCommand, strlen( (const char*)szAuthCommand ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szAuthCommand ); - free( pReceiveBuffer ); - return FALSE; - } - - // Check response - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szAuthCommand ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( auth_hex ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc() failed.", GetLastError() ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::SendMessage( LPCSTR szFromAddress, LPCSTR szFromName, LPCSTR szToAddresses, LPCSTR szSubject, LPCSTR szXMailer, LPBYTE pBodyBuffer, DWORD dwBodySize ) - { - BOOL bSuccess = FALSE; - - // Format Header - if ( !szFromAddress ) - { - SetErrorText( "SendMessage. Invalid Parameters!" ); - return NULL; - } - - char *szHeaderBuffer = (char*)malloc( 1024 * 16 ); - if ( szHeaderBuffer ) - { - // get the current date and time - char szDate[ 500 ]; - char sztTime[ 500 ]; - - SYSTEMTIME st = { 0 }; - ::GetSystemTime(&st); - - ::GetDateFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &st, "ddd',' dd MMM yyyy", szDate , sizeof( szDate ) ); - ::GetTimeFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), TIME_FORCE24HOURFORMAT, &st, "HH':'mm':'ss", sztTime, sizeof( sztTime ) ); - - sprintf( szHeaderBuffer, "DATE: %s %s\r\n", szDate, sztTime ); - - // X-Mailer Field - if ( szXMailer && strlen( szXMailer ) ) - { - strcat( szHeaderBuffer, "X-Mailer: " ); - strcat( szHeaderBuffer, szXMailer ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // From: - strcat( szHeaderBuffer, "From: " ); - if ( szFromName ) - { - strcat( szHeaderBuffer, "\"" ); - strcat( szHeaderBuffer, szFromName ); - strcat( szHeaderBuffer, "\" <" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - else - { - strcat( szHeaderBuffer, "<" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - - // Subject: - if ( szSubject && strlen( szSubject ) ) - { - strcat( szHeaderBuffer, "Subject: " ); - strcat( szHeaderBuffer, szSubject ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // To Fields - strcat( szHeaderBuffer, "To: " ); - strcat( szHeaderBuffer, szToAddresses ); - strcat( szHeaderBuffer, "\r\n" ); - - // MIME - strcat( szHeaderBuffer, "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n" ); - - // End Header - strcat( szHeaderBuffer, "\r\n" ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - return FALSE; - } - - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "MAIL FROM:<%s> SIZE=%u\r\n", (char*)szFromAddress, strlen( szHeaderBuffer ) + dwBodySize + 2 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - // Post "RCTP TO:" - char *szCurrentAddr = (char*)malloc( strlen( szToAddresses ) + 1 ); - if ( !szCurrentAddr ) - { - SetErrorText( "malloc error.", GetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - const char* szToOffset = szToAddresses; - char* szZap = NULL; - - BOOL bRCPTAccepted = FALSE; - do - { - strcpy( szCurrentAddr, szToOffset ); - char *szExtractedAdress = szCurrentAddr; - szZap = strchr( szCurrentAddr, ',' ); - - if ( szZap ) - { - *szZap = 0; - szToOffset = szZap + 1; - } - - char *pSkobka1 = strchr( szCurrentAddr, '<' ); - char *pSkobka2 = strchr( szCurrentAddr, '>' ); - - if ( pSkobka1 && pSkobka2 && pSkobka2 > pSkobka1 ) - { - szExtractedAdress = pSkobka1 + 1; - *pSkobka2 = NULL; - } - - if ( szExtractedAdress && strlen( szExtractedAdress ) > 0 ) - { - sprintf( (char*)szCommandBuffer, "RCPT TO:<%s>\r\n", (char*)szExtractedAdress ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bRCPTAccepted = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - - } while( szZap ); - - free( szCurrentAddr ); - - if ( bRCPTAccepted ) - { - sprintf( (char*)szCommandBuffer, "DATA\r\n" ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 354 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 354 ) - { - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - // Send message data (header + body + .) - if ( SendData( m_hSocket, (PBYTE)szHeaderBuffer, strlen( (const char*)szHeaderBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)pBodyBuffer, dwBodySize ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)"\r\n.\r\n", 5 ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bSuccess = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - } - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - } - - if ( szHeaderBuffer ) - free( szHeaderBuffer ); - - return bSuccess; - } - - - - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - - -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif - -#ifndef ROUNDTOPAGE -#define ROUNDTOPAGE(a) (((a/4096)+1)*4096) -#endif - - ////////////////////////////////////////////////////////////////////// - // Construction/Destruction - ////////////////////////////////////////////////////////////////////// - - inline Base64Coder::Base64Coder() - : m_pDBuffer(NULL), - m_pEBuffer(NULL), - m_nDBufLen(0), - m_nEBufLen(0) - { - - } - - inline Base64Coder::~Base64Coder() - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - } - - inline LPCSTR Base64Coder::DecodedMessage() const - { - return (LPCSTR) m_pDBuffer; - } - - inline LPCSTR Base64Coder::EncodedMessage() const - { - return (LPCSTR) m_pEBuffer; - } - - inline void Base64Coder::AllocEncode(DWORD nSize) - { - if(m_nEBufLen < nSize) - { - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - - m_nEBufLen = ROUNDTOPAGE(nSize); - m_pEBuffer = new BYTE[m_nEBufLen]; - } - - ::ZeroMemory(m_pEBuffer, m_nEBufLen); - m_nEDataLen = 0; - } - - inline void Base64Coder::AllocDecode(DWORD nSize) - { - if(m_nDBufLen < nSize) - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - m_nDBufLen = ROUNDTOPAGE(nSize); - m_pDBuffer = new BYTE[m_nDBufLen]; - } - - ::ZeroMemory(m_pDBuffer, m_nDBufLen); - m_nDDataLen = 0; - } - - inline void Base64Coder::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - DWORD i = 0; - - AllocEncode(nBufLen); - while(i < nBufLen) - { - if(!_IsBadMimeChar(pBuffer[i])) - { - m_pEBuffer[m_nEDataLen] = pBuffer[i]; - m_nEDataLen++; - } - - i++; - } - } - - inline void Base64Coder::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - AllocDecode(nBufLen); - ::CopyMemory(m_pDBuffer, pBuffer, nBufLen); - m_nDDataLen = nBufLen; - } - - inline void Base64Coder::Encode(const PBYTE pBuffer, DWORD nBufLen) - { - SetDecodeBuffer(pBuffer, nBufLen); - AllocEncode(nBufLen * 2); - - TempBucket Raw; - DWORD nIndex = 0; - - while((nIndex + 3) <= nBufLen) - { - Raw.Clear(); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3); - Raw.nSize = 3; - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - nIndex += 3; - m_nEDataLen += 4; - } - - if(nBufLen > nIndex) - { - Raw.Clear(); - Raw.nSize = (BYTE) (nBufLen - nIndex); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex); - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - m_nEDataLen += 4; - } - } - - inline void Base64Coder::Encode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Encode((const PBYTE)szMessage, strlen( (const char*)szMessage)); - } - - inline void Base64Coder::Decode(const PBYTE pBuffer, DWORD dwBufLen) - { - if(is_init()) - _Init(); - - SetEncodeBuffer(pBuffer, dwBufLen); - - AllocDecode(dwBufLen); - - TempBucket Raw; - - DWORD nIndex = 0; - - while((nIndex + 4) <= m_nEDataLen) - { - Raw.Clear(); - Raw.nData[0] = DecodeTable()[m_pEBuffer[nIndex]]; - Raw.nData[1] = DecodeTable()[m_pEBuffer[nIndex + 1]]; - Raw.nData[2] = DecodeTable()[m_pEBuffer[nIndex + 2]]; - Raw.nData[3] = DecodeTable()[m_pEBuffer[nIndex + 3]]; - - if(Raw.nData[2] == 255) - Raw.nData[2] = 0; - if(Raw.nData[3] == 255) - Raw.nData[3] = 0; - - Raw.nSize = 4; - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - nIndex += 4; - m_nDDataLen += 3; - } - - // If nIndex < m_nEDataLen, then we got a decode message without padding. - // We may want to throw some kind of warning here, but we are still required - // to handle the decoding as if it was properly padded. - if(nIndex < m_nEDataLen) - { - Raw.Clear(); - for(DWORD i = nIndex; i < m_nEDataLen; i++) - { - Raw.nData[i - nIndex] = DecodeTable()[m_pEBuffer[i]]; - Raw.nSize++; - if(Raw.nData[i - nIndex] == 255) - Raw.nData[i - nIndex] = 0; - } - - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - m_nDDataLen += (m_nEDataLen - nIndex); - } - } - - inline void Base64Coder::Decode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Decode((const PBYTE)szMessage, strlen((const char*)szMessage)); - } - - inline DWORD Base64Coder::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - DWORD nCount = 0; - - _DecodeRaw(Data, Decode); - - for(int i = 0; i < 3; i++) - { - pBuffer[i] = Data.nData[i]; - if(pBuffer[i] != 255) - nCount++; - } - - return nCount; - } - - - inline void Base64Coder::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - - _EncodeRaw(Data, Decode); - - for(int i = 0; i < 4; i++) - pBuffer[i] = Base64Digits()[Data.nData[i]]; - - switch(Decode.nSize) - { - case 1: - pBuffer[2] = '='; - case 2: - pBuffer[3] = '='; - } - } - - inline void Base64Coder::_DecodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] <<= 2; - - nTemp = Decode.nData[1]; - nTemp >>= 4; - nTemp &= 0x03; - Data.nData[0] |= nTemp; - - Data.nData[1] = Decode.nData[1]; - Data.nData[1] <<= 4; - - nTemp = Decode.nData[2]; - nTemp >>= 2; - nTemp &= 0x0F; - Data.nData[1] |= nTemp; - - Data.nData[2] = Decode.nData[2]; - Data.nData[2] <<= 6; - nTemp = Decode.nData[3]; - nTemp &= 0x3F; - Data.nData[2] |= nTemp; - } - - inline void Base64Coder::_EncodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] >>= 2; - - Data.nData[1] = Decode.nData[0]; - Data.nData[1] <<= 4; - nTemp = Decode.nData[1]; - nTemp >>= 4; - Data.nData[1] |= nTemp; - Data.nData[1] &= 0x3F; - - Data.nData[2] = Decode.nData[1]; - Data.nData[2] <<= 2; - - nTemp = Decode.nData[2]; - nTemp >>= 6; - - Data.nData[2] |= nTemp; - Data.nData[2] &= 0x3F; - - Data.nData[3] = Decode.nData[2]; - Data.nData[3] &= 0x3F; - } - - inline BOOL Base64Coder::_IsBadMimeChar(BYTE nData) - { - switch(nData) - { - case '\r': case '\n': case '\t': case ' ' : - case '\b': case '\a': case '\f': case '\v': - return TRUE; - default: - return FALSE; - } - } - - inline void Base64Coder::_Init() - { // Initialize Decoding table. - - int i; - - for(i = 0; i < 256; i++) - DecodeTable()[i] = -2; - - for(i = 0; i < 64; i++) - { - DecodeTable()[Base64Digits()[i]] = i; - DecodeTable()[Base64Digits()[i]|0x80] = i; - } - - DecodeTable()['='] = -1; - DecodeTable()['='|0x80] = -1; - - is_init() = TRUE; - } - - - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/net/smtp_helper.h b/contrib/epee/include/net/smtp_helper.h deleted file mode 100644 index b8252e1c..00000000 --- a/contrib/epee/include/net/smtp_helper.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "smtp.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - inline bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_addres, const std::string& from_name, const std::string& maillist, const std::string& subject, const std::string& mail_body) - { - net_utils::smtp::CSMTPClient smtp; - - if ( !smtp.ServerConnect( server.c_str(), port ) ) - { - LOG_PRINT("Reporting: Failed to connect to server " << server <<":"<< port, LOG_LEVEL_0); - return false; - } - - if(login.size() && pass.size()) - { - if ( !smtp.ServerLogin( login.c_str(), pass.c_str()) ) - { - LOG_PRINT("Reporting: Failed to auth on server " << server <<":"<< port, LOG_LEVEL_0); - return false; - - } - } - - if ( !smtp.SendMessage( from_addres.c_str(), - from_name.c_str(), - maillist.c_str(), - subject.c_str(), - "bicycle-client", - (LPBYTE)mail_body.data(), - mail_body.size())) - { - char *szErrorText = smtp.GetLastErrorText(); - if ( szErrorText ) - { - LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0); - } - else - { - LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0); - } - return false; - } - - smtp.ServerDisconnect(); - - return true; - - - } - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/pragma_comp_defs.h b/contrib/epee/include/pragma_comp_defs.h deleted file mode 100644 index f4ef7057..00000000 --- a/contrib/epee/include/pragma_comp_defs.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#if defined(__GNUC__) - #define PRAGMA_WARNING_PUSH _Pragma("GCC diagnostic push") - #define PRAGMA_WARNING_POP _Pragma("GCC diagnostic pop") - #define PRAGMA_WARNING_DISABLE_VS(w) - #define PRAGMA_GCC(w) _Pragma(w) -#elif defined(_MSC_VER) - #define PRAGMA_WARNING_PUSH __pragma(warning( push )) - #define PRAGMA_WARNING_POP __pragma(warning( pop )) - #define PRAGMA_WARNING_DISABLE_VS(w) __pragma( warning ( disable: w )) - //#define PRAGMA_WARNING_DISABLE_GCC(w) - #define PRAGMA_GCC(w) -#endif diff --git a/contrib/epee/include/profile_tools.h b/contrib/epee/include/profile_tools.h deleted file mode 100644 index 49180c6a..00000000 --- a/contrib/epee/include/profile_tools.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _PROFILE_TOOLS_H_ -#define _PROFILE_TOOLS_H_ - -#include - -namespace epee -{ - -#ifdef ENABLE_PROFILING -#define PROFILE_FUNC(immortal_ptr_str) static profile_tools::local_call_account lcl_acc(immortal_ptr_str); \ - profile_tools::call_frame cf(lcl_acc); - -#define PROFILE_FUNC_SECOND(immortal_ptr_str) static profile_tools::local_call_account lcl_acc2(immortal_ptr_str); \ - profile_tools::call_frame cf2(lcl_acc2); - -#define PROFILE_FUNC_THIRD(immortal_ptr_str) static profile_tools::local_call_account lcl_acc3(immortal_ptr_str); \ - profile_tools::call_frame cf3(lcl_acc3); - -#define PROFILE_FUNC_ACC(acc) \ - profile_tools::call_frame cf(acc); - - -#else -#define PROFILE_FUNC(immortal_ptr_str) -#define PROFILE_FUNC_SECOND(immortal_ptr_str) -#define PROFILE_FUNC_THIRD(immortal_ptr_str) -#endif - -#define START_WAY_POINTS() uint64_t _____way_point_time = epee::misc_utils::get_tick_count(); -#define WAY_POINT(name) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} -#define WAY_POINT2(name, avrg_obj) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} - - -#define TIME_MEASURE_START(var_name) uint64_t var_name = epee::misc_utils::get_tick_count(); -#define TIME_MEASURE_FINISH(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; - -namespace profile_tools -{ - struct local_call_account - { - local_call_account(const char* pstr):m_count_of_call(0), m_summary_time_used(0),m_pname(pstr) - {} - ~local_call_account() - { - LOG_PRINT2("profile_details.log", "PROFILE "< - - -namespace epee -{ - class global_regexp_critical_section - { - private: - mutable critical_section regexp_lock; - public: - global_regexp_critical_section(){} - critical_section& get_lock()const {return regexp_lock;} - }; - - const static global_regexp_critical_section gregexplock; - -#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_1 = 0;\ - volatile uint32_t local_is_initialized_1 = regexp_initialized_1;\ - if(!local_is_initialized_1)\ - gregexplock.get_lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_1)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_1, 1);\ - gregexplock.get_lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_2(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_2 = 0;\ - volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\ - if(!local_is_initialized_2)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_2)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\ - gregexplock.get_lock().lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_3(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_3 = 0;\ - volatile uint32_t local_is_initialized_3 = regexp_initialized_3;\ - if(!local_is_initialized_3)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex var_name(xpr_text , reg_exp_flags);\ - if(!local_is_initialized_3)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_3, 1);\ - gregexplock.get_lock().lock().unlock();\ -} -} - -#endif //_REG_EXP_DEFINER_H_ diff --git a/contrib/epee/include/reg_utils.h b/contrib/epee/include/reg_utils.h deleted file mode 100644 index 22227a9b..00000000 --- a/contrib/epee/include/reg_utils.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _MUSC_UTILS_EX_H_ -#define _MUSC_UTILS_EX_H_ - -namespace epee -{ -namespace reg_utils -{ - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const T& valToSave, bool force_create = true) - { - HKEY hRegKey = 0; - DWORD dw = 0; - - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - if(force_create && (::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS) ) - return false; - - - DWORD val_type = (sizeof(valToSave) == sizeof(DWORD)) ? REG_DWORD:REG_BINARY; - - BOOL res = ::RegSetValueExA( hRegKey, pValName, 0, val_type, (LPBYTE)&valToSave, sizeof(valToSave)) == ERROR_SUCCESS; - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, T& valToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || (sizeof(valToSave) < lSize) ) - { - ::RegCloseKey(hRegKey); - return false; - } - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)&valToSave, &lSize); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegSetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& strToSave) - { - HKEY hRegKey = 0; - DWORD dw = 0; - DWORD res_ = 0; - if( (res_ = ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw)) != ERROR_SUCCESS ) - if( (res_= ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey)) != ERROR_SUCCESS ) - return false; - - DWORD valType = REG_SZ; - const char* pStr = strToSave.c_str(); - DWORD sizeOfStr = (DWORD)strToSave.size()+1; - LSTATUS res = ::RegSetValueExA(hRegKey, pValName, 0, valType, (LPBYTE)pStr, sizeOfStr); - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& strToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if((res = ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey)) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res) - { - - ::RegCloseKey(hRegKey); - return false; - } - char* pTmpStr = new char[lSize+2]; - memset(pTmpStr, 0, lSize+2); - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)pTmpStr, &lSize); - pTmpStr[lSize+1] = 0; //be happy ;) - strToSave = pTmpStr; - delete [] pTmpStr; - ::RegCloseKey(hRegKey); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.get(0), (DWORD)valToSave.get_size()); - - return ERROR_SUCCESS==res ? true:false; - } - //---------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hKey, const char* pValName, const std::string & valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.data(), (DWORD)valToSave.size()); - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - valToSave.release(); - return false; - } - if(valToSave.get_size() < lSize) - valToSave.alloc_buff(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.get(0), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegGetRAWValue(HKEY hKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - return false; - } - - valToSave.resize(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.data(), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveValue(HKEY hParentKey, const char* pValName) - { - //CHECK_AND_ASSERT(hParentKey&&pValName, false); - return ::RegDeleteValueA(hParentKey, pValName)==ERROR_SUCCESS ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveKey(HKEY hParentKey, const char* pKeyName) - { - //CHECK_AND_ASSERT(hParentKey&&pKeyName, false); - return ::RegDeleteKeyA(hParentKey, pKeyName)==ERROR_SUCCESS ? true:false; - } - -} -} -#endif //_MUSC_UTILS_EX_H_ diff --git a/contrib/epee/include/serialization/enableable.h b/contrib/epee/include/serialization/enableable.h deleted file mode 100644 index ab1d799e..00000000 --- a/contrib/epee/include/serialization/enableable.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace epee -{ - - template - struct enableable - { - t_obj v; - bool enabled; - - enableable() - : v(t_obj()), enabled(true) - { // construct from defaults - } - - enableable(const t_obj& _v) - : v(_v), enabled(true) - { // construct from specified values - } - - enableable(const enableable& _v) - : v(_v.v), enabled(_v.enabled) - { // construct from specified values - } - }; -} \ No newline at end of file diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h deleted file mode 100644 index bf2c8dac..00000000 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include "misc_log_ex.h" -#include "enableable.h" -#include "keyvalue_serialization_overloads.h" -#include "serialization/serialization.h" - -namespace epee -{ - /************************************************************************/ - /* Serialize map declarations */ - /************************************************************************/ -#define BEGIN_KV_SERIALIZE_MAP() \ -public: \ - template \ - bool store( t_storage& st, typename t_storage::hsection hparent_section = nullptr) const\ - {\ - return serialize_map(*this, st, hparent_section);\ - }\ - template \ - bool _load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ - {\ - return serialize_map(*this, stg, hparent_section);\ - }\ - template \ - bool load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ - {\ - try{\ - return serialize_map(*this, stg, hparent_section);\ - }\ - catch(const std::exception& err) \ - { \ - (void)(err); \ - LOG_ERROR("Exception on unserializing: " << err.what());\ - return false; \ - }\ - }\ - template \ - static bool serialize_map(this_type& this_ref, t_storage& stg, typename t_storage::hsection hparent_section) \ - { - -#define KV_SERIALIZE_N(varialble, val_name) \ - epee::serialization::selector::serialize(this_ref.varialble, stg, hparent_section, val_name); - -#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \ - epee::serialization::selector::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name); - -#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, val_name) \ - static_assert(std::is_pod::value, "t_type must be a POD type."); \ - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) - -#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \ - epee::serialization::selector::serialize_stl_container_pod_val_as_blob(this_ref.varialble, stg, hparent_section, val_name); - -#define END_KV_SERIALIZE_MAP() return true;} - -#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble) -#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble) -#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check -#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble) - -} - - - - diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h deleted file mode 100644 index d53f167f..00000000 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -#include -#include - -namespace epee -{ - namespace serialization - { - - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_val(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.set_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_val(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.get_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - std::string blob((const char *)&d, sizeof(d)); - return stg.set_value(pname, blob, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - std::string blob; - if(!stg.get_value(pname, blob, hparent_section)) - return false; - CHECK_AND_ASSERT_MES(blob.size() == sizeof(d), false, "unserialize_t_val_as_blob: size of " << typeid(t_type).name() << " = " << sizeof(t_type) << ", but stored blod size = " << blob.size() << ", value name = " << pname); - d = *(const t_type*)blob.data(); - return true; - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_obj(const serializible_type& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - CHECK_AND_ASSERT_MES(hchild_section, false, "serialize_t_obj: failed to open/create section " << pname); - return obj.store(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_obj(serializible_type& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - if(!hchild_section) return false; - return obj._load(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_obj(enableable& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!obj.enabled) - return true; - return serialize_t_obj(obj.v, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_obj(enableable& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - obj.enabled = false; - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - if(!hchild_section) return false; - obj.enabled = true; - return obj.v._load(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_t_val (const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!container.size()) return true; - typename stl_container::const_iterator it = container.begin(); - typename t_storage::harray hval_array = stg.insert_first_value(pname, *it, hparent_section); - CHECK_AND_ASSERT_MES(hval_array, false, "failed to insert first value to storage"); - it++; - for(;it!= container.end();it++) - stg.insert_next_value(hval_array, *it); - - return true; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_t_val(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - container.clear(); - typename stl_container::value_type exchange_val; - typename t_storage::harray hval_array = stg.get_first_value(pname, exchange_val, hparent_section); - if(!hval_array) return false; - container.push_back(std::move(exchange_val)); - while(stg.get_next_value(hval_array, exchange_val)) - container.push_back(std::move(exchange_val)); - return true; - }//-------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_pod_val_as_blob(const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!container.size()) return true; - typename stl_container::const_iterator it = container.begin(); - std::string mb; - mb.resize(sizeof(typename stl_container::value_type)*container.size()); - typename stl_container::value_type* p_elem = (typename stl_container::value_type*)mb.data(); - BOOST_FOREACH(const typename stl_container::value_type& v, container) - { - *p_elem = v; - p_elem++; - } - return stg.set_value(pname, mb, hparent_section); - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_pod_val_as_blob(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - container.clear(); - std::string buff; - bool res = stg.get_value(pname, buff, hparent_section); - if(res) - { - size_t loaded_size = buff.size(); - typename stl_container::value_type* pelem = (typename stl_container::value_type*)buff.data(); - CHECK_AND_ASSERT_MES(!(loaded_size%sizeof(typename stl_container::value_type)), - false, - "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type)); - size_t count = (loaded_size/sizeof(typename stl_container::value_type)); - for(size_t i = 0; i < count; i++) - container.push_back(*(pelem++)); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_t_obj (const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - bool res = false; - if(!container.size()) return true; - typename stl_container::const_iterator it = container.begin(); - typename t_storage::hsection hchild_section = nullptr; - typename t_storage::harray hsec_array = stg.insert_first_section(pname, hchild_section, hparent_section); - CHECK_AND_ASSERT_MES(hsec_array && hchild_section, false, "failed to insert first section with section name " << pname); - res = it->store(stg, hchild_section); - it++; - for(;it!= container.end();it++) - { - stg.insert_next_section(hsec_array, hchild_section); - res |= it->store(stg, hchild_section); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_t_obj(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - bool res = false; - container.clear(); - typename stl_container::value_type val = typename stl_container::value_type(); - typename t_storage::hsection hchild_section = nullptr; - typename t_storage::harray hsec_array = stg.get_first_section(pname, hchild_section, hparent_section); - if(!hsec_array || !hchild_section) return false; - res = val._load(stg, hchild_section); - container.push_back(val); - while(stg.get_next_section(hsec_array, hchild_section)) - { - typename stl_container::value_type val_l = typename stl_container::value_type(); - res |= val_l._load(stg, hchild_section); - container.push_back(std::move(val_l)); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - struct kv_serialization_overloads_impl_is_base_serializable_types; - - template<> - struct kv_serialization_overloads_impl_is_base_serializable_types - { - template - static bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.set_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.get_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - }; - template<> - struct kv_serialization_overloads_impl_is_base_serializable_types - { - template - static bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_t_obj(d, stg, hparent_section, pname); - } - - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - }; - template - struct base_serializable_types: public boost::mpl::vector::type - {}; - //------------------------------------------------------------------------------------------------------------------- - template struct selector; - template<> - struct selector - { - template - static bool serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialize(d, stg, hparent_section, pname); - } - - template - static bool serialize_stl_container_pod_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::serialize_stl_container_pod_val_as_blob(d, stg, hparent_section, pname); - } - - template - static bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::serialize_t_val_as_blob(d, stg, hparent_section, pname); - } - - - }; - template<> - struct selector - { - template - static bool serialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_unserialize(d, stg, hparent_section, pname); - } - template - static bool serialize_stl_container_pod_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::unserialize_stl_container_pod_val_as_blob(d, stg, hparent_section, pname); - } - - template - static bool serialize_t_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::unserialize_t_val_as_blob(d, stg, hparent_section, pname); - } - }; - - template - bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - } -} diff --git a/contrib/epee/include/serialization/serialize_base.h b/contrib/epee/include/serialization/serialize_base.h deleted file mode 100644 index 84a1624c..00000000 --- a/contrib/epee/include/serialization/serialize_base.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once - diff --git a/contrib/epee/include/service_impl_base.h b/contrib/epee/include/service_impl_base.h deleted file mode 100644 index 6e9aefc4..00000000 --- a/contrib/epee/include/service_impl_base.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _SERVICE_IMPL_BASE_H_ -#define _SERVICE_IMPL_BASE_H_ - -#pragma comment(lib, "advapi32.lib") - - -namespace epee -{ -class service_impl_base { - public: - service_impl_base(); - virtual ~service_impl_base(); - - virtual const char *get_name() = 0; - virtual const char *get_caption() = 0; - virtual const char *get_description() = 0; - - bool run_service(); - virtual bool install(); - virtual bool remove(); - virtual bool init(); - void set_control_accepted(unsigned controls); - void set_status(unsigned state, unsigned pending = 0); - unsigned get_control_accepted(); - - private: - virtual void service_main() = 0; - virtual unsigned service_handler(unsigned control, unsigned event_code, - void *pdata) = 0; - //------------------------------------------------------------------------- - static service_impl_base*& instance(); - //------------------------------------------------------------------------- - static DWORD __stdcall _service_handler(DWORD control, DWORD event, - void *pdata, void *pcontext); - static void __stdcall service_entry(DWORD argc, char **pargs); - virtual SERVICE_FAILURE_ACTIONSA* get_failure_actions(); - - private: - SC_HANDLE m_manager; - SC_HANDLE m_service; - SERVICE_STATUS_HANDLE m_status_handle; - DWORD m_accepted_control; -}; - -inline service_impl_base::service_impl_base() { - m_manager = 0; - m_service = 0; - m_status_handle = 0; - m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN - | SERVICE_ACCEPT_PAUSE_CONTINUE; - - instance() = this; -} -//----------------------------------------------------------------------------- -inline service_impl_base::~service_impl_base() { - if (m_service) { - ::CloseServiceHandle(m_service); - } - m_service = 0; - if (m_manager) { - ::CloseServiceHandle(m_manager); - } - m_manager = 0; - instance() = 0; -} -//----------------------------------------------------------------------------- -inline service_impl_base*& service_impl_base::instance() { - static service_impl_base *pservice = NULL; - return pservice; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::install() { - CHECK_AND_ASSERT(!m_service, false); - const char *psz_descr = get_description(); - SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions(); - - char sz_path[MAX_PATH]; - ::GetModuleFileNameA(0, sz_path, sizeof(sz_path)); - ::GetShortPathNameA(sz_path, sz_path, sizeof(sz_path)); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - m_service = ::CreateServiceA(m_manager, get_name(), get_caption(), - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, - SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to CreateService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - if (psz_descr) { - SERVICE_DESCRIPTIONA sd = { (char*) psz_descr }; - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION, - &sd)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (fail_acts) { - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS, - fail_acts)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - LOG_PRINT("Installed succesfully.", LOG_LEVEL_0); - return true; - } - LOG_PRINT("Failed to install.", LOG_LEVEL_0); - return false; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::remove() { - CHECK_AND_ASSERT(!m_service, false); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(0, 0, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!m_service) { - m_service = ::OpenServiceA(m_manager, get_name(), SERVICE_STOP | DELETE); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - SERVICE_STATUS status = { }; - if (!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) { - int err = ::GetLastError(); - if (err == ERROR_SHUTDOWN_IN_PROGRESS) - continue; - else if (err != ERROR_SERVICE_NOT_ACTIVE) { - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!::DeleteService(m_service)) { - int err = ::GetLastError(); - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - LOG_PRINT("Removed successfully.", LOG_LEVEL_0); - break; - } - - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::init() { - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::run_service() { - CHECK_AND_ASSERT(!m_service, false); - - long error_code = 0; - - SERVICE_TABLE_ENTRYA service_table[2]; - ZeroMemory(&service_table, sizeof(service_table)); - - service_table->lpServiceName = (char*) get_name(); - service_table->lpServiceProc = service_entry; - - LOG_PRINT("[+] Start service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - - error_code = 1; - BOOL res = ::StartServiceCtrlDispatcherA(service_table); - if (!res) { - int err = GetLastError(); - LOG_PRINT( - "[+] Error starting service control dispatcher, err=" - << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - return false; - } else { - LOG_PRINT("[+] End service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - } - return true; -} -//----------------------------------------------------------------------------- -inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, - DWORD event, void *pdata, void *pcontext) { - CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); - - service_impl_base *pservice = (service_impl_base*) pcontext; - return pservice->service_handler(control, event, pdata); -} -//----------------------------------------------------------------------------- -inline -void __stdcall service_impl_base::service_entry(DWORD argc, char **pargs) { - service_impl_base *pme = instance(); - LOG_PRINT("instance: " << pme, LOG_LEVEL_4); - if (!pme) { - LOG_ERROR("Error: at service_entry() pme = NULL"); - return; - } - pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(), - _service_handler, pme); - - pme->set_status(SERVICE_RUNNING); - pme->service_main(); - pme->set_status(SERVICE_STOPPED); -} -//----------------------------------------------------------------------------- -inline -void service_impl_base::set_status(unsigned state, unsigned pending) { - if (!m_status_handle) - return; - - SERVICE_STATUS status = { 0 }; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - status.dwCurrentState = state; - status.dwControlsAccepted = m_accepted_control; - /*status.dwWin32ExitCode = NO_ERROR; - status.dwServiceSpecificExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - status.dwCheckPoint = 0; - status.dwWaitHint = 0; - - status.dwCurrentState = state;*/ - - if (state == SERVICE_START_PENDING || state == SERVICE_STOP_PENDING - || state == SERVICE_CONTINUE_PENDING || state == SERVICE_PAUSE_PENDING) { - status.dwWaitHint = 2000; - status.dwCheckPoint = pending; - } - ::SetServiceStatus(m_status_handle, &status); -} -//----------------------------------------------------------------------------------------- -inline -void service_impl_base::set_control_accepted(unsigned controls) { - m_accepted_control = controls; -} -//----------------------------------------------------------------------------------------- -inline -unsigned service_impl_base::get_control_accepted() { - return m_accepted_control; -} -//----------------------------------------------------------------------------------------- -inline SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() { - // first 3 failures in 30 minutes. Service will be restarted. - // do nothing for next failures - static SC_ACTION sa[] = { { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_RESTART, 3 * 1000 }, { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_NONE, 0 } }; - - static SERVICE_FAILURE_ACTIONSA sfa = { 1800, // interval for failures counter - 30 min - "", NULL, 4, (SC_ACTION*) &sa }; - - // TODO: refactor this code, really unsafe! - return &sfa; -} -} - -#endif //_SERVICE_IMPL_BASE_H_ diff --git a/contrib/epee/include/sha1.h b/contrib/epee/include/sha1.h deleted file mode 100644 index ce42082f..00000000 --- a/contrib/epee/include/sha1.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SHA1_DEFINED -#define SHA1_DEFINED - -namespace sha1 { - - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - void calc(const void* src, const int bytelength, unsigned char* hash); - - /** - @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. - @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. - */ - void toHexString(const unsigned char* hash, char* hexstring); - -} // namespace sha1 - -#include "sha1.inl" - -#endif // SHA1_DEFINED diff --git a/contrib/epee/include/sha1.inl b/contrib/epee/include/sha1.inl deleted file mode 100644 index d3320272..00000000 --- a/contrib/epee/include/sha1.inl +++ /dev/null @@ -1,179 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Contributors: - Gustav - Several members in the gamedev.se forum. - Gregory Petrosyan - */ - -#include "sha1.h" - -namespace sha1 { -namespace {// local -// Rotate an integer value to left. -inline const unsigned int rol(const unsigned int value, - const unsigned int steps) { - return ((value << steps) | (value >> (32 - steps))); -} - -// Sets the first 16 integers in the buffert to zero. -// Used for clearing the W buffert. -inline void clearWBuffert(unsigned int* buffert) { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } -} - -inline -void innerHash(unsigned int* result, unsigned int* w) { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; - - int round = 0; - -#define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } - - while (round < 16) { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } - -#undef sha1macro - - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; -} -} // namespace - -inline -void calc(const void* src, const int bytelength, unsigned char* hash) { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, - 0xc3d2e1f0 }; - - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; - - // The reusable round buffer - unsigned int w[80]; - - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock(0); - - while (currentBlock <= endOfFullBlocks) { - endCurrentBlock = currentBlock + 64; - - // Init the round buffer with the 64 byte block data. - for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) - { - // This line will swap endian on big endian and keep endian on little endian. - w[roundPos++] = (unsigned int) sarray[currentBlock + 3] - | (((unsigned int) sarray[currentBlock + 2]) << 8) - | (((unsigned int) sarray[currentBlock + 1]) << 16) - | (((unsigned int) sarray[currentBlock]) << 24); - } - innerHash(result, w); - } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (; lastBlockBytes < endCurrentBlock; ++lastBlockBytes) { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes - + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) - & 0xff; - } -} -inline -void toHexString(const unsigned char* hash, char* hexstring) { - const char hexDigits[] = { "0123456789abcdef" }; - - for (int hashByte = 20; --hashByte >= 0;) - { - hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf]; - hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf]; - } - hexstring[40] = 0; -} -} // namespace sha1 diff --git a/contrib/epee/include/soci_helper.h b/contrib/epee/include/soci_helper.h deleted file mode 100644 index 813edc1f..00000000 --- a/contrib/epee/include/soci_helper.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "soci.h" -#include "soci-postgresql.h" - -using namespace epee; -namespace soci -{ - - template <> - struct type_conversion - { - typedef long long base_type; - - static void from_base(base_type a_, indicator ind, uint64_t & mi) - { - if (ind == i_null) - { - mi = 0; - //throw soci_error("Null value not allowed for this type"); - } - mi = (uint64_t)a_; - //mi.set(i); - } - - static void to_base(const uint64_t & mi, base_type & i, indicator & ind) - { - i = (base_type)mi; - ind = i_ok; - } - }; - - - - template <> - struct type_conversion - { - typedef int base_type; - - static void from_base(base_type a_, indicator ind, bool& mi) - { - if (ind == i_null) - { - mi = false; - //throw soci_error("Null value not allowed for this type"); - } - mi = a_? true:false; - //mi.set(i); - } - - static void to_base(const bool & mi, base_type & i, indicator & ind) - { - i = mi? 1:0; - ind = i_ok; - } - }; - - - - class per_thread_session - { - public: - bool init(const std::string& connection_string) - { - m_connection_string = connection_string; - - return true; - } - - soci::session& get() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[epee::misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - //init new connection - return *conn_ptr.get(); - } - - bool reopen() - { - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(conn_ptr.get()) - { - conn_ptr->close(); - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - - //init new connection - return true; - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - return true; - } - - protected: - private: - std::map > m_db_connections; - epee::critical_section m_db_connections_lock; - std::string m_connection_string; - }; -} -/*}*/ \ No newline at end of file diff --git a/contrib/epee/include/static_initializer.h b/contrib/epee/include/static_initializer.h deleted file mode 100644 index 1510805c..00000000 --- a/contrib/epee/include/static_initializer.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _STATIC_INITIALIZER_H_ -#define _STATIC_INITIALIZER_H_ - - -namespace epee -{ -/*********************************************************************** -class initializer - useful to initialize some static classes - which have init() and un_init() static members -************************************************************************/ - -template -class initializer -{ -public: - initializer() - { - to_initialize::init(); - } - ~initializer() - { - to_initialize::un_init(); - } -}; - -} -#endif //_STATIC_INITIALIZER_H_ diff --git a/contrib/epee/include/storages/activity_notifier.h b/contrib/epee/include/storages/activity_notifier.h deleted file mode 100644 index 14b6ebbf..00000000 --- a/contrib/epee/include/storages/activity_notifier.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "inmemtoxml.h" - -//#include "levin/levin_server.h" - -namespace epee -{ - -class activity_printer_base -{ -public: - activity_printer_base(){} - virtual ~activity_printer_base(){} -}; - -template -class notify_activity_printer: public activity_printer_base -{ -public: - notify_activity_printer(int level, A& arg, bool is_notify_mode = true):m_ref_arg(arg), m_level(level), m_is_notify_mode(is_notify_mode) - { - m_command_name = typeid(m_ref_arg).name(); - m_command_name.erase(0, 7); - m_command_name.erase(m_command_name.size()-10, m_command_name.size()-1); - if(level == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(m_command_name, level); - } - else if(level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" -->>" << m_command_name, level); - } - else if(level+2 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" -->>" << m_command_name << "\n" << StorageNamed::xml::get_t_as_xml(m_ref_arg), level); - } - } - - virtual ~notify_activity_printer() - { - if(m_is_notify_mode) - { - if(m_level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name, m_level); - } - } - } -protected: - std::string m_command_name; - A& m_ref_arg; - int m_level; - bool m_is_notify_mode; -}; - -template -class command_activity_printer: public notify_activity_printer -{ -public: - command_activity_printer(int level, A& arg, R& rsp):notify_activity_printer(level, arg, false), m_ref_rsp(rsp) - { - } - - virtual ~command_activity_printer() - { - if(m_level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name, m_level); - } - else if(m_level+2 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name << "\n" << StorageNamed::trace_as_xml(m_ref_rsp), m_level); - } - } -private: - R& m_ref_rsp; -}; - -template -activity_printer_base* create_activity_printer(int level, A& arg, R& rsp) -{ - return new command_activity_printer(level, arg, rsp); -} - -template -activity_printer_base* create_activity_printer(int level, A& arg) -{ - return new notify_activity_printer(level, arg); -} - -} - -#define PRINT_COMMAND_ACTIVITY(level) boost::shared_ptr local_activity_printer(create_activity_printer(level, in_struct, out_struct)); -#define PRINT_NOTIFY_ACTIVITY(level) boost::shared_ptr local_activity_printer(create_activity_printer(level, in_struct)); - -#define PRINT_ACTIVITY(level) \ -{std::string some_str = typeid(in_struct).name(); \ - some_str.erase(0, 7); \ - some_str.erase(some_str.size()-10, some_str.size()-1); \ - LOG_PRINT(some_str, level);} - -} - diff --git a/contrib/epee/include/storages/crypted_storage.h b/contrib/epee/include/storages/crypted_storage.h deleted file mode 100644 index d6e6edcb..00000000 --- a/contrib/epee/include/storages/crypted_storage.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _CRYPTED_STORAGE_H_ -#define _CRYPTED_STORAGE_H_ - -#include "cryptopp_helper.h" - -namespace epee -{ -template -class crypted_storage: public t_base_storage -{ -public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!crypt_provider::encrypt(targetObj, t_key_provider::get_storage_default_key())) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_decrypt = pTargetObj; - if(crypt_provider::decrypt(buff_to_decrypt, t_key_provider::get_storage_default_key())) - return t_base_storage::LoadFromSolidBuffer(buff_to_decrypt); - - return 0; - } -}; -} - -#endif //_CRYPTED_STORAGE_H_ \ No newline at end of file diff --git a/contrib/epee/include/storages/gzipped_inmemstorage.h b/contrib/epee/include/storages/gzipped_inmemstorage.h deleted file mode 100644 index 5c53fffa..00000000 --- a/contrib/epee/include/storages/gzipped_inmemstorage.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _GZIPPED_INMEMSTORAGE_H_ -#define _GZIPPED_INMEMSTORAGE_H_ - -#include "zlib_helper.h" -namespace epee -{ -namespace StorageNamed -{ - - template - class gziped_storage: public t_base_storage - { - public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!zlib_helper::pack(targetObj)) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_ungzip = pTargetObj; - if(zlib_helper::unpack(buff_to_ungzip)) - return t_base_storage::LoadFromSolidBuffer(buff_to_ungzip); - - return 0; - } - - private: - }; - -} -} - -#endif \ No newline at end of file diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h deleted file mode 100644 index 00ee8a4a..00000000 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ /dev/null @@ -1,126 +0,0 @@ - -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "portable_storage_template_helper.h" -#include "net/http_base.h" -#include "net/http_server_handlers_map2.h" - -namespace epee -{ - namespace net_utils - { - template - bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - if(!serialization::store_t_to_json(out_struct, req_param)) - return false; - - const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return serialization::load_t_from_json(result_struct, pri->m_body); - } - - - - template - bool invoke_http_bin_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - if(!serialization::store_t_to_binary(out_struct, req_param)) - return false; - - const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return serialization::load_t_from_binary(result_struct, pri->m_body); - } - - template - bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { - epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); - req_t.jsonrpc = "2.0"; - req_t.id = req_id; - req_t.method = method_name; - req_t.params = out_struct; - epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); - if(!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) - { - return false; - } - if(resp_t.error.code || resp_t.error.message.size()) - { - LOG_ERROR("RPC call of \"" << method_name << "\" returned error: " << resp_t.error.code << ", message: " << resp_t.error.message); - return false; - } - result_struct = resp_t.result; - return true; - } - - template - bool invoke_http_json_rpc(const std::string& url, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { - return invoke_http_json_rpc(url, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id); - } - - } -} diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h deleted file mode 100644 index da12c106..00000000 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include "portable_storage_template_helper.h" -#include -#include "net/levin_base.h" - -namespace epee -{ - namespace net_utils - { - template - bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - - int res = transport.invoke(command, buff_to_send, buff_to_recv); - if( res <=0 ) - { - LOG_PRINT_RED("Failed to invoke command " << command << " return code " << res, LOG_LEVEL_1); - return false; - } - serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - return false; - } - result_struct.load(stg_ret); - return true; - } - - template - bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(&stg); - std::string buff_to_send; - stg.store_to_binary(buff_to_send); - - int res = transport.notify(command, buff_to_send); - if(res <=0 ) - { - LOG_ERROR("Failed to notify command " << command << " return code " << res); - return false; - } - return true; - } - - template - bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) - { - - typename serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - - int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id); - if( res <=0 ) - { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); - return false; - } - typename serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - return false; - } - result_struct.load(stg_ret); - - return true; - } - - template - bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport, callback_t cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - { - typename serialization::portable_storage stg; - const_cast(out_struct).store(stg);//TODO: add true const support to searilzation - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - - int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool - { - t_result result_struct = AUTO_VAL_INIT(result_struct); - if( code <=0 ) - { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code); - cb(code, result_struct, context); - return false; - } - serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - cb(LEVIN_ERROR_FORMAT, result_struct, context); - return false; - } - result_struct.load(stg_ret); - - cb(code, result_struct, context); - return true; - }, inv_timeout); - if( res <=0 ) - { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); - return false; - } - return true; - } - - template - bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport) - { - - serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - - int res = transport.notify(command, buff_to_send, conn_id); - if(res <=0 ) - { - LOG_PRINT_RED_L0("Failed to notify command " << command << " return code " << res); - return false; - } - return true; - } - //---------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------- - template - int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) - { - serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) - { - LOG_ERROR("Failed to load_from_binary in command " << command); - return -1; - } - boost::value_initialized in_struct; - boost::value_initialized out_struct; - - static_cast(in_struct).load(strg); - int res = cb(command, static_cast(in_struct), static_cast(out_struct), context); - serialization::portable_storage strg_out; - static_cast(out_struct).store(strg_out); - - if(!strg_out.store_to_binary(buff_out)) - { - LOG_ERROR("Failed to store_to_binary in command" << command); - return -1; - } - - return res; - }; - - template - int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) - { - serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) - { - LOG_ERROR("Failed to load_from_binary in notify " << command); - return -1; - } - boost::value_initialized in_struct; - static_cast(in_struct).load(strg); - return cb(command, in_struct, context); - }; - -#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ - { \ - bool handled = false; \ - return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ - int notify(int command, const std::string& in_buff, context_type& context) \ - { \ - bool handled = false; std::string fake_str;\ - return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ - } - - -#define CHAIN_LEVIN_INVOKE_MAP() \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ - { \ - bool handled = false; \ - return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_MAP() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ - { \ - bool handled = false; std::string fake_str;\ - return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_STUB() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ - { \ - return -1; \ - } - -#define BEGIN_INVOKE_MAP2(owner_type) \ - template int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ - { \ - typedef owner_type internal_owner_type_name; - -#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \ - if(!is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} - -#define HANDLE_INVOKE_T2(COMMAND, func) \ - if(!is_notify && COMMAND::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} - - -#define HANDLE_NOTIFY2(command_id, func, type_name_in) \ - if(is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} - -#define HANDLE_NOTIFY_T2(NOTIFY, func) \ - if(is_notify && NOTIFY::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} - - -#define CHAIN_INVOKE_MAP2(func) \ - { \ - int res = func(is_notify, command, in_buff, buff_out, context, handled); \ - if(handled) \ - return res; \ - } - -#define CHAIN_INVOKE_MAP_TO_OBJ2(obj) \ - { \ - int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, context, handled); \ - if(handled) \ - return res; \ - } - -#define CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(obj, context_type) \ - { \ - int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, static_cast(context), handled); \ - if(handled) return res; \ - } - - -#define END_INVOKE_MAP2() \ - LOG_ERROR("Unkonown command:" << command); \ - return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \ - } - } -} - diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h deleted file mode 100644 index baafb562..00000000 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -namespace epee -{ -namespace misc_utils -{ - namespace parse - { - inline std::string transform_to_escape_sequence(const std::string& src) - { - //std::stringstream res; - std::string res; - for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) - { - switch(*it) - { - case '\b': //Backspace (ascii code 08) - res+="\\b"; break; - case '\f': //Form feed (ascii code 0C) - res+="\\f"; break; - case '\n': //New line - res+="\\n"; break; - case '\r': //Carriage return - res+="\\r"; break; - case '\t': //Tab - res+="\\t"; break; - case '\v': //Vertical tab - res+="\\v"; break; - //case '\'': //Apostrophe or single quote - // res+="\\'"; break; - case '"': //Double quote - res+="\\\""; break; - case '\\': //Backslash caracter - res+="\\\\"; break; - case '/': //Backslash caracter - res+="\\/"; break; - default: - res.push_back(*it); - } - } - return res; - } - /* - - \b Backspace (ascii code 08) - \f Form feed (ascii code 0C) - \n New line - \r Carriage return - \t Tab - \v Vertical tab - \' Apostrophe or single quote - \" Double quote - \\ Backslash character - - */ - inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - bool escape_mode = false; - std::string::const_iterator it = star_end_string; - ++it; - for(;it != buf_end;it++) - { - if(escape_mode/*prev_ch == '\\'*/) - { - switch(*it) - { - case 'b': //Backspace (ascii code 08) - val.push_back(0x08);break; - case 'f': //Form feed (ascii code 0C) - val.push_back(0x0C);break; - case 'n': //New line - val.push_back('\n');break; - case 'r': //Carriage return - val.push_back('\r');break; - case 't': //Tab - val.push_back('\t');break; - case 'v': //Vertical tab - val.push_back('\v');break; - case '\'': //Apostrophe or single quote - val.push_back('\'');break; - case '"': //Double quote - val.push_back('"');break; - case '\\': //Backslash character - val.push_back('\\');break; - case '/': //Slash character - val.push_back('/');break; - default: - val.push_back(*it); - LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\""); - } - escape_mode = false; - }else if(*it == '"') - { - star_end_string = it; - return; - }else if(*it == '\\') - { - escape_mode = true; - } - else - { - val.push_back(*it); - } - } - ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - - match_string2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } - inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val, bool& is_float_val, bool& is_signed_val) - { - val.clear(); - is_float_val = false; - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.' ) || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+' )) ) - { - if(!val.size() && *it == '-') - is_signed_val = true; - if(*it == '.' ) - is_float_val = true; - val.push_back(*it); - } - else - { - if(val.size()) - { - star_end_string = --it; - return; - } - else - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - bool is_v_float = false;bool is_signed_val = false; - match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val); - return !is_v_float; - } - catch(...) - { - return false; - } - } - inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(!isalpha(*it)) - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return; - }else - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - match_word2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } - inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(!isalnum(*it) && *it != '-' && *it != '_') - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return true; - }else - return false; - } - } - return false; - } - inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) - { - word_end = star_end_string; - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(isspace(*it)) - { - - continue; - }else if( *it == '=' ) - { - star_end_string = it; - word_end = it; - return true; - } - } - return false; - } - } -} -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h deleted file mode 100644 index 87c6edb2..00000000 --- a/contrib/epee/include/storages/portable_storage.h +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" -#include "portable_storage_to_bin.h" -#include "portable_storage_from_bin.h" -#include "portable_storage_to_json.h" -#include "portable_storage_from_json.h" -#include "portable_storage_val_converters.h" - -namespace epee -{ - namespace serialization - { - /************************************************************************/ - /* */ - /************************************************************************/ - class portable_storage - { - public: - typedef epee::serialization::hsection hsection; - typedef epee::serialization::harray harray; - typedef storage_entry meta_entry; - - portable_storage(){} - virtual ~portable_storage(){} - hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false); - template - bool get_value(const std::string& value_name, t_value& val, hsection hparent_section); - bool get_value(const std::string& value_name, storage_entry& val, hsection hparent_section); - template - bool set_value(const std::string& value_name, const t_value& target, hsection hparent_section); - - //serial access for arrays of values -------------------------------------- - //values - template - harray get_first_value(const std::string& value_name, t_value& target, hsection hparent_section); - template - bool get_next_value(harray hval_array, t_value& target); - template - harray insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section); - template - bool insert_next_value(harray hval_array, const t_value& target); - //sections - harray get_first_section(const std::string& pSectionName, hsection& h_child_section, hsection hparent_section); - bool get_next_section(harray hSecArray, hsection& h_child_section); - harray insert_first_section(const std::string& pSectionName, hsection& hinserted_childsection, hsection hparent_section); - bool insert_next_section(harray hSecArray, hsection& hinserted_childsection); - //------------------------------------------------------------------------ - //delete entry (section, value or array) - bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr); - - //------------------------------------------------------------------------------- - bool store_to_binary(binarybuffer& target); - bool load_from_binary(const binarybuffer& target); - template - bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); - bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true); - bool load_from_json(const std::string& source); - - private: - section m_root; - hsection get_root_section() {return &m_root;} - storage_entry* find_storage_entry(const std::string& pentry_name, hsection psection); - template - storage_entry* insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry); - - hsection insert_new_section(const std::string& pentry_name, hsection psection); - -#pragma pack(push) -#pragma pack(1) - struct storage_block_header - { - uint32_t m_signature_a; - uint32_t m_signature_b; - uint8_t m_ver; - }; -#pragma pack(pop) - }; - inline - bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines) - { - TRY_ENTRY(); - std::stringstream ss; - epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines); - buff = ss.str(); - return true; - CATCH_ENTRY("portable_storage::dump_as_json", false) - } - inline - bool portable_storage::load_from_json(const std::string& source) - { - TRY_ENTRY(); - return json::load_from_json(source, *this); - CATCH_ENTRY("portable_storage::load_from_json", false) - } - - template - bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name) - { - return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format - } - - inline - bool portable_storage::store_to_binary(binarybuffer& target) - { - TRY_ENTRY(); - std::stringstream ss; - storage_block_header sbh = AUTO_VAL_INIT(sbh); - sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; - sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; - sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; - ss.write((const char*)&sbh, sizeof(storage_block_header)); - pack_entry_to_buff(ss, m_root); - target = ss.str(); - return true; - CATCH_ENTRY("portable_storage::store_to_binary", false) - } - inline - bool portable_storage::load_from_binary(const binarybuffer& source) - { - m_root.m_entries.clear(); - if(source.size() < sizeof(storage_block_header)) - { - LOG_WARNING("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" - << sizeof(storage_block_header), LOG_LEVEL_2) - return false; - } - storage_block_header* pbuff = (storage_block_header*)source.data(); - if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB - ) - { - LOG_WARNING("portable_storage: wrong binary format - signature missmatch", LOG_LEVEL_2); - return false; - } - if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER) - { - LOG_WARNING("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver, LOG_LEVEL_2); - return false; - } - TRY_ENTRY(); - throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header)); - buf_reader.read(m_root); - return true;//TODO: - CATCH_ENTRY("portable_storage::load_from_binary", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist) - { - TRY_ENTRY(); - hparent_section = hparent_section ? hparent_section:&m_root; - storage_entry* pentry = find_storage_entry(section_name, hparent_section); - if(!pentry) - { - if(!create_if_notexist) - return nullptr; - return insert_new_section(section_name, hparent_section); - } - CHECK_AND_ASSERT(pentry , nullptr); - //check that section_entry we find is real "CSSection" - if(pentry->type() != typeid(section)) - { - if(create_if_notexist) - *pentry = storage_entry(section());//replace - else - return nullptr; - } - return &boost::get
(*pentry); - CATCH_ENTRY("portable_storage::open_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_value_visitor: boost::static_visitor - { - to_type& m_target; - get_value_visitor(to_type& target):m_target(target){} - template - void operator()(const from_type& v){convert_t(v, m_target);} - }; - - template - bool portable_storage::get_value(const std::string& value_name, t_value& val, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return false; - - get_value_visitor gvv(val); - boost::apply_visitor(gvv, *pentry); - return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section) - { - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return false; - - val = *pentry; - return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - template - bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains::type, t_value> )); - TRY_ENTRY(); - if(!hparent_section) - hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, v); - if(!pentry) - return false; - return true; - } - *pentry = storage_entry(v); - return true; - CATCH_ENTRY("portable_storage::template<>set_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); - auto it = psection->m_entries.find(pentry_name); - if(it == psection->m_entries.end()) - return nullptr; - - return &it->second; - CATCH_ENTRY("portable_storage::find_storage_entry", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); - auto ins_res = psection->m_entries.insert(std::pair(pentry_name, entry)); - return &ins_res.first->second; - CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection) - { - TRY_ENTRY(); - storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section()); - if(!pse) return nullptr; - return &boost::get
(*pse); - CATCH_ENTRY("portable_storage::insert_new_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_first_value_visitor: boost::static_visitor - { - to_type& m_target; - get_first_value_visitor(to_type& target):m_target(target){} - template - bool operator()(const array_entry_t& a) - { - const from_type* pv = a.get_first_val(); - if(!pv) - return false; - convert_t(*pv, m_target); - return true; - } - }; - //--------------------------------------------------------------------------------------------------------------- - template - harray portable_storage::get_first_value(const std::string& value_name, t_value& target, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return nullptr; - if(pentry->type() != typeid(array_entry)) - return nullptr; - array_entry& ar_entry = boost::get(*pentry); - - get_first_value_visitor gfv(target); - if(!boost::apply_visitor(gfv, ar_entry)) - return nullptr; - return &ar_entry; - //CATCH_ENTRY("portable_storage::get_first_value", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_next_value_visitor: boost::static_visitor - { - to_type& m_target; - get_next_value_visitor(to_type& target):m_target(target){} - template - bool operator()(const array_entry_t& a) - { - //TODO: optimize code here: work without get_next_val function - const from_type* pv = a.get_next_val(); - if(!pv) - return false; - convert_t(*pv, m_target); - return true; - } - }; - - - template - bool portable_storage::get_next_value(harray hval_array, t_value& target) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); - array_entry& ar_entry = *hval_array; - get_next_value_visitor gnv(target); - if(!boost::apply_visitor(gnv, ar_entry)) - return false; - return true; - //CATCH_ENTRY("portable_storage::get_next_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - template - harray portable_storage::insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, array_entry(array_entry_t())); - if(!pentry) - return nullptr; - } - if(pentry->type() != typeid(array_entry)) - *pentry = storage_entry(array_entry(array_entry_t())); - - array_entry& arr = boost::get(*pentry); - if(arr.type() != typeid(array_entry_t)) - arr = array_entry(array_entry_t()); - - array_entry_t& arr_typed = boost::get >(arr); - arr_typed.insert_first_val(target); - return &arr; - CATCH_ENTRY("portable_storage::insert_first_value", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - bool portable_storage::insert_next_value(harray hval_array, const t_value& target) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); - - CHECK_AND_ASSERT_MES(hval_array->type() == typeid(array_entry_t), - false, "unexpected type in insert_next_value: " << typeid(array_entry_t).name()); - - array_entry_t& arr_typed = boost::get >(*hval_array); - arr_typed.insert_next_value(target); - return true; - CATCH_ENTRY("portable_storage::insert_next_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - //sections - inline - harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(sec_name, hparent_section); - if(!pentry) - return nullptr; - if(pentry->type() != typeid(array_entry)) - return nullptr; - array_entry& ar_entry = boost::get(*pentry); - if(ar_entry.type() != typeid(array_entry_t
)) - return nullptr; - array_entry_t
& sec_array = boost::get>(ar_entry); - section* psec = sec_array.get_first_val(); - if(!psec) - return nullptr; - h_child_section = psec; - return &ar_entry; - CATCH_ENTRY("portable_storage::get_first_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); - if(hsec_array->type() != typeid(array_entry_t
)) - return nullptr; - array_entry_t
& sec_array = boost::get>(*hsec_array); - h_child_section = sec_array.get_next_val(); - if(!h_child_section) - return false; - return true; - CATCH_ENTRY("portable_storage::get_next_section", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(sec_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t
())); - if(!pentry) - return nullptr; - } - if(pentry->type() != typeid(array_entry)) - *pentry = storage_entry(array_entry(array_entry_t
())); - - array_entry& ar_entry = boost::get(*pentry); - if(ar_entry.type() != typeid(array_entry_t
)) - ar_entry = array_entry(array_entry_t
()); - - array_entry_t
& sec_array = boost::get>(ar_entry); - hinserted_childsection = &sec_array.insert_first_val(section()); - return &ar_entry; - CATCH_ENTRY("portable_storage::insert_first_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); - CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t
), - false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name()); - - array_entry_t
& sec_array = boost::get>(*hsec_array); - hinserted_childsection = &sec_array.insert_next_value(section()); - return true; - CATCH_ENTRY("portable_storage::insert_next_section", false); - } - //--------------------------------------------------------------------------------------------------------------- - } -} diff --git a/contrib/epee/include/storages/portable_storage_base.h b/contrib/epee/include/storages/portable_storage_base.h deleted file mode 100644 index 3f163753..00000000 --- a/contrib/epee/include/storages/portable_storage_base.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include -#include - -#define PORTABLE_STORAGE_SIGNATUREA 0x01011101 -#define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare -#define PORTABLE_STORAGE_FORMAT_VER 1 - -#define PORTABLE_RAW_SIZE_MARK_MASK 0x03 -#define PORTABLE_RAW_SIZE_MARK_BYTE 0 -#define PORTABLE_RAW_SIZE_MARK_WORD 1 -#define PORTABLE_RAW_SIZE_MARK_DWORD 2 -#define PORTABLE_RAW_SIZE_MARK_INT64 3 - -#ifndef MAX_STRING_LEN_POSSIBLE -#define MAX_STRING_LEN_POSSIBLE 2000000000 //do not let string be so big -#endif - -//data types -#define SERIALIZE_TYPE_INT64 1 -#define SERIALIZE_TYPE_INT32 2 -#define SERIALIZE_TYPE_INT16 3 -#define SERIALIZE_TYPE_INT8 4 -#define SERIALIZE_TYPE_UINT64 5 -#define SERIALIZE_TYPE_UINT32 6 -#define SERIALIZE_TYPE_UINT16 7 -#define SERIALIZE_TYPE_UINT8 8 -#define SERIALIZE_TYPE_DUOBLE 9 -#define SERIALIZE_TYPE_STRING 10 -#define SERIALIZE_TYPE_BOOL 11 -#define SERIALIZE_TYPE_OBJECT 12 -#define SERIALIZE_TYPE_ARRAY 13 - -#define SERIALIZE_FLAG_ARRAY 0x80 - - -namespace epee -{ - namespace serialization - { - struct section; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct array_entry_t - { - array_entry_t():m_it(m_array.end()){} - - const t_entry_type* get_first_val() const - { - m_it = m_array.begin(); - return get_next_val(); - } - - t_entry_type* get_first_val() - { - m_it = m_array.begin(); - return get_next_val(); - } - - - const t_entry_type* get_next_val() const - { - if(m_it == m_array.end()) - return nullptr; - return &(*(m_it++)); - } - - t_entry_type* get_next_val() - { - if(m_it == m_array.end()) - return nullptr; - return (t_entry_type*)&(*(m_it++));//fuckoff - } - - t_entry_type& insert_first_val(const t_entry_type& v) - { - m_array.clear(); - m_it = m_array.end(); - return insert_next_value(v); - } - - t_entry_type& insert_next_value(const t_entry_type& v) - { - m_array.push_back(v); - return m_array.back(); - } - - std::list m_array; - mutable typename std::list::const_iterator m_it; - }; - - - typedef boost::make_recursive_variant< - array_entry_t
, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t
, - array_entry_t - >::type array_entry; - - typedef boost::variant storage_entry; - - typedef std::string binarybuffer;//it's ok - - /************************************************************************/ - /* */ - /************************************************************************/ - struct section - { - std::map m_entries; - }; - - //handle-like aliases - typedef section* hsection; - typedef array_entry* harray; - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h deleted file mode 100644 index e9b7e2e6..00000000 --- a/contrib/epee/include/storages/portable_storage_from_bin.h +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" - -#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT -#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT -#else -#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100 -#endif - -namespace epee -{ - namespace serialization - { - struct throwable_buffer_reader - { - throwable_buffer_reader(const void* ptr, size_t sz); - void read(void* target, size_t count); - void read_sec_name(std::string& sce_name); - template - void read(t_pod_type& pod_val); - template - t_type read(); - template - storage_entry read_ae(); - storage_entry load_storage_array_entry(uint8_t type); - size_t read_varint(); - template - storage_entry read_se(); - storage_entry load_storage_entry(); - void read(section& sec); - void read(std::string& str); - private: - struct recursuion_limitation_guard - { - size_t& m_counter_ref; - recursuion_limitation_guard(size_t& counter):m_counter_ref(counter) - { - ++m_counter_ref; - CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded"); - } - ~recursuion_limitation_guard() - { - CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()"); - --m_counter_ref; - } - }; -#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count) - - const uint8_t* m_ptr; - size_t m_count; - size_t m_recursion_count; - }; - - inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz) - { - if(!ptr) - throw std::runtime_error("throwable_buffer_reader: ptr==nullptr"); - if(!sz) - throw std::runtime_error("throwable_buffer_reader: sz==0"); - m_ptr = (uint8_t*)ptr; - m_count = sz; - m_recursion_count = 0; - } - inline - void throwable_buffer_reader::read(void* target, size_t count) - { - RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained"); - memcpy(target, m_ptr, count); - m_ptr += count; - m_count -= count; - } - inline - void throwable_buffer_reader::read_sec_name(std::string& sce_name) - { - RECURSION_LIMITATION(); - uint8_t name_len = 0; - read(name_len); - sce_name.resize(name_len); - read((void*)sce_name.data(), name_len); - } - - template - void throwable_buffer_reader::read(t_pod_type& pod_val) - { - RECURSION_LIMITATION(); - read(&pod_val, sizeof(pod_val)); - } - - template - t_type throwable_buffer_reader::read() - { - RECURSION_LIMITATION(); - t_type v; - read(v); - return v; - } - - - template - storage_entry throwable_buffer_reader::read_ae() - { - RECURSION_LIMITATION(); - //for pod types - array_entry_t sa; - size_t size = read_varint(); - //TODO: add some optimization here later - while(size--) - sa.m_array.push_back(read()); - return storage_entry(array_entry(sa)); - } - - inline - storage_entry throwable_buffer_reader::load_storage_array_entry(uint8_t type) - { - RECURSION_LIMITATION(); - type &= ~SERIALIZE_FLAG_ARRAY; - switch(type) - { - case SERIALIZE_TYPE_INT64: return read_ae(); - case SERIALIZE_TYPE_INT32: return read_ae(); - case SERIALIZE_TYPE_INT16: return read_ae(); - case SERIALIZE_TYPE_INT8: return read_ae(); - case SERIALIZE_TYPE_UINT64: return read_ae(); - case SERIALIZE_TYPE_UINT32: return read_ae(); - case SERIALIZE_TYPE_UINT16: return read_ae(); - case SERIALIZE_TYPE_UINT8: return read_ae(); - case SERIALIZE_TYPE_DUOBLE: return read_ae(); - case SERIALIZE_TYPE_BOOL: return read_ae(); - case SERIALIZE_TYPE_STRING: return read_ae(); - case SERIALIZE_TYPE_OBJECT: return read_ae
(); - case SERIALIZE_TYPE_ARRAY: return read_ae(); - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type); - } - } - - inline - size_t throwable_buffer_reader::read_varint() - { - RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint"); - size_t v = 0; - uint8_t size_mask = (*(uint8_t*)m_ptr) &PORTABLE_RAW_SIZE_MARK_MASK; - switch (size_mask) - { - case PORTABLE_RAW_SIZE_MARK_BYTE: v = read();break; - case PORTABLE_RAW_SIZE_MARK_WORD: v = read();break; - case PORTABLE_RAW_SIZE_MARK_DWORD: v = read();break; - case PORTABLE_RAW_SIZE_MARK_INT64: v = read();break; - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask); - } - v >>= 2; - return v; - } - - template - storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - t_type v; - read(v); - return storage_entry(v); - } - - template<> - inline storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - return storage_entry(read()); - } - - - template<> - inline storage_entry throwable_buffer_reader::read_se
() - { - RECURSION_LIMITATION(); - section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio - storage_entry se(s); - section& section_entry = boost::get
(se); - read(section_entry); - return se; - } - - template<> - inline storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - uint8_t ent_type = 0; - read(ent_type); - CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses"); - return load_storage_array_entry(ent_type); - } - - inline - storage_entry throwable_buffer_reader::load_storage_entry() - { - RECURSION_LIMITATION(); - uint8_t ent_type = 0; - read(ent_type); - if(ent_type&SERIALIZE_FLAG_ARRAY) - return load_storage_array_entry(ent_type); - - switch(ent_type) - { - case SERIALIZE_TYPE_INT64: return read_se(); - case SERIALIZE_TYPE_INT32: return read_se(); - case SERIALIZE_TYPE_INT16: return read_se(); - case SERIALIZE_TYPE_INT8: return read_se(); - case SERIALIZE_TYPE_UINT64: return read_se(); - case SERIALIZE_TYPE_UINT32: return read_se(); - case SERIALIZE_TYPE_UINT16: return read_se(); - case SERIALIZE_TYPE_UINT8: return read_se(); - case SERIALIZE_TYPE_DUOBLE: return read_se(); - case SERIALIZE_TYPE_BOOL: return read_se(); - case SERIALIZE_TYPE_STRING: return read_se(); - case SERIALIZE_TYPE_OBJECT: return read_se
(); - case SERIALIZE_TYPE_ARRAY: return read_se(); - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type); - } - } - inline - void throwable_buffer_reader::read(section& sec) - { - RECURSION_LIMITATION(); - sec.m_entries.clear(); - size_t count = read_varint(); - while(count--) - { - //read section name string - std::string sec_name; - read_sec_name(sec_name); - sec.m_entries.insert(std::make_pair(sec_name, load_storage_entry())); - } - } - inline - void throwable_buffer_reader::read(std::string& str) - { - RECURSION_LIMITATION(); - size_t len = read_varint(); - CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len); - CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count); - //do this manually to avoid double memory write in huge strings (first time at resize, second at read) - str.assign((const char*)m_ptr, len); - m_ptr+=len; - m_count -= len; - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h deleted file mode 100644 index 3ca61c02..00000000 --- a/contrib/epee/include/storages/portable_storage_from_json.h +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -#include "parserse_base_utils.h" -#include "file_io_utils.h" - -namespace epee -{ - using namespace misc_utils::parse; - namespace serialization - { - namespace json - { -#define CHECK_ISSPACE() if(!isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} - - /*inline void parse_error() - { - ASSERT_MES_AND_THROW("json parse error"); - }*/ - template - inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg) - { - - std::string::const_iterator sub_element_start; - std::string name; - typename t_storage::harray h_array = nullptr; - enum match_state - { - match_state_lookup_for_section_start, - match_state_lookup_for_name, - match_state_waiting_separator, - match_state_wonder_after_separator, - match_state_wonder_after_value, - match_state_wonder_array, - match_state_array_after_value, - match_state_array_waiting_value, - match_state_error - }; - - enum array_mode - { - array_mode_undifined = 0, - array_mode_sections, - array_mode_string, - array_mode_numbers, - array_mode_booleans - }; - - match_state state = match_state_lookup_for_section_start; - array_mode array_md = array_mode_undifined; - std::string::const_iterator it = sec_buf_begin; - for(;it != buf_end;it++) - { - switch (state) - { - case match_state_lookup_for_section_start: - if(*it == '{') - state = match_state_lookup_for_name; - else CHECK_ISSPACE(); - break; - case match_state_lookup_for_name: - switch(*it) - { - case '"': - match_string2(it, buf_end, name); - state = match_state_waiting_separator; - break; - case '}': - //this is it! section ends here. - //seems that it is empty section - sec_buf_begin = it; - return; - default: - CHECK_ISSPACE(); - } - break; - case match_state_waiting_separator: - if(*it == ':') - state = match_state_wonder_after_separator; - else CHECK_ISSPACE(); - break; - case match_state_wonder_after_separator: - if(*it == '"') - {//just a named string value started - std::string val; - match_string2(it, buf_end, val); - //insert text value - stg.set_value(name, val, current_section); - state = match_state_wonder_after_value; - }else if (isdigit(*it) || *it == '-') - {//just a named number value started - std::string val; - bool is_v_float = false;bool is_signed = false; - match_number2(it, buf_end, val, is_v_float, is_signed); - if(!is_v_float) - { - if(is_signed) - { - int64_t nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - }else - { - uint64_t nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - } - }else - { - double nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - } - state = match_state_wonder_after_value; - }else if(isalpha(*it) ) - {// could be null, true or false - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "null")) - { - state = match_state_wonder_after_value; - //just skip this, - }else if(boost::iequals(word, "true")) - { - stg.set_value(name, true, current_section); - state = match_state_wonder_after_value; - }else if(boost::iequals(word, "false")) - { - stg.set_value(name, false, current_section); - state = match_state_wonder_after_value; - }else ASSERT_MES_AND_THROW("Unknown value keyword " << word); - }else if(*it == '{') - { - //sub section here - typename t_storage::hsection new_sec = stg.open_section(name, current_section, true); - CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end)); - run_handler(new_sec, it, buf_end, stg); - state = match_state_wonder_after_value; - }else if(*it == '[') - {//array of something - state = match_state_wonder_array; - }else CHECK_ISSPACE(); - break; - case match_state_wonder_after_value: - if(*it == ',') - state = match_state_lookup_for_name; - else if(*it == '}') - { - //this is it! section ends here. - sec_buf_begin = it; - return; - }else CHECK_ISSPACE(); - break; - case match_state_wonder_array: - if(*it == '[') - { - ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry"); - //mean array of array - } - if(*it == '{') - { - //mean array of sections - typename t_storage::hsection new_sec = nullptr; - h_array = stg.insert_first_section(name, new_sec, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section"); - run_handler(new_sec, it, buf_end, stg); - state = match_state_array_after_value; - array_md = array_mode_sections; - }else if(*it == '"') - { - //mean array of strings - std::string val; - match_string2(it, buf_end, val); - h_array = stg.insert_first_value(name, val, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); - state = match_state_array_after_value; - array_md = array_mode_string; - }else if (isdigit(*it) || *it == '-') - {//array of numbers value started - std::string val; - bool is_v_float = false;bool is_signed_val = false; - match_number2(it, buf_end, val, is_v_float, is_signed_val); - if(!is_v_float) - { - int64_t nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - }else - { - double nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - } - - state = match_state_array_after_value; - array_md = array_mode_numbers; - }else if(*it == ']')//empty array - { - array_md = array_mode_undifined; - state = match_state_wonder_after_value; - }else if(isalpha(*it) ) - {// array of booleans - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "true")) - { - h_array = stg.insert_first_value(name, true, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - state = match_state_array_after_value; - array_md = array_mode_booleans; - }else if(boost::iequals(word, "false")) - { - h_array = stg.insert_first_value(name, false, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - state = match_state_array_after_value; - array_md = array_mode_booleans; - - }else ASSERT_MES_AND_THROW("Unknown value keyword " << word) - }else CHECK_ISSPACE(); - break; - case match_state_array_after_value: - if(*it == ',') - state = match_state_array_waiting_value; - else if(*it == ']') - { - h_array = nullptr; - array_md = array_mode_undifined; - state = match_state_wonder_after_value; - }else CHECK_ISSPACE(); - break; - case match_state_array_waiting_value: - switch(array_md) - { - case array_mode_sections: - if(*it == '{') - { - typename t_storage::hsection new_sec = NULL; - bool res = stg.insert_next_section(h_array, new_sec); - CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section"); - run_handler(new_sec, it, buf_end, stg); - state = match_state_array_after_value; - }else CHECK_ISSPACE(); - break; - case array_mode_string: - if(*it == '"') - { - std::string val; - match_string2(it, buf_end, val); - bool res = stg.insert_next_value(h_array, val); - CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); - state = match_state_array_after_value; - }else CHECK_ISSPACE(); - break; - case array_mode_numbers: - if (isdigit(*it) || *it == '-') - {//array of numbers value started - std::string val; - bool is_v_float = false;bool is_signed_val = false; - match_number2(it, buf_end, val, is_v_float, is_signed_val); - bool insert_res = false; - if(!is_v_float) - { - int64_t nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - - }else - { - //TODO: optimize here if need - double nval = boost::lexical_cast(val); //string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - } - CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); - state = match_state_array_after_value; - array_md = array_mode_numbers; - }else CHECK_ISSPACE(); - break; - case array_mode_booleans: - if(isalpha(*it) ) - {// array of booleans - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "true")) - { - bool r = stg.insert_next_value(h_array, true); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); - state = match_state_array_after_value; - }else if(boost::iequals(word, "false")) - { - bool r = stg.insert_next_value(h_array, false); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); - state = match_state_array_after_value; - } - else ASSERT_MES_AND_THROW("Unknown value keyword " << word); - }else CHECK_ISSPACE(); - break; - case array_mode_undifined: - default: - ASSERT_MES_AND_THROW("Bad array state"); - } - break; - case match_state_error: - default: - ASSERT_MES_AND_THROW("WRONG JSON STATE"); - } - } - } -/* -{ - "firstName": "John", - "lastName": "Smith", - "age": 25, - "address": { - "streetAddress": "21 2nd Street", - "city": "New York", - "state": "NY", - "postalCode": -10021, - "have_boobs": true, - "have_balls": false - }, - "phoneNumber": [ - { - "type": "home", - "number": "212 555-1234" - }, - { - "type": "fax", - "number": "646 555-4567" - } - ], - "phoneNumbers": [ - "812 123-1234", - "916 123-4567" - ] -} -*/ - template - inline bool load_from_json(const std::string& buff_json, t_storage& stg) - { - std::string::const_iterator sec_buf_begin = buff_json.begin(); - try - { - run_handler(nullptr, sec_buf_begin, buff_json.end(), stg); - return true; - } - catch(const std::exception& ex) - { - (void)(ex); - LOG_PRINT_RED_L0("Failed to parse json, what: " << ex.what()); - return false; - } - catch(...) - { - LOG_PRINT_RED_L0("Failed to parse json"); - return false; - } - } - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h deleted file mode 100644 index 008f4432..00000000 --- a/contrib/epee/include/storages/portable_storage_template_helper.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -#include "parserse_base_utils.h" -#include "portable_storage.h" -#include "file_io_utils.h" - -namespace epee -{ - namespace serialization - { - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_json(t_struct& out, const std::string& json_buff) - { - portable_storage ps; - bool rs = ps.load_from_json(json_buff); - if(!rs) - return false; - - return out.load(ps); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_json_file(t_struct& out, const std::string& json_file) - { - std::string f_buff; - if(!file_io_utils::load_file_to_string(json_file, f_buff)) - return false; - - return load_t_from_json(out, f_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0, bool insert_newlines = true) - { - portable_storage ps; - str_in.store(ps); - ps.dump_as_json(json_buff, indent, insert_newlines); - return true; - } - //----------------------------------------------------------------------------------------------------------- - template - std::string store_t_to_json(t_struct& str_in, size_t indent = 0, bool insert_newlines = true) - { - std::string json_buff; - store_t_to_json(str_in, json_buff, indent, insert_newlines); - return std::move(json_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool store_t_to_json_file(t_struct& str_in, const std::string& fpath) - { - std::string json_buff; - store_t_to_json(str_in, json_buff); - return file_io_utils::save_string_to_file(fpath, json_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_binary(t_struct& out, const std::string& binary_buff) - { - portable_storage ps; - bool rs = ps.load_from_binary(binary_buff); - if(!rs) - return false; - - return out.load(ps); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_binary_file(t_struct& out, const std::string& binary_file) - { - std::string f_buff; - if(!file_io_utils::load_file_to_string(binary_file, f_buff)) - return false; - - return load_t_from_binary(out, f_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool store_t_to_binary(t_struct& str_in, std::string& binary_buff, size_t indent = 0) - { - portable_storage ps; - str_in.store(ps); - return ps.store_to_binary(binary_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - std::string store_t_to_binary(t_struct& str_in, size_t indent = 0) - { - std::string binary_buff; - store_t_to_binary(str_in, binary_buff, indent); - return std::move(binary_buff); - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h deleted file mode 100644 index 6743a608..00000000 --- a/contrib/epee/include/storages/portable_storage_to_bin.h +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" -#include "pragma_comp_defs.h" - -namespace epee -{ - namespace serialization - { - - template - size_t pack_varint_t(t_stream& strm, uint8_t type_or, size_t& pv) - { - pack_value v = (*((pack_value*)&pv)) << 2; - v |= type_or; - strm.write((const char*)&v, sizeof(pack_value)); - return sizeof(pack_value); - } - - PRAGMA_WARNING_PUSH - PRAGMA_GCC("GCC diagnostic ignored \"-Wstrict-aliasing\"") - template - size_t pack_varint(t_stream& strm, size_t val) - { //the first two bits always reserved for size information - - if(val <= 63) - {//mean enough one byte - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_BYTE, val); - } - else if(val <= 16383) - {//mean need word - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_WORD, val); - }else if(val <= 1073741823) - {//mean need dword - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_DWORD, val); - }else - { - CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val); - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_INT64, val); - } - } - PRAGMA_WARNING_POP - - template - bool put_string(t_stream& strm, const std::string& v) - { - pack_varint(strm, v.size()); - if(v.size()) - strm.write((const char*)v.data(), v.size()); - return true; - } - - template - struct array_entry_store_visitor: public boost::static_visitor - { - t_stream& m_strm; - - template - bool pack_pod_array_type(uint8_t contained_type, const array_entry_t& arr_pod) - { - uint8_t type = contained_type|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_pod.m_array.size()); - for(const t_pod_type& x: arr_pod.m_array) - m_strm.write((const char*)&x, sizeof(t_pod_type)); - return true; - } - - array_entry_store_visitor(t_stream& strm):m_strm(strm){} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT64, v);} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT32, v);} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT16, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_UINT8, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT64, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT32, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT16, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT8, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_DUOBLE, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_BOOL, v);} - bool operator()(const array_entry_t& arr_str) - { - uint8_t type = SERIALIZE_TYPE_STRING|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_str.m_array.size()); - for(const std::string& s: arr_str.m_array) - put_string(m_strm, s); - return true; - } - bool operator()(const array_entry_t
& arr_sec) - { - uint8_t type = SERIALIZE_TYPE_OBJECT|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_sec.m_array.size()); - for(const section& s: arr_sec.m_array) - pack_entry_to_buff(m_strm, s); - return true; - } - bool operator()(const array_entry_t& arra_ar) - { - uint8_t type = SERIALIZE_TYPE_ARRAY|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arra_ar.m_array.size()); - for(const array_entry& s: arra_ar.m_array) - pack_entry_to_buff(m_strm, s); - return true; - } - }; - - template - struct storage_entry_store_visitor: public boost::static_visitor - { - t_stream& m_strm; - storage_entry_store_visitor(t_stream& strm):m_strm(strm){} - template - bool pack_pod_type(uint8_t type, const pod_type& v) - { - m_strm.write((const char*)&type, 1); - m_strm.write((const char*)&v, sizeof(pod_type)); - return true; - } - //section, array_entry - bool operator()(const uint64_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT64, v);} - bool operator()(const uint32_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT32, v);} - bool operator()(const uint16_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT16, v);} - bool operator()(const uint8_t& v) { return pack_pod_type(SERIALIZE_TYPE_UINT8, v);} - bool operator()(const int64_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT64, v);} - bool operator()(const int32_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT32, v);} - bool operator()(const int16_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT16, v);} - bool operator()(const int8_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT8, v);} - bool operator()(const double& v) { return pack_pod_type(SERIALIZE_TYPE_DUOBLE, v);} - bool operator()(const bool& v) { return pack_pod_type(SERIALIZE_TYPE_BOOL, v);} - bool operator()(const std::string& v) - { - uint8_t type = SERIALIZE_TYPE_STRING; - m_strm.write((const char*)&type, 1); - put_string(m_strm, v); - return true; - } - bool operator()(const section& v) - { - uint8_t type = SERIALIZE_TYPE_OBJECT; - m_strm.write((const char*)&type, 1); - return pack_entry_to_buff(m_strm, v); - } - - bool operator()(const array_entry& v) - { - //uint8_t type = SERIALIZE_TYPE_ARRAY; - //m_strm.write((const char*)&type, 1); - return pack_entry_to_buff(m_strm, v); - } - }; - - template - bool pack_entry_to_buff(t_stream& strm, const array_entry& ae) - { - array_entry_store_visitor aesv(strm); - return boost::apply_visitor(aesv, ae); - } - - template - bool pack_entry_to_buff(t_stream& strm, const storage_entry& se) - { - storage_entry_store_visitor sv(strm); - return boost::apply_visitor(sv, se); - } - - template - bool pack_entry_to_buff(t_stream& strm, const section& sec) - { - typedef std::map::value_type section_pair; - pack_varint(strm, sec.m_entries.size()); - for(const section_pair& se: sec.m_entries) - { - CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first); - uint8_t len = static_cast(se.first.size()); - strm.write((const char*)&len, sizeof(len)); - strm.write(se.first.data(), size_t(len)); - pack_entry_to_buff(strm, se.second); - } - return true; - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_to_json.h b/contrib/epee/include/storages/portable_storage_to_json.h deleted file mode 100644 index e3fdcec2..00000000 --- a/contrib/epee/include/storages/portable_storage_to_json.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" -#include "parserse_base_utils.h" - -namespace epee -{ - namespace serialization - { - - template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines); - template - void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines); - - - inline std::string make_indent(size_t indent) - { - return std::string(indent*2, ' '); - } - - template - struct array_entry_store_to_json_visitor: public boost::static_visitor - { - t_stream& m_strm; - size_t m_indent; - bool m_insert_newlines; - array_entry_store_to_json_visitor(t_stream& strm, size_t indent, - bool insert_newlines = true) - : m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines) - {} - - template - void operator()(const array_entry_t& a) - { - m_strm << "["; - if(a.m_array.size()) - { - auto last_it = --a.m_array.end(); - for(auto it = a.m_array.begin(); it != a.m_array.end(); it++) - { - dump_as_json(m_strm, *it, m_indent, m_insert_newlines); - if(it != last_it) - m_strm << ","; - } - } - m_strm << "]"; - } - }; - - template - struct storage_entry_store_to_json_visitor: public boost::static_visitor - { - t_stream& m_strm; - size_t m_indent; - bool m_insert_newlines; - storage_entry_store_to_json_visitor(t_stream& strm, size_t indent, - bool insert_newlines = true) - : m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines) - {} - //section, array_entry - template - void operator()(const visited_type& v) - { - dump_as_json(m_strm, v, m_indent, m_insert_newlines); - } - }; - - template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines) - { - array_entry_store_to_json_visitor aesv(strm, indent, insert_newlines); - boost::apply_visitor(aesv, ae); - } - - template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines) - { - storage_entry_store_to_json_visitor sv(strm, indent, insert_newlines); - boost::apply_visitor(sv, se); - } - - template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines) - { - strm << "\"" << misc_utils::parse::transform_to_escape_sequence(v) << "\""; - } - - template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines) - { - strm << static_cast(v); - } - - template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines) - { - strm << static_cast(v); - } - - template - void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines) - { - if(v) - strm << "true"; - else - strm << "false"; - } - - - - template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines) - { - strm << v; - } - - template - void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines) - { - size_t local_indent = indent + 1; - std::string newline = insert_newlines ? "\r\n" : ""; - strm << "{" << newline; - std::string indent_str = make_indent(local_indent); - if(sec.m_entries.size()) - { - auto it_last = --sec.m_entries.end(); - for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++) - { - strm << indent_str << "\"" << misc_utils::parse::transform_to_escape_sequence(it->first) << "\"" << ": "; - dump_as_json(strm, it->second, local_indent, insert_newlines); - if(it_last != it) - strm << ","; - strm << newline; - } - } - strm << make_indent(indent) << "}"; - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h deleted file mode 100644 index 73d339f5..00000000 --- a/contrib/epee/include/storages/portable_storage_val_converters.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -#include "misc_language.h" -#include "portable_storage_base.h" -#include "warnings.h" - -namespace epee -{ - namespace serialization - { -#define ASSERT_AND_THROW_WRONG_CONVERSION() ASSERT_MES_AND_THROW("WRONG DATA CONVERSION: from type=" << typeid(from).name() << " to type " << typeid(to).name()) - - template - void convert_int_to_uint(const from_type& from, to_type& to) - { -PUSH_WARNINGS -DISABLE_VS_WARNINGS(4018) - CHECK_AND_ASSERT_THROW_MES(from >=0, "unexpected int value with signed storage value less than 0, and unsigned receiver value"); -DISABLE_GCC_AND_CLANG_WARNING(sign-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); - to = static_cast(from); -POP_WARNINGS - } - template - void convert_int_to_int(const from_type& from, to_type& to) - { - CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds::lowest(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with lowest possible value = " << boost::numeric::bounds::lowest()); -PUSH_WARNINGS -DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); -POP_WARNINGS - to = static_cast(from); - } - template - void convert_uint_to_any_int(const from_type& from, to_type& to) - { -PUSH_WARNINGS -DISABLE_VS_WARNINGS(4018) -DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "uint value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); - to = static_cast(from); -POP_WARNINGS - } - - template //is from signed, is from to signed - struct convert_to_signed_unsigned; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from signed to signed - convert_int_to_int(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from signed to unsigned - convert_int_to_uint(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from unsigned to signed - convert_uint_to_any_int(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - { - //from unsigned to unsigned - convert_uint_to_any_int(from, to); - } - }; - - template - struct convert_to_integral; - - template - struct convert_to_integral - { - static void convert(const from_type& from, to_type& to) - { - convert_to_signed_unsigned::value, std::is_signed::value>::convert(from, to); - } - }; - - template - struct convert_to_integral - { - static void convert(const from_type& from, to_type& to) - { - ASSERT_AND_THROW_WRONG_CONVERSION(); - } - }; - - template - struct is_convertable: std::integral_constant::value && - std::is_integral::value && - !std::is_same::value && - !std::is_same::value > {}; - - template - struct convert_to_same; - - template - struct convert_to_same - { - static void convert(const from_type& from, to_type& to) - { - to = from; - } - }; - - template - struct convert_to_same - { - static void convert(const from_type& from, to_type& to) - { - convert_to_integral::value>::convert(from, to);// ASSERT_AND_THROW_WRONG_CONVERSION(); - } - }; - - - template - void convert_t(const from_type& from, to_type& to) - { - convert_to_same::value>::convert(from, to); - } - } -} \ No newline at end of file diff --git a/contrib/epee/include/string_coding.h b/contrib/epee/include/string_coding.h deleted file mode 100644 index a2e3d6eb..00000000 --- a/contrib/epee/include/string_coding.h +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _STRING_CODING_H_ -#define _STRING_CODING_H_ - -#include -//#include "md5_l.h" -namespace epee -{ -namespace string_encoding -{ - inline std::string convert_to_ansii(const std::wstring& str_from) - { - - std::string res(str_from.begin(), str_from.end()); - return res; - /* - std::string result; - std::locale loc; - for(unsigned int i= 0; i < str_from.size(); ++i) - { - result += std::use_facet >(loc).narrow(str_from[i]); - } - return result; - */ - - //return boost::lexical_cast(str_from); - /* - std::string str_trgt; - if(!str_from.size()) - return str_trgt; - int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 ); - if(!cb) - return str_trgt; - str_trgt.resize(cb); - ::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(), - (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); - return str_trgt;*/ - } -#ifdef WINDOWS_PLATFORM_EX - inline std::string convert_to_ansii_win(const std::wstring& str_from) - { - - int code_page = CP_ACP; - std::string str_trgt; - if(!str_from.size()) - return str_trgt; - int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 ); - if(!cb) - return str_trgt; - str_trgt.resize(cb); - ::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(), - (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); - return str_trgt; - } -#endif - - inline std::string convert_to_ansii(const std::string& str_from) - { - return str_from; - } - - inline std::wstring convert_to_unicode(const std::string& str_from) - { - std::wstring result; - std::locale loc; - for(unsigned int i= 0; i < str_from.size(); ++i) - { - result += std::use_facet >(loc).widen(str_from[i]); - } - return result; - - //return boost::lexical_cast(str_from); - /* - std::wstring str_trgt; - if(!str_from.size()) - return str_trgt; - - int cb = ::MultiByteToWideChar( code_page, 0, str_from.data(), (int)str_from.size(), 0, 0 ); - if(!cb) - return str_trgt; - - str_trgt.resize(cb); - ::MultiByteToWideChar( code_page, 0, str_from.data(),(int)str_from.size(), - (wchar_t*)str_trgt.data(),(int)str_trgt.size()); - return str_trgt;*/ - } - inline std::wstring convert_to_unicode(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::wstring& str_from); - - template<> - inline std::string convert_to_t(const std::wstring& str_from) - { - return convert_to_ansii(str_from); - } - - template<> - inline std::wstring convert_to_t(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::string& str_from); - - template<> - inline std::string convert_to_t(const std::string& str_from) - { - return str_from; - } - - template<> - inline std::wstring convert_to_t(const std::string& str_from) - { - return convert_to_unicode(str_from); - } - - inline - std::string& base64_chars() - { - - static std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - return chars; - - } - - inline - std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for(i = 0; (i <4) ; i++) - ret += base64_chars()[char_array_4[i]]; - i = 0; - } - } - - if (i) - { - for(j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars()[char_array_4[j]]; - - while((i++ < 3)) - ret += '='; - - } - - return ret; - - } - - inline - std::string base64_encode(const std::string& str) - { - return base64_encode((unsigned char const* )str.data(), str.size()); - } - - inline bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); - } - - - inline - std::string base64_decode(std::string const& encoded_string) { - size_t in_len = encoded_string.size(); - size_t i = 0; - size_t j = 0; - size_t in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; - - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = (unsigned char)base64_chars().find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; - - for (j = 0; j <4; j++) - char_array_4[j] = (unsigned char)base64_chars().find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; - } - - return ret; - } - - //md5 -#ifdef MD5_H - inline - std::string get_buf_as_hex_string(const void* pbuf, size_t len) - { - std::ostringstream result; - - const unsigned char* p_buff = (const unsigned char*)pbuf; - - for(unsigned int i=0;i(len), output); - return get_buf_as_hex_string(output, sizeof(output)); - } - - inline - std::string get_md5_as_hexstring(const std::string& src) - { - return get_md5_as_hexstring(src.data(), src.size()); - } -#endif - - -} -} - -#endif //_STRING_CODING_H_ diff --git a/contrib/epee/include/string_tools.cpp b/contrib/epee/include/string_tools.cpp deleted file mode 100644 index 8181bc10..00000000 --- a/contrib/epee/include/string_tools.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "string_tools.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -#ifdef WINDOWS_PLATFORM -#pragma comment (lib, "Rpcrt4.lib") -#endif - -namespace epee -{ -namespace string_tools -{ - std::wstring get_str_from_guid(const boost::uuids::uuid& rid) - { - return boost::lexical_cast(rid); - } - //---------------------------------------------------------------------------- - std::string get_str_from_guid_a(const boost::uuids::uuid& rid) - { - return boost::lexical_cast(rid); - } - //---------------------------------------------------------------------------- - bool get_guid_from_string( boost::uuids::uuid& inetifer, std::wstring str_id) - { - if(str_id.size() < 36) - return false; - - if('{' == *str_id.begin()) - str_id.erase(0, 1); - - if('}' == *(--str_id.end())) - str_id.erase(--str_id.end()); - - try - { - inetifer = boost::lexical_cast(str_id); - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id) - { - std::string local_str_id = str_id; - if(local_str_id.size() < 36) - return false; - - if('{' == *local_str_id.begin()) - local_str_id.erase(0, 1); - - if('}' == *(--local_str_id.end())) - local_str_id.erase(--local_str_id.end()); - - try - { - inetifer = boost::lexical_cast(local_str_id); - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- -//#ifdef _WINSOCK2API_ - std::string get_ip_string_from_int32(uint32_t ip) - { - in_addr adr; - adr.s_addr = ip; - const char* pbuf = inet_ntoa(adr); - if(pbuf) - return pbuf; - else - return "[failed]"; - } - //---------------------------------------------------------------------------- - bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str) - { - ip = inet_addr(ip_str.c_str()); - if(INADDR_NONE == ip) - return false; - - return true; - } - //---------------------------------------------------------------------------- - bool parse_peer_from_string(uint32_t& ip, uint32_t& port, const std::string& addres) - { - //parse ip and address - std::string::size_type p = addres.find(':'); - if(p == std::string::npos) - { - return false; - } - std::string ip_str = addres.substr(0, p); - std::string port_str = addres.substr(p+1, addres.size()); - - if(!get_ip_int32_from_string(ip, ip_str)) - { - return false; - } - - if(!get_xtype_from_string(port, port_str)) - { - return false; - } - return true; - } - - //---------------------------------------------------------------------------- - std::string num_to_string_fast(int64_t val) - { - /* - char buff[30] = {0}; - i64toa_s(val, buff, sizeof(buff)-1, 10); - return buff;*/ - return boost::lexical_cast(val); - } - //---------------------------------------------------------------------------- - bool string_to_num_fast(const std::string& buff, int64_t& val) - { - //return get_xtype_from_string(val, buff); -#if (defined _MSC_VER) - val = _atoi64(buff.c_str()); -#else - val = atoll(buff.c_str()); -#endif - /* - * val = atoi64(buff.c_str()); - */ - if(buff != "0" && val == 0) - return false; - return true; - } - //---------------------------------------------------------------------------- - bool string_to_num_fast(const std::string& buff, int& val) - { - val = atoi(buff.c_str()); - if(buff != "0" && val == 0) - return false; - - return true; - } - //---------------------------------------------------------------------------- -#ifdef WINDOWS_PLATFORM - std::string system_time_to_string(const SYSTEMTIME& st) - { - - /* - TIME_ZONE_INFORMATION tzi; - GetTimeZoneInformation(&tzi); - SystemTimeToTzSpecificLocalTime(&tzi, &stUTC, &stLocal); - */ - - char szTime[25], szDate[25]; - ::GetTimeFormatA( - LOCALE_USER_DEFAULT, // locale - TIME_FORCE24HOURFORMAT, // options - &st, // time - NULL, // time format string - szTime, // formatted string buffer - 25 // size of string buffer - ); - - ::GetDateFormatA( - LOCALE_USER_DEFAULT, // locale - NULL, // options - &st, // date - NULL, // date format - szDate, // formatted string buffer - 25 // size of buffer - ); - szTime[24] = szDate[24] = 0; //be happy :) - - std::string res = szDate; - (res += " " )+= szTime; - return res; - - } -#endif - //---------------------------------------------------------------------------- - - bool compare_no_case(const std::string& str1, const std::string& str2) - { - - return !boost::iequals(str1, str2); - } - //---------------------------------------------------------------------------- - bool compare_no_case(const std::wstring& str1, const std::wstring& str2) - { - return !boost::iequals(str1, str2); - } - //---------------------------------------------------------------------------- - bool is_match_prefix(const std::wstring& str1, const std::wstring& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- - bool is_match_prefix(const std::string& str1, const std::string& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- - std::string& get_current_module_name() - { - static std::string module_name; - return module_name; - } - //---------------------------------------------------------------------------- - std::string& get_current_module_folder() - { - static std::string module_folder; - return module_folder; - } - //---------------------------------------------------------------------------- -#ifdef _WIN32 - std::string get_current_module_path() - { - char pname [5000] = {0}; - GetModuleFileNameA( NULL, pname, sizeof(pname)); - pname[sizeof(pname)-1] = 0; //be happy ;) - return pname; - } -#endif - //---------------------------------------------------------------------------- - bool set_module_name_and_folder(const std::string& path_to_process_) - { - std::string path_to_process = path_to_process_; -#ifdef _WIN32 - path_to_process = get_current_module_path(); -#endif - std::string::size_type a = path_to_process.rfind( '\\' ); - if(a == std::string::npos ) - { - a = path_to_process.rfind( '/' ); - } - if ( a != std::string::npos ) - { - get_current_module_name() = path_to_process.substr(a+1, path_to_process.size()); - get_current_module_folder() = path_to_process.substr(0, a); - return true; - }else - return false; - - } - - //---------------------------------------------------------------------------- - bool trim_left(std::string& str) - { - for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast(*it));) - str.erase(str.begin()); - - return true; - } - //---------------------------------------------------------------------------- - bool trim_right(std::string& str) - { - - for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast(*it));) - str.erase( --((it++).base())); - - return true; - } - //---------------------------------------------------------------------------- - std::string& trim(std::string& str) - { - - trim_left(str); - trim_right(str); - return str; - } - //---------------------------------------------------------------------------- - std::string trim(const std::string& str_) - { - std::string str = str_; - trim_left(str); - trim_right(str); - return str; - } - //---------------------------------------------------------------------------- - std::string get_extension(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('.'); - if(std::string::npos == pos) - return res; - - res = str.substr(pos+1, str.size()-pos); - return res; - } - //---------------------------------------------------------------------------- - std::string get_filename_from_path(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('\\'); - if(std::string::npos == pos) - return str; - - res = str.substr(pos+1, str.size()-pos); - return res; - } - //---------------------------------------------------------------------------- - - - - std::string cut_off_extension(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('.'); - if(std::string::npos == pos) - return str; - - res = str.substr(0, pos); - return res; - } - - //---------------------------------------------------------------------------- -#ifdef _WININET_ - std::string get_string_from_systemtime(const SYSTEMTIME& sys_time) - { - std::string result_string; - - char buff[100] = {0}; - BOOL res = ::InternetTimeFromSystemTimeA(&sys_time, INTERNET_RFC1123_FORMAT, buff, 99); - if(!res) - { - LOG_ERROR("Failed to load SytemTime to string"); - } - - result_string = buff; - return result_string; - - } - //------------------------------------------------------------------------------------- - SYSTEMTIME get_systemtime_from_string(const std::string& buff) - { - SYSTEMTIME result_time = {0}; - - BOOL res = ::InternetTimeToSystemTimeA(buff.c_str(), &result_time, NULL); - if(!res) - { - LOG_ERROR("Failed to load SytemTime from string " << buff << "interval set to 15 minutes"); - } - - return result_time; - } -#endif - -#ifdef WINDOWS_PLATFORM - const wchar_t* get_pc_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetComputerNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } - - const wchar_t* get_user_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetUserNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } -#endif - -#ifdef _LM_ - const wchar_t* get_domain_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = 0; - static bool init = false; - - if (!init) { - LPWSTR domain( NULL ); - NETSETUP_JOIN_STATUS status; - info[0] = 0; - - if (NET_API_STATUS result = NetGetJoinInformation( NULL, &domain, &status )) - { - LOG_ERROR("get_domain_name error: " << log_space::get_win32_err_descr(result)); - } else - { - StringCchCopyW( info, sizeof(info)/sizeof( info[0] ), domain ); - NetApiBufferFree((void*)domain); - init = true; - } - } - - return info; - } -#endif -#ifdef WINDOWS_PLATFORM - inline - std::string load_resource_string_a(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - char buff[2000] = {0}; - - ::LoadStringA( h, id, buff, sizeof(buff)); - buff[sizeof(buff)-1] = 0; //be happy :) - return buff; - } - inline - std::wstring load_resource_string_w(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - wchar_t buff[2000] = {0}; - - ::LoadStringW( h, id, buff, sizeof(buff) / sizeof( buff[0] ) ); - buff[(sizeof(buff)/sizeof(buff[0]))-1] = 0; //be happy :) - return buff; - } -#endif -} -} diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h deleted file mode 100644 index c5d09421..00000000 --- a/contrib/epee/include/string_tools.h +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#ifndef _STRING_TOOLS_H_ -#define _STRING_TOOLS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "warnings.h" - -#ifndef OUT - #define OUT -#endif - -#ifdef WINDOWS_PLATFORM -#pragma comment (lib, "Rpcrt4.lib") -#endif - -// Don't include lexical_cast.hpp, to reduce compilation time -//#include - -namespace boost { - namespace uuids { - struct uuid; - } - - template - inline Target lexical_cast(const Source &arg); -} - -namespace epee -{ -namespace string_tools -{ - std::wstring get_str_from_guid(const boost::uuids::uuid& rid); - std::string get_str_from_guid_a(const boost::uuids::uuid& rid); - bool get_guid_from_string( boost::uuids::uuid& inetifer, std::wstring str_id); - bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id); - //---------------------------------------------------------------------------- - template - std::basic_string buff_to_hex(const std::basic_string& s) - { - std::basic_stringstream hexStream; - hexStream << std::hex << std::noshowbase << std::setw(2); - - for(typename std::basic_string::const_iterator it = s.begin(); it != s.end(); it++) - { - hexStream << "0x"<< static_cast(static_cast(*it)) << " "; - } - return hexStream.str(); - } - //---------------------------------------------------------------------------- - template - std::basic_string buff_to_hex_nodelimer(const std::basic_string& s) - { - std::basic_stringstream hexStream; - hexStream << std::hex << std::noshowbase; - - for(typename std::basic_string::const_iterator it = s.begin(); it != s.end(); it++) - { - hexStream << std::setw(2) << std::setfill('0') << static_cast(static_cast(*it)); - } - return hexStream.str(); - } - //---------------------------------------------------------------------------- - template - bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res) - { - res.clear(); - try - { - long v = 0; - for(size_t i = 0; i < (s.size() + 1) / 2; i++) - { - CharT byte_str[3]; - size_t copied = s.copy(byte_str, 2, 2 * i); - byte_str[copied] = CharT(0); - CharT* endptr; - v = strtoul(byte_str, &endptr, 16); - if (v < 0 || 0xFF < v || endptr != byte_str + copied) - { - return false; - } - res.push_back(static_cast(v)); - } - - return true; - }catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - template - bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod) - { - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(t_pod_type)) - { - return false; - } - else - { - buf.copy(reinterpret_cast(&t_pod), sizeof(t_pod_type)); - return true; - } - } - //---------------------------------------------------------------------------- -PUSH_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - template - inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id) - { - if (std::is_integral::value && !std::numeric_limits::is_signed && !std::is_same::value) - { - for (char c : str_id) - { - if (!std::isdigit(c)) - return false; - } - } - - try - { - val = boost::lexical_cast(str_id); - return true; - } - catch(std::exception& /*e*/) - { - //const char* pmsg = e.what(); - return false; - } - catch(...) - { - return false; - } - - return true; - } -POP_WARNINGS - //--------------------------------------------------- - template - bool get_xnum_from_hex_string(const std::string str, int_t& res ) - { - try - { - std::stringstream ss; - ss << std::hex << str; - ss >> res; - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - template - inline bool xtype_to_string(const XType& val, std::string& str) - { - try - { - str = boost::lexical_cast(val); - } - catch(...) - { - return false; - } - - return true; - } - - typedef std::map command_line_params_a; - typedef std::map command_line_params_w; - - template - bool parse_commandline(std::map& res, int argc, char** argv) - { - t_string key; - for(int i = 1; i < argc; i++) - { - if(!argv[i]) - break; - t_string s = argv[i]; - std::string::size_type p = s.find('='); - if(std::string::npos == p) - { - res[s] = ""; - }else - { - std::string ss; - t_string nm = s.substr(0, p); - t_string vl = s.substr(p+1, s.size()); - res[nm] = vl; - } - } - return true; - } - - template - bool get_xparam_from_command_line(const std::map& res, const t_string & key, t_type& val) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - if(it->second.size()) - { - return get_xtype_from_string(val, it->second); - } - - return true; - } - - template - t_type get_xparam_from_command_line(const std::map& res, const t_string & key, const t_type& default_value) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return default_value; - - if(it->second.size()) - { - t_type s; - get_xtype_from_string(s, it->second); - return s; - } - - return default_value; - } - - template - bool have_in_command_line(const std::map& res, const std::basic_string& key) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - return true; - } - - //---------------------------------------------------------------------------- - std::string get_ip_string_from_int32(uint32_t ip); - bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str); - bool parse_peer_from_string(uint32_t& ip, uint32_t& port, const std::string& addres); - //---------------------------------------------------------------------------- - template - inline std::string get_t_as_hex_nwidth(const t& v, std::streamsize w = 8) - { - std::stringstream ss; - ss << std::setfill ('0') << std::setw (w) << std::hex << std::noshowbase; - ss << v; - return ss.str(); - } - //---------------------------------------------------------------------------- - std::string num_to_string_fast(int64_t val); - bool string_to_num_fast(const std::string& buff, int64_t& val); - bool string_to_num_fast(const std::string& buff, int& val); -#ifdef WINDOWS_PLATFORM - std::string system_time_to_string(const SYSTEMTIME& st); -#endif - bool compare_no_case(const std::string& str1, const std::string& str2); - bool compare_no_case(const std::wstring& str1, const std::wstring& str2); - bool is_match_prefix(const std::wstring& str1, const std::wstring& prefix); - bool is_match_prefix(const std::string& str1, const std::string& prefix); - std::string& get_current_module_name(); - std::string& get_current_module_folder(); -#ifdef _WIN32 - std::string get_current_module_path(); -#endif - bool set_module_name_and_folder(const std::string& path_to_process_); - bool trim_left(std::string& str); - bool trim_right(std::string& str); - std::string& trim(std::string& str); - std::string trim(const std::string& str_); - //---------------------------------------------------------------------------- - template - std::string pod_to_hex(const t_pod_type& s) - { - std::string buff; - buff.assign(reinterpret_cast(&s), sizeof(s)); - return buff_to_hex_nodelimer(buff); - } - //---------------------------------------------------------------------------- - template - bool hex_to_pod(const std::string& hex_str, t_pod_type& s) - { - std::string hex_str_tr = trim(hex_str); - if(sizeof(s)*2 != hex_str.size()) - return false; - std::string bin_buff; - if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) - return false; - if(bin_buff.size()!=sizeof(s)) - return false; - - s = *(t_pod_type*)bin_buff.data(); - return true; - } - //---------------------------------------------------------------------------- - std::string get_extension(const std::string& str); - std::string get_filename_from_path(const std::string& str); - std::string cut_off_extension(const std::string& str); -#ifdef _WININET_ - std::string get_string_from_systemtime(const SYSTEMTIME& sys_time); - SYSTEMTIME get_systemtime_from_string(const std::string& buff); -#endif - -#ifdef WINDOWS_PLATFORM - const DWORD INFO_BUFFER_SIZE = 10000; - - const wchar_t* get_pc_name(); - const wchar_t* get_user_name(); -#endif - -#ifdef _LM_ - const wchar_t* get_domain_name(); -#endif -#ifdef WINDOWS_PLATFORM - std::string load_resource_string_a(int id, const char* pmodule_name = NULL); - std::wstring load_resource_string_w(int id, const char* pmodule_name = NULL); -#endif -} -} -#endif //_STRING_TOOLS_H_ diff --git a/contrib/epee/include/syncobj.h b/contrib/epee/include/syncobj.h deleted file mode 100644 index 52cb70e6..00000000 --- a/contrib/epee/include/syncobj.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef __WINH_OBJ_H__ -#define __WINH_OBJ_H__ - -#include -#include - -namespace epee -{ - struct simple_event - { - simple_event() : m_rised(false) - { - } - - void raise() - { - std::unique_lock lock(m_mx); - m_rised = true; - m_cond_var.notify_one(); - } - - void wait() - { - std::unique_lock lock(m_mx); - while (!m_rised) - m_cond_var.wait(lock); - m_rised = false; - } - - private: - std::mutex m_mx; - std::condition_variable m_cond_var; - bool m_rised; - }; - - class critical_region; - - class critical_section - { - std::recursive_mutex m_section; - - public: - //to make copy fake! - critical_section(const critical_section& section) - { - } - - critical_section() - { - } - - ~critical_section() - { - } - - void lock() - { - m_section.lock(); - } - - void unlock() - { - m_section.unlock(); - } - - bool tryLock() - { - return m_section.try_lock(); - } - - // to make copy fake - critical_section& operator=(const critical_section& section) - { - return *this; - } - }; - - - template - class critical_region_t - { - t_lock& m_locker; - bool m_unlocked; - - critical_region_t(const critical_region_t&) {} - - public: - critical_region_t(t_lock& cs): m_locker(cs), m_unlocked(false) - { - m_locker.lock(); - } - - ~critical_region_t() - { - unlock(); - } - - void unlock() - { - if (!m_unlocked) - { - m_locker.unlock(); - m_unlocked = true; - } - } - }; - - -#if defined(WINDWOS_PLATFORM) - class shared_critical_section - { - public: - shared_critical_section() - { - ::InitializeSRWLock(&m_srw_lock); - } - ~shared_critical_section() - {} - - bool lock_shared() - { - AcquireSRWLockShared(&m_srw_lock); - return true; - } - bool unlock_shared() - { - ReleaseSRWLockShared(&m_srw_lock); - return true; - } - bool lock_exclusive() - { - ::AcquireSRWLockExclusive(&m_srw_lock); - return true; - } - bool unlock_exclusive() - { - ::ReleaseSRWLockExclusive(&m_srw_lock); - return true; - } - private: - SRWLOCK m_srw_lock; - }; - - - class shared_guard - { - public: - shared_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_shared(); - } - - ~shared_guard() - { - m_ref_sec.unlock_shared(); - } - - private: - shared_critical_section& m_ref_sec; - }; - - - class exclusive_guard - { - public: - exclusive_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_exclusive(); - } - - ~exclusive_guard() - { - m_ref_sec.unlock_exclusive(); - } - - private: - shared_critical_section& m_ref_sec; - }; -#endif - -#define SHARED_CRITICAL_REGION_BEGIN(x) { shared_guard critical_region_var(x) -#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { exclusive_guard critical_region_var(x) - -#define CRITICAL_REGION_LOCAL(x) epee::critical_region_t critical_region_var(x) -#define CRITICAL_REGION_BEGIN(x) { epee::critical_region_t critical_region_var(x) -#define CRITICAL_REGION_LOCAL1(x) epee::critical_region_t critical_region_var1(x) -#define CRITICAL_REGION_BEGIN1(x) { epee::critical_region_t critical_region_var1(x) - -#define CRITICAL_REGION_END() } - - -#if defined(WINDWOS_PLATFORM) - inline const char* get_wait_for_result_as_text(DWORD res) - { - switch(res) - { - case WAIT_ABANDONED: return "WAIT_ABANDONED"; - case WAIT_TIMEOUT: return "WAIT_TIMEOUT"; - case WAIT_OBJECT_0: return "WAIT_OBJECT_0"; - case WAIT_OBJECT_0+1: return "WAIT_OBJECT_1"; - case WAIT_OBJECT_0+2: return "WAIT_OBJECT_2"; - default: return "UNKNOWN CODE"; - } - } -#endif - -} - -#endif diff --git a/contrib/epee/include/time_helper.h b/contrib/epee/include/time_helper.h deleted file mode 100644 index 958176da..00000000 --- a/contrib/epee/include/time_helper.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -//#include -//#include -#include -#include -#include "pragma_comp_defs.h" - -namespace epee -{ -namespace misc_utils -{ - -#ifdef __ATLTIME_H__ - - inline - bool get_time_t_from_ole_date(DATE src, time_t& res) - { - SYSTEMTIME st = {0}; - if(TRUE != ::VariantTimeToSystemTime(src, &st)) - return false; - ATL::CTime ss(st); - res = ss.GetTime(); - return true; - } -#endif - inline - std::string get_time_str(const time_t& time_) - { - - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = localtime(&time_); -PRAGMA_WARNING_POP - - if(pt) - strftime( tmpbuf, 199, "%d.%m.%Y %H:%M:%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; - } - - inline - std::string get_time_str_v2(const time_t& time_) - { - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = localtime(&time_); -PRAGMA_WARNING_POP - - if(pt) - strftime( tmpbuf, 199, "%Y_%m_%d %H_%M_%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; - } - - inline - std::string get_time_str_v3(const boost::posix_time::ptime& time_) - { - return boost::posix_time::to_simple_string(time_); - } - - - - inline std::string get_internet_time_str(const time_t& time_) - { - char tmpbuf[200] = {0}; - tm* pt = NULL; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4996) - pt = gmtime(&time_); -PRAGMA_WARNING_POP - strftime( tmpbuf, 199, "%a, %d %b %Y %H:%M:%S GMT", pt ); - return tmpbuf; - } - - inline std::string get_time_interval_string(const time_t& time_) - { - std::string res; - time_t tail = time_; -PRAGMA_WARNING_PUSH -PRAGMA_WARNING_DISABLE_VS(4244) - int days = tail/(60*60*24); - tail = tail%(60*60*24); - int hours = tail/(60*60); - tail = tail%(60*60); - int minutes = tail/(60); - tail = tail%(60); - int seconds = tail; -PRAGMA_WARNING_POP - res = std::string() + "d" + boost::lexical_cast(days) + ".h" + boost::lexical_cast(hours) + ".m" + boost::lexical_cast(minutes) + ".s" + boost::lexical_cast(seconds); - return res; - } - -#ifdef __SQLEXT - inline - bool odbc_time_to_oledb_taime(const SQL_TIMESTAMP_STRUCT& odbc_timestamp, DATE& oledb_date) - { - - SYSTEMTIME st = {0}; - st.wYear = odbc_timestamp.year; - st.wDay = odbc_timestamp.day; - st.wHour = odbc_timestamp.hour ; - st.wMilliseconds = (WORD)odbc_timestamp.fraction ; - st.wMinute = odbc_timestamp.minute ; - st.wMonth = odbc_timestamp.month ; - st.wSecond = odbc_timestamp.second ; - - if(TRUE != ::SystemTimeToVariantTime(&st, &oledb_date)) - return false; - return true; - } - -#endif -} -} \ No newline at end of file diff --git a/contrib/epee/include/tiny_ini.h b/contrib/epee/include/tiny_ini.h deleted file mode 100644 index 2bc71fc1..00000000 --- a/contrib/epee/include/tiny_ini.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _TINY_INI_H_ -#define _TINY_INI_H_ - -#include -#include -#include "string_tools.h" - -namespace epee -{ -namespace tiny_ini -{ - - inline - bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res) - { - std::string expr_str = std::string() + "^("+ param_name +") *=(.*?)$"; - const boost::regex match_ini_entry( expr_str, boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(!boost::regex_search(ini_entry, result, match_ini_entry, boost::match_default)) - return false; - res = result[2]; - string_tools::trim(res); - return true; - } - inline - std::string get_param_value(const std::string& param_name, const std::string& ini_entry) - { - std::string buff; - get_param_value(param_name, ini_entry, buff); - return buff; - } - - template - bool get_param_value_as_t(const std::string& param_name, const std::string& ini_entry, T& res) - { - std::string str_res = get_param_value(param_name, ini_entry); - - string_tools::trim(str_res); - if(!str_res.size()) - return false; - - return string_tools::get_xtype_from_string(res, str_res); - } - -} -} - -#endif //_TINY_INI_H_ diff --git a/contrib/epee/include/to_nonconst_iterator.h b/contrib/epee/include/to_nonconst_iterator.h deleted file mode 100644 index 729b0e8b..00000000 --- a/contrib/epee/include/to_nonconst_iterator.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _TO_NONCONST_ITERATOR_H_ -#define _TO_NONCONST_ITERATOR_H_ - -namespace epee -{ - -template -typename Type::iterator to_nonsonst_iterator(Type& obj, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(obj.begin()), it); - typename Type::iterator res_it = obj.begin()+dist; - return res_it; -} - - -template -typename Type::iterator to_nonsonst_iterator(typename Type::iterator base_it, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(base_it), it); - typename Type::iterator res_it = base_it+dist; - return res_it; -} -}//namespace epee -#endif //_TO_NONCONST_ITERATOR_H_ diff --git a/contrib/epee/include/warnings.h b/contrib/epee/include/warnings.h deleted file mode 100644 index 37d7a290..00000000 --- a/contrib/epee/include/warnings.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#if defined(_MSC_VER) - -#define PUSH_WARNINGS __pragma(warning(push)) -#define POP_WARNINGS __pragma(warning(pop)) -#define DISABLE_VS_WARNINGS(w) __pragma(warning(disable: w)) -#define DISABLE_GCC_WARNING(w) -#define DISABLE_CLANG_WARNING(w) -#define DISABLE_GCC_AND_CLANG_WARNING(w) - -#else - -#include - -#define PUSH_WARNINGS _Pragma("GCC diagnostic push") -#define POP_WARNINGS _Pragma("GCC diagnostic pop") -#define DISABLE_VS_WARNINGS(w) - -#if defined(__clang__) -#define DISABLE_GCC_WARNING(w) -#define DISABLE_CLANG_WARNING DISABLE_GCC_AND_CLANG_WARNING -#else -#define DISABLE_GCC_WARNING DISABLE_GCC_AND_CLANG_WARNING -#define DISABLE_CLANG_WARNING(w) -#endif - -#define DISABLE_GCC_AND_CLANG_WARNING(w) _Pragma(BOOST_PP_STRINGIZE(GCC diagnostic ignored BOOST_PP_STRINGIZE(-W##w))) - -#endif \ No newline at end of file diff --git a/contrib/epee/include/winobj.h b/contrib/epee/include/winobj.h deleted file mode 100644 index 3279cdac..00000000 --- a/contrib/epee/include/winobj.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef __WINH_OBJ_H__ -#define __WINH_OBJ_H__ - -#include - -namespace epee -{ -class critical_region; - -class critical_section { - - boost::mutex m_section; - -public: - - critical_section( const critical_section& section ) { - InitializeCriticalSection( &m_section ); - } - - critical_section() { - InitializeCriticalSection( &m_section ); - } - - ~critical_section() { - DeleteCriticalSection( &m_section ); - } - - void lock() { - EnterCriticalSection( &m_section ); - } - - void unlock() { - LeaveCriticalSection( &m_section ); - } - - bool tryLock() { - return TryEnterCriticalSection( &m_section )? true:false; - } - - critical_section& operator=( const critical_section& section ) - { - return *this; - } - - -}; - -class critical_region { - - ::critical_section *m_locker; - - critical_region( const critical_region& ){} - -public: - - critical_region(critical_section &cs ) { - m_locker = &cs; - cs.lock(); - } - - ~critical_region() - { - m_locker->unlock(); - } -}; - - -class shared_critical_section -{ -public: - shared_critical_section() - { - ::InitializeSRWLock(&m_srw_lock); - } - ~shared_critical_section() - {} - - bool lock_shared() - { - AcquireSRWLockShared(&m_srw_lock); - return true; - } - bool unlock_shared() - { - ReleaseSRWLockShared(&m_srw_lock); - return true; - } - bool lock_exclusive() - { - ::AcquireSRWLockExclusive(&m_srw_lock); - return true; - } - bool unlock_exclusive() - { - ::ReleaseSRWLockExclusive(&m_srw_lock); - return true; - } -private: - SRWLOCK m_srw_lock; - -}; - - -class shared_guard -{ -public: - shared_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_shared(); - } - - ~shared_guard() - { - m_ref_sec.unlock_shared(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class exclusive_guard -{ -public: - exclusive_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_exclusive(); - } - - ~exclusive_guard() - { - m_ref_sec.unlock_exclusive(); - } - -private: - shared_critical_section& m_ref_sec; -}; - - -class event -{ -public: - event() - { - m_hevent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - } - ~event() - { - ::CloseHandle(m_hevent); - - } - - bool set() - { - return ::SetEvent(m_hevent) ? true:false; - } - - bool reset() - { - return ::ResetEvent(m_hevent) ? true:false; - } - - HANDLE get_handle() - { - return m_hevent; - } -private: - HANDLE m_hevent; - -}; - - -#define SHARED_CRITICAL_REGION_BEGIN(x) { shared_guard critical_region_var(x) -#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { exclusive_guard critical_region_var(x) - - - -#define CRITICAL_REGION_LOCAL(x) critical_region critical_region_var(x) -#define CRITICAL_REGION_BEGIN(x) { critical_region critical_region_var(x) -#define CRITICAL_REGION_END() } - - - inline const char* get_wait_for_result_as_text(DWORD res) - { - switch(res) - { - case WAIT_ABANDONED: return "WAIT_ABANDONED"; - case WAIT_TIMEOUT: return "WAIT_TIMEOUT"; - case WAIT_OBJECT_0: return "WAIT_OBJECT_0"; - case WAIT_OBJECT_0+1: return "WAIT_OBJECT_1"; - case WAIT_OBJECT_0+2: return "WAIT_OBJECT_2"; - default: - return "UNKNOWN CODE"; - } - - } - -}// namespace epee - -#endif diff --git a/contrib/epee/include/zlib_helper.h b/contrib/epee/include/zlib_helper.h deleted file mode 100644 index 46c7f48e..00000000 --- a/contrib/epee/include/zlib_helper.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -extern "C" { -#include "zlib/zlib.h" -} -#pragma comment(lib, "zlibstat.lib") - -namespace epee -{ -namespace zlib_helper -{ - inline - bool pack(std::string& target){ - std::string result_packed_buff; - - z_stream zstream = {0}; - int ret = deflateInit(&zstream, Z_DEFAULT_COMPRESSION); - if(target.size()) - { - - - result_packed_buff.resize(target.size()*2, 'X'); - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - zstream.next_out = (Bytef*)result_packed_buff.data(); - zstream.avail_out = (uInt)result_packed_buff.size(); - - ret = deflate(&zstream, Z_FINISH); - CHECK_AND_ASSERT_MES(ret>=0, false, "Failed to deflate. err = " << ret); - - if(result_packed_buff.size() != zstream.avail_out) - result_packed_buff.resize(result_packed_buff.size()-zstream.avail_out); - - - result_packed_buff.erase(0, 2); - target.swap(result_packed_buff); - } - - deflateEnd(& zstream ); - return true; - } - - inline bool unpack(std::string& target) - { - z_stream zstream = {0}; - int ret = inflateInit(&zstream);// - - std::string decode_summary_buff; - size_t ungzip_buff_size = target.size() * 0x30; - std::string current_decode_buff(ungzip_buff_size, 'X'); - - while(target.size()) - { - - - zstream.next_out = (Bytef*)current_decode_buff.data(); - zstream.avail_out = (uInt)ungzip_buff_size; - - int flag = Z_SYNC_FLUSH; - - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - zstream.next_in = (Bytef*) dummy_head; - zstream.avail_in = sizeof(dummy_head); - ret = inflate(&zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - return false; - } - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - - ret = inflate(&zstream, Z_SYNC_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - LOCAL_ASSERT(0); - return false; - } - - - target.erase(0, target.size()-zstream.avail_in); - - - if(ungzip_buff_size == zstream.avail_out) - { - LOG_ERROR("Can't unpack buffer"); - return false; - } - - - current_decode_buff.resize(ungzip_buff_size - zstream.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_buff_size); - } - - inflateEnd(&zstream ); - - decode_summary_buff.swap(target); - return 1; - } - -}; -}//namespace epee diff --git a/contrib/epee/tests/.gitignore b/contrib/epee/tests/.gitignore deleted file mode 100644 index d9b4f015..00000000 --- a/contrib/epee/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/contrib/epee/tests/data/storages/invalid_storage_1.bin b/contrib/epee/tests/data/storages/invalid_storage_1.bin deleted file mode 100644 index fac7b3e9..00000000 Binary files a/contrib/epee/tests/data/storages/invalid_storage_1.bin and /dev/null differ diff --git a/contrib/epee/tests/data/storages/invalid_storage_2.bin b/contrib/epee/tests/data/storages/invalid_storage_2.bin deleted file mode 100644 index a8c29f15..00000000 Binary files a/contrib/epee/tests/data/storages/invalid_storage_2.bin and /dev/null differ diff --git a/contrib/epee/tests/data/storages/invalid_storage_3.bin b/contrib/epee/tests/data/storages/invalid_storage_3.bin deleted file mode 100644 index b5c31aa0..00000000 --- a/contrib/epee/tests/data/storages/invalid_storage_3.bin +++ /dev/null @@ -1 +0,0 @@ -¢IMóÙŸˆm_bo \ No newline at end of file diff --git a/contrib/epee/tests/data/storages/invalid_storage_4.bin b/contrib/epee/tests/data/storages/invalid_storage_4.bin deleted file mode 100644 index 4f8372d1..00000000 Binary files a/contrib/epee/tests/data/storages/invalid_storage_4.bin and /dev/null differ diff --git a/contrib/epee/tests/data/storages/valid_storage.bin b/contrib/epee/tests/data/storages/valid_storage.bin deleted file mode 100644 index e13f780b..00000000 Binary files a/contrib/epee/tests/data/storages/valid_storage.bin and /dev/null differ diff --git a/contrib/epee/tests/generate_vc_proj.bat b/contrib/epee/tests/generate_vc_proj.bat deleted file mode 100644 index a81bdce0..00000000 --- a/contrib/epee/tests/generate_vc_proj.bat +++ /dev/null @@ -1,5 +0,0 @@ -mkdir build -cd build -cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" ../src -cd .. -pause \ No newline at end of file diff --git a/contrib/epee/tests/src/CMakeLists.txt b/contrib/epee/tests/src/CMakeLists.txt deleted file mode 100644 index c7d31735..00000000 --- a/contrib/epee/tests/src/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ - -cmake_minimum_required(VERSION 2.8) - -set(Boost_USE_MULTITHREADED ON) - -include_directories(.) -include_directories(../../include) - -find_package(Boost COMPONENTS system filesystem thread date_time chrono regex) -include_directories( ${Boost_INCLUDE_DIRS} ) - -IF (MSVC) - add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" ) - include_directories(SYSTEM platform/msvc) -ELSE() - # set stuff for other systems - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Werror") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -Wno-reorder") -ENDIF() - - -# Add folders to filters -file(GLOB_RECURSE SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/*.h) - -source_group(general FILES ${SRC}) - - -add_executable(tests ${SRC} ) -target_link_libraries( tests ${Boost_LIBRARIES} ) - diff --git a/contrib/epee/tests/src/misc/test_math.h b/contrib/epee/tests/src/misc/test_math.h deleted file mode 100644 index 8b3064c2..00000000 --- a/contrib/epee/tests/src/misc/test_math.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" - -namespace epee -{ - namespace tests - { - bool test_median() - { - LOG_PRINT_L0("Testing median"); - std::vector sz; - size_t m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 0, false, "test failed"); - sz.push_back(1); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 1, false, "test failed"); - sz.push_back(10); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 5, false, "test failed"); - - sz.clear(); - sz.resize(3); - sz[0] = 0; - sz[1] = 9; - sz[2] = 3; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 3, false, "test failed"); - - sz.clear(); - sz.resize(4); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 41, false, "test failed"); - - - - sz.clear(); - sz.resize(5); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - sz[4] = 11; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 22, false, "test failed"); - return true; - } - } -} - diff --git a/contrib/epee/tests/src/net/test_net.h b/contrib/epee/tests/src/net/test_net.h deleted file mode 100644 index 0b6dc1f7..00000000 --- a/contrib/epee/tests/src/net/test_net.h +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -#include "net/levin_server_cp2.h" -#include "storages/abstract_invoke.h" - -namespace epee -{ -namespace StorageNamed -{ - typedef CInMemStorage DefaultStorageType; -} -namespace tests -{ - struct some_subdata - { - - std::string str1; - std::list array_of_id; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(str1) - SERIALIZE_STL_CONTAINER_POD(array_of_id) - END_NAMED_SERIALIZE_MAP() - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request - { - - std::string example_string_data; - uint64_t example_id_data; - some_subdata sub; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(example_string_data) - SERIALIZE_POD(example_id_data) - SERIALIZE_T(sub) - END_NAMED_SERIALIZE_MAP() - }; - - - struct response - { - bool m_success; - uint64_t example_id_data; - std::list subs; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(m_success) - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_CONTAINER_T(subs) - END_NAMED_SERIALIZE_MAP() - }; - }; - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request - { - std::string example_string_data2; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_ANSI_STRING(example_string_data2) - END_NAMED_SERIALIZE_MAP() - }; - - struct response - { - bool m_success; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_POD(m_success) - END_NAMED_SERIALIZE_MAP() - }; - }; - typedef boost::uuids::uuid uuid; - - class test_levin_server: public levin::levin_commands_handler<> - { - test_levin_server(const test_levin_server&){} - public: - test_levin_server(){} - void set_thread_prefix(const std::string& pref) - { - m_net_server.set_threads_prefix(pref); - } - template - bool connect_async(const std::string adr, const std::string& port, uint32_t conn_timeot, calback_t cb, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect_async(adr, port, conn_timeot, cb, bind_ip); - } - - bool connect(const std::string adr, const std::string& port, uint32_t conn_timeot, net_utils::connection_context_base& cn, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect(adr, port, conn_timeot, cn, bind_ip); - } - void close(net_utils::connection_context_base& cn) - { - m_net_server.get_config_object().close(cn.m_connection_id); - } - - template - bool invoke(uuid con_id, int command, t_request& req, t_response& resp) - { - return invoke_remote_command(con_id, command, req, resp, m_net_server.get_config_object()); - } - - template< class t_response, class t_request, class callback_t> - bool invoke_async(uuid con_id, int command, t_request& req, callback_t cb) - { - return async_invoke_remote_command(con_id, command, req, m_net_server.get_config_object(), cb); - } - - bool init(const std::string& bind_port = "", const std::string& bind_ip = "0.0.0.0") - { - m_net_server.get_config_object().m_pcommands_handler = this; - m_net_server.get_config_object().m_invoke_timeout = 1000; - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool run() - { - //here you can set worker threads count - int thrds_count = 4; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - uint32_t get_binded_port() - { - return m_net_server.get_binded_port(); - } - private: - - - CHAIN_LEVIN_INVOKE_TO_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_TO_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP(test_levin_server) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_1, &test_levin_server::handle_1) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_2, &test_levin_server::handle_2) - END_INVOKE_MAP() - - //----------------- commands handlers ---------------------------------------------- - int handle_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "---->>"); - COMMAND_EXAMPLE_2::request arg_ = AUTO_VAL_INIT(arg_); - arg_.example_id_data = arg.example_id_data; - COMMAND_EXAMPLE_2::response rsp_ = AUTO_VAL_INIT(rsp_); - invoke_async(context.m_connection_id, COMMAND_EXAMPLE_2::ID, arg_, [](int code, const COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - if(code < 0) - {LOG_PRINT_RED_L0("on_command_1: command_2 failed to invoke");} - else - {LOG_PRINT_L0("on_command_1: command_2 response " << rsp.example_id_data);} - }); - rsp.example_id_data = arg.example_id_data; - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "<<----"); - return true; - } - int handle_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_2: id "<< arg.example_id_data); - rsp.example_id_data = arg.example_id_data; - //misc_utils::sleep_no_w(6000); - return true; - } - //---------------------------------------------------------------------------------- - net_utils::boosted_levin_async_server m_net_server; - }; - - - inline - bool do_run_test_server() - { - - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread th1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread th2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initalized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - net_utils::connection_context_base cntxt_1; - bool r = srv1.connect("127.0.0.1", string_tools::num_to_string_fast(port2), 5000, cntxt_1); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - net_utils::connection_context_base cntxt_2; - r = srv2.connect("127.0.0.1", string_tools::num_to_string_fast(port1), 5000, cntxt_2); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - while(true) - { - LOG_PRINT_L0("Invoking from A to B..."); - int r = srv1.invoke(cntxt_1.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke A to B"); - break; - } - - LOG_PRINT_L0("Invoking from B to A..."); - r = srv2.invoke(cntxt_2.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke B to A"); - break; - } - } - srv1.send_stop_signal(); - srv2.send_stop_signal(); - th1.join(); - th1.join(); - - return true; - } - - - - inline bool do_test2_work_with_srv(test_levin_server& srv, int port) - { - uint64_t i = 0; - boost::mutex wait_event; - wait_event.lock(); - while(true) - { - net_utils::connection_context_base cntxt_local = AUTO_VAL_INIT(cntxt_local); - bool r = srv.connect_async("127.0.0.1", string_tools::num_to_string_fast(port), 5000, [&srv, &port, &wait_event, &i, &cntxt_local](const net_utils::connection_context_base& cntxt, const boost::system::error_code& ec) - { - CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " << ec.message() ); - cntxt_local = cntxt; - LOG_PRINT_L0("Invoking command 1 to " << port); - COMMAND_EXAMPLE_1::request arg = AUTO_VAL_INIT(arg); - arg.example_id_data = i; - /*vc2010 workaround*/ - int port_ = port; - boost::mutex& wait_event_ = wait_event; - int r = srv.invoke_async(cntxt.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, [port_, &wait_event_](int code, const COMMAND_EXAMPLE_1::request& rsp, const net_utils::connection_context_base& cntxt) - { - CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke"); - LOG_PRINT_L0("command 1 invoke to " << port_ << " OK."); - wait_event_.unlock(); - }); - }); - wait_event.lock(); - srv.close(cntxt_local); - ++i; - } - return true; - } - - inline - bool do_run_test_server_async_connect() - { - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread thmain1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread thmain2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initalized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - - boost::thread work_1( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_2( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_3( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_4( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_5( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_6( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_7( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_8( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - - - work_1.join(); - work_2.join(); - srv1.send_stop_signal(); - srv2.send_stop_signal(); - thmain1.join(); - thmain2.join(); - - return true; - } - -} -} \ No newline at end of file diff --git a/contrib/epee/tests/src/storages/portable_storages_test.h b/contrib/epee/tests/src/storages/portable_storages_test.h deleted file mode 100644 index ecded8da..00000000 --- a/contrib/epee/tests/src/storages/portable_storages_test.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include "storages/serializeble_struct_helper.h" -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ - namespace tests - { - - struct port_test_struct_sub - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - END_KV_SERIALIZE_MAP() - }; - -#pragma pack (push, 1) - struct some_pod_struct - { - uint64_t a; - int32_t b; - }; -#pragma pack(pop) - - struct port_test_struct - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - some_pod_struct m_pod; - std::list m_list_of_str; - std::list m_list_of_uint64_t; - std::list m_list_of_uint32_t; - std::list m_list_of_uint16_t; - std::list m_list_of_uint8_t; - std::list m_list_of_int64_t; - std::list m_list_of_int32_t; - std::list m_list_of_int16_t; - std::list m_list_of_int8_t; - std::list m_list_of_double; - std::list m_list_of_bool; - port_test_struct_sub m_subobj; - std::list m_list_of_self; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - KV_SERIALIZE_VAL(m_uint64) - KV_SERIALIZE_VAL(m_uint32) - KV_SERIALIZE_VAL(m_uint16) - KV_SERIALIZE_VAL(m_uint8) - KV_SERIALIZE_VAL(m_int64) - KV_SERIALIZE_VAL(m_int32) - KV_SERIALIZE_VAL(m_int16) - KV_SERIALIZE_VAL(m_int8) - KV_SERIALIZE_VAL(m_double) - KV_SERIALIZE_VAL(m_bool) - KV_SERIALIZE_VAL_POD_AS_BLOB(m_pod) - KV_SERIALIZE_OBJ(m_subobj) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_str) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_double) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_bool) - KV_SERIALIZE_CONTAINER_OBJ(m_list_of_self) - END_KV_SERIALIZE_MAP() - }; - - bool operator != (const port_test_struct_sub& a, const port_test_struct_sub& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const port_test_struct& a, const port_test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_pod.a != a.m_pod.a - || b.m_pod.b != a.m_pod.b - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - void fill_struct_with_test_values(port_test_struct& s) - { - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_pod.a = 32342342342342; - s.m_pod.b = -342342; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - } - - bool test_portable_storages(const std::string& tests_folder) - { - serialization::portable_storage ps, ps2; - port_test_struct s1, s2; - fill_struct_with_test_values(s1); - - s1.store(ps); - std::string binbuf; - bool r = ps.store_to_binary(binbuf); - - ps2.load_from_binary(binbuf); - s2.load(ps2); - if(!(s1 == s2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - - port_test_struct ss1, ss2; - fill_struct_with_test_values(ss1); - std::string json_buff = epee::serialization::store_t_to_json(ss1); - epee::serialization::load_t_from_json(ss2, json_buff); - if(!(ss1 == ss2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - return true; - } - - } -} \ No newline at end of file diff --git a/contrib/epee/tests/src/storages/storage_tests.h b/contrib/epee/tests/src/storages/storage_tests.h deleted file mode 100644 index 522e589c..00000000 --- a/contrib/epee/tests/src/storages/storage_tests.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "storages/serializeble_struct_helper.h" -#include "storages/portable_storage.h" - -namespace epee -{ - namespace tests - { - - - struct test_struct - { - - std::string m_str; - unsigned int m_uint; - bool m_bool; - std::list m_list_of_str; - std::list m_list_of_int; - std::list m_list_of_self; - - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(m_str) - SERIALIZE_POD(m_uint) - SERIALIZE_POD(m_bool) - SERIALIZE_STL_CONTAINER_ANSII_STRING(m_list_of_str) - SERIALIZE_STL_CONTAINER_POD(m_list_of_int) - SERIALIZE_STL_CONTAINER_T(m_list_of_self) - END_NAMED_SERIALIZE_MAP() - - }; - - - bool operator == (const test_struct& a, const test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint != a.m_uint - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_int != a.m_list_of_int - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - inline test_struct get_test_struct() - { - test_struct t = boost::value_initialized(); - t.m_bool = true; - t.m_str = "ackamdc'kmecemcececmacmecmcm[aicm[oeicm[oeicm[qaicm[qoe"; - t.m_uint = 233242; - for(int i = 0; i!=500; i++) - t.m_list_of_int.push_back(i); - - for(int i = 0; i!=500; i++) - t.m_list_of_str.push_back("ssccd"); - - for(int i = 0; i!=5; i++) - { - t.m_list_of_self.push_back(t); - } - return t; - } - - bool test_storages(const std::string& tests_folder) - { - - epee::serialization::portable_storage ps; - auto s = ps.open_section("zzz", nullptr); - uint64_t i = 0; - ps.get_value("afdsdf", i, s); - - - LOG_PRINT_L0("Generating test struct..."); - boost::filesystem::path storage_folder = tests_folder; - storage_folder /= "storages"; - - - test_struct t = get_test_struct(); - - LOG_PRINT_L0("Loading test struct from storage..."); - test_struct t2; - bool res = epee::StorageNamed::load_struct_from_storage_file(t2, (storage_folder /+ "valid_storage.bin").string()); - CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin"); - - LOG_PRINT_L0("Comparing generated and loaded test struct..."); - if(!(t == t2)) - return false; - - LOG_PRINT_L0("Loading broken archive 1..."); - test_struct t3; - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_1.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not "); - - - LOG_PRINT_L0("Loading broken archive 2..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_2.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 3..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_3.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 4..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_4.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - return true; - } - } -} - diff --git a/contrib/epee/tests/src/tests.cpp b/contrib/epee/tests/src/tests.cpp deleted file mode 100644 index ed045d83..00000000 --- a/contrib/epee/tests/src/tests.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "include_base_utils.h" -#include "storages/storage_tests.h" -#include "misc/test_math.h" -#include "storages/portable_storages_test.h" -#include "net/test_net.h" - -using namespace epee; - -int main(int argc, char* argv[]) -{ - - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - string_tools::command_line_params_a start_params; - string_tools::parse_commandline(start_params, argc, argv); - std::string tests_data_path; - string_tools::get_xparam_from_command_line(start_params, std::string("/tests_folder"), tests_data_path); - - if(string_tools::have_in_command_line(start_params, std::string("/run_net_tests"))) - { - if(!tests::do_run_test_server()) - { - LOG_ERROR("net tests failed"); - return 1; - } - if(!tests::do_run_test_server_async_connect() ) - { - LOG_ERROR("net tests failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_unit_tests"))) - { - if(!tests::test_median()) - { - LOG_ERROR("median test failed"); - return 1; - } - - - if(!tests::test_storages(tests_data_path)) - { - LOG_ERROR("storage test failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_portable_storage_test"))) - { - tests::test_portable_storages(tests_data_path); - } - return 1; -} \ No newline at end of file diff --git a/include/BlockchainExplorerData.h b/include/BlockchainExplorerData.h new file mode 100644 index 00000000..6e476da6 --- /dev/null +++ b/include/BlockchainExplorerData.h @@ -0,0 +1,130 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include +#include + +#include + +namespace CryptoNote { + +enum class TransactionRemoveReason : uint8_t +{ + INCLUDED_IN_BLOCK = 0, + TIMEOUT = 1 +}; + +struct TransactionOutputToKeyDetails { + std::array txOutKey; +}; + +struct TransactionOutputMultisignatureDetails { + std::vector> keys; + uint32_t requiredSignatures; +}; + +struct TransactionOutputDetails { + uint64_t amount; + uint64_t globalIndex; + + boost::variant< + TransactionOutputToKeyDetails, + TransactionOutputMultisignatureDetails> output; +}; + +struct TransactionOutputReferenceDetails { + std::array transactionHash; + size_t number; +}; + +struct TransactionInputGenerateDetails { + uint64_t height; +}; + +struct TransactionInputToKeyDetails { + std::vector keyOffsets; + std::array keyImage; + uint64_t mixin; + TransactionOutputReferenceDetails output; +}; + +struct TransactionInputMultisignatureDetails { + uint32_t signatures; + TransactionOutputReferenceDetails output; +}; + +struct TransactionInputDetails { + uint64_t amount; + + boost::variant< + TransactionInputGenerateDetails, + TransactionInputToKeyDetails, + TransactionInputMultisignatureDetails> input; +}; + +struct TransactionExtraDetails { + std::vector padding; + std::vector> publicKey; + std::vector nonce; + std::vector raw; +}; + +struct TransactionDetails { + std::array hash; + uint64_t size; + uint64_t fee; + uint64_t totalInputsAmount; + uint64_t totalOutputsAmount; + uint64_t mixin; + uint64_t unlockTime; + uint64_t timestamp; + std::array paymentId; + bool inBlockchain; + std::array blockHash; + uint64_t blockHeight; + TransactionExtraDetails extra; + std::vector>> signatures; + std::vector inputs; + std::vector outputs; +}; + +struct BlockDetails { + uint8_t majorVersion; + uint8_t minorVersion; + uint64_t timestamp; + std::array prevBlockHash; + uint32_t nonce; + bool isOrphaned; + uint64_t height; + std::array hash; + uint64_t difficulty; + uint64_t reward; + uint64_t baseReward; + uint64_t blockSize; + uint64_t transactionsCumulativeSize; + uint64_t alreadyGeneratedCoins; + uint64_t alreadyGeneratedTransactions; + uint64_t sizeMedian; + double penalty; + uint64_t totalFeeAmount; + std::vector transactions; +}; + +} diff --git a/include/IBlockchainExplorer.h b/include/IBlockchainExplorer.h new file mode 100644 index 00000000..3fa65681 --- /dev/null +++ b/include/IBlockchainExplorer.h @@ -0,0 +1,61 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include + +#include "BlockchainExplorerData.h" + +namespace CryptoNote { + +class IBlockchainObserver { +public: + virtual ~IBlockchainObserver() {} + + virtual void blockchainUpdated(const std::vector& newBlocks, const std::vector& orphanedBlocks) {} + virtual void poolUpdated(const std::vector& newTransactions, const std::vector, TransactionRemoveReason>>& removedTransactions) {} + + virtual void blockchainSynchronized(const BlockDetails& topBlock) {} +}; + +class IBlockchainExplorer { +public: + virtual ~IBlockchainExplorer() {}; + + virtual bool addObserver(IBlockchainObserver* observer) = 0; + virtual bool removeObserver(IBlockchainObserver* observer) = 0; + + virtual void init() = 0; + virtual void shutdown() = 0; + + virtual bool getBlocks(const std::vector& blockHeights, std::vector>& blocks) = 0; + virtual bool getBlocks(const std::vector>& blockHashes, std::vector& blocks) = 0; + + virtual bool getBlockchainTop(BlockDetails& topBlock) = 0; + + virtual bool getTransactions(const std::vector>& transactionHashes, std::vector& transactions) = 0; + virtual bool getPoolState(const std::vector>& knownPoolTransactionHashes, std::array knownBlockchainTop, bool& isBlockchainActual, std::vector& newTransactions, std::vector>& removedTransactions) = 0; + + virtual uint64_t getRewardBlocksWindow() = 0; + virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) = 0; + + virtual bool isSynchronized() = 0; +}; + +} diff --git a/include/IMultiWallet.h b/include/IMultiWallet.h index 1b7f18b0..a6eb2c87 100755 --- a/include/IMultiWallet.h +++ b/include/IMultiWallet.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include diff --git a/include/INode.h b/include/INode.h index 968834be..9c53317f 100644 --- a/include/INode.h +++ b/include/INode.h @@ -27,6 +27,8 @@ #include "cryptonote_protocol/cryptonote_protocol_defs.h" #include "rpc/core_rpc_server_commands_defs.h" +#include "BlockchainExplorerData.h" + namespace CryptoNote { class INodeObserver { @@ -36,6 +38,7 @@ public: virtual void localBlockchainUpdated(uint64_t height) {} virtual void lastKnownBlockHeightUpdated(uint64_t height) {} virtual void poolChanged() {} + virtual void blockchainSynchronized(uint64_t topHeight) {} }; struct OutEntry { @@ -78,6 +81,11 @@ public: virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) = 0; virtual void queryBlocks(std::list&& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) = 0; virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) = 0; + + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) = 0; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) = 0; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) = 0; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) = 0; }; } diff --git a/include/ITransaction.h b/include/ITransaction.h index 36e9490d..9c9fe773 100644 --- a/include/ITransaction.h +++ b/include/ITransaction.h @@ -152,6 +152,7 @@ public: // extra virtual void setPaymentId(const Hash& paymentId) = 0; virtual void setExtraNonce(const std::string& nonce) = 0; + virtual void appendExtra(const Blob& extraData) = 0; // Inputs/Outputs virtual size_t addInput(const TransactionTypes::InputKey& input) = 0; diff --git a/src/BlockchainExplorer/BlockchainExplorer.cpp b/src/BlockchainExplorer/BlockchainExplorer.cpp new file mode 100644 index 00000000..e3ec4b5b --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorer.cpp @@ -0,0 +1,523 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "BlockchainExplorer.h" + +#include +#include +#include + +#include "cryptonote_core/cryptonote_format_utils.h" +#include "BlockchainExplorerErrors.h" + +using namespace Logging; + +namespace CryptoNote { + +class NodeRequest { +public: + + NodeRequest(const std::function& request) : requestFunc(request) {} + + std::error_code performBlocking() { + requestFunc(std::bind(&NodeRequest::completeionCallback, this, std::placeholders::_1)); + return promise.get_future().get(); + } + + void performAsync(const INode::Callback& callback) { + requestFunc(callback); + } + +private: + void completeionCallback(std::error_code ec) { + promise.set_value(ec); + } + + std::promise promise; + const std::function requestFunc; +}; + +BlockchainExplorer::BlockchainExplorer(INode& node, Logging::ILogger& logger) : node(node), logger(logger, "BlockchainExplorer"), state(NOT_INITIALIZED) {} + +BlockchainExplorer::~BlockchainExplorer() {} + +bool BlockchainExplorer::addObserver(IBlockchainObserver* observer) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + return observerManager.add(observer); +} + +bool BlockchainExplorer::removeObserver(IBlockchainObserver* observer) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + return observerManager.remove(observer); +} + +void BlockchainExplorer::init() { + if (state.load() != NOT_INITIALIZED) { + logger(ERROR) << "Init called on already initialized BlockchainExplorer."; + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::ALREADY_INITIALIZED)); + } + if (node.addObserver(this)) { + state.store(INITIALIZED); + } else { + logger(ERROR) << "Can't add observer to node."; + state.store(NOT_INITIALIZED); + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::INTERNAL_ERROR)); + } + if (getBlockchainTop(knownBlockchainTop)) { + knownBlockchainTopHeight = knownBlockchainTop.height; + } else { + logger(ERROR) << "Can't get blockchain top."; + state.store(NOT_INITIALIZED); + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::INTERNAL_ERROR)); + } +} + +void BlockchainExplorer::shutdown() { + if (state.load() != INITIALIZED) { + logger(ERROR) << "Shutdown called on not initialized BlockchainExplorer."; + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + node.removeObserver(this); + state.store(NOT_INITIALIZED); +} + +bool BlockchainExplorer::getBlocks(const std::vector& blockHeights, std::vector>& blocks) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Get blocks by height request came."; + NodeRequest request( + std::bind( + static_cast< + void(INode::*)( + const std::vector&, + std::vector>&, + const INode::Callback& + ) + >(&INode::getBlocks), + std::ref(node), + std::cref(blockHeights), + std::ref(blocks), + std::placeholders::_1 + ) + ); + std::error_code ec = request.performBlocking(); + if (ec) { + logger(ERROR) << "Can't get blocks by height: " << ec.message(); + throw std::system_error(ec); + } + assert(blocks.size() == blockHeights.size()); + return true; +} + +bool BlockchainExplorer::getBlocks(const std::vector>& blockHashes, std::vector& blocks) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Get blocks by hash request came."; + NodeRequest request( + std::bind( + static_cast< + void(INode::*)( + const std::vector&, + std::vector&, + const INode::Callback& + ) + >(&INode::getBlocks), + std::ref(node), + std::cref(reinterpret_cast&>(blockHashes)), + std::ref(blocks), + std::placeholders::_1 + ) + ); + std::error_code ec = request.performBlocking(); + if (ec) { + logger(ERROR) << "Can't get blocks by hash: " << ec.message(); + throw std::system_error(ec); + } + assert(blocks.size() == blockHashes.size()); + return true; +} + +bool BlockchainExplorer::getBlockchainTop(BlockDetails& topBlock) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Get blockchain top request came."; + uint64_t lastHeight = node.getLastLocalBlockHeight(); + + std::vector heights; + heights.push_back(std::move(lastHeight)); + + std::vector> blocks; + if (!getBlocks(heights, blocks)) { + logger(ERROR) << "Can't get blockchain top."; + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::INTERNAL_ERROR)); + } + assert(blocks.size() == heights.size() && blocks.size() == 1); + + bool gotMainchainBlock = false; + for (const BlockDetails& block : blocks.back()) { + if (!block.isOrphaned) { + topBlock = block; + gotMainchainBlock = true; + break; + } + } + + if (!gotMainchainBlock) { + logger(ERROR) << "Can't get blockchain top: all blocks on height " << lastHeight << " are orphaned."; + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::INTERNAL_ERROR)); + } + return true; +} + +bool BlockchainExplorer::getTransactions(const std::vector>& transactionHashes, std::vector& transactions) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Get transactions request came."; + NodeRequest request( + std::bind( + &INode::getTransactions, + std::ref(node), + std::cref(reinterpret_cast&>(transactionHashes)), + std::ref(transactions), + std::placeholders::_1 + ) + ); + std::error_code ec = request.performBlocking(); + if (ec) { + logger(ERROR) << "Can't get transactions: " << ec.message(); + throw std::system_error(ec); + } + return true; +} + +bool BlockchainExplorer::getPoolState(const std::vector>& knownPoolTransactionHashes, std::array knownBlockchainTopHash, bool& isBlockchainActual, std::vector& newTransactions, std::vector>& removedTransactions) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Get pool state request came."; + std::vector rawNewTransactions; + + NodeRequest request( + [&](const INode::Callback& callback) { + std::vector hashes; + for (const std::array& hash : knownPoolTransactionHashes) { + hashes.push_back(std::move(reinterpret_cast(hash))); + } + node.getPoolSymmetricDifference( + std::move(hashes), + reinterpret_cast(knownBlockchainTopHash), + isBlockchainActual, + rawNewTransactions, + reinterpret_cast&>(removedTransactions), + callback + ); + } + ); + std::error_code ec = request.performBlocking(); + if (ec) { + logger(ERROR) << "Can't get pool state: " << ec.message(); + throw std::system_error(ec); + } + + std::vector> newTransactionsHashes; + for (const Transaction& rawTransaction : rawNewTransactions) { + crypto::hash transactionHash = get_transaction_hash(rawTransaction); + newTransactionsHashes.push_back(std::move(reinterpret_cast&>(transactionHash))); + } + + return getTransactions(newTransactionsHashes, newTransactions); +} + +uint64_t BlockchainExplorer::getRewardBlocksWindow() { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + return parameters::CRYPTONOTE_REWARD_BLOCKS_WINDOW; +} + +uint64_t BlockchainExplorer::getFullRewardMaxBlockSize(uint8_t majorVersion) { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + if (majorVersion > 1) { + return parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + } else { + return parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; + } +} + +bool BlockchainExplorer::isSynchronized() { + if (state.load() != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes::NOT_INITIALIZED)); + } + + logger(DEBUGGING) << "Synchronization status request came."; + bool syncStatus = false; + NodeRequest request( + std::bind( + &INode::isSynchronized, + std::ref(node), + std::ref(syncStatus), + std::placeholders::_1 + ) + ); + std::error_code ec = request.performBlocking(); + if (ec) { + logger(ERROR) << "Can't get synchronization status: " << ec.message(); + throw std::system_error(ec); + } + return syncStatus; +} + +void BlockchainExplorer::poolChanged() { + logger(DEBUGGING) << "Got poolChanged notification."; + + std::unique_lock lock(mutex); + + std::shared_ptr> rawNewTransactionsPtr = std::make_shared>(); + std::shared_ptr> removedTransactionsPtr = std::make_shared>(); + std::shared_ptr isBlockchainActualPtr = std::make_shared(false); + + NodeRequest request( + [this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](const INode::Callback& callback) { + std::vector hashes; + for (const crypto::hash& hash : knownPoolState) { + hashes.push_back(std::move(hash)); + } + node.getPoolSymmetricDifference( + std::move(hashes), + reinterpret_cast(knownBlockchainTop.hash), + *isBlockchainActualPtr, + *rawNewTransactionsPtr, + *removedTransactionsPtr, + callback + ); + } + ); + request.performAsync( + [this, rawNewTransactionsPtr, removedTransactionsPtr, isBlockchainActualPtr](std::error_code ec) { + if (ec) { + logger(ERROR) << "Can't send poolChanged notification because can't get pool symmetric difference: " << ec.message(); + return; + } + + if (!*isBlockchainActualPtr) { + logger(WARNING) << "Blockchain not actual."; + } + + std::unique_lock lock(mutex); + + std::shared_ptr> newTransactionsHashesPtr = std::make_shared>(); + for (const Transaction& rawTransaction : *rawNewTransactionsPtr) { + crypto::hash transactionHash = get_transaction_hash(rawTransaction); + bool inserted = knownPoolState.emplace(transactionHash).second; + if (inserted) { + newTransactionsHashesPtr->push_back(std::move(transactionHash)); + } + } + + std::shared_ptr, TransactionRemoveReason>>> removedTransactionsHashesPtr = std::make_shared, TransactionRemoveReason>>>(); + for (const crypto::hash hash : *removedTransactionsPtr) { + auto iter = knownPoolState.find(hash); + if (iter != knownPoolState.end()) { + removedTransactionsHashesPtr->push_back( + std::move(std::make_pair( + reinterpret_cast&>(hash), + TransactionRemoveReason::INCLUDED_IN_BLOCK //Can't have real reason here. + )) + ); + knownPoolState.erase(iter); + } + } + + std::shared_ptr> newTransactionsPtr = std::make_shared>(); + NodeRequest request( + std::bind( + &INode::getTransactions, + std::ref(node), + std::cref(*newTransactionsHashesPtr), + std::ref(*newTransactionsPtr), + std::placeholders::_1 + ) + ); + request.performAsync( + [this, newTransactionsHashesPtr, newTransactionsPtr, removedTransactionsHashesPtr](std::error_code ec) { + if (ec) { + logger(ERROR) << "Can't send poolChanged notification because can't get transactions: " << ec.message(); + return; + } + if (!newTransactionsPtr->empty() || !removedTransactionsHashesPtr->empty()) { + observerManager.notify(&IBlockchainObserver::poolUpdated, *newTransactionsPtr, *removedTransactionsHashesPtr); + logger(DEBUGGING) << "poolUpdated notification was successfully sent."; + } + } + ); + } + ); + +} + +void BlockchainExplorer::blockchainSynchronized(uint64_t topHeight) { + logger(DEBUGGING) << "Got blockchainSynchronized notification."; + + std::shared_ptr> blockHeightsPtr = std::make_shared>(); + std::shared_ptr>> blocksPtr = std::make_shared>>(); + + blockHeightsPtr->push_back(topHeight); + + NodeRequest request( + std::bind( + static_cast< + void(INode::*)( + const std::vector&, + std::vector>&, + const INode::Callback& + ) + >(&INode::getBlocks), + std::ref(node), + std::cref(*blockHeightsPtr), + std::ref(*blocksPtr), + std::placeholders::_1 + ) + ); + + request.performAsync( + [this, blockHeightsPtr, blocksPtr, topHeight](std::error_code ec) { + if (ec) { + logger(ERROR) << "Can't send blockchainSynchronized notification because can't get blocks by height: " << ec.message(); + return; + } + assert(blocksPtr->size() == blockHeightsPtr->size() && blocksPtr->size() == 1); + + BlockDetails topMainchainBlock; + bool gotMainchainBlock = false; + for (const BlockDetails& block : blocksPtr->back()) { + if (!block.isOrphaned) { + topMainchainBlock = block; + gotMainchainBlock = true; + break; + } + } + + if (!gotMainchainBlock) { + logger(ERROR) << "Can't send blockchainSynchronized notification because can't get blockchain top: all blocks on height " << topHeight << " are orphaned."; + return; + } + + observerManager.notify(&IBlockchainObserver::blockchainSynchronized, topMainchainBlock); + logger(DEBUGGING) << "blockchainSynchronized notification was successfully sent."; + } + ); +} + +void BlockchainExplorer::localBlockchainUpdated(uint64_t height) { + logger(DEBUGGING) << "Got localBlockchainUpdated notification."; + + std::unique_lock lock(mutex); + + assert(height >= knownBlockchainTopHeight); + + std::shared_ptr> blockHeightsPtr = std::make_shared>(); + std::shared_ptr>> blocksPtr = std::make_shared>>(); + + for (size_t i = knownBlockchainTopHeight; i <= height; ++i) { + blockHeightsPtr->push_back(i); + } + + knownBlockchainTopHeight = height; + + NodeRequest request( + std::bind( + static_cast< + void(INode::*)( + const std::vector&, + std::vector>&, + const INode::Callback& + ) + >(&INode::getBlocks), + std::ref(node), + std::cref(*blockHeightsPtr), + std::ref(*blocksPtr), + std::placeholders::_1 + ) + ); + + request.performAsync( + [this, blockHeightsPtr, blocksPtr](std::error_code ec) { + if (ec) { + logger(ERROR) << "Can't send blockchainUpdated notification because can't get blocks by height: " << ec.message(); + return; + } + assert(blocksPtr->size() == blockHeightsPtr->size()); + + std::unique_lock lock(mutex); + + BlockDetails topMainchainBlock; + bool gotTopMainchainBlock = false; + uint64_t topHeight = 0; + + std::vector newBlocks; + std::vector orphanedBlocks; + for (const std::vector& sameHeightBlocks : *blocksPtr) { + for (const BlockDetails& block : sameHeightBlocks) { + if (topHeight < block.height) { + topHeight = block.height; + gotTopMainchainBlock = false; + } + if (block.isOrphaned) { + orphanedBlocks.push_back(block); + } else { + if (block.height > knownBlockchainTop.height || block.hash != knownBlockchainTop.hash) { + newBlocks.push_back(block); + } + if (!gotTopMainchainBlock) { + topMainchainBlock = block; + gotTopMainchainBlock = true; + } + } + } + } + + if (!gotTopMainchainBlock) { + logger(ERROR) << "Can't send localBlockchainUpdated notification because can't get blockchain top: all blocks on height " << topHeight << " are orphaned."; + return; + } + + knownBlockchainTop = topMainchainBlock; + + observerManager.notify(&IBlockchainObserver::blockchainUpdated, newBlocks, orphanedBlocks); + logger(DEBUGGING) << "localBlockchainUpdated notification was successfully sent."; + } + ); +} + +} diff --git a/src/BlockchainExplorer/BlockchainExplorer.h b/src/BlockchainExplorer/BlockchainExplorer.h new file mode 100644 index 00000000..d3c644d3 --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorer.h @@ -0,0 +1,88 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include +#include + +#include "IBlockchainExplorer.h" +#include "INode.h" + +#include "Common/ObserverManager.h" +#include "BlockchainExplorerErrors.h" + +#include "Logging/LoggerRef.h" + +namespace CryptoNote { + +class BlockchainExplorer : public IBlockchainExplorer, public INodeObserver { +public: + BlockchainExplorer(INode& node, Logging::ILogger& logger); + + BlockchainExplorer(const BlockchainExplorer&) = delete; + BlockchainExplorer(BlockchainExplorer&&) = delete; + + BlockchainExplorer& operator=(const BlockchainExplorer&) = delete; + BlockchainExplorer& operator=(BlockchainExplorer&&) = delete; + + virtual ~BlockchainExplorer(); + + virtual bool addObserver(IBlockchainObserver* observer) override; + virtual bool removeObserver(IBlockchainObserver* observer) override; + + virtual bool getBlocks(const std::vector& blockHeights, std::vector>& blocks) override; + virtual bool getBlocks(const std::vector>& blockHashes, std::vector& blocks) override; + + virtual bool getBlockchainTop(BlockDetails& topBlock) override; + + virtual bool getTransactions(const std::vector>& transactionHashes, std::vector& transactions) override; + virtual bool getPoolState(const std::vector>& knownPoolTransactionHashes, std::array knownBlockchainTop, bool& isBlockchainActual, std::vector& newTransactions, std::vector>& removedTransactions) override; + + virtual uint64_t getRewardBlocksWindow() override; + virtual uint64_t getFullRewardMaxBlockSize(uint8_t majorVersion) override; + + virtual bool isSynchronized() override; + + virtual void init() override; + virtual void shutdown() override; + + virtual void poolChanged() override; + virtual void blockchainSynchronized(uint64_t topHeight) override; + virtual void localBlockchainUpdated(uint64_t height) override; + +private: + enum State { + NOT_INITIALIZED, + INITIALIZED + }; + + BlockDetails knownBlockchainTop; + uint64_t knownBlockchainTopHeight; + std::unordered_set knownPoolState; + + std::atomic state; + tools::ObserverManager observerManager; + + std::mutex mutex; + + INode& node; + Logging::LoggerRef logger; + +}; +} diff --git a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp new file mode 100644 index 00000000..336b9342 --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp @@ -0,0 +1,358 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "BlockchainExplorerDataBuilder.h" + +#include +#include + +#include "Common/StringTools.h" +#include "cryptonote_core/cryptonote_format_utils.h" + +namespace CryptoNote { + +BlockchainExplorerDataBuilder::BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol) : + core(core), + protocol(protocol) +{ +} + +bool BlockchainExplorerDataBuilder::getMixin(const Transaction& transaction, uint64_t& mixin) { + mixin = 0; + for (const TransactionInput& txin : transaction.vin) { + if (txin.type() != typeid(TransactionInputToKey)) { + continue; + } + uint64_t currentMixin = boost::get(txin).keyOffsets.size(); + if (currentMixin > mixin) { + mixin = currentMixin; + } + } + return true; +} + +bool BlockchainExplorerDataBuilder::getPaymentId(const Transaction& transaction, crypto::hash& paymentId) { + std::vector txExtraFields; + parse_tx_extra(transaction.extra, txExtraFields); + tx_extra_nonce extraNonce; + if (!find_tx_extra_field_by_type(txExtraFields, extraNonce)) { + return false; + } + return get_payment_id_from_tx_extra_nonce(extraNonce.nonce, paymentId); +} + +bool BlockchainExplorerDataBuilder::fillTxExtra(const std::vector& rawExtra, TransactionExtraDetails& extraDetails) { + extraDetails.raw = rawExtra; + std::vector txExtraFields; + parse_tx_extra(rawExtra, txExtraFields); + for (const tx_extra_field& field : txExtraFields) { + if (typeid(tx_extra_padding) == field.type()) { + extraDetails.padding.push_back(std::move(boost::get(field).size)); + } + else if (typeid(tx_extra_pub_key) == field.type()) { + extraDetails.publicKey.push_back(std::move(reinterpret_cast&>(boost::get(field).pub_key))); + } + else if (typeid(tx_extra_nonce) == field.type()) { + extraDetails.nonce.push_back(std::move(Common::toHex(boost::get(field).nonce.data(), boost::get(field).nonce.size()))); + } + } + return true; +} + +size_t BlockchainExplorerDataBuilder::median(std::vector& v) { + if(v.empty()) + return boost::value_initialized(); + if(v.size() == 1) + return v[0]; + + size_t n = (v.size()) / 2; + std::sort(v.begin(), v.end()); + //nth_element(v.begin(), v.begin()+n-1, v.end()); + if(v.size()%2) + {//1, 3, 5... + return v[n]; + }else + {//2, 4, 6... + return (v[n-1] + v[n])/2; + } + +} + +bool BlockchainExplorerDataBuilder::fillBlockDetails(const Block &block, BlockDetails& blockDetails) { + crypto::hash hash = get_block_hash(block); + + blockDetails.majorVersion = block.majorVersion; + blockDetails.minorVersion = block.minorVersion; + blockDetails.timestamp = block.timestamp; + blockDetails.prevBlockHash = reinterpret_cast&>(block.prevId); + blockDetails.nonce = block.nonce; + blockDetails.hash = reinterpret_cast&>(hash); + + blockDetails.reward = 0; + for (const TransactionOutput& out : block.minerTx.vout) { + blockDetails.reward += out.amount; + } + + if (block.minerTx.vin.front().type() != typeid(TransactionInputGenerate)) + return false; + blockDetails.height = boost::get(block.minerTx.vin.front()).height; + + crypto::hash tmpHash = core.getBlockIdByHeight(blockDetails.height); + blockDetails.isOrphaned = hash != tmpHash; + + if (!core.getBlockDifficulty(blockDetails.height, blockDetails.difficulty)) { + return false; + } + + std::vector blocksSizes; + if (!core.getBackwardBlocksSizes(blockDetails.height, blocksSizes, parameters::CRYPTONOTE_REWARD_BLOCKS_WINDOW)) { + return false; + } + blockDetails.sizeMedian = median(blocksSizes); + + size_t blockSize = 0; + if (!core.getBlockSize(hash, blockSize)) { + return false; + } + blockDetails.transactionsCumulativeSize = blockSize; + + size_t blokBlobSize = get_object_blobsize(block); + size_t minerTxBlobSize = get_object_blobsize(block.minerTx); + blockDetails.blockSize = blokBlobSize + blockDetails.transactionsCumulativeSize - minerTxBlobSize; + + if (!core.getAlreadyGeneratedCoins(hash, blockDetails.alreadyGeneratedCoins)) { + return false; + } + + blockDetails.alreadyGeneratedTransactions = 0; //TODO + + uint64_t prevBlockGeneratedCoins = 0; + if (blockDetails.height > 0) + { + if (!core.getAlreadyGeneratedCoins(block.prevId, prevBlockGeneratedCoins)) { + return false; + } + } + uint64_t maxReward = 0; + uint64_t currentReward = 0; + int64_t emissionChange = 0; + bool penalizeFee = block.majorVersion >= 2; + if(!core.getBlockReward(blockDetails.sizeMedian, 0, prevBlockGeneratedCoins, 0, penalizeFee, maxReward, emissionChange)) + { + return false; + } + if(!core.getBlockReward(blockDetails.sizeMedian, blockDetails.transactionsCumulativeSize, prevBlockGeneratedCoins, 0, penalizeFee, currentReward, emissionChange)) + { + return false; + } + + blockDetails.baseReward = maxReward; + if (maxReward == 0 && currentReward == 0) + { + blockDetails.penalty = static_cast(0); + } + else + { + if (maxReward < currentReward) { + return false; + } + blockDetails.penalty = static_cast(maxReward - currentReward) / static_cast(maxReward); + } + + + blockDetails.transactions.reserve(block.txHashes.size() + 1); + TransactionDetails transactionDetails; + if (!fillTransactionDetails(block.minerTx, transactionDetails, block.timestamp)) { + return false; + } + blockDetails.transactions.push_back(std::move(transactionDetails)); + + std::list found; + std::list missed; + core.getTransactions(block.txHashes, found, missed); + if (found.size() != block.txHashes.size()) { + return false; + } + + blockDetails.totalFeeAmount = 0; + + for (const Transaction& tx : found) { + TransactionDetails transactionDetails; + if (!fillTransactionDetails(tx, transactionDetails, block.timestamp)) { + return false; + } + blockDetails.transactions.push_back(std::move(transactionDetails)); + blockDetails.totalFeeAmount += transactionDetails.fee; + } + return true; +} + +bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& transaction, TransactionDetails& transactionDetails, uint64_t timestamp) { + crypto::hash hash = get_transaction_hash(transaction); + transactionDetails.hash = reinterpret_cast&>(hash); + + transactionDetails.timestamp = timestamp; + + crypto::hash blockHash; + uint64_t blockHeight; + if (!core.getBlockContainingTx(hash, blockHash, blockHeight)) { + transactionDetails.inBlockchain = false; + transactionDetails.blockHeight = boost::value_initialized(); + transactionDetails.blockHash = boost::value_initialized>(); + } else { + transactionDetails.inBlockchain = true; + transactionDetails.blockHeight = blockHeight; + transactionDetails.blockHash = reinterpret_cast&>(blockHash); + if (timestamp == 0) { + Block block; + if (!core.getBlockByHash(blockHash, block)) { + return false; + } + transactionDetails.timestamp = block.timestamp; + } + } + + transactionDetails.size = get_object_blobsize(transaction); + transactionDetails.unlockTime = transaction.unlockTime; + transactionDetails.totalOutputsAmount = get_outs_money_amount(transaction); + + uint64_t inputsAmount; + if (!get_inputs_money_amount(transaction, inputsAmount)) { + return false; + } + transactionDetails.totalInputsAmount = inputsAmount; + + if (transaction.vin.size() > 0 && transaction.vin.front().type() == typeid(TransactionInputGenerate)) { + //It's gen transaction + transactionDetails.fee = 0; + transactionDetails.mixin = 0; + } else { + uint64_t fee; + if (!get_tx_fee(transaction, fee)) { + return false; + } + transactionDetails.fee = fee; + uint64_t mixin; + if (!getMixin(transaction, mixin)) { + return false; + } + transactionDetails.mixin = mixin; + } + + crypto::hash paymentId; + if (getPaymentId(transaction, paymentId)) { + transactionDetails.paymentId = reinterpret_cast&>(paymentId); + } + else { + transactionDetails.paymentId = boost::value_initialized>(); + } + + fillTxExtra(transaction.extra, transactionDetails.extra); + + transactionDetails.signatures.reserve(transaction.signatures.size()); + for (const std::vector& signatures : transaction.signatures) { + std::vector> signaturesDetails; + signaturesDetails.reserve(signatures.size()); + for (const crypto::signature& signature : signatures) { + signaturesDetails.push_back(std::move(reinterpret_cast&>(signature))); + } + transactionDetails.signatures.push_back(std::move(signaturesDetails)); + } + + transactionDetails.inputs.reserve(transaction.vin.size()); + for (const TransactionInput& txIn : transaction.vin) { + TransactionInputDetails txInDetails; + + if (txIn.type() == typeid(TransactionInputGenerate)) { + TransactionInputGenerateDetails txInGenDetails; + txInGenDetails.height = boost::get(txIn).height; + txInDetails.amount = 0; + for (const TransactionOutput& out : transaction.vout) { + txInDetails.amount += out.amount; + } + txInDetails.input = txInGenDetails; + } else if (txIn.type() == typeid(TransactionInputToKey)) { + TransactionInputToKeyDetails txInToKeyDetails; + const TransactionInputToKey& txInToKey = boost::get(txIn); + std::list> outputReferences; + if (!core.scanOutputkeysForIndices(txInToKey, outputReferences)) { + return false; + } + txInDetails.amount = txInToKey.amount; + txInToKeyDetails.keyOffsets = txInToKey.keyOffsets; + txInToKeyDetails.keyImage = reinterpret_cast&>(txInToKey.keyImage); + txInToKeyDetails.mixin = txInToKey.keyOffsets.size(); + txInToKeyDetails.output.number = outputReferences.back().second; + txInToKeyDetails.output.transactionHash = reinterpret_cast&>(outputReferences.back().first); + txInDetails.input = txInToKeyDetails; + } else if (txIn.type() == typeid(TransactionInputMultisignature)) { + TransactionInputMultisignatureDetails txInMultisigDetails; + const TransactionInputMultisignature& txInMultisig = boost::get(txIn); + txInDetails.amount = txInMultisig.amount; + txInMultisigDetails.signatures = txInMultisig.signatures; + std::pair outputReference; + if (!core.getMultisigOutputReference(txInMultisig, outputReference)) { + return false; + } + txInMultisigDetails.output.number = outputReference.second; + txInMultisigDetails.output.transactionHash = reinterpret_cast&>(outputReference.first); + txInDetails.input = txInMultisigDetails; + } else { + return false; + } + transactionDetails.inputs.push_back(std::move(txInDetails)); + } + + transactionDetails.outputs.reserve(transaction.vout.size()); + std::vector globalIndices; + globalIndices.reserve(transaction.vout.size()); + if (!core.get_tx_outputs_gindexs(hash, globalIndices)) { + for (size_t i = 0; i < transaction.vout.size(); ++i) { + globalIndices.push_back(0); + } + } + + typedef boost::tuple outputWithIndex; + auto range = boost::combine(transaction.vout, globalIndices); + for (const outputWithIndex& txOutput : range) { + TransactionOutputDetails txOutDetails; + txOutDetails.amount = txOutput.get<0>().amount; + txOutDetails.globalIndex = txOutput.get<1>(); + + if (txOutput.get<0>().target.type() == typeid(TransactionOutputToKey)) { + TransactionOutputToKeyDetails txOutToKeyDetails; + txOutToKeyDetails.txOutKey = reinterpret_cast&>(boost::get(txOutput.get<0>().target).key); + txOutDetails.output = txOutToKeyDetails; + } else if (txOutput.get<0>().target.type() == typeid(TransactionOutputMultisignature)) { + TransactionOutputMultisignatureDetails txOutMultisigDetails; + TransactionOutputMultisignature txOutMultisig = boost::get(txOutput.get<0>().target); + txOutMultisigDetails.keys.reserve(txOutMultisig.keys.size()); + for (const crypto::public_key& key : txOutMultisig.keys) { + txOutMultisigDetails.keys.push_back(std::move(reinterpret_cast&>(key))); + } + txOutMultisigDetails.requiredSignatures = txOutMultisig.requiredSignatures; + txOutDetails.output = txOutMultisigDetails; + } else { + return false; + } + transactionDetails.outputs.push_back(std::move(txOutDetails)); + } + + return true; +} + +} diff --git a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h new file mode 100644 index 00000000..c7a3ea65 --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.h @@ -0,0 +1,52 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include + +#include "cryptonote_protocol/ICryptonoteProtocolQuery.h" +#include "cryptonote_core/ICore.h" +#include "BlockchainExplorerData.h" + +namespace CryptoNote { + +class BlockchainExplorerDataBuilder +{ +public: + BlockchainExplorerDataBuilder(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol); + + BlockchainExplorerDataBuilder(const BlockchainExplorerDataBuilder&) = delete; + BlockchainExplorerDataBuilder(BlockchainExplorerDataBuilder&&) = delete; + + BlockchainExplorerDataBuilder& operator=(const BlockchainExplorerDataBuilder&) = delete; + BlockchainExplorerDataBuilder& operator=(BlockchainExplorerDataBuilder&&) = delete; + + bool fillBlockDetails(const Block& block, BlockDetails& blockDetails); + bool fillTransactionDetails(const Transaction &tx, TransactionDetails& txRpcInfo, uint64_t timestamp = 0); + +private: + bool getMixin(const Transaction& transaction, uint64_t& mixin); + bool getPaymentId(const Transaction& transaction, crypto::hash& paymentId); + bool fillTxExtra(const std::vector& rawExtra, TransactionExtraDetails& extraDetails); + size_t median(std::vector& v); + + CryptoNote::ICore& core; + CryptoNote::ICryptonoteProtocolQuery& protocol; +}; +} diff --git a/src/BlockchainExplorer/BlockchainExplorerErrors.cpp b/src/BlockchainExplorer/BlockchainExplorerErrors.cpp new file mode 100644 index 00000000..e5adeff0 --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorerErrors.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "BlockchainExplorerErrors.h" + +namespace CryptoNote { +namespace error { + +BlockchainExplorerErrorCategory BlockchainExplorerErrorCategory::INSTANCE; + +} //namespace error +} //namespace CryptoNote + diff --git a/src/BlockchainExplorer/BlockchainExplorerErrors.h b/src/BlockchainExplorer/BlockchainExplorerErrors.h new file mode 100644 index 00000000..fc02f317 --- /dev/null +++ b/src/BlockchainExplorer/BlockchainExplorerErrors.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include + +namespace CryptoNote { +namespace error { + +enum class BlockchainExplorerErrorCodes : int { + NOT_INITIALIZED = 1, + ALREADY_INITIALIZED, + INTERNAL_ERROR, + REQUEST_ERROR +}; + +class BlockchainExplorerErrorCategory : public std::error_category { +public: + static BlockchainExplorerErrorCategory INSTANCE; + + virtual const char* name() const throw() { + return "BlockchainExplorerErrorCategory"; + } + + virtual std::error_condition default_error_condition(int ev) const throw() { + return std::error_condition(ev, *this); + } + + virtual std::string message(int ev) const { + switch (ev) { + case static_cast(BlockchainExplorerErrorCodes::NOT_INITIALIZED): return "Object was not initialized"; + case static_cast(BlockchainExplorerErrorCodes::ALREADY_INITIALIZED): return "Object has been already initialized"; + case static_cast(BlockchainExplorerErrorCodes::INTERNAL_ERROR): return "Internal error"; + case static_cast(BlockchainExplorerErrorCodes::REQUEST_ERROR): return "Error in request parameters"; + default: return "Unknown error"; + } + } + +private: + BlockchainExplorerErrorCategory() { + } +}; + +} //namespace error +} //namespace CryptoNote + +inline std::error_code make_error_code(CryptoNote::error::BlockchainExplorerErrorCodes e) { + return std::error_code(static_cast(e), CryptoNote::error::BlockchainExplorerErrorCategory::INSTANCE); +} + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd4b2578..1ebd2854 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_definitions(-DSTATICLIB) +file(GLOB_RECURSE BlockchainExplorer BlockchainExplorer/*) file(GLOB_RECURSE Common Common/*) file(GLOB_RECURSE ConnectivityTool connectivity_tool/*) file(GLOB_RECURSE Crypto crypto/*) @@ -26,8 +27,10 @@ file(GLOB_RECURSE Transfers transfers/*) file(GLOB_RECURSE Wallet wallet/*) file(GLOB_RECURSE PaymentService payment_service/*) + source_group("" FILES ${Common} ${ConnectivityTool} ${Crypto} ${CryptoNote} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${Http} ${Logging} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet}) +add_library(BlockchainExplorer ${BlockchainExplorer}) add_library(Common ${Common}) add_library(Crypto ${Crypto}) add_library(CryptoNote ${CryptoNote}) @@ -43,15 +46,15 @@ add_library(System ${System}) add_library(Transfers ${Transfers}) add_library(Wallet ${Wallet}) -add_executable(ConnectivityTool ${ConnectivityTool} p2p/LevinProtocol.cpp p2p/LevinProtocol.h) +add_executable(ConnectivityTool ${ConnectivityTool}) add_executable(Daemon ${Daemon}) add_executable(SimpleWallet ${SimpleWallet}) add_executable(PaymentGate ${PaymentService}) -target_link_libraries(ConnectivityTool epee Common Crypto Rpc Http System ${Boost_LIBRARIES}) -target_link_libraries(Daemon epee CryptoNoteCore P2P Rpc Serialization System Http Logging Common Crypto upnpc-static ${Boost_LIBRARIES}) -target_link_libraries(SimpleWallet epee Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto ${Boost_LIBRARIES}) -target_link_libraries(PaymentGate epee Wallet NodeRpcProxy Transfers CryptoNoteCore Crypto P2P Rpc Http Serialization System Logging Common InProcessNode upnpc-static ${Boost_LIBRARIES}) +target_link_libraries(ConnectivityTool CryptoNoteCore Common Logging Crypto P2P Rpc Http Serialization System ${Boost_LIBRARIES}) +target_link_libraries(Daemon CryptoNoteCore P2P Rpc Serialization System Http Logging Common Crypto upnpc-static ${Boost_LIBRARIES}) +target_link_libraries(SimpleWallet Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(PaymentGate Wallet NodeRpcProxy Transfers CryptoNoteCore Crypto P2P Rpc Http Serialization System Logging Common InProcessNode BlockchainExplorer upnpc-static ${Boost_LIBRARIES}) add_dependencies(Rpc version) diff --git a/src/Common/ConsoleTools.cpp b/src/Common/ConsoleTools.cpp index 4ccbffc0..1cefdd63 100644 --- a/src/Common/ConsoleTools.cpp +++ b/src/Common/ConsoleTools.cpp @@ -17,15 +17,31 @@ #include "ConsoleTools.h" +#include + #ifdef _WIN32 #include +#include #else #include +#include #endif namespace Common { namespace Console { +bool isConsoleTty() { +#if defined(WIN32) + static bool istty = 0 != _isatty(_fileno(stdout)); +#else + static bool istty = 0 != isatty(fileno(stdout)); +#endif + return istty; +} + void setTextColor(Color color) { + if (!isConsoleTty()) { + return; + } if (color > Color::BrightMagenta) { color = Color::Default; diff --git a/src/Common/ConsoleTools.h b/src/Common/ConsoleTools.h index fc334313..7a275878 100644 --- a/src/Common/ConsoleTools.h +++ b/src/Common/ConsoleTools.h @@ -42,5 +42,6 @@ enum class Color : uint8_t { }; void setTextColor(Color color); +bool isConsoleTty(); }} diff --git a/src/Common/JsonValue.cpp b/src/Common/JsonValue.cpp index e3dd3ff3..be656f75 100644 --- a/src/Common/JsonValue.cpp +++ b/src/Common/JsonValue.cpp @@ -538,51 +538,37 @@ JsonValue& JsonValue::pushBack(JsonValue&& value) { } JsonValue& JsonValue::operator()(const Key& key) { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } - - return reinterpret_cast(valueObject)->at(key); + return getObject().at(key); } const JsonValue& JsonValue::operator()(const Key& key) const { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } - - return reinterpret_cast(valueObject)->at(key); + return getObject().at(key); } -std::size_t JsonValue::count(const Key& key) const { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } - - return reinterpret_cast(valueObject)->count(key); +bool JsonValue::contains(const Key& key) const { + return getObject().count(key) > 0; } JsonValue& JsonValue::insert(const Key& key, const JsonValue& value) { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } - - return reinterpret_cast(valueObject)->emplace(key, value).first->second; + return getObject().emplace(key, value).first->second; } JsonValue& JsonValue::insert(const Key& key, JsonValue&& value) { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } + return getObject().emplace(key, std::move(value)).first->second; +} - return reinterpret_cast(valueObject)->emplace(key, std::move(value)).first->second; +JsonValue& JsonValue::set(const Key& key, const JsonValue& value) { + getObject()[key] = value; + return *this; +} + +JsonValue& JsonValue::set(const Key& key, JsonValue&& value) { + getObject()[key] = std::move(value); + return *this; } std::size_t JsonValue::erase(const Key& key) { - if (type != OBJECT) { - throw std::runtime_error("JsonValue type is not OBJECT"); - } - - return reinterpret_cast(valueObject)->erase(key); + return getObject().erase(key); } JsonValue JsonValue::fromString(const std::string& source) { @@ -660,10 +646,57 @@ std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue) { return out; } -std::istream& operator>>(std::istream& in, JsonValue& jsonValue) { + +namespace { + +char readChar(std::istream& in) { char c; - in >> c; - while (isspace(c)) in >> c; + + if (!(in >> c)) { + throw std::runtime_error("Unable to parse: unexpected end of stream"); + } + + return c; +} + +char readNonWsChar(std::istream& in) { + char c; + + do { + c = readChar(in); + } while (isspace(c)); + + return c; +} + +std::string readStringToken(std::istream& in) { + char c; + std::string value; + + while (in) { + c = readChar(in); + + if (c == '"') { + break; + } + + if (c == '\\') { + value += c; + c = readChar(in); + } + + value += c; + } + + return value; +} + +} + + +std::istream& operator>>(std::istream& in, JsonValue& jsonValue) { + char c = readNonWsChar(in); + if (c == '[') { jsonValue.readArray(in); } else if (c == 't') { @@ -702,21 +735,16 @@ void JsonValue::destructValue() { } void JsonValue::readArray(std::istream& in) { - char c; JsonValue::Array value; + char c = readNonWsChar(in); - c = static_cast(in.peek()); - for (;;) { - if (!isspace(in.peek())) break; - in.read(&c, 1); - } - - if (in.peek() != ']') { + if(c != ']') { + in.putback(c); for (;;) { value.resize(value.size() + 1); in >> value.back(); - in >> c; - while (isspace(c)) in >> c; + c = readNonWsChar(in); + if (c == ']') { break; } @@ -725,8 +753,6 @@ void JsonValue::readArray(std::istream& in) { throw std::runtime_error("Unable to parse"); } } - } else { - in.read(&c, 1); } if (type != JsonValue::ARRAY) { @@ -856,42 +882,27 @@ void JsonValue::readNumber(std::istream& in, char c) { } void JsonValue::readObject(std::istream& in) { - char c; + char c = readNonWsChar(in); JsonValue::Object value; - in >> c; - while (isspace(c)) in >> c; if (c != '}') { std::string name; + for (;;) { if (c != '"') { throw std::runtime_error("Unable to parse"); } - name.clear(); - for (;;) { - in >> c; - if (c == '"') { - break; - } + name = readStringToken(in); + c = readNonWsChar(in); - if (c == '\\') { - name += c; - in >> c; - } - - name += c; - } - - in >> c; - while (isspace(c)) in >> c; if (c != ':') { throw std::runtime_error("Unable to parse"); } in >> value[name]; - in >> c; - while (isspace(c)) in >> c; + c = readNonWsChar(in); + if (c == '}') { break; } @@ -899,8 +910,8 @@ void JsonValue::readObject(std::istream& in) { if (c != ',') { throw std::runtime_error("Unable to parse"); } - in >> c; - while (isspace(c)) in >> c; + + c = readNonWsChar(in); } } @@ -915,22 +926,7 @@ void JsonValue::readObject(std::istream& in) { } void JsonValue::readString(std::istream& in) { - char c; - String value; - - for (;;) { - in.read(&c, 1); - if (c == '"') { - break; - } - - if (c == '\\') { - value += c; - in >> c; - } - - value += c; - } + String value = readStringToken(in); if (type != JsonValue::STRING) { destructValue(); diff --git a/src/Common/JsonValue.h b/src/Common/JsonValue.h index 41f2202c..0fc6d2b5 100644 --- a/src/Common/JsonValue.h +++ b/src/Common/JsonValue.h @@ -121,9 +121,14 @@ public: JsonValue& operator()(const Key& key); const JsonValue& operator()(const Key& key) const; - std::size_t count(const Key& key) const; + bool contains(const Key& key) const; JsonValue& insert(const Key& key, const JsonValue& value); JsonValue& insert(const Key& key, JsonValue&& value); + + // sets or creates value, returns reference to self + JsonValue& set(const Key& key, const JsonValue& value); + JsonValue& set(const Key& key, JsonValue&& value); + std::size_t erase(const Key& key); static JsonValue fromString(const std::string& source); @@ -144,6 +149,7 @@ private: }; void destructValue(); + void readArray(std::istream& in); void readTrue(std::istream& in); void readFalse(std::istream& in); diff --git a/src/Common/Math.cpp b/src/Common/Math.cpp new file mode 100644 index 00000000..922a231d --- /dev/null +++ b/src/Common/Math.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "Math.h" diff --git a/src/Common/Math.h b/src/Common/Math.h new file mode 100644 index 00000000..92a84cd0 --- /dev/null +++ b/src/Common/Math.h @@ -0,0 +1,43 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include +#include + +namespace Common { + +template +T medianValue(std::vector &v) { + if (v.empty()) + return T(); + + if (v.size() == 1) + return v[0]; + + auto n = (v.size()) / 2; + std::sort(v.begin(), v.end()); + //nth_element(v.begin(), v.begin()+n-1, v.end()); + if (v.size() % 2) { //1, 3, 5... + return v[n]; + } else { //2, 4, 6... + return (v[n - 1] + v[n]) / 2; + } +} + +} diff --git a/src/HTTP/HttpParserErrorCodes.h b/src/HTTP/HttpParserErrorCodes.h index 61a53e1a..ad8475e2 100644 --- a/src/HTTP/HttpParserErrorCodes.h +++ b/src/HTTP/HttpParserErrorCodes.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include diff --git a/src/InProcessNode/InProcessNode.cpp b/src/InProcessNode/InProcessNode.cpp index ebfd5b60..0602febc 100644 --- a/src/InProcessNode/InProcessNode.cpp +++ b/src/InProcessNode/InProcessNode.cpp @@ -20,6 +20,7 @@ #include #include +#include "Common/StringTools.h" #include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/verification_context.h" #include "cryptonote_protocol/cryptonote_protocol_handler_common.h" @@ -30,7 +31,8 @@ namespace CryptoNote { InProcessNode::InProcessNode(CryptoNote::ICore& core, CryptoNote::ICryptonoteProtocolQuery& protocol) : state(NOT_INITIALIZED), core(core), - protocol(protocol) + protocol(protocol), + blockchainExplorerDataBuilder(core, protocol) { } @@ -122,19 +124,17 @@ void InProcessNode::getNewBlocks(std::list&& knownBlockIds, std::l void InProcessNode::getNewBlocksAsync(std::list& knownBlockIds, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) { - std::error_code ec; - { - std::unique_lock lock(mutex); - ec = doGetNewBlocks(std::move(knownBlockIds), newBlocks, startHeight); - } - + std::error_code ec = doGetNewBlocks(std::move(knownBlockIds), newBlocks, startHeight); callback(ec); } //it's always protected with mutex std::error_code InProcessNode::doGetNewBlocks(std::list&& knownBlockIds, std::list& newBlocks, uint64_t& startHeight) { - if (state != INITIALIZED) { - return make_error_code(CryptoNote::error::NOT_INITIALIZED); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + return make_error_code(CryptoNote::error::NOT_INITIALIZED); + } } try { @@ -186,19 +186,17 @@ void InProcessNode::getTransactionOutsGlobalIndices(const crypto::hash& transact void InProcessNode::getTransactionOutsGlobalIndicesAsync(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) { - std::error_code ec; - { - std::unique_lock lock(mutex); - ec = doGetTransactionOutsGlobalIndices(transactionHash, outsGlobalIndices); - } - + std::error_code ec = doGetTransactionOutsGlobalIndices(transactionHash, outsGlobalIndices); callback(ec); } //it's always protected with mutex std::error_code InProcessNode::doGetTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices) { - if (state != INITIALIZED) { - return make_error_code(CryptoNote::error::NOT_INITIALIZED); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + return make_error_code(CryptoNote::error::NOT_INITIALIZED); + } } try { @@ -239,19 +237,17 @@ void InProcessNode::getRandomOutsByAmounts(std::vector&& amounts, uint void InProcessNode::getRandomOutsByAmountsAsync(std::vector& amounts, uint64_t outsCount, std::vector& result, const Callback& callback) { - std::error_code ec; - { - std::unique_lock lock(mutex); - ec = doGetRandomOutsByAmounts(std::move(amounts), outsCount, result); - } - + std::error_code ec = doGetRandomOutsByAmounts(std::move(amounts), outsCount, result); callback(ec); } //it's always protected with mutex std::error_code InProcessNode::doGetRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, std::vector& result) { - if (state != INITIALIZED) { - return make_error_code(CryptoNote::error::NOT_INITIALIZED); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + return make_error_code(CryptoNote::error::NOT_INITIALIZED); + } } try { @@ -294,19 +290,17 @@ void InProcessNode::relayTransaction(const CryptoNote::Transaction& transaction, } void InProcessNode::relayTransactionAsync(const CryptoNote::Transaction& transaction, const Callback& callback) { - std::error_code ec; - { - std::unique_lock lock(mutex); - ec = doRelayTransaction(transaction); - } - + std::error_code ec = doRelayTransaction(transaction); callback(ec); } //it's always protected with mutex std::error_code InProcessNode::doRelayTransaction(const CryptoNote::Transaction& transaction) { - if (state != INITIALIZED) { - return make_error_code(CryptoNote::error::NOT_INITIALIZED); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + return make_error_code(CryptoNote::error::NOT_INITIALIZED); + } } try { @@ -338,9 +332,11 @@ std::error_code InProcessNode::doRelayTransaction(const CryptoNote::Transaction& } size_t InProcessNode::getPeerCount() const { - std::unique_lock lock(mutex); - if (state != INITIALIZED) { - throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + } } return protocol.getPeerCount(); @@ -374,9 +370,11 @@ uint64_t InProcessNode::getKnownBlockCount() const { } uint64_t InProcessNode::getLastLocalBlockHeight() const { - std::unique_lock lock(mutex); - if (state != INITIALIZED) { - throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + } } uint64_t height; @@ -390,9 +388,11 @@ uint64_t InProcessNode::getLastLocalBlockHeight() const { } uint64_t InProcessNode::getLastKnownBlockHeight() const { - std::unique_lock lock(mutex); - if (state != INITIALIZED) { - throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + throw std::system_error(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + } } return protocol.getObservedHeight() - 1; @@ -440,6 +440,10 @@ void InProcessNode::poolUpdated() { observerManager.notify(&INodeObserver::poolChanged); } +void InProcessNode::blockchainSynchronized(uint64_t topHeight) { + observerManager.notify(&INodeObserver::blockchainSynchronized, topHeight); +} + void InProcessNode::queryBlocks(std::list&& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const InProcessNode::Callback& callback) { @@ -465,12 +469,7 @@ void InProcessNode::queryBlocks(std::list&& knownBlockIds, uint64_ void InProcessNode::queryBlocksAsync(std::list& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) { - std::error_code ec; - { - std::unique_lock lock(mutex); - ec = doQueryBlocks(std::move(knownBlockIds), timestamp, newBlocks, startHeight); - } - + std::error_code ec = doQueryBlocks(std::move(knownBlockIds), timestamp, newBlocks, startHeight); callback(ec); } @@ -522,13 +521,177 @@ void InProcessNode::getPoolSymmetricDifferenceAsync(std::vector& k std::vector& deleted_tx_ids, const Callback& callback) { std::error_code ec = std::error_code(); - std::unique_lock lock(mutex); - if (!core.getPoolSymmetricDifference(known_pool_tx_ids, known_block_id, is_bc_actual, new_txs, deleted_tx_ids)) { + is_bc_actual = core.getPoolChanges(known_block_id, known_pool_tx_ids, new_txs, deleted_tx_ids); + if (!is_bc_actual) { ec = make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); } - lock.unlock(); callback(ec); } +void InProcessNode::getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + lock.unlock(); + callback(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + return; + } + + ioService.post( + std::bind( + static_cast< + void(InProcessNode::*)( + const std::vector&, + std::vector>&, + const Callback& + ) + >(&InProcessNode::getBlocksAsync), + this, + std::cref(blockHeights), + std::ref(blocks), + callback + ) + ); +} + +void InProcessNode::getBlocksAsync(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { + std::error_code ec = doGetBlocks(blockHeights, blocks); + callback(ec); +} + +std::error_code InProcessNode::doGetBlocks(const std::vector& blockHeights, std::vector>& blocks) { + uint64_t topHeight = 0; + crypto::hash topHash = boost::value_initialized(); + if (!core.get_blockchain_top(topHeight, topHash)) { + return make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); + } + for (const uint64_t& height : blockHeights) { + if (height > topHeight) { + return make_error_code(CryptoNote::error::REQUEST_ERROR); + } + crypto::hash hash = core.getBlockIdByHeight(height); + Block block; + if (!core.getBlockByHash(hash, block)) { + return make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); + } + BlockDetails blockDetails; + if (!blockchainExplorerDataBuilder.fillBlockDetails(block, blockDetails)) { + return make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); + } + std::vector blocksOnSameHeight; + blocksOnSameHeight.push_back(std::move(blockDetails)); + blocks.push_back(std::move(blocksOnSameHeight)); + } + return std::error_code(); +} + +void InProcessNode::getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + lock.unlock(); + callback(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + return; + } + + ioService.post( + std::bind( + static_cast< + void(InProcessNode::*)( + const std::vector&, + std::vector&, + const Callback& + ) + >(&InProcessNode::getBlocksAsync), + this, + std::cref(blockHashes), + std::ref(blocks), + callback + ) + ); +} + +void InProcessNode::getBlocksAsync(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { + std::error_code ec = doGetBlocks(blockHashes, blocks); + callback(ec); +} + +std::error_code InProcessNode::doGetBlocks(const std::vector& blockHashes, std::vector& blocks) { + for (const crypto::hash& hash : blockHashes) { + Block block; + if (!core.getBlockByHash(hash, block)) { + return make_error_code(CryptoNote::error::REQUEST_ERROR); + } + BlockDetails blockDetails; + if (!blockchainExplorerDataBuilder.fillBlockDetails(block, blockDetails)) { + return make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); + } + blocks.push_back(std::move(blockDetails)); + } + return std::error_code(); +} + +void InProcessNode::getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + lock.unlock(); + callback(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + return; + } + + ioService.post( + std::bind( + &InProcessNode::getTransactionsAsync, + this, + std::cref(transactionHashes), + std::ref(transactions), + callback + ) + ); +} + +void InProcessNode::getTransactionsAsync(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { + std::error_code ec= doGetTransactions(transactionHashes, transactions); + callback(ec); +} + +std::error_code InProcessNode::doGetTransactions(const std::vector& transactionHashes, std::vector& transactions) { + std::list txs; + std::list missed_txs; + core.getTransactions(transactionHashes, txs, missed_txs, true); + if (missed_txs.size() > 0) { + return make_error_code(CryptoNote::error::REQUEST_ERROR); + } + for (const Transaction& tx : txs) { + TransactionDetails transactionDetails; + if (!blockchainExplorerDataBuilder.fillTransactionDetails(tx, transactionDetails)) { + return make_error_code(CryptoNote::error::INTERNAL_NODE_ERROR); + } + transactions.push_back(std::move(transactionDetails)); + } + return std::error_code(); +} + +void InProcessNode::isSynchronized(bool& syncStatus, const Callback& callback) { + std::unique_lock lock(mutex); + if (state != INITIALIZED) { + lock.unlock(); + callback(make_error_code(CryptoNote::error::NOT_INITIALIZED)); + return; + } + + ioService.post( + std::bind( + &InProcessNode::isSynchronizedAsync, + this, + std::ref(syncStatus), + callback + ) + ); +} + +void InProcessNode::isSynchronizedAsync(bool& syncStatus, const Callback& callback) { + syncStatus = protocol.isSynchronized(); + callback(std::error_code()); +} + } //namespace CryptoNote diff --git a/src/InProcessNode/InProcessNode.h b/src/InProcessNode/InProcessNode.h index 59674e27..9baed79d 100644 --- a/src/InProcessNode/InProcessNode.h +++ b/src/InProcessNode/InProcessNode.h @@ -23,6 +23,7 @@ #include "cryptonote_core/ICore.h" #include "cryptonote_core/ICoreObserver.h" #include "Common/ObserverManager.h" +#include "BlockchainExplorer/BlockchainExplorerDataBuilder.h" #include #include @@ -66,10 +67,15 @@ public: virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; private: virtual void peerCountUpdated(size_t count) override; virtual void lastKnownBlockHeightUpdated(uint64_t height) override; + virtual void blockchainSynchronized(uint64_t topHeight) override; virtual void blockchainUpdated() override; virtual void poolUpdated() override; @@ -94,6 +100,18 @@ private: void getPoolSymmetricDifferenceAsync(std::vector& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback); + void getBlocksAsync(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback); + std::error_code doGetBlocks(const std::vector& blockHeights, std::vector>& blocks); + + void getBlocksAsync(const std::vector& blockHashes, std::vector& blocks, const Callback& callback); + std::error_code doGetBlocks(const std::vector& blockHashes, std::vector& blocks); + + void getTransactionsAsync(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback); + std::error_code doGetTransactions(const std::vector& transactionHashes, std::vector& transactions); + + void isSynchronizedAsync(bool& syncStatus, const Callback& callback); + std::error_code doIsSynchronized(bool& syncStatus); + void workerFunc(); bool doShutdown(); @@ -111,6 +129,8 @@ private: std::unique_ptr workerThread; std::unique_ptr work; + BlockchainExplorerDataBuilder blockchainExplorerDataBuilder; + mutable std::mutex mutex; }; diff --git a/src/Logging/ILogger.h b/src/Logging/ILogger.h index 89f99558..4b7af082 100755 --- a/src/Logging/ILogger.h +++ b/src/Logging/ILogger.h @@ -59,4 +59,8 @@ public: virtual void operator()(const std::string& category, Level level, boost::posix_time::ptime time, const std::string& body) = 0; }; +#ifndef ENDL +#define ENDL std::endl +#endif + } diff --git a/src/Logging/LoggerManager.cpp b/src/Logging/LoggerManager.cpp index 31eba967..ea159ab2 100755 --- a/src/Logging/LoggerManager.cpp +++ b/src/Logging/LoggerManager.cpp @@ -37,7 +37,7 @@ void LoggerManager::configure(const JsonValue& val) { loggers.clear(); LoggerGroup::loggers.clear(); Level globalLevel; - if (val.count("globalLevel")) { + if (val.contains("globalLevel")) { auto levelVal = val("globalLevel"); if (levelVal.isInteger()) { globalLevel = static_cast(levelVal.getInteger()); @@ -49,7 +49,7 @@ void LoggerManager::configure(const JsonValue& val) { } std::vector globalDisabledCategories; - if (val.count("globalDisabledCategories")) { + if (val.contains("globalDisabledCategories")) { auto globalDisabledCategoriesList = val("globalDisabledCategories"); if (globalDisabledCategoriesList.isArray()) { size_t countOfCategories = globalDisabledCategoriesList.size(); @@ -64,7 +64,7 @@ void LoggerManager::configure(const JsonValue& val) { } } - if (val.count("loggers")) { + if (val.contains("loggers")) { auto loggersList = val("loggers"); if (loggersList.isArray()) { size_t countOfLoggers = loggersList.size(); @@ -75,7 +75,7 @@ void LoggerManager::configure(const JsonValue& val) { } Level level = INFO; - if (loggerConfiguration.count("level")) { + if (loggerConfiguration.contains("level")) { level = static_cast(loggerConfiguration("level").getInteger()); } @@ -93,12 +93,12 @@ void LoggerManager::configure(const JsonValue& val) { throw std::runtime_error("Unknown logger type: " + type); } - if (loggerConfiguration.count("pattern")) { + if (loggerConfiguration.contains("pattern")) { logger->setPattern(loggerConfiguration("pattern").getString()); } std::vector disabledCategories; - if (loggerConfiguration.count("disabledCategories")) { + if (loggerConfiguration.contains("disabledCategories")) { auto disabledCategoriesVal = loggerConfiguration("disabledCategories"); size_t countOfCategories = disabledCategoriesVal.size(); for (size_t i = 0; i < countOfCategories; ++i) { diff --git a/src/Platform/Linux/System/Dispatcher.h b/src/Platform/Linux/System/Dispatcher.h index 31e415f9..c7574f11 100755 --- a/src/Platform/Linux/System/Dispatcher.h +++ b/src/Platform/Linux/System/Dispatcher.h @@ -57,10 +57,10 @@ public: # if __WORDSIZE == 64 static const int SIZEOF_PTHREAD_MUTEX_T = 40; # else - static const int SIZEOF_PTHREAD_MUTEX_T = 32 + static const int SIZEOF_PTHREAD_MUTEX_T = 32; # endif #else - static const int SIZEOF_PTHREAD_MUTEX_T = 24 + static const int SIZEOF_PTHREAD_MUTEX_T = 24; #endif private: diff --git a/src/Platform/OSX/System/Timer.cpp b/src/Platform/OSX/System/Timer.cpp index 2160b17d..a8a9e829 100755 --- a/src/Platform/OSX/System/Timer.cpp +++ b/src/Platform/OSX/System/Timer.cpp @@ -93,7 +93,7 @@ void Timer::stop() { stopped = true; } -void Timer::sleep(std::chrono::milliseconds duration) { +void Timer::sleep(std::chrono::nanoseconds duration) { assert(dispatcher != nullptr); assert(context == nullptr); if (stopped) { @@ -106,7 +106,7 @@ void Timer::sleep(std::chrono::milliseconds duration) { timer = dispatcher->getTimer(); struct kevent event; - EV_SET(&event, timer, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, duration.count(), &timerContext); + EV_SET(&event, timer, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, duration.count() / 1000000, &timerContext); if (kevent(dispatcher->getKqueue(), &event, 1, NULL, 0, NULL) == -1) { throw std::runtime_error("Timer::stop, kevent() failed, errno=" + std::to_string(errno)); diff --git a/src/Platform/OSX/System/Timer.h b/src/Platform/OSX/System/Timer.h index a9940114..75840bed 100755 --- a/src/Platform/OSX/System/Timer.h +++ b/src/Platform/OSX/System/Timer.h @@ -34,7 +34,7 @@ public: Timer& operator=(Timer&& other); void start(); void stop(); - void sleep(std::chrono::milliseconds duration); + void sleep(std::chrono::nanoseconds duration); private: Dispatcher* dispatcher; diff --git a/src/Platform/Windows/System/TcpConnection.cpp b/src/Platform/Windows/System/TcpConnection.cpp index c8836f42..927036d3 100755 --- a/src/Platform/Windows/System/TcpConnection.cpp +++ b/src/Platform/Windows/System/TcpConnection.cpp @@ -26,6 +26,8 @@ #include #include "Dispatcher.h" +#pragma comment(lib, "Ws2_32.lib") + namespace System { namespace { diff --git a/src/Platform/Windows/System/Timer.cpp b/src/Platform/Windows/System/Timer.cpp index 66ede19f..bf3a195b 100755 --- a/src/Platform/Windows/System/Timer.cpp +++ b/src/Platform/Windows/System/Timer.cpp @@ -89,7 +89,7 @@ void Timer::stop() { stopped = true; } -void Timer::sleep(std::chrono::milliseconds duration) { +void Timer::sleep(std::chrono::nanoseconds duration) { assert(dispatcher != nullptr); assert(context == nullptr); if (stopped) { @@ -101,7 +101,7 @@ void Timer::sleep(std::chrono::milliseconds duration) { QueryPerformanceCounter(&ticks); QueryPerformanceFrequency(&frequency); uint64_t currentTime = ticks.QuadPart / (frequency.QuadPart / 1000); - uint64_t time = currentTime + duration.count(); + uint64_t time = currentTime + duration.count() / 1000000; void* fiber = GetCurrentFiber(); TimerContext timerContext{ time, fiber, false }; context = &timerContext; diff --git a/src/Platform/Windows/System/Timer.h b/src/Platform/Windows/System/Timer.h index ed2ab62a..cf2d19b6 100755 --- a/src/Platform/Windows/System/Timer.h +++ b/src/Platform/Windows/System/Timer.h @@ -34,7 +34,7 @@ public: Timer& operator=(Timer&& other); void start(); void stop(); - void sleep(std::chrono::milliseconds duration); + void sleep(std::chrono::nanoseconds duration); private: Dispatcher* dispatcher; diff --git a/src/System/Ipv4Address.cpp b/src/System/Ipv4Address.cpp index 719a6d92..75e9fcee 100755 --- a/src/System/Ipv4Address.cpp +++ b/src/System/Ipv4Address.cpp @@ -115,11 +115,11 @@ bool Ipv4Address::isLoopback() const { bool Ipv4Address::isPrivate() const { return // 10.0.0.0/8 - (value & 0xff000000) == (10 << 24) || + (value & UINT32_C(0xff000000)) == (UINT32_C(10) << 24) || // 172.16.0.0/12 - (value & 0xfff00000) == ((172 << 24) | (16 << 16)) || + (value & UINT32_C(0xfff00000)) == ((UINT32_C(172) << 24) | (UINT32_C(16) << 16)) || // 192.168.0.0/16 - (value & 0xffff0000) == ((192 << 24) | (168 << 16)); + (value & UINT32_C(0xffff0000)) == ((UINT32_C(192) << 24) | (UINT32_C(168) << 16)); } } diff --git a/src/connectivity_tool/conn_tool.cpp b/src/connectivity_tool/conn_tool.cpp index 84fee726..d2b5a2a3 100644 --- a/src/connectivity_tool/conn_tool.cpp +++ b/src/connectivity_tool/conn_tool.cpp @@ -34,11 +34,16 @@ #include "p2p/LevinProtocol.h" #include "rpc/core_rpc_server_commands_defs.h" #include "rpc/HttpClient.h" +#include "serialization/SerializationTools.h" #include "version.h" namespace po = boost::program_options; using namespace CryptoNote; +#ifndef ENDL +#define ENDL std::endl +#endif + namespace { const command_line::arg_descriptor arg_ip = {"ip", "set ip"}; const command_line::arg_descriptor arg_port = { "port", "set port" }; @@ -98,7 +103,7 @@ std::ostream& get_response_schema_as_json(std::ostream& ss, response_schema &rs) << " \"COMMAND_REQUEST_STAT_INFO_status\": \"" << rs.COMMAND_REQUEST_STAT_INFO_status << "\""; if (rs.si_rsp.is_initialized()) { - ss << "," << ENDL << " \"si_rsp\": " << epee::serialization::store_t_to_json(rs.si_rsp.get(), 1); + ss << "," << ENDL << " \"si_rsp\": " << storeToJson(rs.si_rsp.get()); } if (rs.ns_rsp.is_initialized()) { @@ -195,8 +200,8 @@ bool handle_get_daemon_info(po::variables_map& vm) { System::Dispatcher dispatcher; HttpClient httpClient(dispatcher, command_line::get_arg(vm, arg_ip), command_line::get_arg(vm, arg_rpc_port)); - CryptoNote::COMMAND_RPC_GET_INFO::request req = AUTO_VAL_INIT(req); - CryptoNote::COMMAND_RPC_GET_INFO::response res = AUTO_VAL_INIT(res); + CryptoNote::COMMAND_RPC_GET_INFO::request req; + CryptoNote::COMMAND_RPC_GET_INFO::response res; invokeJsonCommand(httpClient, "/getinfo", req, res); // TODO: timeout @@ -225,13 +230,13 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) { return false; } - crypto::secret_key prvk = AUTO_VAL_INIT(prvk); + crypto::secret_key prvk; if (!Common::podFromHex(command_line::get_arg(vm, arg_priv_key), prvk)) { std::cout << "{" << ENDL << " \"status\": \"ERROR: " << "wrong secret key set \"" << ENDL << "}"; return false; } - response_schema rs = AUTO_VAL_INIT(rs); + response_schema rs; unsigned timeout = command_line::get_arg(vm, arg_timeout); try { @@ -262,17 +267,17 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) { peer_id = rsp.my_id; } - proof_of_trust pot = AUTO_VAL_INIT(pot); + proof_of_trust pot; pot.peer_id = peer_id; pot.time = time(NULL); - crypto::public_key pubk = AUTO_VAL_INIT(pubk); + crypto::public_key pubk; Common::podFromHex(P2P_STAT_TRUSTED_PUB_KEY, pubk); crypto::hash h = get_proof_of_trust_hash(pot); crypto::generate_signature(h, pubk, prvk, pot.sign); if (command_line::get_arg(vm, arg_request_stat_info)) { - COMMAND_REQUEST_STAT_INFO::request req = AUTO_VAL_INIT(req); - COMMAND_REQUEST_STAT_INFO::response res = AUTO_VAL_INIT(res); + COMMAND_REQUEST_STAT_INFO::request req; + COMMAND_REQUEST_STAT_INFO::response res; req.tr = pot; @@ -295,9 +300,8 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) { ++pot.time; h = get_proof_of_trust_hash(pot); crypto::generate_signature(h, pubk, prvk, pot.sign); - COMMAND_REQUEST_NETWORK_STATE::request req = AUTO_VAL_INIT(req); - COMMAND_REQUEST_NETWORK_STATE::response res = AUTO_VAL_INIT(res); - req.tr = pot; + COMMAND_REQUEST_NETWORK_STATE::request req{ pot }; + COMMAND_REQUEST_NETWORK_STATE::response res; try { withTimeout(dispatcher, connection, timeout, [&] { @@ -324,8 +328,8 @@ bool handle_request_stat(po::variables_map& vm, peerid_type peer_id) { //--------------------------------------------------------------------------------------------------------------- bool generate_and_print_keys() { - crypto::public_key pk = AUTO_VAL_INIT(pk); - crypto::secret_key sk = AUTO_VAL_INIT(sk); + crypto::public_key pk; + crypto::secret_key sk; generate_keys(pk, sk); std::cout << "PUBLIC KEY: " << Common::podToHex(pk) << ENDL << "PRIVATE KEY: " << Common::podToHex(sk); diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index d25a400c..e6253f4d 100644 --- a/src/crypto/crypto-ops-data.c +++ b/src/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index 027ee95b..4ef2c762 100644 --- a/src/crypto/crypto-ops.c +++ b/src/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 298fe1a4..efa724e1 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #include #include #include diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 2dea3321..9bc0bcd1 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #include diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h index 6c419acb..4b4b16d9 100644 --- a/src/crypto/generic-ops.h +++ b/src/crypto/generic-ops.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #include diff --git a/src/crypto/hash-extra-blake.c b/src/crypto/hash-extra-blake.c index 37e74f51..d14c9eff 100644 --- a/src/crypto/hash-extra-blake.c +++ b/src/crypto/hash-extra-blake.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/hash-extra-groestl.c b/src/crypto/hash-extra-groestl.c index ab00dd63..50c69ffe 100644 --- a/src/crypto/hash-extra-groestl.c +++ b/src/crypto/hash-extra-groestl.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/hash-extra-jh.c b/src/crypto/hash-extra-jh.c index 2b012c24..05018a3d 100644 --- a/src/crypto/hash-extra-jh.c +++ b/src/crypto/hash-extra-jh.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/hash-extra-skein.c b/src/crypto/hash-extra-skein.c index c0327fbc..232f9df3 100644 --- a/src/crypto/hash-extra-skein.c +++ b/src/crypto/hash-extra-skein.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index cdd5a2d3..1a2ec16e 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #if !defined(__cplusplus) diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 9231a585..f652255a 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 041ea647..05e2e459 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #include diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h index 44c24c16..7c402562 100644 --- a/src/crypto/initializer.h +++ b/src/crypto/initializer.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #if defined(__GNUC__) diff --git a/src/crypto/random.c b/src/crypto/random.c index 08604f25..fc7497e3 100644 --- a/src/crypto/random.c +++ b/src/crypto/random.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/random.h b/src/crypto/random.h index 60a670e7..a0781902 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #pragma once #if !defined(__cplusplus) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index cc859443..31ce6766 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/slow-hash.cpp b/src/crypto/slow-hash.cpp index 5d1a204b..33fa46b7 100644 --- a/src/crypto/slow-hash.cpp +++ b/src/crypto/slow-hash.cpp @@ -1,3 +1,20 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + #include #include "hash.h" diff --git a/src/crypto/slow-hash.inl b/src/crypto/slow-hash.inl index 7ed0045c..57c86e06 100644 --- a/src/crypto/slow-hash.inl +++ b/src/crypto/slow-hash.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c index feee98dd..27cd4558 100644 --- a/src/crypto/tree-hash.c +++ b/src/crypto/tree-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index f4a66429..6c2086b0 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -60,6 +60,7 @@ const uint64_t CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS = DIFFICULTY_TARGET const uint64_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; //seconds, one day const uint64_t CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME = 60 * 60 * 24 * 7; //seconds, one week +const uint64_t CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL = 7; // CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL * CRYPTONOTE_MEMPOOL_TX_LIVETIME = time to forget tx const uint64_t UPGRADE_HEIGHT = 546602; const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent @@ -151,7 +152,8 @@ const CheckpointData CHECKPOINTS[] = { {689000, "212ec2698c5ebd15d6242d59f36c2d186d11bb47c58054f476dd8e6b1c7f0008"}, {713000, "a03f836c4a19f907cd6cac095eb6f56f5279ca2d1303fb7f826750dcb9025495"}, {750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"}, - {780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"} + {780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"}, + {785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"} }; } // CryptoNote diff --git a/src/cryptonote_core/AccountKVSerialization.h b/src/cryptonote_core/AccountKVSerialization.h deleted file mode 100644 index 74fbe6bf..00000000 --- a/src/cryptonote_core/AccountKVSerialization.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - -#pragma once - -#include "cryptonote_core/account.h" - -// epee -#include "serialization/keyvalue_serialization.h" - -namespace CryptoNote { - template struct AccountPublicAddressSerializer; - template struct AccountKeysSerializer; - template struct AccountBaseSerializer; - - template<> - struct AccountPublicAddressSerializer { - const AccountPublicAddress& m_account_address; - - AccountPublicAddressSerializer(const AccountPublicAddress& account_address) : m_account_address(account_address) { - } - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_account_address.m_spendPublicKey, "m_spend_public_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_account_address.m_viewPublicKey, "m_view_public_key") - END_KV_SERIALIZE_MAP() - }; - - template<> - struct AccountPublicAddressSerializer { - AccountPublicAddress& m_account_address; - - AccountPublicAddressSerializer(AccountPublicAddress& account_address) : m_account_address(account_address) { - } - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_account_address.m_spendPublicKey, "m_spend_public_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_account_address.m_viewPublicKey, "m_view_public_key") - END_KV_SERIALIZE_MAP() - }; - - template<> - struct AccountKeysSerializer { - const account_keys& m_keys; - - AccountKeysSerializer(const account_keys& keys) : m_keys(keys) { - } - - BEGIN_KV_SERIALIZE_MAP() - AccountPublicAddressSerializer addressSerializer(this_ref.m_keys.m_account_address); - epee::serialization::selector::serialize(addressSerializer, stg, hparent_section, "m_account_address"); - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_keys.m_spend_secret_key, "m_spend_secret_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_keys.m_view_secret_key, "m_view_secret_key") - END_KV_SERIALIZE_MAP() - }; - - template<> - struct AccountKeysSerializer { - account_keys& m_keys; - - AccountKeysSerializer(account_keys& keys) : m_keys(keys) { - } - - BEGIN_KV_SERIALIZE_MAP() - AccountPublicAddressSerializer addressSerializer(this_ref.m_keys.m_account_address); - epee::serialization::selector::serialize(addressSerializer, stg, hparent_section, "m_account_address"); - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_keys.m_spend_secret_key, "m_spend_secret_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(m_keys.m_view_secret_key, "m_view_secret_key") - END_KV_SERIALIZE_MAP() - }; - - template<> - struct AccountBaseSerializer { - const account_base& m_account; - - AccountBaseSerializer(const account_base& account) : m_account(account) { - } - - BEGIN_KV_SERIALIZE_MAP() - AccountKeysSerializer keysSerializer(this_ref.m_account.m_keys); - epee::serialization::selector::serialize(keysSerializer, stg, hparent_section, "m_keys"); - KV_SERIALIZE_N(m_account.m_creation_timestamp, "m_creation_timestamp") - END_KV_SERIALIZE_MAP() - }; - - template<> - struct AccountBaseSerializer { - account_base& m_account; - - AccountBaseSerializer(account_base& account) : m_account(account) { - } - - BEGIN_KV_SERIALIZE_MAP() - AccountKeysSerializer keysSerializer(this_ref.m_account.m_keys); - epee::serialization::selector::serialize(keysSerializer, stg, hparent_section, "m_keys"); - KV_SERIALIZE_N(m_account.m_creation_timestamp, "m_creation_timestamp") - END_KV_SERIALIZE_MAP() - }; -} diff --git a/src/cryptonote_core/Currency.cpp b/src/cryptonote_core/Currency.cpp index 8138ec1f..c75f2b39 100644 --- a/src/cryptonote_core/Currency.cpp +++ b/src/cryptonote_core/Currency.cpp @@ -209,6 +209,10 @@ std::string Currency::accountAddressAsString(const account_base& account) const return getAccountAddressAsStr(m_publicAddressBase58Prefix, account.get_keys().m_account_address); } +std::string Currency::accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const { + return getAccountAddressAsStr(m_publicAddressBase58Prefix, accountPublicAddress); +} + bool Currency::parseAccountAddressString(const std::string& str, AccountPublicAddress& addr) const { uint64_t prefix; if (!CryptoNote::parseAccountAddressString(prefix, addr, str)) { @@ -412,6 +416,7 @@ CurrencyBuilder::CurrencyBuilder(Logging::ILogger& log) : m_currency(log) { mempoolTxLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_LIVETIME); mempoolTxFromAltBlockLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME); + numberOfPeriodsToForgetTxDeletedFromPool(parameters::CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL); upgradeHeight(parameters::UPGRADE_HEIGHT); upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD); diff --git a/src/cryptonote_core/Currency.h b/src/cryptonote_core/Currency.h index c939409f..d4009f0f 100644 --- a/src/cryptonote_core/Currency.h +++ b/src/cryptonote_core/Currency.h @@ -69,6 +69,7 @@ public: uint64_t mempoolTxLiveTime() const { return m_mempoolTxLiveTime; } uint64_t mempoolTxFromAltBlockLiveTime() const { return m_mempoolTxFromAltBlockLiveTime; } + uint64_t numberOfPeriodsToForgetTxDeletedFromPool() const { return m_numberOfPeriodsToForgetTxDeletedFromPool; } uint64_t upgradeHeight() const { return m_upgradeHeight; } unsigned int upgradeVotingThreshold() const { return m_upgradeVotingThreshold; } @@ -97,6 +98,7 @@ public: const blobdata& extraNonce = blobdata(), size_t maxOuts = 1, bool penalizeFee = false) const; std::string accountAddressAsString(const account_base& account) const; + std::string accountAddressAsString(const AccountPublicAddress& accountPublicAddress) const; bool parseAccountAddressString(const std::string& str, AccountPublicAddress& addr) const; std::string formatAmount(uint64_t amount) const; @@ -153,6 +155,7 @@ private: uint64_t m_mempoolTxLiveTime; uint64_t m_mempoolTxFromAltBlockLiveTime; + uint64_t m_numberOfPeriodsToForgetTxDeletedFromPool; uint64_t m_upgradeHeight; unsigned int m_upgradeVotingThreshold; @@ -220,6 +223,7 @@ public: CurrencyBuilder& mempoolTxLiveTime(uint64_t val) { m_currency.m_mempoolTxLiveTime = val; return *this; } CurrencyBuilder& mempoolTxFromAltBlockLiveTime(uint64_t val) { m_currency.m_mempoolTxFromAltBlockLiveTime = val; return *this; } + CurrencyBuilder& numberOfPeriodsToForgetTxDeletedFromPool(uint64_t val) { m_currency.m_numberOfPeriodsToForgetTxDeletedFromPool = val; return *this; } CurrencyBuilder& upgradeHeight(uint64_t val) { m_currency.m_upgradeHeight = val; return *this; } CurrencyBuilder& upgradeVotingThreshold(unsigned int val); diff --git a/src/cryptonote_core/ICore.h b/src/cryptonote_core/ICore.h index 4674c30d..5ab16254 100755 --- a/src/cryptonote_core/ICore.h +++ b/src/cryptonote_core/ICore.h @@ -23,23 +23,28 @@ #include #include "crypto/hash.h" +#include "cryptonote_core/difficulty.h" #include "cryptonote_protocol/blobdatatype.h" -#include "cryptonote_protocol/cryptonote_protocol_defs.h" namespace CryptoNote { struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request; struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response; +struct NOTIFY_RESPONSE_CHAIN_ENTRY_request; +struct NOTIFY_RESPONSE_GET_OBJECTS_request; +struct NOTIFY_REQUEST_GET_OBJECTS_request; -struct Block; -struct Transaction; -struct i_cryptonote_protocol; -struct tx_verification_context; -struct block_verification_context; -struct core_stat_info; -struct BlockFullInfo; -class ICoreObserver; class Currency; +class ICoreObserver; +struct Block; +struct block_verification_context; +struct BlockFullInfo; +struct core_stat_info; +struct i_cryptonote_protocol; +struct Transaction; +struct TransactionInputMultisignature; +struct TransactionInputToKey; +struct tx_verification_context; class ICore { public: @@ -55,7 +60,7 @@ public: virtual void pause_mining() = 0; virtual void update_block_template_and_resume_mining() = 0; virtual bool handle_incoming_block_blob(const CryptoNote::blobdata& block_blob, CryptoNote::block_verification_context& bvc, bool control_miner, bool relay_block) = 0; - virtual bool handle_get_objects(CryptoNote::NOTIFY_REQUEST_GET_OBJECTS::request& arg, CryptoNote::NOTIFY_RESPONSE_GET_OBJECTS::request& rsp) = 0; + virtual bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS_request& arg, NOTIFY_RESPONSE_GET_OBJECTS_request& rsp) = 0; virtual void on_synchronized() = 0; virtual bool is_ready() = 0; @@ -67,11 +72,26 @@ public: virtual bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) = 0; virtual i_cryptonote_protocol* get_protocol() = 0; virtual bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block) = 0; - virtual bool getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, bool& isBcActual, std::vector& new_txs, std::vector& deleted_tx_ids) = 0; + virtual std::vector getPoolTransactions() = 0; + virtual bool getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) = 0; + virtual void getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) = 0; virtual bool queryBlocks(const std::list& block_ids, uint64_t timestamp, uint64_t& start_height, uint64_t& current_height, uint64_t& full_offset, std::list& entries) = 0; + virtual crypto::hash getBlockIdByHeight(uint64_t height) = 0; virtual bool getBlockByHash(const crypto::hash &h, Block &blk) = 0; + virtual void getTransactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs, bool checkTxPool = false) = 0; + virtual bool getBackwardBlocksSizes(uint64_t fromHeight, std::vector& sizes, size_t count) = 0; + virtual bool getBlockSize(const crypto::hash& hash, size_t& size) = 0; + virtual bool getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) = 0; + virtual bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, + bool penalizeFee, uint64_t& reward, int64_t& emissionChange) = 0; + virtual bool scanOutputkeysForIndices(const TransactionInputToKey& txInToKey, std::list>& outputReferences) = 0; + virtual bool getBlockDifficulty(uint64_t height, difficulty_type& difficulty) = 0; + virtual bool getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) = 0; + virtual bool getMultisigOutputReference(const TransactionInputMultisignature& txInMultisig, std::pair& outputReference) = 0; }; } //namespace CryptoNote diff --git a/src/cryptonote_core/Transaction.cpp b/src/cryptonote_core/Transaction.cpp index cba7f5a9..c7dada32 100644 --- a/src/cryptonote_core/Transaction.cpp +++ b/src/cryptonote_core/Transaction.cpp @@ -179,6 +179,7 @@ namespace CryptoNote { virtual void setUnlockTime(uint64_t unlockTime) override; virtual void setPaymentId(const Hash& hash) override; virtual void setExtraNonce(const std::string& nonce) override; + virtual void appendExtra(const Blob& extraData) override; // Inputs/Outputs virtual size_t addInput(const TransactionTypes::InputKey& input) override; @@ -385,7 +386,7 @@ namespace CryptoNote { outMsig.requiredSignatures = requiredSignatures; outMsig.keys.resize(to.size()); - for (int i = 0; i < to.size(); ++i) { + for (size_t i = 0; i < to.size(); ++i) { derivePublicKey(to[i], txKey, outputIndex, outMsig.keys[i]); } @@ -490,6 +491,12 @@ namespace CryptoNote { invalidateHash(); } + void TransactionImpl::appendExtra(const Blob& extraData) { + checkIfSigning(); + transaction.extra.insert( + transaction.extra.end(), extraData.begin(), extraData.end()); + } + bool TransactionImpl::getExtraNonce(std::string& nonce) const { tx_extra_nonce extraNonce; if (extra.get(extraNonce)) { diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index 4f530b2c..e67042aa 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -16,34 +16,35 @@ // along with Bytecoin. If not, see . #include "account.h" +#include "cryptonote_serialization.h" -namespace CryptoNote -{ - //----------------------------------------------------------------- - account_base::account_base() - { - set_null(); - } - //----------------------------------------------------------------- - void account_base::set_null() - { - m_keys = account_keys(); - } - //----------------------------------------------------------------- - void account_base::generate() - { - crypto::generate_keys(m_keys.m_account_address.m_spendPublicKey, m_keys.m_spend_secret_key); - crypto::generate_keys(m_keys.m_account_address.m_viewPublicKey, m_keys.m_view_secret_key); - m_creation_timestamp = time(NULL); - } - //----------------------------------------------------------------- - const account_keys& account_base::get_keys() const - { - return m_keys; - } - - void account_base::set_keys(const account_keys& keys) { - m_keys = keys; - } - //----------------------------------------------------------------- +namespace CryptoNote { +//----------------------------------------------------------------- +account_base::account_base() { + set_null(); +} +//----------------------------------------------------------------- +void account_base::set_null() { + m_keys = account_keys(); +} +//----------------------------------------------------------------- +void account_base::generate() { + crypto::generate_keys(m_keys.m_account_address.m_spendPublicKey, m_keys.m_spend_secret_key); + crypto::generate_keys(m_keys.m_account_address.m_viewPublicKey, m_keys.m_view_secret_key); + m_creation_timestamp = time(NULL); +} +//----------------------------------------------------------------- +const account_keys &account_base::get_keys() const { + return m_keys; +} + +void account_base::set_keys(const account_keys &keys) { + m_keys = keys; +} +//----------------------------------------------------------------- + +void account_base::serialize(ISerializer &s) { + s(m_keys, "m_keys"); + s(m_creation_timestamp, "m_creation_timestamp"); +} } diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h index 171ec91e..35939576 100644 --- a/src/cryptonote_core/account.h +++ b/src/cryptonote_core/account.h @@ -23,10 +23,12 @@ namespace CryptoNote { template struct AccountBaseSerializer; + class ISerializer; + struct account_keys { AccountPublicAddress m_account_address; - crypto::secret_key m_spend_secret_key; - crypto::secret_key m_view_secret_key; + crypto::secret_key m_spend_secret_key; + crypto::secret_key m_view_secret_key; }; /************************************************************************/ @@ -43,15 +45,14 @@ namespace CryptoNote { uint64_t get_createtime() const { return m_creation_timestamp; } void set_createtime(uint64_t val) { m_creation_timestamp = val; } - bool load(const std::string& file_path); - bool store(const std::string& file_path); - template inline void serialize(t_archive &a, const unsigned int /*ver*/) { a & m_keys; a & m_creation_timestamp; } + void serialize(ISerializer& s); + private: void set_null(); account_keys m_keys; diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp index b942f163..7c49b1c6 100644 --- a/src/cryptonote_core/blockchain_storage.cpp +++ b/src/cryptonote_core/blockchain_storage.cpp @@ -27,6 +27,7 @@ #include #include "Common/boost_serialization_helper.h" +#include "Common/Math.h" #include "Common/ShuffleGenerator.h" #include "Common/StringTools.h" @@ -35,12 +36,10 @@ using namespace Logging; -#ifdef ENDL -#undef ENDL -#define ENDL '\n' -#endif +#undef ERROR namespace { + std::string appendPath(const std::string& path, const std::string& fileName) { std::string result = path; if (!result.empty()) { @@ -51,28 +50,6 @@ std::string appendPath(const std::string& path, const std::string& fileName) { return result; } -template -type_vec_type medianValue(std::vector &v) -{ - if (v.empty()) - return boost::value_initialized(); - - if (v.size() == 1) - return v[0]; - - size_t n = (v.size()) / 2; - std::sort(v.begin(), v.end()); - //nth_element(v.begin(), v.begin()+n-1, v.end()); - if (v.size() % 2) - {//1, 3, 5... - return v[n]; - } else - {//2, 4, 6... - return (v[n - 1] + v[n]) / 2; - } -} - - } namespace std { @@ -405,22 +382,31 @@ crypto::hash blockchain_storage::get_tail_id() { return m_blockIndex.getTailId(); } -bool blockchain_storage::getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, std::vector& new_txs, std::vector& deleted_tx_ids) { - - std::lock_guard txLock(m_tx_pool); - std::lock_guard bcLock(m_blockchain_lock); +bool blockchain_storage::getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) { + // Locks are necessary in order to make sure blockchain isn't changed between get_tail_id() and getPoolChanges() + std::lock_guard txPoolLock(m_tx_pool); + std::lock_guard blockchainLock(m_blockchain_lock); - if (known_block_id != get_tail_id()) { + if (tailBlockId != get_tail_id()) { return false; } - std::vector new_tx_ids; - m_tx_pool.get_difference(known_pool_tx_ids, new_tx_ids, deleted_tx_ids); + getPoolChanges(knownTxsIds, addedTxs, deletedTxsIds); + + return true; +} + +void blockchain_storage::getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) { + std::lock_guard txPoolLock(m_tx_pool); + + std::vector addedTxsIds; + m_tx_pool.get_difference(knownTxsIds, addedTxsIds, deletedTxsIds); std::vector misses; - get_transactions(new_tx_ids, new_txs, misses, true); + m_tx_pool.getTransactions(addedTxsIds, addedTxs, misses); assert(misses.empty()); - return true; } bool blockchain_storage::get_short_chain_history(std::list& ids) { @@ -662,7 +648,7 @@ bool blockchain_storage::validate_miner_transaction(const Block& b, uint64_t hei std::vector lastBlocksSizes; get_last_n_blocks_sizes(lastBlocksSizes, m_currency.rewardBlocksWindow()); - size_t blocksSizeMedian = medianValue(lastBlocksSizes); + size_t blocksSizeMedian = Common::medianValue(lastBlocksSizes); bool penalizeFee = get_block_major_version_for_height(height) > BLOCK_MAJOR_VERSION_1; if (!m_currency.getBlockReward(blocksSizeMedian, cumulativeBlockSize, alreadyGeneratedCoins, fee, penalizeFee, reward, emissionChange)) { @@ -1010,8 +996,12 @@ bool blockchain_storage::handle_alternative_block(const Block& b, const crypto:: "###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << ", checkpoint is found in alternative chain on height " << bei.height; bool r = switch_to_alternative_blockchain(alt_chain, true); - if (r) bvc.m_added_to_main_chain = true; - else bvc.m_verifivation_failed = true; + if (r) { + bvc.m_added_to_main_chain = true; + bvc.m_switched_to_alt_chain = true; + } else { + bvc.m_verifivation_failed = true; + } return r; } else if (m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain { @@ -1020,8 +1010,12 @@ bool blockchain_storage::handle_alternative_block(const Block& b, const crypto:: "###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty << ENDL << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty; bool r = switch_to_alternative_blockchain(alt_chain, false); - if (r) bvc.m_added_to_main_chain = true; - else bvc.m_verifivation_failed = true; + if (r) { + bvc.m_added_to_main_chain = true; + bvc.m_switched_to_alt_chain = true; + } else { + bvc.m_verifivation_failed = true; + } return r; } else { logger(INFO, BRIGHT_BLUE) << @@ -1441,7 +1435,7 @@ bool blockchain_storage::check_tx_input(const TransactionInputToKey& txin, const outputs_visitor(std::vector& results_collector, blockchain_storage& bch, ILogger& logger) :m_results_collector(results_collector), m_bch(bch), logger(logger, "outputs_visitor") { } - bool handle_output(const Transaction& tx, const TransactionOutput& out) { + bool handle_output(const Transaction& tx, const TransactionOutput& out, size_t transactionOutputIndex) { //check tx unlock time if (!m_bch.is_tx_spendtime_unlocked(tx.unlockTime)) { logger(INFO, BRIGHT_WHITE) << @@ -1510,7 +1504,7 @@ bool blockchain_storage::check_block_timestamp(std::vector timestamps, return true; } - uint64_t median_ts = medianValue(timestamps); + uint64_t median_ts = Common::medianValue(timestamps); if (b.timestamp < median_ts) { logger(INFO, BRIGHT_WHITE) << @@ -1591,7 +1585,7 @@ bool blockchain_storage::update_next_comulative_size_limit() { std::vector sz; get_last_n_blocks_sizes(sz, m_currency.rewardBlocksWindow()); - uint64_t median = medianValue(sz); + uint64_t median = Common::medianValue(sz); if (median <= nextBlockGrantedFullRewardZone) { median = nextBlockGrantedFullRewardZone; } @@ -2087,4 +2081,75 @@ bool blockchain_storage::getBlockIds(uint64_t startHeight, size_t maxCount, std: return m_blockIndex.getBlockIds(startHeight, maxCount, items); } +bool blockchain_storage::getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) { + std::lock_guard lk(m_blockchain_lock); + auto it = m_transactionMap.find(txId); + if(it == m_transactionMap.end()) { + return false; + } else { + blockHeight = m_blocks[it->second.block].height; + blockId = get_block_id_by_height(blockHeight); + return true; + } +} + +bool blockchain_storage::getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) { + std::lock_guard lk(m_blockchain_lock); + + // try to find block in main chain + uint64_t height = 0; + if (m_blockIndex.getBlockHeight(hash, height)) { + generatedCoins = m_blocks[height].already_generated_coins; + return true; + } + + // try to find block in alternative chain + auto blockByHashIterator = m_alternative_chains.find(hash); + if (blockByHashIterator != m_alternative_chains.end()) { + generatedCoins = blockByHashIterator->second.already_generated_coins; + return true; + } + + logger(DEBUGGING) << "Can't find block with hash " << hash << " to get already generated coins."; + return false; +} + +bool blockchain_storage::getBlockSize(const crypto::hash& hash, size_t& size) { + std::lock_guard lk(m_blockchain_lock); + + // try to find block in main chain + uint64_t height = 0; + if (m_blockIndex.getBlockHeight(hash, height)) { + size = m_blocks[height].block_cumulative_size; + return true; + } + + // try to find block in alternative chain + auto blockByHashIterator = m_alternative_chains.find(hash); + if (blockByHashIterator != m_alternative_chains.end()) { + size = blockByHashIterator->second.block_cumulative_size; + return true; + } + + logger(DEBUGGING) << "Can't find block with hash " << hash << " to get block size."; + return false; +} + +bool blockchain_storage::getMultisigOutputReference(const TransactionInputMultisignature& txInMultisig, std::pair& outputReference) { + std::lock_guard lk(m_blockchain_lock); + MultisignatureOutputsContainer::const_iterator amountIter = m_multisignatureOutputs.find(txInMultisig.amount); + if (amountIter == m_multisignatureOutputs.end()) { + logger(DEBUGGING) << "Transaction contains multisignature input with invalid amount."; + return false; + } + if (amountIter->second.size() <= txInMultisig.outputIndex) { + logger(DEBUGGING) << "Transaction contains multisignature input with invalid outputIndex."; + return false; + } + const MultisignatureOutputUsage& outputIndex = amountIter->second[txInMultisig.outputIndex]; + const Transaction& outputTransaction = m_blocks[outputIndex.transactionIndex.block].transactions[outputIndex.transactionIndex.transaction].tx; + outputReference.first = get_transaction_hash(outputTransaction); + outputReference.second = outputIndex.outputIndex; + return true; +} } diff --git a/src/cryptonote_core/blockchain_storage.h b/src/cryptonote_core/blockchain_storage.h index ba0e29e7..6b0781de 100644 --- a/src/cryptonote_core/blockchain_storage.h +++ b/src/cryptonote_core/blockchain_storage.h @@ -103,8 +103,16 @@ namespace CryptoNote { uint64_t get_current_comulative_blocksize_limit(); bool is_storing_blockchain(){return m_is_blockchain_storing;} uint64_t block_difficulty(size_t i); - bool getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, std::vector& new_txs, std::vector& deleted_tx_ids); + bool getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds); + void getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds); + bool getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight); + bool getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins); + bool getBlockSize(const crypto::hash& hash, size_t& size); + bool getMultisigOutputReference(const TransactionInputMultisignature& txInMultisig, std::pair& outputReference); + template bool scan_outputkeys_for_indexes(const TransactionInputToKey& tx_in_to_key, visitor_t& vis, uint64_t* pmax_related_block_height = NULL); template bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) { @@ -125,8 +133,8 @@ namespace CryptoNote { } template - void get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool checkTxPool = false) { - std::lock_guard lk(m_blockchain_lock); + void getBlockchainTransactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) { + std::lock_guard bcLock(m_blockchain_lock); for (const auto& tx_id : txs_ids) { auto it = m_transactionMap.find(tx_id); @@ -136,11 +144,21 @@ namespace CryptoNote { txs.push_back(transactionByIndex(it->second).tx); } } + } + + template + void get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool checkTxPool = false) { + if (checkTxPool){ + std::lock_guard txLock(m_tx_pool); + + getBlockchainTransactions(txs_ids, txs, missed_txs); - if (checkTxPool) { auto poolTxIds = std::move(missed_txs); missed_txs.clear(); m_tx_pool.getTransactions(poolTxIds, txs, missed_txs); + + } else { + getBlockchainTransactions(txs_ids, txs, missed_txs); } } @@ -234,7 +252,6 @@ namespace CryptoNote { Logging::LoggerRef logger; bool storeCache(); - template bool scan_outputkeys_for_indexes(const TransactionInputToKey& tx_in_to_key, visitor_t& vis, uint64_t* pmax_related_block_height = NULL); bool switch_to_alternative_blockchain(std::list& alt_chain, bool discard_disconnected_chain); bool handle_alternative_block(const Block& b, const crypto::hash& id, block_verification_context& bvc); difficulty_type get_next_difficulty_for_alternative_chain(const std::list& alt_chain, BlockEntry& bei); @@ -315,7 +332,7 @@ namespace CryptoNote { return false; } - if (!vis.handle_output(tx.tx, tx.tx.vout[amount_outs_vec[i].second])) { + if (!vis.handle_output(tx.tx, tx.tx.vout[amount_outs_vec[i].second], amount_outs_vec[i].second)) { logger(Logging::INFO) << "Failed to handle_output for output no = " << count << ", with absolute offset " << i; return false; } diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_core/cryptonote_basic.h index 99ef0be0..17d533c5 100644 --- a/src/cryptonote_core/cryptonote_basic.h +++ b/src/cryptonote_core/cryptonote_basic.h @@ -28,7 +28,6 @@ #include "cryptonote_core/tx_extra.h" #include "serialization/binary_archive.h" #include "serialization/crypto.h" -#include "serialization/keyvalue_serialization.h" // eepe named serialization #include "serialization/json_archive.h" #include "serialization/serialization.h" #include "serialization/variant.h" diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index ceea5b81..de23c866 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -91,8 +91,8 @@ bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blo bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks) { return m_blockchain_storage.get_blocks(start_offset, count, blocks); } -void core::get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs) { - m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs); +void core::getTransactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs, bool checkTxPool) { + m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs, checkTxPool); } bool core::get_alternative_blocks(std::list& blocks) { @@ -258,14 +258,6 @@ bool core::check_tx_inputs_keyimages_diff(const Transaction& tx) { return true; } -bool core::add_new_tx(const Transaction& tx, tx_verification_context& tvc, bool keeped_by_block) { - crypto::hash tx_hash = get_transaction_hash(tx); - crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx); - blobdata bl; - t_serializable_object_to_blob(tx, bl); - return add_new_tx(tx, tx_hash, tx_prefix_hash, bl.size(), tvc, keeped_by_block); -} - size_t core::get_blockchain_total_transactions() { return m_blockchain_storage.get_total_transactions(); } @@ -347,14 +339,19 @@ bool core::handle_block_found(Block& b) { void core::on_synchronized() { m_miner->on_synchronized(); - } - //----------------------------------------------------------------------------------------------- - bool core::getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, bool& isBcActual, std::vector& new_txs, std::vector& deleted_tx_ids) { - isBcActual = m_blockchain_storage.getPoolSymmetricDifference(known_pool_tx_ids, known_block_id, new_txs, deleted_tx_ids); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_block_blob(const blobdata& block_blob, block_verification_context& bvc, bool control_miner, bool relay_block) { +} +//----------------------------------------------------------------------------------------------- +bool core::getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) { + return m_blockchain_storage.getPoolChanges(tailBlockId, knownTxsIds, addedTxs, deletedTxsIds); +} +//----------------------------------------------------------------------------------------------- +void core::getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) { + m_blockchain_storage.getPoolChanges(knownTxsIds, addedTxs, deletedTxsIds); +} +//----------------------------------------------------------------------------------------------- +bool core::handle_incoming_block_blob(const blobdata& block_blob, block_verification_context& bvc, bool control_miner, bool relay_block) { if (block_blob.size() > m_currency.maxBlockBlobSize()) { logger(INFO) << "WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"; bvc.m_verifivation_failed = true; @@ -430,8 +427,15 @@ bool core::check_tx_syntax(const Transaction& tx) { return true; } -void core::get_pool_transactions(std::list& txs) { +std::vector core::getPoolTransactions() { + std::list txs; m_mempool.get_transactions(txs); + + std::vector result; + for (auto& tx : txs) { + result.emplace_back(std::move(tx)); + } + return result; } bool core::get_short_chain_history(std::list& ids) { @@ -442,15 +446,11 @@ bool core::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_R return m_blockchain_storage.handle_get_objects(arg, rsp); } -bool core::getBlockByHash(const crypto::hash &h, Block &blk) { - return core::get_block_by_hash(h, blk); -} - -crypto::hash core::get_block_id_by_height(uint64_t height) { +crypto::hash core::getBlockIdByHeight(uint64_t height) { return m_blockchain_storage.get_block_id_by_height(height); } -bool core::get_block_by_hash(const crypto::hash &h, Block &blk) { +bool core::getBlockByHash(const crypto::hash &h, Block &blk) { return m_blockchain_storage.get_block_by_hash(h, blk); } @@ -572,4 +572,51 @@ void core::blockchainUpdated() { return true; } +bool core::getBackwardBlocksSizes(uint64_t fromHeight, std::vector& sizes, size_t count) { + return m_blockchain_storage.get_backward_blocks_sizes(fromHeight, sizes, count); +} + +bool core::getBlockSize(const crypto::hash& hash, size_t& size) { + return m_blockchain_storage.getBlockSize(hash, size); +} + +bool core::getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) { + return m_blockchain_storage.getAlreadyGeneratedCoins(hash, generatedCoins); +} + +bool core::getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, + bool penalizeFee, uint64_t& reward, int64_t& emissionChange) { + return m_currency.getBlockReward(medianSize, currentBlockSize, alreadyGeneratedCoins, fee, penalizeFee, reward, emissionChange); +} + +bool core::scanOutputkeysForIndices(const TransactionInputToKey& txInToKey, std::list>& outputReferences) { + struct outputs_visitor + { + std::list>& m_resultsCollector; + outputs_visitor(std::list>& resultsCollector):m_resultsCollector(resultsCollector){} + bool handle_output(const Transaction& tx, const TransactionOutput& out, size_t transactionOutputIndex) + { + m_resultsCollector.push_back(std::make_pair(get_transaction_hash(tx), transactionOutputIndex)); + return true; + } + }; + + outputs_visitor vi(outputReferences); + + return m_blockchain_storage.scan_outputkeys_for_indexes(txInToKey, vi); +} + +bool core::getBlockDifficulty(uint64_t height, difficulty_type& difficulty) { + difficulty = m_blockchain_storage.block_difficulty(height); + return true; +} + +bool core::getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) { + return m_blockchain_storage.getBlockContainingTx(txId, blockId, blockHeight); +} + +bool core::getMultisigOutputReference(const TransactionInputMultisignature& txInMultisig, std::pair& outputReference) { + return m_blockchain_storage.getMultisigOutputReference(txInMultisig, outputReference); +} + } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index dd558bf2..d26891b9 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -65,6 +65,15 @@ namespace CryptoNote { // ICore virtual bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS_request& arg, NOTIFY_RESPONSE_GET_OBJECTS_request& rsp) override; + virtual bool getBackwardBlocksSizes(uint64_t fromHeight, std::vector& sizes, size_t count) override; + virtual bool getBlockSize(const crypto::hash& hash, size_t& size) override; + virtual bool getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) override; + virtual bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, + bool penalizeFee, uint64_t& reward, int64_t& emissionChange) override; + virtual bool scanOutputkeysForIndices(const TransactionInputToKey& txInToKey, std::list>& outputReferences) override; + virtual bool getBlockDifficulty(uint64_t height, difficulty_type& difficulty) override; + virtual bool getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) override; + virtual bool getMultisigOutputReference(const TransactionInputMultisignature& txInMultisig, std::pair& output_reference) override; uint64_t get_current_blockchain_height(); bool have_block(const crypto::hash& id); @@ -82,12 +91,10 @@ namespace CryptoNote { } virtual bool queryBlocks(const std::list& block_ids, uint64_t timestamp, uint64_t& start_height, uint64_t& current_height, uint64_t& full_offset, std::list& entries); - crypto::hash get_block_id_by_height(uint64_t height); - void get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs); - bool get_block_by_hash(const crypto::hash &h, Block &blk); - //void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid); - + virtual crypto::hash getBlockIdByHeight(uint64_t height) override; + void getTransactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs, bool checkTxPool = false) override; virtual bool getBlockByHash(const crypto::hash &h, Block &blk) override; + //void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid); bool get_alternative_blocks(std::list& blocks); size_t get_alternative_blocks_count(); @@ -95,14 +102,14 @@ namespace CryptoNote { void set_cryptonote_protocol(i_cryptonote_protocol* pprotocol); void set_checkpoints(checkpoints&& chk_pts); - void get_pool_transactions(std::list& txs); + std::vector getPoolTransactions() override; size_t get_pool_transactions_count(); size_t get_blockchain_total_transactions(); //bool get_outs(uint64_t amount, std::list& pkeys); virtual bool find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY_request& resp); virtual bool find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count); bool get_stat_info(core_stat_info& st_inf); - //bool get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count); + virtual bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs); crypto::hash get_tail_id(); virtual bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& res); @@ -114,11 +121,13 @@ namespace CryptoNote { void print_blockchain_index(); std::string print_pool(bool short_format); void print_blockchain_outs(const std::string& file); - virtual bool getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, bool& isBcActual, std::vector& new_txs, std::vector& deleted_tx_ids) override; + virtual bool getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) override; + virtual void getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) override; private: bool add_new_tx(const Transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block); - bool add_new_tx(const Transaction& tx, tx_verification_context& tvc, bool keeped_by_block); bool load_state_data(); bool parse_tx_from_blob(Transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash, const blobdata& blob); bool handle_incoming_block(const Block& b, block_verification_context& bvc, bool control_miner, bool relay_block); diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 3fac4aa2..e24b121e 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -22,7 +22,6 @@ #include "cryptonote_basic_impl.h" using namespace Logging; -using namespace epee; namespace CryptoNote { diff --git a/src/cryptonote_core/cryptonote_serialization.cpp b/src/cryptonote_core/cryptonote_serialization.cpp index 93317d8f..d3c995f6 100644 --- a/src/cryptonote_core/cryptonote_serialization.cpp +++ b/src/cryptonote_core/cryptonote_serialization.cpp @@ -16,6 +16,7 @@ // along with Bytecoin. If not, see . #include "cryptonote_serialization.h" +#include "account.h" #include "serialization/ISerializer.h" #include "serialization/SerializationOverloads.h" @@ -132,13 +133,18 @@ void getVariantValue(CryptoNote::ISerializer& serializer, uint8_t tag, CryptoNot } template -void serializePod(T& v, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.binary(&v, sizeof(v), name); +bool serializePod(T& v, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializer.binary(&v, sizeof(v), name); } -void serializeVarintVector(std::vector& vector, CryptoNote::ISerializer& serializer, const std::string& name) { +bool serializeVarintVector(std::vector& vector, CryptoNote::ISerializer& serializer, Common::StringView name) { std::size_t size = vector.size(); - serializer.beginArray(size, name); + + if (!serializer.beginArray(size, name)) { + vector.clear(); + return false; + } + vector.resize(size); for (size_t i = 0; i < size; ++i) { @@ -146,49 +152,51 @@ void serializeVarintVector(std::vector& vector, CryptoNote::ISerialize } serializer.endArray(); + return true; } } namespace crypto { -void serialize(public_key& pubKey, const std::string& name, CryptoNote::ISerializer& serializer) { - serializePod(pubKey, name, serializer); +bool serialize(public_key& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(pubKey, name, serializer); } -void serialize(secret_key& secKey, const std::string& name, CryptoNote::ISerializer& serializer) { - serializePod(secKey, name, serializer); +bool serialize(secret_key& secKey, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(secKey, name, serializer); } -void serialize(hash& h, const std::string& name, CryptoNote::ISerializer& serializer) { - serializePod(h, name, serializer); +bool serialize(hash& h, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(h, name, serializer); } -void serialize(key_image& keyImage, const std::string& name, CryptoNote::ISerializer& serializer) { - serializePod(keyImage, name, serializer); +bool serialize(key_image& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(keyImage, name, serializer); } -void serialize(chacha8_iv& chacha, const std::string& name, CryptoNote::ISerializer& serializer) { - serializePod(chacha, name, serializer); +bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(chacha, name, serializer); } +bool serialize(signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializePod(sig, name, serializer); +} + + } namespace CryptoNote { -void serialize(TransactionPrefix& txP, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionPrefix& txP, ISerializer& serializer) { serializer(txP.version, "version"); serializer(txP.unlockTime, "unlock_time"); serializer(txP.vin, "vin"); serializer(txP.vout, "vout"); serializeAsBinary(txP.extra, "extra", serializer); - serializer.endObject(); } -void serialize(Transaction& tx, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(Transaction& tx, ISerializer& serializer) { serializer(tx.version, "version"); serializer(tx.unlockTime, "unlock_time"); serializer(tx.vin, "vin"); @@ -228,13 +236,9 @@ void serialize(Transaction& tx, const std::string& name, ISerializer& serializer } } // serializer.endArray(); - - serializer.endObject(); } -void serialize(TransactionInput& in, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(TransactionInput& in, ISerializer& serializer) { if (serializer.type() == ISerializer::OUTPUT) { BinaryVariantTagGetter tagGetter; uint8_t tag = boost::apply_visitor(tagGetter, in); @@ -248,52 +252,33 @@ void serialize(TransactionInput& in, const std::string& name, ISerializer& seria getVariantValue(serializer, tag, in); } - - serializer.endObject(); } -void serialize(TransactionInputGenerate& gen, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionInputGenerate& gen, ISerializer& serializer) { serializer(gen.height, "height"); - serializer.endObject(); } -void serialize(TransactionInputToScript& script, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} +void serialize(TransactionInputToScript& script, ISerializer& serializer) {} +void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer) {} -void serialize(TransactionInputToScriptHash& scripthash, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} - -void serialize(TransactionInputToKey& key, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionInputToKey& key, ISerializer& serializer) { serializer(key.amount, "amount"); serializeVarintVector(key.keyOffsets, serializer, "key_offsets"); serializer(key.keyImage, "k_image"); - serializer.endObject(); } -void serialize(TransactionInputMultisignature& multisignature, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer) { serializer(multisignature.amount, "amount"); serializer(multisignature.signatures, "signatures"); serializer(multisignature.outputIndex, "outputIndex"); - serializer.endObject(); } -void serialize(TransactionOutput& output, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionOutput& output, ISerializer& serializer) { serializer(output.amount, "amount"); serializer(output.target, "target"); - serializer.endObject(); } -void serialize(TransactionOutputTarget& output, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(TransactionOutputTarget& output, ISerializer& serializer) { if (serializer.type() == ISerializer::OUTPUT) { BinaryVariantTagGetter tagGetter; uint8_t tag = boost::apply_visitor(tagGetter, output); @@ -307,36 +292,21 @@ void serialize(TransactionOutputTarget& output, const std::string& name, ISerial getVariantValue(serializer, tag, output); } - - serializer.endObject(); } -void serialize(TransactionOutputToScript& script, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} +void serialize(TransactionOutputToScript& script, ISerializer& serializer) {} +void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer) {} -void serialize(TransactionOutputToScriptHash& scripthash, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} - -void serialize(TransactionOutputToKey& key, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionOutputToKey& key, ISerializer& serializer) { serializer(key.key, "key"); - serializer.endObject(); } -void serialize(TransactionOutputMultisignature& multisignature, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer) { serializer(multisignature.keys, "keys"); serializer(multisignature.requiredSignatures, "required_signatures"); - serializer.endObject(); } -void serialize(ParentBlockSerializer& pbs, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(ParentBlockSerializer& pbs, ISerializer& serializer) { serializer(pbs.m_parentBlock.majorVersion, "majorVersion"); if (BLOCK_MAJOR_VERSION_1 < pbs.m_parentBlock.majorVersion) { @@ -410,8 +380,6 @@ void serialize(ParentBlockSerializer& pbs, const std::string& name, ISerializer& for (crypto::hash& hash: pbs.m_parentBlock.blockchainBranch) { serializer(hash, ""); } - - serializer.endObject(); } void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) { @@ -432,15 +400,11 @@ void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) { } } -void serialize(BlockHeader& header, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); +void serialize(BlockHeader& header, ISerializer& serializer) { serializeBlockHeader(header, serializer); - serializer.endObject(); } -void serialize(Block& block, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(Block& block, ISerializer& serializer) { serializeBlockHeader(block, serializer); if (block.majorVersion == BLOCK_MAJOR_VERSION_2) { @@ -450,45 +414,40 @@ void serialize(Block& block, const std::string& name, ISerializer& serializer) { serializer(block.minerTx, "miner_tx"); serializer(block.txHashes, "tx_hashes"); - - serializer.endObject(); } -void serialize(AccountPublicAddress& address, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - - serializer(address.m_spendPublicKey, "spend_public_key"); - serializer(address.m_viewPublicKey, "view_public_key"); - - serializer.endObject(); +void serialize(AccountPublicAddress& address, ISerializer& serializer) { + serializer(address.m_spendPublicKey, "m_spend_public_key"); + serializer(address.m_viewPublicKey, "m_view_public_key"); } -void doSerialize(tx_extra_merge_mining_tag& tag, const std::string& name, ISerializer& serializer) { +void serialize(account_keys& keys, ISerializer& s) { + s(keys.m_account_address, "m_account_address"); + s(keys.m_spend_secret_key, "m_spend_secret_key"); + s(keys.m_view_secret_key, "m_view_secret_key"); +} + +void doSerialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer) { uint64_t depth = static_cast(tag.depth); serializer(depth, "depth"); tag.depth = static_cast(depth); serializer(tag.merkle_root, "merkle_root"); } -void serialize(tx_extra_merge_mining_tag& tag, const std::string& name, ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer) { if (serializer.type() == ISerializer::OUTPUT) { std::stringstream stream; BinaryOutputStreamSerializer output(stream); - doSerialize(tag, "", output); + doSerialize(tag, output); std::string field = stream.str(); serializer(field, ""); } else { std::string field; serializer(field, ""); - std::stringstream stream(field); BinaryInputStreamSerializer input(stream); - doSerialize(tag, "", input); + doSerialize(tag, input); } - - serializer.endObject(); } } //namespace CryptoNote diff --git a/src/cryptonote_core/cryptonote_serialization.h b/src/cryptonote_core/cryptonote_serialization.h index 9b72638e..ecf3c8ec 100644 --- a/src/cryptonote_core/cryptonote_serialization.h +++ b/src/cryptonote_core/cryptonote_serialization.h @@ -18,45 +18,46 @@ #pragma once #include "cryptonote_basic.h" - -namespace CryptoNote { -class ISerializer; -} +#include "serialization/ISerializer.h" namespace crypto { -void serialize(public_key& pubKey, const std::string& name, CryptoNote::ISerializer& enumerator); -void serialize(secret_key& secKey, const std::string& name, CryptoNote::ISerializer& enumerator); -void serialize(hash& h, const std::string& name, CryptoNote::ISerializer& enumerator); -void serialize(chacha8_iv& chacha, const std::string& name, CryptoNote::ISerializer& enumerator); -void serialize(key_image& keyImage, const std::string& name, CryptoNote::ISerializer& enumerator); +bool serialize(public_key& pubKey, Common::StringView name, CryptoNote::ISerializer& serializer); +bool serialize(secret_key& secKey, Common::StringView name, CryptoNote::ISerializer& serializer); +bool serialize(hash& h, Common::StringView name, CryptoNote::ISerializer& serializer); +bool serialize(chacha8_iv& chacha, Common::StringView name, CryptoNote::ISerializer& serializer); +bool serialize(key_image& keyImage, Common::StringView name, CryptoNote::ISerializer& serializer); +bool serialize(signature& sig, Common::StringView name, CryptoNote::ISerializer& serializer); } //namespace crypto namespace CryptoNote { -void serialize(ParentBlockSerializer& pbs, const std::string& name, ISerializer& serializer); -void serialize(TransactionPrefix& txP, const std::string& name, ISerializer& serializer); -void serialize(Transaction& tx, const std::string& name, ISerializer& serializer); -void serialize(TransactionInput& in, const std::string& name, ISerializer& serializer); -void serialize(TransactionOutput& in, const std::string& name, ISerializer& serializer); +void serialize(ParentBlockSerializer& pbs, ISerializer& serializer); +void serialize(TransactionPrefix& txP, ISerializer& serializer); +void serialize(Transaction& tx, ISerializer& serializer); +void serialize(TransactionInput& in, ISerializer& serializer); +void serialize(TransactionOutput& in, ISerializer& serializer); -void serialize(TransactionInputGenerate& gen, const std::string& name, ISerializer& serializer); -void serialize(TransactionInputToScript& script, const std::string& name, ISerializer& serializer); -void serialize(TransactionInputToScriptHash& scripthash, const std::string& name, ISerializer& serializer); -void serialize(TransactionInputToKey& key, const std::string& name, ISerializer& serializer); -void serialize(TransactionInputMultisignature& multisignature, const std::string& name, ISerializer& serializer); +void serialize(TransactionInputGenerate& gen, ISerializer& serializer); +void serialize(TransactionInputToScript& script, ISerializer& serializer); +void serialize(TransactionInputToScriptHash& scripthash, ISerializer& serializer); +void serialize(TransactionInputToKey& key, ISerializer& serializer); +void serialize(TransactionInputMultisignature& multisignature, ISerializer& serializer); -void serialize(TransactionOutput& output, const std::string& name, ISerializer& serializer); +void serialize(TransactionOutput& output, ISerializer& serializer); -void serialize(TransactionOutputTarget& output, const std::string& name, ISerializer& serializer); +void serialize(TransactionOutputTarget& output, ISerializer& serializer); + +void serialize(TransactionOutputToScript& script, ISerializer& serializer); +void serialize(TransactionOutputToScriptHash& scripthash, ISerializer& serializer); +void serialize(TransactionOutputToKey& key, ISerializer& serializer); +void serialize(TransactionOutputMultisignature& multisignature, ISerializer& serializer); +void serialize(BlockHeader& header, ISerializer& serializer); +void serialize(Block& block, ISerializer& serializer); +void serialize(tx_extra_merge_mining_tag& tag, ISerializer& serializer); + +void serialize(AccountPublicAddress& address, ISerializer& serializer); +void serialize(account_keys& keys, ISerializer& s); -void serialize(TransactionOutputToScript& script, const std::string& name, ISerializer& serializer); -void serialize(TransactionOutputToScriptHash& scripthash, const std::string& name, ISerializer& serializer); -void serialize(TransactionOutputToKey& key, const std::string& name, ISerializer& serializer); -void serialize(TransactionOutputMultisignature& multisignature, const std::string& name, ISerializer& serializer); -void serialize(BlockHeader& header, const std::string& name, ISerializer& serializer); -void serialize(Block& block, const std::string& name, ISerializer& serializer); -void serialize(AccountPublicAddress& address, const std::string& name, ISerializer& serializer); -void serialize(tx_extra_merge_mining_tag& tag, const std::string& name, ISerializer& serializer); } //namespace CryptoNote diff --git a/src/cryptonote_core/cryptonote_stat_info.h b/src/cryptonote_core/cryptonote_stat_info.h index 74052218..0c7bec64 100644 --- a/src/cryptonote_core/cryptonote_stat_info.h +++ b/src/cryptonote_core/cryptonote_stat_info.h @@ -16,8 +16,8 @@ // along with Bytecoin. If not, see . #pragma once -#include "serialization/keyvalue_serialization.h" +#include "serialization/ISerializer.h" namespace CryptoNote { @@ -29,12 +29,12 @@ namespace CryptoNote uint64_t alternative_blocks; std::string top_block_id_str; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(blockchain_height) - KV_SERIALIZE(mining_speed) - KV_SERIALIZE(alternative_blocks) - KV_SERIALIZE(top_block_id_str) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(tx_pool_size) + KV_MEMBER(blockchain_height) + KV_MEMBER(mining_speed) + KV_MEMBER(alternative_blocks) + KV_MEMBER(top_block_id_str) + } }; } diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp index 809200bd..8c7cddd0 100644 --- a/src/cryptonote_core/miner.cpp +++ b/src/cryptonote_core/miner.cpp @@ -25,14 +25,13 @@ #include #include #include +#include #include #include #include "cryptonote_format_utils.h" #include "Common/command_line.h" - -// epee -#include "storages/portable_storage_template_helper.h" +#include "serialization/SerializationTools.h" using namespace Logging; @@ -182,13 +181,18 @@ namespace CryptoNote } m_config_folder_path = boost::filesystem::path(config.extraMessages).parent_path().string(); m_config = boost::value_initialized(); - epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + CryptoNote::parameters::MINER_CONFIG_FILE_NAME); + + std::string filebuf; + if (Common::loadFileToString(m_config_folder_path + "/" + CryptoNote::parameters::MINER_CONFIG_FILE_NAME, filebuf)) { + loadFromJson(m_config, filebuf); + } + logger(INFO) << "Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index; } if(!config.startMining.empty()) { if (!m_currency.parseAccountAddressString(config.startMining, m_mine_address)) { - LOG_ERROR("Target account address " << config.startMining << " has wrong format, starting daemon canceled"); + logger(ERROR) << "Target account address " << config.startMining << " has wrong format, starting daemon canceled"; return false; } m_threads_total = 1; @@ -410,7 +414,7 @@ namespace CryptoNote --m_config.current_extra_message_index; } else { //success update, lets update config - epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + CryptoNote::parameters::MINER_CONFIG_FILE_NAME); + Common::saveStringToFile(m_config_folder_path + "/" + CryptoNote::parameters::MINER_CONFIG_FILE_NAME, storeToJson(m_config)); } } diff --git a/src/cryptonote_core/miner.h b/src/cryptonote_core/miner.h index e2c3ba06..c52a195e 100644 --- a/src/cryptonote_core/miner.h +++ b/src/cryptonote_core/miner.h @@ -22,9 +22,6 @@ #include #include -// epee -#include "serialization/keyvalue_serialization.h" - #include "cryptonote_core/cryptonote_basic.h" #include "cryptonote_core/Currency.h" #include "cryptonote_core/difficulty.h" @@ -34,6 +31,8 @@ #include +#include "serialization/ISerializer.h" + namespace CryptoNote { class miner { public: @@ -64,13 +63,11 @@ namespace CryptoNote { struct miner_config { uint64_t current_extra_message_index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_extra_message_index) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(current_extra_message_index) + } }; - const Currency& m_currency; Logging::LoggerRef logger; @@ -81,7 +78,6 @@ namespace CryptoNote { std::atomic m_starter_nonce; difficulty_type m_diffic; - // volatile uint32_t m_thread_index; std::atomic m_threads_total; std::atomic m_pausers_count; std::mutex m_miners_count_lock; @@ -90,8 +86,6 @@ namespace CryptoNote { std::mutex m_threads_lock; i_miner_handler& m_handler; AccountPublicAddress m_mine_address; - //epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; - //epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; OnceInInterval m_update_block_template_interval; OnceInInterval m_update_merge_hr_interval; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 36040c36..5f5e8edf 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -34,6 +34,8 @@ using namespace Logging; +#undef ERROR + namespace CryptoNote { //--------------------------------------------------------------------------------- @@ -130,8 +132,8 @@ namespace CryptoNote { const uint64_t fee = inputs_amount - outputs_amount; if (!keptByBlock && fee < m_currency.minimumFee()) { - logger(INFO) << "transaction fee is not enought: " << m_currency.formatAmount(fee) << - ", minumim fee: " << m_currency.formatAmount(m_currency.minimumFee()); + logger(INFO) << "transaction fee is not enough: " << m_currency.formatAmount(fee) << + ", minimum fee: " << m_currency.formatAmount(m_currency.minimumFee()); tvc.m_verifivation_failed = true; tvc.m_tx_fee_too_small = true; return false; @@ -165,6 +167,14 @@ namespace CryptoNote { std::lock_guard lock(m_transactions_lock); + if (!keptByBlock && m_recentlyDeletedTransactions.find(id) != m_recentlyDeletedTransactions.end()) { + logger(INFO) << "Trying to add recently deleted transaction. Ignore: " << id; + tvc.m_verifivation_failed = false; + tvc.m_should_be_relayed = false; + tvc.m_added_to_pool = false; + return true; + } + // add to pool { TransactionDetails txd; @@ -180,7 +190,10 @@ namespace CryptoNote { txd.lastFailedBlock.clear(); auto txd_p = m_transactions.insert(std::move(txd)); - if (!(txd_p.second)) { logger(ERROR, BRIGHT_RED) << "transaction already exists at inserting in memory pool"; return false; } + if (!(txd_p.second)) { + logger(ERROR, BRIGHT_RED) << "transaction already exists at inserting in memory pool"; + return false; + } } tvc.m_added_to_pool = true; @@ -372,6 +385,9 @@ namespace CryptoNote { m_spent_key_images.clear(); m_spentOutputs.clear(); } + + removeExpiredTransactions(); + // Ignore deserialization error return true; } @@ -399,22 +415,32 @@ namespace CryptoNote { bool tx_memory_pool::removeExpiredTransactions() { bool somethingRemoved = false; { - std::lock_guard lock(m_transactions_lock); + std::lock_guard lock(m_transactions_lock); - auto now = m_timeProvider.now(); + uint64_t now = m_timeProvider.now(); - for (auto it = m_transactions.begin(); it != m_transactions.end();) { - uint64_t txAge = now - it->receiveTime; - bool remove = txAge > (it->keptByBlock ? m_currency.mempoolTxFromAltBlockLiveTime() : m_currency.mempoolTxLiveTime()); - - if (remove) { - logger(TRACE) << "Tx " << it->id << " removed from tx pool due to outdated, age: " << txAge; - it = removeTransaction(it); - somethingRemoved = true; - } else { - ++it; + for (auto it = m_recentlyDeletedTransactions.begin(); it != m_recentlyDeletedTransactions.end();) { + uint64_t elapsedTimeSinceDeletion = now - it->second; + if (elapsedTimeSinceDeletion > m_currency.numberOfPeriodsToForgetTxDeletedFromPool() * m_currency.mempoolTxLiveTime()) { + it = m_recentlyDeletedTransactions.erase(it); + } else { + ++it; + } + } + + for (auto it = m_transactions.begin(); it != m_transactions.end();) { + uint64_t txAge = now - it->receiveTime; + bool remove = txAge > (it->keptByBlock ? m_currency.mempoolTxFromAltBlockLiveTime() : m_currency.mempoolTxLiveTime()); + + if (remove) { + logger(TRACE) << "Tx " << it->id << " removed from tx pool due to outdated, age: " << txAge; + m_recentlyDeletedTransactions.emplace(it->id, now); + it = removeTransaction(it); + somethingRemoved = true; + } else { + ++it; + } } - } } if (somethingRemoved) { diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 7276f271..d52173a1 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -127,7 +127,7 @@ namespace CryptoNote { } } -#define CURRENT_MEMPOOL_ARCHIVE_VER 10 +#define CURRENT_MEMPOOL_ARCHIVE_VER 11 template void serialize(archive_t & a, const unsigned int version) { @@ -139,6 +139,7 @@ namespace CryptoNote { a & m_transactions; a & m_spent_key_images; a & m_spentOutputs; + a & m_recentlyDeletedTransactions; } struct TransactionCheckInfo { @@ -212,6 +213,7 @@ namespace CryptoNote { tx_container_t m_transactions; tx_container_t::nth_index<1>::type& m_fee_index; + std::unordered_map m_recentlyDeletedTransactions; Logging::LoggerRef logger; diff --git a/src/cryptonote_core/verification_context.h b/src/cryptonote_core/verification_context.h index 70cc1b54..346bf05a 100644 --- a/src/cryptonote_core/verification_context.h +++ b/src/cryptonote_core/verification_context.h @@ -36,5 +36,6 @@ namespace CryptoNote bool m_verifivation_failed; //bad block, should drop connection bool m_marked_as_orphaned; bool m_already_exists; + bool m_switched_to_alt_chain; }; } diff --git a/src/cryptonote_protocol/ICryptonoteProtocolObserver.h b/src/cryptonote_protocol/ICryptonoteProtocolObserver.h index 3f909048..34c11402 100644 --- a/src/cryptonote_protocol/ICryptonoteProtocolObserver.h +++ b/src/cryptonote_protocol/ICryptonoteProtocolObserver.h @@ -27,6 +27,7 @@ class ICryptonoteProtocolObserver { public: virtual void peerCountUpdated(size_t count) {} virtual void lastKnownBlockHeightUpdated(uint64_t height) {} + virtual void blockchainSynchronized(uint64_t topHeight) {} }; } //namespace CryptoNote diff --git a/src/cryptonote_protocol/ICryptonoteProtocolQuery.h b/src/cryptonote_protocol/ICryptonoteProtocolQuery.h index 1eb79ec9..b9d42279 100644 --- a/src/cryptonote_protocol/ICryptonoteProtocolQuery.h +++ b/src/cryptonote_protocol/ICryptonoteProtocolQuery.h @@ -18,6 +18,7 @@ #pragma once #include +#include namespace CryptoNote { class ICryptonoteProtocolObserver; @@ -29,6 +30,7 @@ public: virtual uint64_t getObservedHeight() const = 0; virtual size_t getPeerCount() const = 0; + virtual bool isSynchronized() const = 0; }; } //namespace CryptoNote diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 57458813..6a1904d9 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -18,10 +18,13 @@ #pragma once #include -#include "serialization/keyvalue_serialization.h" #include "cryptonote_core/cryptonote_basic.h" #include "cryptonote_protocol/blobdatatype.h" +// ISerializer-based serialization +#include "serialization/ISerializer.h" +#include "serialization/SerializationOverloads.h" +#include "cryptonote_core/cryptonote_serialization.h" namespace CryptoNote { @@ -35,21 +38,24 @@ namespace CryptoNote { blobdata block; std::list txs; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block) - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer& s) { + KV_MEMBER(block); + KV_MEMBER(txs); + } + }; struct BlockFullInfo : public block_complete_entry { crypto::hash block_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(block_id) - KV_SERIALIZE(block) - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(block_id); + KV_MEMBER(block); + KV_MEMBER(txs); + } + }; /************************************************************************/ @@ -61,11 +67,11 @@ namespace CryptoNote uint64_t current_blockchain_height; uint32_t hop; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(b) - KV_SERIALIZE(current_blockchain_height) - KV_SERIALIZE(hop) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(b) + KV_MEMBER(current_blockchain_height) + KV_MEMBER(hop) + } }; struct NOTIFY_NEW_BLOCK @@ -81,9 +87,10 @@ namespace CryptoNote { std::list txs; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(txs); + } + }; struct NOTIFY_NEW_TRANSACTIONS @@ -100,10 +107,10 @@ namespace CryptoNote std::list txs; std::list blocks; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(txs) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blocks) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + serializeAsBinary(txs, "txs", s); + serializeAsBinary(blocks, "blocks", s); + } }; struct NOTIFY_REQUEST_GET_OBJECTS @@ -114,17 +121,18 @@ namespace CryptoNote struct NOTIFY_RESPONSE_GET_OBJECTS_request { - std::list txs; - std::list blocks; - std::list missed_ids; - uint64_t current_blockchain_height; + std::list txs; + std::list blocks; + std::list missed_ids; + uint64_t current_blockchain_height; + + void serialize(ISerializer& s) { + KV_MEMBER(txs) + KV_MEMBER(blocks) + serializeAsBinary(missed_ids, "missed_ids", s); + KV_MEMBER(current_blockchain_height) + } - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs) - KV_SERIALIZE(blocks) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(missed_ids) - KV_SERIALIZE(current_blockchain_height) - END_KV_SERIALIZE_MAP() }; struct NOTIFY_RESPONSE_GET_OBJECTS @@ -141,9 +149,9 @@ namespace CryptoNote { std::list block_ids; /*IDs of the first 10 blocks are sequential, next goes with pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + serializeAsBinary(block_ids, "block_ids", s); + } }; }; @@ -153,11 +161,11 @@ namespace CryptoNote uint64_t total_height; std::list m_block_ids; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(start_height) - KV_SERIALIZE(total_height) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_ids) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(start_height) + KV_MEMBER(total_height) + serializeAsBinary(m_block_ids, "m_block_ids", s); + } }; struct NOTIFY_RESPONSE_CHAIN_ENTRY @@ -166,4 +174,19 @@ namespace CryptoNote typedef NOTIFY_RESPONSE_CHAIN_ENTRY_request request; }; + /************************************************************************/ + /* */ + /************************************************************************/ + struct NOTIFY_REQUEST_TX_POOL_request { + std::vector txs; + + void serialize(ISerializer& s) { + serializeAsBinary(txs, "txs", s); + } + }; + + struct NOTIFY_REQUEST_TX_POOL { + const static int ID = BC_COMMANDS_POOL_BASE + 8; + typedef NOTIFY_REQUEST_TX_POOL_request request; + }; } diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler.cpp index 018656f1..0edd5703 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include "cryptonote_core/cryptonote_basic_impl.h" @@ -34,7 +35,7 @@ namespace CryptoNote { namespace { template -bool post_notify(i_p2p_endpoint& p2p, typename t_parametr::request& arg, cryptonote_connection_context& context) { +bool post_notify(i_p2p_endpoint& p2p, typename t_parametr::request& arg, const cryptonote_connection_context& context) { return p2p.invoke_notify_to_peer(t_parametr::ID, LevinProtocol::encode(arg), context); } @@ -151,9 +152,12 @@ bool cryptonote_protocol_handler::process_payload_sync_data(const CORE_SYNC_DATA if (context.m_state == cryptonote_connection_context::state_synchronizing) { } else if (m_core.have_block(hshd.top_id)) { - context.m_state = cryptonote_connection_context::state_normal; - if (is_inital) + if (is_inital) { on_connection_synchronized(); + context.m_state = cryptonote_connection_context::state_pool_sync_required; + } else { + context.m_state = cryptonote_connection_context::state_normal; + } } else { int64_t diff = static_cast(hshd.current_height) - static_cast(get_current_blockchain_height()); @@ -200,7 +204,7 @@ int notifyAdaptor(const std::string& reqBuf, cryptonote_connection_context& ctx, return handler(command, req, ctx); } -#define HANDLE_NOTIFY(CMD, Handler) case CMD::ID: { ret = notifyAdaptor(in, ctx, boost::bind(Handler, this, _1, _2, _3)); break; } +#define HANDLE_NOTIFY(CMD, Handler) case CMD::ID: { ret = notifyAdaptor(in, ctx, std::bind(Handler, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); break; } int cryptonote_protocol_handler::handleCommand(bool is_notify, int command, const std::string& in, std::string& out, cryptonote_connection_context& ctx, bool& handled) { int ret = 0; @@ -213,6 +217,7 @@ int cryptonote_protocol_handler::handleCommand(bool is_notify, int command, cons HANDLE_NOTIFY(NOTIFY_RESPONSE_GET_OBJECTS, &cryptonote_protocol_handler::handle_response_get_objects) HANDLE_NOTIFY(NOTIFY_REQUEST_CHAIN, &cryptonote_protocol_handler::handle_request_chain) HANDLE_NOTIFY(NOTIFY_RESPONSE_CHAIN_ENTRY, &cryptonote_protocol_handler::handle_response_chain_entry) + HANDLE_NOTIFY(NOTIFY_REQUEST_TX_POOL, &cryptonote_protocol_handler::handleRequestTxPool) default: handled = false; @@ -262,6 +267,8 @@ int cryptonote_protocol_handler::handle_notify_new_block(int command, NOTIFY_NEW m_core.get_short_chain_history(r.block_ids); logger(Logging::TRACE) << context << "-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size(); post_notify(*m_p2p, r, context); + } else if (bvc.m_switched_to_alt_chain) { + requestMissingPoolTransactions(context); } return 1; @@ -276,14 +283,13 @@ int cryptonote_protocol_handler::handle_notify_new_transactions(int command, NOT CryptoNote::tx_verification_context tvc = boost::value_initialized(); m_core.handle_incoming_tx(*tx_blob_it, tvc, false); if (tvc.m_verifivation_failed) { - logger(Logging::INFO) << context << "Tx verification failed, dropping connection"; - context.m_state = cryptonote_connection_context::state_shutdown; - return 1; + logger(Logging::INFO) << context << "Tx verification failed"; } - if (tvc.m_should_be_relayed) + if (!tvc.m_verifivation_failed && tvc.m_should_be_relayed) { ++tx_blob_it; - else - arg.txs.erase(tx_blob_it++); + } else { + tx_blob_it = arg.txs.erase(tx_blob_it); + } } if (arg.txs.size()) { @@ -394,7 +400,7 @@ int cryptonote_protocol_handler::handle_response_get_objects(int command, NOTIFY uint64_t height; crypto::hash top; m_core.get_blockchain_top(height, top); - logger(INFO, BRIGHT_GREEN) << "Local blockchain updated, new height = " << height; + logger(DEBUGGING, BRIGHT_GREEN) << "Local blockchain updated, new height = " << height; if (!m_stop && context.m_state == cryptonote_connection_context::state_synchronizing) { request_missing_objects(context, true); @@ -475,7 +481,7 @@ bool cryptonote_protocol_handler::request_missing_objects(cryptonote_connection_ ++count; context.m_requested_objects.insert(*it); } - context.m_needed_objects.erase(it++); + it = context.m_needed_objects.erase(it); } logger(Logging::TRACE) << context << "-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size(); post_notify(*m_p2p, req, context); @@ -500,6 +506,8 @@ bool cryptonote_protocol_handler::request_missing_objects(cryptonote_connection_ return false; } + requestMissingPoolTransactions(context); + context.m_state = cryptonote_connection_context::state_normal; logger(Logging::INFO, Logging::BRIGHT_GREEN) << context << "SYNCHRONIZED OK"; on_connection_synchronized(); @@ -519,6 +527,12 @@ bool cryptonote_protocol_handler::on_connection_synchronized() { << "Use \"help\" command to see the list of available commands." << ENDL << "**********************************************************************"; m_core.on_synchronized(); + + uint64_t height; + crypto::hash hash; + if (m_core.get_blockchain_top(height, hash)) { + m_observerManager.notify(&ICryptonoteProtocolObserver::blockchainSynchronized, height); + } } return true; } @@ -563,6 +577,30 @@ int cryptonote_protocol_handler::handle_response_chain_entry(int command, NOTIFY return 1; } +int cryptonote_protocol_handler::handleRequestTxPool(int command, NOTIFY_REQUEST_TX_POOL::request& arg, + cryptonote_connection_context& context) { + logger(Logging::TRACE) << context << "NOTIFY_REQUEST_TX_POOL: txs.size() = " << arg.txs.size(); + + std::vector addedTransactions; + std::vector deletedTransactions; + m_core.getPoolChanges(arg.txs, addedTransactions, deletedTransactions); + + if (!addedTransactions.empty()) { + NOTIFY_NEW_TRANSACTIONS::request notification; + for (auto& tx : addedTransactions) { + notification.txs.push_back(tx_to_blob(tx)); + } + + bool ok = post_notify(*m_p2p, notification, context); + if (!ok) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Failed to post notification NOTIFY_NEW_TRANSACTIONS to " << context.m_connection_id; + } + } + + return 1; +} + + void cryptonote_protocol_handler::relay_block(NOTIFY_NEW_BLOCK::request& arg) { auto buf = LevinProtocol::encode(arg); m_p2p->externalRelayNotifyToAll(NOTIFY_NEW_BLOCK::ID, buf); @@ -573,6 +611,24 @@ void cryptonote_protocol_handler::relay_transactions(NOTIFY_NEW_TRANSACTIONS::re m_p2p->externalRelayNotifyToAll(NOTIFY_NEW_TRANSACTIONS::ID, buf); } +void cryptonote_protocol_handler::requestMissingPoolTransactions(const cryptonote_connection_context& context) { + if (context.version < P2PProtocolVersion::V1) { + return; + } + + auto poolTxs = m_core.getPoolTransactions(); + + NOTIFY_REQUEST_TX_POOL::request notification; + for (auto& tx : poolTxs) { + notification.txs.emplace_back(get_transaction_hash(tx)); + } + + bool ok = post_notify(*m_p2p, notification, context); + if (!ok) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Failed to post notification NOTIFY_REQUEST_TX_POOL to " << context.m_connection_id; + } +} + void cryptonote_protocol_handler::updateObservedHeight(uint64_t peerHeight, const cryptonote_connection_context& context) { bool updated = false; { diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 1e2cd8aa..9fccc75f 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -35,9 +35,6 @@ #include -PUSH_WARNINGS -DISABLE_VS_WARNINGS(4355) - namespace System { class Dispatcher; } @@ -59,7 +56,7 @@ namespace CryptoNote void set_p2p_endpoint(i_p2p_endpoint* p2p); // ICore& get_core() { return m_core; } - bool is_synchronized() const { return m_synchronized; } + virtual bool isSynchronized() const override { return m_synchronized; } void log_connections(); // Interface t_payload_net_handler, where t_payload_net_handler is template argument of nodetool::node_server @@ -74,6 +71,7 @@ namespace CryptoNote int handleCommand(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, cryptonote_connection_context& context, bool& handled); virtual size_t getPeerCount() const; virtual uint64_t getObservedHeight() const; + void requestMissingPoolTransactions(const cryptonote_connection_context& context); private: //----------------- commands handlers ---------------------------------------------- @@ -83,6 +81,7 @@ namespace CryptoNote int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, cryptonote_connection_context& context); int handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, cryptonote_connection_context& context); int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, cryptonote_connection_context& context); + int handleRequestTxPool(int command, NOTIFY_REQUEST_TX_POOL::request& arg, cryptonote_connection_context& context); //----------------- i_cryptonote_protocol ---------------------------------- virtual void relay_block(NOTIFY_NEW_BLOCK::request& arg) override; @@ -115,5 +114,3 @@ namespace CryptoNote tools::ObserverManager m_observerManager; }; } - -POP_WARNINGS diff --git a/src/daemon/DeamonCommandsHandler.cpp b/src/daemon/DeamonCommandsHandler.cpp index 3f81544b..241424ca 100644 --- a/src/daemon/DeamonCommandsHandler.cpp +++ b/src/daemon/DeamonCommandsHandler.cpp @@ -265,7 +265,7 @@ bool DaemonCommandsHandler::print_tx(const std::vector& args) tx_ids.push_back(tx_hash); std::list txs; std::list missed_ids; - m_core.get_transactions(tx_ids, txs, missed_ids); + m_core.getTransactions(tx_ids, txs, missed_ids); if (1 == txs.size()) { print_as_json(txs.front()); diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 697f20e7..3c5e6957 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -17,6 +17,7 @@ #include "version.h" +#include #include #include "DaemonCommandsHandler.h" diff --git a/src/node_rpc_proxy/NodeRpcProxy.cpp b/src/node_rpc_proxy/NodeRpcProxy.cpp index 4d88d384..3e3c1095 100644 --- a/src/node_rpc_proxy/NodeRpcProxy.cpp +++ b/src/node_rpc_proxy/NodeRpcProxy.cpp @@ -32,6 +32,10 @@ #include "rpc/HttpClient.h" #include "rpc/JsonRpc.h" +#ifndef AUTO_VAL_INIT +#define AUTO_VAL_INIT(n) boost::value_initialized() +#endif + namespace CryptoNote { namespace { @@ -124,9 +128,9 @@ NodeRpcProxy::~NodeRpcProxy() { void NodeRpcProxy::resetInternalState() { m_ioService.reset(); - m_peerCount = 0; - m_nodeHeight = 0; - m_networkHeight = 0; + m_peerCount.store(0, std::memory_order_relaxed); + m_nodeHeight.store(0, std::memory_order_relaxed); + m_networkHeight.store(0, std::memory_order_relaxed); m_lastKnowHash = CryptoNote::null_hash; } @@ -199,16 +203,16 @@ void NodeRpcProxy::updateNodeStatus() { if (blockHash != m_lastKnowHash) { m_lastKnowHash = blockHash; - m_nodeHeight = rsp.block_header.height; + m_nodeHeight.store(rsp.block_header.height, std::memory_order_relaxed); m_lastLocalBlockTimestamp = rsp.block_header.timestamp; // TODO request and update network height - m_networkHeight = m_nodeHeight; - m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight); - //if (m_networkHeight != rsp.block_header.network_height) { - // m_networkHeight = rsp.block_header.network_height; + m_networkHeight.store(rsp.block_header.height, std::memory_order_relaxed); + m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight.load(std::memory_order_relaxed)); + //if (m_networkHeight.load(std::memory_order_relaxed) != rsp.block_header.network_height) { + // m_networkHeight.store(rsp.block_header.height, std::memory_order_relaxed); // m_observerManager.notify(&INodeObserver::lastKnownBlockHeightUpdated, m_networkHeight); //} - m_observerManager.notify(&INodeObserver::localBlockchainUpdated, m_nodeHeight); + m_observerManager.notify(&INodeObserver::localBlockchainUpdated, m_nodeHeight.load(std::memory_order_relaxed)); } } @@ -226,7 +230,7 @@ void NodeRpcProxy::updatePeerCount() { size_t peerCount = rsp.incoming_connections_count + rsp.outgoing_connections_count; if (peerCount != m_peerCount) { m_peerCount = peerCount; - m_observerManager.notify(&INodeObserver::peerCountUpdated, m_peerCount); + m_observerManager.notify(&INodeObserver::peerCountUpdated, m_peerCount.load(std::memory_order_relaxed)); } } } @@ -240,15 +244,15 @@ bool NodeRpcProxy::removeObserver(INodeObserver* observer) { } size_t NodeRpcProxy::getPeerCount() const { - return m_peerCount; + return m_peerCount.load(std::memory_order_relaxed); } uint64_t NodeRpcProxy::getLastLocalBlockHeight() const { - return m_nodeHeight; + return m_nodeHeight.load(std::memory_order_relaxed); } uint64_t NodeRpcProxy::getLastKnownBlockHeight() const { - return m_networkHeight; + return m_networkHeight.load(std::memory_order_relaxed); } uint64_t NodeRpcProxy::getLocalBlockCount() const { @@ -309,6 +313,18 @@ void NodeRpcProxy::queryBlocks(std::list&& knownBlockIds, uint64_t m_ioService.post(std::bind(&NodeRpcProxy::doQueryBlocks, this, std::move(knownBlockIds), timestamp, std::ref(newBlocks), std::ref(startHeight), callback)); } +void NodeRpcProxy::getPoolSymmetricDifference(std::vector&& knownTxsIds, crypto::hash tailBlockId, + bool& isTailBlockActual, std::vector& addedTxs, + std::vector& deletedTxsIds, const Callback& callback) { + if (!m_initState.initialized()) { + callback(make_error_code(error::NOT_INITIALIZED)); + return; + } + + m_ioService.post(std::bind(&NodeRpcProxy::doGetPoolSymmetricDifference, this, std::move(knownTxsIds), tailBlockId, + std::ref(isTailBlockActual), std::ref(addedTxs), std::ref(deletedTxsIds), callback)); +} + void NodeRpcProxy::doRelayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) { COMMAND_RPC_SEND_RAW_TX::request req; COMMAND_RPC_SEND_RAW_TX::response rsp; @@ -385,9 +401,51 @@ void NodeRpcProxy::doQueryBlocks(const std::list& knownBlockIds, u callback(ec); } -void NodeRpcProxy::getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) { - is_bc_actual = true; +void NodeRpcProxy::doGetPoolSymmetricDifference(const std::vector& knownTxsIds, + const crypto::hash& tailBlockId, bool& isTailBlockActual, + std::vector& addedTxs, + std::vector& deletedTxsIds, const Callback& callback) { + CryptoNote::COMMAND_RPC_GET_POOL_CHANGES::request req = AUTO_VAL_INIT(req); + CryptoNote::COMMAND_RPC_GET_POOL_CHANGES::response rsp = AUTO_VAL_INIT(rsp); + + req.tailBlockId = tailBlockId; + req.knownTxsIds = knownTxsIds; + + std::error_code ec = binaryCommand(*m_httpClient, "/get_pool_changes.bin", req, rsp); + if (!ec) { + isTailBlockActual = rsp.isTailBlockActual; + if (isTailBlockActual) { + deletedTxsIds = std::move(rsp.deletedTxsIds); + + for (auto& txBlob : rsp.addedTxs) { + CryptoNote::Transaction tx; + if (!CryptoNote::parse_and_validate_tx_from_blob(txBlob, tx)) { + ec = make_error_code(error::INTERNAL_NODE_ERROR); + break; + } + + addedTxs.emplace_back(std::move(tx)); + } + } + } + + callback(ec); +} + +void NodeRpcProxy::getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { callback(std::error_code()); -}; +} + +void NodeRpcProxy::getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { + callback(std::error_code()); +} + +void NodeRpcProxy::getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { + callback(std::error_code()); +} + +void NodeRpcProxy::isSynchronized(bool& syncStatus, const Callback& callback) { + callback(std::error_code()); +} } diff --git a/src/node_rpc_proxy/NodeRpcProxy.h b/src/node_rpc_proxy/NodeRpcProxy.h index e8dd64a6..72c69526 100644 --- a/src/node_rpc_proxy/NodeRpcProxy.h +++ b/src/node_rpc_proxy/NodeRpcProxy.h @@ -54,8 +54,14 @@ public: virtual void getNewBlocks(std::list&& knownBlockIds, std::list& newBlocks, uint64_t& startHeight, const Callback& callback); virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback); virtual void queryBlocks(std::list&& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) override; - virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) override; - + // TODO INodeObserver::poolChanged() notification NOT implemented!!! + virtual void getPoolSymmetricDifference(std::vector&& knownTxsIds, crypto::hash tailBlockId, + bool& isTailBlockActual, std::vector& addedTxs, + std::vector& deletedTxsIds, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; unsigned int rpcTimeout() const { return m_rpcTimeout; } void rpcTimeout(unsigned int val) { m_rpcTimeout = val; } @@ -73,6 +79,9 @@ private: void doGetNewBlocks(std::list& knownBlockIds, std::list& newBlocks, uint64_t& startHeight, const Callback& callback); void doGetTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback); void doQueryBlocks(const std::list& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const Callback& callback); + void doGetPoolSymmetricDifference(const std::vector& knownTxsIds, const crypto::hash& tailBlockId, + bool& isTailBlockActual, std::vector& addedTxs, + std::vector& deletedTxsIds, const Callback& callback); private: tools::InitState m_initState; @@ -89,9 +98,9 @@ private: uint64_t m_pullInterval; // Internal state - size_t m_peerCount; - uint64_t m_nodeHeight; - uint64_t m_networkHeight; + std::atomic m_peerCount; + std::atomic m_nodeHeight; + std::atomic m_networkHeight; crypto::hash m_lastKnowHash; uint64_t m_lastLocalBlockTimestamp; }; diff --git a/src/p2p/LevinProtocol.h b/src/p2p/LevinProtocol.h index 523e7ac2..5d335c9e 100644 --- a/src/p2p/LevinProtocol.h +++ b/src/p2p/LevinProtocol.h @@ -17,10 +17,8 @@ #pragma once -#include "misc_log_ex.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_from_bin.h" -#include "storages/portable_storage_to_bin.h" +#include "serialization/KVBinaryInputStreamSerializer.h" +#include "serialization/KVBinaryOutputStreamSerializer.h" namespace System { class TcpConnection; @@ -72,20 +70,24 @@ public: template static bool decode(const std::string& buf, T& value) { - epee::serialization::portable_storage stg; - if (!stg.load_from_binary(buf)) { + try { + std::stringstream stream(buf); + KVBinaryInputStreamSerializer serializer(stream); + serialize(value, serializer); + } catch (std::exception&) { return false; } - return value.load(stg); + + return true; } template static std::string encode(const T& value) { - std::string buf; - epee::serialization::portable_storage stg; - value.store(stg); - stg.store_to_binary(buf); - return buf; + KVBinaryOutputStreamSerializer serializer; + serialize(const_cast(value), serializer); + std::stringstream stream; + serializer.write(stream); + return stream.str(); } private: diff --git a/src/p2p/connection_context.h b/src/p2p/connection_context.h index 02cced1b..97cf4021 100644 --- a/src/p2p/connection_context.h +++ b/src/p2p/connection_context.h @@ -28,6 +28,7 @@ namespace CryptoNote { struct cryptonote_connection_context { + uint8_t version; boost::uuids::uuid m_connection_id; uint32_t m_remote_ip = 0; uint32_t m_remote_port = 0; @@ -40,6 +41,7 @@ struct cryptonote_connection_context { state_idle, state_normal, state_sync_required, + state_pool_sync_required, state_shutdown }; diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index 0faf95d4..128c3e88 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -283,7 +283,7 @@ namespace CryptoNote std::vector perrs = command_line::get_arg(vm, arg_p2p_add_peer); for(const std::string& pr_str: perrs) { - peerlist_entry pe = AUTO_VAL_INIT(pe); + peerlist_entry pe = boost::value_initialized(); pe.id = crypto::rand(); bool r = parse_peer_from_string(pe.adr, pr_str); if (!(r)) { logger(ERROR, BRIGHT_RED) << "Failed to parse address from string: " << pr_str; return false; } @@ -512,6 +512,8 @@ namespace CryptoNote proto.invoke(COMMAND_HANDSHAKE::ID, arg, rsp); + context.version = rsp.node_data.version; + if (rsp.node_data.network_id != m_network_id) { logger(Logging::ERROR) << context << "COMMAND_HANDSHAKE Failed, wrong network! (" << rsp.node_data.network_id << "), closing connection."; return false; @@ -545,7 +547,7 @@ namespace CryptoNote bool node_server::timedSync() { - COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg); + COMMAND_TIMED_SYNC::request arg = boost::value_initialized(); m_payload_handler.get_payload_sync_data(arg.payload_data); auto cmdBuf = LevinProtocol::encode(arg); @@ -695,7 +697,7 @@ namespace CryptoNote return true; } - peerlist_entry pe_local = AUTO_VAL_INIT(pe_local); + peerlist_entry pe_local = boost::value_initialized(); pe_local.adr = na; pe_local.id = raw->second.peer_id; time(&pe_local.last_seen); @@ -747,7 +749,7 @@ namespace CryptoNote continue; tried_peers.insert(random_index); - peerlist_entry pe = AUTO_VAL_INIT(pe); + peerlist_entry pe = boost::value_initialized(); bool r = use_white_list ? m_peerlist.get_white_peer_by_index(pe, random_index):m_peerlist.get_gray_peer_by_index(pe, random_index); if (!(r)) { logger(ERROR, BRIGHT_RED) << "Failed to get random peer from peerlist(white:" << use_white_list << ")"; return false; } @@ -894,6 +896,7 @@ namespace CryptoNote bool node_server::get_local_node_data(basic_node_data& node_data) { + node_data.version = P2PProtocolVersion::CURRENT; time_t local_time; time(&local_time); node_data.local_time = local_time; @@ -907,34 +910,34 @@ namespace CryptoNote } //----------------------------------------------------------------------------------- #ifdef ALLOW_DEBUG_COMMANDS - - bool node_server::check_trust(const proof_of_trust& tr) - { + + bool node_server::check_trust(const proof_of_trust &tr) { uint64_t local_time = time(NULL); - uint64_t time_delata = local_time > tr.time ? local_time - tr.time: tr.time - local_time; - if(time_delata > 24*60*60 ) - { - logger(ERROR) << "check_trust failed to check time conditions, local_time=" << local_time << ", proof_time=" << tr.time; + uint64_t time_delata = local_time > tr.time ? local_time - tr.time : tr.time - local_time; + + if (time_delata > 24 * 60 * 60) { + logger(ERROR) << "check_trust failed to check time conditions, local_time=" << local_time << ", proof_time=" << tr.time; return false; } - if(m_last_stat_request_time >= tr.time ) - { - logger(ERROR) << "check_trust failed to check time conditions, last_stat_request_time=" << m_last_stat_request_time << ", proof_time=" << tr.time; + + if (m_last_stat_request_time >= tr.time) { + logger(ERROR) << "check_trust failed to check time conditions, last_stat_request_time=" << m_last_stat_request_time << ", proof_time=" << tr.time; return false; } - if(m_config.m_peer_id != tr.peer_id) - { - logger(ERROR) << "check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << m_config.m_peer_id<< ")"; + + if (m_config.m_peer_id != tr.peer_id) { + logger(ERROR) << "check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << m_config.m_peer_id << ")"; return false; } - crypto::public_key pk = AUTO_VAL_INIT(pk); + + crypto::public_key pk; Common::podFromHex(CryptoNote::P2P_STAT_TRUSTED_PUB_KEY, pk); crypto::hash h = get_proof_of_trust_hash(tr); - if(!crypto::check_signature(h, pk, tr.sign)) - { + if (!crypto::check_signature(h, pk, tr.sign)) { logger(ERROR) << "check_trust failed: sign check failed"; return false; } + //update last request time m_last_stat_request_time = tr.time; return true; @@ -1081,7 +1084,9 @@ namespace CryptoNote int node_server::handle_handshake(int command, COMMAND_HANDSHAKE::request& arg, COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context) { - if(arg.node_data.network_id != m_network_id) { + context.version = arg.node_data.version; + + if (arg.node_data.network_id != m_network_id) { logger(Logging::INFO) << context << "WRONG NETWORK AGENT CONNECTED! id=" << arg.node_data.network_id; context.m_state = cryptonote_connection_context::state_shutdown; return 1; @@ -1211,7 +1216,7 @@ namespace CryptoNote std::vector perrs = command_line::get_arg(vm, arg); for(const std::string& pr_str: perrs) { - net_address na = AUTO_VAL_INIT(na); + net_address na; if (!parse_peer_from_string(na, pr_str)) { logger(ERROR, BRIGHT_RED) << "Failed to parse address from string: " << pr_str; return false; @@ -1223,8 +1228,8 @@ namespace CryptoNote } void node_server::acceptLoop() { - try { - for (;;) { + for (;;) { + try { p2p_connection_context ctx(m_dispatcher, m_listener.accept()); ctx.m_connection_id = boost::uuids::random_generator()(); ctx.m_is_income = true; @@ -1240,10 +1245,11 @@ namespace CryptoNote ++m_spawnCount; m_dispatcher.spawn(std::bind(&node_server::connectionHandler, this, std::cref(connectionId), std::ref(connection))); + } catch (System::InterruptedException&) { + break; + } catch (const std::exception& e) { + logger(WARNING) << "Exception in acceptLoop: " << e.what(); } - } catch (System::InterruptedException&) { - } catch (const std::exception& e) { - logger(WARNING) << "Exception in acceptLoop: " << e.what(); } logger(DEBUGGING) << "acceptLoop finished"; @@ -1301,10 +1307,12 @@ namespace CryptoNote LevinProtocol::Command cmd; for (;;) { - if (ctx.m_state == cryptonote_connection_context::state_sync_required) { ctx.m_state = cryptonote_connection_context::state_synchronizing; m_payload_handler.start_sync(ctx); + } else if (ctx.m_state == cryptonote_connection_context::state_pool_sync_required) { + ctx.m_state = cryptonote_connection_context::state_normal; + m_payload_handler.requestMissingPoolTransactions(ctx); } if (!proto.readCommand(cmd)) { diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index f894606c..cc57c41a 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -184,10 +184,10 @@ namespace CryptoNote network_config m_net_config; uint64_t m_peer_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_net_config) - KV_SERIALIZE(m_peer_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(m_net_config) + KV_MEMBER(m_peer_id) + } }; config m_config; diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 198533b2..84619338 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -23,19 +23,25 @@ #include "cryptonote_config.h" #include "cryptonote_core/cryptonote_stat_info.h" -// epee -#include "serialization/keyvalue_serialization.h" +// new serialization +#include "serialization/ISerializer.h" +#include "serialization/SerializationOverloads.h" +#include "cryptonote_core/cryptonote_serialization.h" namespace CryptoNote { + inline bool serialize(uuid& v, Common::StringView name, ISerializer& s) { + return s.binary(&v, sizeof(v), name); + } + struct network_config { - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(connections_count) - KV_SERIALIZE(handshake_interval) - KV_SERIALIZE(packet_max_size) - KV_SERIALIZE(config_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(connections_count) + KV_MEMBER(handshake_interval) + KV_MEMBER(packet_max_size) + KV_MEMBER(config_id) + } uint32_t connections_count; uint32_t connection_timeout; @@ -46,19 +52,30 @@ namespace CryptoNote uint32_t send_peerlist_sz; }; + enum P2PProtocolVersion : uint8_t { + V0 = 0, + V1 = 1, + CURRENT = V1 + }; + struct basic_node_data { - uuid network_id; + uuid network_id; + uint8_t version; uint64_t local_time; uint32_t my_port; peerid_type peer_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(network_id) - KV_SERIALIZE(peer_id) - KV_SERIALIZE(local_time) - KV_SERIALIZE(my_port) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(network_id) + if (s.type() == ISerializer::INPUT) { + version = 0; + } + KV_MEMBER(version) + KV_MEMBER(peer_id) + KV_MEMBER(local_time) + KV_MEMBER(my_port) + } }; struct CORE_SYNC_DATA @@ -66,10 +83,10 @@ namespace CryptoNote uint64_t current_height; crypto::hash top_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_height) - KV_SERIALIZE_VAL_POD_AS_BLOB(top_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(current_height) + KV_MEMBER(top_id) + } }; #define P2P_COMMANDS_POOL_BASE 1000 @@ -86,10 +103,11 @@ namespace CryptoNote basic_node_data node_data; CORE_SYNC_DATA payload_data; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(node_data) - KV_SERIALIZE(payload_data) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(node_data) + KV_MEMBER(payload_data) + } + }; struct response @@ -98,11 +116,11 @@ namespace CryptoNote CORE_SYNC_DATA payload_data; std::list local_peerlist; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(node_data) - KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(node_data) + KV_MEMBER(payload_data) + serializeAsBinary(local_peerlist, "local_peerlist", s); + } }; }; @@ -117,9 +135,11 @@ namespace CryptoNote struct request { CORE_SYNC_DATA payload_data; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(payload_data) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer& s) { + KV_MEMBER(payload_data) + } + }; struct response @@ -128,11 +148,11 @@ namespace CryptoNote CORE_SYNC_DATA payload_data; std::list local_peerlist; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(local_time) - KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(local_time) + KV_MEMBER(payload_data) + serializeAsBinary(local_peerlist, "local_peerlist", s); + } }; }; @@ -154,9 +174,7 @@ namespace CryptoNote struct request { /*actually we don't need to send any real data*/ - - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) {} }; struct response @@ -164,10 +182,10 @@ namespace CryptoNote std::string status; peerid_type peer_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(peer_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(status) + KV_MEMBER(peer_id) + } }; }; @@ -182,11 +200,11 @@ namespace CryptoNote uint64_t time; crypto::signature sign; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(peer_id) - KV_SERIALIZE(time) - KV_SERIALIZE_VAL_POD_AS_BLOB(sign) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(peer_id) + KV_MEMBER(time) + KV_MEMBER(sign) + } }; inline crypto::hash get_proof_of_trust_hash(const proof_of_trust& pot) { @@ -203,9 +221,10 @@ namespace CryptoNote struct request { proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tr) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer& s) { + KV_MEMBER(tr) + } }; struct response @@ -216,13 +235,13 @@ namespace CryptoNote uint64_t incoming_connections_count; core_stat_info payload_info; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(version) - KV_SERIALIZE(os_version) - KV_SERIALIZE(connections_count) - KV_SERIALIZE(incoming_connections_count) - KV_SERIALIZE(payload_info) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(version) + KV_MEMBER(os_version) + KV_MEMBER(connections_count) + KV_MEMBER(incoming_connections_count) + KV_MEMBER(payload_info) + } }; }; @@ -237,25 +256,27 @@ namespace CryptoNote struct request { proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tr) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer& s) { + KV_MEMBER(tr) + } }; struct response { - std::list local_peerlist_white; - std::list local_peerlist_gray; - std::list connections_list; + std::list local_peerlist_white; + std::list local_peerlist_gray; + std::list connections_list; peerid_type my_id; - uint64_t local_time; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_white) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_gray) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(connections_list) - KV_SERIALIZE(my_id) - KV_SERIALIZE(local_time) - END_KV_SERIALIZE_MAP() + uint64_t local_time; + + void serialize(ISerializer& s) { + serializeAsBinary(local_peerlist_white, "local_peerlist_white", s); + serializeAsBinary(local_peerlist_gray, "local_peerlist_gray", s); + serializeAsBinary(connections_list, "connections_list", s); + KV_MEMBER(my_id) + KV_MEMBER(local_time) + } }; }; @@ -268,17 +289,16 @@ namespace CryptoNote struct request { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) {} }; struct response { peerid_type my_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(my_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(my_id) + } }; }; diff --git a/src/payment_service/ConfigurationManager.cpp b/src/payment_service/ConfigurationManager.cpp index 75ed1ee7..70b169b7 100644 --- a/src/payment_service/ConfigurationManager.cpp +++ b/src/payment_service/ConfigurationManager.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "ConfigurationManager.h" #include diff --git a/src/payment_service/ConfigurationManager.h b/src/payment_service/ConfigurationManager.h index a372a56d..5b3b2c24 100644 --- a/src/payment_service/ConfigurationManager.h +++ b/src/payment_service/ConfigurationManager.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include "cryptonote_core/CoreConfig.h" diff --git a/src/payment_service/JsonRpcMessages.cpp b/src/payment_service/JsonRpcMessages.cpp index 7edac466..ab4b6807 100644 --- a/src/payment_service/JsonRpcMessages.cpp +++ b/src/payment_service/JsonRpcMessages.cpp @@ -15,145 +15,77 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "JsonRpcMessages.h" #include "serialization/SerializationOverloads.h" namespace PaymentService { -namespace { - -void throwIfRequiredParamsMissing(CryptoNote::ISerializer& serializer, const std::vector& names) { - bool r = true; - for (const auto name: names) { - r &= serializer.hasObject(name); - } +void TransferDestination::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(amount, "amount"); + r &= serializer(address, "address"); if (!r) { - throw RequestSerializationError(); + throw std::runtime_error("Required parameter is missing"); } } -void throwIfRequiredParamsMissing(CryptoNote::ISerializer& serializer, const char* name) { - throwIfRequiredParamsMissing(serializer, std::vector{name}); -} +void SendTransactionRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(destinations, "destinations"); + r &= serializer(fee, "fee"); + r &= serializer(mixin, "mixin"); + serializer(unlockTime, "unlock_time"); + serializer(paymentId, "payment_id"); -} - -void TransferDestination::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); - throwIfRequiredParamsMissing(serializer, {"amount", "address"}); - serializer(amount, "amount"); - serializer(address, "address"); - serializer.endObject(); -} - -void SendTransactionRequest::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - throwIfRequiredParamsMissing(serializer, {"destinations", "fee", "mixin"}); - - serializer.beginObject(name); - - size_t size = destinations.size(); - serializer.beginArray(size, "destinations"); - destinations.resize(size); - - auto it = destinations.begin(); - for (size_t i = 0; i < size; ++i, ++it) { - it->serialize(serializer, ""); + if (!r) { + throw std::runtime_error("Required parameter is missing"); } - serializer.endArray(); - - serializer(fee, "fee"); - serializer(mixin, "mixin"); - - if (serializer.hasObject("unlock_time")) { - serializer(unlockTime, "unlock_time"); - } - - if (serializer.hasObject("payment_id")) { - serializer(paymentId, "payment_id"); - } - - serializer.endObject(); } -void SendTransactionResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void SendTransactionResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(transactionId, "transaction_id"); - serializer.endObject(); } -void GetAddressResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetAddressResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(address, "address"); - serializer.endObject(); } -void GetActualBalanceResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetActualBalanceResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(actualBalance, "actual_balance"); - serializer.endObject(); } -void GetPendingBalanceResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetPendingBalanceResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(pendingBalance, "pending_balance"); - serializer.endObject(); } -void GetTransactionsCountResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetTransactionsCountResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(transactionsCount, "transactions_count"); - serializer.endObject(); } -void GetTransfersCountResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetTransfersCountResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(transfersCount, "transfers_count"); - serializer.endObject(); } -void GetTransactionIdByTransferIdRequest::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - throwIfRequiredParamsMissing(serializer, "transfer_id"); +void GetTransactionIdByTransferIdRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(transferId, "transfer_id"); - serializer.beginObject(name); - serializer(transferId, "transfer_id"); - serializer.endObject(); + if (!r) { + throw std::runtime_error("Required parameter is missing"); + } } -void GetTransactionIdByTransferIdResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetTransactionIdByTransferIdResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(transactionid, "transaction_id"); - serializer.endObject(); } -void GetTransactionRequest::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - throwIfRequiredParamsMissing(serializer, "transaction_id"); +void GetTransactionRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(transactionId, "transaction_id"); - serializer.beginObject(name); - serializer(transactionId, "transaction_id"); - serializer.endObject(); + if (!r) { + throw std::runtime_error("Required parameter is missing"); + } } -void TransactionRpcInfo::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); - +void TransactionRpcInfo::serialize(CryptoNote::ISerializer& serializer) { serializer(firstTransferId, "first_transfer_id"); serializer(transferCount, "transfer_count"); serializer(totalAmount, "total_amount"); @@ -163,86 +95,71 @@ void TransactionRpcInfo::serialize(CryptoNote::ISerializer& serializer, const st serializer(blockHeight, "block_height"); serializer(timestamp, "timestamp"); serializer(extra, "extra"); - - serializer.endObject(); } -void GetTransactionResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); - +void GetTransactionResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(found, "found"); if (!found) { - serializer.endObject(); - return; + serializer(transactionInfo, "transaction_info"); } - - transactionInfo.serialize(serializer, "transaction_info"); - - serializer.endObject(); } -void TransferRpcInfo::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void ListTransactionsRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(startingTransactionId, "starting_transaction_id"); + r &= serializer(maxTransactionCount, "max_transaction_count"); + + if (!r) { + throw std::runtime_error("Required parameter is missing"); + } +} + +void ListTransactionsResponse::serialize(CryptoNote::ISerializer& serializer) { + serializer(transactions, "transactions"); +} + +void TransferRpcInfo::serialize(CryptoNote::ISerializer& serializer) { serializer(address, "address"); serializer(amount, "amount"); - serializer.endObject(); } -void GetTransferRequest::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - throwIfRequiredParamsMissing(serializer, "transfer_id"); +void GetTransferRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(transferId, "transfer_id"); - serializer.beginObject(name); - serializer(transferId, "transfer_id"); - serializer.endObject(); -} - -void GetTransferResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); - serializer(found, "found"); - - if (!found) { - serializer.endObject(); - return; + if (!r) { + throw std::runtime_error("Required parameter is missing"); } - - transferInfo.serialize(serializer, "transfer_info"); - - serializer.endObject(); } -void GetIncomingPaymentsRequest::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - throwIfRequiredParamsMissing(serializer, "payments"); - - serializer.beginObject(name); - serializer(payments, "payments"); - serializer.endObject(); +void GetTransferResponse::serialize(CryptoNote::ISerializer& serializer) { + serializer(found, "found"); + if (found) { + serializer(transferInfo, "transfer_info"); + } } -void PaymentsById::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void GetIncomingPaymentsRequest::serialize(CryptoNote::ISerializer& serializer) { + bool r = serializer(payments, "payments"); + if (!r) { + throw std::runtime_error("Required parameter is missing"); + } +} + +void PaymentsById::serialize(CryptoNote::ISerializer& serializer) { serializer(id, "id"); serializer(payments, "payments"); - - serializer.endObject(); } -void GetIncomingPaymentsResponse::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); - +void GetIncomingPaymentsResponse::serialize(CryptoNote::ISerializer& serializer) { serializer(payments, "payments"); - - serializer.endObject(); } -void PaymentDetails::serialize(CryptoNote::ISerializer& serializer, const std::string& name) { - serializer.beginObject(name); +void PaymentDetails::serialize(CryptoNote::ISerializer& serializer) { serializer(txHash, "tx_hash"); serializer(amount, "amount"); serializer(blockHeight, "block_height"); serializer(unlockTime, "unlock_time"); - serializer.endObject(); } } diff --git a/src/payment_service/JsonRpcMessages.h b/src/payment_service/JsonRpcMessages.h index 098e75cc..c3862b18 100644 --- a/src/payment_service/JsonRpcMessages.h +++ b/src/payment_service/JsonRpcMessages.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include "serialization/ISerializer.h" @@ -49,7 +32,7 @@ struct TransferDestination { uint64_t amount; std::string address; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct SendTransactionRequest { @@ -60,59 +43,59 @@ struct SendTransactionRequest { uint64_t unlockTime; std::string paymentId; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct SendTransactionResponse { uint64_t transactionId; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetAddressResponse { std::string address; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetActualBalanceResponse { uint64_t actualBalance; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetPendingBalanceResponse { uint64_t pendingBalance; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransactionsCountResponse { uint64_t transactionsCount; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransfersCountResponse { uint64_t transfersCount; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransactionIdByTransferIdRequest { uint64_t transferId; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransactionIdByTransferIdResponse { uint64_t transactionid; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransactionRequest { uint64_t transactionId; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct TransactionRpcInfo { @@ -126,40 +109,53 @@ struct TransactionRpcInfo { uint64_t timestamp; std::string extra; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransactionResponse { bool found; TransactionRpcInfo transactionInfo; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); +}; + +struct ListTransactionsRequest { + uint32_t startingTransactionId; + uint32_t maxTransactionCount; + + void serialize(CryptoNote::ISerializer& serializer); +}; + +struct ListTransactionsResponse { + std::vector transactions; + + void serialize(CryptoNote::ISerializer& serializer); }; struct TransferRpcInfo { std::string address; int64_t amount; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransferRequest { uint64_t transferId; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetTransferResponse { bool found; TransferRpcInfo transferInfo; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetIncomingPaymentsRequest { std::vector payments; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct PaymentDetails @@ -169,20 +165,20 @@ struct PaymentDetails uint64_t blockHeight; uint64_t unlockTime; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct PaymentsById { std::string id; std::vector payments; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; struct GetIncomingPaymentsResponse { std::vector payments; - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + void serialize(CryptoNote::ISerializer& serializer); }; } //namespace PaymentService diff --git a/src/payment_service/JsonRpcServer.cpp b/src/payment_service/JsonRpcServer.cpp index fbd604f5..83cc9deb 100644 --- a/src/payment_service/JsonRpcServer.cpp +++ b/src/payment_service/JsonRpcServer.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "JsonRpcServer.h" #include @@ -59,65 +42,21 @@ namespace PaymentService { JsonRpcServer::JsonRpcServer(System::Dispatcher& sys, System::Event& stopEvent, WalletService& service, Logging::ILogger& loggerGroup) : - system(sys), - stopEvent(stopEvent), - service(service), - logger(loggerGroup, "JsonRpcServer") + HttpServer(sys, loggerGroup), + system(sys), + stopEvent(stopEvent), + service(service), + logger(loggerGroup, "JsonRpcServer") { } void JsonRpcServer::start(const Configuration& config) { - logger(Logging::INFO) << "Starting server on " << config.bindAddress << ":" << config.bindPort; - - try { - System::TcpListener listener(system, System::Ipv4Address(config.bindAddress), config.bindPort); - system.spawn([this, &listener] () {this->stopEvent.wait(); listener.stop(); }); - for (;;) { - System::TcpConnection connection = listener.accept(); - system.spawn(std::bind(&JsonRpcServer::sessionProcedure, this, new System::TcpConnection(std::move(connection)))); - } - } catch (System::InterruptedException&) { - logger(Logging::DEBUGGING) << "Server is stopped"; - } catch (std::exception& ex) { - logger(Logging::FATAL) << ex.what(); - } + HttpServer::start(config.bindAddress, config.bindPort); + stopEvent.wait(); + HttpServer::stop(); } -void JsonRpcServer::sessionProcedure(System::TcpConnection* tcpConnection) { - logger(Logging::DEBUGGING) << "new connection has been accepted"; - std::unique_ptr connection(tcpConnection); - - System::TcpStreambuf streambuf(*connection); - std::iostream stream(&streambuf); - - CryptoNote::HttpParser parser; - - try { - for (;;) { - CryptoNote::HttpRequest req; - CryptoNote::HttpResponse resp; - - parser.receiveRequest(stream, req); - processHttpRequest(req, resp); - - stream << resp; - stream.flush(); - } - } catch (std::system_error& e) { - //todo: write error conditions - if (e.code().category() == CryptoNote::error::HttpParserErrorCategory::INSTANCE) { - if (e.code().value() == CryptoNote::error::END_OF_STREAM) { - logger(Logging::DEBUGGING) << "The client is disconnected"; - return; - } - } - logger(Logging::WARNING) << e.code().message(); - } catch (std::exception& e) { - logger(Logging::WARNING) << e.what(); - } -} - -void JsonRpcServer::processHttpRequest(const CryptoNote::HttpRequest& req, CryptoNote::HttpResponse& resp) { +void JsonRpcServer::processRequest(const CryptoNote::HttpRequest& req, CryptoNote::HttpResponse& resp) { try { logger(Logging::TRACE) << "HTTP request came: \n" << req; @@ -161,18 +100,16 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: std::string method = req("method").getString(); - CryptoNote::JsonInputValueSerializer inputSerializer; + CryptoNote::JsonInputValueSerializer inputSerializer(req("params")); CryptoNote::JsonOutputStreamSerializer outputSerializer; - inputSerializer.setJsonValue(&req("params")); - if (method == "send_transaction") { SendTransactionRequest sendReq; SendTransactionResponse sendResp; //XXX: refactor it when migrate to different exception types in different subsystems! try { - sendReq.serialize(inputSerializer, ""); + serialize(sendReq, inputSerializer); } catch (std::exception&) { makeGenericErrorReponse(resp, "Invalid Request", -32600); return; @@ -184,7 +121,7 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - sendResp.serialize(outputSerializer, ""); + serialize(sendResp, outputSerializer); } else if (method == "get_address") { GetAddressResponse getAddrResp; @@ -194,7 +131,7 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - getAddrResp.serialize(outputSerializer, ""); + serialize(getAddrResp, outputSerializer); } else if (method == "get_actual_balance") { GetActualBalanceResponse actualResp; @@ -204,7 +141,7 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - actualResp.serialize(outputSerializer, ""); + serialize(actualResp, outputSerializer); } else if (method == "get_pending_balance") { GetPendingBalanceResponse pendingResp; @@ -214,7 +151,7 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - pendingResp.serialize(outputSerializer, ""); + serialize(pendingResp, outputSerializer); } else if (method == "get_transactions_count") { GetTransactionsCountResponse txResp; @@ -224,7 +161,7 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - txResp.serialize(outputSerializer, ""); + serialize(txResp, outputSerializer); } else if (method == "get_transfers_count") { GetTransfersCountResponse trResp; @@ -234,14 +171,14 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - trResp.serialize(outputSerializer, ""); + serialize(trResp, outputSerializer); } else if (method == "get_transaction_id_by_transfer_id") { GetTransactionIdByTransferIdRequest getReq; GetTransactionIdByTransferIdResponse getResp; //XXX: refactor it when migrate to different exception types in different subsystems! try { - getReq.serialize(inputSerializer, ""); + serialize(getReq, inputSerializer); } catch (std::exception&) { makeGenericErrorReponse(resp, "Invalid Request", -32600); return; @@ -255,14 +192,14 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - getResp.serialize(outputSerializer, ""); + serialize(getResp, outputSerializer); } else if (method == "get_transaction") { GetTransactionRequest getReq; GetTransactionResponse getResp; //XXX: refactor it when migrate to different exception types in different subsystems! try { - getReq.serialize(inputSerializer, ""); + serialize(getReq, inputSerializer); } catch (std::exception&) { makeGenericErrorReponse(resp, "Invalid Request", -32600); return; @@ -274,14 +211,34 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - getResp.serialize(outputSerializer, ""); + serialize(getResp, outputSerializer); + } else if (method == "list_transactions") { + ListTransactionsRequest listReq; + ListTransactionsResponse listResp; + + //XXX: refactor it when migrate to different exception types in different subsystems! + try { + serialize(listReq, inputSerializer); + } catch (std::exception&) { + makeGenericErrorReponse(resp, "Invalid Request", -32600); + return; + } + + std::error_code ec = service.listTransactions(static_cast(listReq.startingTransactionId), + listReq.maxTransactionCount, listResp.transactions); + if (ec) { + makeErrorResponse(ec, resp); + return; + } + + serialize(listResp, outputSerializer); } else if (method == "get_transfer") { GetTransferRequest getReq; GetTransferResponse getResp; //XXX: refactor it when migrate to different exception types in different subsystems! try { - getReq.serialize(inputSerializer, ""); + serialize(getReq, inputSerializer); } catch (std::exception&) { makeGenericErrorReponse(resp, "Invalid Request", -32600); return; @@ -293,14 +250,14 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: return; } - getResp.serialize(outputSerializer, ""); + serialize(getResp, outputSerializer); } else if (method == "get_incoming_payments") { GetIncomingPaymentsRequest getReq; GetIncomingPaymentsResponse getResp; //XXX: refactor it when migrate to different exception types in different subsystems! try { - getReq.serialize(inputSerializer, ""); + serialize(getReq, inputSerializer); } catch (std::exception&) { makeGenericErrorReponse(resp, "Invalid Request", -32600); return; @@ -326,15 +283,14 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: getResp.payments.push_back(std::move(pbid)); } - getResp.serialize(outputSerializer, ""); + serialize(getResp, outputSerializer); } else { logger(Logging::DEBUGGING) << "Requested method not found: " << method; makeMethodNotFoundResponse(resp); return; } - Common::JsonValue v = outputSerializer.getJsonValue(); - fillJsonResponse(v, resp); + fillJsonResponse(outputSerializer.getValue(), resp); } catch (RequestSerializationError&) { logger(Logging::WARNING) << "Wrong request came"; @@ -348,15 +304,11 @@ void JsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common:: void JsonRpcServer::prepareJsonResponse(const Common::JsonValue& req, Common::JsonValue& resp) { using Common::JsonValue; - if (req.count("id")) { - JsonValue id = req("id"); - resp.insert("id", id); + if (req.contains("id")) { + resp.insert("id", req("id")); } - - JsonValue jsonRpc; - jsonRpc = "2.0"; - - resp.insert("jsonrpc", jsonRpc); + + resp.insert("jsonrpc", "2.0"); } void JsonRpcServer::makeErrorResponse(const std::error_code& ec, Common::JsonValue& resp) { diff --git a/src/payment_service/JsonRpcServer.h b/src/payment_service/JsonRpcServer.h index 63a66117..feb133e9 100644 --- a/src/payment_service/JsonRpcServer.h +++ b/src/payment_service/JsonRpcServer.h @@ -15,32 +15,18 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once -#include "PaymentServiceConfiguration.h" +#include + #include #include #include "Logging/ILogger.h" #include "Logging/LoggerRef.h" +#include "rpc/HttpServer.h" + +#include "PaymentServiceConfiguration.h" -#include namespace CryptoNote { class HttpResponse; @@ -59,7 +45,7 @@ namespace PaymentService { class WalletService; -class JsonRpcServer { +class JsonRpcServer : CryptoNote::HttpServer { public: JsonRpcServer(System::Dispatcher& sys, System::Event& stopEvent, WalletService& service, Logging::ILogger& loggerGroup); JsonRpcServer(const JsonRpcServer&) = delete; @@ -69,7 +55,9 @@ public: private: void sessionProcedure(System::TcpConnection* tcpConnection); - void processHttpRequest(const CryptoNote::HttpRequest& req, CryptoNote::HttpResponse& resp); + // HttpServer + virtual void processRequest(const CryptoNote::HttpRequest& request, CryptoNote::HttpResponse& response) override; + void processJsonRpcRequest(const Common::JsonValue& req, Common::JsonValue& resp); void prepareJsonResponse(const Common::JsonValue& req, Common::JsonValue& resp); diff --git a/src/payment_service/NodeFactory.cpp b/src/payment_service/NodeFactory.cpp index a7e86b72..7c468c7f 100644 --- a/src/payment_service/NodeFactory.cpp +++ b/src/payment_service/NodeFactory.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "NodeFactory.h" #include "node_rpc_proxy/NodeRpcProxy.h" @@ -58,16 +41,36 @@ public: virtual void relayTransaction(const CryptoNote::Transaction& transaction, const Callback& callback) { callback(std::error_code()); } virtual void getRandomOutsByAmounts(std::vector&& amounts, uint64_t outsCount, - std::vector& result, const Callback& callback) { callback(std::error_code()); } - virtual void getNewBlocks(std::list&& knownBlockIds, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) { callback(std::error_code()); } - virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) { callback(std::error_code()); } + std::vector& result, const Callback& callback) { } + virtual void getNewBlocks(std::list&& knownBlockIds, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) { + startHeight = 0; + callback(std::error_code()); + } + virtual void getTransactionOutsGlobalIndices(const crypto::hash& transactionHash, std::vector& outsGlobalIndices, const Callback& callback) { } virtual void queryBlocks(std::list&& knownBlockIds, uint64_t timestamp, std::list& newBlocks, - uint64_t& startHeight, const CryptoNote::INode::Callback& callback) { startHeight = 0; callback(std::error_code()); } + uint64_t& startHeight, const CryptoNote::INode::Callback& callback) { + startHeight = 0; + callback(std::error_code()); + } virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, - const Callback& callback) { callback(std::error_code()); } + const Callback& callback) { + is_bc_actual = true; + callback(std::error_code()); + } + + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, + const Callback& callback) override { } + + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, + const Callback& callback) override { } + + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, + const Callback& callback) override { } + + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override { } }; diff --git a/src/payment_service/NodeFactory.h b/src/payment_service/NodeFactory.h index fb50c3ff..09de8b40 100644 --- a/src/payment_service/NodeFactory.h +++ b/src/payment_service/NodeFactory.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include "INode.h" diff --git a/src/payment_service/PaymentServiceConfiguration.cpp b/src/payment_service/PaymentServiceConfiguration.cpp index 71d51f1b..f749750b 100644 --- a/src/payment_service/PaymentServiceConfiguration.cpp +++ b/src/payment_service/PaymentServiceConfiguration.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "PaymentServiceConfiguration.h" #include diff --git a/src/payment_service/PaymentServiceConfiguration.h b/src/payment_service/PaymentServiceConfiguration.h index eda15e7e..42316518 100644 --- a/src/payment_service/PaymentServiceConfiguration.h +++ b/src/payment_service/PaymentServiceConfiguration.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include diff --git a/src/payment_service/RpcNodeConfiguration.cpp b/src/payment_service/RpcNodeConfiguration.cpp index 98e5d9a6..a0a7a04d 100644 --- a/src/payment_service/RpcNodeConfiguration.cpp +++ b/src/payment_service/RpcNodeConfiguration.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "RpcNodeConfiguration.h" namespace PaymentService { diff --git a/src/payment_service/RpcNodeConfiguration.h b/src/payment_service/RpcNodeConfiguration.h index 02fd6fba..82cc298f 100644 --- a/src/payment_service/RpcNodeConfiguration.h +++ b/src/payment_service/RpcNodeConfiguration.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include diff --git a/src/payment_service/WalletFactory.cpp b/src/payment_service/WalletFactory.cpp index 9b6d660a..590960fa 100644 --- a/src/payment_service/WalletFactory.cpp +++ b/src/payment_service/WalletFactory.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "WalletFactory.h" #include "node_rpc_proxy/NodeRpcProxy.h" diff --git a/src/payment_service/WalletFactory.h b/src/payment_service/WalletFactory.h index 850c12db..9df4b19e 100644 --- a/src/payment_service/WalletFactory.h +++ b/src/payment_service/WalletFactory.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include "IWallet.h" diff --git a/src/payment_service/WalletObservers.cpp b/src/payment_service/WalletObservers.cpp index b9a62d54..db008960 100644 --- a/src/payment_service/WalletObservers.cpp +++ b/src/payment_service/WalletObservers.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "WalletObservers.h" #include diff --git a/src/payment_service/WalletObservers.h b/src/payment_service/WalletObservers.h index d083d3e7..e4447722 100644 --- a/src/payment_service/WalletObservers.h +++ b/src/payment_service/WalletObservers.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include "IWallet.h" diff --git a/src/payment_service/WalletService.cpp b/src/payment_service/WalletService.cpp index fdef45ab..0d7b0de0 100644 --- a/src/payment_service/WalletService.cpp +++ b/src/payment_service/WalletService.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "WalletService.h" #include "WalletServiceErrorCodes.h" @@ -50,6 +33,9 @@ #include #ifdef WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif #include #else #include @@ -458,6 +444,40 @@ void WalletService::fillTransactionRpcInfo(const CryptoNote::TransactionInfo& tx rpcInfo.hash = Common::podToHex(txInfo.hash); } +std::error_code WalletService::listTransactions(CryptoNote::TransactionId startingTxId, uint32_t maxTxCount, std::vector& txsRpcInfo) { + logger(Logging::DEBUGGING) << "listTransactions request came"; + + if (maxTxCount == 0) { + txsRpcInfo.clear(); + return std::error_code(); + } + + try { + CryptoNote::TransactionId endTxId; + if (startingTxId > std::numeric_limits::max() - static_cast(maxTxCount)) { + endTxId = static_cast(wallet->getTransactionCount()); + } else { + endTxId = startingTxId + static_cast(maxTxCount); + endTxId = std::min(endTxId, static_cast(wallet->getTransactionCount())); + } + + txsRpcInfo.resize(endTxId - startingTxId); + + for (auto txId = startingTxId; txId < endTxId; ++txId) { + CryptoNote::TransactionInfo txInfo; + assert(txId < wallet->getTransactionCount()); + wallet->getTransaction(txId, txInfo); + + fillTransactionRpcInfo(txInfo, txsRpcInfo[txId - startingTxId]); + } + } catch (std::system_error& x) { + logger(Logging::WARNING) << "Unable to list transaction: " << x.what(); + return x.code(); + } + + return std::error_code(); +} + std::error_code WalletService::getTransfer(CryptoNote::TransferId txId, bool& found, TransferRpcInfo& rpcInfo) { logger(Logging::DEBUGGING) << "getTransfer request came"; diff --git a/src/payment_service/WalletService.h b/src/payment_service/WalletService.h index b88dbf47..d70175f6 100644 --- a/src/payment_service/WalletService.h +++ b/src/payment_service/WalletService.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include @@ -80,6 +63,7 @@ public: std::error_code getTransfersCount(uint64_t& trCount); std::error_code getTransactionByTransferId(CryptoNote::TransferId transfer, CryptoNote::TransactionId& transaction); std::error_code getTransaction(CryptoNote::TransactionId txId, bool& found, TransactionRpcInfo& rpcInfo); + std::error_code listTransactions(CryptoNote::TransactionId startingTxId, uint32_t maxTxCount, std::vector& txsRpcInfo); std::error_code getTransfer(CryptoNote::TransferId txId, bool& found, TransferRpcInfo& rpcInfo); private: diff --git a/src/payment_service/WalletServiceErrorCodes.cpp b/src/payment_service/WalletServiceErrorCodes.cpp index 2ca1ff41..61ef02f1 100644 --- a/src/payment_service/WalletServiceErrorCodes.cpp +++ b/src/payment_service/WalletServiceErrorCodes.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "WalletServiceErrorCodes.h" namespace PaymentService { diff --git a/src/payment_service/WalletServiceErrorCodes.h b/src/payment_service/WalletServiceErrorCodes.h index f8e7456c..ba2dcbbe 100644 --- a/src/payment_service/WalletServiceErrorCodes.h +++ b/src/payment_service/WalletServiceErrorCodes.h @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once #include diff --git a/src/payment_service/main.cpp b/src/payment_service/main.cpp index 8182e94a..d4e5805d 100644 --- a/src/payment_service/main.cpp +++ b/src/payment_service/main.cpp @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include #include #include @@ -52,6 +35,9 @@ #include #ifdef WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif #include #include #else @@ -73,13 +59,19 @@ #define SERVICE_NAME "Payment Gate" -PaymentService::ConfigurationManager config; -System::Dispatcher systemService; -System::Event stopEvent(systemService); -PaymentService::WalletService* service; -std::unique_ptr currencyBuilder; -Logging::LoggerGroup logger; -CryptoNote::node_server * gP2pNode = nullptr; +struct PaymentGate { + PaymentGate() : dispatcher(nullptr), stopEvent(nullptr), config(), service(nullptr), logger(), currencyBuilder(logger) { + } + + System::Dispatcher* dispatcher; + System::Event* stopEvent; + PaymentService::ConfigurationManager config; + PaymentService::WalletService* service; + Logging::LoggerGroup logger; + CryptoNote::CurrencyBuilder currencyBuilder; +}; + +PaymentGate* ppg; #ifdef WIN32 SERVICE_STATUS_HANDLE serviceStatusHandle; @@ -88,23 +80,20 @@ SERVICE_STATUS_HANDLE serviceStatusHandle; void run(); void stopSignalHandler() { - Logging::LoggerRef log(logger, "StopSignalHandler"); + Logging::LoggerRef log(ppg->logger, "StopSignalHandler"); log(Logging::INFO) << "Stop signal caught"; try { - if (service) { - service->saveWallet(); + if (ppg->service) { + ppg->service->saveWallet(); } } catch (std::exception& ex) { log(Logging::WARNING) << "Couldn't save wallet: " << ex.what(); } - - if (gP2pNode != nullptr) { - gP2pNode->send_stop_signal(); - } else { - stopEvent.set(); - } + ppg->dispatcher->remoteSpawn([&]() { + ppg->stopEvent->set(); + }); } #ifdef WIN32 @@ -123,28 +112,34 @@ std::string GetLastErrorMessage(DWORD errorMessageID) void __stdcall serviceHandler(DWORD fdwControl) { if (fdwControl == SERVICE_CONTROL_STOP) { - Logging::LoggerRef log(logger, "serviceHandler"); + Logging::LoggerRef log(ppg->logger, "serviceHandler"); log(Logging::INFO) << "Stop signal caught"; SERVICE_STATUS serviceStatus{ SERVICE_WIN32_OWN_PROCESS, SERVICE_STOP_PENDING, 0, NO_ERROR, 0, 0, 0 }; SetServiceStatus(serviceStatusHandle, &serviceStatus); try { - if (service) { + if (ppg->service) { log(Logging::INFO) << "Saving wallet"; - service->saveWallet(); + ppg->service->saveWallet(); } } catch (std::exception& ex) { log(Logging::WARNING) << "Couldn't save wallet: " << ex.what(); } log(Logging::INFO) << "Stopping service"; - stopEvent.set(); + ppg->dispatcher->remoteSpawn([&]() { + ppg->stopEvent->set(); + }); } } void __stdcall serviceMain(DWORD dwArgc, char **lpszArgv) { - Logging::LoggerRef logRef(logger, "WindowsService"); + System::Dispatcher dispatcher; + System::Event stopEvent(dispatcher); + ppg->dispatcher = &dispatcher; + ppg->stopEvent = &stopEvent; + Logging::LoggerRef logRef(ppg->logger, "WindowsService"); serviceStatusHandle = RegisterServiceCtrlHandler("PaymentGate", serviceHandler); if (serviceStatusHandle == NULL) { @@ -209,7 +204,7 @@ int runDaemon() { #ifdef WIN32 SERVICE_TABLE_ENTRY serviceTable[] { - { "PaymentGate", serviceMain }, + { "Payment Gate", serviceMain }, { NULL, NULL } }; @@ -230,6 +225,10 @@ int runDaemon() { return 1; } + System::Dispatcher dispatcher; + System::Event stopEvent(dispatcher); + ppg->dispatcher = &dispatcher; + ppg->stopEvent = &stopEvent; run(); return 0; @@ -238,7 +237,7 @@ int runDaemon() { int registerService() { #ifdef WIN32 - Logging::LoggerRef logRef(logger, "ServiceRegistrator"); + Logging::LoggerRef logRef(ppg->logger, "ServiceRegistrator"); char pathBuff[MAX_PATH]; std::string modulePath; @@ -295,7 +294,7 @@ int registerService() { int unregisterService() { #ifdef WIN32 - Logging::LoggerRef logRef(logger, "ServiceDeregistrator"); + Logging::LoggerRef logRef(ppg->logger, "ServiceDeregistrator"); SC_HANDLE scManager = NULL; SC_HANDLE scService = NULL; @@ -376,28 +375,27 @@ void changeDirectory(const std::string& path) { } void runInProcess() { - Logging::LoggerRef(logger, "run")(Logging::INFO) << "Starting Payment Gate with local node"; + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "Starting Payment Gate with local node"; - CryptoNote::Currency currency = currencyBuilder->currency(); - CryptoNote::core core(currency, NULL, logger); + CryptoNote::Currency currency = ppg->currencyBuilder.currency(); + CryptoNote::core core(currency, NULL, ppg->logger); - CryptoNote::cryptonote_protocol_handler protocol(currency, systemService, core, NULL, logger); - CryptoNote::node_server p2pNode(systemService, protocol, logger); - gP2pNode = &p2pNode; + CryptoNote::cryptonote_protocol_handler protocol(currency, *ppg->dispatcher, core, NULL, ppg->logger); + CryptoNote::node_server p2pNode(*ppg->dispatcher, protocol, ppg->logger); protocol.set_p2p_endpoint(&p2pNode); core.set_cryptonote_protocol(&protocol); std::unique_ptr node; - Logging::LoggerRef(logger, "run")(Logging::INFO) << "initializing p2pNode"; - if (!p2pNode.init(config.netNodeConfig, config.gateConfiguration.testnet)) { + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "initializing p2pNode"; + if (!p2pNode.init(ppg->config.netNodeConfig, ppg->config.gateConfiguration.testnet)) { throw std::runtime_error("Failed to init p2pNode"); } - Logging::LoggerRef(logger, "run")(Logging::INFO) << "initializing core"; + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "initializing core"; CryptoNote::MinerConfig emptyMiner; - core.init(config.coreConfig, emptyMiner, true); + core.init(ppg->config.coreConfig, emptyMiner, true); std::promise initPromise; auto initFuture = initPromise.get_future(); @@ -405,9 +403,9 @@ void runInProcess() { node.reset(new CryptoNote::InProcessNode(core, protocol)); node->init([&initPromise](std::error_code ec) { if (ec) { - Logging::LoggerRef(logger, "run")(Logging::INFO) << "Failed to init node: " << ec.message(); + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "Failed to init node: " << ec.message(); } else { - Logging::LoggerRef(logger, "run")(Logging::INFO) << "node is inited successfully"; + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "node is inited successfully"; } initPromise.set_value(ec); @@ -418,56 +416,57 @@ void runInProcess() { throw std::system_error(ec); } - Logging::LoggerRef(logger, "run")(Logging::INFO) << "Starting p2p server"; + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "Spawning p2p server"; - System::Event p2pStarted(systemService); + System::Event p2pStopped(*ppg->dispatcher); + System::Event p2pStarted(*ppg->dispatcher); - systemService.spawn([&]() { + ppg->dispatcher->spawn([&]() { p2pStarted.set(); p2pNode.run(); - stopEvent.set(); + p2pStopped.set(); }); - + p2pStarted.wait(); - Logging::LoggerRef(logger, "run")(Logging::INFO) << "p2p server is started"; + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "p2p server is started"; - service = new PaymentService::WalletService(currency, systemService, *node, config.gateConfiguration, logger); - std::unique_ptr serviceGuard(service); + ppg->service = new PaymentService::WalletService(currency, *ppg->dispatcher, *node, ppg->config.gateConfiguration, ppg->logger); + std::unique_ptr serviceGuard(ppg->service); - service->init(); + ppg->service->init(); - PaymentService::JsonRpcServer rpcServer(systemService, stopEvent, *service, logger); - - rpcServer.start(config.gateConfiguration); + PaymentService::JsonRpcServer rpcServer(*ppg->dispatcher, *ppg->stopEvent, *ppg->service, ppg->logger); + rpcServer.start(ppg->config.gateConfiguration); serviceGuard.reset(); + p2pNode.send_stop_signal(); + p2pStopped.wait(); node->shutdown(); core.deinit(); p2pNode.deinit(); - gP2pNode = nullptr; } void runRpcProxy() { - Logging::LoggerRef(logger, "run")(Logging::INFO) << "Starting Payment Gate with remote node"; - CryptoNote::Currency currency = currencyBuilder->currency(); + Logging::LoggerRef(ppg->logger, "run")(Logging::INFO) << "Starting Payment Gate with remote node"; + CryptoNote::Currency currency = ppg->currencyBuilder.currency(); std::unique_ptr node; - node.reset(PaymentService::NodeFactory::createNode(config.remoteNodeConfig.daemonHost, config.remoteNodeConfig.daemonPort)); + node.reset(PaymentService::NodeFactory::createNode(ppg->config.remoteNodeConfig.daemonHost, ppg->config.remoteNodeConfig.daemonPort)); - service = new PaymentService::WalletService(currency, systemService, *node, config.gateConfiguration, logger); - std::unique_ptr serviceGuard(service); + ppg->service = new PaymentService::WalletService(currency, *ppg->dispatcher, *node, ppg->config.gateConfiguration, ppg->logger); + std::unique_ptr serviceGuard(ppg->service); - service->init(); + ppg->service->init(); - PaymentService::JsonRpcServer rpcServer(systemService, stopEvent, *service, logger); + PaymentService::JsonRpcServer rpcServer(*ppg->dispatcher, *ppg->stopEvent, *ppg->service, ppg->logger); - rpcServer.start(config.gateConfiguration); + rpcServer.start(ppg->config.gateConfiguration); } void run() { tools::SignalHandler::install(stopSignalHandler); - if (config.startInprocess) { + if (ppg->config.startInprocess) { runInProcess(); } else { runRpcProxy(); @@ -475,62 +474,66 @@ void run() { } int main(int argc, char** argv) { + PaymentGate pg; + ppg = &pg; try { - if (!config.init(argc, argv)) { + if (!pg.config.init(argc, argv)) { return 0; //help message requested or so } - Logging::ConsoleLogger consoleLogger(static_cast(config.gateConfiguration.logLevel)); - logger.addLogger(consoleLogger); + Logging::ConsoleLogger consoleLogger(static_cast(pg.config.gateConfiguration.logLevel)); + pg.logger.addLogger(consoleLogger); - currencyBuilder.reset(new CryptoNote::CurrencyBuilder(logger)); + Logging::LoggerRef(pg.logger, "main")(Logging::INFO) << "PaymentService " << " v" << PROJECT_VERSION_LONG; - Logging::LoggerRef(logger, "main")(Logging::INFO) << "PaymentService " << " v" << PROJECT_VERSION_LONG; - - if (config.gateConfiguration.testnet) { - Logging::LoggerRef(logger, "main")(Logging::INFO) << "Starting in testnet mode"; - currencyBuilder->testnet(true); + if (pg.config.gateConfiguration.testnet) { + Logging::LoggerRef(pg.logger, "main")(Logging::INFO) << "Starting in testnet mode"; + pg.currencyBuilder.testnet(true); } - if (!config.gateConfiguration.serverRoot.empty()) { - changeDirectory(config.gateConfiguration.serverRoot); - Logging::LoggerRef(logger, "main")(Logging::INFO) << "Current working directory now is " << config.gateConfiguration.serverRoot; + if (!pg.config.gateConfiguration.serverRoot.empty()) { + changeDirectory(pg.config.gateConfiguration.serverRoot); + Logging::LoggerRef(pg.logger, "main")(Logging::INFO) << "Current working directory now is " << pg.config.gateConfiguration.serverRoot; } - std::ofstream fileStream(config.gateConfiguration.logFile, std::ofstream::app); + std::ofstream fileStream(pg.config.gateConfiguration.logFile, std::ofstream::app); if (!fileStream) { throw std::runtime_error("Couldn't open log file"); } - Logging::StreamLogger fileLogger(fileStream, static_cast(config.gateConfiguration.logLevel)); - logger.addLogger(fileLogger); + Logging::StreamLogger fileLogger(fileStream, static_cast(pg.config.gateConfiguration.logLevel)); + pg.logger.addLogger(fileLogger); - if (config.gateConfiguration.generateNewWallet) { - CryptoNote::Currency currency = currencyBuilder->currency(); - generateNewWallet(currency, config.gateConfiguration, logger); + if (pg.config.gateConfiguration.generateNewWallet) { + CryptoNote::Currency currency = pg.currencyBuilder.currency(); + generateNewWallet(currency, pg.config.gateConfiguration, pg.logger); return 0; } - if (!config.gateConfiguration.importKeys.empty()) { - importLegacyKeys(config.gateConfiguration); - Logging::LoggerRef(logger, "KeysImporter")(Logging::INFO) << "Keys have been imported successfully"; + if (!pg.config.gateConfiguration.importKeys.empty()) { + importLegacyKeys(pg.config.gateConfiguration); + Logging::LoggerRef(pg.logger, "KeysImporter")(Logging::INFO) << "Keys have been imported successfully"; return 0; } - if (config.gateConfiguration.registerService) { + if (pg.config.gateConfiguration.registerService) { return registerService(); } - if (config.gateConfiguration.unregisterService) { + if (pg.config.gateConfiguration.unregisterService) { return unregisterService(); } - if (config.gateConfiguration.daemonize) { - logger.removeLogger(consoleLogger); + if (pg.config.gateConfiguration.daemonize) { + pg.logger.removeLogger(consoleLogger); if (runDaemon() != 0) { throw std::runtime_error("Failed to start daemon"); } } else { + System::Dispatcher dispatcher; + System::Event stopEvent(dispatcher); + ppg->dispatcher = &dispatcher; + ppg->stopEvent = &stopEvent; run(); } diff --git a/src/rpc/HttpClient.h b/src/rpc/HttpClient.h index 3d7842bb..0e351d7f 100644 --- a/src/rpc/HttpClient.h +++ b/src/rpc/HttpClient.h @@ -24,9 +24,7 @@ #include #include -// epee serialization -#include "misc_log_ex.h" -#include "storages/portable_storage_template_helper.h" +#include "serialization/SerializationTools.h" namespace CryptoNote { @@ -56,14 +54,14 @@ void invokeJsonCommand(HttpClient& client, const std::string& url, const Request HttpResponse hres; hreq.setUrl(url); - hreq.setBody(epee::serialization::store_t_to_json(req)); + hreq.setBody(storeToJson(req)); client.request(hreq, hres); if (hres.getStatus() != HttpResponse::STATUS_200) { throw std::runtime_error("HTTP status: " + std::to_string(hres.getStatus())); } - if (!epee::serialization::load_t_from_json(res, hres.getBody())) { + if (!loadFromJson(res, hres.getBody())) { throw std::runtime_error("Failed to parse JSON response"); } } @@ -74,10 +72,10 @@ void invokeBinaryCommand(HttpClient& client, const std::string& url, const Reque HttpResponse hres; hreq.setUrl(url); - hreq.setBody(epee::serialization::store_t_to_binary(req)); + hreq.setBody(storeToBinaryKeyValue(req)); client.request(hreq, hres); - if (!epee::serialization::load_t_from_binary(res, hres.getBody())) { + if (!loadFromBinaryKeyValue(res, hres.getBody())) { throw std::runtime_error("Failed to parse binary response"); } } diff --git a/src/rpc/JsonRpc.h b/src/rpc/JsonRpc.h index 525e9023..ee1ca60d 100644 --- a/src/rpc/JsonRpc.h +++ b/src/rpc/JsonRpc.h @@ -21,10 +21,9 @@ #include #include -#include "misc_log_ex.h" -#include "storages/portable_storage_template_helper.h" -#include "serialization/enableable.h" -#include "serialization/keyvalue_serialization_overloads.h" +#include "serialization/ISerializer.h" +#include "serialization/SerializationTools.h" +#include namespace CryptoNote { @@ -52,27 +51,37 @@ public: return message.c_str(); } + void serialize(ISerializer& s) { + s(code, "code"); + s(message, "message"); + } + int code; std::string message; }; -typedef boost::optional OptionalId; +typedef boost::optional OptionalId; class JsonRpcRequest { public: + + JsonRpcRequest() : psReq(Common::JsonValue::OBJECT) {} bool parseRequest(const std::string& requestBody) { - if (!psReq.load_from_json(requestBody)) { + try { + psReq = Common::JsonValue::fromString(requestBody); + } catch (std::exception&) { throw JsonRpcError(errParseError); } - OptionalId::value_type idValue; - if (psReq.get_value("id", idValue, nullptr)) { - id = idValue; + if (!psReq.contains("method")) { + throw JsonRpcError(errInvalidRequest); } - if (!psReq.get_value("method", method, nullptr)) { - throw JsonRpcError(errInvalidRequest); + method = psReq("method").getString(); + + if (psReq.contains("id")) { + id = psReq("id"); } return true; @@ -80,13 +89,15 @@ public: template bool loadParams(T& v) const { - return epee::serialization::kv_unserialize(v, - const_cast(psReq), nullptr, "params"); + loadFromJsonValue(v, psReq.contains("params") ? + psReq("params") : Common::JsonValue(Common::JsonValue::NIL)); + return true; } template bool setParams(const T& v) { - return epee::serialization::kv_serialize(v, psReq, nullptr, "params"); + psReq.set("params", storeToJsonValue(v)); + return true; } const std::string& getMethod() const { @@ -102,16 +113,14 @@ public: } std::string getBody() { - std::string reqBody; - psReq.set_value("jsonrpc", std::string("2.0"), nullptr); - psReq.set_value("method", method, nullptr); - psReq.dump_as_json(reqBody); - return reqBody; + psReq.set("jsonrpc", std::string("2.0")); + psReq.set("method", method); + return psReq.toString(); } private: - epee::serialization::portable_storage psReq; + Common::JsonValue psReq; OptionalId id; std::string method; }; @@ -120,55 +129,58 @@ private: class JsonRpcResponse { public: - void parse(const std::string& resonseBody) { - if (!psResp.load_from_json(resonseBody)) { + JsonRpcResponse() : psResp(Common::JsonValue::OBJECT) {} + + void parse(const std::string& responseBody) { + try { + psResp = Common::JsonValue::fromString(responseBody); + } catch (std::exception&) { throw JsonRpcError(errParseError); } } void setId(const OptionalId& id) { if (id.is_initialized()) { - psResp.set_value("id", id.get(), nullptr); + psResp.insert("id", id.get()); } } void setError(const JsonRpcError& err) { - auto errorSection = psResp.open_section("error", nullptr, true); - psResp.set_value("code", err.code, errorSection); - psResp.set_value("message", err.message, errorSection); + psResp.set("error", storeToJsonValue(err)); } - bool getError(JsonRpcError& err) { - auto errorSection = psResp.open_section("error", nullptr, false); - if (!errorSection) { + bool getError(JsonRpcError& err) const { + if (!psResp.contains("error")) { return false; } - psResp.get_value("code", err.code, errorSection); - psResp.get_value("message", err.message, errorSection); + loadFromJsonValue(err, psResp("error")); return true; } std::string getBody() { - std::string responseBody; - psResp.set_value("jsonrpc", std::string("2.0"), nullptr); - psResp.dump_as_json(responseBody); - return responseBody; + psResp.set("jsonrpc", std::string("2.0")); + return psResp.toString(); } template bool setResult(const T& v) { - return epee::serialization::kv_serialize(v, psResp, nullptr, "result"); + psResp.set("result", storeToJsonValue(v)); + return true; } template bool getResult(T& v) const { - return epee::serialization::kv_unserialize(v, - const_cast(psResp), nullptr, "result"); + if (!psResp.contains("result")) { + return false; + } + + loadFromJsonValue(v, psResp("result")); + return true; } private: - epee::serialization::portable_storage psResp; + Common::JsonValue psResp; }; diff --git a/src/rpc/RpcServer.cpp b/src/rpc/RpcServer.cpp index 285efe85..594b17fa 100644 --- a/src/rpc/RpcServer.cpp +++ b/src/rpc/RpcServer.cpp @@ -43,12 +43,12 @@ RpcServer::HandlerFunction binMethod(bool (RpcServer::*handler)(typename Command boost::value_initialized req; boost::value_initialized res; - if (!epee::serialization::load_t_from_binary(static_cast(req), request.getBody())) { + if (!loadFromBinaryKeyValue(static_cast(req), request.getBody())) { return false; } bool result = (obj->*handler)(req, res); - response.setBody(epee::serialization::store_t_to_binary(res.data())); + response.setBody(storeToBinaryKeyValue(res.data())); return result; }; } @@ -60,12 +60,12 @@ RpcServer::HandlerFunction jsonMethod(bool (RpcServer::*handler)(typename Comman boost::value_initialized req; boost::value_initialized res; - if (!epee::serialization::load_t_from_json(static_cast(req), request.getBody())) { + if (!loadFromJson(static_cast(req), request.getBody())) { return false; } bool result = (obj->*handler)(req, res); - response.setBody(epee::serialization::store_t_to_json(res.data())); + response.setBody(storeToJson(res.data())); return result; }; } @@ -79,6 +79,7 @@ std::unordered_map RpcServer::s_handler { "/queryblocks.bin", binMethod(&RpcServer::on_query_blocks) }, { "/get_o_indexes.bin", binMethod(&RpcServer::on_get_indexes) }, { "/getrandom_outs.bin", binMethod(&RpcServer::on_get_random_outs) }, + { "/get_pool_changes.bin", binMethod(&RpcServer::onGetPoolChanges) }, // json handlers { "/getinfo", jsonMethod(&RpcServer::on_get_info) }, @@ -125,7 +126,7 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& JsonRpcResponse jsonResponse; try { - + logger(TRACE) << "JSON-RPC request: " << request.getBody(); jsonRequest.parseRequest(request.getBody()); jsonResponse.setId(jsonRequest.getId()); // copy id @@ -153,16 +154,19 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& } catch (const JsonRpcError& err) { jsonResponse.setError(err); + } catch (const std::exception& e) { + jsonResponse.setError(JsonRpcError(JsonRpc::errInternalError, e.what())); } response.setBody(jsonResponse.getBody()); + logger(TRACE) << "JSON-RPC response: " << jsonResponse.getBody(); return true; } #define CHECK_CORE_READY() bool RpcServer::checkCoreReady() { - return m_core.is_ready() && m_p2p.get_payload_object().is_synchronized(); + return m_core.is_ready() && m_p2p.get_payload_object().isSynchronized(); } // @@ -244,6 +248,28 @@ bool RpcServer::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOU return true; } +bool RpcServer::onGetPoolChanges(const COMMAND_RPC_GET_POOL_CHANGES::request& req, COMMAND_RPC_GET_POOL_CHANGES::response& rsp) { + CHECK_CORE_READY(); + + rsp.status = CORE_RPC_STATUS_OK; + std::vector addedTransactions; + rsp.isTailBlockActual = m_core.getPoolChanges(req.tailBlockId, req.knownTxsIds, addedTransactions, rsp.deletedTxsIds); + if (rsp.isTailBlockActual) { + for (auto& tx : addedTransactions) { + blobdata txBlob; + if (!CryptoNote::tx_to_blob(tx, txBlob)) { + rsp.status = "Internal error"; + break;; + } + + rsp.addedTxs.emplace_back(std::move(txBlob)); + } + } + + return true; +} + + // // JSON handlers // @@ -288,7 +314,7 @@ bool RpcServer::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& } std::list missed_txs; std::list txs; - m_core.get_transactions(vh, txs, missed_txs); + m_core.getTransactions(vh, txs, missed_txs); for (auto& tx : txs) { blobdata blob = t_serializable_object_to_blob(tx); @@ -314,7 +340,7 @@ bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMM return true; } - tx_verification_context tvc = AUTO_VAL_INIT(tvc); + tx_verification_context tvc = boost::value_initialized(); if (!m_core.handle_incoming_tx(tx_blob, tvc, false)) { logger(INFO) << "[on_send_raw_tx]: Failed to process tx"; @@ -409,7 +435,7 @@ bool RpcServer::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, CO }; } - res = Common::podToHex(m_core.get_block_id_by_height(h)); + res = Common::podToHex(m_core.getBlockIdByHeight(h)); return true; } @@ -435,13 +461,13 @@ bool RpcServer::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_TOO_BIG_RESERVE_SIZE, "To big reserved size, maximum 255" }; } - CryptoNote::AccountPublicAddress acc = AUTO_VAL_INIT(acc); + AccountPublicAddress acc = boost::value_initialized(); if (!req.wallet_address.size() || !m_core.currency().parseAccountAddressString(req.wallet_address, acc)) { throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS, "Failed to parse wallet address" }; } - Block b = AUTO_VAL_INIT(b); + Block b = boost::value_initialized(); CryptoNote::blobdata blob_reserve; blob_reserve.resize(req.reserve_size, 0); if (!m_core.get_block_template(b, acc, res.difficulty, res.height, blob_reserve)) { @@ -494,8 +520,7 @@ bool RpcServer::on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMM throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB, "Wrong block blob" }; } - CryptoNote::block_verification_context bvc = AUTO_VAL_INIT(bvc); - + block_verification_context bvc = boost::value_initialized(); System::Event event(m_dispatcher); auto resultFuture = std::async(std::launch::async, [this, &event, &bvc, &blockblob]{ m_core.handle_incoming_block_blob(blockblob, bvc, true, true); @@ -547,7 +572,7 @@ bool RpcServer::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER } Block last_block; - if (!m_core.get_block_by_hash(last_block_hash, last_block)) { + if (!m_core.getBlockByHash(last_block_hash, last_block)) { throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: can't get last block hash." }; } @@ -566,7 +591,7 @@ bool RpcServer::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_B } Block blk; - if (!m_core.get_block_by_hash(block_hash, blk)) { + if (!m_core.getBlockByHash(block_hash, blk)) { throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: can't get block by hash. Hash = " + req.hash + '.' }; @@ -590,9 +615,9 @@ bool RpcServer::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER std::string("To big height: ") + std::to_string(req.height) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()) }; } - crypto::hash block_hash = m_core.get_block_id_by_height(req.height); + crypto::hash block_hash = m_core.getBlockIdByHeight(req.height); Block blk; - if (!m_core.get_block_by_hash(block_hash, blk)) { + if (!m_core.getBlockByHash(block_hash, blk)) { throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: can't get block by height. Height = " + std::to_string(req.height) + '.' }; } diff --git a/src/rpc/RpcServer.h b/src/rpc/RpcServer.h index 35b85cbc..6c6ecc2a 100644 --- a/src/rpc/RpcServer.h +++ b/src/rpc/RpcServer.h @@ -48,6 +48,7 @@ private: bool on_query_blocks(const COMMAND_RPC_QUERY_BLOCKS::request& req, COMMAND_RPC_QUERY_BLOCKS::response& res); bool on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res); bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); + bool onGetPoolChanges(const COMMAND_RPC_GET_POOL_CHANGES::request& req, COMMAND_RPC_GET_POOL_CHANGES::response& rsp); // json handlers bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index c42b4a37..04e070b7 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -16,504 +16,427 @@ // along with Bytecoin. If not, see . #pragma once + #include "cryptonote_protocol/cryptonote_protocol_defs.h" #include "cryptonote_core/cryptonote_basic.h" #include "cryptonote_core/difficulty.h" #include "crypto/hash.h" -namespace CryptoNote -{ - //----------------------------------------------- -#define CORE_RPC_STATUS_OK "OK" -#define CORE_RPC_STATUS_BUSY "BUSY" +#include "serialization/SerializationOverloads.h" - struct COMMAND_RPC_GET_HEIGHT - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; +namespace CryptoNote { +//----------------------------------------------- +#define CORE_RPC_STATUS_OK "OK" +#define CORE_RPC_STATUS_BUSY "BUSY" - struct response - { - uint64_t height; - std::string status; +struct EMPTY_STRUCT { + void serialize(ISerializer &s) {} +}; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; +struct STATUS_STRUCT { + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(status) + } +}; + +struct COMMAND_RPC_GET_HEIGHT { + typedef EMPTY_STRUCT request; + + struct response { + uint64_t height; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(height) + KV_MEMBER(status) + } + }; +}; + +struct COMMAND_RPC_GET_BLOCKS_FAST { + + struct request { + std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ + + void serialize(ISerializer &s) { + serializeAsBinary(block_ids, "block_ids", s); + } }; - struct COMMAND_RPC_GET_BLOCKS_FAST - { + struct response { + std::list blocks; + uint64_t start_height; + uint64_t current_height; + std::string status; - struct request - { - std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list blocks; - uint64_t start_height; - uint64_t current_height; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blocks) - KV_SERIALIZE(start_height) - KV_SERIALIZE(current_height) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(blocks) + KV_MEMBER(start_height) + KV_MEMBER(current_height) + KV_MEMBER(status) + } }; - //----------------------------------------------- - struct COMMAND_RPC_GET_TRANSACTIONS - { - struct request - { - std::list txs_hashes; +}; +//----------------------------------------------- +struct COMMAND_RPC_GET_TRANSACTIONS { + struct request { + std::list txs_hashes; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_hashes) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::list txs_as_hex; //transactions blobs as hex - std::list missed_tx; //not found transactions - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_as_hex) - KV_SERIALIZE(missed_tx) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(txs_hashes) + } }; - //----------------------------------------------- - struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES - { - struct request - { - crypto::hash txid; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(txid) - END_KV_SERIALIZE_MAP() - }; + struct response { + std::list txs_as_hex; //transactions blobs as hex + std::list missed_tx; //not found transactions + std::string status; - - struct response - { - std::vector o_indexes; - std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(o_indexes) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(txs_as_hex) + KV_MEMBER(missed_tx) + KV_MEMBER(status) + } }; - //----------------------------------------------- - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request - { - std::vector amounts; - uint64_t outs_count; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amounts) - KV_SERIALIZE(outs_count) - END_KV_SERIALIZE_MAP() +}; +//----------------------------------------------- +struct COMMAND_RPC_GET_POOL_CHANGES { + struct request { + crypto::hash tailBlockId; + std::vector knownTxsIds; + + void serialize(ISerializer &s) { + KV_MEMBER(tailBlockId) + serializeAsBinary(knownTxsIds, "knownTxsIds", s); + } }; -#pragma pack (push, 1) - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_out_entry - { - uint64_t global_amount_index; - crypto::public_key out_key; + struct response { + bool isTailBlockActual; + std::vector addedTxs; // Added transactions blobs + std::vector deletedTxsIds; // IDs of not found transactions + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(isTailBlockActual) + KV_MEMBER(addedTxs) + serializeAsBinary(deletedTxsIds, "deletedTxsIds", s); + KV_MEMBER(status) + } }; +}; +//----------------------------------------------- +struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES { + + struct request { + crypto::hash txid; + + void serialize(ISerializer &s) { + KV_MEMBER(txid) + } + }; + + struct response { + std::vector o_indexes; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(o_indexes) + KV_MEMBER(status) + } + }; +}; +//----------------------------------------------- +struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request { + std::vector amounts; + uint64_t outs_count; + + void serialize(ISerializer &s) { + KV_MEMBER(amounts) + KV_MEMBER(outs_count) + } +}; + +#pragma pack(push, 1) +struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_out_entry { + uint64_t global_amount_index; + crypto::public_key out_key; +}; #pragma pack(pop) - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount - { - uint64_t amount; - std::list outs; +struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount { + uint64_t amount; + std::list outs; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer &s) { + KV_MEMBER(amount) + serializeAsBinary(outs, "outs", s); + } +}; + +struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response { + std::vector outs; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(outs); + KV_MEMBER(status) + } +}; + +struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS { + typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request request; + typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response response; + + typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_out_entry out_entry; + typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount outs_for_amount; +}; + +//----------------------------------------------- +struct COMMAND_RPC_SEND_RAW_TX { + struct request { + std::string tx_as_hex; + + request() {} + explicit request(const Transaction &); + + void serialize(ISerializer &s) { + KV_MEMBER(tx_as_hex) + } }; - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response - { - std::vector outs; + struct response { std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(outs) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer &s) { + KV_MEMBER(status) + } + }; +}; +//----------------------------------------------- +struct COMMAND_RPC_START_MINING { + struct request { + std::string miner_address; + uint64_t threads_count; + + void serialize(ISerializer &s) { + KV_MEMBER(miner_address) + KV_MEMBER(threads_count) + } }; - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS - { - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_request request; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response response; + struct response { + std::string status; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_out_entry out_entry; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_outs_for_amount outs_for_amount; + void serialize(ISerializer &s) { + KV_MEMBER(status) + } }; - //----------------------------------------------- - struct COMMAND_RPC_SEND_RAW_TX - { - struct request - { - std::string tx_as_hex; +}; +//----------------------------------------------- +struct COMMAND_RPC_GET_INFO { + typedef EMPTY_STRUCT request; - request() {} - explicit request(const Transaction &); + struct response { + std::string status; + uint64_t height; + uint64_t difficulty; + uint64_t tx_count; + uint64_t tx_pool_size; + uint64_t alt_blocks_count; + uint64_t outgoing_connections_count; + uint64_t incoming_connections_count; + uint64_t white_peerlist_size; + uint64_t grey_peerlist_size; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_as_hex) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(status) + KV_MEMBER(height) + KV_MEMBER(difficulty) + KV_MEMBER(tx_count) + KV_MEMBER(tx_pool_size) + KV_MEMBER(alt_blocks_count) + KV_MEMBER(outgoing_connections_count) + KV_MEMBER(incoming_connections_count) + KV_MEMBER(white_peerlist_size) + KV_MEMBER(grey_peerlist_size) + } }; - //----------------------------------------------- - struct COMMAND_RPC_START_MINING - { - struct request - { - std::string miner_address; - uint64_t threads_count; +}; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(miner_address) - KV_SERIALIZE(threads_count) - END_KV_SERIALIZE_MAP() - }; +//----------------------------------------------- +struct COMMAND_RPC_STOP_MINING { + typedef EMPTY_STRUCT request; + typedef STATUS_STRUCT response; +}; - struct response - { - std::string status; +//----------------------------------------------- +struct COMMAND_RPC_STOP_DAEMON { + typedef EMPTY_STRUCT request; + typedef STATUS_STRUCT response; +}; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; +// +struct COMMAND_RPC_GETBLOCKCOUNT { + typedef std::list request; + + struct response { + uint64_t count; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(count) + KV_MEMBER(status) + } }; - //----------------------------------------------- - struct COMMAND_RPC_GET_INFO - { - struct request - { +}; - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; +struct COMMAND_RPC_GETBLOCKHASH { + typedef std::vector request; + typedef std::string response; +}; - struct response - { - std::string status; - uint64_t height; - uint64_t difficulty; - uint64_t tx_count; - uint64_t tx_pool_size; - uint64_t alt_blocks_count; - uint64_t outgoing_connections_count; - uint64_t incoming_connections_count; - uint64_t white_peerlist_size; - uint64_t grey_peerlist_size; +struct COMMAND_RPC_GETBLOCKTEMPLATE { + struct request { + uint64_t reserve_size; //max 255 bytes + std::string wallet_address; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(height) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(tx_count) - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(alt_blocks_count) - KV_SERIALIZE(outgoing_connections_count) - KV_SERIALIZE(incoming_connections_count) - KV_SERIALIZE(white_peerlist_size) - KV_SERIALIZE(grey_peerlist_size) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(reserve_size) + KV_MEMBER(wallet_address) + } }; - - //----------------------------------------------- - struct COMMAND_RPC_STOP_MINING - { - struct request - { + struct response { + uint64_t difficulty; + uint32_t height; + uint64_t reserved_offset; + blobdata blocktemplate_blob; + std::string status; - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(difficulty) + KV_MEMBER(height) + KV_MEMBER(reserved_offset) + KV_MEMBER(blocktemplate_blob) + KV_MEMBER(status) + } + }; +}; + +struct COMMAND_RPC_GET_CURRENCY_ID { + typedef EMPTY_STRUCT request; + + struct response { + std::string currency_id_blob; + + void serialize(ISerializer &s) { + KV_MEMBER(currency_id_blob) + } + }; +}; + +struct COMMAND_RPC_SUBMITBLOCK { + typedef std::vector request; + typedef STATUS_STRUCT response; +}; + +struct block_header_responce { + uint8_t major_version; + uint8_t minor_version; + uint64_t timestamp; + std::string prev_hash; + uint32_t nonce; + bool orphan_status; + uint64_t height; + uint64_t depth; + std::string hash; + difficulty_type difficulty; + uint64_t reward; + + void serialize(ISerializer &s) { + KV_MEMBER(major_version) + KV_MEMBER(minor_version) + KV_MEMBER(timestamp) + KV_MEMBER(prev_hash) + KV_MEMBER(nonce) + KV_MEMBER(orphan_status) + KV_MEMBER(height) + KV_MEMBER(depth) + KV_MEMBER(hash) + KV_MEMBER(difficulty) + KV_MEMBER(reward) + } +}; + +struct BLOCK_HEADER_RESPONSE { + std::string status; + block_header_responce block_header; + + void serialize(ISerializer &s) { + KV_MEMBER(block_header) + KV_MEMBER(status) + } +}; - struct response - { - std::string status; +struct COMMAND_RPC_GET_LAST_BLOCK_HEADER { + typedef EMPTY_STRUCT request; + typedef BLOCK_HEADER_RESPONSE response; +}; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; +struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH { + struct request { + std::string hash; + + void serialize(ISerializer &s) { + KV_MEMBER(hash) + } }; - //----------------------------------------------- - struct COMMAND_RPC_STOP_DAEMON { - struct request { + typedef BLOCK_HEADER_RESPONSE response; +}; - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; +struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT { + struct request { + uint64_t height; - - struct response { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; + void serialize(ISerializer &s) { + KV_MEMBER(height) + } }; + typedef BLOCK_HEADER_RESPONSE response; +}; - // - struct COMMAND_RPC_GETBLOCKCOUNT - { - typedef std::list request; - - struct response - { - uint64_t count; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(count) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; +struct COMMAND_RPC_QUERY_BLOCKS { + struct request { + std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ + uint64_t timestamp; + void serialize(ISerializer &s) { + serializeAsBinary(block_ids, "block_ids", s); + KV_MEMBER(timestamp) + } }; - struct COMMAND_RPC_GETBLOCKHASH - { - typedef std::vector request; + struct response { + std::string status; + uint64_t start_height; + uint64_t current_height; + uint64_t full_offset; + std::list items; - typedef std::string response; + void serialize(ISerializer &s) { + KV_MEMBER(status) + KV_MEMBER(start_height) + KV_MEMBER(current_height) + KV_MEMBER(full_offset) + KV_MEMBER(items) + } }; +}; - - struct COMMAND_RPC_GETBLOCKTEMPLATE - { - struct request - { - uint64_t reserve_size; //max 255 bytes - std::string wallet_address; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(reserve_size) - KV_SERIALIZE(wallet_address) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - uint64_t difficulty; - uint32_t height; - uint64_t reserved_offset; - blobdata blocktemplate_blob; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(difficulty) - KV_SERIALIZE(height) - KV_SERIALIZE(reserved_offset) - KV_SERIALIZE(blocktemplate_blob) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_CURRENCY_ID - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string currency_id_blob; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(currency_id_blob) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SUBMITBLOCK - { - typedef std::vector request; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct block_header_responce - { - uint8_t major_version; - uint8_t minor_version; - uint64_t timestamp; - std::string prev_hash; - uint32_t nonce; - bool orphan_status; - uint64_t height; - uint64_t depth; - std::string hash; - difficulty_type difficulty; - uint64_t reward; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(major_version) - KV_SERIALIZE(minor_version) - KV_SERIALIZE(timestamp) - KV_SERIALIZE(prev_hash) - KV_SERIALIZE(nonce) - KV_SERIALIZE(orphan_status) - KV_SERIALIZE(height) - KV_SERIALIZE(depth) - KV_SERIALIZE(hash) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(reward) - END_KV_SERIALIZE_MAP() - }; - - struct COMMAND_RPC_GET_LAST_BLOCK_HEADER - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_header_responce block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH - { - struct request - { - std::string hash; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hash) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_header_responce block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT - { - struct request - { - uint64_t height; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_header_responce block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_QUERY_BLOCKS - { - struct request - { - std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - uint64_t timestamp; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) - KV_SERIALIZE(timestamp) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - uint64_t start_height; - uint64_t current_height; - uint64_t full_offset; - - std::list items; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(start_height) - KV_SERIALIZE(current_height) - KV_SERIALIZE(full_offset) - KV_SERIALIZE(items) - END_KV_SERIALIZE_MAP() - }; - }; } diff --git a/src/serialization/BinaryInputStreamSerializer.cpp b/src/serialization/BinaryInputStreamSerializer.cpp index ed24bbf5..bcb80df8 100644 --- a/src/serialization/BinaryInputStreamSerializer.cpp +++ b/src/serialization/BinaryInputStreamSerializer.cpp @@ -68,54 +68,52 @@ ISerializer::SerializerType BinaryInputStreamSerializer::type() const { return ISerializer::INPUT; } -ISerializer& BinaryInputStreamSerializer::beginObject(const std::string& name) { - return *this; +bool BinaryInputStreamSerializer::beginObject(Common::StringView name) { + return true; } -ISerializer& BinaryInputStreamSerializer::endObject() { - return *this; +void BinaryInputStreamSerializer::endObject() { } -ISerializer& BinaryInputStreamSerializer::beginArray(std::size_t& size, const std::string& name) { +bool BinaryInputStreamSerializer::beginArray(std::size_t& size, Common::StringView name) { readVarintAs(stream, size); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::endArray() { - return *this; +void BinaryInputStreamSerializer::endArray() { } -ISerializer& BinaryInputStreamSerializer::operator()(uint8_t& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(uint8_t& value, Common::StringView name) { readVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(uint32_t& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(uint32_t& value, Common::StringView name) { readVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(int32_t& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(int32_t& value, Common::StringView name) { readVarintAs(stream, value); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(int64_t& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(int64_t& value, Common::StringView name) { readVarintAs(stream, value); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(uint64_t& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(uint64_t& value, Common::StringView name) { readVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(bool& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(bool& value, Common::StringView name) { value = stream.get() != 0; - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::operator()(std::string& value, const std::string& name) { +bool BinaryInputStreamSerializer::operator()(std::string& value, Common::StringView name) { uint64_t size; readVarint(stream, size); @@ -129,39 +127,28 @@ ISerializer& BinaryInputStreamSerializer::operator()(std::string& value, const s value.clear(); } - return *this; + return true; } -ISerializer& BinaryInputStreamSerializer::binary(void* value, std::size_t size, const std::string& name) { - stream.read(static_cast(value), size); - return *this; +bool BinaryInputStreamSerializer::binary(void* value, std::size_t size, Common::StringView name) { + checkedRead(static_cast(value), size); + return true; } -ISerializer& BinaryInputStreamSerializer::binary(std::string& value, const std::string& name) { +bool BinaryInputStreamSerializer::binary(std::string& value, Common::StringView name) { return (*this)(value, name); } - -bool BinaryInputStreamSerializer::hasObject(const std::string& name) { +bool BinaryInputStreamSerializer::operator()(double& value, Common::StringView name) { assert(false); //the method is not supported for this type of serialization - throw std::runtime_error("hasObject method is not supported in BinaryInputStreamSerializer"); - + throw std::runtime_error("double serialization is not supported in BinaryInputStreamSerializer"); return false; } -ISerializer& BinaryInputStreamSerializer::operator()(double& value, const std::string& name) { - assert(false); //the method is not supported for this type of serialization - throw std::runtime_error("double serialization is not supported in BinaryInputStreamSerializer"); - - return *this; -} - void BinaryInputStreamSerializer::checkedRead(char* buf, size_t size) { - stream.read(buf, size); - if (!stream) { + if (stream.read(buf, size).gcount() != size) { throw std::runtime_error("Stream read error"); } } - } diff --git a/src/serialization/BinaryInputStreamSerializer.h b/src/serialization/BinaryInputStreamSerializer.h index dc956b73..002b8024 100644 --- a/src/serialization/BinaryInputStreamSerializer.h +++ b/src/serialization/BinaryInputStreamSerializer.h @@ -31,36 +31,31 @@ public: virtual ISerializer::SerializerType type() const; - virtual ISerializer& beginObject(const std::string& name) override; - virtual ISerializer& endObject() override; + virtual bool beginObject(Common::StringView name) override; + virtual void endObject() override; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override; - virtual ISerializer& endArray() override; + virtual bool beginArray(std::size_t& size, Common::StringView name) override; + virtual void endArray() override; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) override; - virtual ISerializer& operator()(int32_t& value, const std::string& name) override; - - virtual ISerializer& operator()(uint32_t& value, const std::string& name) override; - virtual ISerializer& operator()(int64_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) override; - virtual ISerializer& operator()(double& value, const std::string& name) override; - virtual ISerializer& operator()(bool& value, const std::string& name) override; - virtual ISerializer& operator()(std::string& value, const std::string& name) override; - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; - - virtual bool hasObject(const std::string& name) override; + virtual bool operator()(uint8_t& value, Common::StringView name) override; + virtual bool operator()(int32_t& value, Common::StringView name) override; + virtual bool operator()(uint32_t& value, Common::StringView name) override; + virtual bool operator()(int64_t& value, Common::StringView name) override; + virtual bool operator()(uint64_t& value, Common::StringView name) override; + virtual bool operator()(double& value, Common::StringView name) override; + virtual bool operator()(bool& value, Common::StringView name) override; + virtual bool operator()(std::string& value, Common::StringView name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; template - ISerializer& operator()(T& value, const std::string& name) { + bool operator()(T& value, Common::StringView name) { return ISerializer::operator()(value, name); } private: void checkedRead(char* buf, size_t size); - std::istream& stream; }; diff --git a/src/serialization/BinaryOutputStreamSerializer.cpp b/src/serialization/BinaryOutputStreamSerializer.cpp index 7b8b55ff..9e9c3e6a 100644 --- a/src/serialization/BinaryOutputStreamSerializer.cpp +++ b/src/serialization/BinaryOutputStreamSerializer.cpp @@ -44,82 +44,72 @@ ISerializer::SerializerType BinaryOutputStreamSerializer::type() const { return ISerializer::OUTPUT; } -ISerializer& BinaryOutputStreamSerializer::beginObject(const std::string& name) { - return *this; +bool BinaryOutputStreamSerializer::beginObject(Common::StringView name) { + return true; } -ISerializer& BinaryOutputStreamSerializer::endObject() { - return *this; +void BinaryOutputStreamSerializer::endObject() { } -ISerializer& BinaryOutputStreamSerializer::beginArray(std::size_t& size, const std::string& name) { +bool BinaryOutputStreamSerializer::beginArray(std::size_t& size, Common::StringView name) { writeVarint(stream, size); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::endArray() { - return *this; +void BinaryOutputStreamSerializer::endArray() { } -ISerializer& BinaryOutputStreamSerializer::operator()(uint8_t& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(uint8_t& value, Common::StringView name) { writeVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(uint32_t& value, Common::StringView name) { writeVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(int32_t& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(int32_t& value, Common::StringView name) { writeVarint(stream, static_cast(value)); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(int64_t& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(int64_t& value, Common::StringView name) { writeVarint(stream, static_cast(value)); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(uint64_t& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(uint64_t& value, Common::StringView name) { writeVarint(stream, value); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(bool& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(bool& value, Common::StringView name) { char boolVal = value; checkedWrite(&boolVal, 1); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::operator()(std::string& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(std::string& value, Common::StringView name) { writeVarint(stream, value.size()); checkedWrite(value.data(), value.size()); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::binary(void* value, std::size_t size, const std::string& name) { +bool BinaryOutputStreamSerializer::binary(void* value, std::size_t size, Common::StringView name) { checkedWrite(static_cast(value), size); - return *this; + return true; } -ISerializer& BinaryOutputStreamSerializer::binary(std::string& value, const std::string& name) { +bool BinaryOutputStreamSerializer::binary(std::string& value, Common::StringView name) { // write as string (with size prefix) return (*this)(value, name); } -bool BinaryOutputStreamSerializer::hasObject(const std::string& name) { - assert(false); //the method is not supported for this type of serialization - throw std::runtime_error("hasObject method is not supported in BinaryOutputStreamSerializer"); - - return false; -} - -ISerializer& BinaryOutputStreamSerializer::operator()(double& value, const std::string& name) { +bool BinaryOutputStreamSerializer::operator()(double& value, Common::StringView name) { assert(false); //the method is not supported for this type of serialization throw std::runtime_error("double serialization is not supported in BinaryOutputStreamSerializer"); - - return *this; + return false; } void BinaryOutputStreamSerializer::checkedWrite(const char* buf, size_t size) { diff --git a/src/serialization/BinaryOutputStreamSerializer.h b/src/serialization/BinaryOutputStreamSerializer.h index 1de71c04..e1dc3500 100644 --- a/src/serialization/BinaryOutputStreamSerializer.h +++ b/src/serialization/BinaryOutputStreamSerializer.h @@ -31,28 +31,25 @@ public: virtual ISerializer::SerializerType type() const; - virtual ISerializer& beginObject(const std::string& name) override; - virtual ISerializer& endObject() override; + virtual bool beginObject(Common::StringView name) override; + virtual void endObject() override; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override; - virtual ISerializer& endArray() override; + virtual bool beginArray(std::size_t& size, Common::StringView name) override; + virtual void endArray() override; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) override; - virtual ISerializer& operator()(int32_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint32_t& value, const std::string& name) override; - virtual ISerializer& operator()(int64_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) override; - virtual ISerializer& operator()(double& value, const std::string& name) override; - virtual ISerializer& operator()(bool& value, const std::string& name) override; - virtual ISerializer& operator()(std::string& value, const std::string& name) override; - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; - - virtual bool hasObject(const std::string& name) override; + virtual bool operator()(uint8_t& value, Common::StringView name) override; + virtual bool operator()(int32_t& value, Common::StringView name) override; + virtual bool operator()(uint32_t& value, Common::StringView name) override; + virtual bool operator()(int64_t& value, Common::StringView name) override; + virtual bool operator()(uint64_t& value, Common::StringView name) override; + virtual bool operator()(double& value, Common::StringView name) override; + virtual bool operator()(bool& value, Common::StringView name) override; + virtual bool operator()(std::string& value, Common::StringView name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; template - ISerializer& operator()(T& value, const std::string& name) { + bool operator()(T& value, Common::StringView name) { return ISerializer::operator()(value, name); } diff --git a/src/serialization/ISerializer.h b/src/serialization/ISerializer.h index d610d4fc..f7c5c5f0 100644 --- a/src/serialization/ISerializer.h +++ b/src/serialization/ISerializer.h @@ -20,6 +20,8 @@ #include #include +#include + namespace CryptoNote { class ISerializer { @@ -34,40 +36,49 @@ public: virtual SerializerType type() const = 0; - virtual ISerializer& beginObject(const std::string& name) = 0; - virtual ISerializer& endObject() = 0; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) = 0; - virtual ISerializer& endArray() = 0; + virtual bool beginObject(Common::StringView name) = 0; + virtual void endObject() = 0; + virtual bool beginArray(std::size_t& size, Common::StringView name) = 0; + virtual void endArray() = 0; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) = 0; - virtual ISerializer& operator()(int32_t& value, const std::string& name) = 0; - virtual ISerializer& operator()(uint32_t& value, const std::string& name) = 0; - virtual ISerializer& operator()(int64_t& value, const std::string& name) = 0; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) = 0; - virtual ISerializer& operator()(double& value, const std::string& name) = 0; - virtual ISerializer& operator()(bool& value, const std::string& name) = 0; - virtual ISerializer& operator()(std::string& value, const std::string& name) = 0; + virtual bool operator()(uint8_t& value, Common::StringView name) = 0; + virtual bool operator()(int32_t& value, Common::StringView name) = 0; + virtual bool operator()(uint32_t& value, Common::StringView name) = 0; + virtual bool operator()(int64_t& value, Common::StringView name) = 0; + virtual bool operator()(uint64_t& value, Common::StringView name) = 0; + virtual bool operator()(double& value, Common::StringView name) = 0; + virtual bool operator()(bool& value, Common::StringView name) = 0; + virtual bool operator()(std::string& value, Common::StringView name) = 0; // read/write binary block - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) = 0; - virtual ISerializer& binary(std::string& value, const std::string& name) = 0; - - virtual bool hasObject(const std::string& name) = 0; + virtual bool binary(void* value, std::size_t size, Common::StringView name) = 0; + virtual bool binary(std::string& value, Common::StringView name) = 0; template - ISerializer& operator()(T& value, const std::string& name); + bool operator()(T& value, Common::StringView name); }; template -ISerializer& ISerializer::operator()(T& value, const std::string& name) { - serialize(value, name, *this); - return *this; +bool ISerializer::operator()(T& value, Common::StringView name) { + return serialize(value, name, *this); } template -void serialize(T& value, const std::string& name, ISerializer& serializer) { - value.serialize(serializer, name); - return; +bool serialize(T& value, Common::StringView name, ISerializer& serializer) { + if (!serializer.beginObject(name)) { + return false; + } + + serialize(value, serializer); + serializer.endObject(); + return true; } +template +void serialize(T& value, ISerializer& serializer) { + value.serialize(serializer); +} + +#define KV_MEMBER(member) s(member, #member); + } diff --git a/src/serialization/JsonInputStreamSerializer.cpp b/src/serialization/JsonInputStreamSerializer.cpp index 37aa12f6..8cb6efe1 100644 --- a/src/serialization/JsonInputStreamSerializer.cpp +++ b/src/serialization/JsonInputStreamSerializer.cpp @@ -22,9 +22,8 @@ namespace CryptoNote { -JsonInputStreamSerializer::JsonInputStreamSerializer(std::istream& stream) { +JsonInputStreamSerializer::JsonInputStreamSerializer(std::istream& stream) : JsonInputValueSerializer(root) { stream >> root; - JsonInputValueSerializer::setJsonValue(&root); } JsonInputStreamSerializer::~JsonInputStreamSerializer() { diff --git a/src/serialization/JsonInputValueSerializer.cpp b/src/serialization/JsonInputValueSerializer.cpp index 60c37307..35b282dc 100644 --- a/src/serialization/JsonInputValueSerializer.cpp +++ b/src/serialization/JsonInputValueSerializer.cpp @@ -23,151 +23,142 @@ using Common::JsonValue; using namespace CryptoNote; -JsonInputValueSerializer::JsonInputValueSerializer() : root(nullptr) { +JsonInputValueSerializer::JsonInputValueSerializer(const Common::JsonValue& value) : root(value) { + chain.push_back(&root); } JsonInputValueSerializer::~JsonInputValueSerializer() { } -void JsonInputValueSerializer::setJsonValue(const JsonValue* value) { - root = value; -} - ISerializer::SerializerType JsonInputValueSerializer::type() const { return ISerializer::INPUT; } -ISerializer& JsonInputValueSerializer::beginObject(const std::string& name) { - assert(root); - - if (chain.size() == 0) { - chain.push_back(root); - return *this; - } - +bool JsonInputValueSerializer::beginObject(Common::StringView name) { const JsonValue* parent = chain.back(); + if (parent->isArray()) { const JsonValue& v = (*parent)[idxs.back()++]; chain.push_back(&v); - } else { - const JsonValue& v = (*parent)(name); - chain.push_back(&v); + return true; } - return *this; + if (parent->contains(std::string(name))) { + const JsonValue& v = (*parent)(std::string(name)); + chain.push_back(&v); + return true; + } + + return false; + + //if (parent->isArray()) { + // const JsonValue& v = (*parent)[idxs.back()++]; + // chain.push_back(&v); + //} else { + // const JsonValue& v = (*parent)(name); + // chain.push_back(&v); + //} } -ISerializer& JsonInputValueSerializer::endObject() { - assert(root); - +void JsonInputValueSerializer::endObject() { + assert(!chain.empty()); chain.pop_back(); - return *this; } -ISerializer& JsonInputValueSerializer::beginArray(std::size_t& size, const std::string& name) { - assert(root); - +bool JsonInputValueSerializer::beginArray(std::size_t& size, Common::StringView name) { const JsonValue* parent = chain.back(); + std::string strName(name); - if (parent->count(name)) { - const JsonValue& arr = (*parent)(name); + if (parent->contains(strName)) { + const JsonValue& arr = (*parent)(strName); size = arr.size(); chain.push_back(&arr); - } else { - size = 0; - chain.push_back(0); + idxs.push_back(0); + return true; } - - idxs.push_back(0); - return *this; + + size = 0; + return false; } -ISerializer& JsonInputValueSerializer::endArray() { - assert(root); +void JsonInputValueSerializer::endArray() { + assert(!chain.empty()); + assert(!idxs.empty()); chain.pop_back(); idxs.pop_back(); - return *this; } -ISerializer& JsonInputValueSerializer::operator()(uint32_t& value, const std::string& name) { - assert(root); - value = static_cast(getNumber(name)); - return *this; +bool JsonInputValueSerializer::operator()(uint32_t& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(int32_t& value, const std::string& name) { - assert(root); - value = static_cast(getNumber(name)); - return *this; +bool JsonInputValueSerializer::operator()(int32_t& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(int64_t& value, const std::string& name) { - assert(root); - value = getNumber(name); - return *this; +bool JsonInputValueSerializer::operator()(int64_t& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(uint64_t& value, const std::string& name) { - assert(root); - value = static_cast(getNumber(name)); - return *this; +bool JsonInputValueSerializer::operator()(uint64_t& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(double& value, const std::string& name) { - assert(root); - value = getValue(name).getReal(); - return *this; +bool JsonInputValueSerializer::operator()(double& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(std::string& value, const std::string& name) { - assert(root); - value = getValue(name).getString(); - return *this; +bool JsonInputValueSerializer::operator()(uint8_t& value, Common::StringView name) { + return getNumber(name, value); } -ISerializer& JsonInputValueSerializer::operator()(uint8_t& value, const std::string& name) { - assert(root); - value = static_cast(getNumber(name)); - return *this; +bool JsonInputValueSerializer::operator()(std::string& value, Common::StringView name) { + auto ptr = getValue(name); + if (!ptr) { + return false; + } + value = ptr->getString(); + return true; } -ISerializer& JsonInputValueSerializer::operator()(bool& value, const std::string& name) { - assert(root); - value = getValue(name).getBool(); - return *this; +bool JsonInputValueSerializer::operator()(bool& value, Common::StringView name) { + auto ptr = getValue(name); + if (!ptr) { + return false; + } + value = ptr->getBool(); + return true; } -bool JsonInputValueSerializer::hasObject(const std::string& name) { - assert(root); - - const Common::JsonValue* value; - if (chain.empty()) { - value = root; - } else { - value = chain.back(); +bool JsonInputValueSerializer::binary(void* value, std::size_t size, Common::StringView name) { + auto ptr = getValue(name); + if (ptr == nullptr) { + return false; } - return value->count(name) != 0; + Common::fromHex(ptr->getString(), value, size); + return true; } -ISerializer& JsonInputValueSerializer::binary(void* value, std::size_t size, const std::string& name) { - auto str = getValue(name).getString(); - Common::fromHex(str, value, size); - return *this; +bool JsonInputValueSerializer::binary(std::string& value, Common::StringView name) { + auto ptr = getValue(name); + if (ptr == nullptr) { + return false; + } + + std::string valueHex = ptr->getString(); + value = Common::asString(Common::fromHex(valueHex)); + + return true; } -ISerializer& JsonInputValueSerializer::binary(std::string& value, const std::string& name) { - auto str = getValue(name).getString(); - value = Common::asString(Common::fromHex(str)); - return *this; -} - -JsonValue JsonInputValueSerializer::getValue(const std::string& name) { +const JsonValue* JsonInputValueSerializer::getValue(Common::StringView name) { const JsonValue& val = *chain.back(); - return val.isArray() ? val[idxs.back()++] : val(name); -} + if (val.isArray()) { + return &val[idxs.back()++]; + } -int64_t JsonInputValueSerializer::getNumber(const std::string& name) { - return getValue(name).getInteger(); + std::string strName(name); + return val.contains(strName) ? &val(strName) : nullptr; } diff --git a/src/serialization/JsonInputValueSerializer.h b/src/serialization/JsonInputValueSerializer.h index 29e53523..e211b700 100644 --- a/src/serialization/JsonInputValueSerializer.h +++ b/src/serialization/JsonInputValueSerializer.h @@ -25,44 +25,51 @@ namespace CryptoNote { //deserialization class JsonInputValueSerializer : public ISerializer { public: - JsonInputValueSerializer(); + JsonInputValueSerializer(const Common::JsonValue& value); virtual ~JsonInputValueSerializer(); - void setJsonValue(const Common::JsonValue* value); SerializerType type() const; - virtual ISerializer& beginObject(const std::string& name) override; - virtual ISerializer& endObject() override; + virtual bool beginObject(Common::StringView name) override; + virtual void endObject() override; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override; - virtual ISerializer& endArray() override; + virtual bool beginArray(std::size_t& size, Common::StringView name) override; + virtual void endArray() override; - virtual ISerializer& operator()(int32_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint32_t& value, const std::string& name) override; - virtual ISerializer& operator()(int64_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) override; - virtual ISerializer& operator()(double& value, const std::string& name) override; - virtual ISerializer& operator()(std::string& value, const std::string& name) override; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) override; - virtual ISerializer& operator()(bool& value, const std::string& name) override; - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; - - virtual bool hasObject(const std::string& name) override; + virtual bool operator()(uint8_t& value, Common::StringView name) override; + virtual bool operator()(int32_t& value, Common::StringView name) override; + virtual bool operator()(uint32_t& value, Common::StringView name) override; + virtual bool operator()(int64_t& value, Common::StringView name) override; + virtual bool operator()(uint64_t& value, Common::StringView name) override; + virtual bool operator()(double& value, Common::StringView name) override; + virtual bool operator()(bool& value, Common::StringView name) override; + virtual bool operator()(std::string& value, Common::StringView name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; template - ISerializer& operator()(T& value, const std::string& name) { + bool operator()(T& value, Common::StringView name) { return ISerializer::operator()(value, name); } private: - const Common::JsonValue* root; + const Common::JsonValue& root; std::vector chain; std::vector idxs; - Common::JsonValue getValue(const std::string& name); - int64_t getNumber(const std::string& name); + const Common::JsonValue* getValue(Common::StringView name); + + template + bool getNumber(Common::StringView name, T& v) { + auto ptr = getValue(name); + + if (!ptr) { + return false; + } + + v = static_cast(ptr->getInteger()); + return true; + } }; } diff --git a/src/serialization/JsonOutputStreamSerializer.cpp b/src/serialization/JsonOutputStreamSerializer.cpp index f3f27036..3224d479 100644 --- a/src/serialization/JsonOutputStreamSerializer.cpp +++ b/src/serialization/JsonOutputStreamSerializer.cpp @@ -30,138 +30,105 @@ std::ostream& operator<<(std::ostream& out, const JsonOutputStreamSerializer& en } } +namespace { + +template +void insertOrPush(JsonValue& js, Common::StringView name, const T& value) { + if (js.isArray()) { + js.pushBack(JsonValue(value)); + } else { + js.insert(std::string(name), JsonValue(value)); + } +} + +} + JsonOutputStreamSerializer::JsonOutputStreamSerializer() : root(JsonValue::OBJECT) { + chain.push_back(&root); } JsonOutputStreamSerializer::~JsonOutputStreamSerializer() { } -JsonValue JsonOutputStreamSerializer::getJsonValue() const { - return root; -} - ISerializer::SerializerType JsonOutputStreamSerializer::type() const { return ISerializer::OUTPUT; } -ISerializer& JsonOutputStreamSerializer::beginObject(const std::string& name) { - if (chain.size() == 0) { - chain.push_back(&root); - return *this; - } - - JsonValue* parent = chain.back(); +bool JsonOutputStreamSerializer::beginObject(Common::StringView name) { + JsonValue& parent = *chain.back(); JsonValue obj(JsonValue::OBJECT); - if (parent->isObject()) { - JsonValue& res = parent->insert(name, obj); - chain.push_back(&res); + if (parent.isObject()) { + chain.push_back(&parent.insert(std::string(name), obj)); } else { - JsonValue& res = parent->pushBack(obj); - chain.push_back(&res); + chain.push_back(&parent.pushBack(obj)); } - return *this; + return true; } -ISerializer& JsonOutputStreamSerializer::endObject() { +void JsonOutputStreamSerializer::endObject() { + assert(!chain.empty()); chain.pop_back(); - return *this; } -ISerializer& JsonOutputStreamSerializer::beginArray(std::size_t& size, const std::string& name) { +bool JsonOutputStreamSerializer::beginArray(std::size_t& size, Common::StringView name) { JsonValue val(JsonValue::ARRAY); - JsonValue& res = chain.back()->insert(name, val); + JsonValue& res = chain.back()->insert(std::string(name), val); chain.push_back(&res); - return *this; + return true; } -ISerializer& JsonOutputStreamSerializer::endArray() { +void JsonOutputStreamSerializer::endArray() { + assert(!chain.empty()); chain.pop_back(); - return *this; } -ISerializer& JsonOutputStreamSerializer::operator()(uint64_t& value, const std::string& name) { +bool JsonOutputStreamSerializer::operator()(uint64_t& value, Common::StringView name) { int64_t v = static_cast(value); return operator()(v, name); } -ISerializer& JsonOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) { +bool JsonOutputStreamSerializer::operator()(uint32_t& value, Common::StringView name) { uint64_t v = static_cast(value); return operator()(v, name); } -ISerializer& JsonOutputStreamSerializer::operator()(int32_t& value, const std::string& name) { +bool JsonOutputStreamSerializer::operator()(int32_t& value, Common::StringView name) { int64_t v = static_cast(value); return operator()(v, name); } -ISerializer& JsonOutputStreamSerializer::operator()(int64_t& value, const std::string& name) { - JsonValue* val = chain.back(); - JsonValue v; - v = static_cast(value); - if (val->isArray()) { - val->pushBack(v); - } else { - val->insert(name, v); - } - return *this; +bool JsonOutputStreamSerializer::operator()(int64_t& value, Common::StringView name) { + insertOrPush(*chain.back(), name, value); + return true; } -ISerializer& JsonOutputStreamSerializer::operator()(double& value, const std::string& name) { - JsonValue* val = chain.back(); - JsonValue v; - v = static_cast(value); - - if (val->isArray()) { - val->pushBack(v); - } else { - val->insert(name, v); - } - return *this; +bool JsonOutputStreamSerializer::operator()(double& value, Common::StringView name) { + insertOrPush(*chain.back(), name, value); + return true; } -ISerializer& JsonOutputStreamSerializer::operator()(std::string& value, const std::string& name) { - JsonValue* val = chain.back(); - JsonValue v; - v = value; - - if (val->isArray()) { - val->pushBack(v); - } else { - val->insert(name, v); - } - return *this; +bool JsonOutputStreamSerializer::operator()(std::string& value, Common::StringView name) { + insertOrPush(*chain.back(), name, value); + return true; } -ISerializer& JsonOutputStreamSerializer::operator()(uint8_t& value, const std::string& name) { - uint64_t v = static_cast(value); - return operator()(v, name); +bool JsonOutputStreamSerializer::operator()(uint8_t& value, Common::StringView name) { + insertOrPush(*chain.back(), name, static_cast(value)); + return true; } -ISerializer& JsonOutputStreamSerializer::operator()(bool& value, const std::string& name) { - JsonValue* val = chain.back(); - if (val->isArray()) { - val->pushBack(JsonValue(value)); - } else { - val->insert(name, JsonValue(value)); - } - - return *this; +bool JsonOutputStreamSerializer::operator()(bool& value, Common::StringView name) { + insertOrPush(*chain.back(), name, value); + return true; } -ISerializer& JsonOutputStreamSerializer::binary(void* value, std::size_t size, const std::string& name) { - auto hex = Common::toHex(value, size); +bool JsonOutputStreamSerializer::binary(void* value, std::size_t size, Common::StringView name) { + std::string hex = Common::toHex(value, size); return (*this)(hex, name); } -ISerializer& JsonOutputStreamSerializer::binary(std::string& value, const std::string& name) { +bool JsonOutputStreamSerializer::binary(std::string& value, Common::StringView name) { return binary(const_cast(value.data()), value.size(), name); } - -bool JsonOutputStreamSerializer::hasObject(const std::string& name) { - assert(false); - throw std::runtime_error("JsonOutputStreamSerializer doesn't support this type of serialization"); - - return false; -} diff --git a/src/serialization/JsonOutputStreamSerializer.h b/src/serialization/JsonOutputStreamSerializer.h index 665350b7..bea003d9 100644 --- a/src/serialization/JsonOutputStreamSerializer.h +++ b/src/serialization/JsonOutputStreamSerializer.h @@ -28,34 +28,34 @@ public: JsonOutputStreamSerializer(); virtual ~JsonOutputStreamSerializer(); - Common::JsonValue getJsonValue() const; SerializerType type() const; - virtual ISerializer& beginObject(const std::string& name) override; - virtual ISerializer& endObject() override; + virtual bool beginObject(Common::StringView name) override; + virtual void endObject() override; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override; - virtual ISerializer& endArray() override; + virtual bool beginArray(std::size_t& size, Common::StringView name) override; + virtual void endArray() override; - virtual ISerializer& operator()(int32_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint32_t& value, const std::string& name) override; - virtual ISerializer& operator()(int64_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) override; - virtual ISerializer& operator()(double& value, const std::string& name) override; - virtual ISerializer& operator()(std::string& value, const std::string& name) override; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) override; - virtual ISerializer& operator()(bool& value, const std::string& name) override; - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; - - virtual bool hasObject(const std::string& name) override; + virtual bool operator()(uint8_t& value, Common::StringView name) override; + virtual bool operator()(int32_t& value, Common::StringView name) override; + virtual bool operator()(uint32_t& value, Common::StringView name) override; + virtual bool operator()(int64_t& value, Common::StringView name) override; + virtual bool operator()(uint64_t& value, Common::StringView name) override; + virtual bool operator()(double& value, Common::StringView name) override; + virtual bool operator()(bool& value, Common::StringView name) override; + virtual bool operator()(std::string& value, Common::StringView name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; template - ISerializer& operator()(T& value, const std::string& name) { + bool operator()(T& value, Common::StringView name) { return ISerializer::operator()(value, name); } + const Common::JsonValue& getValue() const { + return root; + } + friend std::ostream& operator<<(std::ostream& out, const JsonOutputStreamSerializer& enumerator); private: diff --git a/src/serialization/KVBinaryInputStreamSerializer.cpp b/src/serialization/KVBinaryInputStreamSerializer.cpp index 58ca3f79..f6e27208 100644 --- a/src/serialization/KVBinaryInputStreamSerializer.cpp +++ b/src/serialization/KVBinaryInputStreamSerializer.cpp @@ -27,19 +27,23 @@ using namespace CryptoNote; namespace { +void strictRead(std::istream& s, void* ptr, size_t size) { + if (s.read(reinterpret_cast(ptr), size).gcount() != size) { + throw std::runtime_error("read error"); + } +} + template T readPod(std::istream& s) { T v; - s.read(reinterpret_cast(&v), sizeof(T)); + strictRead(s, &v, sizeof(T)); return v; } template JsonValue readPodJson(std::istream& s) { - T v; - s.read(reinterpret_cast(&v), sizeof(T)); JsonValue jv; - jv = static_cast(v); + jv = static_cast(readPod(s)); return jv; } @@ -77,77 +81,44 @@ std::string readString(std::istream& s) { auto size = readVarint(s); std::string str; str.resize(size); - s.read(&str[0], size); + if (size) { + strictRead(s, &str[0], size); + } return str; } JsonValue readStringJson(std::istream& s) { - JsonValue js; - js = readString(s); - return js; + return JsonValue(readString(s)); } void readName(std::istream& s, std::string& name) { uint8_t len = readPod(s); - name.resize(len); - s.read(&name[0], len); -} - -} - -void KVBinaryInputStreamSerializer::parse() { - auto hdr = readPod(stream); - - if ( - hdr.m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - hdr.m_signature_b != PORTABLE_STORAGE_SIGNATUREB) { - throw std::runtime_error("Invalid binary storage signature"); + if (len) { + name.resize(len); + strictRead(s, &name[0], len); } - - if (hdr.m_ver != PORTABLE_STORAGE_FORMAT_VER) { - throw std::runtime_error("Unknown binary storage format version"); - } - - root.reset(new JsonValue(loadSection())); - setJsonValue(root.get()); } -ISerializer& KVBinaryInputStreamSerializer::binary(void* value, std::size_t size, const std::string& name) { - std::string str; +JsonValue loadValue(std::istream& stream, uint8_t type); +JsonValue loadSection(std::istream& stream); +JsonValue loadEntry(std::istream& stream); +JsonValue loadArray(std::istream& stream, uint8_t itemType); - (*this)(str, name); - if (str.size() != size) { - throw std::runtime_error("Binary block size mismatch"); - } - - memcpy(value, str.data(), size); - return *this; -} - -ISerializer& KVBinaryInputStreamSerializer::binary(std::string& value, const std::string& name) { - if (!hasObject(name)) { - value.clear(); - return *this; - } - - return (*this)(value, name); // load as string -} - -JsonValue KVBinaryInputStreamSerializer::loadSection() { +JsonValue loadSection(std::istream& stream) { JsonValue sec(JsonValue::OBJECT); size_t count = readVarint(stream); std::string name; while (count--) { readName(stream, name); - sec.insert(name, loadEntry()); + sec.insert(name, loadEntry(stream)); } return sec; } -JsonValue KVBinaryInputStreamSerializer::loadValue(uint8_t type) { +JsonValue loadValue(std::istream& stream, uint8_t type) { switch (type) { case BIN_KV_SERIALIZE_TYPE_INT64: return readIntegerJson(stream); case BIN_KV_SERIALIZE_TYPE_INT32: return readIntegerJson(stream); @@ -160,32 +131,74 @@ JsonValue KVBinaryInputStreamSerializer::loadValue(uint8_t type) { case BIN_KV_SERIALIZE_TYPE_DOUBLE: return readPodJson(stream); case BIN_KV_SERIALIZE_TYPE_BOOL: return JsonValue(stream.get() != 0); case BIN_KV_SERIALIZE_TYPE_STRING: return readStringJson(stream); - case BIN_KV_SERIALIZE_TYPE_OBJECT: return loadSection(); - case BIN_KV_SERIALIZE_TYPE_ARRAY: return loadArray(type); + case BIN_KV_SERIALIZE_TYPE_OBJECT: return loadSection(stream); + case BIN_KV_SERIALIZE_TYPE_ARRAY: return loadArray(stream, type); default: throw std::runtime_error("Unknown data type"); break; } } -JsonValue KVBinaryInputStreamSerializer::loadEntry() { +JsonValue loadEntry(std::istream& stream) { uint8_t type = readPod(stream); if (type & BIN_KV_SERIALIZE_FLAG_ARRAY) { type &= ~BIN_KV_SERIALIZE_FLAG_ARRAY; - return loadArray(type); + return loadArray(stream, type); } - return loadValue(type); + return loadValue(stream, type); } -JsonValue KVBinaryInputStreamSerializer::loadArray(uint8_t itemType) { +JsonValue loadArray(std::istream& stream, uint8_t itemType) { JsonValue arr(JsonValue::ARRAY); size_t count = readVarint(stream); while (count--) { - arr.pushBack(loadValue(itemType)); + arr.pushBack(loadValue(stream, itemType)); } return arr; } + + +JsonValue parseBinary(std::istream& stream) { + auto hdr = readPod(stream); + + if ( + hdr.m_signature_a != PORTABLE_STORAGE_SIGNATUREA || + hdr.m_signature_b != PORTABLE_STORAGE_SIGNATUREB) { + throw std::runtime_error("Invalid binary storage signature"); + } + + if (hdr.m_ver != PORTABLE_STORAGE_FORMAT_VER) { + throw std::runtime_error("Unknown binary storage format version"); + } + + return loadSection(stream); +} + +} + +KVBinaryInputStreamSerializer::KVBinaryInputStreamSerializer(std::istream& strm) : value(parseBinary(strm)), JsonInputValueSerializer(value) { +} + +bool KVBinaryInputStreamSerializer::binary(void* value, std::size_t size, Common::StringView name) { + std::string str; + + if (!(*this)(str, name)) { + return false; + } + + if (str.size() != size) { + throw std::runtime_error("Binary block size mismatch"); + } + + memcpy(value, str.data(), size); + return true; +} + +bool KVBinaryInputStreamSerializer::binary(std::string& value, Common::StringView name) { + return (*this)(value, name); // load as string +} + diff --git a/src/serialization/KVBinaryInputStreamSerializer.h b/src/serialization/KVBinaryInputStreamSerializer.h index ee922b41..6fe29628 100644 --- a/src/serialization/KVBinaryInputStreamSerializer.h +++ b/src/serialization/KVBinaryInputStreamSerializer.h @@ -18,32 +18,21 @@ #pragma once #include -#include -#include "../Common/JsonValue.h" #include "ISerializer.h" #include "JsonInputValueSerializer.h" -#include "SerializationOverloads.h" namespace CryptoNote { class KVBinaryInputStreamSerializer : public JsonInputValueSerializer { public: - KVBinaryInputStreamSerializer(std::istream& strm) : stream(strm) {} - virtual ~KVBinaryInputStreamSerializer() {} + KVBinaryInputStreamSerializer(std::istream& strm); - void parse(); - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; private: - std::unique_ptr root; - std::istream& stream; - Common::JsonValue loadSection(); - Common::JsonValue loadEntry(); - Common::JsonValue loadValue(uint8_t type); - Common::JsonValue loadArray(uint8_t itemType); + Common::JsonValue value; }; } diff --git a/src/serialization/KVBinaryOutputStreamSerializer.cpp b/src/serialization/KVBinaryOutputStreamSerializer.cpp index 479ddfd1..37c77f69 100644 --- a/src/serialization/KVBinaryOutputStreamSerializer.cpp +++ b/src/serialization/KVBinaryOutputStreamSerializer.cpp @@ -25,6 +25,18 @@ using namespace CryptoNote; namespace { +class StdOutputStream : public IOutputStream { +public: + StdOutputStream(std::ostream& s) : stream(s) {} + + virtual void write(const char* data, std::size_t size) override { + stream.write(data, size); + } + +private: + std::ostream& stream; +}; + template void writePod(IOutputStream& s, const T& value) { s.write((const char*)&value, sizeof(T)); @@ -38,13 +50,14 @@ size_t packVarint(IOutputStream& s, uint8_t type_or, size_t pv) { return sizeof(T); } -void writeElementName(IOutputStream& s, const std::string& name) { - if (name.size() > std::numeric_limits::max()) { +void writeElementName(IOutputStream& s, Common::StringView name) { + if (name.getSize() > std::numeric_limits::max()) { throw std::runtime_error("Element name is too long"); } - uint8_t len = static_cast(name.size()); + + uint8_t len = static_cast(name.getSize()); s.write((const char*)&len, sizeof(len)); - s.write(name.data(), len); + s.write(name.getData(), len); } size_t writeArraySize(IOutputStream& s, size_t val) { @@ -86,6 +99,8 @@ void KVBinaryOutputStreamSerializer::write(std::ostream& target) { hdr.m_ver = PORTABLE_STORAGE_FORMAT_VER; target.write(reinterpret_cast(&hdr), sizeof(hdr)); + StdOutputStream stdstream(target); + writeArraySize(stdstream, m_stack.front().count); target.write(stream().data(), stream().size()); } @@ -93,16 +108,16 @@ ISerializer::SerializerType KVBinaryOutputStreamSerializer::type() const { return ISerializer::OUTPUT; } -ISerializer& KVBinaryOutputStreamSerializer::beginObject(const std::string& name) { +bool KVBinaryOutputStreamSerializer::beginObject(Common::StringView name) { checkArrayPreamble(BIN_KV_SERIALIZE_TYPE_OBJECT); m_stack.push_back(Level(name)); m_objectsStack.push_back(MemoryStream()); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::endObject() { +void KVBinaryOutputStreamSerializer::endObject() { assert(m_objectsStack.size()); auto level = std::move(m_stack.back()); @@ -117,106 +132,95 @@ ISerializer& KVBinaryOutputStreamSerializer::endObject() { writeArraySize(out, level.count); out.write(objStream.data(), objStream.size()); - - return *this; } -ISerializer& KVBinaryOutputStreamSerializer::beginArray(std::size_t& size, const std::string& name) { +bool KVBinaryOutputStreamSerializer::beginArray(std::size_t& size, Common::StringView name) { m_stack.push_back(Level(name, size)); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::endArray() { +void KVBinaryOutputStreamSerializer::endArray() { bool validArray = m_stack.back().state == State::Array; m_stack.pop_back(); if (m_stack.back().state == State::Object && validArray) { ++m_stack.back().count; } - - return *this; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(uint8_t& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(uint8_t& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_UINT8, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(uint32_t& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_UINT32, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(int32_t& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(int32_t& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_INT32, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(int64_t& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(int64_t& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_INT64, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(uint64_t& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(uint64_t& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_UINT64, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(bool& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(bool& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_BOOL, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(double& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(double& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_DOUBLE, name); writePod(stream(), value); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::operator()(std::string& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::operator()(std::string& value, Common::StringView name) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_STRING, name); auto& out = stream(); writeArraySize(out, value.size()); out.write(value.data(), value.size()); - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::binary(void* value, std::size_t size, const std::string& name) { +bool KVBinaryOutputStreamSerializer::binary(void* value, std::size_t size, Common::StringView name) { if (size > 0) { writeElementPrefix(BIN_KV_SERIALIZE_TYPE_STRING, name); auto& out = stream(); writeArraySize(out, size); out.write(static_cast(value), size); } - return *this; + return true; } -ISerializer& KVBinaryOutputStreamSerializer::binary(std::string& value, const std::string& name) { +bool KVBinaryOutputStreamSerializer::binary(std::string& value, Common::StringView name) { return binary(const_cast(value.data()), value.size(), name); } -bool KVBinaryOutputStreamSerializer::hasObject(const std::string& name) { - assert(false); //the method is not supported for this type of serialization - throw std::runtime_error("hasObject method is not supported in KVBinaryOutputStreamSerializer"); - - return false; -} - -void KVBinaryOutputStreamSerializer::writeElementPrefix(uint8_t type, const std::string& name) { +void KVBinaryOutputStreamSerializer::writeElementPrefix(uint8_t type, Common::StringView name) { assert(m_stack.size()); checkArrayPreamble(type); Level& level = m_stack.back(); if (level.state != State::Array) { - if (!name.empty()) { + if (!name.isEmpty()) { auto& s = stream(); writeElementName(s, name); s.write((const char*)&type, 1); diff --git a/src/serialization/KVBinaryOutputStreamSerializer.h b/src/serialization/KVBinaryOutputStreamSerializer.h index 86d3eec0..70fb43d9 100644 --- a/src/serialization/KVBinaryOutputStreamSerializer.h +++ b/src/serialization/KVBinaryOutputStreamSerializer.h @@ -18,7 +18,6 @@ #pragma once #include "ISerializer.h" -#include "SerializationOverloads.h" #include "MemoryStream.h" #include @@ -38,34 +37,31 @@ public: virtual ISerializer::SerializerType type() const; - virtual ISerializer& beginObject(const std::string& name) override; - virtual ISerializer& endObject() override; + virtual bool beginObject(Common::StringView name) override; + virtual void endObject() override; - virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override; - virtual ISerializer& endArray() override; + virtual bool beginArray(std::size_t& size, Common::StringView name) override; + virtual void endArray() override; - virtual ISerializer& operator()(uint8_t& value, const std::string& name) override; - virtual ISerializer& operator()(int32_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint32_t& value, const std::string& name) override; - virtual ISerializer& operator()(int64_t& value, const std::string& name) override; - virtual ISerializer& operator()(uint64_t& value, const std::string& name) override; - virtual ISerializer& operator()(double& value, const std::string& name) override; - virtual ISerializer& operator()(bool& value, const std::string& name) override; - virtual ISerializer& operator()(std::string& value, const std::string& name) override; - - virtual ISerializer& binary(void* value, std::size_t size, const std::string& name) override; - virtual ISerializer& binary(std::string& value, const std::string& name) override; - - virtual bool hasObject(const std::string& name) override; + virtual bool operator()(uint8_t& value, Common::StringView name) override; + virtual bool operator()(int32_t& value, Common::StringView name) override; + virtual bool operator()(uint32_t& value, Common::StringView name) override; + virtual bool operator()(int64_t& value, Common::StringView name) override; + virtual bool operator()(uint64_t& value, Common::StringView name) override; + virtual bool operator()(double& value, Common::StringView name) override; + virtual bool operator()(bool& value, Common::StringView name) override; + virtual bool operator()(std::string& value, Common::StringView name) override; + virtual bool binary(void* value, std::size_t size, Common::StringView name) override; + virtual bool binary(std::string& value, Common::StringView name) override; template - ISerializer& operator()(T& value, const std::string& name) { + bool operator()(T& value, Common::StringView name) { return ISerializer::operator()(value, name); } private: - void writeElementPrefix(uint8_t type, const std::string& name); + void writeElementPrefix(uint8_t type, Common::StringView name); void checkArrayPreamble(uint8_t type); void updateState(uint8_t type); MemoryStream& stream(); @@ -82,10 +78,10 @@ private: std::string name; size_t count; - Level(const std::string& nm) : + Level(Common::StringView nm) : name(nm), state(State::Object), count(0) {} - Level(const std::string& nm, size_t arraySize) : + Level(Common::StringView nm, size_t arraySize) : name(nm), state(State::ArrayPrefix), count(arraySize) {} Level(Level&& rv) { diff --git a/src/serialization/SerializationOverloads.h b/src/serialization/SerializationOverloads.h index 921e9e52..71ddf046 100644 --- a/src/serialization/SerializationOverloads.h +++ b/src/serialization/SerializationOverloads.h @@ -29,8 +29,8 @@ namespace CryptoNote { template -typename std::enable_if::value>::type -serializeAsBinary(std::vector& value, const std::string& name, CryptoNote::ISerializer& serializer) { +typename std::enable_if::value>::type +serializeAsBinary(std::vector& value, Common::StringView name, CryptoNote::ISerializer& serializer) { std::string blob; if (serializer.type() == ISerializer::INPUT) { serializer.binary(blob, name); @@ -47,9 +47,39 @@ serializeAsBinary(std::vector& value, const std::string& name, CryptoNote::IS } template -void serialize(std::vector& value, const std::string& name, CryptoNote::ISerializer& serializer) { +typename std::enable_if::value>::type +serializeAsBinary(std::list& value, Common::StringView name, CryptoNote::ISerializer& serializer) { + std::string blob; + if (serializer.type() == ISerializer::INPUT) { + serializer.binary(blob, name); + + size_t count = blob.size() / sizeof(T); + const T* ptr = reinterpret_cast(blob.data()); + + while (count--) { + value.push_back(*ptr++); + } + } else { + if (!value.empty()) { + blob.resize(value.size() * sizeof(T)); + T* ptr = reinterpret_cast(&blob[0]); + + for (const auto& item : value) { + *ptr++ = item; + } + } + serializer.binary(blob, name); + } +} + +template +bool serializeContainer(Cont& value, Common::StringView name, CryptoNote::ISerializer& serializer) { std::size_t size = value.size(); - serializer.beginArray(size, name); + if (!serializer.beginArray(size, name)) { + value.clear(); + return false; + } + value.resize(size); for (auto& item : value) { @@ -57,28 +87,29 @@ void serialize(std::vector& value, const std::string& name, CryptoNote::ISeri } serializer.endArray(); + return true; } template -void serialize(std::list& value, const std::string& name, CryptoNote::ISerializer& serializer) { - std::size_t size = value.size(); - serializer.beginArray(size, name); - value.resize(size); +bool serialize(std::vector& value, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializeContainer(value, name, serializer); +} - for (auto& item : value) { - serializer(item, ""); - } - - serializer.endArray(); +template +bool serialize(std::list& value, Common::StringView name, CryptoNote::ISerializer& serializer) { + return serializeContainer(value, name, serializer); } template -void serialize(std::unordered_map& value, const std::string& name, CryptoNote::ISerializer& serializer) { +bool serialize(std::unordered_map& value, Common::StringView name, CryptoNote::ISerializer& serializer) { std::size_t size; size = value.size(); - serializer.beginArray(size, name); + if (!serializer.beginArray(size, name)) { + value.clear(); + return false; + } if (serializer.type() == CryptoNote::ISerializer::INPUT) { value.reserve(size); @@ -105,11 +136,12 @@ void serialize(std::unordered_map& value, const std::string& name, C } serializer.endArray(); + return true; } template -void serialize(std::array& value, const std::string& name, CryptoNote::ISerializer& s) { - s.binary(value.data(), value.size(), name); +bool serialize(std::array& value, Common::StringView name, CryptoNote::ISerializer& s) { + return s.binary(value.data(), value.size(), name); } } diff --git a/src/serialization/SerializationTools.h b/src/serialization/SerializationTools.h new file mode 100644 index 00000000..dc314c70 --- /dev/null +++ b/src/serialization/SerializationTools.h @@ -0,0 +1,134 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#pragma once + +#include "KVBinaryInputStreamSerializer.h" +#include "KVBinaryOutputStreamSerializer.h" + +#include "JsonInputStreamSerializer.h" +#include "JsonOutputStreamSerializer.h" + +namespace Common { + +template +T getValueAs(const JsonValue& js) { + return js; + //cdstatic_assert(false, "undefined conversion"); +} + +template <> +inline std::string getValueAs(const JsonValue& js) { return js.getString(); } + +template <> +inline uint64_t getValueAs(const JsonValue& js) { return static_cast(js.getInteger()); } + + +} + +namespace CryptoNote { + +template +Common::JsonValue storeToJsonValue(const T& v) { + JsonOutputStreamSerializer s; + serialize(const_cast(v), s); + return s.getValue(); +} + +template +Common::JsonValue storeContainerToJsonValue(const T& cont) { + Common::JsonValue js(Common::JsonValue::ARRAY); + for (const auto& item : cont) { + js.pushBack(item); + } + return js; +} + +template +Common::JsonValue storeToJsonValue(const std::vector& v) { return storeContainerToJsonValue(v); } + +template +Common::JsonValue storeToJsonValue(const std::list& v) { return storeContainerToJsonValue(v); } + +template <> +inline Common::JsonValue storeToJsonValue(const std::string& v) { return Common::JsonValue(v); } + + +template +void loadFromJsonValue(T& v, const Common::JsonValue& js) { + JsonInputValueSerializer s(js); + serialize(v, s); +} + +template +void loadFromJsonValue(std::vector& v, const Common::JsonValue& js) { + for (size_t i = 0; i < js.size(); ++i) { + v.push_back(Common::getValueAs(js[i])); + } +} + +template +void loadFromJsonValue(std::list& v, const Common::JsonValue& js) { + for (size_t i = 0; i < js.size(); ++i) { + v.push_back(Common::getValueAs(js[i])); + } +} + + +template +std::string storeToJson(const T& v) { + return storeToJsonValue(v).toString(); +} + +template +bool loadFromJson(T& v, const std::string& buf) { + try { + if (buf.empty()) { + return true; + } + auto js = Common::JsonValue::fromString(buf); + loadFromJsonValue(v, js); + } catch (std::exception&) { + return false; + } + return true; +} + +template +std::string storeToBinaryKeyValue(const T& v) { + KVBinaryOutputStreamSerializer s; + serialize(const_cast(v), s); + + std::ostringstream stream; + s.write(stream); + return stream.str(); +} + +template +bool loadFromBinaryKeyValue(T& v, const std::string& buf) { + try { + std::istringstream stream(buf); + KVBinaryInputStreamSerializer s(stream); + serialize(v, s); + return stream.good(); + } catch (std::exception&) { + return false; + } +} + + +} diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 69c01847..5dcbdc04 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -17,11 +17,13 @@ #include "simplewallet.h" +#include #include #include #include #include +#include #include #include #include @@ -57,7 +59,7 @@ using Common::JsonValue; namespace po = boost::program_options; #define EXTENDED_LOGS_FILE "wallet_details.log" - +#undef ERROR namespace { diff --git a/src/transfers/TransfersContainer.cpp b/src/transfers/TransfersContainer.cpp index 4a0a827d..ed469165 100644 --- a/src/transfers/TransfersContainer.cpp +++ b/src/transfers/TransfersContainer.cpp @@ -24,7 +24,7 @@ namespace CryptoNote { -void serialize(TransactionInformation& ti, const std::string& name, CryptoNote::ISerializer& s) { +void serialize(TransactionInformation& ti, CryptoNote::ISerializer& s) { s(ti.transactionHash, ""); s(ti.publicKey, ""); s(ti.blockHeight, ""); @@ -99,7 +99,9 @@ SpentOutputDescriptor::SpentOutputDescriptor() : } SpentOutputDescriptor::SpentOutputDescriptor(const TransactionOutputInformationIn& transactionInfo) : - m_type(transactionInfo.type) { + m_type(transactionInfo.type), + m_amount(0), + m_globalOutputIndex(0) { if (m_type == TransactionTypes::OutputType::Key) { m_keyImage = &transactionInfo.keyImage; } else if (m_type == TransactionTypes::OutputType::Multisignature) { @@ -212,6 +214,7 @@ void TransfersContainer::addTransaction(const BlockInfo& block, const ITransacti } auto result = m_transactions.emplace(std::move(txInfo)); + (void)result; // Disable unused warning assert(result.second); } @@ -244,6 +247,7 @@ bool TransfersContainer::addTransactionOutputs(const BlockInfo& block, const ITr if (transferIsUnconfirmed) { auto result = m_unconfirmedTransfers.emplace(std::move(info)); + (void)result; // Disable unused warning assert(result.second); } else { if (info.type == TransactionTypes::OutputType::Multisignature) { @@ -255,6 +259,7 @@ bool TransfersContainer::addTransactionOutputs(const BlockInfo& block, const ITr } auto result = m_availableTransfers.emplace(std::move(info)); + (void)result; // Disable unused warning assert(result.second); } @@ -400,6 +405,7 @@ bool TransfersContainer::markTransactionConfirmed(const BlockInfo& block, const } auto result = m_availableTransfers.emplace(std::move(transfer)); + (void)result; // Disable unused warning assert(result.second); transferIt = m_unconfirmedTransfers.get().erase(transferIt); @@ -479,6 +485,7 @@ void TransfersContainer::copyToSpent(const BlockInfo& block, const ITransactionR spentOutput.spendingTransactionHash = tx.getTransactionHash(); spentOutput.inputInTransaction = static_cast(inputIndex); auto result = m_spentTransfers.emplace(std::move(spentOutput)); + (void)result; // Disable unused warning assert(result.second); } diff --git a/src/transfers/TransfersContainer.h b/src/transfers/TransfersContainer.h index fba0b269..72d4c17a 100644 --- a/src/transfers/TransfersContainer.h +++ b/src/transfers/TransfersContainer.h @@ -60,7 +60,7 @@ private: TransactionTypes::OutputType m_type; union { const KeyImage* m_keyImage; -struct { + struct { uint64_t m_amount; uint64_t m_globalOutputIndex; }; @@ -86,7 +86,7 @@ struct TransactionOutputInformationEx : public TransactionOutputInformationIn { SpentOutputDescriptor getSpentOutputDescriptor() const { return SpentOutputDescriptor(*this); } const Hash& getTransactionHash() const { return transactionHash; } - void serialize(CryptoNote::ISerializer& s, const std::string& name) { + void serialize(CryptoNote::ISerializer& s) { s(reinterpret_cast(type), "type"); s(amount, ""); s(globalOutputIndex, ""); @@ -112,7 +112,7 @@ struct BlockInfo { uint64_t timestamp; uint32_t transactionIndex; - void serialize(ISerializer& s, const std::string& name) { + void serialize(ISerializer& s) { s(height, "height"); s(timestamp, "timestamp"); s(transactionIndex, "transactionIndex"); @@ -128,8 +128,8 @@ struct SpentTransactionOutput : TransactionOutputInformationEx { return spendingTransactionHash; } - void serialize(ISerializer& s, const std::string& name) { - TransactionOutputInformationEx::serialize(s, name); + void serialize(ISerializer& s) { + TransactionOutputInformationEx::serialize(s); s(spendingBlock, "spendingBlock"); s(spendingTransactionHash, "spendingTransactionHash"); s(inputInTransaction, "inputInTransaction"); diff --git a/src/transfers/TransfersSubscription.cpp b/src/transfers/TransfersSubscription.cpp index 12dcbeaf..cb2309ce 100644 --- a/src/transfers/TransfersSubscription.cpp +++ b/src/transfers/TransfersSubscription.cpp @@ -21,7 +21,7 @@ namespace CryptoNote { TransfersSubscription::TransfersSubscription(const CryptoNote::Currency& currency, const AccountSubscription& sub) - : m_currency(currency), m_subscription(sub), m_transfers(currency, sub.transactionSpendableAge) {} + : m_subscription(sub), m_transfers(currency, sub.transactionSpendableAge) {} SynchronizationStart TransfersSubscription::getSyncStart() { diff --git a/src/transfers/TransfersSubscription.h b/src/transfers/TransfersSubscription.h index 67ff9076..da3630dc 100644 --- a/src/transfers/TransfersSubscription.h +++ b/src/transfers/TransfersSubscription.h @@ -25,7 +25,6 @@ namespace CryptoNote { class TransfersSubscription : public IObservableImpl < ITransfersObserver, ITransfersSubscription > { public: - TransfersSubscription(const CryptoNote::Currency& currency, const AccountSubscription& sub); SynchronizationStart getSyncStart(); @@ -33,8 +32,8 @@ public: void onError(const std::error_code& ec, uint64_t height); bool advanceHeight(uint64_t height); const AccountKeys& getKeys() const; - void addTransaction(const BlockInfo& blockInfo, - const ITransactionReader& tx, const std::vector& transfers); + void addTransaction(const BlockInfo& blockInfo, const ITransactionReader& tx, + const std::vector& transfers); void deleteUnconfirmedTransaction(const Hash& transactionHash); void markTransactionConfirmed(const BlockInfo& block, const Hash& transactionHash, const std::vector& globalIndices); @@ -44,10 +43,8 @@ public: virtual ITransfersContainer& getContainer() override; private: - TransfersContainer m_transfers; AccountSubscription m_subscription; - const CryptoNote::Currency& m_currency; }; } diff --git a/src/transfers/TransfersSynchronizer.cpp b/src/transfers/TransfersSynchronizer.cpp index ea5aaabc..3dafa027 100644 --- a/src/transfers/TransfersSynchronizer.cpp +++ b/src/transfers/TransfersSynchronizer.cpp @@ -23,11 +23,9 @@ namespace CryptoNote { -void serialize(AccountAddress& acc, const std::string& name, CryptoNote::ISerializer& s) { - s.beginObject(name); +void serialize(AccountAddress& acc, CryptoNote::ISerializer& s) { s(acc.spendPublicKey, "spendKey"); s(acc.viewPublicKey, "viewKey"); - s.endObject(); } const uint32_t TRANSFERS_STORAGE_ARCHIVE_VERSION = 0; diff --git a/src/version.h.in b/src/version.h.in index 7a7edafc..ff691919 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define BUILD_COMMIT_ID "@VERSION@" -#define PROJECT_VERSION "1.0.4.1" -#define PROJECT_VERSION_BUILD_NO "466" +#define PROJECT_VERSION "1.0.5" +#define PROJECT_VERSION_BUILD_NO "503" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" diff --git a/src/wallet/LegacyKeysImporter.cpp b/src/wallet/LegacyKeysImporter.cpp index 33605313..44110f34 100755 --- a/src/wallet/LegacyKeysImporter.cpp +++ b/src/wallet/LegacyKeysImporter.cpp @@ -24,11 +24,9 @@ #include "cryptonote_core/Currency.h" #include "cryptonote_core/account.h" -#include "cryptonote_core/AccountKVSerialization.h" #include "serialization/binary_utils.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" +#include "serialization/SerializationTools.h" #include "wallet/WalletSerializer.h" #include "wallet/WalletUserTransactionsCache.h" @@ -71,15 +69,15 @@ void loadKeysFromFile(const std::string& filename, const std::string& password, account_data.resize(keys_file_data.account_data.size()); crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); - const ::CryptoNote::account_keys& keys = account.get_keys(); - CryptoNote::AccountBaseSerializer accountSerializer(account); - bool r = epee::serialization::load_t_from_binary(accountSerializer, account_data); - r = r && verify_keys(keys.m_view_secret_key, keys.m_account_address.m_viewPublicKey); - r = r && verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spendPublicKey); + const CryptoNote::account_keys& keys = account.get_keys(); - if (!r) { - throw std::system_error(make_error_code(CryptoNote::error::WRONG_PASSWORD)); + if (CryptoNote::loadFromBinaryKeyValue(account, account_data) && + verify_keys(keys.m_view_secret_key, keys.m_account_address.m_viewPublicKey) && + verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spendPublicKey)) { + return; } + + throw std::system_error(make_error_code(CryptoNote::error::WRONG_PASSWORD)); } } diff --git a/src/wallet/Wallet.cpp b/src/wallet/Wallet.cpp index d1ce67ca..6d047e59 100755 --- a/src/wallet/Wallet.cpp +++ b/src/wallet/Wallet.cpp @@ -40,11 +40,6 @@ bool verifyKeys(const crypto::secret_key& sec, const crypto::public_key& expecte return r && expected_pub == pub; } -void throwIfKeysMissmatch(const crypto::secret_key& sec, const crypto::public_key& expected_pub) { - if (!verifyKeys(sec, expected_pub)) - throw std::system_error(make_error_code(CryptoNote::error::WRONG_PASSWORD)); -} - class ContextCounterHolder { public: diff --git a/src/wallet/WalletSerialization.cpp b/src/wallet/WalletSerialization.cpp index a79ac6cc..6246c2bd 100644 --- a/src/wallet/WalletSerialization.cpp +++ b/src/wallet/WalletSerialization.cpp @@ -25,8 +25,7 @@ namespace CryptoNote { -void serialize(UnconfirmedTransferDetails& utd, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); +void serialize(UnconfirmedTransferDetails& utd, CryptoNote::ISerializer& serializer) { serializer(utd.tx, "transaction"); serializer(utd.amount, "amount"); serializer(utd.outsAmount, "outs_amount"); @@ -36,12 +35,9 @@ void serialize(UnconfirmedTransferDetails& utd, const std::string& name, CryptoN uint64_t txId = static_cast(utd.transactionId); serializer(txId, "transaction_id"); utd.transactionId = static_cast(txId); - serializer.endObject(); } -void serialize(TransactionInfo& txi, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - +void serialize(TransactionInfo& txi, CryptoNote::ISerializer& serializer) { uint64_t trId = static_cast(txi.firstTransferId); serializer(trId, "first_transfer_id"); txi.firstTransferId = static_cast(trId); @@ -59,14 +55,11 @@ void serialize(TransactionInfo& txi, const std::string& name, CryptoNote::ISeria serializer(txi.timestamp, "timestamp"); serializer(txi.unlockTime, "unlock_time"); serializer(txi.extra, "extra"); - serializer.endObject(); } -void serialize(Transfer& tr, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); +void serialize(Transfer& tr, CryptoNote::ISerializer& serializer) { serializer(tr.address, "address"); serializer(tr.amount, "amount"); - serializer.endObject(); } } //namespace CryptoNote diff --git a/src/wallet/WalletSerialization.h b/src/wallet/WalletSerialization.h index aef7e9b9..85a0f240 100755 --- a/src/wallet/WalletSerialization.h +++ b/src/wallet/WalletSerialization.h @@ -25,16 +25,13 @@ namespace CryptoNote { class ISerializer; -} - -namespace CryptoNote { struct UnconfirmedTransferDetails; struct TransactionInfo; struct Transfer; -void serialize(UnconfirmedTransferDetails& utd, const std::string& name, CryptoNote::ISerializer& serializer); -void serialize(TransactionInfo& txi, const std::string& name, CryptoNote::ISerializer& serializer); -void serialize(Transfer& tr, const std::string& name, CryptoNote::ISerializer& serializer); +void serialize(UnconfirmedTransferDetails& utd, ISerializer& serializer); +void serialize(TransactionInfo& txi, ISerializer& serializer); +void serialize(Transfer& tr, ISerializer& serializer); } diff --git a/src/wallet/WalletTransactionSender.cpp b/src/wallet/WalletTransactionSender.cpp index 95dec268..53eee3b6 100644 --- a/src/wallet/WalletTransactionSender.cpp +++ b/src/wallet/WalletTransactionSender.cpp @@ -316,7 +316,11 @@ namespace { template T popRandomValue(URNG& randomGenerator, std::vector& vec) { - CHECK_AND_ASSERT_MES(!vec.empty(), T(), "Vector must be non-empty"); + assert(!vec.empty()); + + if (vec.empty()) { + return T(); + } std::uniform_int_distribution distribution(0, vec.size() - 1); size_t idx = distribution(randomGenerator); diff --git a/src/wallet/WalletUnconfirmedTransactions.cpp b/src/wallet/WalletUnconfirmedTransactions.cpp index 44dde435..da528c7d 100644 --- a/src/wallet/WalletUnconfirmedTransactions.cpp +++ b/src/wallet/WalletUnconfirmedTransactions.cpp @@ -28,14 +28,12 @@ inline TransactionOutputId getOutputId(const TransactionOutputInformation& out) return std::make_pair(out.transactionPublicKey, out.outputInTransaction); } -void WalletUnconfirmedTransactions::serialize(CryptoNote::ISerializer& s, const std::string& name) { - s.beginObject(name); +bool WalletUnconfirmedTransactions::serialize(CryptoNote::ISerializer& s) { s(m_unconfirmedTxs, "transactions"); - s.endObject(); - if (s.type() == CryptoNote::ISerializer::INPUT) { collectUsedOutputs(); } + return true; } bool WalletUnconfirmedTransactions::findTransactionId(const TransactionHash& hash, TransactionId& id) { diff --git a/src/wallet/WalletUnconfirmedTransactions.h b/src/wallet/WalletUnconfirmedTransactions.h index a5b71152..0ccdf1c2 100644 --- a/src/wallet/WalletUnconfirmedTransactions.h +++ b/src/wallet/WalletUnconfirmedTransactions.h @@ -53,7 +53,7 @@ class WalletUnconfirmedTransactions { public: - void serialize(CryptoNote::ISerializer& s, const std::string& name); + bool serialize(CryptoNote::ISerializer& s); bool findTransactionId(const TransactionHash& hash, TransactionId& id); void erase(const TransactionHash& hash); diff --git a/src/wallet/WalletUserTransactionsCache.cpp b/src/wallet/WalletUserTransactionsCache.cpp index a1f0171c..27729880 100644 --- a/src/wallet/WalletUserTransactionsCache.cpp +++ b/src/wallet/WalletUserTransactionsCache.cpp @@ -27,9 +27,7 @@ namespace CryptoNote { -void WalletUserTransactionsCache::serialize(CryptoNote::ISerializer& s, const std::string& name) { - s.beginObject(name); - +bool WalletUserTransactionsCache::serialize(CryptoNote::ISerializer& s) { if (s.type() == CryptoNote::ISerializer::INPUT) { s(m_transactions, "transactions"); s(m_transfers, "transfers"); @@ -45,7 +43,7 @@ void WalletUserTransactionsCache::serialize(CryptoNote::ISerializer& s, const st s(m_unconfirmedTransactions, "unconfirmed"); } - s.endObject(); + return true; } uint64_t WalletUserTransactionsCache::unconfirmedTransactionsAmount() const { @@ -151,7 +149,7 @@ std::shared_ptr WalletUserTransactionsCache::onTransactionDeleted(c TransactionId id = CryptoNote::INVALID_TRANSACTION_ID; if (m_unconfirmedTransactions.findTransactionId(transactionHash, id)) { m_unconfirmedTransactions.erase(transactionHash); - LOG_ERROR("Unconfirmed transaction is deleted: id = " << id << ", hash = " << transactionHash); + // LOG_ERROR("Unconfirmed transaction is deleted: id = " << id << ", hash = " << transactionHash); assert(false); } else { id = findTransactionByHash(transactionHash); @@ -166,7 +164,7 @@ std::shared_ptr WalletUserTransactionsCache::onTransactionDeleted(c event = std::make_shared(id); } else { - LOG_ERROR("Transaction wasn't found: " << transactionHash); + // LOG_ERROR("Transaction wasn't found: " << transactionHash); assert(false); } diff --git a/src/wallet/WalletUserTransactionsCache.h b/src/wallet/WalletUserTransactionsCache.h index 1bdf9f9b..10faeca8 100644 --- a/src/wallet/WalletUserTransactionsCache.h +++ b/src/wallet/WalletUserTransactionsCache.h @@ -35,7 +35,7 @@ class WalletUserTransactionsCache public: WalletUserTransactionsCache() {} - void serialize(CryptoNote::ISerializer& serializer, const std::string& name); + bool serialize(CryptoNote::ISerializer& serializer); uint64_t unconfirmedTransactionsAmount() const; uint64_t unconfrimedOutsAmount() const; diff --git a/src/wallet/wallet_rpc_server_commans_defs.h b/src/wallet/wallet_rpc_server_commans_defs.h index d8144d20..8ef7be5a 100644 --- a/src/wallet/wallet_rpc_server_commans_defs.h +++ b/src/wallet/wallet_rpc_server_commans_defs.h @@ -20,30 +20,34 @@ #include "cryptonote_core/cryptonote_basic.h" #include "crypto/hash.h" #include "wallet_rpc_server_error_codes.h" + namespace tools { namespace wallet_rpc { + +using CryptoNote::ISerializer; + #define WALLET_RPC_STATUS_OK "OK" #define WALLET_RPC_STATUS_BUSY "BUSY" + struct EMPTY_STRUCT { + void serialize(ISerializer& s) {} + }; + struct COMMAND_RPC_GET_BALANCE { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + typedef EMPTY_STRUCT request; struct response { uint64_t locked_amount; uint64_t available_balance; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(locked_amount) - KV_SERIALIZE(available_balance) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(locked_amount) + KV_MEMBER(available_balance) + } }; }; @@ -51,10 +55,11 @@ namespace wallet_rpc { uint64_t amount; std::string address; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(address) - END_KV_SERIALIZE_MAP() + + void serialize(ISerializer& s) { + KV_MEMBER(amount) + KV_MEMBER(address) + } }; struct COMMAND_RPC_TRANSFER @@ -67,38 +72,29 @@ namespace wallet_rpc uint64_t unlock_time; std::string payment_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(destinations) - KV_SERIALIZE(fee) - KV_SERIALIZE(mixin) - KV_SERIALIZE(unlock_time) - KV_SERIALIZE(payment_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(destinations) + KV_MEMBER(fee) + KV_MEMBER(mixin) + KV_MEMBER(unlock_time) + KV_MEMBER(payment_id) + } }; struct response { std::string tx_hash; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_hash) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(tx_hash) + } }; }; struct COMMAND_RPC_STORE { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + typedef EMPTY_STRUCT request; + typedef EMPTY_STRUCT response; }; struct payment_details @@ -108,12 +104,12 @@ namespace wallet_rpc uint64_t block_height; uint64_t unlock_time; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_hash) - KV_SERIALIZE(amount) - KV_SERIALIZE(block_height) - KV_SERIALIZE(unlock_time) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(tx_hash) + KV_MEMBER(amount) + KV_MEMBER(block_height) + KV_MEMBER(unlock_time) + } }; struct COMMAND_RPC_GET_PAYMENTS @@ -122,18 +118,18 @@ namespace wallet_rpc { std::string payment_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(payment_id) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(payment_id) + } }; struct response { std::list payments; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(payments) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(payments) + } }; }; @@ -148,59 +144,46 @@ namespace wallet_rpc uint64_t blockIndex; uint64_t unlockTime; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(time) - KV_SERIALIZE(output) - KV_SERIALIZE(transactionHash) - KV_SERIALIZE(amount) - KV_SERIALIZE(fee) - KV_SERIALIZE(paymentId) - KV_SERIALIZE(address) - KV_SERIALIZE(blockIndex) - KV_SERIALIZE(unlockTime) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(time) + KV_MEMBER(output) + KV_MEMBER(transactionHash) + KV_MEMBER(amount) + KV_MEMBER(fee) + KV_MEMBER(paymentId) + KV_MEMBER(address) + KV_MEMBER(blockIndex) + KV_MEMBER(unlockTime) + } }; struct COMMAND_RPC_GET_TRANSFERS { - struct request { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + typedef EMPTY_STRUCT request; struct response { std::list transfers; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(transfers) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(transfers) + } }; }; struct COMMAND_RPC_GET_HEIGHT { - struct request { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + typedef EMPTY_STRUCT request; struct response { uint64_t height; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - END_KV_SERIALIZE_MAP() + void serialize(ISerializer& s) { + KV_MEMBER(height) + } }; }; struct COMMAND_RPC_RESET { - struct request { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; + typedef EMPTY_STRUCT request; + typedef EMPTY_STRUCT response; }; } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index efa35703..bad78332 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,20 +33,20 @@ add_executable(DifficultyTests difficulty/difficulty.cpp) add_executable(HashTargetTests hash-target.cpp) add_executable(HashTests hash/main.cpp) -target_link_libraries(CoreTests epee TestGenerator CryptoNoteCore Logging Common Crypto ${Boost_LIBRARIES}) -target_link_libraries(IntegrationTests epee IntegrationTestLibrary Wallet NodeRpcProxy InProcessNode P2P Rpc Http Transfers Serialization System CryptoNoteCore Logging Common Crypto gtest upnpc-static ${Boost_LIBRARIES}) -target_link_libraries(NodeRpcProxyTests epee NodeRpcProxy CryptoNoteCore Rpc Http Serialization System Logging Common Crypto ${Boost_LIBRARIES}) -target_link_libraries(PerformanceTests epee CryptoNoteCore Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(CoreTests TestGenerator CryptoNoteCore Serialization Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(IntegrationTests IntegrationTestLibrary Wallet NodeRpcProxy InProcessNode P2P Rpc Http Transfers Serialization System CryptoNoteCore Logging Common Crypto BlockchainExplorer gtest upnpc-static ${Boost_LIBRARIES}) +target_link_libraries(NodeRpcProxyTests NodeRpcProxy CryptoNoteCore Rpc Http Serialization System Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(PerformanceTests CryptoNoteCore Serialization Logging Common Crypto ${Boost_LIBRARIES}) target_link_libraries(SystemTests System gtest_main) if (MSVC) target_link_libraries(SystemTests ws2_32) endif () -target_link_libraries(TransfersTests IntegrationTestLibrary Wallet epee gtest_main CryptoNoteCore InProcessNode NodeRpcProxy P2P Rpc Http Serialization System Transfers Logging Common Crypto upnpc-static ${Boost_LIBRARIES}) -target_link_libraries(UnitTests epee gtest_main Wallet TestGenerator CryptoNoteCore InProcessNode Transfers Serialization System Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(TransfersTests IntegrationTestLibrary Wallet gtest_main CryptoNoteCore InProcessNode NodeRpcProxy P2P Rpc Http Serialization System Transfers Logging Common Crypto BlockchainExplorer upnpc-static ${Boost_LIBRARIES}) +target_link_libraries(UnitTests gtest_main Wallet TestGenerator CryptoNoteCore InProcessNode Transfers Serialization System Logging Common Crypto BlockchainExplorer ${Boost_LIBRARIES}) -target_link_libraries(DifficultyTests epee CryptoNoteCore Crypto Logging Common ${Boost_LIBRARIES}) -target_link_libraries(HashTargetTests epee CryptoNoteCore Crypto) +target_link_libraries(DifficultyTests CryptoNoteCore Serialization Crypto Logging Common ${Boost_LIBRARIES}) +target_link_libraries(HashTargetTests CryptoNoteCore Crypto) target_link_libraries(HashTests Crypto) if(NOT MSVC) diff --git a/tests/TestGenerator/TestGenerator.cpp b/tests/TestGenerator/TestGenerator.cpp index ed6bfc22..83e2487a 100644 --- a/tests/TestGenerator/TestGenerator.cpp +++ b/tests/TestGenerator/TestGenerator.cpp @@ -17,17 +17,17 @@ #include "TestGenerator.h" -// epee -#include "misc_language.h" - +#include #include "cryptonote_core/account.h" #include "cryptonote_core/miner.h" using namespace std; - -using namespace epee; using namespace CryptoNote; +#ifndef CHECK_AND_ASSERT_MES +#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {std::cerr << message << std::endl; return fail_ret_val;};}while(0) +#endif + void test_generator::getBlockchain(std::vector& blockchain, const crypto::hash& head, size_t n) const { crypto::hash curr = head; @@ -73,7 +73,7 @@ void test_generator::addBlock(const CryptoNote::Block& blk, size_t tsxSize, uint int64_t emissionChange; uint64_t blockReward; bool penalizeFee = blk.majorVersion > BLOCK_MAJOR_VERSION_1; - m_currency.getBlockReward(misc_utils::median(blockSizes), blockSize, alreadyGeneratedCoins, fee, penalizeFee, + m_currency.getBlockReward(Common::medianValue(blockSizes), blockSize, alreadyGeneratedCoins, fee, penalizeFee, blockReward, emissionChange); m_blocksInfo[get_block_hash(blk)] = BlockInfo(blk.prevId, alreadyGeneratedCoins + emissionChange, blockSize); } @@ -103,10 +103,10 @@ bool test_generator::constructBlock(CryptoNote::Block& blk, uint32_t height, con txsSize += get_object_blobsize(tx); } - blk.minerTx = AUTO_VAL_INIT(blk.minerTx); + blk.minerTx = boost::value_initialized(); size_t targetBlockSize = txsSize + get_object_blobsize(blk.minerTx); while (true) { - if (!m_currency.constructMinerTx(height, misc_utils::median(blockSizes), alreadyGeneratedCoins, targetBlockSize, + if (!m_currency.constructMinerTx(height, Common::medianValue(blockSizes), alreadyGeneratedCoins, targetBlockSize, totalFee, minerAcc.get_keys().m_account_address, blk.minerTx, blobdata(), 10)) { return false; } @@ -209,7 +209,7 @@ bool test_generator::constructBlockManually(Block& blk, const Block& prevBlock, } else { size_t currentBlockSize = txsSizes + get_object_blobsize(blk.minerTx); // TODO: This will work, until size of constructed block is less then m_currency.blockGrantedFullRewardZone() - if (!m_currency.constructMinerTx(height, misc_utils::median(blockSizes), alreadyGeneratedCoins, currentBlockSize, 0, + if (!m_currency.constructMinerTx(height, Common::medianValue(blockSizes), alreadyGeneratedCoins, currentBlockSize, 0, minerAcc.get_keys().m_account_address, blk.minerTx, blobdata(), 1, blk.majorVersion > BLOCK_MAJOR_VERSION_1)) { return false; } @@ -257,7 +257,7 @@ bool test_generator::constructMaxSizeBlock(CryptoNote::Block& blk, const CryptoN medianBlockCount = medianBlockCount == 0 ? m_currency.rewardBlocksWindow() : medianBlockCount; getLastNBlockSizes(blockSizes, get_block_hash(blkPrev), medianBlockCount); - size_t median = misc_utils::median(blockSizes); + size_t median = Common::medianValue(blockSizes); size_t blockGrantedFullRewardZone = defaultMajorVersion <= BLOCK_MAJOR_VERSION_1 ? CryptoNote::parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : m_currency.blockGrantedFullRewardZone(); @@ -314,7 +314,7 @@ bool constructMinerTxManually(const CryptoNote::Currency& currency, uint32_t hei int64_t emissionChange; uint64_t blockReward; if (!currency.getBlockReward(0, 0, alreadyGeneratedCoins, fee, false, blockReward, emissionChange)) { - LOG_PRINT_L0("Block is too big"); + std::cerr << "Block is too big" << std::endl; return false; } @@ -338,7 +338,7 @@ bool constructMinerTxBySize(const CryptoNote::Currency& currency, CryptoNote::Tr uint64_t alreadyGeneratedCoins, const CryptoNote::AccountPublicAddress& minerAddress, std::vector& blockSizes, size_t targetTxSize, size_t targetBlockSize, uint64_t fee/* = 0*/, bool penalizeFee/* = false*/) { - if (!currency.constructMinerTx(height, misc_utils::median(blockSizes), alreadyGeneratedCoins, targetBlockSize, + if (!currency.constructMinerTx(height, Common::medianValue(blockSizes), alreadyGeneratedCoins, targetBlockSize, fee, minerAddress, minerTx, CryptoNote::blobdata(), 1, penalizeFee)) { return false; } diff --git a/tests/core_tests/block_reward.cpp b/tests/core_tests/block_reward.cpp index 98c6a331..60e91d54 100644 --- a/tests/core_tests/block_reward.cpp +++ b/tests/core_tests/block_reward.cpp @@ -16,11 +16,8 @@ // along with Bytecoin. If not, see . #include "block_reward.h" +#include -// epee -#include "misc_language.h" - -using namespace epee; using namespace CryptoNote; namespace @@ -136,7 +133,7 @@ bool gen_block_reward::generate(std::vector& events) const std::vector block_sizes; generator.getLastNBlockSizes(block_sizes, get_block_hash(blk_7), m_currency.rewardBlocksWindow()); - size_t median = misc_utils::median(block_sizes); + size_t median = Common::medianValue(block_sizes); Transaction miner_tx; bool r = constructMinerTxBySize(m_currency, miner_tx, get_block_height(blk_7) + 1, generator.getAlreadyGeneratedCoins(blk_7), diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index e7d5b502..fd308afa 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -18,7 +18,6 @@ #include "block_validation.h" #include "TestGenerator.h" -using namespace epee; using namespace CryptoNote; #define BLOCK_VALIDATION_INIT_GENERATE() \ diff --git a/tests/core_tests/chain_split_1.cpp b/tests/core_tests/chain_split_1.cpp index f721029d..3039e790 100644 --- a/tests/core_tests/chain_split_1.cpp +++ b/tests/core_tests/chain_split_1.cpp @@ -18,8 +18,6 @@ #include "chain_split_1.h" using namespace std; - -using namespace epee; using namespace CryptoNote; diff --git a/tests/core_tests/chain_switch_1.cpp b/tests/core_tests/chain_switch_1.cpp index 3c2b5ae5..1845fc9e 100644 --- a/tests/core_tests/chain_switch_1.cpp +++ b/tests/core_tests/chain_switch_1.cpp @@ -17,7 +17,6 @@ #include "chain_switch_1.h" -using namespace epee; using namespace CryptoNote; @@ -131,8 +130,7 @@ bool gen_chain_switch_1::check_split_not_switched(CryptoNote::core& c, size_t ev CHECK_EQ(MK_COINS(14), get_balance(m_recipient_account_3, chain, mtx)); CHECK_EQ(MK_COINS(3), get_balance(m_recipient_account_4, chain, mtx)); - std::list tx_pool; - c.get_pool_transactions(tx_pool); + std::vector tx_pool = c.getPoolTransactions(); CHECK_EQ(1, tx_pool.size()); std::vector tx_outs; @@ -180,8 +178,7 @@ bool gen_chain_switch_1::check_split_switched(CryptoNote::core& c, size_t ev_ind CHECK_EQ(MK_COINS(14), get_balance(m_recipient_account_3, chain, mtx)); CHECK_EQ(MK_COINS(16), get_balance(m_recipient_account_4, chain, mtx)); - std::list tx_pool; - c.get_pool_transactions(tx_pool); + std::vector tx_pool = c.getPoolTransactions(); CHECK_EQ(1, tx_pool.size()); CHECK_TEST_CONDITION(!(tx_pool.front() == m_tx_pool.front())); diff --git a/tests/core_tests/chain_switch_1.h b/tests/core_tests/chain_switch_1.h index 33b06bfc..e9254920 100644 --- a/tests/core_tests/chain_switch_1.h +++ b/tests/core_tests/chain_switch_1.h @@ -39,5 +39,5 @@ private: CryptoNote::account_base m_recipient_account_3; CryptoNote::account_base m_recipient_account_4; - std::list m_tx_pool; + std::vector m_tx_pool; }; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index e60fcb8a..932f9761 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -25,9 +25,6 @@ #include #include -#include "include_base_utils.h" -#include "misc_language.h" - #include "Common/command_line.h" #include "cryptonote_core/account_boost_serialization.h" #include "cryptonote_core/cryptonote_basic.h" @@ -39,8 +36,6 @@ #include "cryptonote_core/UpgradeDetector.h" using namespace std; - -using namespace epee; using namespace CryptoNote; struct output_index { diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 3251489c..2c2cdaf0 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -23,6 +23,8 @@ #include "Common/boost_serialization_helper.h" #include "Common/command_line.h" +#include "Common/ConsoleTools.h" + #include "cryptonote_core/account_boost_serialization.h" #include "cryptonote_core/account.h" #include "cryptonote_core/cryptonote_core.h" @@ -32,45 +34,52 @@ #include #include + + namespace concolor { + using namespace Common::Console; + inline std::basic_ostream >& bright_white(std::basic_ostream >& ostr) { - epee::log_space::set_console_color(epee::log_space::console_color_white, true); + setTextColor(Color::BrightWhite); return ostr; } inline std::basic_ostream >& red(std::basic_ostream >& ostr) { - epee::log_space::set_console_color(epee::log_space::console_color_red, true); + setTextColor(Color::BrightRed); return ostr; } inline std::basic_ostream >& green(std::basic_ostream >& ostr) { - epee::log_space::set_console_color(epee::log_space::console_color_green, true); + setTextColor(Color::BrightGreen); return ostr; } inline std::basic_ostream >& magenta(std::basic_ostream >& ostr) { - epee::log_space::set_console_color(epee::log_space::console_color_magenta, true); + setTextColor(Color::BrightMagenta); return ostr; } inline std::basic_ostream >& yellow(std::basic_ostream >& ostr) { - epee::log_space::set_console_color(epee::log_space::console_color_yellow, true); + setTextColor(Color::BrightYellow); return ostr; } inline std::basic_ostream >& normal(std::basic_ostream >& ostr) { - epee::log_space::reset_console_color(); + setTextColor(Color::Default); return ostr; } } +#define LOG_ERROR(msg) std::cout << concolor::red << msg << concolor::normal << std::endl +#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {std::cout << concolor::red << message << concolor::normal << std::endl; return fail_ret_val;};}while(0) +#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {std::cout << concolor::red << message << concolor::normal << std::endl; return fail_ret_val;};}while(0) struct callback_entry { @@ -372,24 +381,23 @@ private: template inline bool replay_events_through_core(CryptoNote::core& cr, const std::vector& events, t_test_class& validator) { - TRY_ENTRY(); + try { + CHECK_AND_ASSERT_MES(typeid(CryptoNote::Block) == events[0].type(), false, "First event must be genesis block creation"); + cr.set_genesis_block(boost::get(events[0])); - //init core here + bool r = true; + push_core_event_visitor visitor(cr, events, validator); + for (size_t i = 1; i < events.size() && r; ++i) + { + visitor.event_index(i); + r = boost::apply_visitor(visitor, events[i]); + } - CHECK_AND_ASSERT_MES(typeid(CryptoNote::Block) == events[0].type(), false, "First event must be genesis block creation"); - cr.set_genesis_block(boost::get(events[0])); - - bool r = true; - push_core_event_visitor visitor(cr, events, validator); - for(size_t i = 1; i < events.size() && r; ++i) - { - visitor.event_index(i); - r = boost::apply_visitor(visitor, events[i]); + return r; + } catch (std::exception& e) { + std::cout << "replay_events_through_core: " << e.what(); + return false; } - - return r; - - CATCH_ENTRY_L0("replay_events_through_core", false); } //-------------------------------------------------------------------------- template @@ -562,11 +570,11 @@ inline bool do_replay_file(const std::string& filename) } \ catch (const std::exception& ex) \ { \ - LOG_PRINT(#genclass << " generation failed: what=" << ex.what(), 0); \ + std::cout << #genclass << " generation failed: what=" << ex.what(); \ } \ catch (...) \ { \ - LOG_PRINT(#genclass << " generation failed: generic exception", 0); \ + std::cout << #genclass << " generation failed: generic exception"; \ } \ genclass validator; \ if (generated && do_replay_events< genclass >(events, validator)) \ @@ -590,9 +598,9 @@ bool GenerateAndPlay(const char* testname, GenClassT&& g) { try { generated = g.generate(events); } catch (const std::exception& ex) { - LOG_PRINT(testname << " generation failed: what=" << ex.what(), 0); + std::cout << testname << " generation failed: what=" << ex.what(); } catch (...) { - LOG_PRINT(testname << " generation failed: generic exception", 0); + std::cout << testname << " generation failed: generic exception"; } bool succeeded = generated && do_replay_events(events, g); diff --git a/tests/core_tests/chaingen001.cpp b/tests/core_tests/chaingen001.cpp index e1150055..86f4bec2 100644 --- a/tests/core_tests/chaingen001.cpp +++ b/tests/core_tests/chaingen001.cpp @@ -18,8 +18,6 @@ #include "chaingen001.h" using namespace std; - -using namespace epee; using namespace CryptoNote; //////// diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 1700d0b6..9b82daef 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -45,16 +45,7 @@ namespace int main(int argc, char* argv[]) { - TRY_ENTRY(); - // epee::string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_3); - epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2); - - epee::log_space::log_singletone::add_logger(LOGGER_FILE, - epee::log_space::log_singletone::get_default_log_file().c_str(), - epee::log_space::log_singletone::get_default_log_folder().c_str()); + try { po::options_description desc_options("Allowed options"); command_line::add_arg(desc_options, command_line::arg_help); @@ -238,5 +229,7 @@ int main(int argc, char* argv[]) return failed_tests.empty() ? 0 : 1; - CATCH_ENTRY_L0("main", 1); + } catch (std::exception& e) { + std::cout << "Exception in main(): " << e.what() << std::endl; + } } diff --git a/tests/core_tests/double_spend.cpp b/tests/core_tests/double_spend.cpp index 7a23917c..d89e719d 100644 --- a/tests/core_tests/double_spend.cpp +++ b/tests/core_tests/double_spend.cpp @@ -18,7 +18,6 @@ #include "double_spend.h" #include "TestGenerator.h" -using namespace epee; using namespace CryptoNote; //====================================================================================================================== diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 5e50f41e..f3af70ed 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #pragma once //====================================================================================================================== diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index 4815ccc7..daa88eb9 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -17,7 +17,6 @@ #include "integer_overflow.h" -using namespace epee; using namespace CryptoNote; namespace diff --git a/tests/core_tests/ring_signature_1.cpp b/tests/core_tests/ring_signature_1.cpp index 1002b8a3..98e2382e 100644 --- a/tests/core_tests/ring_signature_1.cpp +++ b/tests/core_tests/ring_signature_1.cpp @@ -17,7 +17,6 @@ #include "ring_signature_1.h" -using namespace epee; using namespace CryptoNote; diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index a904e67b..5324a977 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -15,12 +15,12 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -#include "include_base_utils.h" #include "cryptonote_core/cryptonote_basic_impl.h" #include "cryptonote_core/account.h" #include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/Currency.h" -#include "misc_language.h" + +#include #include "chaingen.h" @@ -147,7 +147,7 @@ bool test_block_creation() bool r = currency.parseAccountAddressString("272xWzbWsP4cfNFfxY5ETN5moU8x81PKfWPwynrrqsNGDBQGLmD1kCkKCvPeDUXu5XfmZkCrQ53wsWmdfvHBGLNjGcRiDcK", adr); CHECK_AND_ASSERT_MES(r, false, "failed to import"); Block b; - r = currency.constructMinerTx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, b.minerTx, blobdata(), 11); + r = currency.constructMinerTx(90, Common::medianValue(szs), 3553616528562147, 33094, 10000000, adr, b.minerTx, blobdata(), 11); return r; } diff --git a/tests/core_tests/tx_validation.cpp b/tests/core_tests/tx_validation.cpp index 572e384f..d56beee0 100644 --- a/tests/core_tests/tx_validation.cpp +++ b/tests/core_tests/tx_validation.cpp @@ -18,7 +18,6 @@ #include "tx_validation.h" #include "TestGenerator.h" -using namespace epee; using namespace crypto; using namespace CryptoNote; diff --git a/tests/core_tests/upgrade.cpp b/tests/core_tests/upgrade.cpp index fe13f561..f6f564ba 100644 --- a/tests/core_tests/upgrade.cpp +++ b/tests/core_tests/upgrade.cpp @@ -17,7 +17,6 @@ #include "upgrade.h" -using namespace epee; using namespace CryptoNote; namespace { diff --git a/tests/crypto/crypto-ops-data.c b/tests/crypto/crypto-ops-data.c index e31d95d6..16d1cc4f 100644 --- a/tests/crypto/crypto-ops-data.c +++ b/tests/crypto/crypto-ops-data.c @@ -15,21 +15,4 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "crypto/crypto-ops-data.c" diff --git a/tests/crypto/crypto-ops.c b/tests/crypto/crypto-ops.c index 3affc129..ca2404e7 100644 --- a/tests/crypto/crypto-ops.c +++ b/tests/crypto/crypto-ops.c @@ -15,21 +15,4 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "crypto/crypto-ops.c" diff --git a/tests/crypto/hash.c b/tests/crypto/hash.c index f3663896..d8bab89b 100644 --- a/tests/crypto/hash.c +++ b/tests/crypto/hash.c @@ -15,22 +15,5 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "crypto/hash.c" #include "crypto/keccak.c" diff --git a/tests/crypto/random.c b/tests/crypto/random.c index d3625d3a..68448a5f 100644 --- a/tests/crypto/random.c +++ b/tests/crypto/random.c @@ -15,23 +15,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . -// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - #include "crypto/random.c" #include "crypto-tests.h" diff --git a/tests/integration_test_lib/BaseFunctionalTest.cpp b/tests/integration_test_lib/BaseFunctionalTest.cpp index 83a33a5c..96224f87 100755 --- a/tests/integration_test_lib/BaseFunctionalTest.cpp +++ b/tests/integration_test_lib/BaseFunctionalTest.cpp @@ -321,28 +321,7 @@ bool BaseFunctionalTest::mineBlocks(TestNode& node, const CryptoNote::AccountPub return false; } - blockTemplate.timestamp = m_nextTimestamp; - m_nextTimestamp += 2 * m_currency.difficultyTarget(); - - if (blockTemplate.majorVersion == BLOCK_MAJOR_VERSION_2) { - blockTemplate.parentBlock.majorVersion = BLOCK_MAJOR_VERSION_1; - blockTemplate.parentBlock.minorVersion = BLOCK_MINOR_VERSION_0; - blockTemplate.parentBlock.numberOfTransactions = 1; - - CryptoNote::tx_extra_merge_mining_tag mmTag; - mmTag.depth = 0; - if (!CryptoNote::get_aux_block_header_hash(blockTemplate, mmTag.merkle_root)) { - return false; - } - - blockTemplate.parentBlock.minerTx.extra.clear(); - if (!CryptoNote::append_mm_tag_to_extra(blockTemplate.parentBlock.minerTx.extra, mmTag)) { - return false; - } - } - - blobdata blockBlob = block_to_blob(blockTemplate); - if (!node.submitBlock(::Common::toHex(blockBlob.data(), blockBlob.size()))) { + if (!prepareAndSubmitBlock(node, std::move(blockTemplate))) { return false; } } @@ -350,6 +329,31 @@ bool BaseFunctionalTest::mineBlocks(TestNode& node, const CryptoNote::AccountPub return true; } +bool BaseFunctionalTest::prepareAndSubmitBlock(TestNode& node, CryptoNote::Block&& blockTemplate) { + blockTemplate.timestamp = m_nextTimestamp; + m_nextTimestamp += 2 * m_currency.difficultyTarget(); + + if (blockTemplate.majorVersion == BLOCK_MAJOR_VERSION_2) { + blockTemplate.parentBlock.majorVersion = BLOCK_MAJOR_VERSION_1; + blockTemplate.parentBlock.minorVersion = BLOCK_MINOR_VERSION_0; + blockTemplate.parentBlock.numberOfTransactions = 1; + + CryptoNote::tx_extra_merge_mining_tag mmTag; + mmTag.depth = 0; + if (!CryptoNote::get_aux_block_header_hash(blockTemplate, mmTag.merkle_root)) { + return false; + } + + blockTemplate.parentBlock.minerTx.extra.clear(); + if (!CryptoNote::append_mm_tag_to_extra(blockTemplate.parentBlock.minerTx.extra, mmTag)) { + return false; + } + } + + blobdata blockBlob = block_to_blob(blockTemplate); + return node.submitBlock(::Common::toHex(blockBlob.data(), blockBlob.size())); +} + bool BaseFunctionalTest::mineBlock(std::unique_ptr &wallet) { if (nodeDaemons.empty() || !wallet) return false; diff --git a/tests/integration_test_lib/BaseFunctionalTest.h b/tests/integration_test_lib/BaseFunctionalTest.h index ed5a25fa..1402b84f 100755 --- a/tests/integration_test_lib/BaseFunctionalTest.h +++ b/tests/integration_test_lib/BaseFunctionalTest.h @@ -163,6 +163,8 @@ namespace Tests { bool waitForPoolSize(size_t nodeIndex, CryptoNote::INode& node, size_t expectedPoolSize, std::vector& txPool); + bool prepareAndSubmitBlock(TestNode& node, CryptoNote::Block&& blockTemplate); + private: #ifdef __linux__ std::vector<__pid_t> pids; diff --git a/tests/integration_test_lib/CoreRpcSerialization.cpp b/tests/integration_test_lib/CoreRpcSerialization.cpp deleted file mode 100755 index 14bce8c2..00000000 --- a/tests/integration_test_lib/CoreRpcSerialization.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - -#include "CoreRpcSerialization.h" - -namespace CryptoNote { - -void serialize(COMMAND_RPC_START_MINING::request& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer(value.miner_address, "miner_address"); - serializer(value.threads_count, "threads_count"); - serializer.endObject(); -} - -void serialize(COMMAND_RPC_START_MINING::response& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer(value.status, "status"); - serializer.endObject(); -} - -void serialize(COMMAND_RPC_STOP_MINING::request& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} - -void serialize(COMMAND_RPC_STOP_MINING::response& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer(value.status, "status"); - serializer.endObject(); -} - -void serialize(COMMAND_RPC_STOP_DAEMON::request& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer.endObject(); -} - -void serialize(COMMAND_RPC_STOP_DAEMON::response& value, const std::string& name, CryptoNote::ISerializer& serializer) { - serializer.beginObject(name); - serializer(value.status, "status"); - serializer.endObject(); -} - -} //namespace CryptoNote diff --git a/tests/integration_test_lib/CoreRpcSerialization.h b/tests/integration_test_lib/CoreRpcSerialization.h deleted file mode 100755 index ed4f92b8..00000000 --- a/tests/integration_test_lib/CoreRpcSerialization.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - -#pragma once - -#include - -#include "../../src/serialization/ISerializer.h" -#include "../../src/rpc/core_rpc_server_commands_defs.h" - -namespace CryptoNote { - -void serialize(COMMAND_RPC_START_MINING::request& value, const std::string& name, CryptoNote::ISerializer& serializer); -void serialize(COMMAND_RPC_START_MINING::response& value, const std::string& name, CryptoNote::ISerializer& serializer); - -void serialize(COMMAND_RPC_STOP_MINING::request& value, const std::string& name, CryptoNote::ISerializer& serializer); -void serialize(COMMAND_RPC_STOP_MINING::response& value, const std::string& name, CryptoNote::ISerializer& serializer); - -void serialize(COMMAND_RPC_STOP_DAEMON::request& value, const std::string& name, CryptoNote::ISerializer& serializer); -void serialize(COMMAND_RPC_STOP_DAEMON::response& value, const std::string& name, CryptoNote::ISerializer& serializer); - -} //namespace CryptoNote diff --git a/tests/integration_test_lib/TestNetwork.cpp b/tests/integration_test_lib/TestNetwork.cpp index 838da0e5..65b95376 100644 --- a/tests/integration_test_lib/TestNetwork.cpp +++ b/tests/integration_test_lib/TestNetwork.cpp @@ -17,6 +17,7 @@ #include "TestNetwork.h" +#include #include #include "InProcTestNode.h" diff --git a/tests/integration_tests/BlockchainInfo.h b/tests/integration_tests/BlockchainInfo.h index 2171d982..219412f6 100644 --- a/tests/integration_tests/BlockchainInfo.h +++ b/tests/integration_tests/BlockchainInfo.h @@ -21,12 +21,13 @@ #include "cryptonote_core/cryptonote_serialization.h" namespace CryptoNote { - void serialize(BlockCompleteEntry& v, const std::string& name, ISerializer& s) { + bool serialize(BlockCompleteEntry& v, const Common::StringView& name, ISerializer& s) { s.beginObject(name); s(v.blockHash, "hash"); s.binary(v.block, "block"); s(v.txs, "transactions"); s.endObject(); + return true; } bool operator == (const BlockCompleteEntry& a, const BlockCompleteEntry& b) { @@ -44,11 +45,10 @@ namespace CryptoNote { return blocks == other.blocks && globalOutputs == other.globalOutputs; } - void serialize(ISerializer& s, const std::string& name) { - s.beginObject(name); + ISerializer& serialize(ISerializer& s) { s(blocks, "blocks"); s(globalOutputs, "outputs"); - s.endObject(); + return s; } }; diff --git a/tests/node_rpc_proxy_test/node_rpc_proxy_test.cpp b/tests/node_rpc_proxy_test/node_rpc_proxy_test.cpp index c006ffe0..61353ea0 100644 --- a/tests/node_rpc_proxy_test/node_rpc_proxy_test.cpp +++ b/tests/node_rpc_proxy_test/node_rpc_proxy_test.cpp @@ -18,80 +18,83 @@ #include #include -#include "include_base_utils.h" +#include +#include #include "node_rpc_proxy/NodeRpcProxy.h" using namespace CryptoNote; -using namespace CryptoNote; +using namespace Logging; +#undef ERROR class NodeObserver : public INodeObserver { public: - NodeObserver(const std::string& name, NodeRpcProxy& nodeProxy) + NodeObserver(const std::string& name, NodeRpcProxy& nodeProxy, ILogger& log) : m_name(name) - , m_nodeProxy(nodeProxy) { + , m_nodeProxy(nodeProxy) + , logger(log, "NodeObserver:" + name) { } virtual ~NodeObserver() { } virtual void peerCountUpdated(size_t count) { - LOG_PRINT_L0('[' << m_name << "] peerCountUpdated " << count << " = " << m_nodeProxy.getPeerCount()); + logger(INFO) << '[' << m_name << "] peerCountUpdated " << count << " = " << m_nodeProxy.getPeerCount(); } virtual void localBlockchainUpdated(uint64_t height) { - LOG_PRINT_L0('[' << m_name << "] localBlockchainUpdated " << height << " = " << m_nodeProxy.getLastLocalBlockHeight()); + logger(INFO) << '[' << m_name << "] localBlockchainUpdated " << height << " = " << m_nodeProxy.getLastLocalBlockHeight(); std::vector amounts; amounts.push_back(100000000); auto outs = std::make_shared>(); - m_nodeProxy.getRandomOutsByAmounts(std::move(amounts), 10, *outs.get(), [outs](std::error_code ec) { + m_nodeProxy.getRandomOutsByAmounts(std::move(amounts), 10, *outs.get(), [outs, this](std::error_code ec) { if (!ec) { if (1 == outs->size() && 10 == (*outs)[0].outs.size()) { - LOG_PRINT_L0("getRandomOutsByAmounts called successfully"); + logger(INFO) << "getRandomOutsByAmounts called successfully"; } else { - LOG_PRINT_RED_L0("getRandomOutsByAmounts returned invalid result"); + logger(ERROR) << "getRandomOutsByAmounts returned invalid result"; } } else { - LOG_PRINT_RED_L0("failed to call getRandomOutsByAmounts: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "failed to call getRandomOutsByAmounts: " << ec.message() << ':' << ec.value(); } }); } virtual void lastKnownBlockHeightUpdated(uint64_t height) { - LOG_PRINT_L0('[' << m_name << "] lastKnownBlockHeightUpdated " << height << " = " << m_nodeProxy.getLastKnownBlockHeight()); + logger(INFO) << '[' << m_name << "] lastKnownBlockHeightUpdated " << height << " = " << m_nodeProxy.getLastKnownBlockHeight(); } private: + LoggerRef logger; std::string m_name; NodeRpcProxy& m_nodeProxy; }; int main(int argc, const char** argv) { - //set up logging options - epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); + Logging::ConsoleLogger log; + Logging::LoggerRef logger(log, "main"); NodeRpcProxy nodeProxy("127.0.0.1", 18081); - NodeObserver observer1("obs1", nodeProxy); - NodeObserver observer2("obs2", nodeProxy); + NodeObserver observer1("obs1", nodeProxy, log); + NodeObserver observer2("obs2", nodeProxy, log); nodeProxy.addObserver(&observer1); nodeProxy.addObserver(&observer2); - nodeProxy.init([](std::error_code ec) { + nodeProxy.init([&](std::error_code ec) { if (ec) { - LOG_PRINT_RED_L0("init error: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "init error: " << ec.message() << ':' << ec.value(); } else { - LOG_PRINT_GREEN("initialized", LOG_LEVEL_0); + logger(INFO, BRIGHT_GREEN) << "initialized"; } }); //nodeProxy.init([](std::error_code ec) { // if (ec) { - // LOG_PRINT_RED_L0("init error: " << ec.message() << ':' << ec.value()); + // logger(ERROR) << "init error: " << ec.message() << ':' << ec.value(); // } else { // LOG_PRINT_GREEN("initialized", LOG_LEVEL_0); // } @@ -99,49 +102,49 @@ int main(int argc, const char** argv) { std::this_thread::sleep_for(std::chrono::seconds(5)); if (nodeProxy.shutdown()) { - LOG_PRINT_GREEN("shutdown", LOG_LEVEL_0); + logger(INFO, BRIGHT_GREEN) << "shutdown"; } else { - LOG_PRINT_RED_L0("shutdown error"); + logger(ERROR) << "shutdown error"; } - nodeProxy.init([](std::error_code ec) { + nodeProxy.init([&](std::error_code ec) { if (ec) { - LOG_PRINT_RED_L0("init error: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "init error: " << ec.message() << ':' << ec.value(); } else { - LOG_PRINT_GREEN("initialized", LOG_LEVEL_0); + logger(INFO, BRIGHT_GREEN) << "initialized"; } }); std::this_thread::sleep_for(std::chrono::seconds(5)); if (nodeProxy.shutdown()) { - LOG_PRINT_GREEN("shutdown", LOG_LEVEL_0); + logger(INFO, BRIGHT_GREEN) << "shutdown"; } else { - LOG_PRINT_RED_L0("shutdown error"); + logger(ERROR) << "shutdown error"; } CryptoNote::Transaction tx; - nodeProxy.relayTransaction(tx, [](std::error_code ec) { + nodeProxy.relayTransaction(tx, [&](std::error_code ec) { if (!ec) { - LOG_PRINT_L0("relayTransaction called successfully"); + logger(INFO) << "relayTransaction called successfully"; } else { - LOG_PRINT_RED_L0("failed to call relayTransaction: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "failed to call relayTransaction: " << ec.message() << ':' << ec.value(); } }); - nodeProxy.init([](std::error_code ec) { + nodeProxy.init([&](std::error_code ec) { if (ec) { - LOG_PRINT_RED_L0("init error: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "init error: " << ec.message() << ':' << ec.value(); } else { - LOG_PRINT_GREEN("initialized", LOG_LEVEL_0); + logger(INFO, BRIGHT_GREEN) << "initialized"; } }); std::this_thread::sleep_for(std::chrono::seconds(5)); - nodeProxy.relayTransaction(tx, [](std::error_code ec) { + nodeProxy.relayTransaction(tx, [&](std::error_code ec) { if (!ec) { - LOG_PRINT_L0("relayTransaction called successfully"); + logger(INFO) << "relayTransaction called successfully"; } else { - LOG_PRINT_RED_L0("failed to call relayTransaction: " << ec.message() << ':' << ec.value()); + logger(ERROR) << "failed to call relayTransaction: " << ec.message() << ':' << ec.value(); } }); diff --git a/tests/transfers_tests/test_TxPoolSync.cpp b/tests/transfers_tests/test_TxPoolSync.cpp new file mode 100644 index 00000000..691c5fb8 --- /dev/null +++ b/tests/transfers_tests/test_TxPoolSync.cpp @@ -0,0 +1,600 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "gtest/gtest.h" + +#include "cryptonote_core/account.h" +#include "cryptonote_core/CoreConfig.h" +#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_core/Currency.h" +#include "Logging/LoggerManager.h" +#include "p2p/NetNodeConfig.h" +#include "System/Dispatcher.h" +#include "System/InterruptedException.h" +#include "wallet/Wallet.h" + +#include "../integration_test_lib/BaseFunctionalTest.h" +#include "../integration_test_lib/TestWallet.h" + + +using namespace CryptoNote; + +extern System::Dispatcher globalSystem; + +namespace { + TransactionHash toTransactionHash(const crypto::hash& h) { + TransactionHash result; + std::copy(reinterpret_cast(&h), reinterpret_cast(&h) + sizeof(h), result.begin()); + return result; + } + + class NodeTxPoolSyncTest : public Tests::Common::BaseFunctionalTest, public ::testing::Test { + public: + NodeTxPoolSyncTest() : + BaseFunctionalTest(m_currency, globalSystem, Tests::Common::BaseFunctionalTestConfig()), + m_dispatcher(globalSystem), + m_currency(CurrencyBuilder(m_logManager).testnet(true).currency()) { + } + + protected: + Logging::LoggerManager m_logManager; + System::Dispatcher& m_dispatcher; + CryptoNote::Currency m_currency; + }; + + const std::string TEST_PASSWORD = "password"; + + class TestWallet : private IWalletObserver { + public: + TestWallet(System::Dispatcher& dispatcher, Currency& currency, INode& node) : + m_dispatcher(dispatcher), + m_synchronizationCompleted(dispatcher), + m_someTransactionUpdated(dispatcher), + m_currency(currency), + m_node(node), + m_wallet(new CryptoNote::Wallet(currency, node)), + m_currentHeight(0) { + m_wallet->addObserver(this); + } + + ~TestWallet() { + m_wallet->removeObserver(this); + } + + std::error_code init() { + CryptoNote::account_base walletAccount; + walletAccount.generate(); + + WalletAccountKeys walletKeys; + walletKeys.spendPublicKey = reinterpret_cast(walletAccount.get_keys().m_account_address.m_spendPublicKey); + walletKeys.spendSecretKey = reinterpret_cast(walletAccount.get_keys().m_spend_secret_key); + walletKeys.viewPublicKey = reinterpret_cast(walletAccount.get_keys().m_account_address.m_viewPublicKey); + walletKeys.viewSecretKey = reinterpret_cast(walletAccount.get_keys().m_view_secret_key); + + m_wallet->initWithKeys(walletKeys, TEST_PASSWORD); + m_synchronizationCompleted.wait(); + return m_lastSynchronizationResult; + } + + struct TransactionSendingWaiter : public IWalletObserver { + System::Dispatcher& m_dispatcher; + System::Event m_event; + bool m_waiting = false; + TransactionId m_expectedTxId; + std::error_code m_result; + + TransactionSendingWaiter(System::Dispatcher& dispatcher) : m_dispatcher(dispatcher), m_event(dispatcher) { + } + + void wait(TransactionId expectedTxId) { + m_waiting = true; + m_expectedTxId = expectedTxId; + m_event.wait(); + m_waiting = false; + } + + virtual void sendTransactionCompleted(TransactionId transactionId, std::error_code result) { + m_dispatcher.remoteSpawn([this, transactionId, result]() { + if (m_waiting && m_expectedTxId == transactionId) { + m_result = result; + m_event.set(); + } + }); + } + }; + + std::error_code sendTransaction(const std::string& address, uint64_t amount, TransactionHash& txHash) { + TransactionSendingWaiter transactionSendingWaiter(m_dispatcher); + m_wallet->addObserver(&transactionSendingWaiter); + + Transfer transfer{ address, static_cast(amount) }; + auto txId = m_wallet->sendTransaction(transfer, m_currency.minimumFee()); + transactionSendingWaiter.wait(txId); + m_wallet->removeObserver(&transactionSendingWaiter); + // TODO workaround: make sure ObserverManager doesn't have local pointers to transactionSendingWaiter, so it can be destroyed + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + // Run all spawned handlers from TransactionSendingWaiter::sendTransactionCompleted + m_dispatcher.yield(); + + TransactionInfo txInfo; + if (!m_wallet->getTransaction(txId, txInfo)) { + return std::make_error_code(std::errc::identifier_removed); + } + + txHash = txInfo.hash; + return transactionSendingWaiter.m_result; + } + + void waitForSynchronizationToHeight(uint32_t height) { + while (m_synchronizedHeight < height) { + m_synchronizationCompleted.wait(); + } + } + + IWallet* wallet() { + return m_wallet.get(); + } + + AccountPublicAddress address() const { + std::string addressString = m_wallet->getAddress(); + AccountPublicAddress address; + bool ok = m_currency.parseAccountAddressString(addressString, address); + assert(ok); + return address; + } + + protected: + virtual void synchronizationCompleted(std::error_code result) override { + m_dispatcher.remoteSpawn([this, result]() { + m_lastSynchronizationResult = result; + m_synchronizedHeight = m_currentHeight; + m_synchronizationCompleted.set(); + m_synchronizationCompleted.clear(); + }); + } + + virtual void synchronizationProgressUpdated(uint64_t current, uint64_t total) override { + m_dispatcher.remoteSpawn([this, current]() { + m_currentHeight = static_cast(current); + }); + } + + private: + System::Dispatcher& m_dispatcher; + System::Event m_synchronizationCompleted; + System::Event m_someTransactionUpdated; + + INode& m_node; + Currency& m_currency; + std::unique_ptr m_wallet; + std::unique_ptr m_walletObserver; + uint32_t m_currentHeight; + uint32_t m_synchronizedHeight; + std::error_code m_lastSynchronizationResult; + }; + + TEST_F(NodeTxPoolSyncTest, TxPoolsAreRequestedRightAfterANodeIsConnectedToAnotherIfTheirBlockchainsAreSynchronized) { + //System::Timer timer(m_dispatcher); + //m_dispatcher.spawn([&m_dispatcher, &timer] { + // try { + // timer.sleep(std::chrono::minutes(5)); + // m_dispatcher. + // } catch (System::InterruptedException&) { + // } + //}); + + const size_t NODE_0 = 0; + const size_t NODE_1 = 1; + const size_t NODE_2 = 2; + const size_t NODE_3 = 3; + + launchTestnet(4, Tests::Common::BaseFunctionalTest::Line); + + std::unique_ptr node0; + std::unique_ptr node1; + std::unique_ptr node2; + std::unique_ptr node3; + + nodeDaemons[NODE_0]->makeINode(node0); + nodeDaemons[NODE_1]->makeINode(node1); + nodeDaemons[NODE_2]->makeINode(node2); + nodeDaemons[NODE_3]->makeINode(node3); + + CryptoNote::account_base minerAccount; + minerAccount.generate(); + + TestWallet wallet1(m_dispatcher, m_currency, *node1); + TestWallet wallet2(m_dispatcher, m_currency, *node2); + + ASSERT_FALSE(static_cast(wallet1.init())); + ASSERT_FALSE(static_cast(wallet2.init())); + + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet1.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet2.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], minerAccount.get_keys().m_account_address, m_currency.minedMoneyUnlockWindow())); + + wallet1.waitForSynchronizationToHeight(static_cast(m_currency.minedMoneyUnlockWindow()) + 3); + wallet2.waitForSynchronizationToHeight(static_cast(m_currency.minedMoneyUnlockWindow()) + 3); + + stopNode(NODE_2); + // To make sure new transaction won't be received by NODE_2 and NODE_3 + waitForPeerCount(*node1, 1); + + TransactionHash txHash1; + ASSERT_FALSE(static_cast(wallet1.sendTransaction(m_currency.accountAddressAsString(minerAccount), m_currency.coin(), txHash1))); + + stopNode(NODE_1); + // Don't start NODE_2, while NODE_1 doesn't close its connections + waitForPeerCount(*node0, 0); + + startNode(NODE_2); + waitDaemonReady(NODE_2); + waitForPeerCount(*node3, 1); + + TransactionHash txHash2; + ASSERT_FALSE(static_cast(wallet2.sendTransaction(m_currency.accountAddressAsString(minerAccount), m_currency.coin(), txHash2))); + + startNode(NODE_1); + waitDaemonReady(NODE_1); + + std::vector poolTxs1; + std::vector poolTxs2; + ASSERT_TRUE(waitForPoolSize(NODE_1, *node1, 2, poolTxs1)); + ASSERT_TRUE(waitForPoolSize(NODE_2, *node2, 2, poolTxs2)); + + //timer.stop(); + + std::vector poolTxsIds1; + std::vector poolTxsIds2; + + for (auto& tx : poolTxs1) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds1.emplace_back(std::move(txHash)); + } + for (auto& tx : poolTxs2) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds2.emplace_back(std::move(txHash)); + } + + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash1) != poolTxsIds1.end()); + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash2) != poolTxsIds1.end()); + + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash1) != poolTxsIds2.end()); + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash2) != poolTxsIds2.end()); + } + + TEST_F(NodeTxPoolSyncTest, TxPoolsAreRequestedRightAfterInitialBlockchainsSynchronization) { + //System::Timer timer(m_dispatcher); + //m_dispatcher.spawn([&m_dispatcher, &timer] { + // try { + // timer.sleep(std::chrono::minutes(5)); + // m_dispatcher. + // } catch (System::InterruptedException&) { + // } + //}); + + const size_t NODE_0 = 0; + const size_t NODE_1 = 1; + const size_t NODE_2 = 2; + const size_t NODE_3 = 3; + + launchTestnet(4, Tests::Common::BaseFunctionalTest::Line); + + std::unique_ptr node0; + std::unique_ptr node1; + std::unique_ptr node2; + std::unique_ptr node3; + + nodeDaemons[NODE_0]->makeINode(node0); + nodeDaemons[NODE_1]->makeINode(node1); + nodeDaemons[NODE_2]->makeINode(node2); + nodeDaemons[NODE_3]->makeINode(node3); + + CryptoNote::account_base minerAccount; + minerAccount.generate(); + + TestWallet wallet1(m_dispatcher, m_currency, *node1); + TestWallet wallet2(m_dispatcher, m_currency, *node2); + + ASSERT_FALSE(static_cast(wallet1.init())); + ASSERT_FALSE(static_cast(wallet2.init())); + + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet1.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet2.address(), 1)); + + wallet1.waitForSynchronizationToHeight(static_cast(3)); + wallet2.waitForSynchronizationToHeight(static_cast(3)); + + stopNode(NODE_2); + // To make sure new transaction won't be received by NODE_2 and NODE_3 + waitForPeerCount(*node1, 1); + + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], minerAccount.get_keys().m_account_address, m_currency.minedMoneyUnlockWindow())); + wallet1.waitForSynchronizationToHeight(static_cast(m_currency.minedMoneyUnlockWindow()) + 3); + + TransactionHash txHash1; + ASSERT_FALSE(static_cast(wallet1.sendTransaction(m_currency.accountAddressAsString(minerAccount), m_currency.coin(), txHash1))); + + stopNode(NODE_1); + // Don't start NODE_2, while NODE_1 doesn't close its connections + waitForPeerCount(*node0, 0); + + startNode(NODE_2); + waitDaemonReady(NODE_2); + waitForPeerCount(*node3, 1); + + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_3], minerAccount.get_keys().m_account_address, m_currency.minedMoneyUnlockWindow())); + wallet2.waitForSynchronizationToHeight(static_cast(m_currency.minedMoneyUnlockWindow()) + 3); + + TransactionHash txHash2; + ASSERT_FALSE(static_cast(wallet2.sendTransaction(m_currency.accountAddressAsString(minerAccount), m_currency.coin(), txHash2))); + + startNode(NODE_1); + waitDaemonReady(NODE_1); + + std::vector poolTxs1; + std::vector poolTxs2; + ASSERT_TRUE(waitForPoolSize(NODE_1, *node1, 2, poolTxs1)); + ASSERT_TRUE(waitForPoolSize(NODE_2, *node2, 2, poolTxs2)); + + //timer.stop(); + + std::vector poolTxsIds1; + std::vector poolTxsIds2; + + for (auto& tx : poolTxs1) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds1.emplace_back(std::move(txHash)); + } + for (auto& tx : poolTxs2) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds2.emplace_back(std::move(txHash)); + } + + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash1) != poolTxsIds1.end()); + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash2) != poolTxsIds1.end()); + + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash1) != poolTxsIds2.end()); + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash2) != poolTxsIds2.end()); + } + + TEST_F(NodeTxPoolSyncTest, TxPoolsAreRequestedRightAfterTimedBlockchainsSynchronization) { + //System::Timer timer(m_dispatcher); + //m_dispatcher.spawn([&m_dispatcher, &timer] { + // try { + // timer.sleep(std::chrono::minutes(5)); + // m_dispatcher. + // } catch (System::InterruptedException&) { + // } + //}); + + const size_t NODE_0 = 0; + const size_t NODE_1 = 1; + const size_t NODE_2 = 2; + const size_t NODE_3 = 3; + const size_t NODE_4 = 4; + + launchTestnet(5, Tests::Common::BaseFunctionalTest::Line); + + std::unique_ptr node0; + std::unique_ptr node1; + std::unique_ptr node2; + std::unique_ptr node3; + std::unique_ptr node4; + + nodeDaemons[NODE_0]->makeINode(node0); + nodeDaemons[NODE_1]->makeINode(node1); + nodeDaemons[NODE_2]->makeINode(node2); + nodeDaemons[NODE_3]->makeINode(node3); + nodeDaemons[NODE_4]->makeINode(node4); + + CryptoNote::account_base minerAccount; + minerAccount.generate(); + + TestWallet wallet1(m_dispatcher, m_currency, *node1); + ASSERT_FALSE(static_cast(wallet1.init())); + + stopNode(NODE_4); + waitForPeerCount(*node3, 1); + + stopNode(NODE_3); + waitForPeerCount(*node2, 1); + + stopNode(NODE_2); + waitForPeerCount(*node1, 1); + + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet1.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], minerAccount.get_keys().m_account_address, m_currency.minedMoneyUnlockWindow())); + wallet1.waitForSynchronizationToHeight(static_cast(m_currency.minedMoneyUnlockWindow()) + 2); + + TransactionHash txHash1; + ASSERT_FALSE(static_cast(wallet1.sendTransaction(m_currency.accountAddressAsString(minerAccount), m_currency.coin(), txHash1))); + + // Start nodes simultaneously due to them connect each other and decided that they are connected to network + startNode(NODE_4); + startNode(NODE_3); + waitDaemonReady(NODE_4); + waitDaemonReady(NODE_3); + waitForPeerCount(*node4, 1); + waitForPeerCount(*node3, 1); + + //std::this_thread::sleep_for(std::chrono::seconds(5)); + + startNode(NODE_2); + waitDaemonReady(NODE_2); + + // NODE_3 and NODE_4 are synchronized by timer + std::vector poolTxs2; + std::vector poolTxs3; + std::vector poolTxs4; + ASSERT_TRUE(waitForPoolSize(NODE_2, *node2, 1, poolTxs2)); + ASSERT_TRUE(waitForPoolSize(NODE_3, *node3, 1, poolTxs3)); + ASSERT_TRUE(waitForPoolSize(NODE_4, *node4, 1, poolTxs4)); + + //timer.stop(); + + TransactionHash poolTxId2 = toTransactionHash(CryptoNote::get_transaction_hash(poolTxs2.front())); + TransactionHash poolTxId3 = toTransactionHash(CryptoNote::get_transaction_hash(poolTxs3.front())); + TransactionHash poolTxId4 = toTransactionHash(CryptoNote::get_transaction_hash(poolTxs4.front())); + + ASSERT_EQ(txHash1, poolTxId2); + ASSERT_EQ(txHash1, poolTxId3); + ASSERT_EQ(txHash1, poolTxId4); + } + + TEST_F(NodeTxPoolSyncTest, TxPoolsAreRequestedRightAfterSwitchingToAlternativeChain) { + // If this condition isn't true, then test must be rewritten a bit + ASSERT_GT(m_currency.difficultyLag() + m_currency.difficultyCut(), m_currency.minedMoneyUnlockWindow()); + + //System::Timer timer(m_dispatcher); + //m_dispatcher.spawn([&m_dispatcher, &timer] { + // try { + // timer.sleep(std::chrono::minutes(5)); + // m_dispatcher. + // } catch (System::InterruptedException&) { + // } + //}); + + const size_t NODE_0 = 0; + const size_t NODE_1 = 1; + const size_t NODE_2 = 2; + const size_t NODE_3 = 3; + const size_t NODE_4 = 4; + const size_t NODE_5 = 5; + + launchTestnet(6, Tests::Common::BaseFunctionalTest::Line); + + std::unique_ptr node0; + std::unique_ptr node1; + std::unique_ptr node2; + std::unique_ptr node3; + std::unique_ptr node4; + std::unique_ptr node5; + + nodeDaemons[NODE_0]->makeINode(node0); + nodeDaemons[NODE_1]->makeINode(node1); + nodeDaemons[NODE_2]->makeINode(node2); + nodeDaemons[NODE_3]->makeINode(node3); + nodeDaemons[NODE_4]->makeINode(node4); + nodeDaemons[NODE_5]->makeINode(node5); + + TestWallet wallet0(m_dispatcher, m_currency, *node1); + TestWallet wallet1(m_dispatcher, m_currency, *node1); + TestWallet wallet2(m_dispatcher, m_currency, *node2); + TestWallet wallet5(m_dispatcher, m_currency, *node5); + + ASSERT_FALSE(static_cast(wallet0.init())); + ASSERT_FALSE(static_cast(wallet1.init())); + ASSERT_FALSE(static_cast(wallet2.init())); + ASSERT_FALSE(static_cast(wallet5.init())); + + uint32_t blockchainLenght = 1; + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet0.address(), m_currency.difficultyBlocksCount())); + blockchainLenght += static_cast(m_currency.difficultyBlocksCount()); + + wallet1.waitForSynchronizationToHeight(blockchainLenght); + wallet2.waitForSynchronizationToHeight(blockchainLenght); + wallet5.waitForSynchronizationToHeight(blockchainLenght); + + stopNode(NODE_2); + // To make sure new blocks won't be received by NODE_2 + waitForPeerCount(*node1, 1); + + // Generate alternative chain for NODE_1 + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet1.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_0], wallet2.address(), m_currency.minedMoneyUnlockWindow())); + blockchainLenght += 1 + static_cast(m_currency.minedMoneyUnlockWindow()); + + wallet1.waitForSynchronizationToHeight(blockchainLenght); + + // This transaction is valid in both alternative chains, it is just an indicator, that shows when NODE_1 and NODE_2 are synchronized + TransactionHash txHash0; + ASSERT_FALSE(static_cast(wallet0.sendTransaction(wallet0.wallet()->getAddress(), m_currency.coin(), txHash0))); + + // This transaction is valid only in alternative chain 1 + TransactionHash txHash1; + ASSERT_FALSE(static_cast(wallet1.sendTransaction(wallet0.wallet()->getAddress(), m_currency.coin(), txHash1))); + + stopNode(NODE_1); + // Don't start NODE_2, while NODE_1 doesn't close its connections + waitForPeerCount(*node0, 0); + + startNode(NODE_2); + waitDaemonReady(NODE_2); + waitForPeerCount(*node3, 1); + + // Generate alternative chain for NODE_2. + // After that it is expected that alternative chains 1 and 2 have the same difficulty, because + // m_currency.minedMoneyUnlockWindow() < m_currency.difficultyLag() + m_currency.difficultyCut() + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_5], wallet2.address(), 1)); + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_5], wallet1.address(), m_currency.minedMoneyUnlockWindow())); + + wallet2.waitForSynchronizationToHeight(blockchainLenght); + wallet5.waitForSynchronizationToHeight(blockchainLenght); + + // Tear connection between NODE_2 and nodes 4 and 5, in order to this nodes doesn't receive new transactions + stopNode(NODE_3); + waitForPeerCount(*node4, 1); + + // This transaction is valid only in alternative chain 2 + TransactionHash txHash2; + ASSERT_FALSE(static_cast(wallet2.sendTransaction(wallet0.wallet()->getAddress(), m_currency.coin(), txHash2))); + + startNode(NODE_1); + waitDaemonReady(NODE_1); + waitForPeerCount(*node2, 1); + + std::vector poolTxs2; + ASSERT_TRUE(waitForPoolSize(NODE_2, *node2, 2, poolTxs2)); + + // Now NODE_1 and NODE_2 are synchronized, but both are on its own alternative chains + // Add block to alternative chain 2, and wait for when NODE_1 switches to alternative chain 2. + ASSERT_TRUE(mineBlocks(*nodeDaemons[NODE_5], wallet1.address(), 1)); + blockchainLenght += 1; + + startNode(NODE_3); + waitDaemonReady(NODE_3); + waitForPeerCount(*node2, 2); + + wallet1.waitForSynchronizationToHeight(blockchainLenght); + wallet2.waitForSynchronizationToHeight(blockchainLenght); + + std::vector poolTxs1; + ASSERT_TRUE(waitForPoolSize(NODE_1, *node1, 2, poolTxs1)); + ASSERT_TRUE(waitForPoolSize(NODE_2, *node2, 2, poolTxs2)); + + //timer.stop(); + + std::vector poolTxsIds1; + std::vector poolTxsIds2; + + for (auto& tx : poolTxs1) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds1.emplace_back(std::move(txHash)); + } + for (auto& tx : poolTxs2) { + TransactionHash txHash = toTransactionHash(CryptoNote::get_transaction_hash(tx)); + poolTxsIds2.emplace_back(std::move(txHash)); + } + + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash0) != poolTxsIds1.end()); + ASSERT_TRUE(std::find(poolTxsIds1.begin(), poolTxsIds1.end(), txHash2) != poolTxsIds1.end()); + + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash0) != poolTxsIds2.end()); + ASSERT_TRUE(std::find(poolTxsIds2.begin(), poolTxsIds2.end(), txHash2) != poolTxsIds2.end()); + } +} diff --git a/tests/unit_tests/ICoreStub.cpp b/tests/unit_tests/ICoreStub.cpp index 7ef0890c..ddb05fd0 100755 --- a/tests/unit_tests/ICoreStub.cpp +++ b/tests/unit_tests/ICoreStub.cpp @@ -17,6 +17,8 @@ #include "ICoreStub.h" +#include "cryptonote_core/cryptonote_format_utils.h" + bool ICoreStub::addObserver(CryptoNote::ICoreObserver* observer) { return true; } @@ -77,17 +79,113 @@ void ICoreStub::set_random_outs(const CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS randomOutsResult = result; } -bool ICoreStub::getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, bool& isBcActual, std::vector& new_txs, std::vector& deleted_tx_ids) { +std::vector ICoreStub::getPoolTransactions() { + return std::vector(); +} + +bool ICoreStub::getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) { return true; } +void ICoreStub::getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) { +} + bool ICoreStub::queryBlocks(const std::list& block_ids, uint64_t timestamp, uint64_t& start_height, uint64_t& current_height, uint64_t& full_offset, std::list& entries) { //stub return true; } +crypto::hash ICoreStub::getBlockIdByHeight(uint64_t height) { + auto iter = blockHashByHeightIndex.find(height); + if (iter == blockHashByHeightIndex.end()) { + return boost::value_initialized(); + } + return iter->second; +} + bool ICoreStub::getBlockByHash(const crypto::hash &h, CryptoNote::Block &blk) { - //stub + auto iter = blocks.find(h); + if (iter == blocks.end()) { + return false; + } + blk = iter->second; return true; } + +void ICoreStub::getTransactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs, bool checkTxPool) { + for (const crypto::hash& hash : txs_ids) { + auto iter = transactions.find(hash); + if (iter != transactions.end()) { + txs.push_back(iter->second); + } else { + missed_txs.push_back(hash); + } + } +} + +bool ICoreStub::getBackwardBlocksSizes(uint64_t fromHeight, std::vector& sizes, size_t count) { + return true; +} + +bool ICoreStub::getBlockSize(const crypto::hash& hash, size_t& size) { + return true; +} + +bool ICoreStub::getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) { + return true; +} + +bool ICoreStub::getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, + bool penalizeFee, uint64_t& reward, int64_t& emissionChange) { + return true; +} + +bool ICoreStub::scanOutputkeysForIndices(const CryptoNote::TransactionInputToKey& txInToKey, std::list>& outputReferences) { + return true; +} + +bool ICoreStub::getBlockDifficulty(uint64_t height, CryptoNote::difficulty_type& difficulty) { + return true; +} + +bool ICoreStub::getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) { + auto iter = blockHashByTxHashIndex.find(txId); + if (iter == blockHashByTxHashIndex.end()) { + return false; + } + blockId = iter->second; + auto blockIter = blocks.find(blockId); + if (blockIter == blocks.end()) { + return false; + } + blockHeight = boost::get(blockIter->second.minerTx.vin.front()).height; + return true; +} + +bool ICoreStub::getMultisigOutputReference(const CryptoNote::TransactionInputMultisignature& txInMultisig, std::pair& outputReference) { + return true; +} + +void ICoreStub::addBlock(const CryptoNote::Block& block) { + uint64_t height = boost::get(block.minerTx.vin.front()).height; + crypto::hash hash = CryptoNote::get_block_hash(block); + if (height > topHeight) { + topHeight = height; + topId = hash; + } + blocks.emplace(std::make_pair(hash, block)); + blockHashByHeightIndex.emplace(std::make_pair(height, hash)); + + blockHashByTxHashIndex.emplace(std::make_pair(CryptoNote::get_transaction_hash(block.minerTx), hash)); + for (auto txHash : block.txHashes) { + blockHashByTxHashIndex.emplace(std::make_pair(txHash, hash)); + } +} + +void ICoreStub::addTransaction(const CryptoNote::Transaction& tx) { + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + transactions.emplace(std::make_pair(hash, tx)); +} diff --git a/tests/unit_tests/ICoreStub.h b/tests/unit_tests/ICoreStub.h index 740f4d6c..c3e72e33 100644 --- a/tests/unit_tests/ICoreStub.h +++ b/tests/unit_tests/ICoreStub.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include "cryptonote_core/cryptonote_basic.h" #include "cryptonote_core/ICore.h" @@ -40,12 +41,14 @@ public: virtual bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs); virtual CryptoNote::i_cryptonote_protocol* get_protocol(); virtual bool handle_incoming_tx(CryptoNote::blobdata const& tx_blob, CryptoNote::tx_verification_context& tvc, bool keeped_by_block); - virtual bool getPoolSymmetricDifference(const std::vector& known_pool_tx_ids, const crypto::hash& known_block_id, bool& isBcActual, std::vector& new_txs, std::vector& deleted_tx_ids) override; + virtual std::vector getPoolTransactions() override; + virtual bool getPoolChanges(const crypto::hash& tailBlockId, const std::vector& knownTxsIds, + std::vector& addedTxs, std::vector& deletedTxsIds) override; + virtual void getPoolChanges(const std::vector& knownTxsIds, std::vector& addedTxs, + std::vector& deletedTxsIds) override; virtual bool queryBlocks(const std::list& block_ids, uint64_t timestamp, uint64_t& start_height, uint64_t& current_height, uint64_t& full_offset, std::list& entries); - virtual bool getBlockByHash(const crypto::hash &h, CryptoNote::Block &blk) override; - virtual bool have_block(const crypto::hash& id) override { return false; } virtual bool get_short_chain_history(std::list& ids) override { return false; } virtual bool get_stat_info(CryptoNote::core_stat_info& st_inf) override { return false; } @@ -57,10 +60,26 @@ public: virtual void on_synchronized() override {} virtual bool is_ready() override { return true; } + virtual crypto::hash getBlockIdByHeight(uint64_t height) override; + virtual bool getBlockByHash(const crypto::hash &h, CryptoNote::Block &blk) override; + virtual void getTransactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs, bool checkTxPool = false) override; + virtual bool getBackwardBlocksSizes(uint64_t fromHeight, std::vector& sizes, size_t count) override; + virtual bool getBlockSize(const crypto::hash& hash, size_t& size) override; + virtual bool getAlreadyGeneratedCoins(const crypto::hash& hash, uint64_t& generatedCoins) override; + virtual bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, + bool penalizeFee, uint64_t& reward, int64_t& emissionChange) override; + virtual bool scanOutputkeysForIndices(const CryptoNote::TransactionInputToKey& txInToKey, std::list>& outputReferences) override; + virtual bool getBlockDifficulty(uint64_t height, CryptoNote::difficulty_type& difficulty) override; + virtual bool getBlockContainingTx(const crypto::hash& txId, crypto::hash& blockId, uint64_t& blockHeight) override; + virtual bool getMultisigOutputReference(const CryptoNote::TransactionInputMultisignature& txInMultisig, std::pair& outputReference) override; + void set_blockchain_top(uint64_t height, const crypto::hash& top_id, bool result); void set_outputs_gindexs(const std::vector& indexs, bool result); void set_random_outs(const CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response& resp, bool result); + void addBlock(const CryptoNote::Block& block); + void addTransaction(const CryptoNote::Transaction& tx); + private: uint64_t topHeight; crypto::hash topId; @@ -71,4 +90,11 @@ private: CryptoNote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_response randomOuts; bool randomOutsResult; + + std::unordered_map blocks; + std::unordered_map blockHashByHeightIndex; + std::unordered_map blockHashByTxHashIndex; + + std::unordered_map transactions; + }; diff --git a/tests/unit_tests/ICryptonoteProtocolQueryStub.cpp b/tests/unit_tests/ICryptonoteProtocolQueryStub.cpp index b3c242fb..53aa40bf 100644 --- a/tests/unit_tests/ICryptonoteProtocolQueryStub.cpp +++ b/tests/unit_tests/ICryptonoteProtocolQueryStub.cpp @@ -33,6 +33,10 @@ size_t ICryptonoteProtocolQueryStub::getPeerCount() const { return peers; } +bool ICryptonoteProtocolQueryStub::isSynchronized() const { + return synchronized; +} + void ICryptonoteProtocolQueryStub::setPeerCount(uint32_t count) { peers = count; } @@ -40,3 +44,7 @@ void ICryptonoteProtocolQueryStub::setPeerCount(uint32_t count) { void ICryptonoteProtocolQueryStub::setObservedHeight(uint64_t height) { observedHeight = height; } + +void ICryptonoteProtocolQueryStub::setSynchronizedStatus(bool status) { + synchronized = status; +} diff --git a/tests/unit_tests/ICryptonoteProtocolQueryStub.h b/tests/unit_tests/ICryptonoteProtocolQueryStub.h index fbf55ff2..ed8b7742 100644 --- a/tests/unit_tests/ICryptonoteProtocolQueryStub.h +++ b/tests/unit_tests/ICryptonoteProtocolQueryStub.h @@ -24,16 +24,22 @@ class ICryptonoteProtocolQueryStub: public CryptoNote::ICryptonoteProtocolQuery { public: - ICryptonoteProtocolQueryStub() : peers(0), observedHeight(0) {} + ICryptonoteProtocolQueryStub() : peers(0), observedHeight(0), synchronized(false) {} virtual bool addObserver(CryptoNote::ICryptonoteProtocolObserver* observer); virtual bool removeObserver(CryptoNote::ICryptonoteProtocolObserver* observer); virtual uint64_t getObservedHeight() const; virtual size_t getPeerCount() const; + virtual bool isSynchronized() const; + void setPeerCount(uint32_t count); void setObservedHeight(uint64_t height); + void setSynchronizedStatus(bool status); + private: size_t peers; uint64_t observedHeight; + + bool synchronized; }; diff --git a/tests/unit_tests/INodeStubs.cpp b/tests/unit_tests/INodeStubs.cpp index 87981944..24b08682 100644 --- a/tests/unit_tests/INodeStubs.cpp +++ b/tests/unit_tests/INodeStubs.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include "crypto/crypto.h" namespace { @@ -290,3 +292,155 @@ void INodeTrivialRefreshStub::includeTransactionsFromPoolToBlock() { INodeTrivialRefreshStub::~INodeTrivialRefreshStub() { m_asyncCounter.waitAsyncContextsFinish(); } + +void INodeTrivialRefreshStub::getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { + m_asyncCounter.addAsyncContext(); + + std::thread task( + std::bind( + static_cast< + void(INodeTrivialRefreshStub::*)( + const std::vector&, + std::vector>&, + const Callback& + ) + >(&INodeTrivialRefreshStub::doGetBlocks), + this, + std::cref(blockHeights), + std::ref(blocks), + callback + ) + ); + task.detach(); +} + +void INodeTrivialRefreshStub::doGetBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { + ContextCounterHolder counterHolder(m_asyncCounter); + std::unique_lock lock(m_multiWalletLock); + + for (const uint64_t& height: blockHeights) { + if (m_blockchainGenerator.getBlockchain().size() <= height) { + callback(std::error_code(EDOM, std::generic_category())); + return; + } + CryptoNote::BlockDetails b = CryptoNote::BlockDetails(); + b.height = height; + b.isOrphaned = false; + crypto::hash hash = CryptoNote::get_block_hash(m_blockchainGenerator.getBlockchain()[height]); + b.hash = reinterpret_cast&>(hash); + std::vector v; + v.push_back(b); + blocks.push_back(v); + } + + callback(std::error_code()); +} + +void INodeTrivialRefreshStub::getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { + m_asyncCounter.addAsyncContext(); + + std::thread task( + std::bind( + static_cast< + void(INodeTrivialRefreshStub::*)( + const std::vector&, + std::vector&, + const Callback& + ) + >(&INodeTrivialRefreshStub::doGetBlocks), + this, + std::cref(blockHashes), + std::ref(blocks), + callback + ) + ); + task.detach(); +} + +void INodeTrivialRefreshStub::doGetBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { + ContextCounterHolder counterHolder(m_asyncCounter); + std::unique_lock lock(m_multiWalletLock); + + for (const crypto::hash& hash: blockHashes) { + auto iter = std::find_if( + m_blockchainGenerator.getBlockchain().begin(), + m_blockchainGenerator.getBlockchain().end(), + [&hash](const CryptoNote::Block& block) -> bool { + return hash == CryptoNote::get_block_hash(block); + } + ); + if (iter == m_blockchainGenerator.getBlockchain().end()) { + callback(std::error_code(EDOM, std::generic_category())); + return; + } + CryptoNote::BlockDetails b = CryptoNote::BlockDetails(); + crypto::hash actualHash = CryptoNote::get_block_hash(*iter); + b.hash = reinterpret_cast&>(actualHash); + b.isOrphaned = false; + blocks.push_back(b); + } + + callback(std::error_code()); +} + +void INodeTrivialRefreshStub::getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { + m_asyncCounter.addAsyncContext(); + + std::thread task( + std::bind( + &INodeTrivialRefreshStub::doGetTransactions, + this, + std::cref(transactionHashes), + std::ref(transactions), + callback + ) + ); + task.detach(); +} + +void INodeTrivialRefreshStub::doGetTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { + ContextCounterHolder counterHolder(m_asyncCounter); + std::unique_lock lock(m_multiWalletLock); + + for (const crypto::hash& hash : transactionHashes) { + CryptoNote::Transaction tx; + CryptoNote::TransactionDetails txDetails = CryptoNote::TransactionDetails(); + if (m_blockchainGenerator.getTransactionByHash(hash, tx, false)) { + crypto::hash actualHash = CryptoNote::get_transaction_hash(tx); + txDetails.hash = reinterpret_cast&>(actualHash); + txDetails.inBlockchain = true; + } else if (m_blockchainGenerator.getTransactionByHash(hash, tx, true)) { + crypto::hash actualHash = CryptoNote::get_transaction_hash(tx); + txDetails.hash = reinterpret_cast&>(actualHash); + txDetails.inBlockchain = false; + } else { + callback(std::error_code(EDOM, std::generic_category())); + return; + } + + transactions.push_back(txDetails); + } + + callback(std::error_code()); +} + +void INodeTrivialRefreshStub::isSynchronized(bool& syncStatus, const Callback& callback) { + //m_asyncCounter.addAsyncContext(); + syncStatus = m_synchronized; + callback(std::error_code()); +} + +void INodeTrivialRefreshStub::setSynchronizedStatus(bool status) { + m_synchronized = status; + if (m_synchronized) { + observerManager.notify(&CryptoNote::INodeObserver::blockchainSynchronized, getLastLocalBlockHeight()); + } +} + +void INodeTrivialRefreshStub::sendPoolChanged() { + observerManager.notify(&CryptoNote::INodeObserver::poolChanged); +} + +void INodeTrivialRefreshStub::sendLocalBlockchainUpdated(){ + observerManager.notify(&CryptoNote::INodeObserver::localBlockchainUpdated, getLastLocalBlockHeight()); +} diff --git a/tests/unit_tests/INodeStubs.h b/tests/unit_tests/INodeStubs.h index 03ed9cec..a55f65fd 100644 --- a/tests/unit_tests/INodeStubs.h +++ b/tests/unit_tests/INodeStubs.h @@ -51,6 +51,11 @@ public: virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) override { is_bc_actual = true; callback(std::error_code()); }; virtual void queryBlocks(std::list&& knownBlockIds, uint64_t timestamp, std::list& newBlocks, uint64_t& startHeight, const Callback& callback) { callback(std::error_code()); }; + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) { callback(std::error_code()); }; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) { callback(std::error_code()); }; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) { callback(std::error_code()); }; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) { callback(std::error_code()); }; + void updateObservers(); tools::ObserverManager observerManager; @@ -61,7 +66,7 @@ class INodeTrivialRefreshStub : public INodeDummyStub { public: INodeTrivialRefreshStub(TestBlockchainGenerator& generator) : - m_lastHeight(1), m_blockchainGenerator(generator), m_nextTxError(false), m_getMaxBlocks(std::numeric_limits::max()), m_nextTxToPool(false) {}; + m_lastHeight(1), m_blockchainGenerator(generator), m_nextTxError(false), m_getMaxBlocks(std::numeric_limits::max()), m_nextTxToPool(false), m_synchronized(false) {}; void setGetNewBlocksLimit(size_t maxBlocks) { m_getMaxBlocks = maxBlocks; } @@ -77,11 +82,21 @@ public: virtual void getPoolSymmetricDifference(std::vector&& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback) override; + virtual void getBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback) override; + virtual void getTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback) override; + virtual void isSynchronized(bool& syncStatus, const Callback& callback) override; + virtual void startAlternativeChain(uint64_t height); void setNextTransactionError(); void setNextTransactionToPool(); void includeTransactionsFromPoolToBlock(); + void setSynchronizedStatus(bool status); + + void sendPoolChanged(); + void sendLocalBlockchainUpdated(); + std::vector calls_getTransactionOutsGlobalIndices; virtual ~INodeTrivialRefreshStub(); @@ -95,6 +110,10 @@ protected: void doGetPoolSymmetricDifference(std::vector& known_pool_tx_ids, crypto::hash known_block_id, bool& is_bc_actual, std::vector& new_txs, std::vector& deleted_tx_ids, const Callback& callback); + void doGetBlocks(const std::vector& blockHeights, std::vector>& blocks, const Callback& callback); + void doGetBlocks(const std::vector& blockHashes, std::vector& blocks, const Callback& callback); + void doGetTransactions(const std::vector& transactionHashes, std::vector& transactions, const Callback& callback); + size_t m_getMaxBlocks; uint64_t m_lastHeight; TestBlockchainGenerator& m_blockchainGenerator; @@ -102,4 +121,6 @@ protected: bool m_nextTxToPool; std::mutex m_multiWalletLock; CryptoNote::WalletAsyncContextCounter m_asyncCounter; + + bool m_synchronized; }; diff --git a/tests/unit_tests/TransactionApi.cpp b/tests/unit_tests/TransactionApi.cpp index 12e53599..2948acc9 100644 --- a/tests/unit_tests/TransactionApi.cpp +++ b/tests/unit_tests/TransactionApi.cpp @@ -16,7 +16,10 @@ // along with Bytecoin. If not, see . #include "gtest/gtest.h" + +#include #include + #include "cryptonote_core/TransactionApi.h" #include "cryptonote_core/cryptonote_format_utils.h" // TODO: delete #include "cryptonote_core/account.h" @@ -294,6 +297,27 @@ TEST_F(TransactionApi, setExtraNonce) { ASSERT_EQ(extraNonce, s); } +TEST_F(TransactionApi, appendExtra) { + Blob blob; + + blob.resize(100); + std::iota(blob.begin(), blob.end(), 0); + + auto tx = createTransaction(); + + auto extra = tx->getExtra(); + + ASSERT_FALSE(extra.empty()); + + tx->appendExtra(blob); + + auto newExtra = tx->getExtra(); + + ASSERT_EQ(blob.size() + extra.size(), newExtra.size()); + ASSERT_EQ(0, memcmp(newExtra.data() + extra.size(), blob.data(), blob.size())); +} + + TEST_F(TransactionApi, doubleSpendInTransactionKey) { TransactionTypes::InputKeyInfo info = createInputInfo(1000); diff --git a/tests/unit_tests/binary_serialization_compatibility.cpp b/tests/unit_tests/binary_serialization_compatibility.cpp index c8d267ed..a0d7f389 100644 --- a/tests/unit_tests/binary_serialization_compatibility.cpp +++ b/tests/unit_tests/binary_serialization_compatibility.cpp @@ -30,7 +30,6 @@ #include "serialization_structs_comparators.h" #include -#include "string_tools.h" template void checkEqualBinary(Struct& original) { @@ -54,8 +53,6 @@ void checkEnumeratorToLegacy(Struct& original) { CryptoNote::BinaryOutputStreamSerializer binarySerializer(archive); binarySerializer(original, ""); - //std::cout << "enumerated string: " << epee::string_tools::buff_to_hex_nodelimer(archive.str()) << std::endl; - Struct restored; binary_archive ba(archive); bool r = ::serialization::serialize(ba, restored); @@ -72,8 +69,6 @@ void checkLegacyToEnumerator(Struct& original) { bool r = ::serialization::serialize(ba, original); ASSERT_TRUE(r); - //std::cout << "legacy string: " << epee::string_tools::buff_to_hex_nodelimer(archive.str()) << std::endl; - Struct restored; CryptoNote::BinaryInputStreamSerializer binarySerializer(archive); @@ -463,8 +458,6 @@ void checkEnumeratorToEnumerator(CryptoNote::Block& block) { CryptoNote::Block restoredBlock; -// std::cout << "enumerated string: " << epee::string_tools::buff_to_hex_nodelimer(archive.str()) << std::endl; - CryptoNote::BinaryInputStreamSerializer input(archive); input(restoredBlock, ""); diff --git a/tests/unit_tests/get_xtype_from_string.cpp b/tests/unit_tests/get_xtype_from_string.cpp deleted file mode 100644 index 1b8e5dd9..00000000 --- a/tests/unit_tests/get_xtype_from_string.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers -// -// This file is part of Bytecoin. -// -// Bytecoin is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Bytecoin is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with Bytecoin. If not, see . - -#include "gtest/gtest.h" - -#include - -// epee -#include - -using namespace epee::string_tools; - -namespace -{ - template - void do_pos_test(T expected, const std::string& str) - { - T val; - ASSERT_TRUE(get_xtype_from_string(val, str)); - ASSERT_EQ(expected, val); - } - - template - void do_neg_test(const std::string& str) - { - T val; - ASSERT_FALSE(get_xtype_from_string(val, str)); - } -} - -#define TEST_pos(int_type, expected, str) \ - TEST(get_xtype_from_string, handles_pos_ ## int_type ## _ ## expected) \ - { \ - do_pos_test(expected, str); \ - } - -#define DO_MAKE_NEG_TEST_NAME(prefix, int_type, ln) prefix ## int_type ## _ ## ln -#define MAKE_NEG_TEST_NAME(prefix, int_type, ln) DO_MAKE_NEG_TEST_NAME(prefix, int_type, ln) - -#define TEST_neg(int_type, str) \ - TEST(get_xtype_from_string, MAKE_NEG_TEST_NAME(handles_neg, int_type, __LINE__)) \ - { \ - do_neg_test(str); \ - } - -TEST_pos(uint16_t, 0, "0"); -TEST_pos(uint16_t, 1, "1"); -TEST_pos(uint16_t, 65535, "65535"); - -TEST_neg(uint16_t, ""); -TEST_neg(uint16_t, "+0"); -TEST_neg(uint16_t, "+1"); -TEST_neg(uint16_t, "+65535"); -TEST_neg(uint16_t, "+65536"); - -TEST_neg(uint16_t, "-0"); -TEST_neg(uint16_t, "-1"); -TEST_neg(uint16_t, "-65535"); -TEST_neg(uint16_t, "-65536"); - -TEST_neg(uint16_t, ".0"); -TEST_neg(uint16_t, ".1"); -TEST_neg(uint16_t, "0.0"); -TEST_neg(uint16_t, "0.1"); -TEST_neg(uint16_t, "1.0"); -TEST_neg(uint16_t, "1.1"); - -TEST_neg(uint16_t, "w"); -TEST_neg(uint16_t, "0w"); -TEST_neg(uint16_t, "1w"); -TEST_neg(uint16_t, "1w1"); -TEST_neg(uint16_t, "65535w"); - -TEST_neg(uint16_t, "65536"); -TEST_neg(uint16_t, "4294967296"); -TEST_neg(uint16_t, "18446744073709551616"); - - -TEST_pos(uint32_t, 0, "0"); -TEST_pos(uint32_t, 1, "1"); -TEST_pos(uint32_t, 4294967295, "4294967295"); - -TEST_neg(uint32_t, ""); -TEST_neg(uint32_t, "+0"); -TEST_neg(uint32_t, "+1"); -TEST_neg(uint32_t, "+4294967295"); -TEST_neg(uint32_t, "+4294967296"); - -TEST_neg(uint32_t, "-0"); -TEST_neg(uint32_t, "-1"); -TEST_neg(uint32_t, "-4294967295"); -TEST_neg(uint32_t, "-4294967296"); - -TEST_neg(uint32_t, ".0"); -TEST_neg(uint32_t, ".1"); -TEST_neg(uint32_t, "0.0"); -TEST_neg(uint32_t, "0.1"); -TEST_neg(uint32_t, "1.0"); -TEST_neg(uint32_t, "1.1"); - -TEST_neg(uint32_t, "w"); -TEST_neg(uint32_t, "0w"); -TEST_neg(uint32_t, "1w"); -TEST_neg(uint32_t, "1w1"); -TEST_neg(uint32_t, "4294967295w"); - -TEST_neg(uint32_t, "4294967296"); -TEST_neg(uint32_t, "18446744073709551616"); - -TEST_pos(uint64_t, 0, "0"); -TEST_pos(uint64_t, 1, "1"); -TEST_pos(uint64_t, 18446744073709551615ULL, "18446744073709551615"); - -TEST_neg(uint64_t, ""); -TEST_neg(uint64_t, "+0"); -TEST_neg(uint64_t, "+1"); -TEST_neg(uint64_t, "+18446744073709551615"); -TEST_neg(uint64_t, "+18446744073709551616"); - -TEST_neg(uint64_t, "-0"); -TEST_neg(uint64_t, "-1"); -TEST_neg(uint64_t, "-18446744073709551615"); -TEST_neg(uint64_t, "-18446744073709551616"); - -TEST_neg(uint64_t, ".0"); -TEST_neg(uint64_t, ".1"); -TEST_neg(uint64_t, "0.0"); -TEST_neg(uint64_t, "0.1"); -TEST_neg(uint64_t, "1.0"); -TEST_neg(uint64_t, "1.1"); - -TEST_neg(uint64_t, "w"); -TEST_neg(uint64_t, "0w"); -TEST_neg(uint64_t, "1w"); -TEST_neg(uint64_t, "1w1"); -TEST_neg(uint64_t, "18446744073709551615w"); - -TEST_neg(uint64_t, "18446744073709551616"); diff --git a/tests/unit_tests/main.cpp b/tests/unit_tests/main.cpp index a9e2e005..b42fde00 100644 --- a/tests/unit_tests/main.cpp +++ b/tests/unit_tests/main.cpp @@ -19,11 +19,6 @@ int main(int argc, char** argv) { - // epee::debug::get_set_enable_assert(true, false); - //set up logging options - // epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0); - // epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/tests/unit_tests/serialization_kv.cpp b/tests/unit_tests/serialization_kv.cpp index 7cb85956..39d779f7 100644 --- a/tests/unit_tests/serialization_kv.cpp +++ b/tests/unit_tests/serialization_kv.cpp @@ -21,12 +21,8 @@ #include "serialization/KVBinaryInputStreamSerializer.h" #include "serialization/KVBinaryOutputStreamSerializer.h" - -#include "serialization/keyvalue_serialization.h" -#include "serialization/keyvalue_serialization_overloads.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_from_bin.h" -#include "storages/portable_storage_template_helper.h" +#include "serialization/SerializationOverloads.h" +#include "serialization/SerializationTools.h" #include @@ -34,28 +30,6 @@ using namespace CryptoNote; namespace CryptoNote { - -template -void serializeAsPod(Cont& cont, const std::string& name, ISerializer& s) { - - typedef typename Cont::value_type ElementType; - const size_t elementSize = sizeof(ElementType); - std::string buf; - - if (s.type() == ISerializer::INPUT) { - s.binary(buf, name); - const ElementType* ptr = reinterpret_cast(buf.data()); - size_t count = buf.size() / elementSize; - cont.insert(cont.begin(), ptr, ptr + count); - } else { - auto rawSize = cont.size() * elementSize; - auto ptr = reinterpret_cast(cont.data()); - buf.assign(ptr, ptr + rawSize); - s.binary(buf, name); - } -} - - struct TestElement { std::string name; uint32_t nonce; @@ -70,21 +44,11 @@ struct TestElement { u32array == other.u32array; } - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(name) - KV_SERIALIZE(nonce) - KV_SERIALIZE_VAL_POD_AS_BLOB(blob) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(u32array) - END_KV_SERIALIZE_MAP() - - - void serialize(ISerializer& s, const std::string& nm) { - s.beginObject(nm); + void serialize(ISerializer& s) { s(name, "name"); s(nonce, "nonce"); s.binary(blob.data(), blob.size(), "blob"); - serializeAsPod(u32array, "u32array", s); - s.endObject(); + serializeAsBinary(u32array, "u32array", s); } }; @@ -106,24 +70,13 @@ struct TestStruct { vec2 == other.vec2; } - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(root) - KV_SERIALIZE(vec1) - KV_SERIALIZE(vec2) - KV_SERIALIZE(u8) - KV_SERIALIZE(u32) - KV_SERIALIZE(u64) - END_KV_SERIALIZE_MAP() - - void serialize(ISerializer& s, const std::string& name) { - s.beginObject(name); + void serialize(ISerializer& s) { s(root, "root"); s(vec1, "vec1"); s(vec2, "vec2"); s(u8, "u8"); s(u32, "u32"); s(u64, "u64"); - s.endObject(); } }; @@ -150,7 +103,6 @@ private: TEST(KVSerialize, Simple) { TestElement testData1, testData2; - std::string buf; testData1.name = "hello"; testData1.nonce = 12345; @@ -159,82 +111,8 @@ TEST(KVSerialize, Simple) { testData2.name = "bye"; testData2.nonce = 54321; - epee::serialization::store_t_to_binary(testData1, buf); - - std::stringstream s(buf); - KVBinaryInputStreamSerializer kvInput(s); - kvInput.parse(); - kvInput(testData2, ""); - + std::string buf = CryptoNote::storeToBinaryKeyValue(testData1); + ASSERT_TRUE(CryptoNote::loadFromBinaryKeyValue(testData2, buf)); EXPECT_EQ(testData1, testData2); } - -TEST(KVSerialize, NewWriterOldReader) { - std::string bufOld, bufNew; - TestStruct s1; - TestStruct s2; - - s1.u64 = 0xffULL << 50; - s1.vec1.resize(37); - s1.root.name = "somename"; - s1.root.u32array.resize(128); - - s2.u64 = 13; - s2.vec2.resize(10); - - { - HiResTimer t; - epee::serialization::store_t_to_binary(s1, bufOld); - std::cout << "Old serialization: " << t.duration().count() << std::endl; - } - - { - HiResTimer t; - - KVBinaryOutputStreamSerializer kvOut; - kvOut(s1, ""); - std::stringstream out; - kvOut.write(out); - bufNew = out.str(); - - std::cout << "New serialization: " << t.duration().count() << std::endl; - } - - { - HiResTimer t; - TestStruct outStruct(s2); - - std::stringstream s(bufOld); - KVBinaryInputStreamSerializer kvInput(s); - kvInput.parse(); - kvInput(outStruct, ""); - - std::cout << "New deserialization: " << t.duration().count() << std::endl; - - EXPECT_EQ(s1, outStruct); - } - - - { - HiResTimer t; - TestStruct outStruct(s2); - - bool parseOld = epee::serialization::load_t_from_binary(outStruct, bufOld); - - ASSERT_TRUE(parseOld); - - std::cout << "Old deserialization: " << t.duration().count() << std::endl; - - EXPECT_EQ(s1, outStruct); - } - - { - TestStruct outStruct(s2); - bool parseNew = epee::serialization::load_t_from_binary(outStruct, bufNew); - ASSERT_TRUE(parseNew); - EXPECT_EQ(s1, outStruct); - } - - -} diff --git a/tests/unit_tests/test_BlockchainExplorer.cpp b/tests/unit_tests/test_BlockchainExplorer.cpp new file mode 100644 index 00000000..79046597 --- /dev/null +++ b/tests/unit_tests/test_BlockchainExplorer.cpp @@ -0,0 +1,922 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "gtest/gtest.h" + +#include + +#include + +#include "EventWaiter.h" +#include "ICoreStub.h" +#include "ICryptonoteProtocolQueryStub.h" +#include "INodeStubs.h" +#include "cryptonote_core/TransactionApi.h" +#include "TestBlockchainGenerator.h" + +#include "Logging/FileLogger.h" + +#include "BlockchainExplorer/BlockchainExplorer.h" + +namespace { +CryptoNote::Transaction createTx(CryptoNote::ITransactionReader& tx) { + auto data = tx.getTransactionData(); + + CryptoNote::blobdata txblob(data.data(), data.data() + data.size()); + CryptoNote::Transaction outTx; + CryptoNote::parse_and_validate_tx_from_blob(txblob, outTx); + + return outTx; +} +} + +struct CallbackStatus { + CallbackStatus() {} + + bool wait() { return waiter.wait_for(std::chrono::milliseconds(3000)); } + bool ok() { return waiter.wait_for(std::chrono::milliseconds(3000)) && !static_cast(code); } + void setStatus(const std::error_code& ec) { code = ec; waiter.notify(); } + std::error_code getStatus() const { return code; } + + std::error_code code; + EventWaiter waiter; +}; + +class dummyObserver : public CryptoNote::IBlockchainObserver { +public: + virtual ~dummyObserver() {} +}; + +class smartObserver : public CryptoNote::IBlockchainObserver { +public: + virtual ~smartObserver() {} + + virtual void blockchainUpdated(const std::vector& newBlocks, const std::vector& orphanedBlocks) override { + blockchainUpdatedCallback(newBlocks, orphanedBlocks); + } + + virtual void poolUpdated(const std::vector& newTransactions, const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) override { + poolUpdatedCallback(newTransactions, removedTransactions); + } + + virtual void blockchainSynchronized(const CryptoNote::BlockDetails& topBlock) override { + blockchainSynchronizedCallback(topBlock); + } + + void setCallback(const std::function& newBlocks, const std::vector& orphanedBlocks)>& cb) { + blockchainUpdatedCallback = cb; + } + + void setCallback(const std::function& newTransactions, const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions)>& cb) { + poolUpdatedCallback = cb; + } + + void setCallback(std::function& cb) { + blockchainSynchronizedCallback = cb; + } + +private: + std::function& newBlocks, const std::vector& orphanedBlocks)> blockchainUpdatedCallback; + std::function& newTransactions, const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions)> poolUpdatedCallback; + std::function blockchainSynchronizedCallback; +}; + +class BlockchainExplorer : public ::testing::Test { +public: + BlockchainExplorer() : + currency(CryptoNote::CurrencyBuilder(logger).currency()), + generator(currency), + nodeStub(generator), + blockchainExplorer(nodeStub, logger) {} + void SetUp(); + void TearDown(); + +protected: + CryptoNote::Currency currency; + TestBlockchainGenerator generator; + INodeTrivialRefreshStub nodeStub; + Logging::FileLogger logger; + dummyObserver observer; + CryptoNote::BlockchainExplorer blockchainExplorer; +}; + +void BlockchainExplorer::SetUp() { + logger.init("/dev/null"); + ASSERT_NO_THROW(blockchainExplorer.init()); +} + +void BlockchainExplorer::TearDown() { + ASSERT_NO_THROW(blockchainExplorer.shutdown()); +} + +TEST_F(BlockchainExplorer, initOk) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + + ASSERT_NO_THROW(newExplorer.init()); +} + +TEST_F(BlockchainExplorer, shutdownOk) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_NO_THROW(newExplorer.init()); + ASSERT_NO_THROW(newExplorer.shutdown()); +} + +TEST_F(BlockchainExplorer, doubleInit) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_NO_THROW(newExplorer.init()); + ASSERT_ANY_THROW(newExplorer.init()); +} + +TEST_F(BlockchainExplorer, shutdownNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.shutdown()); +} + +TEST_F(BlockchainExplorer, addObserver) { + ASSERT_TRUE(blockchainExplorer.addObserver(&observer)); +} + +TEST_F(BlockchainExplorer, addObserverNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.addObserver(&observer)); +} + +TEST_F(BlockchainExplorer, removeObserver) { + ASSERT_TRUE(blockchainExplorer.addObserver(&observer)); + ASSERT_TRUE(blockchainExplorer.removeObserver(&observer)); +} + +TEST_F(BlockchainExplorer, removeObserverNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.addObserver(&observer)); + ASSERT_ANY_THROW(newExplorer.removeObserver(&observer)); +} + +TEST_F(BlockchainExplorer, removeObserverNotAdded) { + ASSERT_FALSE(blockchainExplorer.removeObserver(&observer)); +} + +TEST_F(BlockchainExplorer, getBlocksByHeightGenesis) { + std::vector blockHeights; + blockHeights.push_back(0); + std::vector> blocks; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlocks(blockHeights, blocks)); + ASSERT_EQ(blocks.size(), 1); + EXPECT_EQ(blockHeights.size(), blocks.size()); + ASSERT_EQ(blocks.front().size(), 1); + EXPECT_EQ(blocks.front().front().height, 0); + EXPECT_FALSE(blocks.front().front().isOrphaned); +} + +TEST_F(BlockchainExplorer, getBlocksByHeightMany) { + const size_t NUMBER_OF_BLOCKS = 10; + std::vector blockHeights; + for (size_t i = 0; i < NUMBER_OF_BLOCKS; ++i) { + blockHeights.push_back(i); + } + std::vector> blocks; + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_GE(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + ASSERT_TRUE(blockchainExplorer.getBlocks(blockHeights, blocks)); + EXPECT_EQ(blocks.size(), NUMBER_OF_BLOCKS); + ASSERT_EQ(blockHeights.size(), blocks.size()); + + auto range = boost::combine(blockHeights, blocks); + for (const boost::tuple>& sameHeight : range) { + EXPECT_EQ(sameHeight.get<1>().size(), 1); + for (const CryptoNote::BlockDetails& block : sameHeight.get<1>()) { + EXPECT_EQ(block.height, sameHeight.get<0>()); + EXPECT_FALSE(block.isOrphaned); + } + } +} + +TEST_F(BlockchainExplorer, getBlocksByHeightFail) { + const size_t NUMBER_OF_BLOCKS = 10; + std::vector blockHeights; + for (size_t i = 0; i < NUMBER_OF_BLOCKS; ++i) { + blockHeights.push_back(i); + } + std::vector> blocks; + + EXPECT_LT(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + ASSERT_ANY_THROW(blockchainExplorer.getBlocks(blockHeights, blocks)); +} + +TEST_F(BlockchainExplorer, getBlocksByHeightNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + std::vector blockHeights; + blockHeights.push_back(0); + std::vector> blocks; + ASSERT_ANY_THROW(newExplorer.getBlocks(blockHeights, blocks)); +} + +TEST_F(BlockchainExplorer, getBlocksByHashGenesis) { + std::vector> blockHashes; + ASSERT_GE(generator.getBlockchain().size(), 1); + + crypto::hash genesisHash = CryptoNote::get_block_hash(generator.getBlockchain().front()); + blockHashes.push_back(reinterpret_cast&>(genesisHash)); + std::vector blocks; + + ASSERT_TRUE(blockchainExplorer.getBlocks(blockHashes, blocks)); + ASSERT_EQ(blocks.size(), 1); + EXPECT_EQ(blockHashes.size(), blocks.size()); + + std::array expectedHash = reinterpret_cast&>(genesisHash); + EXPECT_EQ(blocks.front().hash, expectedHash); + EXPECT_EQ(blocks.front().hash, blockHashes.front()); + EXPECT_FALSE(blocks.front().isOrphaned); +} + +TEST_F(BlockchainExplorer, getBlocksByHashMany) { + const size_t NUMBER_OF_BLOCKS = 10; + std::vector> blockHashes; + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_GE(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + for (const auto& block : generator.getBlockchain()) { + if (blockHashes.size() == NUMBER_OF_BLOCKS) { + break; + } + crypto::hash hash = CryptoNote::get_block_hash(block); + blockHashes.push_back(reinterpret_cast&>(hash)); + } + + std::vector blocks; + + ASSERT_TRUE(blockchainExplorer.getBlocks(blockHashes, blocks)); + EXPECT_EQ(blocks.size(), NUMBER_OF_BLOCKS); + ASSERT_EQ(blockHashes.size(), blocks.size()); + + auto range = boost::combine(blockHashes, blocks); + for (const boost::tuple, CryptoNote::BlockDetails>& hashWithBlock : range) { + EXPECT_EQ(hashWithBlock.get<0>(), hashWithBlock.get<1>().hash); + EXPECT_FALSE(hashWithBlock.get<1>().isOrphaned); + } +} + +TEST_F(BlockchainExplorer, getBlocksByHashFail) { + const size_t NUMBER_OF_BLOCKS = 10; + std::vector> blockHashes; + + for (size_t i = 0; i < NUMBER_OF_BLOCKS; ++i) { + blockHashes.push_back(boost::value_initialized>()); + } + + std::vector blocks; + + EXPECT_LT(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + ASSERT_ANY_THROW(blockchainExplorer.getBlocks(blockHashes, blocks)); + +} + +TEST_F(BlockchainExplorer, getBlocksByHashNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + std::vector> blockHashes; + crypto::hash genesisHash = CryptoNote::get_block_hash(generator.getBlockchain().front()); + blockHashes.push_back(reinterpret_cast&>(genesisHash)); + std::vector blocks; + ASSERT_ANY_THROW(newExplorer.getBlocks(blockHashes, blocks)); +} + +TEST_F(BlockchainExplorer, getBlockchainTop) { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); +} + +TEST_F(BlockchainExplorer, getBlockchainTopNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_ANY_THROW(newExplorer.getBlockchainTop(topBlock)); +} + +TEST_F(BlockchainExplorer, getTransactionFromBlockchain) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + generator.addTxToBlockchain(tx); + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> transactionHashes; + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + transactionHashes.push_back(reinterpret_cast&>(hash)); + + std::vector transactions; + + ASSERT_TRUE(blockchainExplorer.getTransactions(transactionHashes, transactions)); + ASSERT_EQ(transactions.size(), 1); + EXPECT_EQ(transactions.size(), transactionHashes.size()); + + EXPECT_EQ(transactions.front().hash, transactionHashes.front()); + EXPECT_TRUE(transactions.front().inBlockchain); +} + +TEST_F(BlockchainExplorer, getTransactionFromPool) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + generator.putTxToPool(tx); + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> transactionHashes; + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + transactionHashes.push_back(reinterpret_cast&>(hash)); + + std::vector transactions; + + ASSERT_TRUE(blockchainExplorer.getTransactions(transactionHashes, transactions)); + ASSERT_EQ(transactions.size(), 1); + EXPECT_EQ(transactions.size(), transactionHashes.size()); + + EXPECT_EQ(transactions.front().hash, transactionHashes.front()); + EXPECT_FALSE(transactions.front().inBlockchain); +} + +TEST_F(BlockchainExplorer, getTransactionsMany) { + size_t POOL_TX_NUMBER = 10; + size_t BLOCKCHAIN_TX_NUMBER = 10; + std::vector> poolTxs; + std::vector> blockchainTxs; + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + poolTxs.push_back(reinterpret_cast&>(hash)); + generator.putTxToPool(tx); + } + + for (size_t i = 0; i < BLOCKCHAIN_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + blockchainTxs.push_back(reinterpret_cast&>(hash)); + generator.addTxToBlockchain(tx); + } + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> transactionHashes; + std::copy(poolTxs.begin(), poolTxs.end(), std::back_inserter(transactionHashes)); + std::copy(blockchainTxs.begin(), blockchainTxs.end(), std::back_inserter(transactionHashes)); + + std::vector transactions; + + ASSERT_TRUE(blockchainExplorer.getTransactions(transactionHashes, transactions)); + ASSERT_EQ(transactions.size(), POOL_TX_NUMBER + BLOCKCHAIN_TX_NUMBER); + EXPECT_EQ(transactions.size(), transactionHashes.size()); + + for (const std::array& poolTxHash : poolTxs) { + auto iter = std::find_if( + transactions.begin(), + transactions.end(), + [&poolTxHash](const CryptoNote::TransactionDetails& txDetails) -> bool { + return poolTxHash == txDetails.hash; + } + ); + EXPECT_NE(iter, transactions.end()); + EXPECT_EQ(iter->hash, poolTxHash); + EXPECT_FALSE(iter->inBlockchain); + } + + for (const std::array& blockchainTxHash : blockchainTxs) { + auto iter = std::find_if( + transactions.begin(), + transactions.end(), + [&blockchainTxHash](const CryptoNote::TransactionDetails& txDetails) -> bool { + return blockchainTxHash == txDetails.hash; + } + ); + EXPECT_NE(iter, transactions.end()); + EXPECT_EQ(iter->hash, blockchainTxHash); + EXPECT_TRUE(iter->inBlockchain); + } +} + +TEST_F(BlockchainExplorer, getTransactionsFail) { + size_t POOL_TX_NUMBER = 10; + size_t BLOCKCHAIN_TX_NUMBER = 10; + std::vector> poolTxs; + std::vector> blockchainTxs; + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + poolTxs.push_back(reinterpret_cast&>(hash)); + generator.putTxToPool(tx); + } + + for (size_t i = 0; i < BLOCKCHAIN_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + blockchainTxs.push_back(reinterpret_cast&>(hash)); + generator.addTxToBlockchain(tx); + } + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> transactionHashes; + transactionHashes.push_back(boost::value_initialized>()); + + std::vector transactions; + + ASSERT_ANY_THROW(blockchainExplorer.getTransactions(transactionHashes, transactions)); +} + +TEST_F(BlockchainExplorer, getTransactionsNotInited) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + generator.addTxToBlockchain(tx); + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> transactionHashes; + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + transactionHashes.push_back(reinterpret_cast&>(hash)); + + std::vector transactions; + + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + + ASSERT_ANY_THROW(newExplorer.getTransactions(transactionHashes, transactions)); +} + +TEST_F(BlockchainExplorer, getPoolStateEmpty) { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + std::vector> knownPoolTransactionHashes; + std::array knownBlockchainTop = topBlock.hash; + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_TRUE(isBlockchainActual); + + EXPECT_EQ(newTransactions.size(), 0); + EXPECT_EQ(removedTransactions.size(), 0); +} + +TEST_F(BlockchainExplorer, getPoolStateMany) { + size_t POOL_TX_NUMBER = 10; + std::vector> poolTxs; + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + poolTxs.push_back(reinterpret_cast&>(hash)); + generator.putTxToPool(tx); + } + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + std::vector> knownPoolTransactionHashes; + std::array knownBlockchainTop = topBlock.hash; + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_TRUE(isBlockchainActual); + + EXPECT_EQ(newTransactions.size(), POOL_TX_NUMBER); + EXPECT_EQ(removedTransactions.size(), 0); + + for (const std::array& poolTxHash : poolTxs) { + auto iter = std::find_if( + newTransactions.begin(), + newTransactions.end(), + [&poolTxHash](const CryptoNote::TransactionDetails& txDetails) -> bool { + return poolTxHash == txDetails.hash; + } + ); + EXPECT_NE(iter, newTransactions.end()); + EXPECT_EQ(iter->hash, poolTxHash); + EXPECT_FALSE(iter->inBlockchain); + } + } + + generator.putTxPoolToBlockchain(); + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + std::vector> knownPoolTransactionHashes; + std::array knownBlockchainTop = topBlock.hash; + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_TRUE(isBlockchainActual); + + EXPECT_EQ(newTransactions.size(), 0); + EXPECT_EQ(removedTransactions.size(), 0); + } + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + std::vector> knownPoolTransactionHashes = poolTxs; + std::array knownBlockchainTop = topBlock.hash; + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_TRUE(isBlockchainActual); + + EXPECT_EQ(newTransactions.size(), 0); + EXPECT_EQ(removedTransactions.size(), POOL_TX_NUMBER); + + for (const std::array& poolTxHash : knownPoolTransactionHashes) { + auto iter = std::find( + removedTransactions.begin(), + removedTransactions.end(), + poolTxHash + ); + EXPECT_NE(iter, removedTransactions.end()); + EXPECT_EQ(*iter, poolTxHash); + } + } + + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + std::array newTxHash = reinterpret_cast&>(hash); + generator.putTxToPool(tx); + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + std::vector> knownPoolTransactionHashes = poolTxs; + std::array knownBlockchainTop = topBlock.hash; + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_TRUE(isBlockchainActual); + + ASSERT_EQ(newTransactions.size(), 1); + EXPECT_EQ(newTransactions.front().hash, newTxHash); + EXPECT_EQ(removedTransactions.size(), POOL_TX_NUMBER); + + for (const std::array& poolTxHash : knownPoolTransactionHashes) { + auto iter = std::find( + removedTransactions.begin(), + removedTransactions.end(), + poolTxHash + ); + EXPECT_NE(iter, removedTransactions.end()); + EXPECT_EQ(*iter, poolTxHash); + } + } + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + std::vector> knownPoolTransactionHashes; + std::array knownBlockchainTop = boost::value_initialized>(); + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + ASSERT_TRUE(blockchainExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); + EXPECT_FALSE(isBlockchainActual); + } +} + +TEST_F(BlockchainExplorer, getPoolStateNotInited) { + + std::vector> knownPoolTransactionHashes; + std::array knownBlockchainTop = boost::value_initialized>(); + bool isBlockchainActual; + + std::vector newTransactions; + std::vector> removedTransactions; + + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + + ASSERT_ANY_THROW(newExplorer.getPoolState(knownPoolTransactionHashes, knownBlockchainTop, isBlockchainActual, newTransactions, removedTransactions)); +} + +TEST_F(BlockchainExplorer, getRewardBlocksWindow) { + ASSERT_EQ(blockchainExplorer.getRewardBlocksWindow(), CryptoNote::parameters::CRYPTONOTE_REWARD_BLOCKS_WINDOW); +} + +TEST_F(BlockchainExplorer, getRewardBlocksWindowNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.getRewardBlocksWindow()); +} + +TEST_F(BlockchainExplorer, getFullRewardMaxBlockSize) { + ASSERT_EQ(blockchainExplorer.getFullRewardMaxBlockSize(1), CryptoNote::parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1); + ASSERT_EQ(blockchainExplorer.getFullRewardMaxBlockSize(2), CryptoNote::parameters::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE); +} + +TEST_F(BlockchainExplorer, getFullRewardMaxBlockSizeNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.getFullRewardMaxBlockSize(1)); +} + +TEST_F(BlockchainExplorer, isSynchronizedFalse) { + ASSERT_FALSE(blockchainExplorer.isSynchronized()); +} + +TEST_F(BlockchainExplorer, isSynchronizedNotInited) { + CryptoNote::BlockchainExplorer newExplorer(nodeStub, logger); + ASSERT_ANY_THROW(newExplorer.isSynchronized()); +} + +TEST_F(BlockchainExplorer, isSynchronizedNotification) { + smartObserver observer; + CallbackStatus status; + + std::function cb = [&status, this](const CryptoNote::BlockDetails& topBlock){ + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + blockchainExplorer.addObserver(&observer); + + nodeStub.setSynchronizedStatus(true); + ASSERT_TRUE(blockchainExplorer.isSynchronized()); + ASSERT_TRUE(status.wait()); +} + +TEST_F(BlockchainExplorer, blockchainUpdatedEmpty) { + smartObserver observer; + CallbackStatus status; + + std::function< + void(const std::vector& newBlocks, + const std::vector& orphanedBlocks) + > cb = [&status, this](const std::vector& newBlocks, + const std::vector& orphanedBlocks) { + EXPECT_EQ(newBlocks.size(), 0); + EXPECT_EQ(orphanedBlocks.size(), 0); + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + blockchainExplorer.addObserver(&observer); + + nodeStub.sendLocalBlockchainUpdated(); + ASSERT_TRUE(status.wait()); +} + +TEST_F(BlockchainExplorer, blockchainUpdatedMany) { + const size_t NUMBER_OF_BLOCKS = 10; + std::vector> blockHashes; + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_GE(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + for (auto iter = generator.getBlockchain().begin() + 2; iter != generator.getBlockchain().end(); iter++) { + if (blockHashes.size() == NUMBER_OF_BLOCKS) { + break; + } + crypto::hash hash = CryptoNote::get_block_hash(*iter); + blockHashes.push_back(reinterpret_cast&>(hash)); + } + + smartObserver observer; + CallbackStatus status; + + std::function< + void(const std::vector& newBlocks, + const std::vector& orphanedBlocks) + > cb = [&status, &blockHashes, this, NUMBER_OF_BLOCKS](const std::vector& newBlocks, + const std::vector& orphanedBlocks) { + EXPECT_EQ(newBlocks.size(), NUMBER_OF_BLOCKS); + EXPECT_EQ(orphanedBlocks.size(), 0); + + auto range = boost::combine(blockHashes, newBlocks); + for (const boost::tuple, CryptoNote::BlockDetails>& hashWithBlock : range) { + EXPECT_EQ(hashWithBlock.get<0>(), hashWithBlock.get<1>().hash); + EXPECT_FALSE(hashWithBlock.get<1>().isOrphaned); + } + + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + blockchainExplorer.addObserver(&observer); + + nodeStub.sendLocalBlockchainUpdated(); + ASSERT_TRUE(status.wait()); +} + +TEST_F(BlockchainExplorer, poolUpdatedEmpty) { + smartObserver observer; + CallbackStatus status; + + std::function< + void(const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) + > cb = [&status, this](const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) { + EXPECT_EQ(newTransactions.size(), 0); + EXPECT_EQ(removedTransactions.size(), 0); + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + blockchainExplorer.addObserver(&observer); + + nodeStub.sendPoolChanged(); + ASSERT_FALSE(status.wait()); +} + +TEST_F(BlockchainExplorer, poolUpdatedMany) { + size_t POOL_TX_NUMBER = 10; + std::vector> poolTxs; + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + crypto::hash hash = CryptoNote::get_transaction_hash(tx); + poolTxs.push_back(reinterpret_cast&>(hash)); + generator.putTxToPool(tx); + } + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + smartObserver observer; + CallbackStatus status; + + std::function< + void(const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) + > cb = [&status, &poolTxs, this, POOL_TX_NUMBER](const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) { + EXPECT_EQ(newTransactions.size(), POOL_TX_NUMBER); + EXPECT_EQ(removedTransactions.size(), 0); + + for (const std::array& poolTxHash : poolTxs) { + auto iter = std::find_if( + newTransactions.begin(), + newTransactions.end(), + [&poolTxHash](const CryptoNote::TransactionDetails& txDetails) -> bool { + return poolTxHash == txDetails.hash; + } + ); + EXPECT_NE(iter, newTransactions.end()); + EXPECT_EQ(iter->hash, poolTxHash); + EXPECT_FALSE(iter->inBlockchain); + } + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + + std::function< + void(const std::vector& newBlocks, + const std::vector& orphanedBlocks) + > cb1 = [&status, this](const std::vector& newBlocks, + const std::vector& orphanedBlocks) {}; + observer.setCallback(cb1); + + nodeStub.sendLocalBlockchainUpdated(); + + blockchainExplorer.addObserver(&observer); + + nodeStub.sendPoolChanged(); + ASSERT_TRUE(status.wait()); + blockchainExplorer.removeObserver(&observer); + } + + generator.putTxPoolToBlockchain(); + + { + CryptoNote::BlockDetails topBlock; + + ASSERT_GE(generator.getBlockchain().size(), 1); + + ASSERT_TRUE(blockchainExplorer.getBlockchainTop(topBlock)); + EXPECT_EQ(topBlock.height, generator.getBlockchain().size() - 1); + EXPECT_FALSE(topBlock.isOrphaned); + + smartObserver observer; + CallbackStatus status; + CallbackStatus status1; + + std::function< + void(const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) + > cb = [&status, &poolTxs, this, POOL_TX_NUMBER](const std::vector& newTransactions, + const std::vector, CryptoNote::TransactionRemoveReason>>& removedTransactions) { + EXPECT_EQ(newTransactions.size(), 0); + EXPECT_EQ(removedTransactions.size(), POOL_TX_NUMBER); + + for (const std::array& poolTxHash : poolTxs) { + auto iter = std::find_if( + removedTransactions.begin(), + removedTransactions.end(), + [&poolTxHash](const std::pair, CryptoNote::TransactionRemoveReason>& txDetails) -> bool { + return poolTxHash == txDetails.first; + } + ); + EXPECT_NE(iter, removedTransactions.end()); + EXPECT_EQ(iter->first, poolTxHash); + EXPECT_EQ(iter->second, CryptoNote::TransactionRemoveReason::INCLUDED_IN_BLOCK); + } + status.setStatus(std::error_code()); + }; + observer.setCallback(cb); + + std::function< + void(const std::vector& newBlocks, + const std::vector& orphanedBlocks) + > cb1 = [&status1, this](const std::vector& newBlocks, + const std::vector& orphanedBlocks) { + status1.setStatus(std::error_code()); + }; + observer.setCallback(cb1); + + blockchainExplorer.addObserver(&observer); + + nodeStub.sendLocalBlockchainUpdated(); + ASSERT_TRUE(status1.wait()); + + nodeStub.sendPoolChanged(); + ASSERT_TRUE(status.wait()); + blockchainExplorer.removeObserver(&observer); + } + +} diff --git a/tests/unit_tests/test_JsonValue.cpp b/tests/unit_tests/test_JsonValue.cpp new file mode 100644 index 00000000..85eae1a2 --- /dev/null +++ b/tests/unit_tests/test_JsonValue.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers +// +// This file is part of Bytecoin. +// +// Bytecoin is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Bytecoin is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Bytecoin. If not, see . + +#include "gtest/gtest.h" +#include + +using Common::JsonValue; + +namespace { + +std::vector goodPatterns{ + "{}", + " {} ", + " { } ", + "100", + "[10,20,30]", + " [ 10 , \n 20 , \n 30 ] ", + "{\"prop\": 100}", + "{\"prop\": 100, \"prop2\": [100, 20, 30] }", + "{\"prop\": 100, \"prop2\": { \"p\":\"test\" } }", + +}; + + +std::vector badPatterns{ + "", + "1..2", + "\n\n", + "{", + "[", + "[100,", + "[[]", + "\"", + "{\"prop: 100 }", + "{\"prop\" 100 }", + "{ prop: 100 }", +}; + +} + +TEST(JsonValue, testGoodPatterns) { + for (const auto& p : goodPatterns) { + std::cout << "Pattern: " << p << std::endl; + ASSERT_NO_THROW(Common::JsonValue::fromString(p)); + } +} + +TEST(JsonValue, testBadPatterns) { + for (const auto& p : badPatterns) { + ASSERT_ANY_THROW(Common::JsonValue::fromString(p)); + } +} + diff --git a/tests/unit_tests/test_TransfersConsumer.cpp b/tests/unit_tests/test_TransfersConsumer.cpp index 6cea3e55..ed44a74e 100644 --- a/tests/unit_tests/test_TransfersConsumer.cpp +++ b/tests/unit_tests/test_TransfersConsumer.cpp @@ -843,7 +843,7 @@ TEST_F(TransfersConsumerTest, onPoolUpdated_addTransactionDoesNotGetsGlobalIndic // construct tx auto tx = createTransaction(); addTestInput(*tx, 10000); - auto out = addTestKeyOutput(*tx, 10000, UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX, m_accountKeys); + addTestKeyOutput(*tx, 10000, UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX, m_accountKeys); m_consumer.onPoolUpdated({ convertTx(*tx) }, {}); ASSERT_TRUE(m_node.calls_getTransactionOutsGlobalIndices.empty()); diff --git a/tests/unit_tests/test_TransfersContainer.cpp b/tests/unit_tests/test_TransfersContainer.cpp index 665ff059..1ff15b3f 100644 --- a/tests/unit_tests/test_TransfersContainer.cpp +++ b/tests/unit_tests/test_TransfersContainer.cpp @@ -399,7 +399,7 @@ TEST_F(TransfersContainer_addTransaction, addingEmptyTransactionOuptutsDoesNotCh auto tx = createTransaction(); addTestInput(*tx, TEST_OUTPUT_AMOUNT + 1); - auto outInfo = addTestKeyOutput(*tx, TEST_OUTPUT_AMOUNT, TEST_TRANSACTION_OUTPUT_GLOBAL_INDEX); + addTestKeyOutput(*tx, TEST_OUTPUT_AMOUNT, TEST_TRANSACTION_OUTPUT_GLOBAL_INDEX); std::vector outputs; @@ -615,7 +615,7 @@ TEST_F(TransfersContainer_deleteUnconfirmedTransaction, deleteUnconfirmedSpendin { CryptoNote::BlockInfo blockInfo{ UNCONFIRMED_TRANSACTION_HEIGHT, 1000000 }; addInput(*spendingTx, account, transfers[0]); - auto outInfo = addTestKeyOutput(*spendingTx, TEST_OUTPUT_AMOUNT - 1, UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX); + addTestKeyOutput(*spendingTx, TEST_OUTPUT_AMOUNT - 1, UNCONFIRMED_TRANSACTION_GLOBAL_OUTPUT_INDEX); std::vector outputs; ASSERT_TRUE(container.addTransaction(blockInfo, *spendingTx, outputs)); } diff --git a/tests/unit_tests/test_format_utils.cpp b/tests/unit_tests/test_format_utils.cpp index fd5fb77a..dba54c8e 100644 --- a/tests/unit_tests/test_format_utils.cpp +++ b/tests/unit_tests/test_format_utils.cpp @@ -19,9 +19,6 @@ #include -// epee -#include "misc_language.h" - #include "Common/util.h" #include "cryptonote_core/account.h" #include "cryptonote_core/cryptonote_format_utils.h" @@ -29,6 +26,8 @@ #include +#define AUTO_VAL_INIT(n) boost::value_initialized() + TEST(parse_tx_extra, handles_empty_extra) { std::vector extra;; diff --git a/tests/unit_tests/test_inprocess_node.cpp b/tests/unit_tests/test_inprocess_node.cpp index 4794f0b2..60944531 100644 --- a/tests/unit_tests/test_inprocess_node.cpp +++ b/tests/unit_tests/test_inprocess_node.cpp @@ -19,10 +19,15 @@ #include +#include + #include "EventWaiter.h" #include "ICoreStub.h" #include "ICryptonoteProtocolQueryStub.h" #include "InProcessNode/InProcessNode.h" +#include "TestBlockchainGenerator.h" +#include "Logging/FileLogger.h" +#include "cryptonote_core/TransactionApi.h" struct CallbackStatus { CallbackStatus() {} @@ -36,9 +41,24 @@ struct CallbackStatus { EventWaiter waiter; }; +namespace { +CryptoNote::Transaction createTx(CryptoNote::ITransactionReader& tx) { + auto data = tx.getTransactionData(); + + CryptoNote::blobdata txblob(data.data(), data.data() + data.size()); + CryptoNote::Transaction outTx; + CryptoNote::parse_and_validate_tx_from_blob(txblob, outTx); + + return outTx; +} +} + class InProcessNode : public ::testing::Test { public: - InProcessNode() : node(coreStub, protocolQueryStub) {} + InProcessNode() : + node(coreStub, protocolQueryStub), + currency(CryptoNote::CurrencyBuilder(logger).currency()), + generator(currency) {} void SetUp(); protected: @@ -47,9 +67,14 @@ protected: ICoreStub coreStub; ICryptonoteProtocolQueryStub protocolQueryStub; CryptoNote::InProcessNode node; + + CryptoNote::Currency currency; + TestBlockchainGenerator generator; + Logging::FileLogger logger; }; void InProcessNode::SetUp() { + logger.init("/dev/null"); initNode(); } @@ -282,6 +307,375 @@ TEST_F(InProcessNode, getLastLocalBlockTimestampError) { ASSERT_THROW(newNode.getLastLocalBlockTimestamp(), std::exception); } +TEST_F(InProcessNode, getBlocksByHeightEmpty) { + std::vector blockHeights; + std::vector> blocks; + ASSERT_EQ(blockHeights.size(), 0); + ASSERT_EQ(blocks.size(), 0); + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + CallbackStatus status; + node.getBlocks(blockHeights, blocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getBlocksByHeightMany) { + const uint64_t NUMBER_OF_BLOCKS = 10; + + std::vector blockHeights; + std::vector> actualBlocks; + + std::vector expectedBlocks; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_GE(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + for (auto iter = generator.getBlockchain().begin() + 1; iter != generator.getBlockchain().end(); iter++) { + expectedBlocks.push_back(*iter); + blockHeights.push_back(std::move(boost::get(iter->minerTx.vin.front()).height)); + coreStub.addBlock(*iter); + } + + ASSERT_GE(blockHeights.size(), NUMBER_OF_BLOCKS); + ASSERT_EQ(blockHeights.size(), expectedBlocks.size()); + ASSERT_EQ(actualBlocks.size(), 0); + + CallbackStatus status; + node.getBlocks(blockHeights, actualBlocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); + + ASSERT_EQ(blockHeights.size(), expectedBlocks.size()); + ASSERT_EQ(blockHeights.size(), actualBlocks.size()); + auto range1 = boost::combine(blockHeights, expectedBlocks); + auto range = boost::combine(range1, actualBlocks); + for (const boost::tuple, std::vector>& sameHeight : range) { + EXPECT_EQ(sameHeight.get<1>().size(), 1); + for (const CryptoNote::BlockDetails& block : sameHeight.get<1>()) { + EXPECT_EQ(block.height, sameHeight.get<0>().get<0>()); + crypto::hash expectedCryptoHash = CryptoNote::get_block_hash(sameHeight.get<0>().get<1>()); + std::array expectedHash = reinterpret_cast&>(expectedCryptoHash); + EXPECT_EQ(block.hash, expectedHash); + EXPECT_FALSE(block.isOrphaned); + } + } +} + +TEST_F(InProcessNode, getBlocksByHeightFail) { + const uint64_t NUMBER_OF_BLOCKS = 10; + + std::vector blockHeights; + std::vector> actualBlocks; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_LT(generator.getBlockchain().size(), NUMBER_OF_BLOCKS * 2); + + for (const CryptoNote::Block& block : generator.getBlockchain()) { + coreStub.addBlock(block); + } + + for (uint64_t i = 0; i < NUMBER_OF_BLOCKS * 2; ++i) { + blockHeights.push_back(std::move(i)); + } + + ASSERT_EQ(actualBlocks.size(), 0); + + CallbackStatus status; + node.getBlocks(blockHeights, actualBlocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getBlocksByHeightNotInited) { + CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub); + + std::vector blockHeights; + std::vector> blocks; + ASSERT_EQ(blockHeights.size(), 0); + ASSERT_EQ(blocks.size(), 0); + + CallbackStatus status; + newNode.getBlocks(blockHeights, blocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getBlocksByHashEmpty) { + std::vector blockHashes; + std::vector blocks; + ASSERT_EQ(blockHashes.size(), 0); + ASSERT_EQ(blocks.size(), 0); + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + CallbackStatus status; + node.getBlocks(blockHashes, blocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getBlocksByHashMany) { + const uint64_t NUMBER_OF_BLOCKS = 10; + + std::vector blockHashes; + std::vector actualBlocks; + + std::vector expectedBlocks; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_GE(generator.getBlockchain().size(), NUMBER_OF_BLOCKS); + + for (auto iter = generator.getBlockchain().begin() + 1; iter != generator.getBlockchain().end(); iter++) { + expectedBlocks.push_back(*iter); + blockHashes.push_back(CryptoNote::get_block_hash(*iter)); + coreStub.addBlock(*iter); + } + + ASSERT_GE(blockHashes.size(), NUMBER_OF_BLOCKS); + ASSERT_EQ(blockHashes.size(), expectedBlocks.size()); + ASSERT_EQ(actualBlocks.size(), 0); + + CallbackStatus status; + node.getBlocks(blockHashes, actualBlocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); + + ASSERT_EQ(blockHashes.size(), expectedBlocks.size()); + ASSERT_EQ(blockHashes.size(), actualBlocks.size()); + auto range1 = boost::combine(blockHashes, expectedBlocks); + auto range = boost::combine(range1, actualBlocks); + for (const boost::tuple, CryptoNote::BlockDetails>& sameHeight : range) { + crypto::hash expectedCryptoHash = CryptoNote::get_block_hash(sameHeight.get<0>().get<1>()); + EXPECT_EQ(expectedCryptoHash, sameHeight.get<0>().get<0>()); + std::array expectedHash = reinterpret_cast&>(expectedCryptoHash); + EXPECT_EQ(sameHeight.get<1>().hash, expectedHash); + EXPECT_FALSE(sameHeight.get<1>().isOrphaned); + } +} + +TEST_F(InProcessNode, getBlocksByHashFail) { + const uint64_t NUMBER_OF_BLOCKS = 10; + + std::vector blockHashes; + std::vector actualBlocks; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + generator.generateEmptyBlocks(NUMBER_OF_BLOCKS); + ASSERT_LT(generator.getBlockchain().size(), NUMBER_OF_BLOCKS * 2); + + for (const CryptoNote::Block& block : generator.getBlockchain()) { + coreStub.addBlock(block); + } + + for (uint64_t i = 0; i < NUMBER_OF_BLOCKS * 2; ++i) { + blockHashes.push_back(boost::value_initialized()); + } + + ASSERT_EQ(actualBlocks.size(), 0); + + CallbackStatus status; + node.getBlocks(blockHashes, actualBlocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getBlocksByHashNotInited) { + CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub); + + std::vector blockHashes; + std::vector blocks; + ASSERT_EQ(blockHashes.size(), 0); + ASSERT_EQ(blocks.size(), 0); + + CallbackStatus status; + newNode.getBlocks(blockHashes, blocks, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getTxEmpty) { + std::vector transactionHashes; + std::vector transactions; + ASSERT_EQ(transactionHashes.size(), 0); + ASSERT_EQ(transactions.size(), 0); + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + CallbackStatus status; + node.getTransactions(transactionHashes, transactions, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, getTxMany) { + size_t POOL_TX_NUMBER = 10; + size_t BLOCKCHAIN_TX_NUMBER = 10; + + std::vector transactionHashes; + std::vector actualTransactions; + + std::vector> expectedTransactions; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + size_t prevBlockchainSize = generator.getBlockchain().size(); + for (size_t i = 0; i < BLOCKCHAIN_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + transactionHashes.push_back(CryptoNote::get_transaction_hash(tx)); + generator.addTxToBlockchain(tx); + ASSERT_EQ(generator.getBlockchain().size(), prevBlockchainSize + 1); + prevBlockchainSize = generator.getBlockchain().size(); + coreStub.addBlock(generator.getBlockchain().back()); + coreStub.addTransaction(tx); + expectedTransactions.push_back(std::make_tuple(tx, CryptoNote::get_block_hash(generator.getBlockchain().back()), boost::get(generator.getBlockchain().back().minerTx.vin.front()).height)); + } + + ASSERT_EQ(transactionHashes.size(), BLOCKCHAIN_TX_NUMBER); + ASSERT_EQ(transactionHashes.size(), expectedTransactions.size()); + ASSERT_EQ(actualTransactions.size(), 0); + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + transactionHashes.push_back(CryptoNote::get_transaction_hash(tx)); + coreStub.addTransaction(tx); + expectedTransactions.push_back(std::make_tuple(tx, boost::value_initialized(), boost::value_initialized())); + } + + ASSERT_EQ(transactionHashes.size(), BLOCKCHAIN_TX_NUMBER + POOL_TX_NUMBER); + ASSERT_EQ(transactionHashes.size(), expectedTransactions.size()); + ASSERT_EQ(actualTransactions.size(), 0); + + + CallbackStatus status; + node.getTransactions(transactionHashes, actualTransactions, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); + + ASSERT_EQ(transactionHashes.size(), expectedTransactions.size()); + ASSERT_EQ(transactionHashes.size(), actualTransactions.size()); + auto range1 = boost::combine(transactionHashes, actualTransactions); + auto range = boost::combine(range1, expectedTransactions); + for (const boost::tuple, std::tuple>& sameHeight : range) { + crypto::hash expectedCryptoHash = CryptoNote::get_transaction_hash(std::get<0>(sameHeight.get<1>())); + EXPECT_EQ(expectedCryptoHash, sameHeight.get<0>().get<0>()); + std::array expectedHash = reinterpret_cast&>(expectedCryptoHash); + EXPECT_EQ(sameHeight.get<0>().get<1>().hash, expectedHash); + if (std::get<1>(sameHeight.get<1>()) != boost::value_initialized()) { + EXPECT_TRUE(sameHeight.get<0>().get<1>().inBlockchain); + std::array expectedBlockHash = reinterpret_cast&>(std::get<1>(sameHeight.get<1>())); + EXPECT_EQ(sameHeight.get<0>().get<1>().blockHash, expectedBlockHash); + EXPECT_EQ(sameHeight.get<0>().get<1>().blockHeight, std::get<2>(sameHeight.get<1>())); + } else { + EXPECT_FALSE(sameHeight.get<0>().get<1>().inBlockchain); + } + } +} + +TEST_F(InProcessNode, getTxFail) { +size_t POOL_TX_NUMBER = 10; + size_t BLOCKCHAIN_TX_NUMBER = 10; + + std::vector transactionHashes; + std::vector actualTransactions; + + std::vector> expectedTransactions; + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + size_t prevBlockchainSize = generator.getBlockchain().size(); + for (size_t i = 0; i < BLOCKCHAIN_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + transactionHashes.push_back(CryptoNote::get_transaction_hash(tx)); + generator.addTxToBlockchain(tx); + ASSERT_EQ(generator.getBlockchain().size(), prevBlockchainSize + 1); + prevBlockchainSize = generator.getBlockchain().size(); + coreStub.addBlock(generator.getBlockchain().back()); + coreStub.addTransaction(tx); + expectedTransactions.push_back(std::make_tuple(tx, CryptoNote::get_block_hash(generator.getBlockchain().back()), boost::get(generator.getBlockchain().back().minerTx.vin.front()).height)); + } + + ASSERT_EQ(transactionHashes.size(), BLOCKCHAIN_TX_NUMBER); + ASSERT_EQ(transactionHashes.size(), expectedTransactions.size()); + ASSERT_EQ(actualTransactions.size(), 0); + + for (size_t i = 0; i < POOL_TX_NUMBER; ++i) { + auto txptr = CryptoNote::createTransaction(); + auto tx = ::createTx(*txptr.get()); + transactionHashes.push_back(CryptoNote::get_transaction_hash(tx)); + expectedTransactions.push_back(std::make_tuple(tx, boost::value_initialized(), boost::value_initialized())); + } + + ASSERT_EQ(transactionHashes.size(), BLOCKCHAIN_TX_NUMBER + POOL_TX_NUMBER); + ASSERT_EQ(transactionHashes.size(), expectedTransactions.size()); + ASSERT_EQ(actualTransactions.size(), 0); + + + CallbackStatus status; + node.getTransactions(transactionHashes, actualTransactions, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); + +} + +TEST_F(InProcessNode, getTxNotInited) { + CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub); + + std::vector transactionHashes; + std::vector transactions; + ASSERT_EQ(transactionHashes.size(), 0); + ASSERT_EQ(transactions.size(), 0); + + coreStub.set_blockchain_top(0, boost::value_initialized(), true); + + CallbackStatus status; + newNode.getTransactions(transactionHashes, transactions, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + +TEST_F(InProcessNode, isSynchronized) { + bool syncStatus; + { + CallbackStatus status; + node.isSynchronized(syncStatus, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); + ASSERT_FALSE(syncStatus); + } + + protocolQueryStub.setSynchronizedStatus(true); + + { + CallbackStatus status; + node.isSynchronized(syncStatus, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_EQ(std::error_code(), status.getStatus()); + ASSERT_TRUE(syncStatus); + } +} + +TEST_F(InProcessNode, isSynchronizedNotInited) { + CryptoNote::InProcessNode newNode(coreStub, protocolQueryStub); + bool syncStatus; + + CallbackStatus status; + newNode.isSynchronized(syncStatus, [&status] (std::error_code ec) { status.setStatus(ec); }); + ASSERT_TRUE(status.wait()); + ASSERT_NE(std::error_code(), status.getStatus()); +} + //TODO: make relayTransaction unit test //TODO: make getNewBlocks unit test //TODO: make queryBlocks unit test diff --git a/tests/unit_tests/test_peerlist.cpp b/tests/unit_tests/test_peerlist.cpp index 32eee076..704466c8 100644 --- a/tests/unit_tests/test_peerlist.cpp +++ b/tests/unit_tests/test_peerlist.cpp @@ -71,7 +71,6 @@ TEST(peer_list, merge_peer_lists) peerlist_manager plm; plm.init(false); std::list outer_bs; -#define ADD_NODE_TO_PL(ip_, port_, id_, timestamp_) { peerlist_entry ple; epee::string_tools::get_ip_int32_from_string(ple.adr.ip, ip_); ple.last_seen = timestamp_; ple.adr.port = port_; ple.id = id_;outer_bs.push_back(ple);} } diff --git a/tests/unit_tests/test_protocol_pack.cpp b/tests/unit_tests/test_protocol_pack.cpp index d3f06005..b68f39ec 100644 --- a/tests/unit_tests/test_protocol_pack.cpp +++ b/tests/unit_tests/test_protocol_pack.cpp @@ -18,10 +18,8 @@ #include #include "gtest/gtest.h" - -#include "include_base_utils.h" #include "cryptonote_protocol/cryptonote_protocol_defs.h" -#include "storages/portable_storage_template_helper.h" +#include "serialization/SerializationTools.h" TEST(protocol_pack, protocol_pack_command) { @@ -29,14 +27,12 @@ TEST(protocol_pack, protocol_pack_command) CryptoNote::NOTIFY_RESPONSE_CHAIN_ENTRY::request r; r.start_height = 1; r.total_height = 3; - for(int i = 1; i < 10000; i += i*10) - { + for(int i = 1; i < 10000; i += i*10) { r.m_block_ids.resize(i, boost::value_initialized()); - bool res = epee::serialization::store_t_to_binary(r, buff); - ASSERT_TRUE(res); + buff = CryptoNote::storeToBinaryKeyValue(r); CryptoNote::NOTIFY_RESPONSE_CHAIN_ENTRY::request r2; - res = epee::serialization::load_t_from_binary(r2, buff); + bool res = CryptoNote::loadFromBinaryKeyValue(r2, buff); ASSERT_TRUE(r.m_block_ids.size() == i); ASSERT_TRUE(r.start_height == 1); ASSERT_TRUE(r.total_height == 3); diff --git a/tests/unit_tests/tx_pool.cpp b/tests/unit_tests/tx_pool.cpp index 3381b43c..db808958 100644 --- a/tests/unit_tests/tx_pool.cpp +++ b/tests/unit_tests/tx_pool.cpp @@ -19,6 +19,8 @@ #include +#include + #include "cryptonote_core/account.h" #include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/Currency.h" @@ -136,9 +138,20 @@ public: tx_pool() : currency(CryptoNote::CurrencyBuilder(logger).currency()) {} +protected: + virtual void SetUp() override { + m_configDir = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("test_data_%%%%%%%%%%%%"); + } + + virtual void TearDown() override { + boost::system::error_code ignoredErrorCode; + boost::filesystem::remove_all(m_configDir, ignoredErrorCode); + } + protected: Logging::ConsoleLogger logger; CryptoNote::Currency currency; + boost::filesystem::path m_configDir; }; namespace @@ -421,7 +434,11 @@ TEST_F(tx_pool, add_tx_after_cleanup) ASSERT_TRUE(pool.add_tx(tx, tvc, false)); // main chain ASSERT_TRUE(tvc.m_added_to_pool); - pool.timeProvider.timeNow = startTime + currency.mempoolTxLiveTime() + 1; + uint64_t cleanupTime = startTime + currency.mempoolTxLiveTime() + 1; + pool.timeProvider.timeNow = cleanupTime; + pool.on_idle(); + + pool.timeProvider.timeNow = cleanupTime + currency.numberOfPeriodsToForgetTxDeletedFromPool() * currency.mempoolTxLiveTime() + 1; pool.on_idle(); ASSERT_EQ(0, pool.get_transactions_count()); @@ -433,3 +450,203 @@ TEST_F(tx_pool, add_tx_after_cleanup) ASSERT_EQ(1, pool.get_transactions_count()); } + +TEST_F(tx_pool, RecentlyDeletedTransactionCannotBeAddedToTxPoolAgain) { + TestPool pool(currency, logger); + + uint64_t startTime = pool.timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool.add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + pool.timeProvider.timeNow = deleteTime; + pool.on_idle(); + ASSERT_EQ(0, pool.get_transactions_count()); + + // Try to add tx again + ASSERT_TRUE(pool.add_tx(tx, tvc, false)); + ASSERT_FALSE(tvc.m_added_to_pool); + ASSERT_FALSE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(0, pool.get_transactions_count()); +} + +TEST_F(tx_pool, RecentlyDeletedTransactionCanBeAddedAgainAfterSomeTime) { + TestPool pool(currency, logger); + + uint64_t startTime = pool.timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool.add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + pool.timeProvider.timeNow = deleteTime; + pool.on_idle(); + ASSERT_EQ(0, pool.get_transactions_count()); + + uint64_t forgetDeletedTxTime = deleteTime + currency.numberOfPeriodsToForgetTxDeletedFromPool() * currency.mempoolTxLiveTime() + 1; + pool.timeProvider.timeNow = forgetDeletedTxTime; + pool.on_idle(); + + // Try to add tx again + ASSERT_TRUE(pool.add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + ASSERT_TRUE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(1, pool.get_transactions_count()); +} + +TEST_F(tx_pool, RecentlyDeletedTransactionCanBeAddedToTxPoolIfItIsReceivedInBlock) { + TestPool pool(currency, logger); + + uint64_t startTime = pool.timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool.add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + pool.timeProvider.timeNow = deleteTime; + pool.on_idle(); + ASSERT_EQ(0, pool.get_transactions_count()); + + // Try to add tx again + ASSERT_TRUE(pool.add_tx(tx, tvc, true)); + ASSERT_TRUE(tvc.m_added_to_pool); + ASSERT_TRUE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(1, pool.get_transactions_count()); +} + +TEST_F(tx_pool, OldTransactionIsDeletedDuringTxPoolInitialization) { + TransactionValidator validator; + FakeTimeProvider timeProvider; + std::unique_ptr pool(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + + uint64_t startTime = timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + ASSERT_TRUE(pool->deinit()); + pool.reset(); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + timeProvider.timeNow = deleteTime; + + pool.reset(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + ASSERT_EQ(0, pool->get_transactions_count()); +} + +TEST_F(tx_pool, TransactionThatWasDeletedLongAgoIsForgottenDuringTxPoolInitialization) { + TransactionValidator validator; + FakeTimeProvider timeProvider; + std::unique_ptr pool(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + + uint64_t startTime = timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + timeProvider.timeNow = deleteTime; + pool->on_idle(); + ASSERT_EQ(0, pool->get_transactions_count()); + + ASSERT_TRUE(pool->deinit()); + pool.reset(); + + uint64_t forgetDeletedTxTime = deleteTime + currency.numberOfPeriodsToForgetTxDeletedFromPool() * currency.mempoolTxLiveTime() + 1; + timeProvider.timeNow = forgetDeletedTxTime; + + pool.reset(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + + // Try to add tx again + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + ASSERT_TRUE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(1, pool->get_transactions_count()); +} + +TEST_F(tx_pool, RecentlyDeletedTxInfoIsSerializedAndDeserialized) { + TransactionValidator validator; + FakeTimeProvider timeProvider; + std::unique_ptr pool(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + + uint64_t startTime = timeProvider.now(); + + Transaction tx; + GenerateTransaction(currency, tx, currency.minimumFee(), 1); + + tx_verification_context tvc = boost::value_initialized(); + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + + uint64_t deleteTime = startTime + currency.mempoolTxLiveTime() + 1; + timeProvider.timeNow = deleteTime; + pool->on_idle(); + ASSERT_EQ(0, pool->get_transactions_count()); + + ASSERT_TRUE(pool->deinit()); + + pool.reset(new tx_memory_pool(currency, validator, timeProvider, logger)); + ASSERT_TRUE(pool->init(m_configDir.string())); + + uint64_t timeBeforeCleanupDeletedTx = deleteTime + currency.numberOfPeriodsToForgetTxDeletedFromPool() * currency.mempoolTxLiveTime(); + timeProvider.timeNow = timeBeforeCleanupDeletedTx; + pool->on_idle(); + + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_FALSE(tvc.m_added_to_pool); + ASSERT_FALSE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(0, pool->get_transactions_count()); + + timeProvider.timeNow = timeBeforeCleanupDeletedTx + 61; + pool->on_idle(); + + // Try to add tx again + ASSERT_TRUE(pool->add_tx(tx, tvc, false)); + ASSERT_TRUE(tvc.m_added_to_pool); + ASSERT_TRUE(tvc.m_should_be_relayed); + ASSERT_FALSE(tvc.m_verifivation_failed); + ASSERT_FALSE(tvc.m_verifivation_impossible); + + ASSERT_EQ(1, pool->get_transactions_count()); +}