├── CMakeLists.txt ├── README.md ├── examples ├── CMakeLists.txt ├── client_message_factory.cpp ├── client_message_factory.h ├── dmo.pb.cc ├── dmo.pb.h ├── dmo.proto ├── proto_client_message_factory.cpp ├── proto_client_message_factory.h ├── proto_server_message_factory.cpp ├── proto_server_message_factory.h ├── server_message_factory.cpp ├── server_message_factory.h ├── tcp_client.cpp ├── tcp_client_proto.cpp ├── tcp_server.cpp ├── tcp_server_proto.cpp ├── udp_client.cpp ├── udp_client_proto.cpp ├── udp_server.cpp ├── udp_server_proto.cpp └── utils.h └── src ├── CMakeLists.txt ├── ip ├── CMakeLists.txt ├── async_write_buffer.cpp ├── async_write_buffer.h ├── client │ ├── tcp_client.cpp │ ├── tcp_client.h │ ├── udp_client.cpp │ └── udp_client.h ├── io_service_pool.cpp ├── io_service_pool.h ├── message_factory.h └── server │ ├── server.h │ ├── session.cpp │ ├── session.h │ ├── tcp_server.cpp │ ├── tcp_server.h │ ├── tcp_session.cpp │ ├── tcp_session.h │ ├── udp_server.cpp │ ├── udp_server.h │ ├── udp_session.cpp │ ├── udp_session.h │ └── unordered_map_safe.h └── network ├── CMakeLists.txt ├── adler32.cpp ├── adler32.h ├── client_message_factory.cpp ├── client_message_factory.h ├── network_convert.cpp ├── network_convert.h ├── news.h ├── proto_network_convert.cpp ├── proto_network_convert.h ├── quicklz.cpp ├── quicklz.h ├── response_error.pb.cc ├── response_error.pb.h ├── response_error.proto ├── server_message_factory.h ├── util_message_factory.cpp └── util_message_factory.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(happy_ip) 3 | 4 | # 清空build目录,保证CMakeCache.txt为最新 5 | #file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/build/*) 6 | #message(STATUS "clean build file") 7 | 8 | #debug或release模式 9 | if(NOT CMAKE_BUILD_TYPE) 10 | set(CMAKE_BUILD_TYPE "Release") 11 | endif() 12 | message(STATUS "Build " ${CMAKE_BUILD_TYPE}) 13 | 14 | add_compile_options(-std=c++14) 15 | message(STATUS "optional: -std=c++14") 16 | 17 | if (NOT DEFINED BOOST_INCLUDE_DIR) 18 | message( FATAL_ERROR "not define BOOST_INCLUDE_DIR" ) 19 | endif() 20 | if (NOT DEFINED PROTOBUF_INCLUDE_DIR OR NOT DEFINED PROTOBUF_LIB_DIR) 21 | message( FATAL_ERROR "not define PROTOBUF_INCLUDE_DIR or PROTOBUF_LIB_DIR" ) 22 | endif() 23 | if (NOT DEFINED 3RDPARTY_INCLUDE_DIR) 24 | message( FATAL_ERROR "not define 3RDPARTY_INCLUDE_DIR" ) 25 | endif() 26 | 27 | option(GLOG_OUTPUT OFF) 28 | if (GLOG_OUTPUT) 29 | if(NOT DEFINED GLOG_INCLUDE_DIR OR NOT DEFINED GLOG_LIB_DIR) 30 | message( FATAL_ERROR "not define GLOG_INCLUDE_DIR or GLOG_LIB_DIR" ) 31 | endif() 32 | message (STATUS "build with glog") 33 | add_definitions(-DGLOG_OUTPUT -DGLOG_NO_ABBREVIATED_SEVERITIES -DGOOGLE_GLOG_DLL_DECL=) 34 | endif() 35 | include_directories(${BOOST_INCLUDE_DIR} ./ ${PROTOBUF_INCLUDE_DIR} ${3RDPARTY_INCLUDE_DIR} ${GLOG_INCLUDE_DIR}) 36 | 37 | add_subdirectory(src) 38 | message (STATUS "build examples") 39 | add_subdirectory(examples) 40 | 41 | install(FILES ${3RDPARTY_INCLUDE_DIR}/singleton.h ${3RDPARTY_INCLUDE_DIR}/thread_pool.h 42 | ${3RDPARTY_INCLUDE_DIR}/config_glog.h ${3RDPARTY_INCLUDE_DIR}/output.h DESTINATION include) 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # happy-ip 2 | 简介 3 | 4 |         开发c++多年,一直没有一个跨平台、高性能的TCP&UDP服务器,c++在开源工具包上面已落后python、java等开发语言。python开发很简单,绝大部分功能都是第三方包搞定,一个pip命令就完成了;java开发也是,只需要一条mvn指令,就可以调用第三方包。只有c++是最麻烦的,为了做到跨平台,c++支持的功能是尽量的少,不具备通用性、高性能,就不会在c++标准里面出现。从c++98、c++03、c++11用了多长的时间来完成版本迭代。不支持日期时间类型、配置文件读取、日志文件输出、跨平台TCP&UDP服务器...太多太多这样的例子,三天三夜也说不完。我们c++的从业者天天折腾这些功能、人家早上AI、大数据了,我们还在折腾语法、折腾内存泄漏、折腾以上的功能(可喜的是从c++11开始、c++14、c++17陆续推出,在逐渐拉近与其他语言的距离,那天,c++开发能和python一样容易,也有pip这样的三方工具,就实现心目中的大同世界了!)。于是乎,自己动了想开源一套高性能TCP&UDP服务器的念头,于是就有了happy-ip的项目。 5 | 6 |         自己之所有能够完成这个项目,是因为我们公司这么多年一直在用这个我们开发的框架。公司现在的tcp连接数量已经达到50万+,通过简单的分布式,代码还是能高性能、安全的运行,这也是直接发表开源项目的底气。happy-ip的是依托于boost的asio。之所以选择asio,是不想再折腾最原始的封装。boost库的asio相较于ace要更友好一些,最主要是boost库是c++第一库,在扩展性和稳定性方面有不可比拟的优势。happy-ip对asio做了以下核心封装: 7 | 8 |          (1)更友好的调用(继承抽象接口的读写事件即可); 9 | 10 |          (2)会话管理(方便做超时控制、推送消息以及回收资源); 11 | 12 |          (3)收发数据与业务逻辑隔离(读取数据后放入线程池处理,不阻塞读事件); 13 | 14 | (4)关闭延迟(特别适合TCP移动通信,TCP会话经常关闭但却不会一直投递关闭事件); 15 | 16 |          (5)自动分包(自动处理后续包问题,完整包数据提交给上层应用); 17 | 18 |          (6)无缝融入json、protobuf等RPC框架(后面会提交protobuf的rpc代码); 19 | 20 | 编译: 21 | 22 | 1、编译选项说明: 23 | 24 | BOOST_INCLUDE:boost头文件所在路径 25 | 26 | CMAKE_BUILD_TYPE:编译类型(默认Debug) 27 | 28 | BUILD_EXAMPLES: 是否编译样例(默认OFF) 29 | 30 | 2、编译命令 31 | 32 | 根目录创建build目录,进入build文件夹执行如下命令 33 | 34 | 2.1 windows 35 | 36 | cmake .. -LA -DBOOST_INCLUDE='E:/work/git' -DCMAKE_BUILD_TYPE=Debug -DBUILD_EXAMPLES=ON 37 | 38 | 2.2 linux 39 | 40 | cmake .. -D3RDPARTY_INCLUDE_DIR=../utils -DPROTOBUF_INCLUDE_DIR=../utils/3rdparty/include/protobuf/3.6.1 \ 41 | -DPROTOBUF_LIB_DIR=../utils/3rdparty/lib/ubuntu/protobuf/3.6.1 -DBOOST_LIB_DIR=../utils/3rdparty/lib/ubuntu/boost \ 42 | -DBOOST_INCLUDE_DIR=../utils/3rdparty/include -DGLOG_OUTPUT=ON -DGLOG_INCLUDE_DIR=../utils/3rdparty/include \ 43 | -DGLOG_LIB_DIR=../utils/3rdparty/lib/ubuntu -DCMAKE_INSTALL_PREFIX=install 44 | 45 | make 46 | 47 | make install 48 | 49 | (安装位置在install目录) 50 | 51 | 更为详细信息请参考:https://blog.csdn.net/wang19840301 52 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if (NOT DEFINED BOOST_LIB_DIR) 2 | message( FATAL_ERROR "not define BOOST_LIB_DIR" ) 3 | endif() 4 | 5 | include_directories(./ ${PROJECT_SOURCE_DIR}/src ${PROTOBUF_INCLUDE_DIR}) 6 | LINK_DIRECTORIES(${BUILD_DIR} ../${BOOST_LIB_DIR} ../${PROTOBUF_LIB_DIR} ../${GLOG_LIB_DIR}) 7 | set(THREADS_PREFER_PTHREAD_FLAG ON) 8 | find_package(Threads REQUIRED) 9 | 10 | ##############################编译tcp_server##################################### 11 | #程序名 12 | set(OUT_NAME tcp_server) 13 | #可执行程序 14 | file(GLOB_RECURSE SOURCE_FILES "./tcp_server.cpp" "./utils.h" "./server_message_factory.*") 15 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 16 | #连接库 17 | target_link_libraries(${OUT_NAME} ip) 18 | #SET(CMAKE_EXE_LINKER_FLAGS " -no-pie") 19 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 20 | ##############################编译tcp_client##################################### 21 | #程序名 22 | set(OUT_NAME tcp_client) 23 | #可执行程序 24 | file(GLOB_RECURSE SOURCE_FILES "./tcp_client.cpp" "./utils.h" "./client_message_factory.*") 25 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 26 | #连接库 27 | target_link_libraries(${OUT_NAME} ip) 28 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 29 | ##############################编译udp_server##################################### 30 | #程序名 31 | set(OUT_NAME udp_server) 32 | #可执行程序 33 | file(GLOB_RECURSE SOURCE_FILES "./udp_server.cpp" "./utils.h" "./server_message_factory.*") 34 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 35 | #连接库 36 | target_link_libraries(${OUT_NAME} ip) 37 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 38 | ##############################编译udp_client##################################### 39 | #程序名 40 | set(OUT_NAME udp_client) 41 | #可执行程序 42 | file(GLOB_RECURSE SOURCE_FILES "./udp_client.cpp" "./utils.h" "./client_message_factory.*") 43 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 44 | #连接库 45 | target_link_libraries(${OUT_NAME} ip) 46 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 47 | 48 | #RETURN() 49 | 50 | #if (NOT DEFINED PROTOBUF_INCLUDE_DIR OR NOT DEFINED PROTOBUF_LIB_DIR) 51 | # message( FATAL_ERROR "not define PROTOBUF" ) 52 | #endif() 53 | 54 | ##############################编译tcp_server_proto############################### 55 | #程序名 56 | set(OUT_NAME tcp_server_proto) 57 | #可执行程序 58 | file(GLOB_RECURSE SOURCE_FILES "./tcp_server_proto.cpp" "./utils.h" "./dmo.pb.*" "./proto_server_message_factory.*") 59 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 60 | #连接库 61 | target_link_libraries(${OUT_NAME} ip network protobuf) 62 | if (GLOG_OUTPUT) 63 | target_link_libraries(${OUT_NAME} glog) 64 | endif() 65 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 66 | ##############################编译tcp_client_proto############################### 67 | #程序名 68 | set(OUT_NAME tcp_client_proto) 69 | #可执行程序 70 | file(GLOB_RECURSE SOURCE_FILES "./tcp_client_proto.cpp" "./utils.h" "./dmo.pb.*" "./proto_client_message_factory.*") 71 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 72 | #连接库 73 | target_link_libraries(${OUT_NAME} ip network protobuf) 74 | if (GLOG_OUTPUT) 75 | target_link_libraries(${OUT_NAME} glog) 76 | endif() 77 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 78 | ##############################编译udp_server_proto############################### 79 | #程序名 80 | set(OUT_NAME udp_server_proto) 81 | #可执行程序 82 | file(GLOB_RECURSE SOURCE_FILES "./udp_server_proto.cpp" "./utils.h" "./dmo.pb.*" "./proto_server_message_factory.*") 83 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 84 | #连接库 85 | target_link_libraries(${OUT_NAME} ip network protobuf) 86 | if (GLOG_OUTPUT) 87 | target_link_libraries(${OUT_NAME} glog) 88 | endif() 89 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 90 | ##############################编译udp_client_proto############################### 91 | #程序名 92 | set(OUT_NAME udp_client_proto) 93 | #可执行程序 94 | file(GLOB_RECURSE SOURCE_FILES "./udp_client_proto.cpp" "./utils.h" "./dmo.pb.*" "./proto_client_message_factory.*") 95 | add_executable(${OUT_NAME} ${SOURCE_FILES}) 96 | #连接库 97 | target_link_libraries(${OUT_NAME} ip network protobuf) 98 | if (GLOG_OUTPUT) 99 | target_link_libraries(${OUT_NAME} glog) 100 | endif() 101 | target_link_libraries(${OUT_NAME} boost_system boost_thread Threads::Threads) 102 | -------------------------------------------------------------------------------- /examples/client_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "client_message_factory.h" 2 | #include 3 | 4 | bool ClientMessageFactory::IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) 5 | { 6 | uint32_t content_length = 0; 7 | if (length < 4 || (content_length = boost::asio::detail::socket_ops::network_to_host_long(*reinterpret_cast (buffer))) > length - 4) 8 | { 9 | has_package = true; 10 | 11 | return false; 12 | } 13 | deal_length = 4 + content_length; 14 | 15 | return true; 16 | } 17 | 18 | bool ClientMessageFactory::HandleRead(const uint8_t* buffer, const size_t& length, string& response) 19 | { 20 | printf("receive server data: %s\n", ToHost(buffer, length).content.c_str()); 21 | 22 | return true; 23 | } -------------------------------------------------------------------------------- /examples/client_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class ClientMessageFactory : public happy::asio::ip::MessageFactory 6 | { 7 | using happy::asio::ip::MessageFactory::MessageFactory; 8 | CREATE(ClientMessageFactory); 9 | private: 10 | virtual bool IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) override final; 11 | virtual bool HandleRead(const uint8_t* buffer, const size_t& length, string& response) override final; 12 | }; -------------------------------------------------------------------------------- /examples/dmo.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: dmo.proto 3 | 4 | #include "dmo.pb.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | // @@protoc_insertion_point(includes) 17 | #include 18 | 19 | namespace happy { 20 | namespace utils { 21 | namespace network { 22 | class RequestInfoDefaultTypeInternal { 23 | public: 24 | ::google::protobuf::internal::ExplicitlyConstructed _instance; 25 | } _RequestInfo_default_instance_; 26 | class ResponseInfoDefaultTypeInternal { 27 | public: 28 | ::google::protobuf::internal::ExplicitlyConstructed _instance; 29 | } _ResponseInfo_default_instance_; 30 | } // namespace network 31 | } // namespace utils 32 | } // namespace happy 33 | static void InitDefaultsRequestInfo_dmo_2eproto() { 34 | GOOGLE_PROTOBUF_VERIFY_VERSION; 35 | 36 | { 37 | void* ptr = &::happy::utils::network::_RequestInfo_default_instance_; 38 | new (ptr) ::happy::utils::network::RequestInfo(); 39 | ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); 40 | } 41 | ::happy::utils::network::RequestInfo::InitAsDefaultInstance(); 42 | } 43 | 44 | ::google::protobuf::internal::SCCInfo<0> scc_info_RequestInfo_dmo_2eproto = 45 | {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsRequestInfo_dmo_2eproto}, {}}; 46 | 47 | static void InitDefaultsResponseInfo_dmo_2eproto() { 48 | GOOGLE_PROTOBUF_VERIFY_VERSION; 49 | 50 | { 51 | void* ptr = &::happy::utils::network::_ResponseInfo_default_instance_; 52 | new (ptr) ::happy::utils::network::ResponseInfo(); 53 | ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); 54 | } 55 | ::happy::utils::network::ResponseInfo::InitAsDefaultInstance(); 56 | } 57 | 58 | ::google::protobuf::internal::SCCInfo<0> scc_info_ResponseInfo_dmo_2eproto = 59 | {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsResponseInfo_dmo_2eproto}, {}}; 60 | 61 | void InitDefaults_dmo_2eproto() { 62 | ::google::protobuf::internal::InitSCC(&scc_info_RequestInfo_dmo_2eproto.base); 63 | ::google::protobuf::internal::InitSCC(&scc_info_ResponseInfo_dmo_2eproto.base); 64 | } 65 | 66 | ::google::protobuf::Metadata file_level_metadata_dmo_2eproto[2]; 67 | constexpr ::google::protobuf::EnumDescriptor const** file_level_enum_descriptors_dmo_2eproto = nullptr; 68 | constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmo_2eproto = nullptr; 69 | 70 | const ::google::protobuf::uint32 TableStruct_dmo_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 71 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::RequestInfo, _has_bits_), 72 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::RequestInfo, _internal_metadata_), 73 | ~0u, // no _extensions_ 74 | ~0u, // no _oneof_case_ 75 | ~0u, // no _weak_field_map_ 76 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::RequestInfo, info_), 77 | 0, 78 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseInfo, _has_bits_), 79 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseInfo, _internal_metadata_), 80 | ~0u, // no _extensions_ 81 | ~0u, // no _oneof_case_ 82 | ~0u, // no _weak_field_map_ 83 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseInfo, info_), 84 | 0, 85 | }; 86 | static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 87 | { 0, 6, sizeof(::happy::utils::network::RequestInfo)}, 88 | { 7, 13, sizeof(::happy::utils::network::ResponseInfo)}, 89 | }; 90 | 91 | static ::google::protobuf::Message const * const file_default_instances[] = { 92 | reinterpret_cast(&::happy::utils::network::_RequestInfo_default_instance_), 93 | reinterpret_cast(&::happy::utils::network::_ResponseInfo_default_instance_), 94 | }; 95 | 96 | ::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmo_2eproto = { 97 | {}, AddDescriptors_dmo_2eproto, "dmo.proto", schemas, 98 | file_default_instances, TableStruct_dmo_2eproto::offsets, 99 | file_level_metadata_dmo_2eproto, 2, file_level_enum_descriptors_dmo_2eproto, file_level_service_descriptors_dmo_2eproto, 100 | }; 101 | 102 | const char descriptor_table_protodef_dmo_2eproto[] = 103 | "\n\tdmo.proto\022\023happy.utils.network\"\033\n\013Requ" 104 | "estInfo\022\014\n\004info\030\001 \002(\t\"\034\n\014ResponseInfo\022\014\n" 105 | "\004info\030\001 \002(\t" 106 | ; 107 | ::google::protobuf::internal::DescriptorTable descriptor_table_dmo_2eproto = { 108 | false, InitDefaults_dmo_2eproto, 109 | descriptor_table_protodef_dmo_2eproto, 110 | "dmo.proto", &assign_descriptors_table_dmo_2eproto, 91, 111 | }; 112 | 113 | void AddDescriptors_dmo_2eproto() { 114 | static constexpr ::google::protobuf::internal::InitFunc deps[1] = 115 | { 116 | }; 117 | ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmo_2eproto, deps, 0); 118 | } 119 | 120 | // Force running AddDescriptors() at dynamic initialization time. 121 | static bool dynamic_init_dummy_dmo_2eproto = []() { AddDescriptors_dmo_2eproto(); return true; }(); 122 | namespace happy { 123 | namespace utils { 124 | namespace network { 125 | 126 | // =================================================================== 127 | 128 | void RequestInfo::InitAsDefaultInstance() { 129 | } 130 | class RequestInfo::HasBitSetters { 131 | public: 132 | static void set_has_info(RequestInfo* msg) { 133 | msg->_has_bits_[0] |= 0x00000001u; 134 | } 135 | }; 136 | 137 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 138 | const int RequestInfo::kInfoFieldNumber; 139 | #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 140 | 141 | RequestInfo::RequestInfo() 142 | : ::google::protobuf::Message(), _internal_metadata_(nullptr) { 143 | SharedCtor(); 144 | // @@protoc_insertion_point(constructor:happy.utils.network.RequestInfo) 145 | } 146 | RequestInfo::RequestInfo(const RequestInfo& from) 147 | : ::google::protobuf::Message(), 148 | _internal_metadata_(nullptr), 149 | _has_bits_(from._has_bits_) { 150 | _internal_metadata_.MergeFrom(from._internal_metadata_); 151 | info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 152 | if (from.has_info()) { 153 | info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); 154 | } 155 | // @@protoc_insertion_point(copy_constructor:happy.utils.network.RequestInfo) 156 | } 157 | 158 | void RequestInfo::SharedCtor() { 159 | ::google::protobuf::internal::InitSCC( 160 | &scc_info_RequestInfo_dmo_2eproto.base); 161 | info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 162 | } 163 | 164 | RequestInfo::~RequestInfo() { 165 | // @@protoc_insertion_point(destructor:happy.utils.network.RequestInfo) 166 | SharedDtor(); 167 | } 168 | 169 | void RequestInfo::SharedDtor() { 170 | info_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 171 | } 172 | 173 | void RequestInfo::SetCachedSize(int size) const { 174 | _cached_size_.Set(size); 175 | } 176 | const RequestInfo& RequestInfo::default_instance() { 177 | ::google::protobuf::internal::InitSCC(&::scc_info_RequestInfo_dmo_2eproto.base); 178 | return *internal_default_instance(); 179 | } 180 | 181 | 182 | void RequestInfo::Clear() { 183 | // @@protoc_insertion_point(message_clear_start:happy.utils.network.RequestInfo) 184 | ::google::protobuf::uint32 cached_has_bits = 0; 185 | // Prevent compiler warnings about cached_has_bits being unused 186 | (void) cached_has_bits; 187 | 188 | cached_has_bits = _has_bits_[0]; 189 | if (cached_has_bits & 0x00000001u) { 190 | info_.ClearNonDefaultToEmptyNoArena(); 191 | } 192 | _has_bits_.Clear(); 193 | _internal_metadata_.Clear(); 194 | } 195 | 196 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 197 | const char* RequestInfo::_InternalParse(const char* begin, const char* end, void* object, 198 | ::google::protobuf::internal::ParseContext* ctx) { 199 | auto msg = static_cast(object); 200 | ::google::protobuf::int32 size; (void)size; 201 | int depth; (void)depth; 202 | ::google::protobuf::uint32 tag; 203 | ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; 204 | auto ptr = begin; 205 | while (ptr < end) { 206 | ptr = ::google::protobuf::io::Parse32(ptr, &tag); 207 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 208 | switch (tag >> 3) { 209 | // required string info = 1; 210 | case 1: { 211 | if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual; 212 | ptr = ::google::protobuf::io::ReadSize(ptr, &size); 213 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 214 | ctx->extra_parse_data().SetFieldName("happy.utils.network.RequestInfo.info"); 215 | auto str = msg->mutable_info(); 216 | if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) { 217 | object = str; 218 | str->clear(); 219 | str->reserve(size); 220 | parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8Verify; 221 | goto len_delim_till_end; 222 | } 223 | GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8Verify(ptr, size, ctx)); 224 | ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx); 225 | ptr += size; 226 | break; 227 | } 228 | default: { 229 | handle_unusual: 230 | if ((tag & 7) == 4 || tag == 0) { 231 | ctx->EndGroup(tag); 232 | return ptr; 233 | } 234 | auto res = UnknownFieldParse(tag, {_InternalParse, msg}, 235 | ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); 236 | ptr = res.first; 237 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); 238 | if (res.second) return ptr; 239 | } 240 | } // switch 241 | } // while 242 | return ptr; 243 | len_delim_till_end: 244 | return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, 245 | {parser_till_end, object}, size); 246 | } 247 | #else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 248 | bool RequestInfo::MergePartialFromCodedStream( 249 | ::google::protobuf::io::CodedInputStream* input) { 250 | #define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure 251 | ::google::protobuf::uint32 tag; 252 | // @@protoc_insertion_point(parse_start:happy.utils.network.RequestInfo) 253 | for (;;) { 254 | ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); 255 | tag = p.first; 256 | if (!p.second) goto handle_unusual; 257 | switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 258 | // required string info = 1; 259 | case 1: { 260 | if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { 261 | DO_(::google::protobuf::internal::WireFormatLite::ReadString( 262 | input, this->mutable_info())); 263 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 264 | this->info().data(), static_cast(this->info().length()), 265 | ::google::protobuf::internal::WireFormat::PARSE, 266 | "happy.utils.network.RequestInfo.info"); 267 | } else { 268 | goto handle_unusual; 269 | } 270 | break; 271 | } 272 | 273 | default: { 274 | handle_unusual: 275 | if (tag == 0) { 276 | goto success; 277 | } 278 | DO_(::google::protobuf::internal::WireFormat::SkipField( 279 | input, tag, _internal_metadata_.mutable_unknown_fields())); 280 | break; 281 | } 282 | } 283 | } 284 | success: 285 | // @@protoc_insertion_point(parse_success:happy.utils.network.RequestInfo) 286 | return true; 287 | failure: 288 | // @@protoc_insertion_point(parse_failure:happy.utils.network.RequestInfo) 289 | return false; 290 | #undef DO_ 291 | } 292 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 293 | 294 | void RequestInfo::SerializeWithCachedSizes( 295 | ::google::protobuf::io::CodedOutputStream* output) const { 296 | // @@protoc_insertion_point(serialize_start:happy.utils.network.RequestInfo) 297 | ::google::protobuf::uint32 cached_has_bits = 0; 298 | (void) cached_has_bits; 299 | 300 | cached_has_bits = _has_bits_[0]; 301 | // required string info = 1; 302 | if (cached_has_bits & 0x00000001u) { 303 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 304 | this->info().data(), static_cast(this->info().length()), 305 | ::google::protobuf::internal::WireFormat::SERIALIZE, 306 | "happy.utils.network.RequestInfo.info"); 307 | ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 308 | 1, this->info(), output); 309 | } 310 | 311 | if (_internal_metadata_.have_unknown_fields()) { 312 | ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 313 | _internal_metadata_.unknown_fields(), output); 314 | } 315 | // @@protoc_insertion_point(serialize_end:happy.utils.network.RequestInfo) 316 | } 317 | 318 | ::google::protobuf::uint8* RequestInfo::InternalSerializeWithCachedSizesToArray( 319 | ::google::protobuf::uint8* target) const { 320 | // @@protoc_insertion_point(serialize_to_array_start:happy.utils.network.RequestInfo) 321 | ::google::protobuf::uint32 cached_has_bits = 0; 322 | (void) cached_has_bits; 323 | 324 | cached_has_bits = _has_bits_[0]; 325 | // required string info = 1; 326 | if (cached_has_bits & 0x00000001u) { 327 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 328 | this->info().data(), static_cast(this->info().length()), 329 | ::google::protobuf::internal::WireFormat::SERIALIZE, 330 | "happy.utils.network.RequestInfo.info"); 331 | target = 332 | ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 333 | 1, this->info(), target); 334 | } 335 | 336 | if (_internal_metadata_.have_unknown_fields()) { 337 | target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 338 | _internal_metadata_.unknown_fields(), target); 339 | } 340 | // @@protoc_insertion_point(serialize_to_array_end:happy.utils.network.RequestInfo) 341 | return target; 342 | } 343 | 344 | size_t RequestInfo::ByteSizeLong() const { 345 | // @@protoc_insertion_point(message_byte_size_start:happy.utils.network.RequestInfo) 346 | size_t total_size = 0; 347 | 348 | if (_internal_metadata_.have_unknown_fields()) { 349 | total_size += 350 | ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 351 | _internal_metadata_.unknown_fields()); 352 | } 353 | // required string info = 1; 354 | if (has_info()) { 355 | total_size += 1 + 356 | ::google::protobuf::internal::WireFormatLite::StringSize( 357 | this->info()); 358 | } 359 | ::google::protobuf::uint32 cached_has_bits = 0; 360 | // Prevent compiler warnings about cached_has_bits being unused 361 | (void) cached_has_bits; 362 | 363 | int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); 364 | SetCachedSize(cached_size); 365 | return total_size; 366 | } 367 | 368 | void RequestInfo::MergeFrom(const ::google::protobuf::Message& from) { 369 | // @@protoc_insertion_point(generalized_merge_from_start:happy.utils.network.RequestInfo) 370 | GOOGLE_DCHECK_NE(&from, this); 371 | const RequestInfo* source = 372 | ::google::protobuf::DynamicCastToGenerated( 373 | &from); 374 | if (source == nullptr) { 375 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:happy.utils.network.RequestInfo) 376 | ::google::protobuf::internal::ReflectionOps::Merge(from, this); 377 | } else { 378 | // @@protoc_insertion_point(generalized_merge_from_cast_success:happy.utils.network.RequestInfo) 379 | MergeFrom(*source); 380 | } 381 | } 382 | 383 | void RequestInfo::MergeFrom(const RequestInfo& from) { 384 | // @@protoc_insertion_point(class_specific_merge_from_start:happy.utils.network.RequestInfo) 385 | GOOGLE_DCHECK_NE(&from, this); 386 | _internal_metadata_.MergeFrom(from._internal_metadata_); 387 | ::google::protobuf::uint32 cached_has_bits = 0; 388 | (void) cached_has_bits; 389 | 390 | if (from.has_info()) { 391 | _has_bits_[0] |= 0x00000001u; 392 | info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); 393 | } 394 | } 395 | 396 | void RequestInfo::CopyFrom(const ::google::protobuf::Message& from) { 397 | // @@protoc_insertion_point(generalized_copy_from_start:happy.utils.network.RequestInfo) 398 | if (&from == this) return; 399 | Clear(); 400 | MergeFrom(from); 401 | } 402 | 403 | void RequestInfo::CopyFrom(const RequestInfo& from) { 404 | // @@protoc_insertion_point(class_specific_copy_from_start:happy.utils.network.RequestInfo) 405 | if (&from == this) return; 406 | Clear(); 407 | MergeFrom(from); 408 | } 409 | 410 | bool RequestInfo::IsInitialized() const { 411 | if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; 412 | return true; 413 | } 414 | 415 | void RequestInfo::Swap(RequestInfo* other) { 416 | if (other == this) return; 417 | InternalSwap(other); 418 | } 419 | void RequestInfo::InternalSwap(RequestInfo* other) { 420 | using std::swap; 421 | _internal_metadata_.Swap(&other->_internal_metadata_); 422 | swap(_has_bits_[0], other->_has_bits_[0]); 423 | info_.Swap(&other->info_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), 424 | GetArenaNoVirtual()); 425 | } 426 | 427 | ::google::protobuf::Metadata RequestInfo::GetMetadata() const { 428 | ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmo_2eproto); 429 | return ::file_level_metadata_dmo_2eproto[kIndexInFileMessages]; 430 | } 431 | 432 | 433 | // =================================================================== 434 | 435 | void ResponseInfo::InitAsDefaultInstance() { 436 | } 437 | class ResponseInfo::HasBitSetters { 438 | public: 439 | static void set_has_info(ResponseInfo* msg) { 440 | msg->_has_bits_[0] |= 0x00000001u; 441 | } 442 | }; 443 | 444 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 445 | const int ResponseInfo::kInfoFieldNumber; 446 | #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 447 | 448 | ResponseInfo::ResponseInfo() 449 | : ::google::protobuf::Message(), _internal_metadata_(nullptr) { 450 | SharedCtor(); 451 | // @@protoc_insertion_point(constructor:happy.utils.network.ResponseInfo) 452 | } 453 | ResponseInfo::ResponseInfo(const ResponseInfo& from) 454 | : ::google::protobuf::Message(), 455 | _internal_metadata_(nullptr), 456 | _has_bits_(from._has_bits_) { 457 | _internal_metadata_.MergeFrom(from._internal_metadata_); 458 | info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 459 | if (from.has_info()) { 460 | info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); 461 | } 462 | // @@protoc_insertion_point(copy_constructor:happy.utils.network.ResponseInfo) 463 | } 464 | 465 | void ResponseInfo::SharedCtor() { 466 | ::google::protobuf::internal::InitSCC( 467 | &scc_info_ResponseInfo_dmo_2eproto.base); 468 | info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 469 | } 470 | 471 | ResponseInfo::~ResponseInfo() { 472 | // @@protoc_insertion_point(destructor:happy.utils.network.ResponseInfo) 473 | SharedDtor(); 474 | } 475 | 476 | void ResponseInfo::SharedDtor() { 477 | info_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 478 | } 479 | 480 | void ResponseInfo::SetCachedSize(int size) const { 481 | _cached_size_.Set(size); 482 | } 483 | const ResponseInfo& ResponseInfo::default_instance() { 484 | ::google::protobuf::internal::InitSCC(&::scc_info_ResponseInfo_dmo_2eproto.base); 485 | return *internal_default_instance(); 486 | } 487 | 488 | 489 | void ResponseInfo::Clear() { 490 | // @@protoc_insertion_point(message_clear_start:happy.utils.network.ResponseInfo) 491 | ::google::protobuf::uint32 cached_has_bits = 0; 492 | // Prevent compiler warnings about cached_has_bits being unused 493 | (void) cached_has_bits; 494 | 495 | cached_has_bits = _has_bits_[0]; 496 | if (cached_has_bits & 0x00000001u) { 497 | info_.ClearNonDefaultToEmptyNoArena(); 498 | } 499 | _has_bits_.Clear(); 500 | _internal_metadata_.Clear(); 501 | } 502 | 503 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 504 | const char* ResponseInfo::_InternalParse(const char* begin, const char* end, void* object, 505 | ::google::protobuf::internal::ParseContext* ctx) { 506 | auto msg = static_cast(object); 507 | ::google::protobuf::int32 size; (void)size; 508 | int depth; (void)depth; 509 | ::google::protobuf::uint32 tag; 510 | ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; 511 | auto ptr = begin; 512 | while (ptr < end) { 513 | ptr = ::google::protobuf::io::Parse32(ptr, &tag); 514 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 515 | switch (tag >> 3) { 516 | // required string info = 1; 517 | case 1: { 518 | if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual; 519 | ptr = ::google::protobuf::io::ReadSize(ptr, &size); 520 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 521 | ctx->extra_parse_data().SetFieldName("happy.utils.network.ResponseInfo.info"); 522 | auto str = msg->mutable_info(); 523 | if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) { 524 | object = str; 525 | str->clear(); 526 | str->reserve(size); 527 | parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8Verify; 528 | goto len_delim_till_end; 529 | } 530 | GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8Verify(ptr, size, ctx)); 531 | ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx); 532 | ptr += size; 533 | break; 534 | } 535 | default: { 536 | handle_unusual: 537 | if ((tag & 7) == 4 || tag == 0) { 538 | ctx->EndGroup(tag); 539 | return ptr; 540 | } 541 | auto res = UnknownFieldParse(tag, {_InternalParse, msg}, 542 | ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); 543 | ptr = res.first; 544 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); 545 | if (res.second) return ptr; 546 | } 547 | } // switch 548 | } // while 549 | return ptr; 550 | len_delim_till_end: 551 | return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, 552 | {parser_till_end, object}, size); 553 | } 554 | #else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 555 | bool ResponseInfo::MergePartialFromCodedStream( 556 | ::google::protobuf::io::CodedInputStream* input) { 557 | #define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure 558 | ::google::protobuf::uint32 tag; 559 | // @@protoc_insertion_point(parse_start:happy.utils.network.ResponseInfo) 560 | for (;;) { 561 | ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); 562 | tag = p.first; 563 | if (!p.second) goto handle_unusual; 564 | switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 565 | // required string info = 1; 566 | case 1: { 567 | if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { 568 | DO_(::google::protobuf::internal::WireFormatLite::ReadString( 569 | input, this->mutable_info())); 570 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 571 | this->info().data(), static_cast(this->info().length()), 572 | ::google::protobuf::internal::WireFormat::PARSE, 573 | "happy.utils.network.ResponseInfo.info"); 574 | } else { 575 | goto handle_unusual; 576 | } 577 | break; 578 | } 579 | 580 | default: { 581 | handle_unusual: 582 | if (tag == 0) { 583 | goto success; 584 | } 585 | DO_(::google::protobuf::internal::WireFormat::SkipField( 586 | input, tag, _internal_metadata_.mutable_unknown_fields())); 587 | break; 588 | } 589 | } 590 | } 591 | success: 592 | // @@protoc_insertion_point(parse_success:happy.utils.network.ResponseInfo) 593 | return true; 594 | failure: 595 | // @@protoc_insertion_point(parse_failure:happy.utils.network.ResponseInfo) 596 | return false; 597 | #undef DO_ 598 | } 599 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 600 | 601 | void ResponseInfo::SerializeWithCachedSizes( 602 | ::google::protobuf::io::CodedOutputStream* output) const { 603 | // @@protoc_insertion_point(serialize_start:happy.utils.network.ResponseInfo) 604 | ::google::protobuf::uint32 cached_has_bits = 0; 605 | (void) cached_has_bits; 606 | 607 | cached_has_bits = _has_bits_[0]; 608 | // required string info = 1; 609 | if (cached_has_bits & 0x00000001u) { 610 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 611 | this->info().data(), static_cast(this->info().length()), 612 | ::google::protobuf::internal::WireFormat::SERIALIZE, 613 | "happy.utils.network.ResponseInfo.info"); 614 | ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 615 | 1, this->info(), output); 616 | } 617 | 618 | if (_internal_metadata_.have_unknown_fields()) { 619 | ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 620 | _internal_metadata_.unknown_fields(), output); 621 | } 622 | // @@protoc_insertion_point(serialize_end:happy.utils.network.ResponseInfo) 623 | } 624 | 625 | ::google::protobuf::uint8* ResponseInfo::InternalSerializeWithCachedSizesToArray( 626 | ::google::protobuf::uint8* target) const { 627 | // @@protoc_insertion_point(serialize_to_array_start:happy.utils.network.ResponseInfo) 628 | ::google::protobuf::uint32 cached_has_bits = 0; 629 | (void) cached_has_bits; 630 | 631 | cached_has_bits = _has_bits_[0]; 632 | // required string info = 1; 633 | if (cached_has_bits & 0x00000001u) { 634 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 635 | this->info().data(), static_cast(this->info().length()), 636 | ::google::protobuf::internal::WireFormat::SERIALIZE, 637 | "happy.utils.network.ResponseInfo.info"); 638 | target = 639 | ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 640 | 1, this->info(), target); 641 | } 642 | 643 | if (_internal_metadata_.have_unknown_fields()) { 644 | target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 645 | _internal_metadata_.unknown_fields(), target); 646 | } 647 | // @@protoc_insertion_point(serialize_to_array_end:happy.utils.network.ResponseInfo) 648 | return target; 649 | } 650 | 651 | size_t ResponseInfo::ByteSizeLong() const { 652 | // @@protoc_insertion_point(message_byte_size_start:happy.utils.network.ResponseInfo) 653 | size_t total_size = 0; 654 | 655 | if (_internal_metadata_.have_unknown_fields()) { 656 | total_size += 657 | ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 658 | _internal_metadata_.unknown_fields()); 659 | } 660 | // required string info = 1; 661 | if (has_info()) { 662 | total_size += 1 + 663 | ::google::protobuf::internal::WireFormatLite::StringSize( 664 | this->info()); 665 | } 666 | ::google::protobuf::uint32 cached_has_bits = 0; 667 | // Prevent compiler warnings about cached_has_bits being unused 668 | (void) cached_has_bits; 669 | 670 | int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); 671 | SetCachedSize(cached_size); 672 | return total_size; 673 | } 674 | 675 | void ResponseInfo::MergeFrom(const ::google::protobuf::Message& from) { 676 | // @@protoc_insertion_point(generalized_merge_from_start:happy.utils.network.ResponseInfo) 677 | GOOGLE_DCHECK_NE(&from, this); 678 | const ResponseInfo* source = 679 | ::google::protobuf::DynamicCastToGenerated( 680 | &from); 681 | if (source == nullptr) { 682 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:happy.utils.network.ResponseInfo) 683 | ::google::protobuf::internal::ReflectionOps::Merge(from, this); 684 | } else { 685 | // @@protoc_insertion_point(generalized_merge_from_cast_success:happy.utils.network.ResponseInfo) 686 | MergeFrom(*source); 687 | } 688 | } 689 | 690 | void ResponseInfo::MergeFrom(const ResponseInfo& from) { 691 | // @@protoc_insertion_point(class_specific_merge_from_start:happy.utils.network.ResponseInfo) 692 | GOOGLE_DCHECK_NE(&from, this); 693 | _internal_metadata_.MergeFrom(from._internal_metadata_); 694 | ::google::protobuf::uint32 cached_has_bits = 0; 695 | (void) cached_has_bits; 696 | 697 | if (from.has_info()) { 698 | _has_bits_[0] |= 0x00000001u; 699 | info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); 700 | } 701 | } 702 | 703 | void ResponseInfo::CopyFrom(const ::google::protobuf::Message& from) { 704 | // @@protoc_insertion_point(generalized_copy_from_start:happy.utils.network.ResponseInfo) 705 | if (&from == this) return; 706 | Clear(); 707 | MergeFrom(from); 708 | } 709 | 710 | void ResponseInfo::CopyFrom(const ResponseInfo& from) { 711 | // @@protoc_insertion_point(class_specific_copy_from_start:happy.utils.network.ResponseInfo) 712 | if (&from == this) return; 713 | Clear(); 714 | MergeFrom(from); 715 | } 716 | 717 | bool ResponseInfo::IsInitialized() const { 718 | if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false; 719 | return true; 720 | } 721 | 722 | void ResponseInfo::Swap(ResponseInfo* other) { 723 | if (other == this) return; 724 | InternalSwap(other); 725 | } 726 | void ResponseInfo::InternalSwap(ResponseInfo* other) { 727 | using std::swap; 728 | _internal_metadata_.Swap(&other->_internal_metadata_); 729 | swap(_has_bits_[0], other->_has_bits_[0]); 730 | info_.Swap(&other->info_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), 731 | GetArenaNoVirtual()); 732 | } 733 | 734 | ::google::protobuf::Metadata ResponseInfo::GetMetadata() const { 735 | ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmo_2eproto); 736 | return ::file_level_metadata_dmo_2eproto[kIndexInFileMessages]; 737 | } 738 | 739 | 740 | // @@protoc_insertion_point(namespace_scope) 741 | } // namespace network 742 | } // namespace utils 743 | } // namespace happy 744 | namespace google { 745 | namespace protobuf { 746 | template<> PROTOBUF_NOINLINE ::happy::utils::network::RequestInfo* Arena::CreateMaybeMessage< ::happy::utils::network::RequestInfo >(Arena* arena) { 747 | return Arena::CreateInternal< ::happy::utils::network::RequestInfo >(arena); 748 | } 749 | template<> PROTOBUF_NOINLINE ::happy::utils::network::ResponseInfo* Arena::CreateMaybeMessage< ::happy::utils::network::ResponseInfo >(Arena* arena) { 750 | return Arena::CreateInternal< ::happy::utils::network::ResponseInfo >(arena); 751 | } 752 | } // namespace protobuf 753 | } // namespace google 754 | 755 | // @@protoc_insertion_point(global_scope) 756 | #include 757 | -------------------------------------------------------------------------------- /examples/dmo.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: dmo.proto 3 | 4 | #ifndef PROTOBUF_INCLUDED_dmo_2eproto 5 | #define PROTOBUF_INCLUDED_dmo_2eproto 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #if PROTOBUF_VERSION < 3006001 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3006001 < PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include // IWYU pragma: export 32 | #include // IWYU pragma: export 33 | #include 34 | // @@protoc_insertion_point(includes) 35 | #include 36 | #define PROTOBUF_INTERNAL_EXPORT_dmo_2eproto 37 | 38 | // Internal implementation detail -- do not use these members. 39 | struct TableStruct_dmo_2eproto { 40 | static const ::google::protobuf::internal::ParseTableField entries[] 41 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 42 | static const ::google::protobuf::internal::AuxillaryParseTableField aux[] 43 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 44 | static const ::google::protobuf::internal::ParseTable schema[2] 45 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 46 | static const ::google::protobuf::internal::FieldMetadata field_metadata[]; 47 | static const ::google::protobuf::internal::SerializationTable serialization_table[]; 48 | static const ::google::protobuf::uint32 offsets[]; 49 | }; 50 | void AddDescriptors_dmo_2eproto(); 51 | namespace happy { 52 | namespace utils { 53 | namespace network { 54 | class RequestInfo; 55 | class RequestInfoDefaultTypeInternal; 56 | extern RequestInfoDefaultTypeInternal _RequestInfo_default_instance_; 57 | class ResponseInfo; 58 | class ResponseInfoDefaultTypeInternal; 59 | extern ResponseInfoDefaultTypeInternal _ResponseInfo_default_instance_; 60 | } // namespace network 61 | } // namespace utils 62 | } // namespace happy 63 | namespace google { 64 | namespace protobuf { 65 | template<> ::happy::utils::network::RequestInfo* Arena::CreateMaybeMessage<::happy::utils::network::RequestInfo>(Arena*); 66 | template<> ::happy::utils::network::ResponseInfo* Arena::CreateMaybeMessage<::happy::utils::network::ResponseInfo>(Arena*); 67 | } // namespace protobuf 68 | } // namespace google 69 | namespace happy { 70 | namespace utils { 71 | namespace network { 72 | 73 | // =================================================================== 74 | 75 | class RequestInfo : 76 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:happy.utils.network.RequestInfo) */ { 77 | public: 78 | RequestInfo(); 79 | virtual ~RequestInfo(); 80 | 81 | RequestInfo(const RequestInfo& from); 82 | 83 | inline RequestInfo& operator=(const RequestInfo& from) { 84 | CopyFrom(from); 85 | return *this; 86 | } 87 | #if LANG_CXX11 88 | RequestInfo(RequestInfo&& from) noexcept 89 | : RequestInfo() { 90 | *this = ::std::move(from); 91 | } 92 | 93 | inline RequestInfo& operator=(RequestInfo&& from) noexcept { 94 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 95 | if (this != &from) InternalSwap(&from); 96 | } else { 97 | CopyFrom(from); 98 | } 99 | return *this; 100 | } 101 | #endif 102 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 103 | return _internal_metadata_.unknown_fields(); 104 | } 105 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 106 | return _internal_metadata_.mutable_unknown_fields(); 107 | } 108 | 109 | static const ::google::protobuf::Descriptor* descriptor() { 110 | return default_instance().GetDescriptor(); 111 | } 112 | static const RequestInfo& default_instance(); 113 | 114 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 115 | static inline const RequestInfo* internal_default_instance() { 116 | return reinterpret_cast( 117 | &_RequestInfo_default_instance_); 118 | } 119 | static constexpr int kIndexInFileMessages = 120 | 0; 121 | 122 | void Swap(RequestInfo* other); 123 | friend void swap(RequestInfo& a, RequestInfo& b) { 124 | a.Swap(&b); 125 | } 126 | 127 | // implements Message ---------------------------------------------- 128 | 129 | inline RequestInfo* New() const final { 130 | return CreateMaybeMessage(nullptr); 131 | } 132 | 133 | RequestInfo* New(::google::protobuf::Arena* arena) const final { 134 | return CreateMaybeMessage(arena); 135 | } 136 | void CopyFrom(const ::google::protobuf::Message& from) final; 137 | void MergeFrom(const ::google::protobuf::Message& from) final; 138 | void CopyFrom(const RequestInfo& from); 139 | void MergeFrom(const RequestInfo& from); 140 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 141 | bool IsInitialized() const final; 142 | 143 | size_t ByteSizeLong() const final; 144 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 145 | static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); 146 | ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } 147 | #else 148 | bool MergePartialFromCodedStream( 149 | ::google::protobuf::io::CodedInputStream* input) final; 150 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 151 | void SerializeWithCachedSizes( 152 | ::google::protobuf::io::CodedOutputStream* output) const final; 153 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 154 | ::google::protobuf::uint8* target) const final; 155 | int GetCachedSize() const final { return _cached_size_.Get(); } 156 | 157 | private: 158 | void SharedCtor(); 159 | void SharedDtor(); 160 | void SetCachedSize(int size) const final; 161 | void InternalSwap(RequestInfo* other); 162 | private: 163 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 164 | return nullptr; 165 | } 166 | inline void* MaybeArenaPtr() const { 167 | return nullptr; 168 | } 169 | public: 170 | 171 | ::google::protobuf::Metadata GetMetadata() const final; 172 | 173 | // nested types ---------------------------------------------------- 174 | 175 | // accessors ------------------------------------------------------- 176 | 177 | // required string info = 1; 178 | bool has_info() const; 179 | void clear_info(); 180 | static const int kInfoFieldNumber = 1; 181 | const ::std::string& info() const; 182 | void set_info(const ::std::string& value); 183 | #if LANG_CXX11 184 | void set_info(::std::string&& value); 185 | #endif 186 | void set_info(const char* value); 187 | void set_info(const char* value, size_t size); 188 | ::std::string* mutable_info(); 189 | ::std::string* release_info(); 190 | void set_allocated_info(::std::string* info); 191 | 192 | // @@protoc_insertion_point(class_scope:happy.utils.network.RequestInfo) 193 | private: 194 | class HasBitSetters; 195 | 196 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 197 | ::google::protobuf::internal::HasBits<1> _has_bits_; 198 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 199 | ::google::protobuf::internal::ArenaStringPtr info_; 200 | friend struct ::TableStruct_dmo_2eproto; 201 | }; 202 | // ------------------------------------------------------------------- 203 | 204 | class ResponseInfo : 205 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:happy.utils.network.ResponseInfo) */ { 206 | public: 207 | ResponseInfo(); 208 | virtual ~ResponseInfo(); 209 | 210 | ResponseInfo(const ResponseInfo& from); 211 | 212 | inline ResponseInfo& operator=(const ResponseInfo& from) { 213 | CopyFrom(from); 214 | return *this; 215 | } 216 | #if LANG_CXX11 217 | ResponseInfo(ResponseInfo&& from) noexcept 218 | : ResponseInfo() { 219 | *this = ::std::move(from); 220 | } 221 | 222 | inline ResponseInfo& operator=(ResponseInfo&& from) noexcept { 223 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 224 | if (this != &from) InternalSwap(&from); 225 | } else { 226 | CopyFrom(from); 227 | } 228 | return *this; 229 | } 230 | #endif 231 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 232 | return _internal_metadata_.unknown_fields(); 233 | } 234 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 235 | return _internal_metadata_.mutable_unknown_fields(); 236 | } 237 | 238 | static const ::google::protobuf::Descriptor* descriptor() { 239 | return default_instance().GetDescriptor(); 240 | } 241 | static const ResponseInfo& default_instance(); 242 | 243 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 244 | static inline const ResponseInfo* internal_default_instance() { 245 | return reinterpret_cast( 246 | &_ResponseInfo_default_instance_); 247 | } 248 | static constexpr int kIndexInFileMessages = 249 | 1; 250 | 251 | void Swap(ResponseInfo* other); 252 | friend void swap(ResponseInfo& a, ResponseInfo& b) { 253 | a.Swap(&b); 254 | } 255 | 256 | // implements Message ---------------------------------------------- 257 | 258 | inline ResponseInfo* New() const final { 259 | return CreateMaybeMessage(nullptr); 260 | } 261 | 262 | ResponseInfo* New(::google::protobuf::Arena* arena) const final { 263 | return CreateMaybeMessage(arena); 264 | } 265 | void CopyFrom(const ::google::protobuf::Message& from) final; 266 | void MergeFrom(const ::google::protobuf::Message& from) final; 267 | void CopyFrom(const ResponseInfo& from); 268 | void MergeFrom(const ResponseInfo& from); 269 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 270 | bool IsInitialized() const final; 271 | 272 | size_t ByteSizeLong() const final; 273 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 274 | static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); 275 | ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } 276 | #else 277 | bool MergePartialFromCodedStream( 278 | ::google::protobuf::io::CodedInputStream* input) final; 279 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 280 | void SerializeWithCachedSizes( 281 | ::google::protobuf::io::CodedOutputStream* output) const final; 282 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 283 | ::google::protobuf::uint8* target) const final; 284 | int GetCachedSize() const final { return _cached_size_.Get(); } 285 | 286 | private: 287 | void SharedCtor(); 288 | void SharedDtor(); 289 | void SetCachedSize(int size) const final; 290 | void InternalSwap(ResponseInfo* other); 291 | private: 292 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 293 | return nullptr; 294 | } 295 | inline void* MaybeArenaPtr() const { 296 | return nullptr; 297 | } 298 | public: 299 | 300 | ::google::protobuf::Metadata GetMetadata() const final; 301 | 302 | // nested types ---------------------------------------------------- 303 | 304 | // accessors ------------------------------------------------------- 305 | 306 | // required string info = 1; 307 | bool has_info() const; 308 | void clear_info(); 309 | static const int kInfoFieldNumber = 1; 310 | const ::std::string& info() const; 311 | void set_info(const ::std::string& value); 312 | #if LANG_CXX11 313 | void set_info(::std::string&& value); 314 | #endif 315 | void set_info(const char* value); 316 | void set_info(const char* value, size_t size); 317 | ::std::string* mutable_info(); 318 | ::std::string* release_info(); 319 | void set_allocated_info(::std::string* info); 320 | 321 | // @@protoc_insertion_point(class_scope:happy.utils.network.ResponseInfo) 322 | private: 323 | class HasBitSetters; 324 | 325 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 326 | ::google::protobuf::internal::HasBits<1> _has_bits_; 327 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 328 | ::google::protobuf::internal::ArenaStringPtr info_; 329 | friend struct ::TableStruct_dmo_2eproto; 330 | }; 331 | // =================================================================== 332 | 333 | 334 | // =================================================================== 335 | 336 | #ifdef __GNUC__ 337 | #pragma GCC diagnostic push 338 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 339 | #endif // __GNUC__ 340 | // RequestInfo 341 | 342 | // required string info = 1; 343 | inline bool RequestInfo::has_info() const { 344 | return (_has_bits_[0] & 0x00000001u) != 0; 345 | } 346 | inline void RequestInfo::clear_info() { 347 | info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 348 | _has_bits_[0] &= ~0x00000001u; 349 | } 350 | inline const ::std::string& RequestInfo::info() const { 351 | // @@protoc_insertion_point(field_get:happy.utils.network.RequestInfo.info) 352 | return info_.GetNoArena(); 353 | } 354 | inline void RequestInfo::set_info(const ::std::string& value) { 355 | _has_bits_[0] |= 0x00000001u; 356 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 357 | // @@protoc_insertion_point(field_set:happy.utils.network.RequestInfo.info) 358 | } 359 | #if LANG_CXX11 360 | inline void RequestInfo::set_info(::std::string&& value) { 361 | _has_bits_[0] |= 0x00000001u; 362 | info_.SetNoArena( 363 | &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 364 | // @@protoc_insertion_point(field_set_rvalue:happy.utils.network.RequestInfo.info) 365 | } 366 | #endif 367 | inline void RequestInfo::set_info(const char* value) { 368 | GOOGLE_DCHECK(value != nullptr); 369 | _has_bits_[0] |= 0x00000001u; 370 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 371 | // @@protoc_insertion_point(field_set_char:happy.utils.network.RequestInfo.info) 372 | } 373 | inline void RequestInfo::set_info(const char* value, size_t size) { 374 | _has_bits_[0] |= 0x00000001u; 375 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 376 | ::std::string(reinterpret_cast(value), size)); 377 | // @@protoc_insertion_point(field_set_pointer:happy.utils.network.RequestInfo.info) 378 | } 379 | inline ::std::string* RequestInfo::mutable_info() { 380 | _has_bits_[0] |= 0x00000001u; 381 | // @@protoc_insertion_point(field_mutable:happy.utils.network.RequestInfo.info) 382 | return info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 383 | } 384 | inline ::std::string* RequestInfo::release_info() { 385 | // @@protoc_insertion_point(field_release:happy.utils.network.RequestInfo.info) 386 | if (!has_info()) { 387 | return nullptr; 388 | } 389 | _has_bits_[0] &= ~0x00000001u; 390 | return info_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 391 | } 392 | inline void RequestInfo::set_allocated_info(::std::string* info) { 393 | if (info != nullptr) { 394 | _has_bits_[0] |= 0x00000001u; 395 | } else { 396 | _has_bits_[0] &= ~0x00000001u; 397 | } 398 | info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), info); 399 | // @@protoc_insertion_point(field_set_allocated:happy.utils.network.RequestInfo.info) 400 | } 401 | 402 | // ------------------------------------------------------------------- 403 | 404 | // ResponseInfo 405 | 406 | // required string info = 1; 407 | inline bool ResponseInfo::has_info() const { 408 | return (_has_bits_[0] & 0x00000001u) != 0; 409 | } 410 | inline void ResponseInfo::clear_info() { 411 | info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 412 | _has_bits_[0] &= ~0x00000001u; 413 | } 414 | inline const ::std::string& ResponseInfo::info() const { 415 | // @@protoc_insertion_point(field_get:happy.utils.network.ResponseInfo.info) 416 | return info_.GetNoArena(); 417 | } 418 | inline void ResponseInfo::set_info(const ::std::string& value) { 419 | _has_bits_[0] |= 0x00000001u; 420 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 421 | // @@protoc_insertion_point(field_set:happy.utils.network.ResponseInfo.info) 422 | } 423 | #if LANG_CXX11 424 | inline void ResponseInfo::set_info(::std::string&& value) { 425 | _has_bits_[0] |= 0x00000001u; 426 | info_.SetNoArena( 427 | &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 428 | // @@protoc_insertion_point(field_set_rvalue:happy.utils.network.ResponseInfo.info) 429 | } 430 | #endif 431 | inline void ResponseInfo::set_info(const char* value) { 432 | GOOGLE_DCHECK(value != nullptr); 433 | _has_bits_[0] |= 0x00000001u; 434 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 435 | // @@protoc_insertion_point(field_set_char:happy.utils.network.ResponseInfo.info) 436 | } 437 | inline void ResponseInfo::set_info(const char* value, size_t size) { 438 | _has_bits_[0] |= 0x00000001u; 439 | info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 440 | ::std::string(reinterpret_cast(value), size)); 441 | // @@protoc_insertion_point(field_set_pointer:happy.utils.network.ResponseInfo.info) 442 | } 443 | inline ::std::string* ResponseInfo::mutable_info() { 444 | _has_bits_[0] |= 0x00000001u; 445 | // @@protoc_insertion_point(field_mutable:happy.utils.network.ResponseInfo.info) 446 | return info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 447 | } 448 | inline ::std::string* ResponseInfo::release_info() { 449 | // @@protoc_insertion_point(field_release:happy.utils.network.ResponseInfo.info) 450 | if (!has_info()) { 451 | return nullptr; 452 | } 453 | _has_bits_[0] &= ~0x00000001u; 454 | return info_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 455 | } 456 | inline void ResponseInfo::set_allocated_info(::std::string* info) { 457 | if (info != nullptr) { 458 | _has_bits_[0] |= 0x00000001u; 459 | } else { 460 | _has_bits_[0] &= ~0x00000001u; 461 | } 462 | info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), info); 463 | // @@protoc_insertion_point(field_set_allocated:happy.utils.network.ResponseInfo.info) 464 | } 465 | 466 | #ifdef __GNUC__ 467 | #pragma GCC diagnostic pop 468 | #endif // __GNUC__ 469 | // ------------------------------------------------------------------- 470 | 471 | 472 | // @@protoc_insertion_point(namespace_scope) 473 | 474 | } // namespace network 475 | } // namespace utils 476 | } // namespace happy 477 | 478 | // @@protoc_insertion_point(global_scope) 479 | 480 | #include 481 | #endif // PROTOBUF_INCLUDED_dmo_2eproto 482 | -------------------------------------------------------------------------------- /examples/dmo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package happy.utils.network; 3 | 4 | message RequestInfo 5 | { 6 | required string info = 1; 7 | } 8 | message ResponseInfo 9 | { 10 | required string info = 1; 11 | } -------------------------------------------------------------------------------- /examples/proto_client_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "proto_client_message_factory.h" 2 | #include "dmo.pb.h" 3 | 4 | ProtoClientMessageFactory::ProtoClientMessageFactory(const string& closed_print, const bool is_read_print) 5 | : ClientMessageFactory(closed_print, is_read_print) 6 | { 7 | handler_[RequestInfo::descriptor()->full_name()] = std::bind(&ProtoClientMessageFactory::ResponseInfoHandler, this, std::placeholders::_1); 8 | } 9 | 10 | shared_ptr ProtoClientMessageFactory::Produce(const shared_ptr news) 11 | { 12 | return nullptr; 13 | } 14 | 15 | shared_ptr ProtoClientMessageFactory::ResponseInfoHandler(const shared_ptr message) 16 | { 17 | //auto response_info = dynamic_pointer_cast (message); 18 | return nullptr; 19 | } -------------------------------------------------------------------------------- /examples/proto_client_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace happy::utils::network; 4 | 5 | class ProtoClientMessageFactory : public ClientMessageFactory 6 | { 7 | public: 8 | ProtoClientMessageFactory(const string& closed_print = "", const bool is_read_print = false); 9 | private: 10 | virtual shared_ptr Produce(const shared_ptr news) override final; 11 | shared_ptr ResponseInfoHandler(const shared_ptr message); 12 | }; -------------------------------------------------------------------------------- /examples/proto_server_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "proto_server_message_factory.h" 2 | #include "dmo.pb.h" 3 | 4 | ProtoServerMessageFactory::ProtoServerMessageFactory(const string& session_id, const bool is_read_print) 5 | : ServerMessageFactory(session_id, is_read_print) 6 | { 7 | handler_[RequestInfo::descriptor()->full_name()] = std::bind(&ProtoServerMessageFactory::RequestInfoHandler, this, std::placeholders::_1); 8 | } 9 | 10 | shared_ptr ProtoServerMessageFactory::RequestInfoHandler(const shared_ptr message) 11 | { 12 | //auto request_info = dynamic_pointer_cast (message); 13 | auto response = make_shared (); 14 | response->set_info("server response data"); 15 | 16 | return response; 17 | } -------------------------------------------------------------------------------- /examples/proto_server_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using namespace happy::utils::network; 5 | 6 | class ProtoServerMessageFactory : public ServerMessageFactory 7 | { 8 | CREATE_PROTO(ProtoServerMessageFactory); 9 | public: 10 | ProtoServerMessageFactory(const string& session_id, const bool is_read_print); 11 | private: 12 | shared_ptr RequestInfoHandler(const shared_ptr message); 13 | }; -------------------------------------------------------------------------------- /examples/server_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "server_message_factory.h" 2 | #include 3 | 4 | bool ServerMessageFactory::IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) 5 | { 6 | uint32_t content_length = 0; 7 | if (length < 4 || (content_length = boost::asio::detail::socket_ops::network_to_host_long(*reinterpret_cast (buffer))) > length - 4) 8 | { 9 | has_package = true; 10 | 11 | return false; 12 | } 13 | deal_length = 4 + content_length; 14 | 15 | return true; 16 | } 17 | 18 | bool ServerMessageFactory::HandleRead(const uint8_t* buffer, const size_t& length, string& response) 19 | { 20 | printf("receive client data: %s\n", ToHost(buffer, length).content.c_str()); 21 | response = ToNetwork("server response data"); 22 | 23 | return true; 24 | } -------------------------------------------------------------------------------- /examples/server_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class ServerMessageFactory : public happy::asio::ip::MessageFactory 6 | { 7 | using happy::asio::ip::MessageFactory::MessageFactory; 8 | CREATE(ServerMessageFactory); 9 | private: 10 | virtual bool IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) override final; 11 | virtual bool HandleRead(const uint8_t* buffer, const size_t& length, string& response) override final; 12 | }; -------------------------------------------------------------------------------- /examples/tcp_client.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangziwen333/happy-ip/f8a1ae787f85c0131c4c8e9c782d64eadd1b09f7/examples/tcp_client.cpp -------------------------------------------------------------------------------- /examples/tcp_client_proto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proto_client_message_factory.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "dmo.pb.h" 8 | #include 9 | #ifdef GLOG_OUTPUT 10 | #include 11 | #endif 12 | using namespace happy::utils::network; 13 | using namespace std; 14 | using namespace happy::asio::ip; 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | // 默认创建线程池的大小为4。 19 | //IoServicePool::singleton::Create(4); 20 | #ifdef GLOG_OUTPUT 21 | utils::ConfigGlog(argv[0]); 22 | #endif 23 | auto tcp_client = make_shared (); 24 | tcp_client->SetMessageFactory(dynamic_pointer_cast (make_shared ("", true))); 25 | auto const ip = "127.0.0.1"; 26 | auto const port = 1234; 27 | cout << "connect to " << ip << ":" << port << endl; 28 | tcp_client->Connect(ip, port); 29 | cout << "connection is successful" << endl; 30 | thread t([]() { IoServicePool::singleton::GetInstance()->Run(); }); 31 | t.detach(); 32 | while (true) 33 | { 34 | cout << "please input send server string(enter to end): "; 35 | char buffer[1024]; 36 | cin >> buffer; 37 | auto request_info = make_shared (); 38 | request_info->set_info(buffer); 39 | string out_buffer; 40 | ProtoNetworkConvert::singleton::GetInstance()->ToNetwork(request_info, out_buffer); 41 | tcp_client->AsyncWrite(out_buffer); 42 | this_thread::sleep_for(chrono::seconds(1)); 43 | //cin.getline(buffer, size(buffer)); 44 | } 45 | return EXIT_SUCCESS; 46 | } -------------------------------------------------------------------------------- /examples/tcp_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "server_message_factory.h" 3 | using namespace happy::asio::ip; 4 | 5 | int main() 6 | { 7 | // 默认创建线程池的大小为4 8 | //IoServicePool::singleton::Create(4); 9 | uint16_t port = 1234; 10 | TcpServer tcp_server(port); 11 | printf("tcp server is run (port=%d)\n", port); 12 | tcp_server.SetMessageFactory(make_shared ()); 13 | IoServicePool::singleton::GetInstance()->Run(); 14 | 15 | return EXIT_SUCCESS; 16 | } -------------------------------------------------------------------------------- /examples/tcp_server_proto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proto_server_message_factory.h" 3 | #ifdef GLOG_OUTPUT 4 | #include 5 | #endif 6 | using namespace happy::asio::ip; 7 | 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | // 默认创建线程池的大小为4 12 | //IoServicePool::singleton::Create(4); 13 | #ifdef GLOG_OUTPUT 14 | utils::ConfigGlog(argv[0]); 15 | #endif 16 | uint16_t port = 1234; 17 | TcpServer tcp_server(port); 18 | printf("tcp server is run (port=%d)\n", port); 19 | tcp_server.SetMessageFactory(make_shared ("", true)); 20 | IoServicePool::singleton::GetInstance()->Run(); 21 | 22 | return EXIT_SUCCESS; 23 | } -------------------------------------------------------------------------------- /examples/udp_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "client_message_factory.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | using namespace happy::asio::ip; 9 | 10 | int main() 11 | { 12 | // 默认创建线程池的大小为4 13 | //IoServicePool::singleton::Create(4); 14 | auto const ip = "127.0.0.1"; 15 | auto const port = 1235; 16 | auto udp_client = make_shared (ip, port); 17 | udp_client->SetMessageFactory(shared_ptr (new ClientMessageFactory)); 18 | thread t([]() { IoServicePool::singleton::GetInstance()->Run(); }); 19 | t.detach(); 20 | while (true) 21 | { 22 | cout << "please input send server string(enter to end): "; 23 | char buffer[1024]; 24 | cin >> buffer; 25 | udp_client->AsyncWrite(ToNetwork(buffer)); 26 | this_thread::sleep_for(chrono::seconds(1)); 27 | } 28 | return EXIT_SUCCESS; 29 | } -------------------------------------------------------------------------------- /examples/udp_client_proto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proto_client_message_factory.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "dmo.pb.h" 8 | #include 9 | #ifdef GLOG_OUTPUT 10 | #include 11 | #endif 12 | using namespace happy::utils::network; 13 | using namespace std; 14 | using namespace happy::asio::ip; 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | // 默认创建线程池的大小为4 19 | //IoServicePool::singleton::Create(4); 20 | #ifdef GLOG_OUTPUT 21 | utils::ConfigGlog(argv[0]); 22 | #endif 23 | 24 | auto const ip = "127.0.0.1"; 25 | auto const port = 1235; 26 | auto udp_client = make_shared (ip, port); 27 | udp_client->SetMessageFactory(dynamic_pointer_cast (make_shared ("", true))); 28 | thread t([]() { IoServicePool::singleton::GetInstance()->Run(); }); 29 | t.detach(); 30 | while (true) 31 | { 32 | cout << "please input send server string(enter to end): "; 33 | char buffer[1024]; 34 | cin >> buffer; 35 | auto request_info = make_shared (); 36 | request_info->set_info(buffer); 37 | string out_buffer; 38 | ProtoNetworkConvert::singleton::GetInstance()->ToNetwork(request_info, out_buffer); 39 | udp_client->AsyncWrite(out_buffer); 40 | this_thread::sleep_for(chrono::seconds(1)); 41 | } 42 | return EXIT_SUCCESS; 43 | } -------------------------------------------------------------------------------- /examples/udp_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "server_message_factory.h" 3 | using namespace happy::asio::ip; 4 | 5 | int main() 6 | { 7 | // 默认创建线程池的大小为4 8 | //IoServicePool::singleton::Create(4); 9 | uint16_t port = 1235; 10 | UdpServer udp_server(port); 11 | printf("udp server is run (port=%d)\n", port); 12 | udp_server.SetMessageFactory(make_shared ()); 13 | IoServicePool::singleton::GetInstance()->Run(); 14 | 15 | return EXIT_SUCCESS; 16 | } -------------------------------------------------------------------------------- /examples/udp_server_proto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "proto_server_message_factory.h" 3 | #ifdef GLOG_OUTPUT 4 | #include 5 | #endif 6 | using namespace happy::asio::ip; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | // 默认创建线程池的大小为4。 11 | //IoServicePool::singleton::Create(4); 12 | #ifdef GLOG_OUTPUT 13 | utils::ConfigGlog(argv[0]); 14 | #endif 15 | uint16_t port = 1235; 16 | UdpServer udp_server(port); 17 | printf("udp server is run (port=%d)\n", port); 18 | udp_server.SetMessageFactory(make_shared ("", true)); 19 | IoServicePool::singleton::GetInstance()->Run(); 20 | 21 | return EXIT_SUCCESS; 22 | } -------------------------------------------------------------------------------- /examples/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct NetworkData 7 | { 8 | uint32_t length; 9 | string content; 10 | }; 11 | 12 | #define CREATE(class_name); \ 13 | private: \ 14 | virtual shared_ptr Create(const string& session_id) override final { return make_shared (session_id); } 15 | #define CREATE_PROTO(class_name); \ 16 | private: \ 17 | virtual shared_ptr Create(const string& session_id) override final { return make_shared (session_id, true); } 18 | 19 | inline string HexToString(const uint8_t* buffer, const size_t length, const string& separator = "") 20 | { 21 | string result; 22 | auto GetChar = [](int value) { 23 | if (value < 10) 24 | { 25 | return value + 48; 26 | } 27 | else 28 | { 29 | return value + 65 - 10; 30 | } 31 | }; 32 | for (size_t i = 0; i < length; i++) 33 | { 34 | if (result.length()) 35 | { 36 | result.append(separator); 37 | } 38 | result.append(1, GetChar(buffer[i] >> 4)); 39 | result.append(1, GetChar(buffer[i] % 16)); 40 | } 41 | return result; 42 | } 43 | 44 | inline string ToNetwork(const string& content) 45 | { 46 | NetworkData network_data; 47 | network_data.content = content; 48 | network_data.length = boost::asio::detail::socket_ops::network_to_host_long(network_data.content.length()); 49 | string response; 50 | response.append(reinterpret_cast (&network_data.length), 4); 51 | response.append(network_data.content); 52 | 53 | return move(response); 54 | } 55 | 56 | inline NetworkData ToHost(const uint8_t* buffer, const size_t length) 57 | { 58 | NetworkData network_data; 59 | network_data.length = boost::asio::detail::socket_ops::network_to_host_long(*reinterpret_cast (buffer)); 60 | network_data.content.append(reinterpret_cast (buffer + 4), network_data.length); 61 | 62 | return network_data; 63 | } 64 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #设置lib输出目录 2 | #SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/build/lib") 3 | 4 | #设置安装库目录 5 | #set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install/lib) 6 | 7 | add_subdirectory(ip) 8 | message (STATUS "build network") 9 | add_subdirectory(network) 10 | -------------------------------------------------------------------------------- /src/ip/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #project(ip) 2 | #依赖包含 3 | include_directories(../ ../../) 4 | 5 | # 遍历主目录源文件 6 | file(GLOB_RECURSE SOURCE_FILES "./*.h" "./*.cpp") 7 | 8 | #编译静态库程序 9 | add_library(ip STATIC ${SOURCE_FILES}) 10 | 11 | #设置安装库目录 12 | install(TARGETS ip ARCHIVE DESTINATION lib) 13 | install(DIRECTORY ./ DESTINATION include/ip FILES_MATCHING PATTERN "*.h") 14 | -------------------------------------------------------------------------------- /src/ip/async_write_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace happy 4 | { 5 | namespace asio 6 | { 7 | namespace ip 8 | { 9 | bool AsyncWriteBuffer::AsyncWrite(shared_ptr in_write_data, shared_ptr & out_write_data) 10 | { 11 | lock_guard lock(mutex_); 12 | if (is_async_write_) 13 | { 14 | list_wirte_data_.push_back(in_write_data); 15 | return false; 16 | } 17 | out_write_data = in_write_data; 18 | is_async_write_ = true; 19 | 20 | return true; 21 | } 22 | 23 | bool AsyncWriteBuffer::HandleWrite(shared_ptr & out_write_data) 24 | { 25 | lock_guard lock(mutex_); 26 | do 27 | { 28 | is_async_write_ = true; 29 | if (!list_wirte_data_.size()) 30 | { 31 | is_async_write_ = false; 32 | break; 33 | } 34 | out_write_data = list_wirte_data_.front(); 35 | list_wirte_data_.pop_front(); 36 | } while (false); 37 | 38 | return is_async_write_; 39 | } 40 | 41 | void AsyncWriteBuffer::Clear() 42 | { 43 | lock_guard lock(mutex_); 44 | list_wirte_data_.clear(); 45 | is_async_write_ = false; 46 | } 47 | 48 | void AsyncWriteBuffer::HandleWriteFailed(shared_ptr in_write_data) 49 | { 50 | lock_guard lock(mutex_); 51 | list_wirte_data_.push_front(in_write_data); 52 | is_async_write_ = false; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ip/async_write_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | namespace happy 9 | { 10 | namespace asio 11 | { 12 | namespace ip 13 | { 14 | struct WriteData 15 | { 16 | WriteData(const string& in_data, const string& in_tag) : data(in_data), tag(in_tag) {} 17 | string data; 18 | string tag; 19 | }; 20 | 21 | class AsyncWriteBuffer 22 | { 23 | public: 24 | bool AsyncWrite(shared_ptr in_write_data, shared_ptr & out_write_data); 25 | bool HandleWrite(shared_ptr & out_write_data); 26 | void Clear(); 27 | void HandleWriteFailed(shared_ptr in_write_data); 28 | unsigned GetWriteBufferSize() 29 | { 30 | lock_guard lock(mutex_); 31 | return list_wirte_data_.size(); 32 | } 33 | private: 34 | bool is_async_write_ = false; 35 | list > list_wirte_data_; 36 | mutex mutex_; 37 | }; 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/ip/client/tcp_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std::chrono; 4 | 5 | namespace happy 6 | { 7 | namespace asio 8 | { 9 | namespace ip 10 | { 11 | TcpClient::TcpClient(const bool auto_reconnect, const int session_timeout) 12 | : TcpSession(false, session_timeout) , timer_reconnect_(timer_.get_io_service()) 13 | { 14 | reconnect_ = auto_reconnect; 15 | if (auto_reconnect) 16 | { 17 | SetCloseHandler([&](const string&) 18 | { 19 | if (reconnect_) 20 | { 21 | DeliverConnect(); 22 | } 23 | }); 24 | } 25 | } 26 | 27 | void TcpClient::AsyncConnect(const string& ip_addr, const int port) 28 | { 29 | endpoint_ = tcp::endpoint(address::from_string(ip_addr.c_str()), port); 30 | DeliverConnect(0); 31 | } 32 | 33 | void TcpClient::DeliverConnect(const int seconds) 34 | { 35 | timer_reconnect_.expires_from_now(boost::posix_time::seconds(seconds)); 36 | timer_reconnect_.async_wait(std::bind(&TcpClient::AsyncConnectHandler, this, _1)); 37 | } 38 | 39 | void TcpClient::AsyncConnectHandler(const boost::system::error_code&) 40 | { 41 | socket_.async_connect(endpoint_, bind(&TcpClient::HandleConnect, this, _1)); 42 | } 43 | 44 | void TcpClient::HandleConnect(const boost::system::error_code& ec) 45 | { 46 | if (!ec) 47 | { 48 | Start(); 49 | } 50 | else if (ec != boost::asio::error::already_connected) 51 | { 52 | DeliverConnect(); 53 | } 54 | } 55 | 56 | bool TcpClient::Connect(const string& ip_addr, const int port, const int waiting_seconds) 57 | { 58 | endpoint_ = tcp::endpoint(address::from_string(ip_addr.c_str()), port); 59 | 60 | return Reconnect(waiting_seconds); 61 | } 62 | 63 | void TcpClient::Disconnect() 64 | { 65 | reconnect_ = false; 66 | timer_reconnect_.cancel(); 67 | Close(CLOSED_BY_REMOTE); 68 | } 69 | 70 | bool TcpClient::Reconnect(const int waiting_seconds) 71 | { 72 | if (!endpoint_.port()) 73 | { 74 | return false; 75 | } 76 | 77 | auto start_time = system_clock::now(); 78 | boost::system::error_code error = boost::asio::error::host_not_found; 79 | duration elapsed_seconds; 80 | while (1) 81 | { 82 | // Has error is true 83 | if (socket_.connect(endpoint_, error)) 84 | { 85 | elapsed_seconds = system_clock::now() - start_time; 86 | if (elapsed_seconds.count() > waiting_seconds) 87 | { 88 | return false; 89 | } 90 | continue; 91 | } 92 | else 93 | { 94 | break; 95 | } 96 | } 97 | Start(); 98 | 99 | return true; 100 | } 101 | 102 | void TcpClient::Close(const ClosedType closed_type) 103 | { 104 | boost::system::error_code ec; 105 | socket_.cancel(ec); 106 | socket_.close(ec); 107 | Session::Close(closed_type); 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/ip/client/tcp_client.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangziwen333/happy-ip/f8a1ae787f85c0131c4c8e9c782d64eadd1b09f7/src/ip/client/tcp_client.h -------------------------------------------------------------------------------- /src/ip/client/udp_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | //using namespace std::chrono; 4 | 5 | namespace happy 6 | { 7 | namespace asio 8 | { 9 | namespace ip 10 | { 11 | UdpClient::UdpClient(const string& ip_addr, const int port, const int session_timeout) 12 | : socket_(timer_.get_io_service()), UdpSession(socket_, session_timeout) 13 | { 14 | remote_endpoint_ = udp::endpoint(address::from_string(ip_addr.c_str()), 1235); 15 | socket_.open(udp::v4()); 16 | DeliverReceive(); 17 | } 18 | 19 | void UdpClient::DeliverReceive() 20 | { 21 | socket_.async_receive_from(buffer(buffer_), remote_endpoint_, bind(&UdpClient::HandleReceive, this, _1, _2)); 22 | } 23 | 24 | void UdpClient::HandleReceive(const boost::system::error_code& error, const size_t bytes_recvd) 25 | { 26 | if (!error) 27 | { 28 | HandleRead(buffer_.data(), bytes_recvd); 29 | } 30 | DeliverReceive(); 31 | } 32 | 33 | //TcpClient::TcpClient(const bool& auto_reconnect, const int& session_timeout) 34 | // : TcpSession(false, session_timeout) , timer_reconnect_(timer_.get_io_service()) 35 | //{ 36 | // reconnect_ = auto_reconnect; 37 | // if (auto_reconnect) 38 | // { 39 | // SetCloseHandler([&](const string&) 40 | // { 41 | // if (reconnect_) 42 | // { 43 | // DeliverConnect(); 44 | // } 45 | // }); 46 | // } 47 | //} 48 | 49 | //void TcpClient::AsyncConnect(const string& ip_addr, const int& port) 50 | //{ 51 | // endpoint_ = tcp::endpoint(address::from_string(ip_addr.c_str()), port); 52 | // DeliverConnect(0); 53 | //} 54 | 55 | //void TcpClient::DeliverConnect(const int seconds) 56 | //{ 57 | // timer_reconnect_.expires_from_now(boost::posix_time::seconds(seconds)); 58 | // timer_reconnect_.async_wait(std::bind(&TcpClient::AsyncConnectHandler, this, _1)); 59 | //} 60 | 61 | //void TcpClient::AsyncConnectHandler(const boost::system::error_code&) 62 | //{ 63 | // socket_.async_connect(endpoint_, bind(&TcpClient::HandleConnect, this, _1)); 64 | //} 65 | 66 | //void TcpClient::HandleConnect(const boost::system::error_code& ec) 67 | //{ 68 | // if (!ec) 69 | // { 70 | // Start(); 71 | // } 72 | // else if (ec != boost::asio::error::already_connected) 73 | // { 74 | // DeliverConnect(); 75 | // } 76 | //} 77 | 78 | //bool TcpClient::Connect(const string& ip_addr, const int& port, const int& waiting_seconds) 79 | //{ 80 | // endpoint_ = tcp::endpoint(address::from_string(ip_addr.c_str()), port); 81 | 82 | // return Reconnect(waiting_seconds); 83 | //} 84 | 85 | //void TcpClient::Disconnect() 86 | //{ 87 | // reconnect_ = false; 88 | // timer_reconnect_.cancel(); 89 | // Close(CLOSED_BY_REMOTE); 90 | //} 91 | 92 | //bool TcpClient::Reconnect(const int& waiting_seconds) 93 | //{ 94 | // if (!endpoint_.port()) 95 | // { 96 | // return false; 97 | // } 98 | 99 | // auto start_time = system_clock::now(); 100 | // boost::system::error_code error = boost::asio::error::host_not_found; 101 | // duration elapsed_seconds; 102 | // while (1) 103 | // { 104 | // // Has error is true 105 | // if (socket_.connect(endpoint_, error)) 106 | // { 107 | // elapsed_seconds = system_clock::now() - start_time; 108 | // if (elapsed_seconds.count() > waiting_seconds) 109 | // { 110 | // return false; 111 | // } 112 | // continue; 113 | // } 114 | // else 115 | // { 116 | // break; 117 | // } 118 | // } 119 | // Start(); 120 | 121 | // return true; 122 | //} 123 | 124 | //void TcpClient::Close(const ClosedType closed_type) 125 | //{ 126 | // boost::system::error_code ec; 127 | // socket_.cancel(ec); 128 | // socket_.close(ec); 129 | // Session::Close(closed_type); 130 | //} 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/ip/client/udp_client.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangziwen333/happy-ip/f8a1ae787f85c0131c4c8e9c782d64eadd1b09f7/src/ip/client/udp_client.h -------------------------------------------------------------------------------- /src/ip/io_service_pool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | using namespace boost::asio; 8 | 9 | namespace happy 10 | { 11 | namespace asio 12 | { 13 | namespace ip 14 | { 15 | 16 | void IoServicePool::Run() 17 | { 18 | // Create a pool of threads to run all of the io_services. 19 | std::vector> threads; 20 | for (std::size_t i = 0; i < io_services_.size(); ++i) 21 | { 22 | boost::shared_ptr thread(new boost::thread(bind(static_cast(&io_service::run), io_services_[i]))); 23 | threads.push_back(thread); 24 | } 25 | 26 | // Wait for all threads in the pool to exit. 27 | for (auto& thread : threads) 28 | thread->join(); 29 | } 30 | 31 | void IoServicePool::Stop() 32 | { 33 | // Explicitly stop all io_services. 34 | for (auto& io_service : io_services_) 35 | io_service->stop(); 36 | } 37 | 38 | io_service& IoServicePool::GetNextIoService_() 39 | { 40 | std::lock_guard lock(mutex_); 41 | // Use a round-robin scheme to choose the next io_service to use. 42 | io_service& io_service = *io_services_[next_io_service_]; 43 | next_io_service_ = (next_io_service_ + 1) % io_services_.size(); 44 | 45 | return io_service; 46 | } 47 | 48 | IoServicePool::IoServicePool(const size_t pool_size) 49 | { 50 | for (std::size_t i = 0; i < pool_size; ++i) 51 | { 52 | io_service_ptr service(new io_service); 53 | work_ptr work(new io_service::work(*service)); 54 | io_services_.push_back(service); 55 | work_.push_back(work); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ip/io_service_pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace happy 9 | { 10 | namespace asio 11 | { 12 | namespace ip 13 | { 14 | 15 | class IoServicePool 16 | { 17 | DEFINE_SINGLETON_CONSTRUCT_WITH_DEFAULT(IoServicePool); 18 | public: 19 | /// Construct the io_service pool. 20 | IoServicePool(const size_t pool_size = 4); 21 | 22 | /// Run all io_service objects in the pool. 23 | void Run(); 24 | 25 | /// Stop all io_service objects in the pool. 26 | void Stop(); 27 | 28 | /// Get an io_service to use. 29 | boost::asio::io_service& GetNextIoService_(); 30 | 31 | private: 32 | typedef boost::shared_ptr io_service_ptr; 33 | typedef boost::shared_ptr work_ptr; 34 | 35 | /// The pool of io_services. 36 | std::vector io_services_; 37 | 38 | /// The work that keeps the io_services running. 39 | std::vector work_; 40 | 41 | /// The next io_service to use for a connection. 42 | std::size_t next_io_service_ = 0; 43 | 44 | std::mutex mutex_; 45 | }; 46 | 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/ip/message_factory.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangziwen333/happy-ip/f8a1ae787f85c0131c4c8e9c782d64eadd1b09f7/src/ip/message_factory.h -------------------------------------------------------------------------------- /src/ip/server/server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace happy 7 | { 8 | namespace asio 9 | { 10 | namespace ip 11 | { 12 | #define CLOSE_HANDLE [&](const string& session_id){ DeleteSession(session_id); } 13 | class server 14 | { 15 | public: 16 | server(const int session_timeout) 17 | : session_timeout_(session_timeout) 18 | {} 19 | 20 | void SetMessageFactory(shared_ptr message_factory) 21 | { 22 | message_factory_ = message_factory; 23 | } 24 | 25 | void PublishAll(const string& buffer) 26 | { 27 | if (buffer.length()) 28 | { 29 | sessions_.ForEach([&](const string& session_id, const shared_ptr& session) 30 | { 31 | session->AsyncWrite(buffer); 32 | }); 33 | } 34 | } 35 | 36 | void PublishOne(const string& session_id, const string& buffer,const string &tag="") 37 | { 38 | if (buffer.length()) 39 | { 40 | sessions_.ForOne(session_id, [&](const string& session_id, const shared_ptr& session) 41 | { 42 | session->AsyncWrite(buffer,tag); 43 | }); 44 | } 45 | } 46 | 47 | /*void AllSend(const function& session)>& _Func) 48 | { 49 | sessions_.ForEach([&](const string& session_id, const shared_ptr& session) 50 | { 51 | auto temp = _Func(session_id, session); 52 | 53 | if (!temp.empty()) 54 | { 55 | session->AsyncWrite(temp); 56 | } 57 | }); 58 | } 59 | 60 | void AllHandle(const function& session)>& _Func) 61 | { 62 | sessions_.ForEach([&](const string& session_id, const shared_ptr& session) 63 | { 64 | _Func(session_id, session); 65 | }); 66 | }*/ 67 | 68 | protected: 69 | virtual shared_ptr GetMessageFactory(const string& session_id) 70 | { 71 | return message_factory_->Create(session_id); 72 | } 73 | 74 | // true: is update 75 | bool UpsertSession(const string& session_id, const shared_ptr& session_in, shared_ptr* session_out = nullptr) 76 | { 77 | return sessions_.Upsert(session_id, session_in, session_out); 78 | } 79 | 80 | shared_ptr FindSession(const string& session_id) 81 | { 82 | shared_ptr value; 83 | bool b = sessions_.GetValue(session_id, value); 84 | if (b) 85 | return value; 86 | else 87 | return nullptr; 88 | } 89 | 90 | virtual void DeleteSession(const string& session_id) 91 | { 92 | sessions_.Erase(session_id); 93 | } 94 | 95 | const int session_timeout_; 96 | private: 97 | UnorderedMapSafe > sessions_; 98 | shared_ptr message_factory_{ new happy::asio::ip::MessageFactory }; 99 | }; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /src/ip/server/session.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace happy 4 | { 5 | namespace asio 6 | { 7 | namespace ip 8 | { 9 | void Session::SetMessageFactory(shared_ptr message_factory) 10 | { 11 | message_factory_ = message_factory; 12 | } 13 | 14 | void Session::SetCloseHandler(const function & handler) 15 | { 16 | close_handler_ = handler; 17 | } 18 | 19 | void Session::SetMessageFactoryRead(const function & handler) 20 | { 21 | message_factor_read_ = handler; 22 | } 23 | 24 | void Session::CancelTimer() 25 | { 26 | timer_.cancel(); 27 | } 28 | 29 | string Session::GetSessionId() 30 | { 31 | return ""; 32 | } 33 | 34 | void Session::HandleCreate() 35 | { 36 | string response; 37 | message_factory_->HandleCreate(response); 38 | if (response.length()) 39 | { 40 | AsyncWrite(response); 41 | } 42 | } 43 | 44 | void Session::MessageFactoryRead(const string str_buffer) 45 | { 46 | string response; 47 | if (message_factory_->HandleRead(reinterpret_cast (str_buffer.data()), str_buffer.length(), response)) 48 | { 49 | ResetTimer(); 50 | if (response.length()) 51 | { 52 | AsyncWrite(response); 53 | } 54 | } 55 | } 56 | 57 | void Session::HandleRead(const uint8_t* in_buffer, const size_t& in_buffer_length) 58 | { 59 | size_t total_deal_length = 0; 60 | const uint8_t* buffer = in_buffer; 61 | size_t buffer_length = in_buffer_length; 62 | is_handle_read_ = true; 63 | // continue package 64 | if (receive_buffer_.length()) 65 | { 66 | receive_buffer_.append(reinterpret_cast (const_cast (in_buffer)), in_buffer_length); 67 | buffer = reinterpret_cast (const_cast (receive_buffer_.data())); 68 | buffer_length = receive_buffer_.length(); 69 | } 70 | while (total_deal_length < buffer_length) 71 | { 72 | size_t deal_length = 0; 73 | bool has_package = false; 74 | string response; 75 | if (message_factory_->IsConsumedForRead(buffer + total_deal_length, buffer_length - total_deal_length, deal_length, has_package)) 76 | { 77 | string str_buffer; 78 | str_buffer.append(reinterpret_cast (buffer + total_deal_length), deal_length); 79 | message_factor_read_(str_buffer); 80 | total_deal_length += deal_length; 81 | } 82 | else if (has_package) 83 | { 84 | receive_buffer_.assign(reinterpret_cast (const_cast (buffer)) + total_deal_length, buffer_length - total_deal_length); 85 | 86 | break; 87 | } 88 | else 89 | { 90 | total_deal_length += deal_length; 91 | } 92 | // ���û�к�����������ij�����Ϊ�㣬��ʾҵ���������⣬��ʱ����ȫ�����ݴ��� 93 | if (deal_length <= 0 && !has_package) 94 | { 95 | break; 96 | } 97 | } 98 | if (total_deal_length == buffer_length) 99 | { 100 | receive_buffer_.clear(); 101 | } 102 | is_handle_read_ = false; 103 | } 104 | 105 | void Session::Close(const ClosedType closed_type) 106 | { 107 | boost::system::error_code ec; 108 | timer_.cancel(ec); 109 | message_factory_->HandleClose(closed_type); 110 | close_handler_(GetSessionId()); 111 | async_write_buffer_.Clear(); 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /src/ip/server/session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using utils::ThreadPool; 10 | using namespace std; 11 | using namespace boost::asio; 12 | using namespace std::placeholders; 13 | 14 | namespace happy 15 | { 16 | namespace asio 17 | { 18 | namespace ip 19 | { 20 | class Session 21 | { 22 | public: 23 | void SetMessageFactory(shared_ptr message_factory); 24 | void SetCloseHandler(const function & handler); 25 | void SetMessageFactoryRead(const function & handler); 26 | virtual void AsyncWrite(const string& buffer, const string& tag = "") = 0; 27 | void CancelTimer(); 28 | Session(const int session_timeout) 29 | : session_timeout_(session_timeout) {} 30 | void MessageFactoryRead(const string str_buffer); 31 | protected: 32 | virtual void ResetTimer() = 0; 33 | virtual string GetSessionId(); 34 | void HandleCreate(); 35 | void HandleRead(const uint8_t* in_buffer, const size_t& in_buffer_length); 36 | void Close(const ClosedType closed_type); 37 | protected: 38 | shared_ptr message_factory_; 39 | function close_handler_ { [&](const string&){} }; 40 | AsyncWriteBuffer async_write_buffer_; 41 | deadline_timer timer_{ IoServicePool::singleton::GetInstance()->GetNextIoService_() }; 42 | string receive_buffer_; 43 | const int session_timeout_; // unit: seconds 44 | bool is_handle_read_; 45 | private: 46 | function message_factor_read_ = bind([this](const string str_buffer) { MessageFactoryRead(str_buffer); }, _1); 47 | }; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/ip/server/tcp_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace happy 5 | { 6 | namespace asio 7 | { 8 | namespace ip 9 | { 10 | TcpServer::TcpServer(const uint16_t& port, const std::string &ip, const bool& is_closed_delay, const int& session_timeout, const bool& is_start_delay, const int read_work_threads) 11 | : server(session_timeout), is_closed_delay_(is_closed_delay), is_start_delay_(is_start_delay) 12 | , acceptor_(IoServicePool::singleton::GetInstance()->GetNextIoService_(), tcp::endpoint(address::from_string(ip.c_str()), port)) 13 | { 14 | if (read_work_threads) 15 | { 16 | read_thread_pool_ = make_shared (read_work_threads); 17 | } 18 | if (!is_start_delay) 19 | StartAccept(); 20 | } 21 | 22 | void TcpServer::Run() 23 | { 24 | if (is_start_delay_) 25 | StartAccept(); 26 | } 27 | 28 | void TcpServer::StartAccept() 29 | { 30 | shared_ptr new_session(new TcpSession(is_closed_delay_, session_timeout_)); 31 | acceptor_.async_accept(new_session->GetSocket_(), bind(&TcpServer::HandleAccept, this, new_session, _1)); 32 | } 33 | 34 | void TcpServer::HandleAccept(const shared_ptr session, const boost::system::error_code& ec) 35 | { 36 | if (!ec) 37 | { 38 | UpsertSession(session->GetSessionId(), session); 39 | auto message_factory = GetMessageFactory(session->GetSessionId()); 40 | session->SetMessageFactory(message_factory); 41 | session->SetCloseHandler(CLOSE_HANDLE); 42 | if (read_thread_pool_ != nullptr) 43 | { 44 | session->SetMessageFactoryRead(bind([](const shared_ptr session, shared_ptr read_thread_pool, const string str_buffer) { 45 | read_thread_pool->enqueue(&TcpSession::MessageFactoryRead, session->shared_from_this(), str_buffer); 46 | }, session, read_thread_pool_, _1)); 47 | } 48 | session->Start(); 49 | } 50 | StartAccept(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ip/server/tcp_server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using utils::ThreadPool; 9 | 10 | namespace happy 11 | { 12 | namespace asio 13 | { 14 | namespace ip 15 | { 16 | class TcpServer : public server 17 | { 18 | public: 19 | /*-------------------------------------------------------- 20 | 参数 21 | port:绑定的端口 22 | ip:绑定的ip地址 23 | is_closed_delay:是否关闭延迟(如果设置此参数,只有session_timeout到期时,业务层才会收到close事件) 24 | session_timeout:会话超时时间(每个包之间的最长间隔时间,超时会自动关闭会话) 25 | is_start_delay:启动延迟(如果设置此参数,要手动运行run函数,服务器才会启动) 26 | read_work_threads:投递读事件线程池大小(设置此参数后,底层会自动将收到的数据投递到线程池中处理,防止业务处理阻塞读事件) 27 | --------------------------------------------------------*/ 28 | TcpServer(const uint16_t& port, const std::string &ip = "0.0.0.0", const bool& is_closed_delay = false 29 | , const int& session_timeout = 0, const bool& is_start_delay = false, const int read_work_threads = 0); 30 | void Run(); 31 | private: 32 | const bool is_closed_delay_; 33 | const bool is_start_delay_; 34 | shared_ptr read_thread_pool_ = nullptr; 35 | protected: 36 | tcp::acceptor acceptor_; 37 | 38 | virtual void StartAccept(); 39 | virtual void HandleAccept(const shared_ptr session, const boost::system::error_code& ec); 40 | }; 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/ip/server/tcp_session.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace happy 5 | { 6 | namespace asio 7 | { 8 | namespace ip 9 | { 10 | TcpSession::TcpSession(const bool is_closed_delay, const int session_timeout) 11 | : Session(session_timeout), is_closed_delay_(is_closed_delay), socket_(timer_.get_io_service()) {} 12 | 13 | void TcpSession::Start() 14 | { 15 | if (!message_factory_) 16 | { 17 | message_factory_ = make_shared (); 18 | } 19 | ResetTimer(); 20 | HandleCreate(); 21 | DeliverRead(); 22 | GetSessionId(); 23 | } 24 | 25 | void TcpSession::DeliverRead() 26 | { 27 | socket_.async_read_some(buffer(buffer_), bind(&TcpSession::HandleRead, shared_from_this(), _1, _2)); 28 | } 29 | 30 | void TcpSession::HandleRead(const boost::system::error_code& ec, const size_t bytes_recvd) 31 | { 32 | if (!ec) 33 | { 34 | Session::HandleRead(buffer_.data(), bytes_recvd); 35 | DeliverRead(); 36 | } 37 | else if (false == is_closed_delay_ && boost::asio::error::operation_aborted != ec) 38 | { 39 | Close(CLOSED_BY_REMOTE); 40 | } 41 | } 42 | 43 | void TcpSession::AsyncWrite(const string& packet, const string& tag) 44 | { 45 | shared_ptr write_data; 46 | if (async_write_buffer_.AsyncWrite(make_shared (packet, tag), write_data)) 47 | { 48 | async_write(socket_, buffer(write_data->data), bind(&TcpSession::HandleWrite, shared_from_this(), _1, _2, write_data)); 49 | } 50 | } 51 | 52 | void TcpSession::HandleWrite(const boost::system::error_code& ec, const size_t, shared_ptr in_write_data) 53 | { 54 | if (!ec) 55 | { 56 | message_factory_->HandleWrite(in_write_data->tag); 57 | shared_ptr write_data; 58 | if (async_write_buffer_.HandleWrite(write_data)) 59 | { 60 | async_write(socket_, buffer(write_data->data), bind(&TcpSession::HandleWrite, shared_from_this(), _1, _2, write_data)); 61 | } 62 | if (!is_handle_read_) 63 | { 64 | ResetTimer(); 65 | } 66 | } 67 | else 68 | { 69 | async_write_buffer_.HandleWriteFailed(in_write_data); 70 | } 71 | } 72 | 73 | tcp::socket& TcpSession::GetSocket_() 74 | { 75 | return socket_; 76 | } 77 | 78 | string TcpSession::GetSessionId() 79 | { 80 | if (!session_id_.length()) 81 | { 82 | boost::system::error_code ec, ec1; 83 | auto remote_endpoint = socket_.remote_endpoint(ec); 84 | auto local_endpoint = socket_.local_endpoint(ec1); 85 | if (!ec && !ec1) 86 | { 87 | session_id_ = local_endpoint.address().to_string() + ":" + to_string(local_endpoint.port()) + "_" 88 | + remote_endpoint.address().to_string() + ":" + to_string(remote_endpoint.port()); 89 | } 90 | } 91 | return session_id_; 92 | } 93 | 94 | void TcpSession::ResetTimer() 95 | { 96 | if (session_timeout_) 97 | { 98 | timer_.cancel(); 99 | timer_.expires_from_now(boost::posix_time::seconds(session_timeout_)); 100 | timer_.async_wait(std::bind(&TcpSession::HandleSessionTimeout, shared_from_this(), _1)); 101 | } 102 | } 103 | 104 | void TcpSession::HandleSessionTimeout(const boost::system::error_code& ec) 105 | { 106 | if (boost::asio::error::operation_aborted != ec) 107 | { 108 | Close(CLOSED_BY_TIMEOUT); 109 | } 110 | } 111 | 112 | void TcpSession::SyncWrite(const string& packet) 113 | { 114 | write(socket_, buffer(packet.data(), packet.length())); 115 | } 116 | 117 | void TcpSession::Close(const ClosedType closed_type) 118 | { 119 | Session::Close(closed_type); 120 | boost::system::error_code ec; 121 | socket_.cancel(ec); 122 | socket_.close(ec); 123 | } 124 | } 125 | } 126 | } 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/ip/server/tcp_session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace happy 9 | { 10 | namespace asio 11 | { 12 | namespace ip 13 | { 14 | using namespace boost::asio; 15 | using namespace std::placeholders; 16 | using namespace std; 17 | using namespace boost::asio::ip; 18 | 19 | class TcpSession : public enable_shared_from_this, public Session 20 | { 21 | public: 22 | TcpSession(const bool is_closed_delay = false, const int session_timeout = 60); 23 | void Start(); 24 | virtual void AsyncWrite(const string& packet, const string& tag = "") override final; 25 | void SyncWrite(const string& packet); 26 | tcp::socket& GetSocket_(); 27 | virtual string GetSessionId() override final; 28 | protected: 29 | const bool is_closed_delay_; 30 | tcp::socket socket_; 31 | array buffer_; 32 | string session_id_ = ""; 33 | protected: 34 | // Release server resource 35 | void DeliverRead(); 36 | void HandleRead(const boost::system::error_code& ec, const size_t bytes_recvd); 37 | void HandleWrite(const boost::system::error_code& ec, const size_t, shared_ptr in_write_data); 38 | virtual void ResetTimer() override final; 39 | void HandleSessionTimeout(const boost::system::error_code& ec); 40 | virtual void Close(const ClosedType closed_type); 41 | }; 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/ip/server/udp_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace boost::asio; 4 | 5 | namespace happy 6 | { 7 | namespace asio 8 | { 9 | namespace ip 10 | { 11 | UdpServer::UdpServer(const uint16_t& port, const std::string &ip, const int& session_timeout) 12 | : server(session_timeout) 13 | , socket_(IoServicePool::singleton::GetInstance()->GetNextIoService_(), udp::endpoint(address::from_string(ip.c_str()), port)) 14 | { 15 | DeliverReceive(); 16 | } 17 | 18 | void UdpServer::DeliverReceive() 19 | { 20 | shared_ptr udp_session(new UdpSession(socket_, session_timeout_)); 21 | socket_.async_receive_from(buffer(buffer_), udp_session->GetRemoteEndpoint_(), bind(&UdpServer::HandleReceive, this, _1, _2, udp_session)); 22 | } 23 | 24 | void UdpServer::HandleReceive(const boost::system::error_code& error, const size_t bytes_recvd, shared_ptr udp_session) 25 | { 26 | string response; 27 | if (!error) 28 | { 29 | auto session = server::FindSession(udp_session->GetSessionId()); 30 | if (nullptr == session) 31 | { 32 | server::UpsertSession(udp_session->GetSessionId(), udp_session); 33 | auto message_factory = GetMessageFactory(udp_session->GetSessionId()); 34 | udp_session->SetMessageFactory(message_factory); 35 | udp_session->SetCloseHandler(CLOSE_HANDLE); 36 | session = udp_session; 37 | } 38 | dynamic_cast (session.get())->HandleRead(buffer_.data(), bytes_recvd); 39 | } 40 | DeliverReceive(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ip/server/udp_server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace boost::asio::ip; 7 | 8 | namespace happy 9 | { 10 | namespace asio 11 | { 12 | namespace ip 13 | { 14 | class UdpServer : public server 15 | { 16 | public: 17 | UdpServer(const uint16_t& port, const std::string &ip = "0.0.0.0", const int& session_timeout = 0); 18 | 19 | private: 20 | // Receive socket 21 | udp::socket socket_; 22 | //shared_ptr socket_; 23 | // Receive buffer 24 | array buffer_; 25 | // Deliver receive message to boost io 26 | void DeliverReceive(); 27 | // Receive handle 28 | void HandleReceive(const boost::system::error_code& error, const size_t bytes_recvd, shared_ptr udp_session); 29 | }; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ip/server/udp_session.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace happy 5 | { 6 | namespace asio 7 | { 8 | namespace ip 9 | { 10 | UdpSession::UdpSession(udp::socket& server_socket, const int session_timeout) 11 | : Session(session_timeout),server_socket_(server_socket) 12 | { 13 | } 14 | 15 | void UdpSession::AsyncWrite(const string& buffer, const string& tag) 16 | { 17 | if (buffer.length()) 18 | { 19 | server_socket_.async_send_to(boost::asio::buffer(buffer.c_str(), buffer.length()), remote_endpoint_ 20 | , bind(&UdpSession::HandleWrite, shared_from_this(), _1, _2)); 21 | } 22 | } 23 | 24 | void UdpSession::HandleWrite(const boost::system::error_code& error, const size_t bytes_sent) 25 | { 26 | if (error) 27 | { 28 | return; 29 | } 30 | } 31 | 32 | udp::endpoint& UdpSession::GetRemoteEndpoint_() 33 | { 34 | return remote_endpoint_; 35 | } 36 | 37 | void UdpSession::HandleRead(const uint8_t* buffer, const size_t length) 38 | { 39 | ResetTimer(); 40 | Session::HandleRead(buffer, length); 41 | } 42 | 43 | string UdpSession::GetSessionId() 44 | { 45 | return remote_endpoint_.address().to_string() + ":" + std::to_string(remote_endpoint_.port()); 46 | } 47 | 48 | void UdpSession::ResetTimer() 49 | { 50 | timer_.cancel(); 51 | timer_.expires_from_now(boost::posix_time::seconds(session_timeout_)); 52 | timer_.async_wait(std::bind(&UdpSession::HandleSessionTimeout, shared_from_this(), _1)); 53 | } 54 | 55 | void UdpSession::HandleSessionTimeout(const boost::system::error_code& ec) 56 | { 57 | if (boost::asio::error::operation_aborted != ec) 58 | { 59 | close_handler_(GetSessionId()); 60 | message_factory_->HandleClose(CLOSED_BY_TIMEOUT); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/ip/server/udp_session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace happy 6 | { 7 | namespace asio 8 | { 9 | namespace ip 10 | { 11 | using namespace boost::asio::ip; 12 | using namespace std::placeholders; 13 | using namespace boost::asio; 14 | using namespace std; 15 | 16 | class UdpSession : public enable_shared_from_this, public Session 17 | { 18 | public: 19 | UdpSession(udp::socket& server_socket, const int session_timeout = 60); 20 | virtual void AsyncWrite(const string& buffer, const string& tag = "") override final; 21 | void HandleRead(const uint8_t* buffer, const size_t length); 22 | udp::endpoint& GetRemoteEndpoint_(); 23 | virtual string GetSessionId() override final; 24 | private: 25 | udp::socket& server_socket_; 26 | protected: 27 | udp::endpoint remote_endpoint_; 28 | private: 29 | void HandleWrite(const boost::system::error_code& error, const size_t bytes_sent); 30 | virtual void ResetTimer() override final; 31 | void HandleSessionTimeout(const boost::system::error_code& ec); 32 | }; 33 | 34 | } 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/ip/server/unordered_map_safe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | namespace happy 8 | { 9 | namespace asio 10 | { 11 | namespace ip 12 | { 13 | template 14 | class UnorderedMapSafe 15 | { 16 | public: 17 | bool Upsert(const TKey& key, const TValue& value_in, TValue *value_out = nullptr) 18 | { 19 | lock_guard lock(mutex_); 20 | bool is_update = false; 21 | auto it = unordered_map_.find(key); 22 | if (it == unordered_map_.end()) 23 | { 24 | unordered_map_[key] = value_in; 25 | } 26 | else 27 | { 28 | is_update = true; 29 | if (value_out != nullptr) 30 | { 31 | *value_out = it->second; 32 | } 33 | it->second = value_in; 34 | } 35 | return is_update; 36 | } 37 | 38 | void Erase(const TKey& key) 39 | { 40 | lock_guard lock(mutex_); 41 | unordered_map_.erase(key); 42 | } 43 | 44 | bool EraseByKeyAndValue(const TKey& key, const TValue& value) 45 | { 46 | lock_guard lock(mutex_); 47 | auto it = unordered_map_.find(key); 48 | if (it != unordered_map_.end() && value == it->second) 49 | { 50 | unordered_map_.erase(it); 51 | 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | void EraseByValue(const TValue& value) 58 | { 59 | lock_guard lock(mutex_); 60 | list values_erase; 61 | for (auto pair : unordered_map_) 62 | { 63 | if (value == pair.second) 64 | { 65 | values_erase.push_back(pair.first); 66 | } 67 | } 68 | for (auto value_erase : values_erase) 69 | { 70 | unordered_map_.erase(value_erase); 71 | } 72 | } 73 | 74 | bool Erase(const TKey& key, TValue& value) 75 | { 76 | lock_guard lock(mutex_); 77 | auto it = unordered_map_.find(key); 78 | if (unordered_map_.end() == it) 79 | { 80 | return false; 81 | } 82 | value = it->second; 83 | unordered_map_.erase(it); 84 | 85 | return true; 86 | } 87 | 88 | void ForEach(const function& _Func) 89 | { 90 | lock_guard lock(mutex_); 91 | for (auto pair : unordered_map_) 92 | { 93 | _Func(pair.first, pair.second); 94 | } 95 | }; 96 | 97 | bool ForOne(const TKey& key, const function& _Func) 98 | { 99 | lock_guard lock(mutex_); 100 | auto it = unordered_map_.find(key); 101 | if (unordered_map_.end() == it) 102 | { 103 | return false; 104 | } 105 | _Func(it->first, it->second); 106 | 107 | return true; 108 | } 109 | 110 | bool ForOneAndDelete(const TKey& key, const function& _Func) 111 | { 112 | lock_guard lock(mutex_); 113 | auto it = unordered_map_.find(key); 114 | if (unordered_map_.end() == it) 115 | { 116 | return false; 117 | } 118 | bool is_delete = false; 119 | _Func(it->second, is_delete); 120 | if (is_delete) 121 | { 122 | unordered_map_.erase(it); 123 | } 124 | return true; 125 | } 126 | 127 | bool GetValue(const TKey& key, TValue& value) 128 | { 129 | lock_guard lock(mutex_); 130 | auto it = unordered_map_.find(key); 131 | if (unordered_map_.end() == it) 132 | { 133 | return false; 134 | } 135 | value = it->second; 136 | 137 | return true; 138 | } 139 | 140 | bool IsExists(const TKey& key) 141 | { 142 | lock_guard lock(mutex_); 143 | auto it = unordered_map_.find(key); 144 | if (unordered_map_.end() == it) 145 | { 146 | return false; 147 | } 148 | return true; 149 | } 150 | 151 | void Clear() 152 | { 153 | lock_guard lock(mutex_); 154 | unordered_map_.clear(); 155 | } 156 | 157 | int Size() 158 | { 159 | lock_guard lock(mutex_); 160 | return unordered_map_.size(); 161 | } 162 | void ForEachErase(const function& _Func) 163 | { 164 | lock_guard lock(mutex_); 165 | for (auto iter = unordered_map_.begin(); iter != unordered_map_.end();) 166 | { 167 | if (_Func(iter->second))unordered_map_.erase(iter++); 168 | else iter++; 169 | } 170 | } 171 | void ForEachChange(const function& _Func) 172 | { 173 | lock_guard lock(mutex_); 174 | for (auto &pair : unordered_map_) 175 | { 176 | _Func(pair.first, pair.second); 177 | } 178 | }; 179 | 180 | private: 181 | mutex mutex_; 182 | unordered_map unordered_map_; 183 | }; 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/network/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #依赖包含 2 | include_directories(../) 3 | # 遍历主目录源文件 4 | file(GLOB_RECURSE SOURCE_FILES "./*.h" "./*.cpp" "./*.cc") 5 | 6 | #编译静态库程序 7 | add_library(network STATIC ${SOURCE_FILES}) 8 | 9 | #设置安装库目录 10 | install(TARGETS network ARCHIVE DESTINATION lib) 11 | install(DIRECTORY ./ DESTINATION include/network FILES_MATCHING PATTERN "*.h") 12 | -------------------------------------------------------------------------------- /src/network/adler32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace happy 4 | { 5 | namespace utils 6 | { 7 | namespace network 8 | { 9 | static const uint32_t BASE = 65521UL; /* largest prime smaller than 65536 */ 10 | static const uint32_t NMAX = 5552; 11 | 12 | // Used to expand the loop to boost the speed. 13 | #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} 14 | #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); 15 | #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); 16 | #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); 17 | #define DO16(buf) DO8(buf,0); DO8(buf,8); 18 | 19 | uint32_t adler32(const void* rbuf, uint32_t length, uint32_t adler/* = 1*/) { 20 | auto buf = reinterpret_cast(rbuf); 21 | uint64_t sum2 = (adler >> 16) & 0xffff; 22 | adler &= 0xffff; 23 | if (length == 1) { 24 | adler += buf[0]; 25 | if (adler >= BASE) 26 | adler -= BASE; 27 | sum2 += adler; 28 | if (sum2 >= BASE) 29 | sum2 -= BASE; 30 | return adler | static_cast(sum2 << 16); 31 | } 32 | 33 | // deferred CHECK_NOTNULL make length == 1 fase 34 | if (buf == nullptr) 35 | return 1; 36 | 37 | if (length < 16) { 38 | while (length--) { 39 | adler += *buf++; 40 | sum2 += adler; 41 | } 42 | if (adler >= BASE) 43 | adler -= BASE; 44 | sum2 %= BASE; 45 | return static_cast(adler | (sum2 << 16)); 46 | } 47 | 48 | while (length >= NMAX) { 49 | length -= NMAX; 50 | uint32_t n = NMAX / 16; 51 | do { 52 | DO16(buf); 53 | buf += 16; 54 | } while (--n); 55 | adler %= BASE; 56 | sum2 %= BASE; 57 | } 58 | 59 | if (length) { 60 | while (length >= 16) { 61 | length -= 16; 62 | DO16(buf); 63 | buf += 16; 64 | } 65 | while (length--) { 66 | adler += *buf++; 67 | sum2 += adler; 68 | } 69 | adler %= BASE; 70 | sum2 %= BASE; 71 | } 72 | return static_cast(adler | (sum2 << 16)); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/network/adler32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace happy 5 | { 6 | namespace utils 7 | { 8 | namespace network 9 | { 10 | 11 | // http://en.wikipedia.org/wiki/Adler-32 12 | // no error check, invoker must insure rbuf is valid 13 | uint32_t adler32(const void* rbuf, uint32_t length, uint32_t adler = 1); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/network/client_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace happy 6 | { 7 | namespace utils 8 | { 9 | namespace network 10 | { 11 | ClientMessageFactory::ClientMessageFactory(const string& closed_print, const bool is_read_print) 12 | : closed_print_(closed_print), UtilMessageFactory(ProtoNetworkConvert::singleton::GetInstance(), is_read_print, false) {} 13 | 14 | void ClientMessageFactory::HandleClose(const ClosedType closed_type) 15 | { 16 | if (closed_print_.length()) 17 | { 18 | OUTPUT << closed_print_ << endl; 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/network/client_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace happy::asio::ip; 4 | 5 | namespace happy 6 | { 7 | namespace utils 8 | { 9 | namespace network 10 | { 11 | class ClientMessageFactory : public UtilMessageFactory 12 | { 13 | public: 14 | ClientMessageFactory(const string& closed_print = "", const bool is_read_print = false); 15 | private: 16 | const string closed_print_; 17 | private: 18 | virtual void HandleClose(const ClosedType closed_type) override; 19 | }; 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/network/network_convert.cpp: -------------------------------------------------------------------------------- 1 | #include "network_convert.h" 2 | 3 | namespace happy 4 | { 5 | namespace utils 6 | { 7 | namespace network 8 | { 9 | shared_ptr NetworkConvert::CreateMessage(const string& type_name) 10 | { 11 | if (!type_name.length()) 12 | { 13 | return nullptr; 14 | } 15 | auto const descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name); 16 | if (descriptor) 17 | { 18 | auto const prototype = MessageFactory::generated_factory()->GetPrototype(descriptor); 19 | if (prototype) 20 | { 21 | return shared_ptr (prototype->New()); 22 | } 23 | } 24 | return nullptr; 25 | } 26 | 27 | string NetworkConvert::GetLastError() 28 | { 29 | return last_error_; 30 | } 31 | 32 | void NetworkConvert::SetLastError(const string& last_error) 33 | { 34 | last_error_ = last_error; 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/network/network_convert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace google::protobuf; 6 | using namespace std; 7 | 8 | namespace happy 9 | { 10 | namespace utils 11 | { 12 | namespace network 13 | { 14 | class NetworkConvert 15 | { 16 | public: 17 | virtual bool IsConsumed(const uint8_t* buffer, const size_t length, size_t& deal_length, bool& is_discarded) = 0; 18 | virtual shared_ptr ToProto(const uint8_t* buffer, const size_t length) = 0; 19 | virtual bool ToNetwork(const shared_ptr message, string& out_buffer, const int session_id = 0) = 0; 20 | shared_ptr CreateMessage(const string& type_name); 21 | string GetLastError(); 22 | protected: 23 | void SetLastError(const string& last_error); 24 | private: 25 | string last_error_; 26 | }; 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/network/news.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using namespace google::protobuf; 5 | using std::shared_ptr; 6 | 7 | namespace happy 8 | { 9 | namespace utils 10 | { 11 | namespace network 12 | { 13 | struct News 14 | { 15 | int session_id; 16 | shared_ptr message; 17 | News(const shared_ptr in_message = nullptr, const int in_session_id = 0) 18 | { 19 | message = in_message; 20 | session_id = in_session_id; 21 | } 22 | }; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/network/proto_network_convert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace boost::asio::detail::socket_ops; 6 | 7 | namespace happy 8 | { 9 | namespace utils 10 | { 11 | namespace network 12 | { 13 | bool ProtoNetworkConvert::IsConsumed(const uint8_t* buffer, const size_t length, size_t& deal_length, bool& has_package) 14 | { 15 | deal_length = length; 16 | if (length < sizeof(NetworkHeader)) 17 | { 18 | has_package = true; 19 | 20 | return false; 21 | } 22 | NetworkData network_data{ 0 }; 23 | network_data.header.MemoryCopyAndConvert(buffer); 24 | auto total_length = sizeof(network_data.header) + network_data.header.content_length + network_data.header.message_name_length + sizeof(network_data.check_sum); 25 | // header check sum 26 | if (adler32(buffer, sizeof(network_data.header) - sizeof(network_data.header.check_sum)) != network_data.header.check_sum) 27 | { 28 | return false; 29 | } 30 | // has package 31 | if (total_length > length) 32 | { 33 | has_package = true; 34 | 35 | return false; 36 | } 37 | 38 | deal_length = total_length; 39 | // check sum 40 | if (adler32(buffer, total_length - sizeof(network_data.check_sum)) 41 | != network_to_host_long(*(reinterpret_cast (const_cast (buffer + total_length - sizeof(network_data.check_sum)))))) 42 | { 43 | return false; 44 | } 45 | return true; 46 | } 47 | 48 | shared_ptr ProtoNetworkConvert::ToProto(const uint8_t* buffer, const size_t) 49 | { 50 | shared_ptr news = make_shared (); 51 | NetworkData network_data{ 0 }; 52 | network_data.header.MemoryCopyAndConvert(buffer); 53 | network_data.message_name.append(reinterpret_cast (const_cast (buffer)) + sizeof(NetworkHeader), network_data.header.message_name_length); 54 | network_data.content.append(reinterpret_cast (const_cast (buffer)) + sizeof(NetworkHeader) + network_data.header.message_name_length 55 | , network_data.header.content_length); 56 | if (network_data.header.content_compress_type) 57 | { 58 | auto length = qlz_size_decompressed(network_data.content.c_str()); 59 | if (length > 102400000) 60 | { 61 | length = network_data.content.length() * 10; 62 | } 63 | string str(length, '\0'); 64 | str.resize(qlz_decompress(network_data.content.c_str(), const_cast (str.data()), make_shared ().get())); 65 | network_data.content.swap(str); 66 | } 67 | news->session_id = network_data.header.session_id; 68 | news->message = CreateMessage(network_data.message_name); 69 | 70 | if (nullptr == news->message) 71 | { 72 | SetLastError("Create message "+ network_data.message_name +" error!"); 73 | return news; 74 | } 75 | 76 | if (!news->message->ParseFromString(network_data.content)) 77 | { 78 | SetLastError("Parse message " + network_data.message_name + " error!"); 79 | news->message = nullptr; 80 | return news; 81 | } 82 | if (!news->message->IsInitialized()) 83 | { 84 | SetLastError("Initialize message " + network_data.message_name + " error!"); 85 | news->message = nullptr; 86 | return news; 87 | } 88 | return news; 89 | } 90 | 91 | bool ProtoNetworkConvert::ToNetwork(const shared_ptr message, string& out_buffer, const int session_id) 92 | { 93 | if (nullptr == message) 94 | { 95 | return false; 96 | } 97 | NetworkData network_data; 98 | static const int kMaxUncompressSize = 1024000; 99 | auto content = message->SerializeAsString(); 100 | if (content.length() > kMaxUncompressSize) 101 | { 102 | network_data.content.resize(content.length()); 103 | network_data.content.resize(qlz_compress(content.c_str(), const_cast (network_data.content.data()) 104 | , content.length(), make_shared ().get())); 105 | network_data.header.content_compress_type = 1; 106 | } 107 | else 108 | { 109 | network_data.header.content_compress_type = 0; 110 | network_data.content.swap(content); 111 | } 112 | network_data.message_name = message->GetDescriptor()->full_name(); 113 | network_data.header.session_id = session_id; 114 | network_data.header.content_length = network_data.content.length(); 115 | network_data.header.message_name_length = network_data.message_name.length(); 116 | network_data.header.MemoryCopyAndConvert(nullptr); 117 | network_data.header.check_sum = network_to_host_long(adler32(reinterpret_cast (&network_data.header) 118 | , sizeof(network_data.header) - sizeof(network_data.header.check_sum))); 119 | out_buffer = ""; 120 | out_buffer.append(reinterpret_cast (&network_data.header), sizeof(network_data.header)); 121 | out_buffer.append(network_data.message_name); 122 | out_buffer.append(network_data.content); 123 | network_data.check_sum = network_to_host_long(adler32(out_buffer.c_str(), out_buffer.length())); 124 | out_buffer.append(reinterpret_cast (&network_data.check_sum), sizeof(network_data.check_sum)); 125 | 126 | return true; 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/network/proto_network_convert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define DEFINE_HOST_NETWORK_CONVERT(format) \ 6 | void MemoryCopyAndConvert(const uint8_t* buffer) \ 7 | { \ 8 | if (nullptr == format) \ 9 | { \ 10 | return; \ 11 | } \ 12 | auto tmp_buffer = *this; \ 13 | const uint8_t* current_buffer = buffer; \ 14 | if (nullptr == current_buffer) \ 15 | { \ 16 | current_buffer = reinterpret_cast (&tmp_buffer); \ 17 | } \ 18 | int member_size; \ 19 | uint8_t* current_data = reinterpret_cast (this); \ 20 | for (size_t i = 0; i < strlen(format); i++) \ 21 | { \ 22 | member_size = format[i] - '0'; \ 23 | if (2 == member_size) \ 24 | { \ 25 | current_data[0] = current_buffer[1]; \ 26 | current_data[1] = current_buffer[0]; \ 27 | } \ 28 | else if (4 == member_size) \ 29 | { \ 30 | current_data[0] = current_buffer[3]; \ 31 | current_data[1] = current_buffer[2]; \ 32 | current_data[2] = current_buffer[1]; \ 33 | current_data[3] = current_buffer[0]; \ 34 | } \ 35 | else if (8 == member_size) \ 36 | { \ 37 | current_data[0] = current_buffer[7]; \ 38 | current_data[1] = current_buffer[6]; \ 39 | current_data[2] = current_buffer[5]; \ 40 | current_data[3] = current_buffer[4]; \ 41 | current_data[4] = current_buffer[3]; \ 42 | current_data[5] = current_buffer[2]; \ 43 | current_data[6] = current_buffer[1]; \ 44 | current_data[7] = current_buffer[0]; \ 45 | } \ 46 | else \ 47 | { \ 48 | current_data[0] = current_buffer[0]; \ 49 | } \ 50 | current_data += member_size; \ 51 | current_buffer += member_size; \ 52 | } \ 53 | } 54 | 55 | namespace happy 56 | { 57 | namespace utils 58 | { 59 | namespace network 60 | { 61 | class ProtoNetworkConvert : public NetworkConvert 62 | { 63 | DEFINE_SINGLETON_DEFAULT(ProtoNetworkConvert); 64 | public: 65 | virtual bool IsConsumed(const uint8_t* buffer, const size_t length, size_t& deal_length, bool& has_package) override final; 66 | virtual shared_ptr ToProto(const uint8_t* buffer, const size_t length) override final; 67 | virtual bool ToNetwork(const shared_ptr message, string& out_buffer, const int session_id = 0) override final; 68 | private: 69 | #pragma pack(push, 1) 70 | struct NetworkHeader 71 | { 72 | int session_id; // 会话标识 73 | int message_name_length; // 消息名称长度 74 | int content_length; // 消息内容长度 75 | uint8_t content_compress_type; // 0: 未压缩; 1: klz压缩 76 | uint32_t check_sum; // 头校验和 77 | DEFINE_HOST_NETWORK_CONVERT("44414"); 78 | }; 79 | #pragma pack(pop) 80 | struct NetworkData 81 | { 82 | NetworkHeader header; // 消息头 83 | string message_name; // 消息名称 84 | string content; // 消息内容 85 | uint32_t check_sum; // 校验和 86 | }; 87 | }; 88 | } 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/network/quicklz.cpp: -------------------------------------------------------------------------------- 1 | // Fast data compression library 2 | // Copyright (C) 2006-2011 Lasse Mikkel Reinhold 3 | // lar@quicklz.com 4 | // 5 | // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything 6 | // released into public must be open source) or under a commercial license if such 7 | // has been acquired (see http://www.quicklz.com/order.html). The commercial license 8 | // does not cover derived or ported versions created by third parties under GPL. 9 | 10 | // 1.5.0 final 11 | 12 | #include "quicklz.h" 13 | 14 | #if QLZ_VERSION_MAJOR != 1 || QLZ_VERSION_MINOR != 5 || QLZ_VERSION_REVISION != 0 15 | #error quicklz.c and quicklz.h have different versions 16 | #endif 17 | 18 | #if (defined(__X86__) || defined(__i386__) || defined(i386) || defined(_M_IX86) || defined(__386__) || defined(__x86_64__) || defined(_M_X64)) 19 | #define X86X64 20 | #endif 21 | 22 | #define MINOFFSET 2 23 | #define UNCONDITIONAL_MATCHLEN 6 24 | #define UNCOMPRESSED_END 4 25 | #define CWORD_LEN 4 26 | 27 | #if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 28 | #define OFFSET_BASE source 29 | #define CAST (ui32)(size_t) 30 | #else 31 | #define OFFSET_BASE 0 32 | #define CAST 33 | #endif 34 | 35 | int qlz_get_setting(int setting) 36 | { 37 | switch (setting) 38 | { 39 | case 0: return QLZ_COMPRESSION_LEVEL; 40 | case 1: return sizeof(qlz_state_compress); 41 | case 2: return sizeof(qlz_state_decompress); 42 | case 3: return QLZ_STREAMING_BUFFER; 43 | #ifdef QLZ_MEMORY_SAFE 44 | case 6: return 1; 45 | #else 46 | case 6: return 0; 47 | #endif 48 | case 7: return QLZ_VERSION_MAJOR; 49 | case 8: return QLZ_VERSION_MINOR; 50 | case 9: return QLZ_VERSION_REVISION; 51 | } 52 | return -1; 53 | } 54 | 55 | #if QLZ_COMPRESSION_LEVEL == 1 56 | static int same(const unsigned char *src, size_t n) 57 | { 58 | while(n > 0 && *(src + n) == *src) 59 | n--; 60 | return n == 0 ? 1 : 0; 61 | } 62 | #endif 63 | 64 | static void reset_table_compress(qlz_state_compress *state) 65 | { 66 | int i; 67 | for(i = 0; i < QLZ_HASH_VALUES; i++) 68 | { 69 | #if QLZ_COMPRESSION_LEVEL == 1 70 | state->hash[i].offset = 0; 71 | #else 72 | state->hash_counter[i] = 0; 73 | #endif 74 | } 75 | } 76 | 77 | static void reset_table_decompress(qlz_state_decompress *state) 78 | { 79 | int i; 80 | (void)state; 81 | (void)i; 82 | #if QLZ_COMPRESSION_LEVEL == 2 83 | for(i = 0; i < QLZ_HASH_VALUES; i++) 84 | { 85 | state->hash_counter[i] = 0; 86 | } 87 | #endif 88 | } 89 | 90 | static __inline ui32 hash_func(ui32 i) 91 | { 92 | #if QLZ_COMPRESSION_LEVEL == 2 93 | return ((i >> 9) ^ (i >> 13) ^ i) & (QLZ_HASH_VALUES - 1); 94 | #else 95 | return ((i >> 12) ^ i) & (QLZ_HASH_VALUES - 1); 96 | #endif 97 | } 98 | 99 | static __inline ui32 fast_read(void const *src, ui32 bytes) 100 | { 101 | #ifndef X86X64 102 | unsigned char *p = (unsigned char*)src; 103 | switch (bytes) 104 | { 105 | case 4: 106 | return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24); 107 | case 3: 108 | return(*p | *(p + 1) << 8 | *(p + 2) << 16); 109 | case 2: 110 | return(*p | *(p + 1) << 8); 111 | case 1: 112 | return(*p); 113 | } 114 | return 0; 115 | #else 116 | if (bytes >= 1 && bytes <= 4) 117 | return *((ui32*)src); 118 | else 119 | return 0; 120 | #endif 121 | } 122 | 123 | static __inline ui32 hashat(const unsigned char *src) 124 | { 125 | ui32 fetch, hash; 126 | fetch = fast_read(src, 3); 127 | hash = hash_func(fetch); 128 | return hash; 129 | } 130 | 131 | static __inline void fast_write(ui32 f, void *dst, size_t bytes) 132 | { 133 | #ifndef X86X64 134 | unsigned char *p = (unsigned char*)dst; 135 | 136 | switch (bytes) 137 | { 138 | case 4: 139 | *p = (unsigned char)f; 140 | *(p + 1) = (unsigned char)(f >> 8); 141 | *(p + 2) = (unsigned char)(f >> 16); 142 | *(p + 3) = (unsigned char)(f >> 24); 143 | return; 144 | case 3: 145 | *p = (unsigned char)f; 146 | *(p + 1) = (unsigned char)(f >> 8); 147 | *(p + 2) = (unsigned char)(f >> 16); 148 | return; 149 | case 2: 150 | *p = (unsigned char)f; 151 | *(p + 1) = (unsigned char)(f >> 8); 152 | return; 153 | case 1: 154 | *p = (unsigned char)f; 155 | return; 156 | } 157 | #else 158 | switch (bytes) 159 | { 160 | case 4: 161 | *((ui32*)dst) = f; 162 | return; 163 | case 3: 164 | *((ui32*)dst) = f; 165 | return; 166 | case 2: 167 | *((ui16 *)dst) = (ui16)f; 168 | return; 169 | case 1: 170 | *((unsigned char*)dst) = (unsigned char)f; 171 | return; 172 | } 173 | #endif 174 | } 175 | 176 | 177 | size_t qlz_size_decompressed(const char *source) 178 | { 179 | ui32 n, r; 180 | n = (((*source) & 2) == 2) ? 4 : 1; 181 | r = fast_read(source + 1 + n, n); 182 | r = r & (0xffffffff >> ((4 - n)*8)); 183 | return r; 184 | } 185 | 186 | size_t qlz_size_compressed(const char *source) 187 | { 188 | ui32 n, r; 189 | n = (((*source) & 2) == 2) ? 4 : 1; 190 | r = fast_read(source + 1, n); 191 | r = r & (0xffffffff >> ((4 - n)*8)); 192 | return r; 193 | } 194 | 195 | size_t qlz_size_header(const char *source) 196 | { 197 | size_t n = 2*((((*source) & 2) == 2) ? 4 : 1) + 1; 198 | return n; 199 | } 200 | 201 | 202 | static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui32 n) 203 | { 204 | // Caution if modifying memcpy_up! Overlap of dst and src must be special handled. 205 | #ifndef X86X64 206 | unsigned char *end = dst + n; 207 | while(dst < end) 208 | { 209 | *dst = *src; 210 | dst++; 211 | src++; 212 | } 213 | #else 214 | ui32 f = 0; 215 | do 216 | { 217 | *(ui32 *)(dst + f) = *(ui32 *)(src + f); 218 | f += MINOFFSET + 1; 219 | } 220 | while (f < n); 221 | #endif 222 | } 223 | 224 | static __inline void update_hash(qlz_state_decompress *state, const unsigned char *s) 225 | { 226 | #if QLZ_COMPRESSION_LEVEL == 1 227 | ui32 hash; 228 | hash = hashat(s); 229 | state->hash[hash].offset = s; 230 | state->hash_counter[hash] = 1; 231 | #elif QLZ_COMPRESSION_LEVEL == 2 232 | ui32 hash; 233 | unsigned char c; 234 | hash = hashat(s); 235 | c = state->hash_counter[hash]; 236 | state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s; 237 | c++; 238 | state->hash_counter[hash] = c; 239 | #endif 240 | (void)state; 241 | (void)s; 242 | } 243 | 244 | #if QLZ_COMPRESSION_LEVEL <= 2 245 | static void update_hash_upto(qlz_state_decompress *state, unsigned char **lh, const unsigned char *max) 246 | { 247 | while(*lh < max) 248 | { 249 | (*lh)++; 250 | update_hash(state, *lh); 251 | } 252 | } 253 | #endif 254 | 255 | static size_t qlz_compress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_compress *state) 256 | { 257 | const unsigned char *last_byte = source + size - 1; 258 | const unsigned char *src = source; 259 | unsigned char *cword_ptr = destination; 260 | unsigned char *dst = destination + CWORD_LEN; 261 | ui32 cword_val = 1U << 31; 262 | const unsigned char *last_matchstart = last_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END; 263 | ui32 fetch = 0; 264 | unsigned int lits = 0; 265 | 266 | (void) lits; 267 | 268 | if(src <= last_matchstart) 269 | fetch = fast_read(src, 3); 270 | 271 | while(src <= last_matchstart) 272 | { 273 | if ((cword_val & 1) == 1) 274 | { 275 | // store uncompressed if compression ratio is too low 276 | if (src > source + (size >> 1) && dst - destination > src - source - ((src - source) >> 5)) 277 | return 0; 278 | 279 | fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN); 280 | 281 | cword_ptr = dst; 282 | dst += CWORD_LEN; 283 | cword_val = 1U << 31; 284 | fetch = fast_read(src, 3); 285 | } 286 | #if QLZ_COMPRESSION_LEVEL == 1 287 | { 288 | const unsigned char *o; 289 | ui32 hash, cached; 290 | 291 | hash = hash_func(fetch); 292 | cached = fetch ^ state->hash[hash].cache; 293 | state->hash[hash].cache = fetch; 294 | 295 | o = state->hash[hash].offset + OFFSET_BASE; 296 | state->hash[hash].offset = CAST(src - OFFSET_BASE); 297 | 298 | #ifdef X86X64 299 | if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) 300 | { 301 | if(cached != 0) 302 | { 303 | #else 304 | if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6)))) 305 | { 306 | if (*(o + 3) != *(src + 3)) 307 | { 308 | #endif 309 | hash <<= 4; 310 | cword_val = (cword_val >> 1) | (1U << 31); 311 | fast_write((3 - 2) | hash, dst, 2); 312 | src += 3; 313 | dst += 2; 314 | } 315 | else 316 | { 317 | const unsigned char *old_src = src; 318 | size_t matchlen; 319 | hash <<= 4; 320 | 321 | cword_val = (cword_val >> 1) | (1U << 31); 322 | src += 4; 323 | 324 | if(*(o + (src - old_src)) == *src) 325 | { 326 | src++; 327 | if(*(o + (src - old_src)) == *src) 328 | { 329 | size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1; 330 | size_t remaining = q > 255 ? 255 : q; 331 | src++; 332 | while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining) 333 | src++; 334 | } 335 | } 336 | 337 | matchlen = src - old_src; 338 | if (matchlen < 18) 339 | { 340 | fast_write((ui32)(matchlen - 2) | hash, dst, 2); 341 | dst += 2; 342 | } 343 | else 344 | { 345 | fast_write((ui32)(matchlen << 16) | hash, dst, 3); 346 | dst += 3; 347 | } 348 | } 349 | fetch = fast_read(src, 3); 350 | lits = 0; 351 | } 352 | else 353 | { 354 | lits++; 355 | *dst = *src; 356 | src++; 357 | dst++; 358 | cword_val = (cword_val >> 1); 359 | #ifdef X86X64 360 | fetch = fast_read(src, 3); 361 | #else 362 | fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16); 363 | #endif 364 | } 365 | } 366 | #elif QLZ_COMPRESSION_LEVEL >= 2 367 | { 368 | const unsigned char *o, *offset2; 369 | ui32 hash, matchlen, k, m, best_k = 0; 370 | unsigned char c; 371 | size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1); 372 | (void)best_k; 373 | 374 | 375 | //hash = hashat(src); 376 | fetch = fast_read(src, 3); 377 | hash = hash_func(fetch); 378 | 379 | c = state->hash_counter[hash]; 380 | 381 | offset2 = state->hash[hash].offset[0]; 382 | if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0) 383 | { 384 | matchlen = 3; 385 | if(*(offset2 + matchlen) == *(src + matchlen)) 386 | { 387 | matchlen = 4; 388 | while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining) 389 | matchlen++; 390 | } 391 | } 392 | else 393 | matchlen = 0; 394 | for(k = 1; k < QLZ_POINTERS && c > k; k++) 395 | { 396 | o = state->hash[hash].offset[k]; 397 | #if QLZ_COMPRESSION_LEVEL == 3 398 | if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) 399 | #elif QLZ_COMPRESSION_LEVEL == 2 400 | if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET) 401 | #endif 402 | { 403 | m = 3; 404 | while(*(o + m) == *(src + m) && m < remaining) 405 | m++; 406 | #if QLZ_COMPRESSION_LEVEL == 3 407 | if ((m > matchlen) || (m == matchlen && o > offset2)) 408 | #elif QLZ_COMPRESSION_LEVEL == 2 409 | if (m > matchlen) 410 | #endif 411 | { 412 | offset2 = o; 413 | matchlen = m; 414 | best_k = k; 415 | } 416 | } 417 | } 418 | o = offset2; 419 | state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; 420 | c++; 421 | state->hash_counter[hash] = c; 422 | 423 | #if QLZ_COMPRESSION_LEVEL == 3 424 | if(matchlen > 2 && src - o < 131071) 425 | { 426 | ui32 u; 427 | size_t offset = src - o; 428 | 429 | for(u = 1; u < matchlen; u++) 430 | { 431 | hash = hashat(src + u); 432 | c = state->hash_counter[hash]++; 433 | state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u; 434 | } 435 | 436 | cword_val = (cword_val >> 1) | (1U << 31); 437 | src += matchlen; 438 | 439 | if(matchlen == 3 && offset <= 63) 440 | { 441 | *dst = (unsigned char)(offset << 2); 442 | dst++; 443 | } 444 | else if (matchlen == 3 && offset <= 16383) 445 | { 446 | ui32 f = (ui32)((offset << 2) | 1); 447 | fast_write(f, dst, 2); 448 | dst += 2; 449 | } 450 | else if (matchlen <= 18 && offset <= 1023) 451 | { 452 | ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2; 453 | fast_write(f, dst, 2); 454 | dst += 2; 455 | } 456 | 457 | else if(matchlen <= 33) 458 | { 459 | ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3; 460 | fast_write(f, dst, 3); 461 | dst += 3; 462 | } 463 | else 464 | { 465 | ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3; 466 | fast_write(f, dst, 4); 467 | dst += 4; 468 | } 469 | } 470 | else 471 | { 472 | *dst = *src; 473 | src++; 474 | dst++; 475 | cword_val = (cword_val >> 1); 476 | } 477 | #elif QLZ_COMPRESSION_LEVEL == 2 478 | 479 | if(matchlen > 2) 480 | { 481 | cword_val = (cword_val >> 1) | (1U << 31); 482 | src += matchlen; 483 | 484 | if (matchlen < 10) 485 | { 486 | ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5); 487 | fast_write(f, dst, 2); 488 | dst += 2; 489 | } 490 | else 491 | { 492 | ui32 f = best_k | (matchlen << 16) | (hash << 5); 493 | fast_write(f, dst, 3); 494 | dst += 3; 495 | } 496 | } 497 | else 498 | { 499 | *dst = *src; 500 | src++; 501 | dst++; 502 | cword_val = (cword_val >> 1); 503 | } 504 | #endif 505 | } 506 | #endif 507 | } 508 | while (src <= last_byte) 509 | { 510 | if ((cword_val & 1) == 1) 511 | { 512 | fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN); 513 | cword_ptr = dst; 514 | dst += CWORD_LEN; 515 | cword_val = 1U << 31; 516 | } 517 | #if QLZ_COMPRESSION_LEVEL < 3 518 | if (src <= last_byte - 3) 519 | { 520 | #if QLZ_COMPRESSION_LEVEL == 1 521 | ui32 hash, fetch; 522 | fetch = fast_read(src, 3); 523 | hash = hash_func(fetch); 524 | state->hash[hash].offset = CAST(src - OFFSET_BASE); 525 | state->hash[hash].cache = fetch; 526 | #elif QLZ_COMPRESSION_LEVEL == 2 527 | ui32 hash; 528 | unsigned char c; 529 | hash = hashat(src); 530 | c = state->hash_counter[hash]; 531 | state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src; 532 | c++; 533 | state->hash_counter[hash] = c; 534 | #endif 535 | } 536 | #endif 537 | *dst = *src; 538 | src++; 539 | dst++; 540 | cword_val = (cword_val >> 1); 541 | } 542 | 543 | while((cword_val & 1) != 1) 544 | cword_val = (cword_val >> 1); 545 | 546 | fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN); 547 | 548 | // min. size must be 9 bytes so that the qlz_size functions can take 9 bytes as argument 549 | return dst - destination < 9 ? 9 : dst - destination; 550 | } 551 | 552 | static size_t qlz_decompress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_decompress *state, const unsigned char *history) 553 | { 554 | const unsigned char *src = source + qlz_size_header((const char *)source); 555 | unsigned char *dst = destination; 556 | const unsigned char *last_destination_byte = destination + size - 1; 557 | ui32 cword_val = 1; 558 | const unsigned char *last_matchstart = last_destination_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END; 559 | unsigned char *last_hashed = destination - 1; 560 | const unsigned char *last_source_byte = source + qlz_size_compressed((const char *)source) - 1; 561 | static const ui32 bitlut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; 562 | 563 | (void) last_source_byte; 564 | (void) last_hashed; 565 | (void) state; 566 | (void) history; 567 | 568 | for(;;) 569 | { 570 | ui32 fetch; 571 | 572 | if (cword_val == 1) 573 | { 574 | #ifdef QLZ_MEMORY_SAFE 575 | if(src + CWORD_LEN - 1 > last_source_byte) 576 | return 0; 577 | #endif 578 | cword_val = fast_read(src, CWORD_LEN); 579 | src += CWORD_LEN; 580 | } 581 | 582 | #ifdef QLZ_MEMORY_SAFE 583 | if(src + 4 - 1 > last_source_byte) 584 | return 0; 585 | #endif 586 | 587 | fetch = fast_read(src, 4); 588 | 589 | if ((cword_val & 1) == 1) 590 | { 591 | ui32 matchlen; 592 | const unsigned char *offset2; 593 | 594 | #if QLZ_COMPRESSION_LEVEL == 1 595 | ui32 hash; 596 | cword_val = cword_val >> 1; 597 | hash = (fetch >> 4) & 0xfff; 598 | offset2 = (const unsigned char *)(size_t)state->hash[hash].offset; 599 | 600 | if((fetch & 0xf) != 0) 601 | { 602 | matchlen = (fetch & 0xf) + 2; 603 | src += 2; 604 | } 605 | else 606 | { 607 | matchlen = *(src + 2); 608 | src += 3; 609 | } 610 | 611 | #elif QLZ_COMPRESSION_LEVEL == 2 612 | ui32 hash; 613 | unsigned char c; 614 | cword_val = cword_val >> 1; 615 | hash = (fetch >> 5) & 0x7ff; 616 | c = (unsigned char)(fetch & 0x3); 617 | offset2 = state->hash[hash].offset[c]; 618 | 619 | if((fetch & (28)) != 0) 620 | { 621 | matchlen = ((fetch >> 2) & 0x7) + 2; 622 | src += 2; 623 | } 624 | else 625 | { 626 | matchlen = *(src + 2); 627 | src += 3; 628 | } 629 | 630 | #elif QLZ_COMPRESSION_LEVEL == 3 631 | ui32 offset; 632 | cword_val = cword_val >> 1; 633 | if ((fetch & 3) == 0) 634 | { 635 | offset = (fetch & 0xff) >> 2; 636 | matchlen = 3; 637 | src++; 638 | } 639 | else if ((fetch & 2) == 0) 640 | { 641 | offset = (fetch & 0xffff) >> 2; 642 | matchlen = 3; 643 | src += 2; 644 | } 645 | else if ((fetch & 1) == 0) 646 | { 647 | offset = (fetch & 0xffff) >> 6; 648 | matchlen = ((fetch >> 2) & 15) + 3; 649 | src += 2; 650 | } 651 | else if ((fetch & 127) != 3) 652 | { 653 | offset = (fetch >> 7) & 0x1ffff; 654 | matchlen = ((fetch >> 2) & 0x1f) + 2; 655 | src += 3; 656 | } 657 | else 658 | { 659 | offset = (fetch >> 15); 660 | matchlen = ((fetch >> 7) & 255) + 3; 661 | src += 4; 662 | } 663 | 664 | offset2 = dst - offset; 665 | #endif 666 | 667 | #ifdef QLZ_MEMORY_SAFE 668 | if(offset2 < history || offset2 > dst - MINOFFSET - 1) 669 | return 0; 670 | 671 | if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1)) 672 | return 0; 673 | #endif 674 | 675 | memcpy_up(dst, offset2, matchlen); 676 | dst += matchlen; 677 | 678 | #if QLZ_COMPRESSION_LEVEL <= 2 679 | update_hash_upto(state, &last_hashed, dst - matchlen); 680 | last_hashed = dst - 1; 681 | #endif 682 | } 683 | else 684 | { 685 | if (dst < last_matchstart) 686 | { 687 | unsigned int n = bitlut[cword_val & 0xf]; 688 | #ifdef X86X64 689 | *(ui32 *)dst = *(ui32 *)src; 690 | #else 691 | memcpy_up(dst, src, 4); 692 | #endif 693 | cword_val = cword_val >> n; 694 | dst += n; 695 | src += n; 696 | #if QLZ_COMPRESSION_LEVEL <= 2 697 | update_hash_upto(state, &last_hashed, dst - 3); 698 | #endif 699 | } 700 | else 701 | { 702 | while(dst <= last_destination_byte) 703 | { 704 | if (cword_val == 1) 705 | { 706 | src += CWORD_LEN; 707 | cword_val = 1U << 31; 708 | } 709 | #ifdef QLZ_MEMORY_SAFE 710 | if(src >= last_source_byte + 1) 711 | return 0; 712 | #endif 713 | *dst = *src; 714 | dst++; 715 | src++; 716 | cword_val = cword_val >> 1; 717 | } 718 | 719 | #if QLZ_COMPRESSION_LEVEL <= 2 720 | update_hash_upto(state, &last_hashed, last_destination_byte - 3); // todo, use constant 721 | #endif 722 | return size; 723 | } 724 | 725 | } 726 | } 727 | } 728 | 729 | size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state) 730 | { 731 | size_t r; 732 | ui32 compressed; 733 | size_t base; 734 | 735 | if(size == 0 || size > 0xffffffff - 400) 736 | return 0; 737 | 738 | if(size < 216) 739 | base = 3; 740 | else 741 | base = 9; 742 | 743 | #if QLZ_STREAMING_BUFFER > 0 744 | if (state->stream_counter + size - 1 >= QLZ_STREAMING_BUFFER) 745 | #endif 746 | { 747 | reset_table_compress(state); 748 | r = base + qlz_compress_core((const unsigned char *)source, (unsigned char*)destination + base, size, state); 749 | #if QLZ_STREAMING_BUFFER > 0 750 | reset_table_compress(state); 751 | #endif 752 | if(r == base) 753 | { 754 | memcpy(destination + base, source, size); 755 | r = size + base; 756 | compressed = 0; 757 | } 758 | else 759 | { 760 | compressed = 1; 761 | } 762 | state->stream_counter = 0; 763 | } 764 | #if QLZ_STREAMING_BUFFER > 0 765 | else 766 | { 767 | unsigned char *src = state->stream_buffer + state->stream_counter; 768 | 769 | memcpy(src, source, size); 770 | r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state); 771 | 772 | if(r == base) 773 | { 774 | memcpy(destination + base, src, size); 775 | r = size + base; 776 | compressed = 0; 777 | reset_table_compress(state); 778 | } 779 | else 780 | { 781 | compressed = 1; 782 | } 783 | state->stream_counter += size; 784 | } 785 | #endif 786 | if(base == 3) 787 | { 788 | *destination = (unsigned char)(0 | compressed); 789 | *(destination + 1) = (unsigned char)r; 790 | *(destination + 2) = (unsigned char)size; 791 | } 792 | else 793 | { 794 | *destination = (unsigned char)(2 | compressed); 795 | fast_write((ui32)r, destination + 1, 4); 796 | fast_write((ui32)size, destination + 5, 4); 797 | } 798 | 799 | *destination |= (QLZ_COMPRESSION_LEVEL << 2); 800 | *destination |= (1 << 6); 801 | *destination |= ((QLZ_STREAMING_BUFFER == 0 ? 0 : (QLZ_STREAMING_BUFFER == 100000 ? 1 : (QLZ_STREAMING_BUFFER == 1000000 ? 2 : 3))) << 4); 802 | 803 | // 76543210 804 | // 01SSLLHC 805 | 806 | return r; 807 | } 808 | 809 | size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state) 810 | { 811 | size_t dsiz = qlz_size_decompressed(source); 812 | 813 | #if QLZ_STREAMING_BUFFER > 0 814 | if (state->stream_counter + qlz_size_decompressed(source) - 1 >= QLZ_STREAMING_BUFFER) 815 | #endif 816 | { 817 | if((*source & 1) == 1) 818 | { 819 | reset_table_decompress(state); 820 | dsiz = qlz_decompress_core((const unsigned char *)source, (unsigned char *)destination, dsiz, state, (const unsigned char *)destination); 821 | } 822 | else 823 | { 824 | memcpy(destination, source + qlz_size_header(source), dsiz); 825 | } 826 | state->stream_counter = 0; 827 | reset_table_decompress(state); 828 | } 829 | #if QLZ_STREAMING_BUFFER > 0 830 | else 831 | { 832 | unsigned char *dst = state->stream_buffer + state->stream_counter; 833 | if((*source & 1) == 1) 834 | { 835 | dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer); 836 | } 837 | else 838 | { 839 | memcpy(dst, source + qlz_size_header(source), dsiz); 840 | reset_table_decompress(state); 841 | } 842 | memcpy(destination, dst, dsiz); 843 | state->stream_counter += dsiz; 844 | } 845 | #endif 846 | return dsiz; 847 | } 848 | 849 | -------------------------------------------------------------------------------- /src/network/quicklz.h: -------------------------------------------------------------------------------- 1 | #ifndef QLZ_HEADER 2 | #define QLZ_HEADER 3 | 4 | // Fast data compression library 5 | // Copyright (C) 2006-2011 Lasse Mikkel Reinhold 6 | // lar@quicklz.com 7 | // 8 | // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything 9 | // released into public must be open source) or under a commercial license if such 10 | // has been acquired (see http://www.quicklz.com/order.html). The commercial license 11 | // does not cover derived or ported versions created by third parties under GPL. 12 | 13 | // You can edit following user settings. Data must be decompressed with the same 14 | // setting of QLZ_COMPRESSION_LEVEL and QLZ_STREAMING_BUFFER as it was compressed 15 | // (see manual). If QLZ_STREAMING_BUFFER > 0, scratch buffers must be initially 16 | // zeroed out (see manual). First #ifndef makes it possible to define settings from 17 | // the outside like the compiler command line. 18 | 19 | // 1.5.0 final 20 | 21 | #ifndef QLZ_COMPRESSION_LEVEL 22 | 23 | // 1 gives fastest compression speed. 3 gives fastest decompression speed and best 24 | // compression ratio. 25 | #define QLZ_COMPRESSION_LEVEL 1 26 | //#define QLZ_COMPRESSION_LEVEL 2 27 | //#define QLZ_COMPRESSION_LEVEL 3 28 | 29 | // If > 0, zero out both states prior to first call to qlz_compress() or qlz_decompress() 30 | // and decompress packets in the same order as they were compressed 31 | #define QLZ_STREAMING_BUFFER 0 32 | //#define QLZ_STREAMING_BUFFER 100000 33 | //#define QLZ_STREAMING_BUFFER 1000000 34 | 35 | // Guarantees that decompression of corrupted data cannot crash. Decreases decompression 36 | // speed 10-20%. Compression speed not affected. 37 | //#define QLZ_MEMORY_SAFE 38 | #endif 39 | 40 | #define QLZ_VERSION_MAJOR 1 41 | #define QLZ_VERSION_MINOR 5 42 | #define QLZ_VERSION_REVISION 0 43 | 44 | // Using size_t, memset() and memcpy() 45 | #include 46 | 47 | // Verify compression level 48 | #if QLZ_COMPRESSION_LEVEL != 1 && QLZ_COMPRESSION_LEVEL != 2 && QLZ_COMPRESSION_LEVEL != 3 49 | #error QLZ_COMPRESSION_LEVEL must be 1, 2 or 3 50 | #endif 51 | 52 | typedef unsigned int ui32; 53 | typedef unsigned short int ui16; 54 | 55 | // Decrease QLZ_POINTERS for level 3 to increase compression speed. Do not touch any other values! 56 | #if QLZ_COMPRESSION_LEVEL == 1 57 | #define QLZ_POINTERS 1 58 | #define QLZ_HASH_VALUES 4096 59 | #elif QLZ_COMPRESSION_LEVEL == 2 60 | #define QLZ_POINTERS 4 61 | #define QLZ_HASH_VALUES 2048 62 | #elif QLZ_COMPRESSION_LEVEL == 3 63 | #define QLZ_POINTERS 16 64 | #define QLZ_HASH_VALUES 4096 65 | #endif 66 | 67 | // Detect if pointer size is 64-bit. It's not fatal if some 64-bit target is not detected because this is only for adding an optional 64-bit optimization. 68 | #if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || __WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 || defined __x86_64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__ 69 | #define QLZ_PTR_64 70 | #endif 71 | 72 | // hash entry 73 | typedef struct 74 | { 75 | #if QLZ_COMPRESSION_LEVEL == 1 76 | ui32 cache; 77 | #if defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0 78 | unsigned int offset; 79 | #else 80 | const unsigned char *offset; 81 | #endif 82 | #else 83 | const unsigned char *offset[QLZ_POINTERS]; 84 | #endif 85 | 86 | } qlz_hash_compress; 87 | 88 | typedef struct 89 | { 90 | #if QLZ_COMPRESSION_LEVEL == 1 91 | const unsigned char *offset; 92 | #else 93 | const unsigned char *offset[QLZ_POINTERS]; 94 | #endif 95 | } qlz_hash_decompress; 96 | 97 | 98 | // states 99 | typedef struct 100 | { 101 | #if QLZ_STREAMING_BUFFER > 0 102 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 103 | #endif 104 | size_t stream_counter; 105 | qlz_hash_compress hash[QLZ_HASH_VALUES]; 106 | unsigned char hash_counter[QLZ_HASH_VALUES]; 107 | } qlz_state_compress; 108 | 109 | 110 | #if QLZ_COMPRESSION_LEVEL == 1 || QLZ_COMPRESSION_LEVEL == 2 111 | typedef struct 112 | { 113 | #if QLZ_STREAMING_BUFFER > 0 114 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 115 | #endif 116 | qlz_hash_decompress hash[QLZ_HASH_VALUES]; 117 | unsigned char hash_counter[QLZ_HASH_VALUES]; 118 | size_t stream_counter; 119 | } qlz_state_decompress; 120 | #elif QLZ_COMPRESSION_LEVEL == 3 121 | typedef struct 122 | { 123 | #if QLZ_STREAMING_BUFFER > 0 124 | unsigned char stream_buffer[QLZ_STREAMING_BUFFER]; 125 | #endif 126 | #if QLZ_COMPRESSION_LEVEL <= 2 127 | qlz_hash_decompress hash[QLZ_HASH_VALUES]; 128 | #endif 129 | size_t stream_counter; 130 | } qlz_state_decompress; 131 | #endif 132 | 133 | 134 | #if defined (__cplusplus) 135 | extern "C" { 136 | #endif 137 | 138 | // Public functions of QuickLZ 139 | size_t qlz_size_decompressed(const char *source); 140 | size_t qlz_size_compressed(const char *source); 141 | size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state); 142 | size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state); 143 | int qlz_get_setting(int setting); 144 | 145 | #if defined (__cplusplus) 146 | } 147 | #endif 148 | 149 | #endif 150 | 151 | -------------------------------------------------------------------------------- /src/network/response_error.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: response_error.proto 3 | 4 | #include "response_error.pb.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | // @@protoc_insertion_point(includes) 17 | #include 18 | 19 | namespace happy { 20 | namespace utils { 21 | namespace network { 22 | class ResponseErrorDefaultTypeInternal { 23 | public: 24 | ::google::protobuf::internal::ExplicitlyConstructed _instance; 25 | } _ResponseError_default_instance_; 26 | } // namespace network 27 | } // namespace utils 28 | } // namespace happy 29 | static void InitDefaultsResponseError_response_5ferror_2eproto() { 30 | GOOGLE_PROTOBUF_VERIFY_VERSION; 31 | 32 | { 33 | void* ptr = &::happy::utils::network::_ResponseError_default_instance_; 34 | new (ptr) ::happy::utils::network::ResponseError(); 35 | ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); 36 | } 37 | ::happy::utils::network::ResponseError::InitAsDefaultInstance(); 38 | } 39 | 40 | ::google::protobuf::internal::SCCInfo<0> scc_info_ResponseError_response_5ferror_2eproto = 41 | {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsResponseError_response_5ferror_2eproto}, {}}; 42 | 43 | void InitDefaults_response_5ferror_2eproto() { 44 | ::google::protobuf::internal::InitSCC(&scc_info_ResponseError_response_5ferror_2eproto.base); 45 | } 46 | 47 | ::google::protobuf::Metadata file_level_metadata_response_5ferror_2eproto[1]; 48 | constexpr ::google::protobuf::EnumDescriptor const** file_level_enum_descriptors_response_5ferror_2eproto = nullptr; 49 | constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_response_5ferror_2eproto = nullptr; 50 | 51 | const ::google::protobuf::uint32 TableStruct_response_5ferror_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 52 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseError, _has_bits_), 53 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseError, _internal_metadata_), 54 | ~0u, // no _extensions_ 55 | ~0u, // no _oneof_case_ 56 | ~0u, // no _weak_field_map_ 57 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseError, error_code_), 58 | PROTOBUF_FIELD_OFFSET(::happy::utils::network::ResponseError, error_string_), 59 | 1, 60 | 0, 61 | }; 62 | static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 63 | { 0, 7, sizeof(::happy::utils::network::ResponseError)}, 64 | }; 65 | 66 | static ::google::protobuf::Message const * const file_default_instances[] = { 67 | reinterpret_cast(&::happy::utils::network::_ResponseError_default_instance_), 68 | }; 69 | 70 | ::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_response_5ferror_2eproto = { 71 | {}, AddDescriptors_response_5ferror_2eproto, "response_error.proto", schemas, 72 | file_default_instances, TableStruct_response_5ferror_2eproto::offsets, 73 | file_level_metadata_response_5ferror_2eproto, 1, file_level_enum_descriptors_response_5ferror_2eproto, file_level_service_descriptors_response_5ferror_2eproto, 74 | }; 75 | 76 | const char descriptor_table_protodef_response_5ferror_2eproto[] = 77 | "\n\024response_error.proto\022\023happy.utils.netw" 78 | "ork\"9\n\rResponseError\022\022\n\nerror_code\030\001 \002(\005" 79 | "\022\024\n\014error_string\030\002 \002(\t" 80 | ; 81 | ::google::protobuf::internal::DescriptorTable descriptor_table_response_5ferror_2eproto = { 82 | false, InitDefaults_response_5ferror_2eproto, 83 | descriptor_table_protodef_response_5ferror_2eproto, 84 | "response_error.proto", &assign_descriptors_table_response_5ferror_2eproto, 102, 85 | }; 86 | 87 | void AddDescriptors_response_5ferror_2eproto() { 88 | static constexpr ::google::protobuf::internal::InitFunc deps[1] = 89 | { 90 | }; 91 | ::google::protobuf::internal::AddDescriptors(&descriptor_table_response_5ferror_2eproto, deps, 0); 92 | } 93 | 94 | // Force running AddDescriptors() at dynamic initialization time. 95 | static bool dynamic_init_dummy_response_5ferror_2eproto = []() { AddDescriptors_response_5ferror_2eproto(); return true; }(); 96 | namespace happy { 97 | namespace utils { 98 | namespace network { 99 | 100 | // =================================================================== 101 | 102 | void ResponseError::InitAsDefaultInstance() { 103 | } 104 | class ResponseError::HasBitSetters { 105 | public: 106 | static void set_has_error_code(ResponseError* msg) { 107 | msg->_has_bits_[0] |= 0x00000002u; 108 | } 109 | static void set_has_error_string(ResponseError* msg) { 110 | msg->_has_bits_[0] |= 0x00000001u; 111 | } 112 | }; 113 | 114 | #if !defined(_MSC_VER) || _MSC_VER >= 1900 115 | const int ResponseError::kErrorCodeFieldNumber; 116 | const int ResponseError::kErrorStringFieldNumber; 117 | #endif // !defined(_MSC_VER) || _MSC_VER >= 1900 118 | 119 | ResponseError::ResponseError() 120 | : ::google::protobuf::Message(), _internal_metadata_(nullptr) { 121 | SharedCtor(); 122 | // @@protoc_insertion_point(constructor:happy.utils.network.ResponseError) 123 | } 124 | ResponseError::ResponseError(const ResponseError& from) 125 | : ::google::protobuf::Message(), 126 | _internal_metadata_(nullptr), 127 | _has_bits_(from._has_bits_) { 128 | _internal_metadata_.MergeFrom(from._internal_metadata_); 129 | error_string_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 130 | if (from.has_error_string()) { 131 | error_string_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_string_); 132 | } 133 | error_code_ = from.error_code_; 134 | // @@protoc_insertion_point(copy_constructor:happy.utils.network.ResponseError) 135 | } 136 | 137 | void ResponseError::SharedCtor() { 138 | ::google::protobuf::internal::InitSCC( 139 | &scc_info_ResponseError_response_5ferror_2eproto.base); 140 | error_string_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 141 | error_code_ = 0; 142 | } 143 | 144 | ResponseError::~ResponseError() { 145 | // @@protoc_insertion_point(destructor:happy.utils.network.ResponseError) 146 | SharedDtor(); 147 | } 148 | 149 | void ResponseError::SharedDtor() { 150 | error_string_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 151 | } 152 | 153 | void ResponseError::SetCachedSize(int size) const { 154 | _cached_size_.Set(size); 155 | } 156 | const ResponseError& ResponseError::default_instance() { 157 | ::google::protobuf::internal::InitSCC(&::scc_info_ResponseError_response_5ferror_2eproto.base); 158 | return *internal_default_instance(); 159 | } 160 | 161 | 162 | void ResponseError::Clear() { 163 | // @@protoc_insertion_point(message_clear_start:happy.utils.network.ResponseError) 164 | ::google::protobuf::uint32 cached_has_bits = 0; 165 | // Prevent compiler warnings about cached_has_bits being unused 166 | (void) cached_has_bits; 167 | 168 | cached_has_bits = _has_bits_[0]; 169 | if (cached_has_bits & 0x00000001u) { 170 | error_string_.ClearNonDefaultToEmptyNoArena(); 171 | } 172 | error_code_ = 0; 173 | _has_bits_.Clear(); 174 | _internal_metadata_.Clear(); 175 | } 176 | 177 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 178 | const char* ResponseError::_InternalParse(const char* begin, const char* end, void* object, 179 | ::google::protobuf::internal::ParseContext* ctx) { 180 | auto msg = static_cast(object); 181 | ::google::protobuf::int32 size; (void)size; 182 | int depth; (void)depth; 183 | ::google::protobuf::uint32 tag; 184 | ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; 185 | auto ptr = begin; 186 | while (ptr < end) { 187 | ptr = ::google::protobuf::io::Parse32(ptr, &tag); 188 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 189 | switch (tag >> 3) { 190 | // required int32 error_code = 1; 191 | case 1: { 192 | if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual; 193 | ::google::protobuf::uint64 val; 194 | ptr = ::google::protobuf::io::Parse64(ptr, &val); 195 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 196 | ::google::protobuf::int32 value = val; 197 | msg->set_error_code(value); 198 | break; 199 | } 200 | // required string error_string = 2; 201 | case 2: { 202 | if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual; 203 | ptr = ::google::protobuf::io::ReadSize(ptr, &size); 204 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); 205 | ctx->extra_parse_data().SetFieldName("happy.utils.network.ResponseError.error_string"); 206 | auto str = msg->mutable_error_string(); 207 | if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) { 208 | object = str; 209 | str->clear(); 210 | str->reserve(size); 211 | parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8Verify; 212 | goto len_delim_till_end; 213 | } 214 | GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8Verify(ptr, size, ctx)); 215 | ::google::protobuf::internal::InlineGreedyStringParser(str, ptr, size, ctx); 216 | ptr += size; 217 | break; 218 | } 219 | default: { 220 | handle_unusual: 221 | if ((tag & 7) == 4 || tag == 0) { 222 | ctx->EndGroup(tag); 223 | return ptr; 224 | } 225 | auto res = UnknownFieldParse(tag, {_InternalParse, msg}, 226 | ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); 227 | ptr = res.first; 228 | GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); 229 | if (res.second) return ptr; 230 | } 231 | } // switch 232 | } // while 233 | return ptr; 234 | len_delim_till_end: 235 | return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, 236 | {parser_till_end, object}, size); 237 | } 238 | #else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 239 | bool ResponseError::MergePartialFromCodedStream( 240 | ::google::protobuf::io::CodedInputStream* input) { 241 | #define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure 242 | ::google::protobuf::uint32 tag; 243 | // @@protoc_insertion_point(parse_start:happy.utils.network.ResponseError) 244 | for (;;) { 245 | ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); 246 | tag = p.first; 247 | if (!p.second) goto handle_unusual; 248 | switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 249 | // required int32 error_code = 1; 250 | case 1: { 251 | if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) { 252 | HasBitSetters::set_has_error_code(this); 253 | DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< 254 | ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 255 | input, &error_code_))); 256 | } else { 257 | goto handle_unusual; 258 | } 259 | break; 260 | } 261 | 262 | // required string error_string = 2; 263 | case 2: { 264 | if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) { 265 | DO_(::google::protobuf::internal::WireFormatLite::ReadString( 266 | input, this->mutable_error_string())); 267 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 268 | this->error_string().data(), static_cast(this->error_string().length()), 269 | ::google::protobuf::internal::WireFormat::PARSE, 270 | "happy.utils.network.ResponseError.error_string"); 271 | } else { 272 | goto handle_unusual; 273 | } 274 | break; 275 | } 276 | 277 | default: { 278 | handle_unusual: 279 | if (tag == 0) { 280 | goto success; 281 | } 282 | DO_(::google::protobuf::internal::WireFormat::SkipField( 283 | input, tag, _internal_metadata_.mutable_unknown_fields())); 284 | break; 285 | } 286 | } 287 | } 288 | success: 289 | // @@protoc_insertion_point(parse_success:happy.utils.network.ResponseError) 290 | return true; 291 | failure: 292 | // @@protoc_insertion_point(parse_failure:happy.utils.network.ResponseError) 293 | return false; 294 | #undef DO_ 295 | } 296 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 297 | 298 | void ResponseError::SerializeWithCachedSizes( 299 | ::google::protobuf::io::CodedOutputStream* output) const { 300 | // @@protoc_insertion_point(serialize_start:happy.utils.network.ResponseError) 301 | ::google::protobuf::uint32 cached_has_bits = 0; 302 | (void) cached_has_bits; 303 | 304 | cached_has_bits = _has_bits_[0]; 305 | // required int32 error_code = 1; 306 | if (cached_has_bits & 0x00000002u) { 307 | ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->error_code(), output); 308 | } 309 | 310 | // required string error_string = 2; 311 | if (cached_has_bits & 0x00000001u) { 312 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 313 | this->error_string().data(), static_cast(this->error_string().length()), 314 | ::google::protobuf::internal::WireFormat::SERIALIZE, 315 | "happy.utils.network.ResponseError.error_string"); 316 | ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 317 | 2, this->error_string(), output); 318 | } 319 | 320 | if (_internal_metadata_.have_unknown_fields()) { 321 | ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 322 | _internal_metadata_.unknown_fields(), output); 323 | } 324 | // @@protoc_insertion_point(serialize_end:happy.utils.network.ResponseError) 325 | } 326 | 327 | ::google::protobuf::uint8* ResponseError::InternalSerializeWithCachedSizesToArray( 328 | ::google::protobuf::uint8* target) const { 329 | // @@protoc_insertion_point(serialize_to_array_start:happy.utils.network.ResponseError) 330 | ::google::protobuf::uint32 cached_has_bits = 0; 331 | (void) cached_has_bits; 332 | 333 | cached_has_bits = _has_bits_[0]; 334 | // required int32 error_code = 1; 335 | if (cached_has_bits & 0x00000002u) { 336 | target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->error_code(), target); 337 | } 338 | 339 | // required string error_string = 2; 340 | if (cached_has_bits & 0x00000001u) { 341 | ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( 342 | this->error_string().data(), static_cast(this->error_string().length()), 343 | ::google::protobuf::internal::WireFormat::SERIALIZE, 344 | "happy.utils.network.ResponseError.error_string"); 345 | target = 346 | ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 347 | 2, this->error_string(), target); 348 | } 349 | 350 | if (_internal_metadata_.have_unknown_fields()) { 351 | target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 352 | _internal_metadata_.unknown_fields(), target); 353 | } 354 | // @@protoc_insertion_point(serialize_to_array_end:happy.utils.network.ResponseError) 355 | return target; 356 | } 357 | 358 | size_t ResponseError::RequiredFieldsByteSizeFallback() const { 359 | // @@protoc_insertion_point(required_fields_byte_size_fallback_start:happy.utils.network.ResponseError) 360 | size_t total_size = 0; 361 | 362 | if (has_error_string()) { 363 | // required string error_string = 2; 364 | total_size += 1 + 365 | ::google::protobuf::internal::WireFormatLite::StringSize( 366 | this->error_string()); 367 | } 368 | 369 | if (has_error_code()) { 370 | // required int32 error_code = 1; 371 | total_size += 1 + 372 | ::google::protobuf::internal::WireFormatLite::Int32Size( 373 | this->error_code()); 374 | } 375 | 376 | return total_size; 377 | } 378 | size_t ResponseError::ByteSizeLong() const { 379 | // @@protoc_insertion_point(message_byte_size_start:happy.utils.network.ResponseError) 380 | size_t total_size = 0; 381 | 382 | if (_internal_metadata_.have_unknown_fields()) { 383 | total_size += 384 | ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 385 | _internal_metadata_.unknown_fields()); 386 | } 387 | if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. 388 | // required string error_string = 2; 389 | total_size += 1 + 390 | ::google::protobuf::internal::WireFormatLite::StringSize( 391 | this->error_string()); 392 | 393 | // required int32 error_code = 1; 394 | total_size += 1 + 395 | ::google::protobuf::internal::WireFormatLite::Int32Size( 396 | this->error_code()); 397 | 398 | } else { 399 | total_size += RequiredFieldsByteSizeFallback(); 400 | } 401 | ::google::protobuf::uint32 cached_has_bits = 0; 402 | // Prevent compiler warnings about cached_has_bits being unused 403 | (void) cached_has_bits; 404 | 405 | int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); 406 | SetCachedSize(cached_size); 407 | return total_size; 408 | } 409 | 410 | void ResponseError::MergeFrom(const ::google::protobuf::Message& from) { 411 | // @@protoc_insertion_point(generalized_merge_from_start:happy.utils.network.ResponseError) 412 | GOOGLE_DCHECK_NE(&from, this); 413 | const ResponseError* source = 414 | ::google::protobuf::DynamicCastToGenerated( 415 | &from); 416 | if (source == nullptr) { 417 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:happy.utils.network.ResponseError) 418 | ::google::protobuf::internal::ReflectionOps::Merge(from, this); 419 | } else { 420 | // @@protoc_insertion_point(generalized_merge_from_cast_success:happy.utils.network.ResponseError) 421 | MergeFrom(*source); 422 | } 423 | } 424 | 425 | void ResponseError::MergeFrom(const ResponseError& from) { 426 | // @@protoc_insertion_point(class_specific_merge_from_start:happy.utils.network.ResponseError) 427 | GOOGLE_DCHECK_NE(&from, this); 428 | _internal_metadata_.MergeFrom(from._internal_metadata_); 429 | ::google::protobuf::uint32 cached_has_bits = 0; 430 | (void) cached_has_bits; 431 | 432 | cached_has_bits = from._has_bits_[0]; 433 | if (cached_has_bits & 0x00000003u) { 434 | if (cached_has_bits & 0x00000001u) { 435 | _has_bits_[0] |= 0x00000001u; 436 | error_string_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_string_); 437 | } 438 | if (cached_has_bits & 0x00000002u) { 439 | error_code_ = from.error_code_; 440 | } 441 | _has_bits_[0] |= cached_has_bits; 442 | } 443 | } 444 | 445 | void ResponseError::CopyFrom(const ::google::protobuf::Message& from) { 446 | // @@protoc_insertion_point(generalized_copy_from_start:happy.utils.network.ResponseError) 447 | if (&from == this) return; 448 | Clear(); 449 | MergeFrom(from); 450 | } 451 | 452 | void ResponseError::CopyFrom(const ResponseError& from) { 453 | // @@protoc_insertion_point(class_specific_copy_from_start:happy.utils.network.ResponseError) 454 | if (&from == this) return; 455 | Clear(); 456 | MergeFrom(from); 457 | } 458 | 459 | bool ResponseError::IsInitialized() const { 460 | if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; 461 | return true; 462 | } 463 | 464 | void ResponseError::Swap(ResponseError* other) { 465 | if (other == this) return; 466 | InternalSwap(other); 467 | } 468 | void ResponseError::InternalSwap(ResponseError* other) { 469 | using std::swap; 470 | _internal_metadata_.Swap(&other->_internal_metadata_); 471 | swap(_has_bits_[0], other->_has_bits_[0]); 472 | error_string_.Swap(&other->error_string_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), 473 | GetArenaNoVirtual()); 474 | swap(error_code_, other->error_code_); 475 | } 476 | 477 | ::google::protobuf::Metadata ResponseError::GetMetadata() const { 478 | ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_response_5ferror_2eproto); 479 | return ::file_level_metadata_response_5ferror_2eproto[kIndexInFileMessages]; 480 | } 481 | 482 | 483 | // @@protoc_insertion_point(namespace_scope) 484 | } // namespace network 485 | } // namespace utils 486 | } // namespace happy 487 | namespace google { 488 | namespace protobuf { 489 | template<> PROTOBUF_NOINLINE ::happy::utils::network::ResponseError* Arena::CreateMaybeMessage< ::happy::utils::network::ResponseError >(Arena* arena) { 490 | return Arena::CreateInternal< ::happy::utils::network::ResponseError >(arena); 491 | } 492 | } // namespace protobuf 493 | } // namespace google 494 | 495 | // @@protoc_insertion_point(global_scope) 496 | #include 497 | -------------------------------------------------------------------------------- /src/network/response_error.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: response_error.proto 3 | 4 | #ifndef PROTOBUF_INCLUDED_response_5ferror_2eproto 5 | #define PROTOBUF_INCLUDED_response_5ferror_2eproto 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #if PROTOBUF_VERSION < 3006001 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3006001 < PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include // IWYU pragma: export 32 | #include // IWYU pragma: export 33 | #include 34 | // @@protoc_insertion_point(includes) 35 | #include 36 | #define PROTOBUF_INTERNAL_EXPORT_response_5ferror_2eproto 37 | 38 | // Internal implementation detail -- do not use these members. 39 | struct TableStruct_response_5ferror_2eproto { 40 | static const ::google::protobuf::internal::ParseTableField entries[] 41 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 42 | static const ::google::protobuf::internal::AuxillaryParseTableField aux[] 43 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 44 | static const ::google::protobuf::internal::ParseTable schema[1] 45 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 46 | static const ::google::protobuf::internal::FieldMetadata field_metadata[]; 47 | static const ::google::protobuf::internal::SerializationTable serialization_table[]; 48 | static const ::google::protobuf::uint32 offsets[]; 49 | }; 50 | void AddDescriptors_response_5ferror_2eproto(); 51 | namespace happy { 52 | namespace utils { 53 | namespace network { 54 | class ResponseError; 55 | class ResponseErrorDefaultTypeInternal; 56 | extern ResponseErrorDefaultTypeInternal _ResponseError_default_instance_; 57 | } // namespace network 58 | } // namespace utils 59 | } // namespace happy 60 | namespace google { 61 | namespace protobuf { 62 | template<> ::happy::utils::network::ResponseError* Arena::CreateMaybeMessage<::happy::utils::network::ResponseError>(Arena*); 63 | } // namespace protobuf 64 | } // namespace google 65 | namespace happy { 66 | namespace utils { 67 | namespace network { 68 | 69 | // =================================================================== 70 | 71 | class ResponseError : 72 | public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:happy.utils.network.ResponseError) */ { 73 | public: 74 | ResponseError(); 75 | virtual ~ResponseError(); 76 | 77 | ResponseError(const ResponseError& from); 78 | 79 | inline ResponseError& operator=(const ResponseError& from) { 80 | CopyFrom(from); 81 | return *this; 82 | } 83 | #if LANG_CXX11 84 | ResponseError(ResponseError&& from) noexcept 85 | : ResponseError() { 86 | *this = ::std::move(from); 87 | } 88 | 89 | inline ResponseError& operator=(ResponseError&& from) noexcept { 90 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 91 | if (this != &from) InternalSwap(&from); 92 | } else { 93 | CopyFrom(from); 94 | } 95 | return *this; 96 | } 97 | #endif 98 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 99 | return _internal_metadata_.unknown_fields(); 100 | } 101 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 102 | return _internal_metadata_.mutable_unknown_fields(); 103 | } 104 | 105 | static const ::google::protobuf::Descriptor* descriptor() { 106 | return default_instance().GetDescriptor(); 107 | } 108 | static const ResponseError& default_instance(); 109 | 110 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 111 | static inline const ResponseError* internal_default_instance() { 112 | return reinterpret_cast( 113 | &_ResponseError_default_instance_); 114 | } 115 | static constexpr int kIndexInFileMessages = 116 | 0; 117 | 118 | void Swap(ResponseError* other); 119 | friend void swap(ResponseError& a, ResponseError& b) { 120 | a.Swap(&b); 121 | } 122 | 123 | // implements Message ---------------------------------------------- 124 | 125 | inline ResponseError* New() const final { 126 | return CreateMaybeMessage(nullptr); 127 | } 128 | 129 | ResponseError* New(::google::protobuf::Arena* arena) const final { 130 | return CreateMaybeMessage(arena); 131 | } 132 | void CopyFrom(const ::google::protobuf::Message& from) final; 133 | void MergeFrom(const ::google::protobuf::Message& from) final; 134 | void CopyFrom(const ResponseError& from); 135 | void MergeFrom(const ResponseError& from); 136 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 137 | bool IsInitialized() const final; 138 | 139 | size_t ByteSizeLong() const final; 140 | #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 141 | static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); 142 | ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } 143 | #else 144 | bool MergePartialFromCodedStream( 145 | ::google::protobuf::io::CodedInputStream* input) final; 146 | #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER 147 | void SerializeWithCachedSizes( 148 | ::google::protobuf::io::CodedOutputStream* output) const final; 149 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 150 | ::google::protobuf::uint8* target) const final; 151 | int GetCachedSize() const final { return _cached_size_.Get(); } 152 | 153 | private: 154 | void SharedCtor(); 155 | void SharedDtor(); 156 | void SetCachedSize(int size) const final; 157 | void InternalSwap(ResponseError* other); 158 | private: 159 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 160 | return nullptr; 161 | } 162 | inline void* MaybeArenaPtr() const { 163 | return nullptr; 164 | } 165 | public: 166 | 167 | ::google::protobuf::Metadata GetMetadata() const final; 168 | 169 | // nested types ---------------------------------------------------- 170 | 171 | // accessors ------------------------------------------------------- 172 | 173 | // required string error_string = 2; 174 | bool has_error_string() const; 175 | void clear_error_string(); 176 | static const int kErrorStringFieldNumber = 2; 177 | const ::std::string& error_string() const; 178 | void set_error_string(const ::std::string& value); 179 | #if LANG_CXX11 180 | void set_error_string(::std::string&& value); 181 | #endif 182 | void set_error_string(const char* value); 183 | void set_error_string(const char* value, size_t size); 184 | ::std::string* mutable_error_string(); 185 | ::std::string* release_error_string(); 186 | void set_allocated_error_string(::std::string* error_string); 187 | 188 | // required int32 error_code = 1; 189 | bool has_error_code() const; 190 | void clear_error_code(); 191 | static const int kErrorCodeFieldNumber = 1; 192 | ::google::protobuf::int32 error_code() const; 193 | void set_error_code(::google::protobuf::int32 value); 194 | 195 | // @@protoc_insertion_point(class_scope:happy.utils.network.ResponseError) 196 | private: 197 | class HasBitSetters; 198 | 199 | // helper for ByteSizeLong() 200 | size_t RequiredFieldsByteSizeFallback() const; 201 | 202 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 203 | ::google::protobuf::internal::HasBits<1> _has_bits_; 204 | mutable ::google::protobuf::internal::CachedSize _cached_size_; 205 | ::google::protobuf::internal::ArenaStringPtr error_string_; 206 | ::google::protobuf::int32 error_code_; 207 | friend struct ::TableStruct_response_5ferror_2eproto; 208 | }; 209 | // =================================================================== 210 | 211 | 212 | // =================================================================== 213 | 214 | #ifdef __GNUC__ 215 | #pragma GCC diagnostic push 216 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 217 | #endif // __GNUC__ 218 | // ResponseError 219 | 220 | // required int32 error_code = 1; 221 | inline bool ResponseError::has_error_code() const { 222 | return (_has_bits_[0] & 0x00000002u) != 0; 223 | } 224 | inline void ResponseError::clear_error_code() { 225 | error_code_ = 0; 226 | _has_bits_[0] &= ~0x00000002u; 227 | } 228 | inline ::google::protobuf::int32 ResponseError::error_code() const { 229 | // @@protoc_insertion_point(field_get:happy.utils.network.ResponseError.error_code) 230 | return error_code_; 231 | } 232 | inline void ResponseError::set_error_code(::google::protobuf::int32 value) { 233 | _has_bits_[0] |= 0x00000002u; 234 | error_code_ = value; 235 | // @@protoc_insertion_point(field_set:happy.utils.network.ResponseError.error_code) 236 | } 237 | 238 | // required string error_string = 2; 239 | inline bool ResponseError::has_error_string() const { 240 | return (_has_bits_[0] & 0x00000001u) != 0; 241 | } 242 | inline void ResponseError::clear_error_string() { 243 | error_string_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 244 | _has_bits_[0] &= ~0x00000001u; 245 | } 246 | inline const ::std::string& ResponseError::error_string() const { 247 | // @@protoc_insertion_point(field_get:happy.utils.network.ResponseError.error_string) 248 | return error_string_.GetNoArena(); 249 | } 250 | inline void ResponseError::set_error_string(const ::std::string& value) { 251 | _has_bits_[0] |= 0x00000001u; 252 | error_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 253 | // @@protoc_insertion_point(field_set:happy.utils.network.ResponseError.error_string) 254 | } 255 | #if LANG_CXX11 256 | inline void ResponseError::set_error_string(::std::string&& value) { 257 | _has_bits_[0] |= 0x00000001u; 258 | error_string_.SetNoArena( 259 | &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 260 | // @@protoc_insertion_point(field_set_rvalue:happy.utils.network.ResponseError.error_string) 261 | } 262 | #endif 263 | inline void ResponseError::set_error_string(const char* value) { 264 | GOOGLE_DCHECK(value != nullptr); 265 | _has_bits_[0] |= 0x00000001u; 266 | error_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 267 | // @@protoc_insertion_point(field_set_char:happy.utils.network.ResponseError.error_string) 268 | } 269 | inline void ResponseError::set_error_string(const char* value, size_t size) { 270 | _has_bits_[0] |= 0x00000001u; 271 | error_string_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 272 | ::std::string(reinterpret_cast(value), size)); 273 | // @@protoc_insertion_point(field_set_pointer:happy.utils.network.ResponseError.error_string) 274 | } 275 | inline ::std::string* ResponseError::mutable_error_string() { 276 | _has_bits_[0] |= 0x00000001u; 277 | // @@protoc_insertion_point(field_mutable:happy.utils.network.ResponseError.error_string) 278 | return error_string_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 279 | } 280 | inline ::std::string* ResponseError::release_error_string() { 281 | // @@protoc_insertion_point(field_release:happy.utils.network.ResponseError.error_string) 282 | if (!has_error_string()) { 283 | return nullptr; 284 | } 285 | _has_bits_[0] &= ~0x00000001u; 286 | return error_string_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 287 | } 288 | inline void ResponseError::set_allocated_error_string(::std::string* error_string) { 289 | if (error_string != nullptr) { 290 | _has_bits_[0] |= 0x00000001u; 291 | } else { 292 | _has_bits_[0] &= ~0x00000001u; 293 | } 294 | error_string_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error_string); 295 | // @@protoc_insertion_point(field_set_allocated:happy.utils.network.ResponseError.error_string) 296 | } 297 | 298 | #ifdef __GNUC__ 299 | #pragma GCC diagnostic pop 300 | #endif // __GNUC__ 301 | 302 | // @@protoc_insertion_point(namespace_scope) 303 | 304 | } // namespace network 305 | } // namespace utils 306 | } // namespace happy 307 | 308 | // @@protoc_insertion_point(global_scope) 309 | 310 | #include 311 | #endif // PROTOBUF_INCLUDED_response_5ferror_2eproto 312 | -------------------------------------------------------------------------------- /src/network/response_error.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package happy.utils.network; 3 | 4 | message ResponseError 5 | { 6 | required int32 error_code = 1; 7 | required string error_string = 2; 8 | } -------------------------------------------------------------------------------- /src/network/server_message_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace happy 6 | { 7 | namespace utils 8 | { 9 | namespace network 10 | { 11 | class ServerMessageFactory : public UtilMessageFactory 12 | { 13 | 14 | public: 15 | ServerMessageFactory(const string& session_id = "", const bool is_read_print = false 16 | , NetworkConvert* network_convert = ProtoNetworkConvert::singleton::GetInstance()) 17 | : UtilMessageFactory(network_convert, is_read_print, true, session_id) {} 18 | }; 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/network/util_message_factory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace happy 6 | { 7 | namespace utils 8 | { 9 | namespace network 10 | { 11 | UtilMessageFactory::UtilMessageFactory(NetworkConvert* network_convert 12 | , const bool is_read_print, const bool is_response, const string& session_id) 13 | : happy::asio::ip::MessageFactory(session_id), network_convert_(network_convert), is_read_print_(is_read_print), is_response_(is_response) {} 14 | 15 | void UtilMessageFactory::PrintMessage(const shared_ptr message) 16 | { 17 | if (is_read_print_) 18 | { 19 | OUTPUT << "receive message: " << message->GetDescriptor()->full_name() << endl; 20 | if (message->ByteSize() && message->ByteSize() < 1024) 21 | { 22 | OUTPUT << message->DebugString(); 23 | } 24 | } 25 | } 26 | 27 | shared_ptr UtilMessageFactory::Produce(const shared_ptr news) 28 | { 29 | auto it = handler_.find(news->message->GetDescriptor()->full_name()); 30 | if (handler_.end() == it) 31 | { 32 | return nullptr; 33 | } 34 | return it->second(news->message); 35 | } 36 | 37 | bool UtilMessageFactory::IsConsumedForRead(const uint8_t* buffer, const size_t& length, size_t& deal_length, bool& has_package) 38 | { 39 | return network_convert_->IsConsumed(buffer, length, deal_length, has_package); 40 | } 41 | 42 | bool UtilMessageFactory::HandleRead(const uint8_t* buffer, const size_t& length, string& response) 43 | { 44 | auto news = network_convert_->ToProto(buffer, length); 45 | shared_ptr response_message = nullptr; 46 | if (nullptr == news) 47 | { 48 | return false; 49 | } 50 | do 51 | { 52 | if (nullptr == news->message) 53 | { 54 | auto response_error = make_shared (); 55 | response_error->set_error_code(9); 56 | response_error->set_error_string(network_convert_->GetLastError()); 57 | response_message = response_error; 58 | } 59 | else 60 | { 61 | PrintMessage(news->message); 62 | response_message = Produce(news); 63 | if (!is_response_) 64 | { 65 | break; 66 | } 67 | if (nullptr == response_message) 68 | { 69 | auto response_error = make_shared (); 70 | response_error->set_error_code(1); 71 | response_error->set_error_string("Unknown error"); 72 | response_message = response_error; 73 | } 74 | } 75 | if (is_read_print_) 76 | { 77 | OUTPUT << "Send response: " << response_message->GetDescriptor()->full_name() << endl; 78 | } 79 | network_convert_->ToNetwork(response_message, response, news->session_id); 80 | } while (false); 81 | 82 | return true; 83 | } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/network/util_message_factory.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangziwen333/happy-ip/f8a1ae787f85c0131c4c8e9c782d64eadd1b09f7/src/network/util_message_factory.h --------------------------------------------------------------------------------