mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 00:07:38 +00:00
Merge pull request #8211
1137142
Change C-cast to static_cast in net_peerlist.h (Jeffrey)175b411
Change C-style-casts to static_cast in time_helper.h (Jeffrey)b49ed59
Remove the only 4 non-UTF8 characters in codebase (Jeffrey)1f25aa2
Factor out move_it_backward from misc_language.h (Jeffrey)7764d69
Move copyable_atomic into connection_context (Jeffrey)801568d
Refactor out to_nonconst_iterator.h (Jeffrey)87ec36c
Refactor out pragma_comp_defs (Jeffrey)441c860
Merge functionality of misc_os_dependent into time_helper.h (Jeffrey)40f02f9
Add Include statements (Jeffrey)12b1b74
Trimming Fat (Jeffrey690ce56
Boring Old Deletes (Jeffrey)
This commit is contained in:
commit
53bf62d114
103 changed files with 98 additions and 10281 deletions
1
contrib/epee/demo/.gitignore
vendored
1
contrib/epee/demo/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build/*
|
|
@ -1,49 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
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()
|
||||
|
||||
|
|
@ -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
|
|
@ -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 <stdio.h>
|
||||
|
||||
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
#define ENABLE_RELEASE_LOGGING
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
@ -1,41 +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 <stdio.h>
|
||||
|
||||
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
#define ENABLE_RELEASE_LOGGING
|
||||
#include "log_opt_defs.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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 ..
|
|
@ -1,7 +0,0 @@
|
|||
mkdir build
|
||||
|
||||
cd build
|
||||
|
||||
cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" ..
|
||||
cd ..
|
||||
pause
|
|
@ -1,225 +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<std::string> m_list_of_str;
|
||||
std::list<uint64_t> m_list_of_uint64_t;
|
||||
std::list<uint32_t> m_list_of_uint32_t;
|
||||
std::list<uint16_t> m_list_of_uint16_t;
|
||||
std::list<uint8_t> m_list_of_uint8_t;
|
||||
std::list<int64_t> m_list_of_int64_t;
|
||||
std::list<int32_t> m_list_of_int32_t;
|
||||
std::list<int16_t> m_list_of_int16_t;
|
||||
std::list<int8_t> m_list_of_int8_t;
|
||||
std::list<double> m_list_of_double;
|
||||
std::list<bool> m_list_of_bool;
|
||||
some_test_subdata m_subobj;
|
||||
std::list<some_test_data> 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_t
|
||||
{
|
||||
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()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
|
||||
struct response_t
|
||||
{
|
||||
bool m_success;
|
||||
std::list<some_test_data> subs;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_success)
|
||||
KV_SERIALIZE(subs)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
|
||||
|
||||
|
||||
struct COMMAND_EXAMPLE_2
|
||||
{
|
||||
const static int ID = 1001;
|
||||
|
||||
struct request_t
|
||||
{
|
||||
std::string example_string_data2;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(example_string_data2)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
bool m_success;
|
||||
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_success)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------
|
||||
//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;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,56 +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 <atomic>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class copyable_atomic: public std::atomic<uint32_t>
|
||||
{
|
||||
public:
|
||||
copyable_atomic()
|
||||
{};
|
||||
copyable_atomic(uint32_t value)
|
||||
{ store(value); }
|
||||
copyable_atomic(const copyable_atomic& a):std::atomic<uint32_t>(a.load())
|
||||
{}
|
||||
copyable_atomic& operator= (const copyable_atomic& a)
|
||||
{
|
||||
store(a.load());
|
||||
return *this;
|
||||
}
|
||||
uint32_t operator++()
|
||||
{
|
||||
return std::atomic<uint32_t>::operator++();
|
||||
}
|
||||
uint32_t operator++(int fake)
|
||||
{
|
||||
return std::atomic<uint32_t>::operator++(fake);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -36,10 +36,7 @@ namespace file_io_utils
|
|||
{
|
||||
bool is_file_exist(const std::string& path);
|
||||
bool save_string_to_file(const std::string& path_to_file, const std::string& str);
|
||||
bool get_file_time(const std::string& path_to_file, time_t& ft);
|
||||
bool set_file_time(const std::string& path_to_file, const time_t& ft);
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);
|
||||
bool append_string_to_file(const std::string& path_to_file, const std::string& str);
|
||||
bool get_file_size(const std::string& path_to_file, uint64_t &size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -37,8 +37,8 @@
|
|||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
|
||||
#include "misc_os_dependent.h"
|
||||
#include "syncobj.h"
|
||||
#include "time_helper.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
|
|
@ -30,74 +30,14 @@
|
|||
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
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<decltype(v)>()
|
||||
|
||||
namespace misc_utils
|
||||
{
|
||||
template<typename t_type>
|
||||
t_type get_max_t_val(t_type t)
|
||||
{
|
||||
return (std::numeric_limits<t_type>::max)();
|
||||
}
|
||||
|
||||
|
||||
template<typename t_iterator>
|
||||
t_iterator move_it_forward(t_iterator it, size_t count)
|
||||
{
|
||||
while(count--)
|
||||
it++;
|
||||
return it;
|
||||
}
|
||||
|
||||
template<typename t_iterator>
|
||||
t_iterator move_it_backward(t_iterator it, size_t count)
|
||||
{
|
||||
while(count--)
|
||||
it--;
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
// TEMPLATE STRUCT less
|
||||
template<class _Ty>
|
||||
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<class _Ty>
|
||||
bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right)
|
||||
{ // apply operator< to operands
|
||||
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
|
||||
}
|
||||
|
||||
bool sleep_no_w(long ms );
|
||||
bool sleep_no_w(long ms);
|
||||
|
||||
template <typename T>
|
||||
T get_mid(const T &a, const T &b)
|
||||
|
|
|
@ -1,129 +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.
|
||||
//
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
//#ifdef _WIN32_WINNT
|
||||
// #undef _WIN32_WINNT
|
||||
// #define _WIN32_WINNT 0x0600
|
||||
//#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MACH__
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#pragma once
|
||||
namespace epee
|
||||
{
|
||||
namespace misc_utils
|
||||
{
|
||||
|
||||
inline uint64_t get_ns_count()
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return ::GetTickCount64() * 1000000;
|
||||
#elif defined(WIN32)
|
||||
static LARGE_INTEGER pcfreq = {0};
|
||||
LARGE_INTEGER ticks;
|
||||
if (!pcfreq.QuadPart)
|
||||
QueryPerformanceFrequency(&pcfreq);
|
||||
QueryPerformanceCounter(&ticks);
|
||||
ticks.QuadPart *= 1000000000; /* we want nsec */
|
||||
return ticks.QuadPart / pcfreq.QuadPart;
|
||||
#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 ((uint64_t)mts.tv_sec * 1000000000) + (mts.tv_nsec);
|
||||
#else
|
||||
struct timespec ts;
|
||||
if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return ((uint64_t)ts.tv_sec * 1000000000) + (ts.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint64_t get_tick_count()
|
||||
{
|
||||
return get_ns_count() / 1000000;
|
||||
}
|
||||
|
||||
|
||||
inline 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();
|
||||
|
||||
inline bool get_gmt_time(time_t t, struct tm &tm)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return gmtime_s(&tm, &t);
|
||||
#else
|
||||
return gmtime_r(&t, &tm);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,318 +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 <process.h>
|
||||
#include <list>
|
||||
#include <winsock2.h>
|
||||
#include "winobj.h"
|
||||
//#include "threads_helper.h"
|
||||
#include "net_utils_base.h"
|
||||
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
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 THandler>
|
||||
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<thread_context> 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<class THandler>
|
||||
unsigned __stdcall abstract_tcp_server<THandler>::ConnectionHandlerProc(void* lpParameter)
|
||||
{
|
||||
|
||||
thread_context* pthread_context = (thread_context*)lpParameter;
|
||||
if(!pthread_context)
|
||||
return 0;
|
||||
abstract_tcp_server<THandler>* 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<class THandler>
|
||||
abstract_tcp_server<THandler>::abstract_tcp_server():m_listen_socket(INVALID_SOCKET),
|
||||
m_initialized(false),
|
||||
m_stop_server(0), m_port(0), m_threads_count(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
template<class THandler>
|
||||
bool abstract_tcp_server<THandler>::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<char*>(&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<class THandler>
|
||||
bool abstract_tcp_server<THandler>::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<class THandler>
|
||||
bool abstract_tcp_server<THandler>::send_stop_signal()
|
||||
{
|
||||
InterlockedExchange(&m_stop_server, 1);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
template<class THandler>
|
||||
bool abstract_tcp_server<THandler>::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<class THandler>
|
||||
bool abstract_tcp_server<THandler>::invoke_connection(SOCKET hnew_sock, const network_address &remote_address)
|
||||
{
|
||||
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_address = remote_address;
|
||||
m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
#endif //_ABSTRACT_TCP_SERVER_H_
|
|
@ -44,8 +44,6 @@
|
|||
#include "warnings.h"
|
||||
#include "string_tools_lexical.h"
|
||||
#include "misc_language.h"
|
||||
#include "net/local_ip.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
@ -64,7 +62,6 @@
|
|||
#define TIMEOUT_EXTRA_MS_PER_BYTE 0.2
|
||||
|
||||
|
||||
PRAGMA_WARNING_PUSH
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
|
@ -79,8 +76,6 @@ namespace net_utils
|
|||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
PRAGMA_WARNING_DISABLE_VS(4355)
|
||||
|
||||
template<class t_protocol_handler>
|
||||
connection<t_protocol_handler>::connection( boost::asio::io_service& io_service,
|
||||
std::shared_ptr<shared_state> state,
|
||||
|
@ -111,7 +106,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
|||
MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type);
|
||||
}
|
||||
|
||||
PRAGMA_WARNING_DISABLE_VS(4355)
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
connection<t_protocol_handler>::~connection() noexcept(false)
|
||||
|
@ -1092,8 +1086,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
|||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
PUSH_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port, const std::string& address,
|
||||
const std::string port_ipv6, const std::string address_ipv6, bool use_ipv6, bool require_ipv4,
|
||||
|
@ -1113,7 +1105,6 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
|
|||
}
|
||||
return this->init_server(p, address, p_ipv6, address_ipv6, use_ipv6, require_ipv4, std::move(ssl_options));
|
||||
}
|
||||
POP_WARNINGS
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::worker_thread()
|
||||
|
@ -1734,4 +1725,3 @@ POP_WARNINGS
|
|||
|
||||
} // namespace
|
||||
} // namespace
|
||||
PRAGMA_WARNING_POP
|
||||
|
|
|
@ -1,236 +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 <winsock2.h>
|
||||
#include <rpc.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#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"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
#define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
template<class TProtocol>
|
||||
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<class TProtocol>
|
||||
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<TProtocol>& operator=(const connection<TProtocol>& 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<TProtocol>(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<TProtocol>* pconn);
|
||||
|
||||
|
||||
typedef std::map<SOCKET, boost::shared_ptr<connection<TProtocol> > > 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_
|
|
@ -1,607 +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")
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
template<class TProtocol>
|
||||
cp_server_impl<TProtocol>::cp_server_impl():
|
||||
m_port(0), m_stop(false),
|
||||
m_worker_thread_counter(0), m_listen_socket(INVALID_SOCKET)
|
||||
{
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
cp_server_impl<TProtocol>::~cp_server_impl()
|
||||
{
|
||||
deinit_server();
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::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<char*>(&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<class TProtocol>
|
||||
size_t cp_server_impl<TProtocol>::get_active_connections_num()
|
||||
{
|
||||
return m_connections.size();
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
unsigned CALLBACK cp_server_impl<TProtocol>::worker_thread(void* param)
|
||||
{
|
||||
if(!param)
|
||||
return 0;
|
||||
|
||||
cp_server_impl<TProtocol>* pthis = (cp_server_impl<TProtocol>*)param;
|
||||
pthis->worker_thread_member();
|
||||
return 1;
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::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<TProtocol>* 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<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::shutdown_connection(connection<TProtocol>* 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<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::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<m_worker_thread_counter; i++)
|
||||
{
|
||||
::PostQueuedCompletionStatus(m_completion_port, 0, 0, 0);
|
||||
}
|
||||
|
||||
wait_count = 0;
|
||||
while(InterlockedCompareExchange(&m_worker_thread_counter, 0, 0) && wait_count < 100)
|
||||
{
|
||||
Sleep(100);
|
||||
wait_count++;
|
||||
}
|
||||
|
||||
LOG_PRINT("Net Server STOPPED, wait_count = " << wait_count, LOG_LEVEL_1);
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::add_new_connection(SOCKET new_sock, const network_address &address_from)
|
||||
{
|
||||
PROFILE_FUNC("[add_new_connection]");
|
||||
|
||||
LOG_PRINT("Add new connection zone: entering lock", LOG_LEVEL_3);
|
||||
m_connections_lock.lock();
|
||||
|
||||
boost::shared_ptr<connection<TProtocol> > ptr;
|
||||
ptr.reset(new connection<TProtocol>(m_config));
|
||||
|
||||
connection<TProtocol>& 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_address = address_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<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::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<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::send_stop_signal()
|
||||
{
|
||||
::InterlockedExchange(&m_stop, 1);
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
template<class TProtocol>
|
||||
bool cp_server_impl<TProtocol>::is_stop_signal()
|
||||
{
|
||||
return m_stop?true:false;
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
}
|
||||
}
|
|
@ -50,7 +50,6 @@
|
|||
#include "abstract_http_client.h"
|
||||
#include "http_base.h"
|
||||
#include "http_auth.h"
|
||||
#include "to_nonconst_iterator.h"
|
||||
#include "net_parse_helpers.h"
|
||||
#include "syncobj.h"
|
||||
|
||||
|
|
|
@ -1,180 +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 <wininet.h>
|
||||
#include <atlutil.h>
|
||||
#pragma comment(lib, "Wininet.lib")
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
|
||||
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<std::basic_string<TCHAR> >(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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,6 @@
|
|||
#include <boost/optional/optional.hpp>
|
||||
#include <string>
|
||||
#include "net_utils_base.h"
|
||||
#include "to_nonconst_iterator.h"
|
||||
#include "http_auth.h"
|
||||
#include "http_base.h"
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ namespace net_utils
|
|||
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_cache.erase(m_cache.begin(), result[0].second);
|
||||
|
||||
m_state = http_state_retriving_header;
|
||||
|
||||
|
|
|
@ -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 _HTTP_SERVER_CP_H_
|
||||
#define _HTTP_SERVER_CP_H_
|
||||
|
||||
#include "abstract_tcp_server_cp.h"
|
||||
#include "http_server.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
typedef cp_server_impl<http::simple_http_connection_handler> cp_http_server_file_system;
|
||||
typedef cp_server_impl<http::http_custom_handler> cp_http_server_custum_handling;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,51 +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"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
typedef boosted_tcp_server<http::simple_http_connection_handler<> > boosted_http_server_file_system;
|
||||
typedef boosted_tcp_server<http::http_custom_handler<> > boosted_http_server_custum_handling;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -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<http::simple_http_connection_handler> mt_http_server_file_system;
|
||||
typedef abstract_tcp_server<http::http_custom_handler> mt_http_server_custum_handling;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
#ifndef JSONRPC_PROTOCOL_HANDLER_H
|
||||
#define JSONRPC_PROTOCOL_HANDLER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#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<epee::json_rpc::error_response&>(rsp), response_data, 0, false);
|
||||
response_data += "\n";
|
||||
return response_data;
|
||||
}
|
||||
|
||||
template<class t_connection_context>
|
||||
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<class t_connection_context>
|
||||
struct jsonrpc2_server_config
|
||||
{
|
||||
i_jsonrpc2_server_handler<t_connection_context>* m_phandler;
|
||||
critical_section m_lock;
|
||||
};
|
||||
|
||||
template<class t_connection_context = net_utils::connection_context_base>
|
||||
class jsonrpc2_connection_handler
|
||||
{
|
||||
public:
|
||||
typedef t_connection_context connection_context;
|
||||
typedef jsonrpc2_server_config<t_connection_context> 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 */
|
|
@ -1,86 +0,0 @@
|
|||
#ifndef JSONRPC_SERVER_HANDLERS_MAP_H
|
||||
#define JSONRPC_SERVER_HANDLERS_MAP_H
|
||||
|
||||
#include <string>
|
||||
#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<epee::json_rpc::request<command_type::request> > req_; \
|
||||
epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(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<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \
|
||||
epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(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<epee::json_rpc::error_response&>(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 */
|
|
@ -1,84 +0,0 @@
|
|||
#ifndef JSONRPC_SERVER_IMPL_BASE_H
|
||||
#define JSONRPC_SERVER_IMPL_BASE_H
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "net/jsonrpc_protocol_handler.h"
|
||||
#include "net/jsonrpc_server_handlers_map.h"
|
||||
#include "net/abstract_tcp_server2.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
||||
template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base>
|
||||
class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler<t_connection_context>
|
||||
{
|
||||
|
||||
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<t_child_class*>(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<net_utils::jsonrpc2::jsonrpc2_connection_handler<t_connection_context> > m_net_server;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* JSONRPC_SERVER_IMPL_BASE_H */
|
||||
|
|
@ -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 epee::span<const uint8_t> 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 epee::span<const uint8_t> 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_
|
|
@ -1,199 +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"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
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 epee::span<const uint8_t> in_buff, std::string& buff_out)
|
||||
{
|
||||
if(!is_connected())
|
||||
return -1;
|
||||
|
||||
bucket_head head = {0};
|
||||
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = SWAP64LE(in_buff.size());
|
||||
head.m_have_to_return_data = 1;
|
||||
head.m_command = SWAP32LE(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!=SWAP64LE(LEVIN_SIGNATURE))
|
||||
{
|
||||
LOG_PRINT_L1("Signature mismatch 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 = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = SWAP64LE(in_buff.size());
|
||||
head.m_have_to_return_data = 0;
|
||||
head.m_command = SWAP32LE(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, epee::span<const uint8_t>string& in_buff, std::string& buff_out)
|
||||
{
|
||||
if(!is_connected())
|
||||
return -1;
|
||||
|
||||
bucket_head2 head = {0};
|
||||
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = SWAP64LE(in_buff.size());
|
||||
head.m_have_to_return_data = 1;
|
||||
head.m_command = SWAP32LE(command);
|
||||
head.m_return_code = SWAP32LE(0);
|
||||
head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST);
|
||||
head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1);
|
||||
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 != SWAP64LE(LEVIN_SIGNATURE))
|
||||
{
|
||||
LOG_PRINT_L1("Signature mismatch in response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!m_transport.recv_n(buff_out, SWAP64LE(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 = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = SWAP64LE(in_buff.size());
|
||||
head.m_have_to_return_data = 0;
|
||||
head.m_command = SWAP32LE(command);
|
||||
head.m_return_code = SWAP32LE(0);
|
||||
head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST);
|
||||
head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1);
|
||||
|
||||
if(!m_transport.send((const char*)&head, sizeof(head)))
|
||||
return -1;
|
||||
|
||||
if(!m_transport.send(in_buff))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
|
@ -1,585 +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"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
|
||||
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;
|
||||
void (*commands_handler_destroy)(levin_commands_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<packet_entry> 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), commands_handler_destroy(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), commands_handler_destroy(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);
|
||||
|
||||
set_handler(NULL);
|
||||
}
|
||||
|
||||
void set_handler(levin_commands_handler* phandler, void (*destroy)(levin_commands_handler*) = NULL)
|
||||
{
|
||||
if (commands_handler_destroy && m_pcommands_handler)
|
||||
(*commands_handler_destroy)(m_pcommands_handler);
|
||||
m_pcommands_handler = phandler;
|
||||
m_pcommands_handler_destroy = destroy;
|
||||
}
|
||||
|
||||
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() because 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 = 1;
|
||||
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<boost::mutex> 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 = 0;
|
||||
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 mismatch 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_RECEIVED. [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_address = m_address;
|
||||
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 = 0;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
|
@ -1,161 +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"
|
||||
#include "int-util.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace levin
|
||||
{
|
||||
template<class t_struct>
|
||||
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 = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = 0;
|
||||
head.m_have_to_return_data = 1;
|
||||
head.m_command = SWAP32LE(command_id);
|
||||
head.m_return_code = SWAP32LE(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_struct, StorageNamed::DefaultStorageType>(t, buff_strg))
|
||||
return false;
|
||||
|
||||
head.m_cb = SWAP64LE(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 = SWAP64LE(LEVIN_SIGNATURE);
|
||||
head.m_cb = 0;
|
||||
head.m_have_to_return_data = 1;
|
||||
head.m_command = SWAP32LE(command_id);
|
||||
head.m_return_code = SWAP32LE(1);
|
||||
head.m_reservedA = rand(); //probably some flags in future
|
||||
head.m_reservedB = rand(); //probably some check summ in future
|
||||
|
||||
head.m_cb = SWAP64LE(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;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]);
|
||||
#else
|
||||
levin::bucket_head head = *(levin::bucket_head*)(&buff[0]);
|
||||
head.m_signature = SWAP64LE(head.m_signature);
|
||||
head.m_cb = SWAP64LE(head.m_cb);
|
||||
head.m_command = SWAP32LE(head.m_command);
|
||||
head.m_return_code = SWAP32LE(head.m_return_code);
|
||||
head.m_reservedA = SWAP32LE(head.m_reservedA);
|
||||
head.m_reservedB = SWAP32LE(head.m_reservedB);
|
||||
#endif
|
||||
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 mismatch, 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<class t_struct>
|
||||
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;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]);
|
||||
#else
|
||||
levin::bucket_head head = *(levin::bucket_head*)(&buff[0]);
|
||||
head.m_signature = SWAP64LE(head.m_signature);
|
||||
head.m_cb = SWAP64LE(head.m_cb);
|
||||
head.m_command = SWAP32LE(head.m_command);
|
||||
head.m_return_code = SWAP32LE(head.m_return_code);
|
||||
head.m_reservedA = SWAP32LE(head.m_reservedA);
|
||||
head.m_reservedB = SWAP32LE(head.m_reservedB);
|
||||
#endif
|
||||
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 mismatch, 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_struct, StorageNamed::DefaultStorageType>(t, buff_strg))
|
||||
{
|
||||
LOG_ERROR("Failed to read storage, at load_struct_from_levin_message");
|
||||
return false;
|
||||
}
|
||||
command = head.m_command;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@
|
|||
#include "buffer.h"
|
||||
#include "misc_language.h"
|
||||
#include "syncobj.h"
|
||||
#include "misc_os_dependent.h"
|
||||
#include "time_helper.h"
|
||||
#include "int-util.h"
|
||||
|
||||
#include <random>
|
||||
|
|
|
@ -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<levin::protocol_handler> cp_levin_server;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -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<levin::protocol_handler<> > boosted_levin_server;
|
||||
typedef boosted_tcp_server<levin::async_protocol_handler<> > boosted_levin_async_server;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "int-util.h"
|
||||
|
||||
// IP addresses are kept in network byte order
|
||||
|
@ -44,9 +43,9 @@ namespace epee
|
|||
ip = SWAP32LE(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
|
||||
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;
|
||||
|
@ -71,7 +70,7 @@ namespace epee
|
|||
//MAKE_IP
|
||||
/*
|
||||
loopback ip
|
||||
127.0.0.0 — 127.255.255.255
|
||||
127.0.0.0 ... 127.255.255.255
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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<net_utils::protocol_switcher> multiprotocol_server;
|
||||
typedef boosted_tcp_server<net_utils::protocol_switcher> boosted_multiprotocol_server;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //_MULTIPROTOCOLS_SERVER_H_
|
||||
|
|
@ -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 <string>
|
||||
#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<std::string>(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<munin_service> 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! Unknown 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<munin_service>::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<munin_service>::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_
|
|
@ -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 <string>
|
||||
//#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_connection_handler> munin_node_server;
|
||||
//typedef cp_server_impl<munin_node_server_connection_handler> munin_node_cp_server;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif//!_MUNIN_NODE_SERVER_H_
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (c) 2019-2022, The Monero Project
|
||||
//
|
||||
// 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 copyright holder 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 HOLDER 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
struct ssl_authentication_t;
|
||||
class ssl_options_t;
|
||||
}
|
||||
}
|
|
@ -59,7 +59,6 @@
|
|||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "misc_language.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
|
|
@ -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>
|
||||
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<http::http_custom_handler> m_http_handler;
|
||||
t_protocol_handler<levin::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_
|
|
@ -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;}
|
|
@ -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 <iostream>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
#include <boost/archive/iterators/transform_width.hpp>
|
||||
#include <boost/archive/iterators/ostream_iterator.hpp>
|
||||
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
namespace smtp
|
||||
{
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
using namespace boost::archive::iterators;
|
||||
typedef base64_from_binary<transform_width<const char *,6,8> > 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<std::string>( 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<char>(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"
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -28,7 +28,7 @@
|
|||
#ifndef _PROFILE_TOOLS_H_
|
||||
#define _PROFILE_TOOLS_H_
|
||||
|
||||
#include "misc_os_dependent.h"
|
||||
#include "time_helper.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
|
|
@ -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<class T>
|
||||
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<class T>
|
||||
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<class TMemoryObject>
|
||||
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<class TMemoryObject>
|
||||
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<class TMemoryObject>
|
||||
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<class TMemoryObject>
|
||||
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_
|
|
@ -1,2 +0,0 @@
|
|||
#pragma once
|
||||
|
|
@ -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_
|
|
@ -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
|
|
@ -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
|
|
@ -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<uint64_t>
|
||||
{
|
||||
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<bool>
|
||||
{
|
||||
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<soci::session>& 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<soci::session>& 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<std::string, boost::shared_ptr<soci::session> > m_db_connections;
|
||||
epee::critical_section m_db_connections_lock;
|
||||
std::string m_connection_string;
|
||||
};
|
||||
}
|
||||
/*}*/
|
|
@ -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.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#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 to_initialize>
|
||||
class initializer
|
||||
{
|
||||
public:
|
||||
initializer()
|
||||
{
|
||||
to_initialize::init();
|
||||
//get_set_is_initialized(true, true);
|
||||
}
|
||||
~initializer()
|
||||
{
|
||||
to_initialize::un_init();
|
||||
//get_set_is_uninitialized(true, true);
|
||||
}
|
||||
|
||||
/*static inline bool is_initialized()
|
||||
{
|
||||
return get_set_is_initialized();
|
||||
}
|
||||
static inline bool is_uninitialized()
|
||||
{
|
||||
return get_set_is_uninitialized();
|
||||
}
|
||||
|
||||
private:
|
||||
static inline bool get_set_is_initialized(bool need_to_set = false, bool val_to_set= false)
|
||||
{
|
||||
static bool val_is_initialized = false;
|
||||
if(need_to_set)
|
||||
val_is_initialized = val_to_set;
|
||||
return val_is_initialized;
|
||||
}
|
||||
static inline bool get_set_is_uninitialized(bool need_to_set = false, bool val_to_set = false)
|
||||
{
|
||||
static bool val_is_uninitialized = false;
|
||||
if(need_to_set)
|
||||
val_is_uninitialized = val_to_set;
|
||||
return val_is_uninitialized;
|
||||
}*/
|
||||
};
|
||||
|
||||
}
|
||||
#endif //_STATIC_INITIALIZER_H_
|
|
@ -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 t_base_storage, class crypt_provider, class t_key_provider>
|
||||
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_
|
|
@ -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 t_base_storage>
|
||||
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
|
|
@ -56,54 +56,6 @@ namespace epee
|
|||
{
|
||||
namespace net_utils
|
||||
{
|
||||
#if 0
|
||||
template<class t_arg, class t_result, class t_transport>
|
||||
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 )
|
||||
{
|
||||
MERROR("Failed to invoke command " << command << " return code " << res);
|
||||
return false;
|
||||
}
|
||||
serialization::portable_storage stg_ret;
|
||||
if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits))
|
||||
{
|
||||
LOG_ERROR("Failed to load_from_binary on command " << command);
|
||||
return false;
|
||||
}
|
||||
return result_struct.load(stg_ret);
|
||||
}
|
||||
|
||||
template<class t_arg, class t_transport>
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class t_arg, class t_result, class t_transport>
|
||||
bool invoke_remote_command2(const epee::net_utils::connection_context_base context, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport)
|
||||
{
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "pragma_comp_defs.h"
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_bin_utils.h"
|
||||
|
@ -49,12 +48,7 @@ namespace epee
|
|||
return sizeof(pack_value);
|
||||
}
|
||||
|
||||
PRAGMA_WARNING_PUSH
|
||||
PRAGMA_GCC("GCC diagnostic ignored \"-Wstrict-aliasing\"")
|
||||
#ifdef __clang__
|
||||
PRAGMA_GCC("GCC diagnostic ignored \"-Wtautological-constant-out-of-range-compare\"")
|
||||
#endif
|
||||
template<class t_stream>
|
||||
template<class t_stream>
|
||||
size_t pack_varint(t_stream& strm, size_t val)
|
||||
{ //the first two bits always reserved for size information
|
||||
|
||||
|
@ -70,13 +64,13 @@ namespace epee
|
|||
return pack_varint_t<uint32_t>(strm, PORTABLE_RAW_SIZE_MARK_DWORD, val);
|
||||
}else
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val);
|
||||
// Same as checking val <= 4611686018427387903 except that it's portable for 32-bit size_t
|
||||
CHECK_AND_ASSERT_THROW_MES(!(val >> 31 >> 31), "failed to pack varint - too big amount = " << val);
|
||||
return pack_varint_t<uint64_t>(strm, PORTABLE_RAW_SIZE_MARK_INT64, val);
|
||||
}
|
||||
}
|
||||
PRAGMA_WARNING_POP
|
||||
|
||||
template<class t_stream>
|
||||
template<class t_stream>
|
||||
bool put_string(t_stream& strm, const std::string& v)
|
||||
{
|
||||
pack_varint(strm, v.size());
|
||||
|
|
|
@ -28,132 +28,60 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
//#include <atltime.h>
|
||||
//#include <sqlext.h>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace misc_utils
|
||||
{
|
||||
|
||||
#ifdef __ATLTIME_H__
|
||||
|
||||
inline
|
||||
bool get_time_t_from_ole_date(DATE src, time_t& res)
|
||||
inline bool get_gmt_time(time_t t, struct tm &tm)
|
||||
{
|
||||
SYSTEMTIME st = {0};
|
||||
if(TRUE != ::VariantTimeToSystemTime(src, &st))
|
||||
return false;
|
||||
ATL::CTime ss(st);
|
||||
res = ss.GetTime();
|
||||
return true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return gmtime_s(&tm, &t);
|
||||
#else
|
||||
return gmtime_r(&t, &tm);
|
||||
#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 );
|
||||
struct tm pt;
|
||||
get_gmt_time(time_, pt);
|
||||
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);
|
||||
const int days = static_cast<int>(tail/(60*60*24));
|
||||
tail = tail%(60*60*24);
|
||||
int hours = tail/(60*60);
|
||||
const int hours = static_cast<int>(tail/(60*60));
|
||||
tail = tail%(60*60);
|
||||
int minutes = tail/(60);
|
||||
const int minutes = static_cast<int>(tail/60);
|
||||
tail = tail%(60);
|
||||
int seconds = tail;
|
||||
PRAGMA_WARNING_POP
|
||||
res = std::string() + "d" + boost::lexical_cast<std::string>(days) + ".h" + boost::lexical_cast<std::string>(hours) + ".m" + boost::lexical_cast<std::string>(minutes) + ".s" + boost::lexical_cast<std::string>(seconds);
|
||||
return res;
|
||||
const int seconds = static_cast<int>(tail);
|
||||
|
||||
char tmpbuf[64] = {0};
|
||||
snprintf(tmpbuf, sizeof(tmpbuf) - 1, "d%d.h%d.m%d.s%d", days, hours, minutes, seconds);
|
||||
|
||||
return tmpbuf;
|
||||
}
|
||||
|
||||
#ifdef __SQLEXT
|
||||
inline
|
||||
bool odbc_time_to_oledb_taime(const SQL_TIMESTAMP_STRUCT& odbc_timestamp, DATE& oledb_date)
|
||||
inline uint64_t get_ns_count()
|
||||
{
|
||||
|
||||
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;
|
||||
typedef std::chrono::duration<uint64_t, std::nano> ns_duration;
|
||||
const ns_duration ns_since_epoch = std::chrono::steady_clock::now().time_since_epoch();
|
||||
return ns_since_epoch.count();
|
||||
}
|
||||
|
||||
#endif
|
||||
inline uint64_t get_tick_count()
|
||||
{
|
||||
return get_ns_count() / 1000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +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 "string_tools.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace tiny_ini
|
||||
{
|
||||
|
||||
bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res);
|
||||
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<class T>
|
||||
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_
|
|
@ -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<class Type>
|
||||
typename Type::iterator to_nonsonst_iterator(Type& obj, typename Type::const_iterator it)
|
||||
{
|
||||
typename Type::difference_type dist = std::distance(static_cast<typename Type::const_iterator>(obj.begin()), it);
|
||||
typename Type::iterator res_it = obj.begin()+dist;
|
||||
return res_it;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
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<typename Type::const_iterator>(base_it), it);
|
||||
typename Type::iterator res_it = base_it+dist;
|
||||
return res_it;
|
||||
}
|
||||
}//namespace epee
|
||||
#endif //_TO_NONCONST_ITERATOR_H_
|
|
@ -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 <boost/thread/locks.hpp>
|
||||
|
||||
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
|
|
@ -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
|
|
@ -35,11 +35,9 @@ monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_cli
|
|||
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp portable_storage.cpp
|
||||
misc_language.cpp
|
||||
misc_os_dependent.cpp
|
||||
file_io_utils.cpp
|
||||
net_parse_helpers.cpp
|
||||
http_base.cpp
|
||||
tiny_ini.cpp
|
||||
${EPEE_HEADERS_PUBLIC}
|
||||
)
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include "misc_language.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/asio/basic_socket.hpp>
|
||||
|
|
|
@ -102,29 +102,6 @@ namespace file_io_utils
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
@ -174,26 +151,6 @@ namespace file_io_utils
|
|||
}
|
||||
|
||||
|
||||
bool append_string_to_file(const std::string& path_to_file, const std::string& str)
|
||||
{
|
||||
// No special Windows implementation because so far not used in Monero code
|
||||
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 get_file_size(const std::string& path_to_file, uint64_t &size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
|
@ -1,44 +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 <boost/lexical_cast.hpp>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace misc_utils
|
||||
{
|
||||
// TODO: (vtnerd) This function is weird since boost::this_thread::get_id() exists but returns a different value.
|
||||
std::string get_thread_string_id()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return boost::lexical_cast<std::string>(GetCurrentThreadId());
|
||||
#elif defined(__GNUC__)
|
||||
return boost::lexical_cast<std::string>(pthread_self());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "string_tools.h"
|
||||
#include "misc_os_dependent.h"
|
||||
#include "time_helper.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "misc_log_ex.h"
|
||||
#include <boost/chrono.hpp>
|
||||
#include "misc_language.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
|
|
@ -1,46 +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 <boost/regex.hpp>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace tiny_ini
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
1
contrib/epee/tests/.gitignore
vendored
1
contrib/epee/tests/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build/*
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
¢IMóÙŸˆm_bo
|
Binary file not shown.
Binary file not shown.
|
@ -1,5 +0,0 @@
|
|||
mkdir build
|
||||
cd build
|
||||
cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" ../src
|
||||
cd ..
|
||||
pause
|
|
@ -1,40 +0,0 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
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} -Wall")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -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} )
|
||||
|
|
@ -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<size_t> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,408 +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 <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "net/abstract_tcp_server2.h"
|
||||
#include "net/levin_protocol_handler.h"
|
||||
#include "net/levin_protocol_handler_async.h"
|
||||
#include "storages/abstract_invoke.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace StorageNamed
|
||||
{
|
||||
typedef CInMemStorage DefaultStorageType;
|
||||
}
|
||||
namespace tests
|
||||
{
|
||||
struct some_subdata
|
||||
{
|
||||
|
||||
std::string str1;
|
||||
std::list<uint64_t> 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_t
|
||||
{
|
||||
|
||||
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()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
bool m_success;
|
||||
uint64_t example_id_data;
|
||||
std::list<some_subdata> subs;
|
||||
|
||||
BEGIN_NAMED_SERIALIZE_MAP()
|
||||
SERIALIZE_POD(m_success)
|
||||
SERIALIZE_POD(example_id_data)
|
||||
SERIALIZE_STL_CONTAINER_T(subs)
|
||||
END_NAMED_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_EXAMPLE_2
|
||||
{
|
||||
const static int ID = 1001;
|
||||
|
||||
struct request_t
|
||||
{
|
||||
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()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
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 epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
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<class calback_t>
|
||||
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<class t_request, class t_response>
|
||||
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<t_response>(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().set_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<COMMAND_EXAMPLE_2::response>(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("Initialized 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<COMMAND_EXAMPLE_1::request>(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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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 <list>
|
||||
#include <string>
|
||||
#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<std::string> m_list_of_str;
|
||||
std::list<uint64_t> m_list_of_uint64_t;
|
||||
std::list<uint32_t> m_list_of_uint32_t;
|
||||
std::list<uint16_t> m_list_of_uint16_t;
|
||||
std::list<uint8_t> m_list_of_uint8_t;
|
||||
std::list<int64_t> m_list_of_int64_t;
|
||||
std::list<int32_t> m_list_of_int32_t;
|
||||
std::list<int16_t> m_list_of_int16_t;
|
||||
std::list<int8_t> m_list_of_int8_t;
|
||||
std::list<double> m_list_of_double;
|
||||
std::list<bool> m_list_of_bool;
|
||||
port_test_struct_sub m_subobj;
|
||||
std::list<port_test_struct> 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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<std::string> m_list_of_str;
|
||||
std::list<int> m_list_of_int;
|
||||
std::list<test_struct> 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<test_struct>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -27,7 +27,7 @@
|
|||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <vector>
|
||||
#include "misc_os_dependent.h"
|
||||
#include "time_helper.h"
|
||||
#include "perf_timer.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include "include_base_utils.h"
|
||||
#include "file_io_utils.h"
|
||||
#include "wipeable_string.h"
|
||||
#include "misc_os_dependent.h"
|
||||
#include "time_helper.h"
|
||||
using namespace epee;
|
||||
|
||||
#include "crypto/crypto.h"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Parts of this file are originally copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
|
||||
#pragma once
|
||||
#include <unordered_set>
|
||||
|
@ -34,7 +35,6 @@
|
|||
#include <algorithm>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "net/net_utils_base.h"
|
||||
#include "copyable_atomic.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
namespace cryptonote
|
||||
|
@ -55,6 +55,37 @@ namespace cryptonote
|
|||
state_normal
|
||||
};
|
||||
|
||||
/*
|
||||
This class was originally from the EPEE module. It is identical in function to std::atomic<uint32_t> except
|
||||
that it has copy-construction and copy-assignment defined, which means that earliers devs didn't have to write
|
||||
custom copy-contructors and copy-assingment operators for the outer class, cryptonote_connection_context.
|
||||
cryptonote_connection_context should probably be refactored because it is both trying to be POD-like while
|
||||
also (very loosely) controlling access to its atomic members.
|
||||
*/
|
||||
class copyable_atomic: public std::atomic<uint32_t>
|
||||
{
|
||||
public:
|
||||
copyable_atomic()
|
||||
{};
|
||||
copyable_atomic(uint32_t value)
|
||||
{ store(value); }
|
||||
copyable_atomic(const copyable_atomic& a):std::atomic<uint32_t>(a.load())
|
||||
{}
|
||||
copyable_atomic& operator= (const copyable_atomic& a)
|
||||
{
|
||||
store(a.load());
|
||||
return *this;
|
||||
}
|
||||
uint32_t operator++()
|
||||
{
|
||||
return std::atomic<uint32_t>::operator++();
|
||||
}
|
||||
uint32_t operator++(int fake)
|
||||
{
|
||||
return std::atomic<uint32_t>::operator++(fake);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr int handshake_command() noexcept { return 1001; }
|
||||
bool handshake_complete() const noexcept { return m_state != state_before_handshake; }
|
||||
|
||||
|
@ -67,7 +98,7 @@ namespace cryptonote
|
|||
uint64_t m_remote_blockchain_height;
|
||||
uint64_t m_last_response_height;
|
||||
boost::posix_time::ptime m_last_request_time;
|
||||
epee::copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise
|
||||
copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise
|
||||
crypto::hash m_last_known_hash;
|
||||
uint32_t m_pruning_seed;
|
||||
uint16_t m_rpc_port;
|
||||
|
@ -77,8 +108,8 @@ namespace cryptonote
|
|||
int m_expect_response;
|
||||
uint64_t m_expect_height;
|
||||
size_t m_num_requested;
|
||||
epee::copyable_atomic m_new_stripe_notification{0};
|
||||
epee::copyable_atomic m_idle_peer_notification{0};
|
||||
copyable_atomic m_new_stripe_notification{0};
|
||||
copyable_atomic m_idle_peer_notification{0};
|
||||
};
|
||||
|
||||
inline std::string get_protocol_state_string(cryptonote_connection_context::state s)
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include "misc_language.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include "daemon/rpc_command_executor.h"
|
||||
#include "common/common_fwd.h"
|
||||
#include "net/net_fwd.h"
|
||||
#include "rpc/core_rpc_server.h"
|
||||
|
||||
namespace daemonize {
|
||||
|
|
|
@ -43,7 +43,6 @@ Passing RPC commands:
|
|||
#include "common/common_fwd.h"
|
||||
#include "console_handler.h"
|
||||
#include "daemon/command_parser_executor.h"
|
||||
#include "net/net_fwd.h"
|
||||
|
||||
namespace daemonize {
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "common/common_fwd.h"
|
||||
#include "common/rpc_client.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "net/net_fwd.h"
|
||||
#include "rpc/core_rpc_server.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include "math_helper.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "p2p_protocol_defs.h"
|
||||
#include "net/local_ip.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "storages/levin_abstract_invoke2.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -46,7 +47,6 @@
|
|||
#include "crypto/crypto.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "net/enums.h"
|
||||
#include "net/local_ip.h"
|
||||
#include "p2p_protocol_defs.h"
|
||||
#include "syncobj.h"
|
||||
|
||||
|
@ -184,6 +184,7 @@ namespace nodetool
|
|||
private:
|
||||
void trim_white_peerlist();
|
||||
void trim_gray_peerlist();
|
||||
static peerlist_entry get_nth_latest_peer(peers_indexed& peerlist, size_t n);
|
||||
|
||||
friend class boost::serialization::access;
|
||||
epee::critical_section m_peerlist_lock;
|
||||
|
@ -214,6 +215,16 @@ namespace nodetool
|
|||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
peerlist_entry peerlist_manager::get_nth_latest_peer(peers_indexed& peerlist, const size_t n)
|
||||
{
|
||||
// Is not thread-safe nor does it check bounds. Do this before calling. Indexing starts at 0.
|
||||
peers_indexed::index<by_time>::type& by_time_index = peerlist.get<by_time>();
|
||||
auto by_time_it = --by_time_index.end();
|
||||
std::advance(by_time_it, -static_cast<long long>(n));
|
||||
return *by_time_it;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool peerlist_manager::merge_peerlist(const std::vector<peerlist_entry>& outer_bs, const std::function<bool(const peerlist_entry&)> &f)
|
||||
{
|
||||
|
@ -235,8 +246,7 @@ namespace nodetool
|
|||
if(i >= m_peers_white.size())
|
||||
return false;
|
||||
|
||||
peers_indexed::index<by_time>::type& by_time_index = m_peers_white.get<by_time>();
|
||||
p = *epee::misc_utils::move_it_backward(--by_time_index.end(), i);
|
||||
p = peerlist_manager::get_nth_latest_peer(m_peers_white, i);
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -247,8 +257,7 @@ namespace nodetool
|
|||
if(i >= m_peers_gray.size())
|
||||
return false;
|
||||
|
||||
peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
|
||||
p = *epee::misc_utils::move_it_backward(--by_time_index.end(), i);
|
||||
p = peerlist_manager::get_nth_latest_peer(m_peers_gray, i);
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -437,9 +446,7 @@ namespace nodetool
|
|||
}
|
||||
|
||||
size_t random_index = crypto::rand_idx(m_peers_gray.size());
|
||||
|
||||
peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
|
||||
pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), random_index);
|
||||
pe = peerlist_manager::get_nth_latest_peer(m_peers_gray, random_index);
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <iomanip>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include "serialization/keyvalue_serialization.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue