├── .gitignore ├── 3rd ├── README.md ├── aes │ ├── aes.c │ └── aes.h ├── base64.hpp ├── md5.hpp ├── protobuf │ └── google │ │ ├── COPYING.txt │ │ ├── protobuf │ │ ├── compiler │ │ │ ├── code_generator.h │ │ │ ├── command_line_interface.h │ │ │ ├── cpp │ │ │ │ └── cpp_generator.h │ │ │ ├── importer.h │ │ │ ├── java │ │ │ │ └── java_generator.h │ │ │ ├── parser.h │ │ │ ├── plugin.h │ │ │ └── python │ │ │ │ └── python_generator.h │ │ ├── descriptor.h │ │ ├── descriptor.pb.h │ │ ├── descriptor_database.h │ │ ├── dynamic_message.h │ │ ├── extension_set.h │ │ ├── generated_enum_reflection.h │ │ ├── generated_message_reflection.h │ │ ├── generated_message_util.h │ │ ├── io │ │ │ ├── coded_stream.h │ │ │ ├── gzip_stream.h │ │ │ ├── printer.h │ │ │ ├── tokenizer.h │ │ │ ├── zero_copy_stream.h │ │ │ ├── zero_copy_stream_impl.h │ │ │ └── zero_copy_stream_impl_lite.h │ │ ├── message.h │ │ ├── message_lite.h │ │ ├── reflection_ops.h │ │ ├── repeated_field.h │ │ ├── service.h │ │ ├── stubs │ │ │ ├── atomicops.h │ │ │ ├── atomicops_internals_x86_msvc.h │ │ │ ├── common.h │ │ │ ├── once.h │ │ │ ├── platform_macros.h │ │ │ ├── template_util.h │ │ │ └── type_traits.h │ │ ├── text_format.h │ │ ├── unknown_field_set.h │ │ ├── wire_format.h │ │ ├── wire_format_lite.h │ │ └── wire_format_lite_inl.h │ │ ├── protoc-readme.txt │ │ └── protoc.exe ├── rapidjson │ ├── allocators.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── filereadstream.h │ ├── filestream.h │ ├── filewritestream.h │ ├── internal │ │ ├── pow10.h │ │ ├── stack.h │ │ └── strfunc.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── stringbuffer.h │ └── writer.h ├── rapidxml │ ├── license.txt │ ├── manual.zip │ ├── rapidxml.hpp │ ├── rapidxml_iterators.hpp │ ├── rapidxml_print.hpp │ └── rapidxml_utils.hpp ├── sha1.hpp └── xml2json.h ├── README.md ├── base ├── atomic_integer.h ├── common.h ├── condition.h ├── debug_win.h ├── event.h ├── file_tools.h ├── ini_file.h ├── ip_addr_util.h ├── mailslot.h ├── mem_pool.h ├── mutex.h ├── object_pool.h ├── observer.h ├── read_write_lock.h ├── ring_buffer.h ├── scoped_ptr.h ├── semaphore.h ├── shared_ptr.h ├── singleton.h ├── stack.h ├── string_unicode.h ├── string_util.h ├── sys_util.h ├── table.h ├── test │ ├── atomic_integer_unittest.cc │ ├── condition_untitest.cc │ ├── debug_win_unittest.cc │ ├── mem_pool_unittest.cc │ ├── object_pool_unittest.cc │ ├── stack_unittest.cc │ ├── thread_win_unittest.cc │ └── timestamp_unittest.cc ├── thread.h ├── thread_pool.h ├── thread_util.h ├── time_util.h ├── timestamp.h └── uuid.h ├── db ├── Makefile ├── README.md ├── mysql_connection.h ├── mysql_result_set.h ├── mysql_util.h └── test.cc ├── log ├── Makefile ├── README.md ├── log_file.cc ├── log_file.h ├── log_stdout.cc ├── log_stdout.h ├── log_syslog.cc ├── log_syslog.h ├── logging.cc ├── logging.h └── testLog.cc ├── net ├── Makefile ├── README.md ├── acceptor.cc ├── acceptor.h ├── asio │ ├── buffer.h │ ├── callbacks.h │ ├── net_asio.h │ ├── tcp_client.cc │ ├── tcp_client.h │ ├── tcp_client_test.cc │ ├── tcp_connection.cc │ ├── tcp_connection.h │ ├── tcp_server.cc │ ├── tcp_server.h │ └── tcp_server_test.cc ├── buffer.h ├── callbacks.h ├── client_test.cc ├── epoll_event.cc ├── epoll_event.h ├── event.h ├── event_loop.cc ├── event_loop.h ├── inet_address.h ├── iocp_event.cc ├── iocp_event.h ├── server_test.cc ├── socket.cc ├── socket.h ├── tcp_client.cc ├── tcp_client.h ├── tcp_connection.cc ├── tcp_connection.h ├── tcp_server.cc └── tcp_server.h ├── project ├── IocpDemo │ ├── IocpDemo.vcxproj │ ├── IocpDemo.vcxproj.filters │ ├── IocpDemo.vcxproj.user │ └── main.cc ├── NetClient │ ├── NetClient.vcxproj │ ├── NetClient.vcxproj.filters │ ├── NetClient.vcxproj.user │ └── main.cc ├── TestLog │ ├── ReadMe.txt │ ├── TestLog.cpp │ ├── TestLog.vcproj │ ├── TestLog.vcxproj │ ├── TestLog.vcxproj.filters │ ├── TestLog.vcxproj.user │ ├── stdafx.cpp │ └── stdafx.h ├── TheFoxFramework.sln ├── libthefox │ ├── libthefox.vcxproj │ ├── libthefox.vcxproj.filters │ └── libthefox.vcxproj.user └── removejunk.bat ├── rpc ├── README.md ├── c.bat ├── common.h ├── oneway_dispatcher.h ├── protoc.exe ├── rpc.pb.cc ├── rpc.pb.h ├── rpc.proto ├── rpc_channel.cc ├── rpc_channel.h ├── rpc_client.cc ├── rpc_client.h ├── rpc_codec.h ├── rpc_controller.cc ├── rpc_controller.h ├── rpc_server.cc ├── rpc_server.h ├── rpc_service.cc ├── rpc_service.h ├── rpc_service_manager.cc ├── rpc_service_manager.h ├── task.h ├── task_manager.cc ├── task_manager.h └── test │ ├── echo.pb.cc │ ├── echo.pb.h │ ├── echo.proto │ ├── testrpcclient.cc │ └── testrpcserver.cc └── snmp ├── Makefile ├── README.md ├── Snmp.h └── test.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.aps 3 | *.idb 4 | *.ncp 5 | *.obj 6 | *.pch 7 | *.sbr 8 | *.tmp 9 | *.pdb 10 | *.bsc 11 | *.ilk 12 | *.res 13 | *.ncb 14 | *.opt 15 | *.suo 16 | *.manifest 17 | *.dep 18 | *.log 19 | .DS_Store 20 | -------------------------------------------------------------------------------- /3rd/README.md: -------------------------------------------------------------------------------- 1 | 第三方库 2 | 如有侵权,我将及时删除 -------------------------------------------------------------------------------- /3rd/aes/aes.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | 3 | Copyright 2006-2009 MakingThings 4 | 5 | Licensed under the Apache License, 6 | Version 2.0 (the "License"); you may not use this file except in compliance 7 | with the License. You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software distributed 12 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 13 | CONDITIONS OF ANY KIND, either express or implied. See the License for 14 | the specific language governing permissions and limitations under the License. 15 | 16 | *********************************************************************************/ 17 | 18 | #ifndef AES_H 19 | #define AES_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | int aesEncrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* key); 25 | int aesDecrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password); 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | #endif // AES_H 30 | -------------------------------------------------------------------------------- /3rd/protobuf/google/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright 2008, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Code generated by the Protocol Buffer compiler is owned by the owner 31 | of the input file used when generating it. This code is not 32 | standalone and requires a support library to be linked with it. This 33 | support library is itself covered by the above license. 34 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/compiler/cpp/cpp_generator.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // Generates C++ code for a given .proto file. 36 | 37 | #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ 38 | #define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ 39 | 40 | #include 41 | #include 42 | 43 | namespace google { 44 | namespace protobuf { 45 | namespace compiler { 46 | namespace cpp { 47 | 48 | // CodeGenerator implementation which generates a C++ source file and 49 | // header. If you create your own protocol compiler binary and you want 50 | // it to support C++ output, you can do so by registering an instance of this 51 | // CodeGenerator with the CommandLineInterface in your main() function. 52 | class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { 53 | public: 54 | CppGenerator(); 55 | ~CppGenerator(); 56 | 57 | // implements CodeGenerator ---------------------------------------- 58 | bool Generate(const FileDescriptor* file, 59 | const string& parameter, 60 | GeneratorContext* generator_context, 61 | string* error) const; 62 | 63 | private: 64 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator); 65 | }; 66 | 67 | } // namespace cpp 68 | } // namespace compiler 69 | } // namespace protobuf 70 | 71 | } // namespace google 72 | #endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ 73 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/compiler/java/java_generator.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // Generates Java code for a given .proto file. 36 | 37 | #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ 38 | #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ 39 | 40 | #include 41 | #include 42 | 43 | namespace google { 44 | namespace protobuf { 45 | namespace compiler { 46 | namespace java { 47 | 48 | // CodeGenerator implementation which generates Java code. If you create your 49 | // own protocol compiler binary and you want it to support Java output, you 50 | // can do so by registering an instance of this CodeGenerator with the 51 | // CommandLineInterface in your main() function. 52 | class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { 53 | public: 54 | JavaGenerator(); 55 | ~JavaGenerator(); 56 | 57 | // implements CodeGenerator ---------------------------------------- 58 | bool Generate(const FileDescriptor* file, 59 | const string& parameter, 60 | GeneratorContext* context, 61 | string* error) const; 62 | 63 | private: 64 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator); 65 | }; 66 | 67 | } // namespace java 68 | } // namespace compiler 69 | } // namespace protobuf 70 | 71 | } // namespace google 72 | #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ 73 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/compiler/plugin.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // 33 | // Front-end for protoc code generator plugins written in C++. 34 | // 35 | // To implement a protoc plugin in C++, simply write an implementation of 36 | // CodeGenerator, then create a main() function like: 37 | // int main(int argc, char* argv[]) { 38 | // MyCodeGenerator generator; 39 | // return google::protobuf::compiler::PluginMain(argc, argv, &generator); 40 | // } 41 | // You must link your plugin against libprotobuf and libprotoc. 42 | // 43 | // To get protoc to use the plugin, do one of the following: 44 | // * Place the plugin binary somewhere in the PATH and give it the name 45 | // "protoc-gen-NAME" (replacing "NAME" with the name of your plugin). If you 46 | // then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace 47 | // "NAME" with your plugin's name), protoc will invoke your plugin to generate 48 | // the output, which will be placed in OUT_DIR. 49 | // * Place the plugin binary anywhere, with any name, and pass the --plugin 50 | // parameter to protoc to direct it to your plugin like so: 51 | // protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR 52 | // On Windows, make sure to include the .exe suffix: 53 | // protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR 54 | 55 | #ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ 56 | #define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ 57 | 58 | #include 59 | namespace google { 60 | namespace protobuf { 61 | namespace compiler { 62 | 63 | class CodeGenerator; // code_generator.h 64 | 65 | // Implements main() for a protoc plugin exposing the given code generator. 66 | LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator); 67 | 68 | } // namespace compiler 69 | } // namespace protobuf 70 | 71 | } // namespace google 72 | #endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ 73 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/generated_enum_reflection.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: jasonh@google.com (Jason Hsueh) 32 | // 33 | // This header is logically internal, but is made public because it is used 34 | // from protocol-compiler-generated code, which may reside in other components. 35 | // It provides reflection support for generated enums, and is included in 36 | // generated .pb.h files and should have minimal dependencies. The methods are 37 | // implemented in generated_message_reflection.cc. 38 | 39 | #ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ 40 | #define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ 41 | 42 | #include 43 | 44 | namespace google { 45 | namespace protobuf { 46 | class EnumDescriptor; 47 | } // namespace protobuf 48 | 49 | namespace protobuf { 50 | 51 | // Returns the EnumDescriptor for enum type E, which must be a 52 | // proto-declared enum type. Code generated by the protocol compiler 53 | // will include specializations of this template for each enum type declared. 54 | template 55 | const EnumDescriptor* GetEnumDescriptor(); 56 | 57 | namespace internal { 58 | 59 | // Helper for EnumType_Parse functions: try to parse the string 'name' as an 60 | // enum name of the given type, returning true and filling in value on success, 61 | // or returning false and leaving value unchanged on failure. 62 | LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, 63 | const string& name, 64 | int* value); 65 | 66 | template 67 | bool ParseNamedEnum(const EnumDescriptor* descriptor, 68 | const string& name, 69 | EnumType* value) { 70 | int tmp; 71 | if (!ParseNamedEnum(descriptor, name, &tmp)) return false; 72 | *value = static_cast(tmp); 73 | return true; 74 | } 75 | 76 | // Just a wrapper around printing the name of a value. The main point of this 77 | // function is not to be inlined, so that you can do this without including 78 | // descriptor.h. 79 | LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); 80 | 81 | } // namespace internal 82 | } // namespace protobuf 83 | 84 | } // namespace google 85 | #endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ 86 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/generated_message_util.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // This file contains miscellaneous helper code used by generated code -- 36 | // including lite types -- but which should not be used directly by users. 37 | 38 | #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 39 | #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 40 | 41 | #include 42 | 43 | #include 44 | namespace google { 45 | namespace protobuf { 46 | namespace internal { 47 | 48 | // Annotation for the compiler to emit a deprecation message if a field marked 49 | // with option 'deprecated=true' is used in the code, or for other things in 50 | // generated code which are deprecated. 51 | // 52 | // For internal use in the pb.cc files, deprecation warnings are suppressed 53 | // there. 54 | #undef DEPRECATED_PROTOBUF_FIELD 55 | #define PROTOBUF_DEPRECATED 56 | 57 | 58 | // Constants for special floating point values. 59 | LIBPROTOBUF_EXPORT double Infinity(); 60 | LIBPROTOBUF_EXPORT double NaN(); 61 | 62 | // Constant used for empty default strings. 63 | LIBPROTOBUF_EXPORT extern const ::std::string kEmptyString; 64 | 65 | // Defined in generated_message_reflection.cc -- not actually part of the lite 66 | // library. 67 | // 68 | // TODO(jasonh): The various callers get this declaration from a variety of 69 | // places: probably in most cases repeated_field.h. Clean these up so they all 70 | // get the declaration from this file. 71 | LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); 72 | 73 | } // namespace internal 74 | } // namespace protobuf 75 | 76 | } // namespace google 77 | #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ 78 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/reflection_ops.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // This header is logically internal, but is made public because it is used 36 | // from protocol-compiler-generated code, which may reside in other components. 37 | 38 | #ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__ 39 | #define GOOGLE_PROTOBUF_REFLECTION_OPS_H__ 40 | 41 | #include 42 | #include 43 | 44 | namespace google { 45 | namespace protobuf { 46 | namespace internal { 47 | 48 | // Basic operations that can be performed using reflection. 49 | // These can be used as a cheap way to implement the corresponding 50 | // methods of the Message interface, though they are likely to be 51 | // slower than implementations tailored for the specific message type. 52 | // 53 | // This class should stay limited to operations needed to implement 54 | // the Message interface. 55 | // 56 | // This class is really a namespace that contains only static methods. 57 | class LIBPROTOBUF_EXPORT ReflectionOps { 58 | public: 59 | static void Copy(const Message& from, Message* to); 60 | static void Merge(const Message& from, Message* to); 61 | static void Clear(Message* message); 62 | static bool IsInitialized(const Message& message); 63 | static void DiscardUnknownFields(Message* message); 64 | 65 | // Finds all unset required fields in the message and adds their full 66 | // paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to 67 | // the front of each name. 68 | static void FindInitializationErrors(const Message& message, 69 | const string& prefix, 70 | vector* errors); 71 | 72 | private: 73 | // All methods are static. No need to construct. 74 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps); 75 | }; 76 | 77 | } // namespace internal 78 | } // namespace protobuf 79 | 80 | } // namespace google 81 | #endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__ 82 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protobuf/stubs/platform_macros.h: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2012 Google Inc. All rights reserved. 3 | // http://code.google.com/p/protobuf/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 32 | #define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 33 | 34 | #include 35 | 36 | // Processor architecture detection. For more info on what's defined, see: 37 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx 38 | // http://www.agner.org/optimize/calling_conventions.pdf 39 | // or with gcc, run: "echo | gcc -E -dM -" 40 | #if defined(_M_X64) || defined(__x86_64__) 41 | #define GOOGLE_PROTOBUF_ARCH_X64 1 42 | #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 43 | #elif defined(_M_IX86) || defined(__i386__) 44 | #define GOOGLE_PROTOBUF_ARCH_IA32 1 45 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 46 | #elif defined(__QNX__) 47 | #define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 48 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 49 | #elif defined(__ARMEL__) 50 | #define GOOGLE_PROTOBUF_ARCH_ARM 1 51 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 52 | #elif defined(__MIPSEL__) 53 | #define GOOGLE_PROTOBUF_ARCH_MIPS 1 54 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 55 | #elif defined(__pnacl__) 56 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 57 | #elif defined(__ppc__) 58 | #define GOOGLE_PROTOBUF_ARCH_PPC 1 59 | #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 60 | #else 61 | #error Host architecture was not detected as supported by protobuf 62 | #endif 63 | 64 | #if defined(__APPLE__) 65 | #define GOOGLE_PROTOBUF_OS_APPLE 66 | #elif defined(__native_client__) 67 | #define GOOGLE_PROTOBUF_OS_NACL 68 | #endif 69 | 70 | #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ 71 | -------------------------------------------------------------------------------- /3rd/protobuf/google/protoc-readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/3rd/protobuf/google/protoc-readme.txt -------------------------------------------------------------------------------- /3rd/protobuf/google/protoc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/3rd/protobuf/google/protoc.exe -------------------------------------------------------------------------------- /3rd/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 2 | #define RAPIDJSON_FILEREADSTREAM_H_ 3 | 4 | #include "rapidjson.h" 5 | #include 6 | 7 | namespace rapidjson { 8 | 9 | //! File byte stream for input using fread(). 10 | /*! 11 | \implements Stream 12 | */ 13 | class FileReadStream { 14 | public: 15 | typedef char Ch; //!< Character type (byte). 16 | 17 | //! Constructor. 18 | /*! 19 | \param fp File pointer opened for read. 20 | \param buffer user-supplied buffer. 21 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 22 | */ 23 | FileReadStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 24 | RAPIDJSON_ASSERT(fp_ != 0); 25 | RAPIDJSON_ASSERT(bufferSize >= 4); 26 | Read(); 27 | } 28 | 29 | Ch Peek() const { return *current_; } 30 | Ch Take() { Ch c = *current_; Read(); return c; } 31 | size_t Tell() const { return count_ + (current_ - buffer_); } 32 | 33 | // Not implemented 34 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 35 | void Flush() { RAPIDJSON_ASSERT(false); } 36 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 37 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 38 | 39 | // For encoding detection only. 40 | const Ch* Peek4() const { 41 | return (current_ + 4 <= bufferLast_) ? current_ : 0; 42 | } 43 | 44 | private: 45 | void Read() { 46 | if (current_ < bufferLast_) 47 | ++current_; 48 | else if (!eof_) { 49 | count_ += readCount_; 50 | readCount_ = fread(buffer_, 1, bufferSize_, fp_); 51 | bufferLast_ = buffer_ + readCount_ - 1; 52 | current_ = buffer_; 53 | 54 | if (readCount_ < bufferSize_) { 55 | buffer_[readCount_] = '\0'; 56 | ++bufferLast_; 57 | eof_ = true; 58 | } 59 | } 60 | } 61 | 62 | FILE* fp_; 63 | Ch *buffer_; 64 | size_t bufferSize_; 65 | Ch *bufferLast_; 66 | Ch *current_; 67 | size_t readCount_; 68 | size_t count_; //!< Number of characters read 69 | bool eof_; 70 | }; 71 | 72 | } // namespace rapidjson 73 | 74 | #endif // RAPIDJSON_FILESTREAM_H_ 75 | -------------------------------------------------------------------------------- /3rd/rapidjson/filestream.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_FILESTREAM_H_ 2 | #define RAPIDJSON_FILESTREAM_H_ 3 | 4 | #include "rapidjson.h" 5 | #include 6 | 7 | namespace rapidjson { 8 | 9 | //! (Depreciated) Wrapper of C file stream for input or output. 10 | /*! 11 | This simple wrapper does not check the validity of the stream. 12 | \implements Stream 13 | \deprecated { This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead. } 14 | */ 15 | class FileStream { 16 | public: 17 | typedef char Ch; //!< Character type. Only support char. 18 | 19 | FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } 20 | char Peek() const { return current_; } 21 | char Take() { char c = current_; Read(); return c; } 22 | size_t Tell() const { return count_; } 23 | void Put(char c) { fputc(c, fp_); } 24 | void Flush() { fflush(fp_); } 25 | 26 | // Not implemented 27 | char* PutBegin() { return 0; } 28 | size_t PutEnd(char*) { return 0; } 29 | 30 | private: 31 | void Read() { 32 | RAPIDJSON_ASSERT(fp_ != 0); 33 | int c = fgetc(fp_); 34 | if (c != EOF) { 35 | current_ = (char)c; 36 | count_++; 37 | } 38 | else if (current_ != '\0') 39 | current_ = '\0'; 40 | } 41 | 42 | FILE* fp_; 43 | char current_; 44 | size_t count_; 45 | }; 46 | 47 | } // namespace rapidjson 48 | 49 | #endif // RAPIDJSON_FILESTREAM_H_ 50 | -------------------------------------------------------------------------------- /3rd/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 2 | #define RAPIDJSON_FILEWRITESTREAM_H_ 3 | 4 | #include "rapidjson.h" 5 | #include 6 | 7 | namespace rapidjson { 8 | 9 | //! Wrapper of C file stream for input using fread(). 10 | /*! 11 | \implements Stream 12 | */ 13 | class FileWriteStream { 14 | public: 15 | typedef char Ch; //!< Character type. Only support char. 16 | 17 | FileWriteStream(FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 18 | RAPIDJSON_ASSERT(fp_ != 0); 19 | } 20 | 21 | void Put(char c) { 22 | if (current_ >= bufferEnd_) 23 | Flush(); 24 | 25 | *current_++ = c; 26 | } 27 | 28 | void PutN(char c, size_t n) { 29 | size_t avail = bufferEnd_ - current_; 30 | while (n > avail) { 31 | memset(current_, c, avail); 32 | current_ += avail; 33 | Flush(); 34 | n -= avail; 35 | avail = bufferEnd_ - current_; 36 | } 37 | 38 | if (n > 0) { 39 | memset(current_, c, n); 40 | current_ += n; 41 | } 42 | } 43 | 44 | void Flush() { 45 | if (current_ != buffer_) { 46 | fwrite(buffer_, 1, current_ - buffer_, fp_); 47 | current_ = buffer_; 48 | } 49 | } 50 | 51 | // Not implemented 52 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 53 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 54 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 55 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 56 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 57 | 58 | private: 59 | FILE* fp_; 60 | char *buffer_; 61 | char *bufferEnd_; 62 | char *current_; 63 | }; 64 | 65 | //! Implement specialized version of PutN() with memset() for better performance. 66 | template<> 67 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 68 | stream.PutN(c, n); 69 | } 70 | 71 | } // namespace rapidjson 72 | 73 | #endif // RAPIDJSON_FILESTREAM_H_ 74 | -------------------------------------------------------------------------------- /3rd/rapidjson/internal/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ 2 | #define RAPIDJSON_INTERNAL_STACK_H_ 3 | 4 | namespace rapidjson { 5 | namespace internal { 6 | 7 | /////////////////////////////////////////////////////////////////////////////// 8 | // Stack 9 | 10 | //! A type-unsafe stack for storing different types of data. 11 | /*! \tparam Allocator Allocator for allocating stack memory. 12 | */ 13 | template 14 | class Stack { 15 | public: 16 | Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { 17 | RAPIDJSON_ASSERT(stack_capacity_ > 0); 18 | if (!allocator_) 19 | own_allocator_ = allocator_ = new Allocator(); 20 | stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); 21 | stack_end_ = stack_ + stack_capacity_; 22 | } 23 | 24 | ~Stack() { 25 | Allocator::Free(stack_); 26 | delete own_allocator_; // Only delete if it is owned by the stack 27 | } 28 | 29 | void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } 30 | 31 | template 32 | T* Push(size_t count = 1) { 33 | // Expand the stack if needed 34 | if (stack_top_ + sizeof(T) * count >= stack_end_) { 35 | size_t new_capacity = stack_capacity_ * 2; 36 | size_t size = GetSize(); 37 | size_t new_size = GetSize() + sizeof(T) * count; 38 | if (new_capacity < new_size) 39 | new_capacity = new_size; 40 | stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); 41 | stack_capacity_ = new_capacity; 42 | stack_top_ = stack_ + size; 43 | stack_end_ = stack_ + stack_capacity_; 44 | } 45 | T* ret = (T*)stack_top_; 46 | stack_top_ += sizeof(T) * count; 47 | return ret; 48 | } 49 | 50 | template 51 | T* Pop(size_t count) { 52 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 53 | stack_top_ -= count * sizeof(T); 54 | return (T*)stack_top_; 55 | } 56 | 57 | template 58 | T* Top() { 59 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 60 | return (T*)(stack_top_ - sizeof(T)); 61 | } 62 | 63 | template 64 | T* Bottom() { return (T*)stack_; } 65 | 66 | Allocator& GetAllocator() { return *allocator_; } 67 | bool Empty() const { return stack_top_ == stack_; } 68 | size_t GetSize() const { return stack_top_ - stack_; } 69 | size_t GetCapacity() const { return stack_capacity_; } 70 | 71 | private: 72 | Allocator* allocator_; 73 | Allocator* own_allocator_; 74 | char *stack_; 75 | char *stack_top_; 76 | char *stack_end_; 77 | size_t stack_capacity_; 78 | }; 79 | 80 | } // namespace internal 81 | } // namespace rapidjson 82 | 83 | #endif // RAPIDJSON_STACK_H_ 84 | -------------------------------------------------------------------------------- /3rd/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 2 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 3 | 4 | namespace rapidjson { 5 | namespace internal { 6 | 7 | //! Custom strlen() which works on different character types. 8 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 9 | \param s Null-terminated input string. 10 | \return Number of characters in the string. 11 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 12 | */ 13 | template 14 | inline SizeType StrLen(const Ch* s) { 15 | const Ch* p = s; 16 | while (*p != '\0') 17 | ++p; 18 | return SizeType(p - s); 19 | } 20 | 21 | } // namespace internal 22 | } // namespace rapidjson 23 | 24 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 25 | -------------------------------------------------------------------------------- /3rd/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 2 | #define RAPIDJSON_STRINGBUFFER_H_ 3 | 4 | #include "rapidjson.h" 5 | #include "internal/stack.h" 6 | 7 | namespace rapidjson { 8 | 9 | //! Represents an in-memory output stream. 10 | /*! 11 | \tparam Encoding Encoding of the stream. 12 | \tparam Allocator type for allocating memory buffer. 13 | \implements Stream 14 | */ 15 | template 16 | struct GenericStringBuffer { 17 | typedef typename Encoding::Ch Ch; 18 | 19 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 20 | 21 | void Put(Ch c) { *stack_.template Push() = c; } 22 | void Flush() {} 23 | 24 | void Clear() { stack_.Clear(); } 25 | 26 | const Ch* GetString() const { 27 | // Push and pop a null terminator. This is safe. 28 | *stack_.template Push() = '\0'; 29 | stack_.template Pop(1); 30 | 31 | return stack_.template Bottom(); 32 | } 33 | 34 | size_t GetSize() const { return stack_.GetSize(); } 35 | 36 | static const size_t kDefaultCapacity = 256; 37 | mutable internal::Stack stack_; 38 | }; 39 | 40 | typedef GenericStringBuffer > StringBuffer; 41 | 42 | //! Implement specialized version of PutN() with memset() for better performance. 43 | template<> 44 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 45 | memset(stream.stack_.Push(n), c, n * sizeof(c)); 46 | } 47 | 48 | } // namespace rapidjson 49 | 50 | #endif // RAPIDJSON_STRINGBUFFER_H_ 51 | -------------------------------------------------------------------------------- /3rd/rapidxml/license.txt: -------------------------------------------------------------------------------- 1 | Use of this software is granted under one of the following two licenses, 2 | to be chosen freely by the user. 3 | 4 | 1. Boost Software License - Version 1.0 - August 17th, 2003 5 | =============================================================================== 6 | 7 | Copyright (c) 2006, 2007 Marcin Kalicinski 8 | 9 | Permission is hereby granted, free of charge, to any person or organization 10 | obtaining a copy of the software and accompanying documentation covered by 11 | this license (the "Software") to use, reproduce, display, distribute, 12 | execute, and transmit the Software, and to prepare derivative works of the 13 | Software, and to permit third-parties to whom the Software is furnished to 14 | do so, all subject to the following: 15 | 16 | The copyright notices in the Software and this entire statement, including 17 | the above license grant, this restriction and the following disclaimer, 18 | must be included in all copies of the Software, in whole or in part, and 19 | all derivative works of the Software, unless such copies or derivative 20 | works are solely in the form of machine-executable object code generated by 21 | a source language processor. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 26 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 27 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 28 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE. 30 | 31 | 2. The MIT License 32 | =============================================================================== 33 | 34 | Copyright (c) 2006, 2007 Marcin Kalicinski 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a copy 37 | of this software and associated documentation files (the "Software"), to deal 38 | in the Software without restriction, including without limitation the rights 39 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 40 | of the Software, and to permit persons to whom the Software is furnished to do so, 41 | subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included in all 44 | copies or substantial portions of the Software. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 49 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 50 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 51 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 52 | IN THE SOFTWARE. 53 | -------------------------------------------------------------------------------- /3rd/rapidxml/manual.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/3rd/rapidxml/manual.zip -------------------------------------------------------------------------------- /3rd/rapidxml/rapidxml_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RAPIDXML_UTILS_HPP_INCLUDED 2 | #define RAPIDXML_UTILS_HPP_INCLUDED 3 | 4 | // Copyright (C) 2006, 2009 Marcin Kalicinski 5 | // Version 1.13 6 | // Revision $DateTime: 2009/05/13 01:46:17 $ 7 | //! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful 8 | //! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. 9 | 10 | #include "rapidxml.hpp" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace rapidxml 17 | { 18 | 19 | //! Represents data loaded from a file 20 | template 21 | class file 22 | { 23 | 24 | public: 25 | 26 | //! Loads file into the memory. Data will be automatically destroyed by the destructor. 27 | //! \param filename Filename to load. 28 | file(const char *filename) 29 | { 30 | using namespace std; 31 | 32 | // Open stream 33 | basic_ifstream stream(filename, ios::binary); 34 | if (!stream) 35 | throw runtime_error(string("cannot open file ") + filename); 36 | stream.unsetf(ios::skipws); 37 | 38 | // Determine stream size 39 | stream.seekg(0, ios::end); 40 | size_t size = stream.tellg(); 41 | stream.seekg(0); 42 | 43 | // Load data and add terminating 0 44 | m_data.resize(size + 1); 45 | stream.read(&m_data.front(), static_cast(size)); 46 | m_data[size] = 0; 47 | } 48 | 49 | //! Loads file into the memory. Data will be automatically destroyed by the destructor 50 | //! \param stream Stream to load from 51 | file(std::basic_istream &stream) 52 | { 53 | using namespace std; 54 | 55 | // Load data and add terminating 0 56 | stream.unsetf(ios::skipws); 57 | m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); 58 | if (stream.fail() || stream.bad()) 59 | throw runtime_error("error reading stream"); 60 | m_data.push_back(0); 61 | } 62 | 63 | //! Gets file data. 64 | //! \return Pointer to data of file. 65 | Ch *data() 66 | { 67 | return &m_data.front(); 68 | } 69 | 70 | //! Gets file data. 71 | //! \return Pointer to data of file. 72 | const Ch *data() const 73 | { 74 | return &m_data.front(); 75 | } 76 | 77 | //! Gets file data size. 78 | //! \return Size of file data, in characters. 79 | std::size_t size() const 80 | { 81 | return m_data.size(); 82 | } 83 | 84 | private: 85 | 86 | std::vector m_data; // File data 87 | 88 | }; 89 | 90 | //! Counts children of node. Time complexity is O(n). 91 | //! \return Number of children of node 92 | template 93 | inline std::size_t count_children(xml_node *node) 94 | { 95 | xml_node *child = node->first_node(); 96 | std::size_t count = 0; 97 | while (child) 98 | { 99 | ++count; 100 | child = child->next_sibling(); 101 | } 102 | return count; 103 | } 104 | 105 | //! Counts attributes of node. Time complexity is O(n). 106 | //! \return Number of attributes of node 107 | template 108 | inline std::size_t count_attributes(xml_node *node) 109 | { 110 | xml_attribute *attr = node->first_attribute(); 111 | std::size_t count = 0; 112 | while (attr) 113 | { 114 | ++count; 115 | attr = attr->next_attribute(); 116 | } 117 | return count; 118 | } 119 | 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /3rd/sha1.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/3rd/sha1.hpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TheFox Cpp Framework 2 | 3 | ## 简介 ## 4 | 一个C++的基础开发库,包含包括常见的C++常用工具类(file、mutex、semaphore、thread、线程池等)、mysql封装、net-snmp封装、net库、rpc、log库。 5 | 6 | 现在主要工作平台是Windows,最近也在将其中的一部分慢慢的实现Windows和Linux跨平台 7 | 8 | 本库尽量保证轻量级,功能比较简单 9 | 10 | **请保证您的编译器支持C++11** 11 | 12 | ## 文件说明 ## 13 | 14 | |thefoxframework 15 | --|base 比较基础的功能封装 16 | --|common.h 公用的一些宏定义和类型定义 17 | --|debug_win.h Windows下帮助调试的工具 18 | --|file_tools.h 文件操作工具 19 | --|ini_file.h ini文件的操作的封装 20 | --|ip_addr_utill.h 提供Ip地址字符串类型和整型之间互换的函数 21 | --|mailslot.h Windows下邮槽的封装 22 | --|mem_pool.h 内存池的封装 23 | --|object_pool.h 对象池的封装 24 | --|ring_buffer.h 环形缓冲的封装 25 | --|observer.h Observer模式的封装 26 | --|singleton.h 对Singleton模式的封装 27 | --|string_util.h 提供一些字符串操作函数 28 | --|time_util.h 时间戳帮助函数 29 | --|timestamp.h 精确到微妙的时间戳类 30 | --|uuid.h 产生UUID字符串的函数 31 | [多线程开发工具] 32 | --|atomic_integer.h 对原子操作的封装 33 | --|condition.h 条件变量的封装 34 | --|event.h Windows下Event的封装 35 | --|mutex.h 互斥锁的封装 36 | --|semaphore.h 对信号量的封装 37 | --|read_write_lock.h 读写锁 38 | --|thread.h 对线程操作的封装 39 | --|thread_pool.h 一个线程池的封装 40 | --|log 一个日志库 41 | --|logging.h{.cc} 操作日志字符串,日志库的主要逻辑代码都在这里 42 | --|log_file.h(.cc) 把日志字符串写到文件的类 43 | --|log_stdout.h{.cc} 把日志字符串输出到STDOUT上 44 | --|log_syslog.h{.cc} 把日志字符串通过syslog协议输出 45 | --|net 一个网络开发框架 46 | --|acceptor.h{.cc} 监听TCP端口的类 47 | --|buffer.h 应用层缓存类(接收和发送数据用) 48 | --|callback.h 网络框架提供给上层的回调函数 49 | --|event.h {.cc} 表示一个异步IO事件 50 | --|event_loop.h{.cc} 提供异步IO时间循环的支持 51 | --|epoll_event.h{.cc} EPOLL封装的代码 52 | --|iocp_event.h{.cc} IOCP封装的代码 53 | --|inet_address.h Socket地址的封装 54 | --|socket.h{.cc} Socket操作的封装 55 | --|tcp_connection.h{.cc} 一个tcp会话的封装 ,这是网络库的核心 56 | --|tcp_client.h{.cc} tcp客户端操作的封装 57 | --|tcp_server.h{.cc} tcp服务器操作的封装 58 | --|db mysql数据库连接的封装 59 | --|mysql_connection.h mysql连接的封装 60 | --|mysql_result_set.h 查询结果集的封装 61 | --|mysql_util.h 经常使用的sql操作的封装 62 | --|snmp SNMP客户端操作类 63 | --|rpc 基于net+protobuf的rpc实现 64 | --|3rd 第三方库 65 | --|aes aes加密算法库 66 | --|protobuf-2.5.0 protobuf库 67 | --|rapidjson json格式操作库 68 | --|rapidxml xml格式操作库 69 | --|base64.hpp base64操作类 70 | --|md5.hpp md5操作类 71 | --|sha1.hpp sha1操作类 72 | --|xml2json.h xml格式和json格式互相转换的类 73 | 74 | 75 | E-mail: elemeta@foxmail.com 76 | -------------------------------------------------------------------------------- /base/atomic_integer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename atomic_integer.h 3 | * @brief 原子的数字类 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_ATOMIC_INTEGER_H_ 8 | #define _THEFOX_BASE_ATOMIC_INTEGER_H_ 9 | 10 | #include 11 | 12 | #ifdef WIN32 13 | #include 14 | #endif 15 | 16 | namespace thefox { 17 | 18 | #ifdef WIN32 19 | inline LONG atomicInc(volatile LONG *value) 20 | { return InterlockedIncrement(value); } 21 | #else 22 | inline int32_t atomicInc(volatile int32_t *value) 23 | { 24 | __sync_fetch_and_add(value, 1); 25 | return *value; 26 | } 27 | #endif 28 | 29 | #ifdef WIN32 30 | inline LONGLONG atomicInc(volatile LONGLONG *value) 31 | { return InterlockedIncrement64(value); } 32 | #else 33 | inline int64_t atomicInc(volatile int64_t *value) 34 | { 35 | __sync_fetch_and_add(value, 1); 36 | return *value; 37 | } 38 | #endif 39 | 40 | #ifdef WIN32 41 | inline LONG atomicDec(volatile LONG *value) 42 | { return InterlockedDecrement(value); } 43 | #else 44 | inline int32_t atomicDec(volatile int32_t *value) 45 | { 46 | __sync_fetch_and_sub(value, 1); 47 | return *value; 48 | } 49 | #endif 50 | 51 | #ifdef WIN32 52 | inline LONGLONG atomicDec(volatile LONGLONG *value) 53 | { return InterlockedDecrement64(value); } 54 | #else 55 | inline int64_t atomicDec(volatile int64_t *value) 56 | { 57 | __sync_fetch_and_sub(value, 1); 58 | return *value; 59 | } 60 | #endif 61 | 62 | 63 | template 64 | class AtomicInteger 65 | { 66 | public: 67 | AtomicInteger() 68 | : _value(0) 69 | {} 70 | 71 | T inc() { return atomicInc(&_value); } 72 | T dec() { return atomicDec(&_value); } 73 | T value() const { return _value; } 74 | private: 75 | T _value; 76 | }; 77 | 78 | #ifdef WIN32 79 | typedef AtomicInteger AtomicInt32; 80 | typedef AtomicInteger AtomicInt64; 81 | #else 82 | typedef AtomicInteger AtomicInt32; 83 | typedef AtomicInteger AtomicInt64; 84 | #endif 85 | 86 | } // namespace thefox 87 | 88 | #endif // _THEFOX_BASE_ATOMIC_INTEGER_H_ 89 | -------------------------------------------------------------------------------- /base/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename common.h 3 | * @brief 这里放一些最常用的头文件、宏、函数等,需要C++11的支持才行 4 | * @author macwe1024 at gmail dot com 5 | * 6 | */ 7 | 8 | #ifndef _THEFOX_BASE_COMMON_H_ 9 | #define _THEFOX_BASE_COMMON_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef NDEBUG 17 | #include 18 | #endif 19 | 20 | #ifdef WIN32 21 | #pragma warning(disable:4819) 22 | #pragma warning(disable:4996) 23 | #define snprintf _snprintf 24 | 25 | #if _MSC_VER < 1500 // MSVC 2008 26 | #define vsnprintf _vsnprintf 27 | #endif 28 | #endif 29 | 30 | namespace thefox { 31 | 32 | using std::string; 33 | using namespace std::placeholders; // for std::bind 34 | 35 | // disallow copy ctor and assign opt 36 | #undef THEFOX_DISALLOW_EVIL_CONSTRUCTORS 37 | #define THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ 38 | TypeName(const TypeName&); \ 39 | void operator=(const TypeName&) 40 | 41 | // delete object safe 42 | #define SAFE_DELETE(p) \ 43 | if (NULL != p) { \ 44 | delete p; \ 45 | p = NULL; \ 46 | } 47 | 48 | // delete object array safe 49 | #define SAFE_DELETE_ARRAY(p) \ 50 | if (NULL != p) { \ 51 | delete []p; \ 52 | p = NULL; \ 53 | } 54 | 55 | #define MIN(a,b) ((a)<(b)) ? (a) : (b) 56 | #define MAX(a,b) ((a)>(b)) ? (a) : (b) 57 | 58 | } // namespace thefox 59 | 60 | #endif // _THEFOX_BASE_COMMON_H_ 61 | -------------------------------------------------------------------------------- /base/condition.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename condition.h 3 | * @brief 对条件变量的封装,只适用于linux 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_CONDITION_H_ 8 | #define _THEFOX_BASE_CONDITION_H_ 9 | 10 | #ifdef WIN32 11 | #error "class condition use for linux only" 12 | #else 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace thefox { 19 | 20 | class Condition 21 | { 22 | public: 23 | static const uint32_t kInfinite = 0xffffffff; 24 | 25 | Condition(Mutex &mutex) 26 | : _mutex(mutex) 27 | { 28 | pthread_cond_init(&_cond, NULL); 29 | } 30 | ~Condition() 31 | { 32 | pthread_cond_destroy(&_cond); 33 | } 34 | 35 | bool wait(uint32_t millisecond = kInfinite) 36 | { 37 | int32_t ret = 0; 38 | 39 | if (kInfinite == millisecond) { 40 | ret = pthread_cond_wait(&_cond, _mutex.getMutex()); 41 | } else { 42 | struct timespec ts = {0, 0}; 43 | TimeUtil::getAbsTimespec(&ts, millisecond); 44 | ret = pthread_cond_timedwait(&_cond, _mutex.getMutex(), &ts); 45 | } 46 | 47 | return 0 == ret; 48 | } 49 | 50 | bool notify() 51 | { 52 | return 0 == pthread_cond_signal(&_cond); 53 | } 54 | 55 | bool notifyAll() 56 | { 57 | return 0 == pthread_cond_broadcast(&_cond); 58 | } 59 | 60 | private: 61 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Condition); 62 | 63 | Mutex& _mutex; 64 | pthread_cond_t _cond; 65 | }; 66 | 67 | } // namespace thefox 68 | 69 | #endif // #ifdef WIN32 #else 70 | 71 | #endif // _THEFOX_BASE_CONDITION_H_ 72 | -------------------------------------------------------------------------------- /base/debug_win.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_DEBUG_WIN_H_ 2 | #define _THEFOX_DEBUG_WIN_H_ 3 | 4 | #ifndef WIN32 5 | #error "debug_win.h is Windows only" 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "Dbghelp.lib") 13 | 14 | namespace thefox { 15 | 16 | LONG WINAPI thefoxUnhandledFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo) 17 | { 18 | LONG ret = EXCEPTION_EXECUTE_HANDLER; 19 | 20 | char szFileName[64]; 21 | SYSTEMTIME st; 22 | ::GetLocalTime(&st); 23 | _snprintf(szFileName, sizeof(szFileName), "%04d-%02d-%02d-%02d-%02d-%02d-%02d-%02d.dmp", 24 | st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, rand()%100); 25 | 26 | HANDLE hFile = ::CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); 27 | if (hFile != INVALID_HANDLE_VALUE) { 28 | MINIDUMP_EXCEPTION_INFORMATION ExInfo; 29 | 30 | ExInfo.ThreadId = ::GetCurrentThreadId(); 31 | ExInfo.ExceptionPointers = lpExceptionInfo; 32 | ExInfo.ClientPointers = false; 33 | 34 | // write the dump 35 | MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL ); 36 | 37 | ::CloseHandle(hFile); 38 | } 39 | 40 | return ret; 41 | } 42 | 43 | } // namespace thefox 44 | 45 | #define THEFOX_SET_UNHANDLED_EXCEPTION_FILTER ::SetUnhandledExceptionFilter(thefox::thefoxUnhandledFilter) 46 | 47 | #endif // _THEFOX_DEBUG_WIN_H_ 48 | -------------------------------------------------------------------------------- /base/event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename event.h 3 | * @brief 对windows下Event的封装 4 | * @ author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_EVENT_H_ 8 | #define _THEFOX_BASE_EVENT_H_ 9 | 10 | #ifdef WIN32 11 | #define WIN32_LEAN_AND_MEAN 12 | #include 13 | 14 | #include 15 | 16 | namespace thefox { 17 | 18 | class Event 19 | { 20 | public: 21 | static const uint32_t kInfinite = INFINITE; 22 | Event() 23 | : _event(NULL) 24 | { 25 | _event = ::CreateEvent(NULL, TRUE, FALSE, NULL); 26 | assert (NULL != _event); 27 | } 28 | ~Event() 29 | { 30 | if (NULL != _event) { 31 | CloseHandle(_event); 32 | } 33 | } 34 | 35 | void set() { ::SetEvent(_event); } 36 | void reset() { ::ResetEvent(_event); } 37 | bool wait(DWORD dwMilliseconds = kInfinite) 38 | { 39 | ::WaitForSingleObject(_event, dwMilliseconds); 40 | return true; 41 | } 42 | operator HANDLE() { return _event; } 43 | private: 44 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Event); 45 | HANDLE _event; 46 | }; 47 | 48 | } // namespace thefox 49 | 50 | #else // #ifdef WIN32 51 | #error "class Event use for Windows only" 52 | #endif 53 | 54 | #endif // _THEFOX_BASE_EVENT_H_ -------------------------------------------------------------------------------- /base/file_tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename file_tools.h 3 | * @brief 一些文件操作的辅助帮助函数 4 | * @author macwe1023 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_FILES_H_ 8 | #define _THEFOX_BASE_FILES_H_ 9 | 10 | #include 11 | #include 12 | 13 | #ifdef WIN32 14 | #include 15 | #define getcwd _getcwd 16 | #else 17 | #include 18 | #include 19 | #include 20 | #endif 21 | 22 | namespace thefox { 23 | 24 | class Files 25 | { 26 | public: 27 | /// @biref 创建目录 28 | static void makePath(string &dir) 29 | { 30 | char filePath[1000] = {0}; 31 | bool bAbsolutePath = true; 32 | 33 | #ifdef WIN32 34 | if (string::npos == dir.find(':')) 35 | bAbsolutePath = false; 36 | #else 37 | if ('/' != dir[0]) 38 | bAbsolutePath = false; 39 | #endif 40 | 41 | if (!bAbsolutePath) { 42 | getcwd(filePath, sizeof(filePath)); 43 | char cSeparator = filePath[strlen(filePath)]; 44 | if (!(cSeparator == '/' || cSeparator == '\\')) 45 | strcat(filePath, "/"); 46 | 47 | strncat(filePath, dir.c_str(), sizeof(filePath) - strlen(filePath)); 48 | } else { 49 | strncpy(filePath, dir.c_str(), sizeof(filePath)); 50 | } 51 | 52 | char *curDir = filePath; 53 | 54 | while (*curDir != '\0') { 55 | if (*curDir == '\\' || *curDir == '/') { 56 | *curDir = '\0'; 57 | #ifdef WIN32 58 | _mkdir(filePath); 59 | #else 60 | mkdir(filePath, S_IRWXU); 61 | #endif 62 | *curDir = '/'; 63 | } 64 | ++curDir; 65 | } 66 | #ifdef WIN32 67 | _mkdir(filePath); 68 | #else 69 | mkdir(filePath, S_IRWXU); 70 | #endif 71 | size_t pathLen = strlen(filePath); 72 | if ('/' != filePath[pathLen - 1]) { 73 | strcat(filePath, "/"); 74 | ++pathLen; 75 | } 76 | 77 | dir = filePath; 78 | } 79 | }; 80 | 81 | } // namespace thefox 82 | 83 | #endif // _THEFOX_BASE_FILES_H_ -------------------------------------------------------------------------------- /base/ini_file.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_INI_FILE_H_ 2 | #define _THEFOX_BASE_INI_FILE_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace thefox { 8 | 9 | class IniFile 10 | { 11 | public: 12 | IniFile(const char *fileName) 13 | : _fileName(fileName) 14 | {} 15 | ~IniFile() 16 | {} 17 | 18 | int getInt(const char *section, const char *key, int defaultValue) 19 | { 20 | return ::GetPrivateProfileInt(section, key, defaultValue, _fileName.c_str()); 21 | } 22 | 23 | string getString(const char *section, const char *key, const char *defaultValue) 24 | { 25 | char buf[8192] = {0}; 26 | ::GetPrivateProfileString(section, key, defaultValue, buf, sizeof(buf), _fileName.c_str()); 27 | return buf; 28 | } 29 | 30 | void setInt(const char *section, const char *key, int value) 31 | { 32 | char buf[32] = {0}; 33 | snprintf(buf, sizeof(buf), "%d", value); 34 | ::WritePrivateProfileStringA(section, key, buf, _fileName.c_str()); 35 | } 36 | 37 | void setString(const char *section, const char *key, const string &value) 38 | { 39 | ::WritePrivateProfileStringA(section, key, value.c_str(), _fileName.c_str()); 40 | } 41 | 42 | private: 43 | string _fileName; 44 | }; 45 | 46 | } // namespace thefox 47 | 48 | #endif // _THEFOX_BASE_INI_FILE_H_ -------------------------------------------------------------------------------- /base/ip_addr_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_IP_ADDR_UTIL_H_ 2 | #define _THEFOX_BASE_IP_ADDR_UTIL_H_ 3 | 4 | #include 5 | 6 | namespace thefox { 7 | 8 | class IpAddrUtil 9 | { 10 | public: 11 | /// @brief 将uint类型的ip地址装换成字符串 12 | /// @param[in] ip uint类型的ip地址 13 | /// @return 返回字符串类型的ip地址 14 | static string toString(uint32_t ip) 15 | { 16 | char buf[32] = {0}; 17 | uint8_t* ptr = (uint8_t*)&ip; 18 | snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", ptr[3], ptr[2], ptr[1], ptr[0]); 19 | buf[sizeof(buf) - 1] = '\0'; 20 | return buf; 21 | } 22 | 23 | /// @brief 将ip地址字符串转换成数字类型 24 | /// @param[in] ip地址字符串 25 | /// @return 返回数字类型的字符串 26 | static uint32_t stoi(const char* ipStr) 27 | { 28 | if (strlen(ipStr) > 15) { // ip地址最长只有15个字符 29 | return 0; 30 | } 31 | int32_t ip, d0, d1, d2, d3; 32 | sscanf(ipStr, "%d.%d.%d.%d", &d0, &d1, &d2, &d3); 33 | ip = (((((d0<<8)+d1)<<8)+d2)<<8)+d3; 34 | return ip; 35 | } 36 | 37 | static uint32_t stoi(const string &ipStr) 38 | { 39 | return stoi(ipStr.c_str()); 40 | } 41 | }; 42 | 43 | } // namespace thefox 44 | 45 | #endif // _THEFOX_BASE_IPADDRUTIL_H_ -------------------------------------------------------------------------------- /base/mailslot.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_MAILSLOT_H_ 2 | #define _THEFOX_BASE_MAILSLOT_H_ 3 | 4 | #include 5 | 6 | namespace thefox { 7 | 8 | DROWD WINAPI mailslotThreadProc(LPVOID lpParameter); 9 | 10 | class MailslotServer 11 | { 12 | public: 13 | MailslotServer() 14 | : _bCreated(false) 15 | {} 16 | ~CMailslotServer() 17 | {} 18 | 19 | bool create(LPCTSTR lpszSlotName) 20 | { 21 | _hSlot = CreateMailslot(lpszSlotName, 0, MAILSLOT_WAIT_FOREVER, (LPSECURITY_ATTRIBUTES)NULL); 22 | 23 | if (_hSlot == INVALID_HANDLE_VALUE) { 24 | //TRACE("CreateMailslot failed with %d\n", GetLastError()); 25 | return false; 26 | } 27 | 28 | _hReadThread= ::CreateThread(NULL, 0, mailslotThreadProc, this, 0, NULL); 29 | } 30 | 31 | void close() 32 | { 33 | TerminateThread(_hReadThread, 4); 34 | CloseHandle(_hReadThread); 35 | CloseHandle(_hSlot); 36 | } 37 | 38 | virtual void onRead(const DWORD dataLen) = 0; 39 | 40 | private: 41 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(MailslotServer); 42 | bool _bCreated; 43 | HANDLE _hSlot; 44 | HANDLE _hReadThread; 45 | }; 46 | 47 | 48 | class MailslotClient 49 | { 50 | public: 51 | MailslotClient() 52 | {} 53 | ~MailslotClient() 54 | {} 55 | 56 | bool open(LPCTSTR SlotName) 57 | { 58 | m_hFile = CreateFile(SlotName, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL, 59 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); 60 | if (m_hFile == INVALID_HANDLE_VALUE) { 61 | //TRACE("CreateFile failed with %d.\n", GetLastError()); 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | void close() 68 | { 69 | ::CloseHandle(m_hFile); 70 | } 71 | 72 | bool write(const char *data, const size_t dataLen) 73 | { 74 | BOOL fResult; 75 | DWORD cbWritten; 76 | 77 | fResult = WriteFile(m_hFile, data, (DWORD)dataLen, &cbWritten, (LPOVERLAPPED)NULL); 78 | if (!fResult) { 79 | //TRACE("WriteFile failed with %d.\n", GetLastError()); 80 | return false; 81 | } 82 | 83 | return true; 84 | } 85 | 86 | private: 87 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(MailslotClient); 88 | HANDLE _hFile; 89 | }; 90 | 91 | 92 | DROWD WINAPI MailslotThreadProc(LPVOID lpParameter) 93 | { 94 | CMailslotServer *svr = (CMailslotServer *)param; 95 | BOOL fResult; 96 | 97 | while (1) { 98 | if (!svr->m_bCreated) 99 | return 0; 100 | 101 | DWORD cbMessage, cMessage; 102 | cbMessage = cMessage = 0; 103 | 104 | cbMessage = cMessage = cbRead = 0; 105 | GetMailslotInfo(svr->m_hSlot, (LPDWORD)NULL, &cbMessage, &cMessage, (LPDWORD)NULL); 106 | 107 | if (cMessage > 0) { 108 | svr->OnRead(cMessage); 109 | } 110 | } 111 | return 0; 112 | } 113 | 114 | } // namespace thefox 115 | 116 | #endif // _THEFOX_BASE_MAILSLOT_H_ -------------------------------------------------------------------------------- /base/mem_pool.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename mem_pool.h 3 | * @brief 可存放固定大小元素的内存池 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_MEM_POOL_H_ 8 | #define _THEFOX_BASE_MEM_POOL_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | 16 | template 17 | class MemPool 18 | { 19 | public: 20 | MemPool() 21 | { 22 | addChunk(); 23 | _freeHead = _chunks.back(); 24 | } 25 | ~MemPool() 26 | { 27 | while (!_chunks.empty()) { 28 | T *pointer = _chunks.back(); 29 | _chunks.pop_back(); 30 | free(pointer); 31 | } 32 | 33 | _freeBlocks.clear(); 34 | _freeHead = NULL; 35 | } 36 | 37 | /// @brief alloc memory 38 | /// @raturn pointer to allocated memory 39 | T *get() 40 | { 41 | T *ret = NULL; 42 | 43 | MutexGuard lock(_mutex); 44 | if (!_freeBlocks.empty()) { 45 | ret = _freeBlocks.back(); 46 | _freeBlocks.pop_back(); 47 | } else { 48 | if (_freeHead == (_chunks.back() + (_chunks.size() * kDefaultBlockSize))) { 49 | addChunk(); 50 | _freeHead = _chunks.back(); 51 | } 52 | ret = _freeHead; 53 | ++_freeHead; 54 | } 55 | return ret; 56 | } 57 | 58 | /// @brief delete memory 59 | /// @param[in] pointer pointer to delete 60 | void put(T *pointer) 61 | { 62 | MutexGuard lock(_mutex); 63 | _freeBlocks.push_back(pointer); 64 | } 65 | 66 | private: 67 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(MemPool); 68 | void addChunk() 69 | { 70 | size_t blockSize = (_chunks.size() + 1) * kDefaultBlockSize; 71 | _chunks.push_back(reinterpret_cast(malloc(sizeof(T)* kDefaultBlockSize))); 72 | } 73 | 74 | Mutex _mutex; 75 | T *_freeHead; 76 | std::vector _chunks; 77 | std::vector _freeBlocks; 78 | 79 | static const size_t kDefaultBlockSize = 128; 80 | }; 81 | 82 | } // namespace thefox 83 | 84 | #endif // _THEFOX_BASE_MEMPOOL_H_ -------------------------------------------------------------------------------- /base/mutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename mutex.h 3 | * @brief 互斥量操作类, 支持Windows和Linux 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_MUTEX_H_ 8 | #define _THEFOX_BASE_MUTEX_H_ 9 | 10 | #ifdef WIN32 11 | #define WIN32_LEAN_AND_MEAN 12 | #include 13 | typedef CRITICAL_SECTION pthread_mutex_t; 14 | #else 15 | #include 16 | #endif 17 | 18 | #include 19 | 20 | namespace thefox { 21 | 22 | class Mutex 23 | { 24 | public: 25 | Mutex() 26 | : _threadId(0) 27 | { 28 | #ifdef WIN32 29 | InitializeCriticalSection(&_mutex); 30 | #else 31 | pthread_mutex_init(&_mutex, NULL); 32 | #endif 33 | } 34 | ~Mutex() 35 | { 36 | #ifdef WIN32 37 | DeleteCriticalSection(&_mutex); 38 | #else 39 | pthread_mutex_destroy(&_mutex); 40 | #endif 41 | } 42 | 43 | void lock() 44 | { 45 | #ifdef WIN32 46 | EnterCriticalSection(&_mutex); 47 | _threadId = static_cast(GetCurrentThreadId()); 48 | #else 49 | pthread_mutex_lock(&_mutex); 50 | _threadId = static_cast(pthread_self()); 51 | #endif 52 | } 53 | 54 | void unlock() 55 | { 56 | _threadId = 0; 57 | #ifdef WIN32 58 | LeaveCriticalSection(&_mutex); 59 | #else 60 | pthread_mutex_unlock(&_mutex); 61 | #endif 62 | } 63 | 64 | pthread_mutex_t *getMutex() 65 | { 66 | return &_mutex; 67 | } 68 | 69 | private: 70 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Mutex); 71 | 72 | uint32_t _threadId; 73 | pthread_mutex_t _mutex; 74 | }; 75 | 76 | class MutexGuard 77 | { 78 | public: 79 | MutexGuard(Mutex &mutex) 80 | : _mutex(mutex) 81 | { 82 | _mutex.lock(); 83 | } 84 | ~MutexGuard() 85 | { 86 | _mutex.unlock(); 87 | } 88 | private: 89 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(MutexGuard); 90 | Mutex &_mutex; 91 | }; 92 | 93 | #define MutexGuard(x) error "Missing MutexGuard object name" 94 | 95 | } // namespace thefox 96 | 97 | #endif // _THEFOX_BASE_MUTEXLOCK_H_ 98 | -------------------------------------------------------------------------------- /base/object_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename 0bject_pool.h 3 | * @brief 存放对象元素的内存池,可自动调用构造函数和析构函数 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_OBJECT_POOL_H_ 8 | #define _THEFOX_BASE_OBJECT_POOL_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace thefox { 14 | 15 | template 16 | class ObjectPool 17 | { 18 | public: 19 | T *get() 20 | { 21 | T *obj = _pool.get(); 22 | new(obj) T(); // placement new 23 | return obj; 24 | } 25 | 26 | template 27 | T *get(Arg0 &arg0) 28 | { 29 | T *obj = _pool.get(); 30 | new(obj) T(arg0); // placement new 31 | return obj; 32 | } 33 | 34 | template 35 | T *get(Arg0 &arg0, Arg1 &arg1) 36 | { 37 | T *obj = _pool.get(); 38 | new(obj) T(arg0, arg1); // placement new 39 | return obj; 40 | } 41 | 42 | template 43 | T *get(Arg0 &arg0, Arg1 &arg1, Arg2 &arg2) 44 | { 45 | T *obj = _pool.get(); 46 | new(obj) T(arg0, arg1, arg2); // placement new 47 | return obj; 48 | } 49 | 50 | template 51 | T *get(Arg0 &arg0, Arg1 &arg1, Arg2 &arg2, Arg3 &arg3) 52 | { 53 | T *obj = _pool.get(); 54 | new(obj) T(arg0, arg1, arg2, arg3); // placement new 55 | return obj; 56 | } 57 | 58 | template 59 | T *get(Arg0 &arg0, Arg1 &arg1, Arg2 &arg2, Arg3 &arg3, Arg4 &arg4) 60 | { 61 | T *obj = _pool.get(); 62 | new(obj) T(arg0, arg1, arg2, arg3, arg4); // placement new 63 | return obj; 64 | } 65 | 66 | /* 67 | * @brief delete object 68 | */ 69 | void put(T *obj) 70 | { 71 | obj->~T(); 72 | _pool.put(obj); 73 | } 74 | 75 | private: 76 | MemPool _pool; 77 | }; 78 | 79 | } // namespace thefox 80 | 81 | #endif // _THEFOX_BASE_OBJECT_MEM_POOL_H_ 82 | -------------------------------------------------------------------------------- /base/observer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename observer.h 3 | * @brief Observer模式 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_OBSERVER_H_ 8 | #define _THEFOX_BASE_OBSERVER_H_ 9 | 10 | #include 11 | 12 | namespace thefox { 13 | 14 | class Observable; 15 | 16 | class Observer 17 | { 18 | public: 19 | virtual ~Observer() {} 20 | 21 | virtual void update(Observable *p, void *arg) = 0; 22 | }; 23 | 24 | 25 | class Observable 26 | { 27 | public: 28 | Observable() 29 | : _observers(false) {} 30 | 31 | virtual ~Observable() {} 32 | 33 | virtual bool addObserver(Observer *obj) 34 | { 35 | std::pair::iterator, bool> ret = _observers.insert(obj); 36 | return ret.second; 37 | } 38 | 39 | virtual bool deleteObserver(Observer *obj) 40 | { 41 | std::set::iterator it = _observers.find(obj); 42 | if (it != _observers.end()) { 43 | _observers.erase(it); 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | virtual void notifyObservers(void* arg = 0) 50 | { 51 | if (_changed) { 52 | std::set::iterator it = _observers.begin(); 53 | std::set::iterator itEnd = _observers.end(); 54 | for (; it != itEnd; ++it) { 55 | (*it)->update(this, arg); 56 | } 57 | _changed = false; 58 | } 59 | } 60 | 61 | virtual void setChanged() 62 | { 63 | _changed = true; 64 | } 65 | 66 | protected: 67 | std::set _observers; 68 | bool _changed; 69 | }; 70 | 71 | } // namespace thefox 72 | 73 | #endif // _THEFOX_BASE_OBSERVER_H_ 74 | -------------------------------------------------------------------------------- /base/read_write_lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename read_write_lock.h 3 | * @brief 读写锁 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_READ_WRITE_LOCK_H_ 8 | #define _THEFOX_BASE_READ_WRITE_LOCK_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | 16 | class ReadWriteLock 17 | { 18 | public: 19 | ReadWriteLock() 20 | : _reads(0) 21 | {} 22 | 23 | ~ReadWriteLock() 24 | {} 25 | 26 | void readLock() 27 | { 28 | _enterLock.lock(); 29 | atomicInc(&_reads); 30 | _enterLock.unlock(); 31 | } 32 | 33 | void readUnlock() 34 | { 35 | atomicDec(&_reads); 36 | } 37 | 38 | void writeLock() 39 | { 40 | _enterLock.lock(); 41 | while (_reads > 0) { 42 | Sleep(0); 43 | } 44 | } 45 | 46 | void writeUnlock() 47 | { 48 | _enterLock.unlock(); 49 | } 50 | 51 | private: 52 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(ReadWriteLock); 53 | volatile uint32_t _reads; 54 | MutexLock _enterLock; 55 | }; 56 | 57 | class ReadLockGuard 58 | { 59 | public: 60 | ReadLockGuard(ReadWriteLock &lock) 61 | : _lock(lock) 62 | { 63 | _lock.readLock(); 64 | } 65 | ~ReadLockGuard() 66 | { 67 | _lock.readUnlock(); 68 | } 69 | private: 70 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(ReadLockGuard); 71 | ReadWriteLock &_lock; 72 | }; 73 | 74 | class WriteLockGuard 75 | { 76 | public: 77 | WriteLockGuard(ReadWriteLock &lock) 78 | : _lock(lock) 79 | { 80 | _lock.writeLock(); 81 | } 82 | ~WriteLockGuard() 83 | { 84 | _lock.writeUnlock(); 85 | } 86 | private: 87 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(WriteLockGuard); 88 | ReadWriteLock &_lock; 89 | }; 90 | 91 | #define ReadLockGuard(x) error "Missing guard object name" 92 | #define WriteLockGuard(x) error "Missing guard object name" 93 | } 94 | 95 | #endif // _THEFOX_BASE_READWRITELOCK_H_ -------------------------------------------------------------------------------- /base/ring_buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ring_buffer.h 3 | * @brief 环形缓冲,可实现两个线程无锁并行的读写数据 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_RINGBUFFER_H_ 8 | #define _THEFOX_BASE_RINGBUFFER_H_ 9 | 10 | #include 11 | 12 | namespace thefox { 13 | 14 | class RingBuffer 15 | { 16 | public: 17 | explicit RingBuffer(uint32_t size) 18 | : _in(0) 19 | , _out(0) 20 | { 21 | // 调整size到2的n次幂大小 22 | if (size & (size - 1)) { 23 | size = roundupPowOfTwo(size); 24 | } 25 | 26 | _size = size; 27 | 28 | _buffer = static_cast(malloc(_size)); 29 | 30 | } 31 | ~RingBuffer() 32 | { 33 | free(_buffer); 34 | } 35 | 36 | uint32_t put(char *buffer, uint32_t len) 37 | { 38 | len = MIN(len, _size - _in + _out); 39 | 40 | // 拷贝从_in -> end 41 | uint32_t l = MIN(len, _size - (_in & (_size - 1))); 42 | memcpy(_buffer + (_in & (_size - 1)), buffer, l); 43 | 44 | // 拷贝从 begin -> 剩余的部分 45 | memcpy(_buffer, buffer + l, len -1); 46 | 47 | _in += len; 48 | 49 | return len; 50 | } 51 | 52 | unit32_t get(char *buffer, uint32_t len) 53 | { 54 | len = MIN(len, _in - _out); 55 | 56 | // 拷贝从_out -> end 57 | unit32_t l = min(len, _size - (_out & (size - 1))); 58 | memcpy(buffer, _buffer + (_out & (_size - 1)), l); 59 | 60 | //拷贝剩余的 61 | memcpy(_buffer + l, _buffer, len - l); 62 | 63 | _out += len; 64 | 65 | return len; 66 | } 67 | 68 | unit32_t size() const { return _size; } 69 | unit32_t count() const { return _in - _out; } 70 | private: 71 | uint32_t roundupPowOfTwo(uint32_t size) 72 | { 73 | int n = 0; 74 | while (0 != size) { 75 | size > 1; 76 | ++n; 77 | } 78 | 79 | return 1 << (n + 1); 80 | } 81 | 82 | char *_buffer; 83 | uint32_t _size; // ringbuffer的总大小 84 | uint32_t _in; // 写数据的位置 85 | uint32_t _out; // 读数据的位置 86 | }; 87 | 88 | } // namespace thefox 89 | 90 | #endif // _THEFOX_BASE_RINGBUFFER_H_ 91 | -------------------------------------------------------------------------------- /base/scoped_ptr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * from boost 3 | */ 4 | 5 | #ifndef _THEFOX_BASE_SCOPED_PTR_H_ 6 | #define _THEFOX_BASE_SCOPED_PTR_H_ 7 | 8 | namespace thefox { 9 | 10 | 11 | // scoped_ptr mimics a built-in pointer except that it guarantees deletion 12 | // of the object pointed to, either on destruction of the scoped_ptr or via 13 | // an explicit reset(). scoped_ptr is a simple solution for simple needs; 14 | // use shared_ptr or std::auto_ptr if your needs are more complex. 15 | 16 | template class scoped_ptr // noncopyable 17 | { 18 | private: 19 | 20 | T * ptr; 21 | 22 | scoped_ptr(scoped_ptr const &); 23 | scoped_ptr & operator=(scoped_ptr const &); 24 | 25 | typedef scoped_ptr this_type; 26 | 27 | public: 28 | 29 | typedef T element_type; 30 | 31 | explicit scoped_ptr(T * p = 0): ptr(p) // never throws 32 | { 33 | } 34 | 35 | ~scoped_ptr() // never throws 36 | { 37 | if (0 != ptr) { 38 | delete ptr; 39 | } 40 | } 41 | 42 | void reset(T * p = 0) // never throws 43 | { 44 | this_type(p).swap(*this); 45 | } 46 | 47 | T & operator*() const // never throws 48 | { 49 | return *ptr; 50 | } 51 | 52 | T * operator->() const // never throws 53 | { 54 | return ptr; 55 | } 56 | 57 | T * get() const // never throws 58 | { 59 | return ptr; 60 | } 61 | 62 | bool operator! () const // never throws 63 | { 64 | return ptr == 0; 65 | } 66 | 67 | void swap(scoped_ptr & b) // never throws 68 | { 69 | T * tmp = b.ptr; 70 | b.ptr = ptr; 71 | ptr = tmp; 72 | } 73 | }; 74 | 75 | template inline void swap(scoped_ptr & a, scoped_ptr & b) // never throws 76 | { 77 | a.swap(b); 78 | } 79 | 80 | // get_pointer(p) is a generic way to say p.get() 81 | 82 | template inline T * get_pointer(scoped_ptr const & p) 83 | { 84 | return p.get(); 85 | } 86 | 87 | } // namespace thefox 88 | 89 | #endif // _THEFOX_BASE_SCOPEDPTR_H_ 90 | -------------------------------------------------------------------------------- /base/semaphore.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_SEMAPHORE_H_ 2 | #define _THEFOX_NET_SEMAPHORE_H_ 3 | 4 | #ifdef WIN32 5 | #define WIN32_LEAN_AND_MEAN 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | 16 | class Semaphore 17 | { 18 | public: 19 | #ifdef _WIN32 20 | static const uint32_t kInfinite = INFINITE; 21 | typedef HANDLE sem_t; 22 | #else 23 | static const uint32_t kInfinite = UINT_MAX; 24 | #endif 25 | 26 | Semaphore(int32_t num = 0) 27 | { 28 | #ifdef _WIN32 29 | _sem = ::CreateSemaphore(NULL, num, LONG_MAX, NULL); 30 | #else 31 | sem_init(&_sem, 0, num); 32 | #endif 33 | } 34 | ~Semaphore() 35 | { 36 | #ifdef _WIN32 37 | if (NULL != _sem) { 38 | if (0 != ::CloseHandle(_sem)) { 39 | _sem = NULL; 40 | } 41 | } 42 | #else 43 | sem_destroy(&_sem); 44 | #endif 45 | } 46 | 47 | // P 48 | bool wait(uint32_t millisecond = kInfinite) 49 | { 50 | #ifdef _WIN32 51 | if (NULL == _sem) 52 | return false; 53 | 54 | DWORD ret = ::WaitForSingleObject(_sem, millisecond); 55 | if (WAIT_OBJECT_0 == ret || WAIT_ABANDONED == ret) { 56 | return true; 57 | } else { 58 | return false; 59 | } 60 | #else 61 | int32_t ret = 0; 62 | 63 | if (kInfinite == millisecond) { 64 | ret = sem_wait(&_sem); 65 | } else { 66 | struct timespec ts = {0, 0}; 67 | TimeUtil::getAbsTimespec(&ts, millisecond); 68 | ret = sem_timedwait(&_sem, &ts); 69 | } 70 | 71 | return -1 != ret; 72 | #endif 73 | } 74 | 75 | // V 76 | bool signal() 77 | { 78 | #ifdef _WIN32 79 | BOOL ret = FALSE; 80 | 81 | if (NULL != _sem) { 82 | ret = ::ReleaseSemaphore(_sem, 1, NULL); 83 | } 84 | return TRUE == ret; 85 | #else 86 | return -1 != sem_post(&_sem); 87 | #endif 88 | } 89 | 90 | private: 91 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Semaphore); 92 | sem_t _sem; 93 | }; 94 | 95 | } // namespace thefox 96 | #endif // _THEFOX_NET_SEMAPHORE_H_ -------------------------------------------------------------------------------- /base/shared_ptr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename shared_ptr.h 3 | * @brief 基于引用计数的智能指针 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_SHARED_PTR_H_ 8 | #define _THEFOX_BASE_SHARED_PTR_H_ 9 | 10 | #include 11 | 12 | namespace thefox { 13 | 14 | class PtrCounter 15 | { 16 | public: 17 | PtrCounter() 18 | : _spCOunter(0), _wkCounter(0) {} 19 | ~PtrCounter() {} 20 | 21 | size_t addSpRef() 22 | { 23 | MutexGuard lock(_mutex); 24 | return ++_spCounter; 25 | } 26 | size_t releaseSp() 27 | { 28 | MutexGuard lock(_mutex); 29 | return --_spCounter; 30 | } 31 | const size_t spCounter() const { return _spCounter; } 32 | 33 | size_t addWkRef() 34 | { 35 | MutexGuard lock(_mutex); 36 | return ++_wkCounter; 37 | } 38 | size_t releaseWk() 39 | { 40 | MutexGuard lock(_mutex); 41 | return --_wkCounter; 42 | } 43 | const size_t wkCounter() const { return _wkCounter; } 44 | 45 | private: 46 | Mutecx _mutex; 47 | size_t _spCounter; 48 | size_t _wkCounter 49 | }; 50 | 51 | 52 | template 53 | class shared_ptr 54 | { 55 | public: 56 | shared_ptr() 57 | :_pointer(NULL), _counter(NULL) {} 58 | shared_ptr(T *p) 59 | : _pointer(p) , _counter(new PtrCounter()) 60 | { 61 | if (NULL != _pointer) { 62 | _counter->addSpRef(); 63 | } 64 | } 65 | 66 | shared_ptr(const shared_ptr &rsp) 67 | : _pointer(rsp._pointer), _counter(rps._counter) 68 | { 69 | if (NULL != _counter) { 70 | _counter->addSpRef(); 71 | } 72 | } 73 | 74 | ~shared_ptr() 75 | { 76 | if (NULL != _pointer) { 77 | if (0 == _pointer->release()) { 78 | SAFE_DELETE(_pointer); 79 | } 80 | } 81 | } 82 | 83 | shared_ptr &operator=(const shared_ptr &rsp) 84 | { 85 | if (_pointer != rsp._pointer) { 86 | if (NULL != _pointer) { 87 | if (0 == _pointer->release()) { 88 | SAFE_DELETE(_pointer); 89 | } 90 | } 91 | _pointer = rsp._pointer; 92 | _pointer->addRef(); 93 | } 94 | return *this; 95 | } 96 | 97 | T &operator*() 98 | { return *_pointer; } 99 | 100 | T *operator->() 101 | { return _pointer;} 102 | 103 | operator bool() 104 | { return NULL != _pointer; } 105 | 106 | bool operator==(const shared_ptr &rsp) 107 | { return _pointer == rsp._pointer; } 108 | 109 | size_t use_count() const 110 | { return (NULL != _pointer) ? _pointer->use_count() : 0; } 111 | 112 | private: 113 | addRef() 114 | { 115 | if (NULL == _counter) { 116 | _counter = new PtrCounter(); 117 | } 118 | _counter->addSpRef(); 119 | } 120 | 121 | size_t release() 122 | { 123 | if (NULL == _counter) { 124 | return 0; 125 | } else { 126 | return _counter->releaseSp(); 127 | } 128 | } 129 | 130 | T *_pointer; 131 | PtrCounter *_counter; 132 | }; 133 | 134 | template 135 | inline SharedPtr make_shared(T *p) 136 | { 137 | return SharedPtr(p); 138 | } 139 | 140 | } // namespace thefox; 141 | 142 | #endif // _THEFOX_BASE_SHARED_PTR_H_ 143 | -------------------------------------------------------------------------------- /base/singleton.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename singleton.h 3 | * @brief 单例模式 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_SINGLETION_H_ 8 | #define _THEFOX_BASE_SINGLETION_H_ 9 | 10 | namespace thefox { 11 | 12 | template 13 | class singleton : private T 14 | { 15 | public: 16 | static T &instance() 17 | { 18 | static singleton s_oT; 19 | return s_oT; 20 | } 21 | 22 | private: 23 | singleton() {} 24 | ~singleton() {} 25 | }; 26 | 27 | } // namespace thefox 28 | 29 | #endif // _THEFOX_BASE_SINGLETION_H_ -------------------------------------------------------------------------------- /base/stack.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename stack.h 3 | * @brief 使用数组实现的栈 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_STACK_H_ 8 | #define _THEFOX_BASE_STACK_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace thefox { 14 | 15 | /// @brief 栈的实现类 16 | template 17 | class Stack 18 | { 19 | public: 20 | Stack() 21 | {} 22 | ~Stack() 23 | {} 24 | 25 | /// @brief 入栈 26 | /// param[in] value 需要入栈的值 27 | void push(const T &value) 28 | { 29 | MutexGuard lock(_mutex); 30 | _data.push_back(value); 31 | } 32 | 33 | /// @brief 弹出栈顶 34 | void pop() 35 | { 36 | MutexGuard lock(_mutex); 37 | if (!_data.empty()) 38 | _data.pop_back(); 39 | } 40 | 41 | /// @brief 得到栈顶数据 42 | /// @param[out] value 得到的栈顶的值 43 | /// @return 成功返回true,否则返回false 44 | bool getTop(T &value) 45 | { 46 | MutexGuard lock(_mutex); 47 | if (!_data.empty()) { 48 | value = _data[_data.size() - 1]; 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | /// @brief 得到栈中指定位置的值 55 | /// @param[in] position 需要得到值的位置 56 | /// 从正数1开始递增,表示从栈顶向下遍历的位置 57 | /// 从负数-1开始递减,表示从栈底向上遍历的位置 58 | /// @param[out] value 得到position位置上的值 59 | /// @return 成功返回true,否则返回false 60 | bool getAt(const int position, T &value) 61 | { 62 | MutexGuard lock(_mutex); 63 | size_t index = 0; 64 | if (getIndexByPosition(position, index)) { 65 | value = _data[index]; 66 | return true; 67 | } 68 | return false; 69 | } 70 | 71 | /// @brief 给栈中指定位置赋值 72 | /// @param[in] position 需要赋值的位置 73 | /// 从正数1开始递增,表示从栈顶向下遍历的位置 74 | /// 从负数-1开始递减,表示从栈底向上遍历的位置 75 | /// @param[out] value 待设置的值 76 | /// @return 成功返回true,否则返回false 77 | bool setAt(const int position, const T &value) 78 | { 79 | MutexGuard lock(_mutex); 80 | size_t index = 0; 81 | if (getIndexByPosition(position, index)) { 82 | _data[index] = value; 83 | return true; 84 | } 85 | return false; 86 | } 87 | 88 | /// @brief 得到栈中数据个数 89 | /// @return 返回栈中数据个数 90 | size_t size() 91 | { 92 | MutexGuard lock(_mutex); 93 | return _data.size(); 94 | } 95 | 96 | /// @brief 判断是否是空栈 97 | /// @return 如果栈不为空返回true,否则返回false 98 | bool empty() 99 | { 100 | MutexGuard lock(_mutex); 101 | return _data.empty(); 102 | } 103 | 104 | private: 105 | // 通过Position得到在vector中的索引 106 | bool getIndexByPosition(const int position, size_t &index) const 107 | { 108 | if (_data.empty()) { 109 | return false; 110 | } 111 | 112 | if (position > 0) { // 从栈顶向下遍历 113 | int i = static_cast(_data.size() - position); 114 | if (i >= 0) { 115 | index = i; 116 | return true; 117 | } 118 | } else if (position < 0) { //从栈底向上遍历 119 | if (static_cast(_data.size()) + position >= 0) { 120 | index = (position * -1) - 1; 121 | return true; 122 | } 123 | } 124 | return false; 125 | } 126 | 127 | std::vector _data; 128 | Mutex _mutex; 129 | }; 130 | 131 | } // namespace thefox 132 | 133 | #endif // _THEFOX_BASE_STACK_H_ 134 | -------------------------------------------------------------------------------- /base/string_unicode.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_STRING_UNIDOCE_H_ 2 | #define _THEFOX_BASE_STRING_UNIDOCE_H_ 3 | 4 | #include 5 | 6 | namespace thefox { 7 | 8 | inline string bgkToUtf8(const string &str) 9 | { 10 | 11 | } 12 | 13 | inline string utf8ToGbk(const string &str) 14 | { 15 | 16 | } 17 | 18 | inline string gbkToUnicode(const string &str) 19 | { 20 | 21 | 22 | } 23 | 24 | inline string unicodeToGbk(const string &str) 25 | { 26 | 27 | } 28 | 29 | inline bool isUtf8(const char* str, size_t length) 30 | { 31 | size_t i; 32 | int32_t nBytes=0;//UFT8可用1-6个字节编码,ASCII用一个字节 33 | uchar chr; 34 | bool bAllAscii = true; //如果全部都是ASCII, 说明不是UTF-8 35 | 36 | for(i=0;i= 0x80) { 42 | if(chr >= 0xFC && chr <= 0xFD) 43 | nBytes = 6; 44 | else if(chr >= 0xF8) 45 | nBytes = 5; 46 | else if(chr >= 0xF0) 47 | nBytes = 4; 48 | else if(chr >= 0xE0) 49 | nBytes = 3; 50 | else if(chr >= 0xC0) 51 | nBytes = 2; 52 | else 53 | return false; 54 | 55 | nBytes--; 56 | } 57 | } else { //多字节符的非首字节,应为 10xxxxxx 58 | if((chr & 0xC0) != 0x80) 59 | return false; 60 | nBytes--; 61 | } 62 | } 63 | if(nBytes > 0) { //违返规则 64 | return false; 65 | 66 | return !bAllAscii; 67 | } 68 | 69 | } 70 | 71 | #endif // _THEFOX_BASE_STRING_UNIDOCE_H_ -------------------------------------------------------------------------------- /base/sys_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_SYS_UTIL_H_ 2 | #define _THEFOX_BASE_SYS_UTIL_H_ 3 | 4 | #ifdef WIN32 5 | #define WIN32_LEAN_AND_MEAN 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | 13 | namespace thefox { 14 | 15 | class SysUtil 16 | { 17 | public: 18 | static void msleep(uint32_t msec) 19 | { 20 | #ifdef WIN32 21 | ::Sleep(msec); 22 | #else 23 | usleep(msec * 1000); 24 | #endif 25 | } 26 | }; 27 | 28 | } // namespace thefox 29 | 30 | #endif // _THEFOX_BASE_SYS_UTIL_H_ -------------------------------------------------------------------------------- /base/table.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_TABLE_H_ 2 | #define _THEFOX_BASE_TABLE_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace thefox { 8 | 9 | template 10 | class Table 11 | { 12 | public: 13 | typedef std::vector Row; 14 | typedef std::vector TableType; 15 | 16 | Table(void) 17 | : _rowIndex(-1) 18 | {} 19 | Table(const Table &from) 20 | : _table(from._table) 21 | , _rowIndex(from._rowIndex) 22 | {} 23 | ~Table() 24 | {} 25 | 26 | const Table &operator=(const Table &from) 27 | { 28 | _table = from._table; 29 | _rowIndex = from._rowIndex; 30 | return *this; 31 | } 32 | 33 | int fieldCount() const 34 | { 35 | if (!_table.empty()) { 36 | return _table[0].size(); 37 | } 38 | return 0; 39 | } 40 | 41 | int rowCount() const 42 | { return _table.size(); } 43 | 44 | bool fetchRow() 45 | { 46 | if (_table.empty()) { 47 | return false; 48 | } 49 | if (++_rowIndex >= _table.size()) { 50 | return false; 51 | } else { 52 | return true; 53 | } 54 | } 55 | 56 | const T &operator[](const int index) const 57 | { 58 | assert(_rowIndex < _table.size()); 59 | assert(index < _table[_rowIndex].size()); 60 | 61 | return _table[_rowIndex][index]; 62 | } 63 | 64 | operator bool() const 65 | { return !_table.empty(); } 66 | 67 | Row *addRow() 68 | { 69 | Row row; 70 | _table.push_back(row); 71 | return &_table[_table.size() - 1]; 72 | } 73 | 74 | void clear() 75 | { _table.clear(); } 76 | 77 | bool empty() const 78 | { return _table.empty(); } 79 | 80 | private: 81 | TableType _table; 82 | int _rowIndex; 83 | }; 84 | 85 | } // namespace thefox 86 | 87 | #endif // _THEFOX_BASE_TABLE_H_ -------------------------------------------------------------------------------- /base/test/atomic_integer_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | thefox::AtomicInt32 i32; 8 | i32.inc(); 9 | i32.dec(); 10 | 11 | thefox::AtomicInt64 i64; 12 | i64.inc(); 13 | i64.dec(); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /base/test/condition_untitest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace thefox; 7 | 8 | Mutex *mutex; 9 | Condition *cond; 10 | 11 | void testThreadA() 12 | { 13 | while (true) { 14 | usleep(1000*1000); 15 | cond->notify(); 16 | cond->notify(); 17 | } 18 | } 19 | 20 | void testThreadB() 21 | { 22 | MutexGuard lock(*mutex); 23 | while (true) { 24 | cond->wait(); 25 | printf("%u, cond->wait done\n", currentThreadId()); 26 | } 27 | } 28 | 29 | int main(int argc, char **argv) 30 | { 31 | mutex = new Mutex(); 32 | cond = new Condition(*mutex); 33 | 34 | Thread a(testThreadA, "testThreadA"); 35 | 36 | Thread b(testThreadB, "testThreadB"); 37 | Thread c(testThreadB, "testThreadB"); 38 | Thread d(testThreadB, "testThreadB"); 39 | 40 | a.start(); 41 | b.start(); 42 | c.start(); 43 | d.start(); 44 | 45 | a.join(); 46 | b.join(); 47 | c.start(); 48 | d.start(); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /base/test/debug_win_unittest.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/base/test/debug_win_unittest.cc -------------------------------------------------------------------------------- /base/test/mem_pool_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace thefox; 6 | 7 | class TestA 8 | { 9 | int32_t _usedBuf; 10 | char _buffer[4]; 11 | }; 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | MemPool testaPool; 16 | 17 | TestA *ta = testaPool.get(); 18 | TestA *tb = testaPool.get(); 19 | TestA *tc = testaPool.get(); 20 | TestA *td = testaPool.get(); 21 | TestA *te = testaPool.get(); 22 | TestA *tf = testaPool.get(); 23 | TestA *tg = testaPool.get(); 24 | TestA *th = testaPool.get(); 25 | 26 | testaPool.put(ta); 27 | testaPool.put(tb); 28 | testaPool.put(tc); 29 | testaPool.put(td); 30 | testaPool.put(te); 31 | testaPool.put(tf); 32 | testaPool.put(tg); 33 | testaPool.put(th); 34 | 35 | ta = testaPool.get(); 36 | tb = testaPool.get(); 37 | tc = testaPool.get(); 38 | td = testaPool.get(); 39 | te = testaPool.get(); 40 | tf = testaPool.get(); 41 | tg = testaPool.get(); 42 | th = testaPool.get(); 43 | TestA *ti = testaPool.get(); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /base/test/object_pool_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox; 5 | 6 | class TestA 7 | { 8 | public: 9 | TestA(const string &str) 10 | : _str(str) {} 11 | ~TestA() {} 12 | string str() const { return _str; } 13 | private: 14 | string _str; 15 | }; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | ObjectPool pool; 20 | TestA *a = pool.get("hi"); 21 | assert(NULL !=a); 22 | assert(a->str() == "hi"); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /base/test/stack_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | thefox::Stack s; 7 | s.push(3); 8 | s.push(5); 9 | int i; 10 | s.getTop(i); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /base/test/thread_win_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using thefox::Thread; 5 | using thefox::ThreadGroup; 6 | 7 | void foo() 8 | { 9 | printf("this is a thread function output\r\n"); 10 | } 11 | 12 | int main(int argc, char **argv) 13 | { 14 | printf("--- Thread ---\r\n"); 15 | Thread t(&foo); 16 | t.start(); 17 | t.join(); 18 | 19 | printf("--- ThreadGroup ---\r\n"); 20 | ThreadGroup tg; 21 | Thread t1(&foo); 22 | tg.addThread(&t1); 23 | tg.createThread(&foo); 24 | tg.createThread(&foo); 25 | tg.startAll(); 26 | tg.joinAll(); 27 | 28 | getchar(); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /base/test/timestamp_unittest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | printf("%ld\n", time(NULL)); 7 | thefox::Timestamp t(thefox::Timestamp::now()); 8 | printf("%s\n", t.toString().c_str()); 9 | printf("%s\n", t.toFormatString().c_str()); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /base/thread_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_THREADPOOL_H_ 2 | #define _THEFOX_BASE_THREADPOOL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace thefox { 11 | 12 | typedef std::function TaskMethod; 13 | 14 | class ThreadPool 15 | { 16 | public: 17 | ThreadPool() 18 | : _inited(false) 19 | {} 20 | ~ThreadPool() 21 | {} 22 | 23 | /// @brief 初始化线程池 24 | /// @param[in] threadNum 线程个数 25 | bool init(int threadNum = kDefaultThreadNum) 26 | { 27 | if (_inited) { 28 | return false; 29 | } 30 | _inited = true; 31 | addWorker(threadNum); 32 | return _inited; 33 | } 34 | 35 | /// @brief 添加线程任务 36 | void addTask(const TaskMethod &task) 37 | { _tasks.put(task); } 38 | 39 | /// @brief 等待线程池结束 40 | void join() 41 | { 42 | for (ThreadVector::const_iterator it = _threads.begin(); it != _threads.end(); ++it) { 43 | (*it)->join(); 44 | } 45 | 46 | _threads.clear(); 47 | } 48 | 49 | /// @brief 得到线程个数 50 | size_t size() const { return _threads.size(); } 51 | 52 | /// @brief 结束线程池 53 | void terminate() 54 | { 55 | for (ThreadVector::const_iterator it = _threads.begin(); it != _threads.end(); ++it) { 56 | (*it)->stop(); 57 | } 58 | } 59 | 60 | private: 61 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(ThreadPool); 62 | typedef std::vector> ThreadVector; 63 | 64 | class TaskQueue 65 | { 66 | public: 67 | TaskQueue() {} 68 | ~TaskQueue() {} 69 | 70 | void put(const TaskMethod &task) 71 | { 72 | MutexLockGuard lock(_mutex); 73 | _tasks.push(task); 74 | _sem.signal(); 75 | } 76 | ThreadCallback get() 77 | { 78 | TaskMethod task; 79 | _sem.wait(Semaphore::kInfinite); 80 | MutexLockGuard lock(_mutex); 81 | task = _tasks.front(); 82 | _tasks.pop(); 83 | return task; 84 | } 85 | 86 | private: 87 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TaskQueue); 88 | typedef std::queue Tasks; 89 | Tasks _tasks; 90 | MutexLock _mutex; 91 | Semaphore _sem; 92 | }; 93 | 94 | // 添加工作线程 95 | void addWorker(int threadNum) 96 | { 97 | for (int i = 0; i < threadNum; ++i) { 98 | std::shared_ptr thread(new Thread(std::bind(&ThreadPool::taskRunner, this))); 99 | _threads.push_back(thread); 100 | thread->start(); 101 | } 102 | } 103 | 104 | // 运行任务 105 | void taskRunner() 106 | { 107 | while(true) { 108 | TaskMethod task = _tasks.get(); 109 | task(); 110 | } 111 | } 112 | 113 | bool _inited; 114 | ThreadVector _threads; 115 | TaskQueue _tasks; 116 | 117 | static const int32_t kDefaultThreadNum = 10; 118 | }; 119 | 120 | } // namespace thefox 121 | 122 | #endif // _THEFOX_BASE_THREADPOOL_H_ -------------------------------------------------------------------------------- /base/thread_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_THREAD_UTIL_H_ 2 | #define _THEFOX_BASE_THREAD_UTIL_H_ 3 | 4 | #ifdef WIN32 5 | #else 6 | #include 7 | #endif 8 | 9 | #include 10 | 11 | namespace thefox { 12 | 13 | #ifdef WIN32 14 | #define currentThreadId (uint32_t)::GetCurrentThreadId 15 | #else 16 | #define currentThreadId (uint32_t)pthread_self 17 | #endif 18 | 19 | } // namespace thefox 20 | 21 | #endif // _THEFOX_BASE_THREAD_UTIL_H_ 22 | -------------------------------------------------------------------------------- /base/time_util.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/base/time_util.h -------------------------------------------------------------------------------- /base/timestamp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename timestamp.h 3 | * @brief 时间戳,精确到1微妙,格式:20131001 08:30:00.0000000 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_BASE_TIMESTAMP_H_ 8 | #define _THEFOX_BASE_TIMESTAMP_H_ 9 | 10 | #ifdef WIN32 11 | #define WIN32_LEAN_AND_MEAN 12 | #include 13 | #else 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | 20 | namespace thefox { 21 | 22 | class Timestamp 23 | { 24 | public: 25 | Timestamp() 26 | : _usTimestamp(0) 27 | {} 28 | Timestamp(int64_t usTimestamp) 29 | : _usTimestamp(usTimestamp) 30 | {} 31 | Timestamp(const Timestamp &ts) 32 | : _usTimestamp(ts._usTimestamp) 33 | {} 34 | 35 | string toString() 36 | { 37 | char buf[32] = {0}; 38 | int64_t seconds = _usTimestamp / kMicroSecondsPerSecond; 39 | int64_t microseconds = _usTimestamp % kMicroSecondsPerSecond; 40 | snprintf(buf, sizeof(buf), "%lld.%06lld", seconds, microseconds); 41 | return buf; 42 | } 43 | 44 | string toFormatString() 45 | { 46 | char buf[32] = {0}; 47 | time_t seconds = static_cast(_usTimestamp / kMicroSecondsPerSecond); 48 | int microseconds = static_cast(_usTimestamp % kMicroSecondsPerSecond); 49 | tm *tm_time = localtime(&seconds); 50 | 51 | snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d", 52 | tm_time->tm_year + 1900, tm_time->tm_mon + 1, tm_time->tm_mday, 53 | tm_time->tm_hour, tm_time->tm_min, tm_time->tm_sec, 54 | microseconds); 55 | return buf; 56 | } 57 | 58 | time_t toUnixTimestamp() const 59 | { return static_cast(_usTimestamp / kMicroSecondsPerSecond); } 60 | 61 | int64_t timestamp() const { return _usTimestamp; } 62 | 63 | bool valid() const { return _usTimestamp > 0; } 64 | 65 | #ifdef WIN32 66 | LARGE_INTEGER toLargeInt() const 67 | { 68 | LARGE_INTEGER li; 69 | li.QuadPart = (_usTimestamp * 10) + 116444736000000000; 70 | return li; 71 | } 72 | #endif 73 | 74 | static Timestamp now() 75 | { 76 | #ifdef WIN32 77 | FILETIME ft; 78 | ULARGE_INTEGER ui; 79 | GetSystemTimeAsFileTime(&ft); // 精确到100ns 80 | ui.LowPart = ft.dwLowDateTime; 81 | ui.HighPart = ft.dwHighDateTime; 82 | return Timestamp(static_cast(ui.QuadPart - 116444736000000000) / 10); 83 | #else 84 | struct timeval tv; 85 | gettimeofday(&tv, NULL); 86 | int64_t seconds = tv.tv_sec; 87 | return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec); 88 | #endif 89 | } 90 | 91 | static Timestamp invalid() { return Timestamp(); } 92 | 93 | static const int kMicroSecondsPerSecond = 1000 * 1000; 94 | 95 | private: 96 | int64_t _usTimestamp; 97 | }; 98 | 99 | inline bool operator<(Timestamp lhs, Timestamp rhs) 100 | { 101 | return lhs.timestamp() < rhs.timestamp(); 102 | } 103 | 104 | inline bool operator<=(Timestamp lhs, Timestamp rhs) 105 | { 106 | return lhs.timestamp() <= rhs.timestamp(); 107 | } 108 | 109 | inline bool operator==(Timestamp lhs, Timestamp rhs) 110 | { 111 | return lhs.timestamp() == rhs.timestamp(); 112 | } 113 | 114 | } // namespace thefox 115 | 116 | #endif // _THEFOX_BASE_TIMESTAMP_H_ 117 | -------------------------------------------------------------------------------- /base/uuid.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_BASE_UUID_H_ 2 | #define _THEFOX_BASE_UUID_H_ 3 | 4 | /** 5 | * linux: -luuid 6 | */ 7 | 8 | #include 9 | #ifdef WIN32 10 | #else 11 | #include 12 | #endif 13 | 14 | namespace thefox { 15 | 16 | inline string createUuid() 17 | { 18 | 19 | char buf[64] = {0}; 20 | #ifdef WIN32 21 | GUID guid; 22 | if (S_OK == CoCreateGuid(&guid)){ 23 | snprintf(buf, sizeof(buf), 24 | "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", 25 | guid.Data1, guid.Data2, guid.Data3, 26 | guid.Data4[0], guid.Data4[1], 27 | guid.Data4[2], guid.Data4[3], 28 | guid.Data4[4], guid.Data4[5], 29 | guid.Data4[6], guid.Data4[7]); 30 | } 31 | #else 32 | uuid_t uu; 33 | uuid_generate(uu); 34 | if (!uuid_is_null(uu)) { 35 | snprintf(buf, sizeof(buf), 36 | "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 37 | uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], 38 | uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); 39 | } 40 | #endif 41 | 42 | return buf; 43 | } 44 | 45 | } // namespace thefox 46 | 47 | #endif // _THEFOX_BASE_UUID_H_ -------------------------------------------------------------------------------- /db/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | INCLUDE=./.. 3 | LIBRARY=mysqlclient 4 | 5 | testmysql: test.cpp 6 | $(CC) -std=c++0x -o $@ $^ -I$(INCLUDE) -l$(LIBRARY) 7 | -------------------------------------------------------------------------------- /db/README.md: -------------------------------------------------------------------------------- 1 | # 对libmysql简单的C++封装 2 | 3 | **使用方法:** 4 | 5 | #include 6 | using namespace thefox::db; 7 | 8 | int main(int argc, char **argv) 9 | { 10 | 11 | 12 | MySqlConnection db("localhost", "root", "srdLHnms"); 13 | db.open(); 14 | MySqlResultSet rs; 15 | db.query("select id,name from table", rs)) 16 | while (rs.fetchRow()) 17 | { 18 | int id = rs.getInt(0); 19 | String name = rs.getString(1); 20 | } 21 | db.close(); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /db/mysql_result_set.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename mysql_result_set.h 3 | * @brief libmysql结果集的C++封装类,支持Windows和Linux 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_DB_MYSQL_RESULTSET_H_ 8 | #define _THEFOX_DB_MYSQL_RESULTSET_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace thefox { 14 | namespace db { 15 | 16 | /// @beirf 结果集类 17 | class MySqlResultSet 18 | { 19 | public: 20 | MySqlResultSet() 21 | : _res(NULL) 22 | , _row(NULL) 23 | {} 24 | 25 | ~MySqlResultSet() 26 | { 27 | if (_res) { 28 | mysql_free_result(_res); 29 | _res = NULL; 30 | } 31 | } 32 | 33 | /// @beirf 得到字段的数量 34 | int fieldCount() const 35 | { 36 | if (!_res) 37 | return 0; 38 | return _res->field_count; 39 | } 40 | 41 | /// @beirf 得到索引指定的字段的名称 42 | const char *fieldName(int index) const 43 | { 44 | if (!_res) 45 | return ""; 46 | if (index < 0 || index >= _res->field_count) 47 | return ""; 48 | return _res->fields[index].name; 49 | } 50 | 51 | /// @beirf 得到结果集中有多少行记录 52 | int rowCount() const 53 | { 54 | if (!_res) 55 | return 0; 56 | return (int)_res->row_count; 57 | } 58 | 59 | /// @beirf 取下一行的记录 60 | /// @return true表示成功取到下一行,false表示已经全部取完了 61 | bool fetchRow() 62 | { 63 | if (!_res) 64 | return false; 65 | if (_row = mysql_fetch_row(_res)) 66 | return true; 67 | else 68 | return false; 69 | } 70 | 71 | /// @beirf 根据索引得到字符串类型的值 72 | /// @param[in] index 字段索引号 73 | /// @return 返回对应的值 74 | const char *getString(const int index) const 75 | { 76 | if (!_res || !_row) 77 | return ""; 78 | if (index < 0 || index >= fieldCount()) 79 | return ""; 80 | return _row[index] ? _row[index] : ""; 81 | } 82 | 83 | /// @beirf 根据索引得到字符串类型的值 84 | /// @param[in] fiendName 字段的名称 85 | /// @return 返回对应的值 86 | const char *getString(const String &fieldName) const 87 | { 88 | int index = getFieldIndex(fieldName); 89 | if (index >= 0) 90 | return _row[index] ? _row[index] : ""; 91 | return ""; 92 | } 93 | 94 | /// @beirf 根据索引得到int类型的值 95 | /// @param[in] index 字段索引号 96 | /// @return 返回对应的值 97 | int getInt(const int index) const 98 | { return atoi(getString(index)); } 99 | 100 | int64_t getInt64(const int index) const 101 | { 102 | int64_t v = 0; 103 | sscanf(getString(index), "%lld", &v); 104 | return v; 105 | } 106 | 107 | /// @beirf 根据索引得到int类型的值 108 | /// @param[in] fiendName 字段的名称 109 | /// @return 返回对应的值 110 | int getInt(const string &fieldName) const 111 | { return atoi(getString(fieldName)); } 112 | 113 | /// @beirf 根据索引得到uint类型的值 114 | /// @param[in] index 字段索引号 115 | /// @return 返回对应的值 116 | uint32_t getUInt(const int index) const 117 | { return (uint32_t)atoi(getString(index)); } 118 | 119 | /// @beirf 根据索引得到uint类型的值 120 | /// @param[in] fiendName 字段的名称 121 | /// @return 返回对应的值 122 | uint32_t getUInt(const string &fieldName) const 123 | { return (uint32_t)atoi(getString(fieldName)); } 124 | 125 | /// @beirf 根据索引得到一个字符串类型值 126 | /// @return 返回索引号对应的值 127 | /// @sa getString 128 | const char *operator[](const int index) const 129 | { 130 | return getString(index); 131 | } 132 | 133 | operator bool() const 134 | { return NULL == _res; } 135 | 136 | operator MYSQL_RES *() const 137 | { return _res; } 138 | 139 | const MySqlResultSet &operator=(MYSQL_RES *res) 140 | { 141 | _res = res; 142 | return *this; 143 | } 144 | 145 | private: 146 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(MySqlResultSet); 147 | 148 | int getFieldIndex(const string &fieldName) const 149 | { 150 | for (int i = 0; i < _res->field_count; ++i) { 151 | if (fieldName == _res->fields[i].name) 152 | return i; 153 | } 154 | return -1; 155 | } 156 | 157 | MYSQL_RES *_res; 158 | MYSQL_ROW _row; 159 | }; 160 | 161 | } // namespace db 162 | 163 | } // namespace thefox 164 | 165 | #endif // _THEFOX_DB_MYSQL_RESULTSET_H_ 166 | -------------------------------------------------------------------------------- /db/mysql_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename mysql_util.h 3 | * @brief mysql的一些好用的辅助函数,支持Windows和Linux 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_DB_MYSQL_UTIL_H_ 8 | #define _THEFOX_DB_MYSQL_UTIL_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | namespace db { 16 | 17 | class MysqlUtil 18 | { 19 | public: 20 | typedef std::map VariableMap; 21 | typedef std::map StatusMap; 22 | 23 | static bool isTableExist(MySqlConnection &conn, const string &tableName) 24 | { 25 | MySqlResultSet resultSet; 26 | string sql("SHOW TABLES LIKE '"+ tableName+"'"); 27 | conn.query(sql, resultSet); 28 | if (0 == resultSet.rowCount()) { 29 | return false; 30 | } else { 31 | return true; 32 | } 33 | } 34 | 35 | static bool isQueryNotRecord(MySqlConnection &conn, const string &selectSql) 36 | { 37 | MySqlResultSet resultSet; 38 | conn.query(selectSql, resultSet); 39 | if (0 == resultSet.rowCount()) { 40 | return false; 41 | } else { 42 | return true; 43 | } 44 | } 45 | 46 | static bool setNames(MySqlConnection &conn, const string &csName) 47 | { 48 | string sql("SET NAMES '"+ csName+"'"); 49 | return conn.exec(sql); 50 | } 51 | 52 | static VariableMap getVariable(MySqlConnection &conn, const string &keys) 53 | { 54 | VariableMap result; 55 | MySqlResultSet rs; 56 | string strsql("show variables"); 57 | if (!keys.empty()) { 58 | strsql += " where Variable_name in ("; 59 | strsql += keys; 60 | strsql += ")"; 61 | } 62 | 63 | conn.query(strsql, rs); 64 | while (rs.fetchRow()) { 65 | result[rs.getString(0)] = rs.getString(1); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | static StatusMap getGlobalStatus(MySqlConnection &conn, const string &keys) 72 | { 73 | StatusMap result; 74 | MySqlResultSet rs; 75 | string strsql("show global status"); 76 | if (!keys.empty()) { 77 | strsql += " where Variable_name in ("; 78 | strsql += keys; 79 | strsql += ")"; 80 | } 81 | 82 | conn.query(strsql, rs); 83 | while (rs.fetchRow()) { 84 | result[rs.getString(0)] = rs.getString(1); 85 | } 86 | 87 | return result; 88 | } 89 | }; 90 | 91 | } // nsmespace db 92 | } // namespace thefox 93 | 94 | #endif // _THEFOX_DB_MYSQL_UTIL_H_ 95 | 96 | -------------------------------------------------------------------------------- /db/test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox::db; 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | MySqlConnection mysql; 9 | mysql.setParam("localhost","root","root",3306,"test"); 10 | mysql.open(); 11 | MySqlResultSet rs; 12 | if (mysql.query("select now()", rs)) 13 | { 14 | while (rs.fetchRow()) 15 | { 16 | printf("%s\r\n", rs.getString(0)); 17 | } 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /log/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -Wall -std=c++0x -fPIC -shared 3 | INCLUDE = .. 4 | 5 | logging.o: logging.cc 6 | $(CC) $(CFLAGS) -I$(INCLUDE) -o $@ -c $^ 7 | 8 | log_file.o: log_file.cc 9 | $(CC) $(CFLAGS) -I$(INCLUDE) -o $@ -c $^ 10 | 11 | log_syslog.o: log_syslog.cc 12 | $(CC) $(CFLAGS) -I$(INCLUDE) -o $@ -c $^ 13 | 14 | clean: 15 | rm -rf *.o *.a 16 | -------------------------------------------------------------------------------- /log/README.md: -------------------------------------------------------------------------------- 1 | # 日志操作库 2 | 3 | supported for windows and linux 4 | 使用: 5 | 6 | #include "stdafx.h" 7 | #include 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | thefox::LogFile log("logs","TestLog"); // 在该变量生命周期内使用才有效 12 | 13 | THEFOX_LOG(TRACE) <<"dddddddd" << "dfdfd"; 14 | THEFOX_LOG(DEBUG) << "dfdf" << 12 << -12.23; 15 | THEFOX_LOG(INFO) << "dfdf"; 16 | THEFOX_LOG(WARN) << "dfdf"; 17 | THEFOX_LOG(ERROR) << "dfdf"; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /log/log_file.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace thefox; 6 | 7 | static LogFile *g_logFile = NULL; 8 | 9 | void THEFOX_SET_LOG_FILE(const string &dir, const string &basename, size_t rollSize) 10 | { 11 | if (g_logFile) { 12 | delete g_logFile; 13 | g_logFile = NULL; 14 | } 15 | g_logFile = new LogFile(dir, basename, rollSize); 16 | } 17 | 18 | void logFileAppend(const string &message) 19 | { 20 | if (g_logFile) { 21 | g_logFile->append(message); 22 | } 23 | } 24 | 25 | // not thread safe 26 | class LogFile::File 27 | { 28 | public: 29 | explicit File(const string& filename) 30 | : _fp(fopen(filename.data(), "a")) 31 | , _writtenBytes(0) 32 | { 33 | setvbuf(_fp, _buffer, _IOFBF, sizeof(_buffer)); 34 | } 35 | 36 | ~File() 37 | { 38 | fclose(_fp); 39 | } 40 | 41 | void append(const char* logline, const size_t len) 42 | { 43 | size_t n = write(logline, len); 44 | size_t remain = len - n; 45 | while (remain > 0) { 46 | size_t x = write(logline + n, remain); 47 | if (x == 0) { 48 | int err = ferror(_fp); 49 | if (err) { 50 | //TODO::错误处理 51 | } 52 | break; 53 | } 54 | n += x; 55 | remain = len - n; 56 | } 57 | 58 | _writtenBytes += len; 59 | } 60 | 61 | void flush() 62 | { 63 | fflush(_fp); 64 | } 65 | 66 | size_t writtenBytes() const { return _writtenBytes; } 67 | 68 | private: 69 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(File); 70 | size_t write(const char* logline, size_t len) 71 | { 72 | return ::fwrite(logline, 1, len, _fp); 73 | } 74 | 75 | FILE* _fp; 76 | char _buffer[64*1024]; 77 | size_t _writtenBytes; 78 | }; 79 | 80 | LogFile::LogFile(const string &dir, const string& basename, size_t rollSize) 81 | : _dir(dir) 82 | , _basename(basename) 83 | , _rollSize(rollSize) 84 | , _startOfPeriod(0) 85 | , _lastRoll(0) 86 | , _file(NULL) 87 | { 88 | Files::makePath(_dir); 89 | rollFile(); 90 | thefoxSetLogHandler(logFileAppend); 91 | } 92 | 93 | LogFile::~LogFile() 94 | { 95 | thefoxSetLogHandler(NULL); 96 | 97 | if (NULL != _file) 98 | delete _file; 99 | } 100 | 101 | void LogFile::append(const string &message) 102 | { 103 | MutexGuard lock(_mutex); 104 | _file->append(message.c_str(), message.length()); 105 | _file->append("\n", 1); 106 | 107 | if (_file->writtenBytes() > _rollSize) { 108 | rollFile(); 109 | } else { 110 | time_t now = ::time(NULL); 111 | time_t _thisPeriod = now / _kRollPerSeconds * _kRollPerSeconds; 112 | if (_thisPeriod != _startOfPeriod) 113 | rollFile(); 114 | else 115 | _file->flush(); 116 | } 117 | } 118 | 119 | void LogFile::flush() 120 | { 121 | MutexGuard lock(_mutex); 122 | _file->flush(); 123 | } 124 | 125 | void LogFile::rollFile() 126 | { 127 | time_t now = 0; 128 | string filename = getLogFileName(_dir, _basename, &now); 129 | time_t start = now / _kRollPerSeconds * _kRollPerSeconds; 130 | 131 | if (now > _lastRoll) { 132 | _lastRoll = now; 133 | _startOfPeriod = start; 134 | if (NULL != _file) 135 | delete _file; 136 | _file = new File(filename); 137 | } 138 | } 139 | 140 | string LogFile::getLogFileName(const string &dir, const string& basename, time_t *now) 141 | { 142 | string filename; 143 | 144 | filename.reserve(dir.size() + basename.size() + 64); 145 | filename = dir + basename; 146 | 147 | char timebuf[32]; 148 | char pidbuf[32]; 149 | 150 | *now = time(NULL); 151 | tm *tm_time = localtime(now); 152 | strftime(timebuf, sizeof timebuf, ".%Y%m%d-%H%M%S", tm_time); 153 | filename += timebuf; 154 | 155 | snprintf(pidbuf, sizeof pidbuf, ".%d", 156 | #ifdef WIN32 157 | ::GetCurrentProcessId() 158 | #else 159 | getpid() 160 | #endif 161 | ); 162 | 163 | filename += pidbuf; 164 | filename += ".log"; 165 | 166 | return filename; 167 | } 168 | -------------------------------------------------------------------------------- /log/log_file.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file LogFile.h 3 | * @brief log to file 4 | * @ahthor macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_LOGFILE_H_ 8 | #define _THEFOX_LOGFILE_H_ 9 | 10 | #ifdef WIN32 11 | #else 12 | #include 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace thefox { 23 | 24 | class LogFile 25 | { 26 | public: 27 | class File; 28 | 29 | LogFile(const string &dir, const string &basename, size_t rollSize); 30 | ~LogFile(); 31 | 32 | void init(); 33 | void append(const string &message); 34 | void flush(); 35 | 36 | private: 37 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(LogFile); 38 | 39 | static string getLogFileName(const string &dir, const string& basename, time_t* now); 40 | void rollFile(); 41 | 42 | string _dir; 43 | const string _basename; 44 | size_t _rollSize; 45 | 46 | Mutex _mutex; 47 | time_t _startOfPeriod; 48 | time_t _lastRoll; 49 | File *_file; 50 | 51 | static const int _kRollPerSeconds = 86400; 52 | }; 53 | 54 | } // namespace thefox 55 | 56 | void THEFOX_SET_LOG_FILE(const thefox::string &dir, 57 | const thefox::string &basename, 58 | size_t rollSize = 100*1024*1024); 59 | #endif // _THEFOX_LOGFILE_H_ 60 | -------------------------------------------------------------------------------- /log/log_stdout.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace thefox; 4 | 5 | static LogStdout *g_logStdout = NULL; 6 | 7 | void THEFOX_SET_LOG_STDOUT(const string& basename) 8 | { 9 | if (g_logStdout) { 10 | delete g_logStdout; 11 | g_logStdout = NULL; 12 | } 13 | g_logStdout = new LogStdout(basename); 14 | } 15 | 16 | void logStdoutAppend(const string &message) 17 | { 18 | if (g_logStdout) { 19 | g_logStdout->append(message); 20 | } 21 | } 22 | 23 | LogStdout::LogStdout(const string& basename) 24 | : _basename(basename) 25 | { 26 | thefoxSetLogHandler(logStdoutAppend); 27 | } 28 | 29 | LogStdout::~LogStdout() 30 | { 31 | thefoxSetLogHandler(NULL); 32 | } 33 | 34 | void LogStdout::append(const string &message) 35 | { 36 | MutexGuard lock(_mutex); 37 | if (message.empty()) { 38 | std::cout << message << '\n'; 39 | } else { 40 | std::cout << _basename << " " << message << '\n'; 41 | } 42 | } -------------------------------------------------------------------------------- /log/log_stdout.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log_stdout.h 3 | * @brief log to stdout 4 | * @ahthor macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_LOGSYSLOG_H_ 8 | #define _THEFOX_LOGSYSLOG_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace thefox { 16 | 17 | class LogStdout 18 | { 19 | public: 20 | explicit LogStdout(const string& basename); 21 | ~LogStdout(); 22 | 23 | void append(const string &message); 24 | 25 | private: 26 | Mutex _mutex; 27 | const string _basename; 28 | }; 29 | 30 | } // namespace thefox 31 | 32 | void THEFOX_SET_LOG_STDOUT(const thefox::string &basename = ""); 33 | 34 | #endif // _THEFOX_LOGSYSLOG_H_ 35 | -------------------------------------------------------------------------------- /log/log_syslog.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace thefox; 4 | 5 | static LogSyslog *g_logSyslog = NULL; 6 | 7 | void THEFOX_SET_LOG_STDOUT(const string& basename, const net::InetAddress &serverAddr) 8 | { 9 | if (g_logSyslog) { 10 | delete g_logSyslog; 11 | g_logSyslog = NULL; 12 | } 13 | g_logSyslog = new LogSyslog(basename, serverAddr); 14 | } 15 | 16 | void logSyslogAppend(const string &message) 17 | { 18 | if (g_logSyslog) { 19 | g_logSyslog->append(message); 20 | } 21 | } 22 | 23 | LogSyslog::LogSyslog(const string& basename, const net::InetAddress &serverAddr) 24 | : _basename(basename) 25 | , _serverAddr(serverAddr) 26 | 27 | { 28 | setLogHandler(std::bind(&LogSyslog::append, this, _1)); 29 | } 30 | 31 | LogSyslog::~LogSyslog() 32 | { 33 | } 34 | 35 | void LogSyslog::append(const string &message) 36 | { 37 | MutexGuard lock(_mutex); 38 | if (_sockfd >= 0) { 39 | ::sendto(_sockfd, message.c_str(), message.length(), 0, 40 | (struct sockaddr *)&_serverAddr.getSockAddrInet(), 41 | sizeof(struct sockaddr_in)); 42 | } 43 | } 44 | 45 | bool LogSyslog::init() 46 | { 47 | _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0); 48 | return _sockfd >= 0; 49 | } -------------------------------------------------------------------------------- /log/log_syslog.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log_syslog.h 3 | * @brief log to syslog server 4 | * @ahthor macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_LOGSYSLOG_H_ 8 | #define _THEFOX_LOGSYSLOG_H_ 9 | 10 | #ifdef WIN32 11 | #include 12 | #else 13 | #include 14 | #define SOCKET int 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace thefox 23 | { 24 | 25 | class LogSyslog 26 | { 27 | public: 28 | LogSyslog(const string& basename, const net::InetAddress &serverAddr); 29 | ~LogSyslog(); 30 | 31 | void append(const string &message); 32 | bool init(); 33 | 34 | private: 35 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(LogSyslog); 36 | 37 | const string _basename; 38 | net::InetAddress _serverAddr; 39 | SOCKET _sockfd; 40 | Mutex _mutex; 41 | }; 42 | 43 | } // namespace thefox 44 | 45 | void THEFOX_SET_LOG_SYSLOG(const string& basename, const net::InetAddress &serverAddr); 46 | 47 | #endif // _THEFOX_LOGSYSLOG_H_ 48 | -------------------------------------------------------------------------------- /log/logging.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_LOG_LOGMESSAGE_H_ 2 | #define _THEFOX_LOG_LOGMESSAGE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace thefox { 11 | 12 | enum LogLevel { 13 | LOGLEVEL_TRACE, 14 | LOGLEVEL_DEBUG, 15 | LOGLEVEL_INFO, 16 | LOGLEVEL_WARN, 17 | LOGLEVEL_ERROR, 18 | LOGLEVEL_FATAL, 19 | LOGLEVEL_NUM_LOG_LEVELS 20 | }; 21 | 22 | namespace detail 23 | { 24 | 25 | // 从路径中得到文件名 26 | inline const char *getFileNameFromPath(const char *pathName) 27 | { 28 | const char* slash = strrchr(pathName, '/'); 29 | if (slash) { 30 | return slash + 1; 31 | } else { 32 | const char *bslash = strrchr(pathName, '\\'); 33 | if (bslash) { 34 | return bslash + 1; 35 | } 36 | } 37 | return pathName; 38 | } 39 | 40 | class LogFinisher; 41 | 42 | class LogMessage 43 | { 44 | public: 45 | LogMessage(LogLevel level, const char *filename, int line); 46 | ~LogMessage(); 47 | 48 | LogMessage &operator<<(const string &value); 49 | LogMessage &operator<<(const char *value); 50 | LogMessage &operator<<(char value); 51 | LogMessage &operator<<(int value); 52 | LogMessage &operator<<(unsigned int value); 53 | LogMessage &operator<<(long value); 54 | LogMessage &operator<<(unsigned long value); 55 | LogMessage &operator<<(long long value); 56 | LogMessage &operator<<(unsigned long long value); 57 | LogMessage &operator<<(double value); 58 | LogMessage &operator<<(const void *p); 59 | 60 | private: 61 | friend class LogFinisher; 62 | friend class LogTraceFunction; 63 | void Finish(); 64 | 65 | LogLevel _level; 66 | string _message; 67 | }; 68 | 69 | class LogFinisher 70 | { 71 | public: 72 | void operator=(LogMessage &other); 73 | }; 74 | 75 | // 跟踪函数的开头和结束, 放在函数的第一行 76 | class LogTraceFunction { 77 | public: 78 | LogTraceFunction(const char *func, const char *file, int line); 79 | ~LogTraceFunction(); 80 | 81 | void operator=(LogMessage &other); 82 | private: 83 | const char *_func; 84 | const char *_file; 85 | int _line; 86 | }; 87 | 88 | } // namespace detail 89 | 90 | // 写日志函数 91 | typedef void (*ThefoxLogHandler)(const string &message); 92 | 93 | void thefoxSetLogHandler(ThefoxLogHandler newFunc); 94 | 95 | void setLogLevel(LogLevel level); 96 | LogLevel logLevel(); 97 | 98 | #undef ERROR 99 | 100 | #define THEFOX_LOG(LEVEL) if (thefox::logLevel() <= thefox::LOGLEVEL_##LEVEL) \ 101 | thefox::detail::LogFinisher() = \ 102 | thefox::detail::LogMessage( \ 103 | thefox::LOGLEVEL_##LEVEL, thefox::detail::getFileNameFromPath(__FILE__), __LINE__) 104 | #define THEFOX_LOG_IF(LEVEL, CONDITION) \ 105 | !(CONDITION) ? (void)0 : THEFOX_LOG(LEVEL) 106 | 107 | #define THEFOX_CHECK(EXPRESSION) \ 108 | THEFOX_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " 109 | #define THEFOX_CHECK_EQ(A, B) THEFOX_CHECK((A) == (B)) 110 | #define THEFOX_CHECK_NE(A, B) THEFOX_CHECK((A) != (B)) 111 | #define THEFOX_CHECK_LT(A, B) THEFOX_CHECK((A) < (B)) 112 | #define THEFOX_CHECK_LE(A, B) THEFOX_CHECK((A) <= (B)) 113 | #define THEFOX_CHECK_GT(A, B) THEFOX_CHECK((A) > (B)) 114 | #define THEFOX_CHECK_GE(A, B) THEFOX_CHECK((A) >= (B)) 115 | 116 | namespace detail 117 | { 118 | template 119 | T* checkNotNull(const char *name, T* val) 120 | { 121 | if (val == NULL) 122 | THEFOX_LOG(FATAL) << name; 123 | return val; 124 | } 125 | 126 | } // namespace detail 127 | 128 | #define THEFOX_CHECK_NOTNULL(A) \ 129 | thefox::detail::checkNotNull("'" #A "' must not be NULL", (A)) 130 | 131 | #define THEFOX_TRACE_FUNCTION \ 132 | thefox::detail::LogTraceFunction LogTraceFunction(__FUNCTION__, __FILE__, __LINE__); \ 133 | if (thefox::logLevel() <= thefox::LOGLEVEL_TRACE) \ 134 | LogTraceFunction = thefox::detail::LogMessage(LOGLEVEL_TRACE, \ 135 | thefox::detail::getFileNameFromPath(__FILE__), __LINE__) \ 136 | << __FUNCTION__ << "() begin " 137 | } // namespace thefox 138 | 139 | #endif // _THEFOX_LOG_LOGMESSAGE_H_ 140 | -------------------------------------------------------------------------------- /log/testLog.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox; 5 | 6 | int main(int argc,char * argv[]) 7 | { 8 | THEFOX_SET_LOG_FILE("logs","TestLog"); 9 | int i=100; 10 | while (--i) 11 | { 12 | Sleep(rand()%50); 13 | THEFOX_LOG(TRACE) <<"dddddddd" << "dfdfd"; 14 | THEFOX_LOG(DEBUG) << "dfdf" << 12 << -12.23; 15 | THEFOX_LOG(INFO) << "dfdf"; 16 | THEFOX_LOG(WARN) << "dfdf"; 17 | THEFOX_LOG(ERROR) << "dfdf"; 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /net/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -std=c++0x -g -fPIC -shared 3 | INCLUDE = -I.. 4 | LIBRARY = -lpthread 5 | 6 | all:libthefox.so 7 | 8 | 9 | libthefox.so: acceptor.o epoll_event.o event_loop.o socket.o tcp_client.o tcp_connection.o tcp_server.o 10 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 11 | 12 | acceptor.o: acceptor.cc 13 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 14 | 15 | epoll_event.o: epoll_event.cc 16 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 17 | event_loop.o: event_loop.cc 18 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 19 | socket.o: socket.cc 20 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 21 | tcp_connection.o: tcp_connection.cc 22 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 23 | tcp_client.o: tcp_client.cc 24 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 25 | tcp_server.o: tcp_server.cc 26 | $(CC) $(CFLAGS) -o $@ $^ $(INCLUDE) $(LIBRARY) 27 | 28 | clean: 29 | rm -rf *.o *.so 30 | 31 | -------------------------------------------------------------------------------- /net/README.md: -------------------------------------------------------------------------------- 1 | # 轻量级的网络库 2 | 3 | 支持Windwos和Linux跨平台使用 4 | 5 | 使用IOCP(Windows)和epoll(linux) 6 | 7 | 感谢 chenshuo 大牛的 muduo 项目让我思路变得开阔。 -------------------------------------------------------------------------------- /net/acceptor.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #ifndef WIN32 5 | #include 6 | #endif 7 | using namespace thefox; 8 | using namespace thefox::net; 9 | 10 | Acceptor::Acceptor(EventLoop *loop, const InetAddress& listenAddr) 11 | : _loop(loop) 12 | , _listenAddr(listenAddr) 13 | , _listening(false) 14 | , _acceptSocket(Socket::create()) 15 | { 16 | Socket::setNonBlock(_acceptSocket.fd()); 17 | } 18 | 19 | Acceptor::~Acceptor() 20 | { 21 | _listening = false; 22 | 23 | #ifdef WIN32 24 | ::CloseHandle(_hAcceptEvent); 25 | _acceptThread->stop(); 26 | delete _acceptThread; 27 | #else 28 | _loop->delEvent(&_event); 29 | #endif 30 | } 31 | 32 | bool Acceptor::init() 33 | { 34 | THEFOX_TRACE_FUNCTION; 35 | 36 | assert(_acceptSocket.fd() >= 0); 37 | 38 | bool ret = _acceptSocket.bind(_listenAddr); 39 | 40 | #ifdef WIN32 41 | _acceptThread = new Thread(std::bind(&Acceptor::acceptLoop, this)); 42 | #else 43 | _event.fd = _acceptSocket.fd(); 44 | #endif 45 | 46 | return ret; 47 | } 48 | 49 | bool Acceptor::listen() 50 | { 51 | THEFOX_TRACE_FUNCTION; 52 | 53 | if (_listening) 54 | return true; 55 | 56 | if (_acceptSocket.listen()) { 57 | _listening = true; 58 | 59 | #ifdef WIN32 60 | _hAcceptEvent = ::WSACreateEvent(); 61 | WSAEventSelect(_acceptSocket.fd(), _hAcceptEvent, FD_ACCEPT); 62 | _acceptThread->start(); 63 | #else 64 | _loop->addEvent(&_event); 65 | _event.handler = std::bind(&Acceptor::onAccept, this, _1, _2); 66 | #endif 67 | 68 | THEFOX_LOG(INFO) << "Acceptor::listen() done"; 69 | return true; 70 | } else { 71 | THEFOX_LOG(ERROR) << "Acceptor::listen() failed"; 72 | return false; 73 | } 74 | } 75 | 76 | #ifdef WIN32 77 | void Acceptor::acceptLoop() 78 | { 79 | while (_listening) { 80 | if (WSA_WAIT_TIMEOUT == ::WSAWaitForMultipleEvents(1, &_hAcceptEvent, FALSE, 100, FALSE)) { 81 | continue; 82 | } 83 | 84 | WSANETWORKEVENTS events; 85 | if (SOCKET_ERROR == ::WSAEnumNetworkEvents(_acceptSocket.fd(), _hAcceptEvent, &events)) { 86 | THEFOX_LOG(ERROR) << "WSAEnumNetworkEvents() error"; 87 | continue; 88 | } 89 | 90 | if (events.lNetworkEvents & FD_ACCEPT && 0 == events.iErrorCode[FD_ACCEPT_BIT]) { 91 | InetAddress peerAddr; 92 | SOCKET clientSockfd = _acceptSocket.accept(&peerAddr); 93 | if (INVALID_SOCKET == clientSockfd) { 94 | THEFOX_LOG(ERROR) << "accept a socket error"; 95 | } 96 | 97 | if (_newConnectionCallback) { 98 | _newConnectionCallback(clientSockfd, _listenAddr, peerAddr); 99 | } 100 | } 101 | } 102 | } 103 | #else 104 | void Acceptor::onAccept(Event *ev, void *arg) 105 | { 106 | THEFOX_TRACE_FUNCTION; 107 | 108 | uint32_t revents = (uint32_t)arg; 109 | 110 | if (revents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) { 111 | InetAddress peerAddr; 112 | SOCKET clientSockfd = _acceptSocket.accept(&peerAddr); 113 | if (INVALID_SOCKET == clientSockfd) { 114 | THEFOX_LOG(ERROR) << "accept a socket error"; 115 | } 116 | 117 | if (_newConnectionCallback) { 118 | _newConnectionCallback(clientSockfd, _listenAddr, peerAddr); 119 | } 120 | } 121 | } 122 | #endif 123 | -------------------------------------------------------------------------------- /net/acceptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename acceptor.h 3 | * @brief tcp acceptor 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_ACCEPTOR_H_ 8 | #define _THEFOX_NET_ACCEPTOR_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #ifdef WIN32 16 | #include 17 | #endif 18 | 19 | namespace thefox { 20 | namespace net { 21 | 22 | class EventLoop; 23 | 24 | typedef std::function NewConnectionCallback; 25 | 26 | class Acceptor 27 | { 28 | public: 29 | Acceptor(EventLoop *loop, const InetAddress& listenAddr); 30 | ~Acceptor(void); 31 | 32 | bool init(); 33 | bool listen(); 34 | bool listening() const { return _listening; } 35 | void setNewConnectionCallback(const NewConnectionCallback &cb) 36 | { _newConnectionCallback = cb; } 37 | 38 | private: 39 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Acceptor); 40 | 41 | const InetAddress _listenAddr; 42 | EventLoop *_loop; 43 | Socket _acceptSocket; 44 | bool _listening; 45 | NewConnectionCallback _newConnectionCallback; 46 | 47 | #ifdef WIN32 48 | void acceptLoop(); 49 | Thread *_acceptThread; 50 | HANDLE _hAcceptEvent; 51 | #else 52 | void onAccept(Event *ev, void *arg); 53 | Event _event; 54 | #endif 55 | }; 56 | 57 | } // namespace net 58 | } // namespace thefox 59 | 60 | #endif // _THEFOX_NET_ACCEPTOR_H_ 61 | -------------------------------------------------------------------------------- /net/asio/callbacks.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_ASIO_CALLBACKS_H_ 2 | #define _THEFOX_NET_ASIO_CALLBACKS_H_ 3 | 4 | #include 5 | 6 | namespace thefox { 7 | namespace net_asio { 8 | 9 | class Buffer; 10 | class TcpConnection; 11 | typedef std::shared_ptr TcpConnectionPtr; 12 | 13 | typedef std::function ConnectionCallback; 14 | typedef std::function MessageCallback; 16 | typedef std::function WriteCompleteCallback; 17 | 18 | void defaultMessageCallback(const TcpConnectionPtr &conn, 19 | Buffer *buffer, Timestamp recvTime); 20 | 21 | } // namespace net_asio 22 | } // namespace thefox 23 | 24 | #endif // _THEFOX_NET_ASIO_CALLBACKS_H_ -------------------------------------------------------------------------------- /net/asio/net_asio.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_ASIO_NETASIO_H_ 2 | #define _THEFOX_NET_ASIO_NETASIO_H_ 3 | 4 | #ifdef WIN32 5 | #pragma warning(disable:4819) 6 | #pragma warning(disable:4996) 7 | #endif 8 | 9 | #include 10 | 11 | using namespace boost::asio; 12 | 13 | #define THEFOX_USE_BOOST_ASIO 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #endif // _THEFOX_NET_ASIO_NETASIO_H_ -------------------------------------------------------------------------------- /net/asio/tcp_client.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace thefox; 6 | using namespace thefox::net_asio; 7 | 8 | TcpClient::TcpClient(io_service &io, const string &nameArg) 9 | : _io(io) 10 | , _name(nameArg) 11 | , _messageCallback(defaultMessageCallback) 12 | { 13 | } 14 | 15 | TcpClient::~TcpClient() 16 | { 17 | close(); 18 | } 19 | 20 | bool TcpClient::open(ip::tcp::endpoint endpoint) 21 | { 22 | if (opened()) { 23 | return false; 24 | } 25 | 26 | _conn = std::make_shared(_io, 1); 27 | 28 | _conn->socket().async_connect(endpoint, 29 | [this](const boost::system::error_code &ec) { 30 | if (!ec) { 31 | _conn->setConnectionCallback(_connectionCallback); 32 | _conn->setMessageCallback(_messageCallback); 33 | _conn->setWriteCompleteCallback(_writeCompleteCallback); 34 | _conn->setRemoveConnectionCallback(std::bind(&TcpClient::removeConnection, this, _1)); 35 | _conn->connectEstablished(); 36 | } 37 | }); 38 | return true; 39 | } 40 | 41 | void TcpClient::close() 42 | { 43 | if (_conn) { 44 | _conn->forceClose(); 45 | } 46 | } 47 | 48 | bool TcpClient::opened() 49 | { 50 | if (_conn) { 51 | if (TcpConnection::kConnected == _conn->state()) { 52 | return true; 53 | } 54 | } 55 | 56 | return false; 57 | } 58 | 59 | void TcpClient::send(const char *data, size_t len) 60 | { 61 | if (_conn) { 62 | _conn->send(data, len); 63 | } 64 | } 65 | 66 | void TcpClient::send(const string &data) 67 | { 68 | if (_conn) { 69 | _conn->send(data); 70 | } 71 | } 72 | 73 | void TcpClient::removeConnection(const TcpConnectionPtr &conn) 74 | { 75 | _conn.reset(); 76 | } 77 | -------------------------------------------------------------------------------- /net/asio/tcp_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @brief tcp client 3 | * @author macwe1024 at gmail dot com 4 | */ 5 | 6 | #ifndef _THEFOX_NET_ASIO_TCPCLIENT_H_ 7 | #define _THEFOX_NET_ASIO_TCPCLIENT_H_ 8 | 9 | #include 10 | 11 | namespace thefox { 12 | namespace net_asio { 13 | 14 | class TcpClient 15 | { 16 | public: 17 | TcpClient(io_service &io, const string &nameArg); 18 | ~TcpClient(void); 19 | 20 | /// @brief connect to server 21 | /// @return return true if success,then return false 22 | bool open(ip::tcp::endpoint endpoint); 23 | 24 | /// @brief close the client 25 | void close(); 26 | 27 | /// @brief check if connection is opened 28 | /// @return return true if success,then return false 29 | bool opened(); 30 | 31 | /// @brief send data 32 | void send(const char *data, size_t len); 33 | void send(const string &data); 34 | 35 | TcpConnectionPtr conn() { return _conn;} 36 | 37 | void setConnectionCallback(const ConnectionCallback &cb) 38 | { _connectionCallback = cb; } 39 | void setMessageCallback(const MessageCallback &cb) 40 | { _messageCallback = cb; } 41 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 42 | { _writeCompleteCallback = cb; } 43 | 44 | private: 45 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpClient); 46 | 47 | void removeConnection(const TcpConnectionPtr &conn); 48 | 49 | const string _name; 50 | io_service &_io; 51 | TcpConnectionPtr _conn; 52 | 53 | ConnectionCallback _connectionCallback; 54 | MessageCallback _messageCallback; 55 | WriteCompleteCallback _writeCompleteCallback; 56 | }; 57 | 58 | } // namespace net_asio 59 | } // namespace thefox 60 | 61 | #endif // _THEFOX_NET_ASIO_TCPCLIENT_H_ -------------------------------------------------------------------------------- /net/asio/tcp_client_test.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/net/asio/tcp_client_test.cc -------------------------------------------------------------------------------- /net/asio/tcp_connection.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/net/asio/tcp_connection.cc -------------------------------------------------------------------------------- /net/asio/tcp_connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename TcpConnection.h 3 | * @brief 表示一个客户连接 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_ASIO_TCPCONNECTION_H_ 8 | #define _THEFOX_NET_ASIO_TCPCONNECTION_H_ 9 | 10 | #include 11 | #include 12 | 13 | namespace thefox { 14 | namespace net_asio { 15 | 16 | typedef std::function RemoveConnectionCallback; 17 | 18 | class TcpConnection : public std::enable_shared_from_this 19 | { 20 | public: 21 | enum StateT { kDisconnected, kConnecting, kConnected, kDisconnecting }; 22 | 23 | TcpConnection(io_service &io, int id); 24 | ~TcpConnection(); 25 | 26 | /// @brief get conn id 27 | int32_t id() const { return _id; } 28 | 29 | ip::tcp::socket &socket() { return _socket; } 30 | 31 | /// @brief get peer address 32 | ip::tcp::endpoint peerAddr() const 33 | { 34 | return _socket.remote_endpoint(); 35 | } 36 | 37 | /// @brief get connection state 38 | StateT state() const { return _state; } 39 | void setState(StateT state) { _state = state; } 40 | 41 | /// @brief 42 | void *arg() const { return _arg; } 43 | 44 | /// @brief 45 | void setArg(void *arg) { _arg = arg; } 46 | 47 | size_t readBytes() const { return _readBytes; } 48 | size_t writeBytes() const { return _writeBytes; } 49 | 50 | void send(const string &data); 51 | void send(const char *data, size_t len); 52 | 53 | void shutdown(); 54 | void setTcpNoDelay(bool on); 55 | void forceClose(); 56 | void connectEstablished(); 57 | 58 | void setConnectionCallback(const ConnectionCallback &cb) 59 | { _connectionCallback = cb; } 60 | void setMessageCallback(const MessageCallback &cb) 61 | { _messageCallback = cb; } 62 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 63 | { _writeCompleteCallback = cb; } 64 | void setRemoveConnectionCallback(const RemoveConnectionCallback &cb) 65 | { _removeConnectionCallback = cb; } 66 | 67 | private: 68 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpConnection); 69 | void doRead(); 70 | void doWrite(); 71 | 72 | void connectDestroyed(); 73 | 74 | void enterIo(); 75 | void leaveIo(); 76 | 77 | int32_t _pendingIo; 78 | Mutex _ioMutex; 79 | 80 | int32_t _id; 81 | io_service &_io; 82 | ip::tcp::socket _socket; 83 | 84 | Buffer _readBuffer; 85 | Buffer _writeBuffer; 86 | Mutex _writeMutex; 87 | 88 | StateT _state; 89 | 90 | void *_arg; 91 | 92 | // io transfer counter 93 | size_t _readBytes; 94 | size_t _writeBytes; 95 | 96 | ConnectionCallback _connectionCallback; 97 | MessageCallback _messageCallback; 98 | WriteCompleteCallback _writeCompleteCallback; 99 | RemoveConnectionCallback _removeConnectionCallback; 100 | 101 | static const size_t kDefaultSizeToWrite = 8192; 102 | }; 103 | 104 | } // namespace net_asio 105 | } // namespace thefox 106 | 107 | #endif // _THEFOX_NET_ASIO_TCPCONNECTION_H_ -------------------------------------------------------------------------------- /net/asio/tcp_server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox; 5 | using namespace thefox::net_asio; 6 | 7 | TcpServer::TcpServer(io_service &io, 8 | boost::asio::ip::tcp::endpoint listenAddr, 9 | const string &nameArg) 10 | : _io(io) 11 | , _name(nameArg) 12 | , _started(false) 13 | , _messageCallback(defaultMessageCallback) 14 | , _acceptor(io, listenAddr) 15 | { 16 | } 17 | 18 | TcpServer::~TcpServer() 19 | { 20 | _started = false; 21 | 22 | for (ConnectionMap::iterator it(_connections.begin()); it != _connections.end(); ++it) { 23 | TcpConnectionPtr conn = it->second; 24 | conn->forceClose(); 25 | } 26 | } 27 | 28 | bool TcpServer::start() 29 | { 30 | if (_started) 31 | return true; 32 | 33 | _started = true; 34 | 35 | doAccept(); 36 | 37 | return _started; 38 | } 39 | 40 | void TcpServer::doAccept() 41 | { 42 | int32_t id = _nextConnId.inc(); 43 | TcpConnectionPtr newConnection(new TcpConnection(_io, id)); 44 | 45 | _acceptor.async_accept(newConnection->socket(), 46 | [this, newConnection](const boost::system::error_code &ec) { 47 | if (!ec) { 48 | _connections[newConnection->id()] = newConnection; 49 | 50 | newConnection->setConnectionCallback(_connectionCallback); 51 | newConnection->setMessageCallback(_messageCallback); 52 | newConnection->setWriteCompleteCallback(_writeCompleteCallback); 53 | newConnection->setRemoveConnectionCallback(std::bind(&TcpServer::removeConnection, this, _1)); 54 | newConnection->connectEstablished(); 55 | 56 | doAccept(); 57 | } 58 | }); 59 | } 60 | 61 | void TcpServer::removeConnection(const TcpConnectionPtr &conn) 62 | { 63 | _connections.erase(conn->id()); 64 | } 65 | -------------------------------------------------------------------------------- /net/asio/tcp_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @brief tcp server for asio 3 | * @author macwe1024 at gmail dot com 4 | */ 5 | 6 | #ifndef _THEFOX_NET_ASIO_TCPSERVER_H_ 7 | #define _THEFOX_NET_ASIO_TCPSERVER_H_ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | namespace net_asio { 16 | 17 | class TcpServer 18 | { 19 | public: 20 | TcpServer(io_service &io, 21 | ip::tcp::endpoint listenAddr, 22 | const string &nameArg); 23 | ~TcpServer(void); 24 | 25 | /// @brief start the server 26 | /// @return return true if success,then return false 27 | bool start(); 28 | 29 | /// @brief check if the server started 30 | /// @return return true if success,then return false 31 | bool started() const { return _started; } 32 | 33 | void setConnectionCallback(const ConnectionCallback &cb) 34 | { 35 | _connectionCallback = cb; 36 | } 37 | void setMessageCallback(const MessageCallback &cb) 38 | { 39 | _messageCallback = cb; 40 | } 41 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 42 | { 43 | _writeCompleteCallback = cb; 44 | } 45 | 46 | private: 47 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpServer); 48 | 49 | void doAccept(); 50 | void removeConnection(const TcpConnectionPtr &conn); 51 | 52 | typedef std::map ConnectionMap; 53 | 54 | const string _name; 55 | io_service &_io; 56 | ip::tcp::acceptor _acceptor; 57 | 58 | bool _started; 59 | AtomicInt32 _nextConnId; 60 | Mutex _mutex; 61 | ConnectionMap _connections; 62 | 63 | ConnectionCallback _connectionCallback; 64 | MessageCallback _messageCallback; 65 | WriteCompleteCallback _writeCompleteCallback; 66 | }; 67 | 68 | } // namespace net_asio 69 | } // namespace thefox 70 | 71 | #endif // _THEFOX_NET_ASIO_TCPSERVER_H_ 72 | -------------------------------------------------------------------------------- /net/asio/tcp_server_test.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/net/asio/tcp_server_test.cc -------------------------------------------------------------------------------- /net/callbacks.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_CALLBACKS_H_ 2 | #define _THEFOX_NET_CALLBACKS_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace thefox { 8 | namespace net { 9 | 10 | class Buffer; 11 | class TcpConnection; 12 | 13 | typedef std::function ConnectionCallback; 14 | typedef std::function MessageCallback; 16 | typedef std::function WriteCompleteCallback; 17 | 18 | void defaultMessageCallback(TcpConnection *conn, 19 | Buffer *buffer, const Timestamp recvTime); 20 | 21 | } // namespace net 22 | } // namespace thefox 23 | 24 | #endif // _THEFOX_NET_CALLBACKS_H_ -------------------------------------------------------------------------------- /net/client_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace thefox; 11 | using namespace thefox::net; 12 | 13 | void onConnection(TcpConnection *conn) 14 | { 15 | switch (conn->state()) { 16 | case TcpConnection::kConnected: 17 | printf("Connection success connID=%d\r\n", conn->id()); 18 | conn->send("ping!", strlen("ping!")); 19 | break; 20 | case TcpConnection::kDisconnected: 21 | printf("Connection disconnect connID=%d\r\n", conn->id()); 22 | break; 23 | default: 24 | printf("Connection connection state=%d connID=%d\r\n", conn->state(), conn->id()); 25 | break; 26 | } 27 | } 28 | 29 | void onMessage(TcpConnection *conn, Buffer *buf, Timestamp receiveTime) 30 | { 31 | printf("onMessage readBytes: %u\r\n", conn->readBytes()); 32 | conn->send(buf->peek(), buf->readableBytes()); 33 | buf->retrieveAll(); 34 | } 35 | 36 | void onWriteComplete(TcpConnection *conn) 37 | { 38 | printf("onWriteComplete writeBytes: %u\r\n", conn->writeBytes()); 39 | } 40 | 41 | int main(int argc, char **argv) 42 | { 43 | LogFile log("./logs", "client_test"); 44 | 45 | THEFOX_SOCKET_STARTUP; 46 | 47 | EventLoop loop; 48 | TcpClient *client = new TcpClient(&loop, "MyIocpClientDemo"); 49 | client->setConnectionCallback(onConnection); 50 | client->setMessageCallback(onMessage); 51 | client->setWriteCompleteCallback(onWriteComplete); 52 | 53 | loop.start(); 54 | 55 | client->open(InetAddress("127.0.0.1", 7901)); 56 | 57 | loop.join(); 58 | 59 | THEFOX_SOCKET_CLEANUP; 60 | 61 | delete client; 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /net/epoll_event.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_EPOLL_EVENT_H_ 2 | #define _THEFOX_NET_EPOLL_EVENT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef WIN32 9 | #error "class EpollEvent run in Linux only" 10 | #else 11 | 12 | struct epoll_event; 13 | 14 | namespace thefox { 15 | namespace net { 16 | 17 | class TcpConnection; 18 | 19 | class EpollEvent 20 | { 21 | public: 22 | EpollEvent(); 23 | ~EpollEvent(); 24 | 25 | bool init(); 26 | bool processEvents(uint32_t timer); 27 | 28 | bool addEvent(Event *ev); 29 | bool delEvent(Event *ev); 30 | bool updateRead(Event *ev) { return true; } 31 | bool updateWrite(Event *ev); 32 | 33 | private: 34 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(EpollEvent); 35 | void handler(Event *ev, void *arg); 36 | bool onRead(Event *ev); 37 | bool onWrite(Event *ev); 38 | bool onClose(Event *ev, uint32_t revents); 39 | 40 | typedef std::vector EventList; 41 | int _epollfd; 42 | EventList _events; 43 | 44 | static const size_t kDefaultBufferSize = 8192; 45 | }; 46 | 47 | } // namespace net 48 | } // namespace thefox 49 | 50 | #endif // WIN32 51 | 52 | #endif // _THEFOX_NET_EPOLL_EVENT_H_ 53 | -------------------------------------------------------------------------------- /net/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @brief a io event entry 3 | * @author macwe1024 at gmail dot com 4 | */ 5 | 6 | #ifndef _THEFOX_NET_EVENT_H_ 7 | #define _THEFOX_NET_EVENT_H_ 8 | 9 | #ifdef WIN32 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace thefox { 18 | namespace net { 19 | 20 | class TcpConnection; 21 | class Event; 22 | 23 | class Event 24 | { 25 | public: 26 | typedef std::function Handler; 27 | 28 | Event() 29 | : in(false), out(false), error(false), fd(INVALID_SOCKET), conn(NULL) 30 | {} 31 | 32 | bool testAndSetWrite() 33 | { 34 | MutexGuard lock(_mutex); 35 | bool temp = out; 36 | out = true; 37 | return temp; 38 | } 39 | 40 | void resetWrite() 41 | { 42 | MutexGuard lock(_mutex); 43 | out = false; 44 | } 45 | 46 | bool in; 47 | bool out; 48 | bool error; 49 | 50 | SOCKET fd; 51 | TcpConnection *conn; 52 | 53 | Handler handler; 54 | private: 55 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(Event); 56 | Mutex _mutex; 57 | }; 58 | 59 | 60 | #ifdef WIN32 61 | 62 | #define OVLP_TYPE_READ 1 63 | #define OVLP_TYPE_WRITE 2 64 | #define OVLP_TYPE_CLOSE 3 65 | 66 | typedef struct { 67 | OVERLAPPED ovlp; 68 | int32_t type; // io类型 69 | uint32_t avaliable; // 传输的字节数 70 | Event *ev; 71 | } EventOvlp; 72 | 73 | #endif 74 | 75 | } // namespace net 76 | } // namespace thefox 77 | 78 | #endif // _THEFOX_NET_EVENT_H_ 79 | -------------------------------------------------------------------------------- /net/event_loop.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/net/event_loop.cc -------------------------------------------------------------------------------- /net/event_loop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * author event_loop.h 3 | * @brief 事件循环 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_EVENTLOOP_H_ 8 | #define _THEFOX_NET_EVENTLOOP_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | namespace net { 16 | 17 | class Event; 18 | 19 | #ifdef WIN32 20 | class IocpEvent; 21 | #define Poller IocpEvent 22 | typedef void *HANDLE; 23 | #else 24 | class EpollEvent; 25 | #define Poller EpollEvent 26 | #endif 27 | 28 | class EventLoop 29 | { 30 | public: 31 | EventLoop(); 32 | ~EventLoop(); 33 | 34 | // for user 35 | 36 | /// @brief start event loop 37 | void start(); 38 | 39 | /// @brief blocking and wait thread quit 40 | void join(); 41 | 42 | /// @brief quit thread 43 | void stop(); 44 | 45 | //void setTimer(uint32_t time, const TimerCallback &cb); 46 | 47 | // for internal 48 | bool updateRead(Event *ev); 49 | bool updateWrite(Event *ev); 50 | bool addEvent(Event *ev); 51 | bool delEvent(Event *ev); 52 | 53 | private: 54 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(EventLoop); 55 | 56 | void loop(); 57 | 58 | Poller *_poller; 59 | bool _started; 60 | const int _threadNum; // number of threads 61 | std::vector _threads; 62 | }; 63 | 64 | } // namespace net 65 | } // namespace thefox 66 | 67 | #endif // _THEFOX_NET_EVENTLOOP_H_ -------------------------------------------------------------------------------- /net/inet_address.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_INETADDRESS_H 2 | #define _THEFOX_NET_INETADDRESS_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef WIN32 8 | #include 9 | #else 10 | #include 11 | #include 12 | #endif 13 | 14 | namespace thefox { 15 | namespace net { 16 | 17 | class InetAddress 18 | { 19 | public: 20 | InetAddress() 21 | { 22 | memset(&_addr, 0, sizeof(_addr)); 23 | } 24 | InetAddress(uint16_t port) 25 | { 26 | memset(&_addr, 0, sizeof(_addr)); 27 | _addr.sin_family = AF_INET; 28 | _addr.sin_addr.s_addr = htonl(INADDR_ANY); 29 | _addr.sin_port = htons(port); 30 | } 31 | 32 | InetAddress(const string &ip, uint16_t port) 33 | { 34 | memset(&_addr, 0, sizeof(_addr)); 35 | _addr.sin_family = AF_INET; 36 | _addr.sin_addr.s_addr = inet_addr(ip.c_str()); 37 | _addr.sin_port = htons(port); 38 | } 39 | 40 | InetAddress(const struct sockaddr_in &addr) 41 | : _addr(addr) 42 | {} 43 | 44 | string toIp() const 45 | { 46 | char *host = inet_ntoa(_addr.sin_addr); 47 | if (NULL != host) 48 | return host; 49 | else 50 | return "INVALID"; 51 | } 52 | 53 | string toIpPort() const 54 | { 55 | char buf[32]; 56 | snprintf(buf, sizeof(buf), "%s:%u", toIp().c_str(), ntohs(_addr.sin_port)); 57 | return buf; 58 | } 59 | 60 | // default copy/assignment are Okay 61 | 62 | const struct sockaddr_in &getSockAddrInet() const { return _addr; } 63 | void setSockAddrInet(const struct sockaddr_in &addr) { _addr = addr; } 64 | 65 | uint32_t ipNetEndian() const { return _addr.sin_addr.s_addr; } 66 | uint16_t portNetEndian() const { return _addr.sin_port; } 67 | 68 | void operator=(struct sockaddr_in addr) 69 | { _addr = addr; } 70 | 71 | #ifdef THEFOX_USE_BOOST_ASIO 72 | tcp::endpoint() 73 | #endif 74 | 75 | private: 76 | struct sockaddr_in _addr; 77 | }; 78 | 79 | } // namespace net 80 | } // namespace thefox 81 | 82 | #endif // _THEFOX_NET_INETADDRESS_H 83 | -------------------------------------------------------------------------------- /net/iocp_event.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_IOCP_EVENT_H_ 2 | #define _THEFOX_NET_IOCP_EVENT_H_ 3 | 4 | #ifdef WIN32 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace thefox { 13 | namespace net { 14 | 15 | class TcpConnection; 16 | 17 | class IocpEvent 18 | { 19 | public: 20 | IocpEvent(); 21 | ~IocpEvent(); 22 | 23 | bool init(); 24 | bool processEvents(uint32_t timer); 25 | 26 | bool addEvent(Event *ev); 27 | bool delEvent(Event *ev); 28 | bool updateRead(Event *ev); 29 | bool updateWrite(Event *ev); 30 | 31 | private: 32 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(IocpEvent); 33 | void handler(Event *ev, void *arg); 34 | void onRead(Event *ev, uint32_t avaliable); 35 | void onWrite(Event *ev, uint32_t avaliable); 36 | 37 | HANDLE _hIocp; 38 | MemPool _ovlpPool; 39 | static const size_t kMaxBufSize = 8192; 40 | }; 41 | 42 | } // namespace net 43 | } // namespace thefox 44 | 45 | #else 46 | #error "class IocpEvent run in Windows only" 47 | #endif // WIN32 48 | 49 | #endif // _THEFOX_NET_IOCP_EVENT_H_ 50 | -------------------------------------------------------------------------------- /net/server_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace thefox; 11 | using namespace thefox::net; 12 | 13 | void onConnection(TcpConnection *conn) 14 | { 15 | switch (conn->state()) { 16 | case TcpConnection::kConnected: 17 | printf("Connection success connID=%d\r\n", conn->id()); 18 | break; 19 | case TcpConnection::kDisconnected: 20 | printf("Connection disconnect connID=%d\r\n", conn->id()); 21 | break; 22 | default: 23 | printf("Connection connection state=%d connID=%d\r\n", conn->state(), conn->id()); 24 | break; 25 | } 26 | } 27 | 28 | void onMessage(TcpConnection *conn, Buffer *buf, Timestamp receiveTime) 29 | { 30 | printf("onMessage readBytes: %u\r\n", conn->readBytes()); 31 | conn->send(buf->peek(), buf->readableBytes()); 32 | buf->retrieveAll(); 33 | } 34 | 35 | void onWriteComplete(TcpConnection *conn) 36 | { 37 | printf("onWriteComplete writeBytes: %u\r\n", conn->writeBytes()); 38 | } 39 | 40 | int main(int argc, char **argv) 41 | { 42 | LogFile log("./logs", "server_test"); 43 | 44 | THEFOX_LOG(INFO) << "tcp_server begin"; 45 | 46 | THEFOX_SOCKET_STARTUP; 47 | 48 | EventLoop loop; 49 | TcpServer *svr = new TcpServer(&loop, InetAddress(7901), "MyIocpDemo"); 50 | svr->setConnectionCallback(onConnection); 51 | svr->setMessageCallback(onMessage); 52 | svr->setWriteCompleteCallback(onWriteComplete); 53 | svr->start(); 54 | loop.start(); 55 | loop.join(); 56 | 57 | THEFOX_SOCKET_CLEANUP; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /net/socket.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_SOCKET_H_ 2 | #define _THEFOX_NET_SOCKET_H_ 3 | 4 | #ifdef WIN32 5 | #include 6 | 7 | /// @breaf socket库初始化 8 | #define THEFOX_SOCKET_STARTUP \ 9 | WSADATA wsd; \ 10 | ::WSAStartup(MAKEWORD(2, 2), &wsd); 11 | 12 | /// @breaf socket库注销 13 | #define THEFOX_SOCKET_CLEANUP \ 14 | ::WSACleanup(); 15 | 16 | #else 17 | #define SOCKET int 18 | #define INVALID_SOCKET -1 19 | #define SOCKET_ERROR -1 20 | #define THEFOX_SOCKET_STARTUP 21 | #define THEFOX_SOCKET_CLEANUP 22 | #endif 23 | 24 | #include 25 | 26 | namespace thefox { 27 | namespace net { 28 | 29 | class InetAddress; 30 | 31 | class Socket 32 | { 33 | public: 34 | explicit Socket(SOCKET sockfd); 35 | ~Socket(); 36 | 37 | static InetAddress getLocalAddr(SOCKET sockfd); 38 | static SOCKET create(); 39 | static bool setNonBlock(SOCKET sockfd); 40 | static bool connect(SOCKET sockfd, const InetAddress &serverAddr); 41 | static bool close(SOCKET sockfd); 42 | 43 | bool bind(const InetAddress &listenAddr); 44 | bool listen(); 45 | SOCKET accept(InetAddress *peerAddr); 46 | 47 | bool shutdownWrite(); 48 | // 取消nagle算法 49 | void setTcpNoDelay(bool on); 50 | void setKeepAlive(bool on); 51 | 52 | SOCKET fd() const { return _sockfd; } 53 | 54 | private: 55 | SOCKET _sockfd; 56 | }; 57 | 58 | } // namespace net 59 | } // namespace thefox 60 | 61 | #endif // _THEFOX_NET_SOCKET_H_ 62 | -------------------------------------------------------------------------------- /net/tcp_client.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace thefox; 7 | using namespace thefox::net; 8 | 9 | TcpClient::TcpClient(EventLoop *loop, const string &nameArg) 10 | : _loop(loop) 11 | , _name(nameArg) 12 | , _conn(NULL) 13 | , _messageCallback(defaultMessageCallback) 14 | {} 15 | 16 | TcpClient::TcpClient() 17 | { 18 | close(); 19 | } 20 | 21 | bool TcpClient::open(const InetAddress &serverAddr) 22 | { 23 | THEFOX_TRACE_FUNCTION << "addr:" << serverAddr.toIpPort(); 24 | if (opened()) { 25 | THEFOX_LOG(WARN) << "server:"<< serverAddr.toIpPort() << "opened"; 26 | return false; 27 | } 28 | 29 | SOCKET sockfd = Socket::create(); 30 | if (sockfd < 0) { 31 | return false; 32 | } 33 | 34 | if (!Socket::connect(sockfd, serverAddr)) { 35 | Socket::close(sockfd); 36 | return false; 37 | } 38 | 39 | handleNewConnection(sockfd, serverAddr); 40 | return true; 41 | } 42 | 43 | void TcpClient::close() 44 | { 45 | if (_conn) 46 | _conn->forceClose(); 47 | } 48 | 49 | bool TcpClient::opened() 50 | { 51 | if (NULL != _conn) { 52 | if (TcpConnection::kConnected == _conn->state()) 53 | return true; 54 | } 55 | return false; 56 | } 57 | 58 | void TcpClient::send(const char *data, size_t len) 59 | { 60 | if (_conn) 61 | _conn->send(data, len); 62 | } 63 | 64 | void TcpClient::send(const string &data) 65 | { 66 | if (_conn) 67 | _conn->send(data); 68 | } 69 | 70 | void TcpClient::handleNewConnection(SOCKET sockfd, const InetAddress &peerAddr) 71 | { 72 | THEFOX_TRACE_FUNCTION; 73 | 74 | InetAddress localAddr(Socket::getLocalAddr(sockfd)); 75 | _conn = new TcpConnection(_loop, sockfd, 0, localAddr, peerAddr); 76 | 77 | _conn->setConnectionCallback(_connectionCallback); 78 | _conn->setMessageCallback(_messageCallback); 79 | _conn->setWriteCompleteCallback(_writeCompleteCallback); 80 | _conn->setRemoveConnectionCallback(std::bind(&TcpClient::removeConnection, this, _1)); 81 | 82 | _conn->connectEstablished(); 83 | } 84 | 85 | void TcpClient::removeConnection(TcpConnection *conn) 86 | { 87 | THEFOX_TRACE_FUNCTION; 88 | 89 | SAFE_DELETE(_conn); 90 | } -------------------------------------------------------------------------------- /net/tcp_client.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief tcp_client.h 3 | * @brief tcp client 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_TCPCLIENT_H_ 8 | #define _THEFOX_NET_TCPCLIENT_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace thefox { 15 | namespace net { 16 | 17 | class EventLoop; 18 | class InetAddress; 19 | class TcpConnection; 20 | 21 | class TcpClient 22 | { 23 | public: 24 | TcpClient(EventLoop *loop, const string &nameArg); 25 | TcpClient(void); 26 | 27 | /// @brief connect to server 28 | /// @return return true if success,then return false 29 | bool open(const InetAddress &serverAddr); 30 | 31 | /// @brief close the client 32 | void close(); 33 | 34 | /// @brief check if connection is opened 35 | /// @return return true if success,then return false 36 | bool opened(); 37 | 38 | /// @brief send data 39 | void send(const char *data, size_t len); 40 | void send(const string &data); 41 | 42 | void setConnectionCallback(const ConnectionCallback &cb) 43 | { _connectionCallback = cb; } 44 | void setMessageCallback(const MessageCallback &cb) 45 | { _messageCallback = cb; } 46 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 47 | { _writeCompleteCallback = cb; } 48 | 49 | private: 50 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpClient); 51 | 52 | void handleNewConnection(SOCKET sockfd, const InetAddress &peerAddr); 53 | void removeConnection(TcpConnection *conn); 54 | 55 | const string _name; 56 | EventLoop *_loop; 57 | TcpConnection *_conn; 58 | 59 | ConnectionCallback _connectionCallback; 60 | MessageCallback _messageCallback; 61 | WriteCompleteCallback _writeCompleteCallback; 62 | }; 63 | 64 | } // namespace net 65 | } // namespace thefox 66 | 67 | #endif // _THEFOX_NET_TCPCLIENT_H_ -------------------------------------------------------------------------------- /net/tcp_connection.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox; 5 | using namespace thefox::net; 6 | 7 | void thefox::net::defaultMessageCallback(TcpConnection *conn, 8 | Buffer* buf, const Timestamp recvTime) 9 | { 10 | buf->retrieveAll(); 11 | } 12 | 13 | TcpConnection::TcpConnection(EventLoop *loop, SOCKET sockfd, int id, 14 | const InetAddress& localAddr, const InetAddress &peerAddr) 15 | : _loop(loop) 16 | , _socket(sockfd) 17 | , _id(id) 18 | , _localAddr(localAddr) 19 | , _peerAddr(peerAddr) 20 | , _readBytes(0) 21 | , _writeBytes(0) 22 | , _arg(NULL) 23 | , _state(kConnecting) 24 | , _pendingEvents(0) 25 | { 26 | THEFOX_TRACE_FUNCTION; 27 | 28 | Socket::setNonBlock(sockfd); 29 | } 30 | 31 | TcpConnection::~TcpConnection() 32 | { 33 | THEFOX_TRACE_FUNCTION; 34 | } 35 | 36 | void TcpConnection::send(const string &data) 37 | { 38 | this->send(data.c_str(), data.length()); 39 | } 40 | 41 | void TcpConnection::send(const char *data, size_t len) 42 | { 43 | _writeBuffer.append(data, len); 44 | 45 | if (!_event.testAndSetWrite()) { 46 | _loop->updateWrite(&_event); 47 | } 48 | } 49 | 50 | bool TcpConnection::shutdown() 51 | { 52 | THEFOX_TRACE_FUNCTION; 53 | 54 | return _socket.shutdownWrite(); 55 | } 56 | 57 | void TcpConnection::setTcpNoDelay(bool on) 58 | { 59 | THEFOX_TRACE_FUNCTION << "on=" << on; 60 | 61 | _socket.setTcpNoDelay(on); 62 | } 63 | 64 | void TcpConnection::forceClose() 65 | { 66 | THEFOX_TRACE_FUNCTION; 67 | 68 | if (kConnected == _state || kDisconnecting == _state) { 69 | setState(kDisconnecting); 70 | connectDestroyed(); 71 | } 72 | } 73 | 74 | void TcpConnection::connectEstablished() 75 | { 76 | THEFOX_TRACE_FUNCTION; 77 | 78 | assert(kConnecting == _state ); 79 | 80 | setState(kConnected); 81 | 82 | _event.fd = fd(); 83 | _event.conn = this; 84 | 85 | _loop->addEvent(&_event); 86 | 87 | // set read 88 | _loop->updateRead(&_event); 89 | 90 | if (_connectionCallback) { 91 | _connectionCallback(this); 92 | } 93 | } 94 | 95 | void TcpConnection::connectDestroyed() 96 | { 97 | THEFOX_TRACE_FUNCTION; 98 | 99 | _event.error = true; 100 | 101 | if (kConnected == _state || kDisconnecting == _state) { 102 | setState(kDisconnected); 103 | THEFOX_LOG(DEBUG) << "connection closed, addr:" << _peerAddr.toIpPort(); 104 | 105 | _loop->delEvent(&_event); 106 | Socket::close(_socket.fd()); 107 | 108 | if (_connectionCallback) { 109 | _connectionCallback(this); 110 | } 111 | } 112 | 113 | if (0 == leaveEvent()) { 114 | if (_removeConnectionCallback) { 115 | _removeConnectionCallback(this); // it's last line, connection is over 116 | return; 117 | } 118 | } 119 | } 120 | 121 | void TcpConnection::enterEvent() 122 | { 123 | MutexGuard lock(_eventmutex); 124 | ++_pendingEvents; 125 | } 126 | 127 | size_t TcpConnection::leaveEvent() 128 | { 129 | MutexGuard lock(_eventmutex); 130 | if (0 != _pendingEvents) { 131 | --_pendingEvents; 132 | } 133 | return _pendingEvents; 134 | } 135 | -------------------------------------------------------------------------------- /net/tcp_connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @filename tcp_connection.h 3 | * @brief 表示一个客户连接 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_TCPCONNECTION_H_ 8 | #define _THEFOX_NET_TCPCONNECTION_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace thefox { 20 | namespace net { 21 | 22 | class EventLoop; 23 | class TcpConnection; 24 | typedef std::function RemoveConnectionCallback; 25 | 26 | class TcpConnection 27 | { 28 | public: 29 | enum StateT { kDisconnected, kConnecting, kConnected, kDisconnecting }; 30 | 31 | TcpConnection(EventLoop *loop, SOCKET sockfd, int id, 32 | const InetAddress &localAddr, const InetAddress &peerAddr); 33 | ~TcpConnection(); 34 | 35 | /// @brief get conn id 36 | int32_t id() const { return _id; } 37 | 38 | /// @brief get socket handle 39 | SOCKET fd() const { return _socket.fd(); } 40 | 41 | /// @brief get peer address 42 | const InetAddress &peerAddr() const { return _peerAddr; } 43 | 44 | Buffer *readBuffer() { return &_readBuffer; } 45 | Buffer *writeBuffer() { return &_writeBuffer; } 46 | 47 | /// @brief get connection state 48 | StateT state() const { return _state; } 49 | void setState(StateT state) { _state = state; } 50 | 51 | /// @brief 52 | void *arg() const { return _arg; } 53 | 54 | /// @brief 55 | void setArg(void *arg) { _arg = arg; } 56 | 57 | size_t readBytes() const { return _readBytes; } 58 | size_t writeBytes() const { return _writeBytes; } 59 | 60 | void send(const string &data); 61 | void send(const char *data, size_t len); 62 | 63 | bool shutdown(); 64 | void setTcpNoDelay(bool on); 65 | void forceClose(); 66 | void connectEstablished(); 67 | 68 | void setConnectionCallback(const ConnectionCallback &cb) 69 | { _connectionCallback = cb; } 70 | void setMessageCallback(const MessageCallback &cb) 71 | { _messageCallback = cb; } 72 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 73 | { _writeCompleteCallback = cb; } 74 | void setRemoveConnectionCallback(const RemoveConnectionCallback &cb) 75 | { _removeConnectionCallback = cb; } 76 | 77 | private: 78 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpConnection); 79 | 80 | void connectDestroyed(); 81 | 82 | void enterEvent(); 83 | size_t leaveEvent(); 84 | 85 | void addReadBytes(size_t bytes) { _readBytes += bytes; } 86 | void addWriteBytes(size_t bytes) { _writeBytes += bytes; } 87 | 88 | EventLoop *_loop; 89 | int32_t _id; 90 | Socket _socket; 91 | const InetAddress _localAddr; 92 | const InetAddress _peerAddr; 93 | Buffer _readBuffer; 94 | Buffer _writeBuffer; 95 | StateT _state; 96 | 97 | void *_arg; 98 | 99 | // io transfer counter 100 | size_t _readBytes; 101 | size_t _writeBytes; 102 | 103 | ConnectionCallback _connectionCallback; 104 | MessageCallback _messageCallback; 105 | WriteCompleteCallback _writeCompleteCallback; 106 | RemoveConnectionCallback _removeConnectionCallback; 107 | 108 | Event _event; 109 | Mutex _eventmutex; 110 | size_t _pendingEvents; 111 | 112 | friend class Poller; 113 | }; 114 | 115 | } // namespace net 116 | } // namespace thefox 117 | 118 | #endif // _THEFOX_NET_TCPCONNECTION_H_ -------------------------------------------------------------------------------- /net/tcp_server.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/net/tcp_server.cc -------------------------------------------------------------------------------- /net/tcp_server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename tcp_server.h 3 | * @brief tcp server 4 | * @author macwe1024 at gmail dot com 5 | */ 6 | 7 | #ifndef _THEFOX_NET_TCPSERVER_H_ 8 | #define _THEFOX_NET_TCPSERVER_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace thefox { 21 | namespace net { 22 | 23 | class EventLoop; 24 | class InetAddress; 25 | class TcpConnection; 26 | 27 | class TcpServer 28 | { 29 | public: 30 | TcpServer(EventLoop *loop, const InetAddress &listenAddr, const string &nameArg); 31 | ~TcpServer(void); 32 | 33 | /// @brief start the server 34 | /// @return return true if success,then return false 35 | bool start(); 36 | 37 | /// @brief check if the server started 38 | /// @return return true if success,then return false 39 | bool started() const { return _started; } 40 | 41 | void setConnectionCallback(const ConnectionCallback &cb) 42 | { 43 | _connectionCallback = cb; 44 | } 45 | void setMessageCallback(const MessageCallback &cb) 46 | { 47 | _messageCallback = cb; 48 | } 49 | void setWriteCompleteCallback(const WriteCompleteCallback &cb) 50 | { 51 | _writeCompleteCallback = cb; 52 | } 53 | 54 | private: 55 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TcpServer); 56 | 57 | void onNewConnection(SOCKET sockfd, const InetAddress &localAddr, const InetAddress &peerAddr); 58 | void onRemoveConnection(TcpConnection *conn); 59 | 60 | typedef std::map ConnectionMap; 61 | 62 | const string _name; 63 | EventLoop *_loop; 64 | Acceptor *_acceptor; 65 | 66 | bool _started; 67 | AtomicInt32 _nextConnId; 68 | Mutex _mutex; 69 | ConnectionMap _connections; 70 | ObjectPool _connectionPool; 71 | 72 | ConnectionCallback _connectionCallback; 73 | MessageCallback _messageCallback; 74 | WriteCompleteCallback _writeCompleteCallback; 75 | }; 76 | 77 | } // namespace net 78 | } // namespace thefox 79 | 80 | #endif // _THEFOX_NET_TCPSERVER_H_ 81 | -------------------------------------------------------------------------------- /project/IocpDemo/IocpDemo.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | 10 | 11 | 源文件 12 | 13 | 14 | -------------------------------------------------------------------------------- /project/IocpDemo/IocpDemo.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /project/IocpDemo/main.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/IocpDemo/main.cc -------------------------------------------------------------------------------- /project/NetClient/NetClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | 10 | 11 | Source Files 12 | 13 | 14 | -------------------------------------------------------------------------------- /project/NetClient/NetClient.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /project/NetClient/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace thefox; 6 | 7 | char text[81920]; 8 | 9 | void onConnection(const TcpConnectionPtr &conn) 10 | { 11 | conn->send(text, strlen(text)); 12 | } 13 | 14 | void onClose(const TcpConnectionPtr &conn) 15 | { 16 | printf("Connection close\r\n"); 17 | } 18 | 19 | void onMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp receiveTime) 20 | { 21 | printf("%s Message come, size=%u\r\n", receiveTime.toFormatString().c_str(), buf->readableBytes()); 22 | conn->send(buf->peek(), buf->readableBytes()); 23 | buf->retrieveAll(); 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | for (int i = 0; i < sizeof(text); ++i ) { 29 | text[i] = 'a'; 30 | } 31 | text[sizeof(text)] = '\0'; 32 | 33 | io_service io; 34 | 35 | ip::tcp::endpoint serverAddr(ip::address::from_string("127.0.0.1"), 8888); 36 | 37 | TcpClient client(io, "fdf"); 38 | client.setConnectionCallback(onConnection); 39 | client.setMessageCallback(onMessage); 40 | client.open(serverAddr); 41 | 42 | //for(;;) { 43 | io.run(); 44 | //} 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /project/TestLog/ReadMe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/TestLog/ReadMe.txt -------------------------------------------------------------------------------- /project/TestLog/TestLog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/TestLog/TestLog.cpp -------------------------------------------------------------------------------- /project/TestLog/TestLog.vcproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/TestLog/TestLog.vcproj -------------------------------------------------------------------------------- /project/TestLog/TestLog.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 头文件 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/TestLog/TestLog.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /project/TestLog/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/TestLog/stdafx.cpp -------------------------------------------------------------------------------- /project/TestLog/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/project/TestLog/stdafx.h -------------------------------------------------------------------------------- /project/TheFoxFramework.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libthefox", "libthefox\libthefox.vcxproj", "{77DF8D9B-AE9A-41AB-B798-6205096D3029}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IocpDemo", "IocpDemo\IocpDemo.vcxproj", "{F11C017B-D665-4E5B-942C-4791ECE52DCC}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetClient", "NetClient\NetClient.vcxproj", "{ED5F747A-580C-498D-A86A-29A6EADE83EC}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLog", "TestLog\TestLog.vcxproj", "{06038EFF-4A50-41DB-B39C-E350E58EAB43}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Win32 = Debug|Win32 15 | Release|Win32 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {77DF8D9B-AE9A-41AB-B798-6205096D3029}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {77DF8D9B-AE9A-41AB-B798-6205096D3029}.Debug|Win32.Build.0 = Debug|Win32 20 | {77DF8D9B-AE9A-41AB-B798-6205096D3029}.Release|Win32.ActiveCfg = Release|Win32 21 | {77DF8D9B-AE9A-41AB-B798-6205096D3029}.Release|Win32.Build.0 = Release|Win32 22 | {F11C017B-D665-4E5B-942C-4791ECE52DCC}.Debug|Win32.ActiveCfg = Debug|Win32 23 | {F11C017B-D665-4E5B-942C-4791ECE52DCC}.Debug|Win32.Build.0 = Debug|Win32 24 | {F11C017B-D665-4E5B-942C-4791ECE52DCC}.Release|Win32.ActiveCfg = Release|Win32 25 | {F11C017B-D665-4E5B-942C-4791ECE52DCC}.Release|Win32.Build.0 = Release|Win32 26 | {ED5F747A-580C-498D-A86A-29A6EADE83EC}.Debug|Win32.ActiveCfg = Debug|Win32 27 | {ED5F747A-580C-498D-A86A-29A6EADE83EC}.Debug|Win32.Build.0 = Debug|Win32 28 | {ED5F747A-580C-498D-A86A-29A6EADE83EC}.Release|Win32.ActiveCfg = Release|Win32 29 | {ED5F747A-580C-498D-A86A-29A6EADE83EC}.Release|Win32.Build.0 = Release|Win32 30 | {06038EFF-4A50-41DB-B39C-E350E58EAB43}.Debug|Win32.ActiveCfg = Debug|Win32 31 | {06038EFF-4A50-41DB-B39C-E350E58EAB43}.Debug|Win32.Build.0 = Debug|Win32 32 | {06038EFF-4A50-41DB-B39C-E350E58EAB43}.Release|Win32.ActiveCfg = Release|Win32 33 | {06038EFF-4A50-41DB-B39C-E350E58EAB43}.Release|Win32.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /project/libthefox/libthefox.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {e9e31d0d-cf35-4496-9a47-00d8497e2bac} 6 | 7 | 8 | {07e1d8f6-b463-4363-ad4b-81a3a4a2352e} 9 | 10 | 11 | 12 | 13 | log 14 | 15 | 16 | log 17 | 18 | 19 | log 20 | 21 | 22 | net 23 | 24 | 25 | net 26 | 27 | 28 | net 29 | 30 | 31 | net 32 | 33 | 34 | net 35 | 36 | 37 | net 38 | 39 | 40 | net 41 | 42 | 43 | net 44 | 45 | 46 | net 47 | 48 | 49 | net 50 | 51 | 52 | net 53 | 54 | 55 | 56 | 57 | log 58 | 59 | 60 | log 61 | 62 | 63 | log 64 | 65 | 66 | net 67 | 68 | 69 | net 70 | 71 | 72 | net 73 | 74 | 75 | net 76 | 77 | 78 | net 79 | 80 | 81 | net 82 | 83 | 84 | net 85 | 86 | 87 | -------------------------------------------------------------------------------- /project/libthefox/libthefox.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /project/removejunk.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo ---------------------------------------------------- 3 | echo Press any key to delete all files with ending: 4 | echo *.aps *.idb *.ncp *.obj *.pch *.tmp *.sbr 5 | echo Visual c++/.Net junk 6 | echo ---------------------------------------------------- 7 | pause 8 | 9 | del /F /Q /S *.aps *.idb *.ncp *.obj *.pch *.sbr *.tmp *.pdb *.bsc *.ilk *.res *.ncb *.opt *.suo *.manifest *.dep *.sdf 10 | 11 | 12 | pause 13 | 14 | 15 | -------------------------------------------------------------------------------- /rpc/README.md: -------------------------------------------------------------------------------- 1 | TheFox RPC framework 2 | =============== 3 | 猎狐软件 的 RPC框架 4 | 基于protobuf开发,支持同步和异步的调用方式 5 | 6 | 使用说明: 7 | 1.定义service描述,并生产代码 8 | 9 | package echo; 10 | 11 | option cc_generic_services = true; 12 | 13 | message EchoRequest { 14 | required string message = 1; 15 | } 16 | 17 | message EchoResponse { 18 | required string response = 1; 19 | } 20 | 21 | service EchoService { 22 | rpc echo (EchoRequest) returns (EchoResponse); 23 | } 24 | 25 | 2.服务端: 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "../../rpc/test/echo.pb.h" 32 | 33 | using namespace thefox; 34 | 35 | class EchoSerivceImpl : public echo::EchoService 36 | { 37 | virtual void echo(gpb::RpcController *controller, 38 | const echo::EchoRequest *request, 39 | echo::EchoResponse *response, 40 | gpb::Closure *done) 41 | { 42 | response->set_response(request->message()); 43 | done->Run(); 44 | } 45 | }; 46 | 47 | int main(int argc, char **argv) 48 | { 49 | WSADATA wsd; 50 | WSAStartup(MAKEWORD(2, 2), &wsd); 51 | 52 | EventLoop loop; 53 | loop.start(); 54 | 55 | RpcServer rpcServer(&loop); 56 | 57 | EchoSerivceImpl echoService; 58 | rpcServer.registerService(&echoService); 59 | 60 | rpcServer.start(InetAddress(7903)); 61 | 62 | loop.join(); 63 | 64 | WSACleanup(); 65 | return 0; 66 | } 67 | 68 | 2.客户端 69 | 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include "../../rpc/test/echo.pb.h" 75 | 76 | using namespace thefox; 77 | 78 | int main(int argc, char **argv) 79 | { 80 | WSADATA wsd; 81 | WSAStartup(MAKEWORD(2, 2), &wsd); 82 | 83 | EventLoop loop; 84 | loop.start(); 85 | 86 | RpcChannel rpcChannel(&loop); 87 | rpcChannel.open(InetAddress("127.0.0.1", 7903)); 88 | 89 | 90 | echo::EchoService::Stub echoChannel(&rpcChannel); 91 | echo::EchoRequest request; 92 | request.set_message("hello"); 93 | echo::EchoResponse response; 94 | 95 | echoChannel.echo(NULL, &request, &response, NULL); 96 | 97 | loop.join(); 98 | 99 | WSACleanup(); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /rpc/c.bat: -------------------------------------------------------------------------------- 1 | .\protoc.exe --cpp_out=. .\rpc.proto 2 | pause -------------------------------------------------------------------------------- /rpc/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_RPC_COMMON_H_ 2 | #define _THEFOX_RPC_COMMON_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace google 8 | { 9 | namespace protobuf 10 | { 11 | 12 | typedef std::shared_ptr MessagePtr; 13 | 14 | } 15 | } 16 | 17 | namespace thefox 18 | { 19 | 20 | #define gpb ::google::protobuf 21 | 22 | 23 | class RpcServiceManager; 24 | typedef std::shared_ptr ServiceManagerPtr; 25 | typedef std::shared_ptr BoxPtr; 26 | 27 | class TaskManager; 28 | typedef std::shared_ptr TaskManagerPtr; 29 | 30 | typedef std::function OnewayCallback; 34 | 35 | typedef std::function HeartBeathCallback; 36 | typedef std::function ReplyCallback; 39 | typedef std::function CallCallback; 42 | 43 | } //namespace thefox; 44 | 45 | #endif // _THEFOX_RPC_COMMON_H_ -------------------------------------------------------------------------------- /rpc/oneway_dispatcher.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/oneway_dispatcher.h -------------------------------------------------------------------------------- /rpc/protoc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/protoc.exe -------------------------------------------------------------------------------- /rpc/rpc.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/rpc.proto -------------------------------------------------------------------------------- /rpc/rpc_channel.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace thefox; 10 | 11 | RpcChannel::RpcChannel(RpcClient *rpcClient, const InetAddress &serverAddr) 12 | : _client(new TcpClient(rpcClient->eventloop(), "thefox.rpcchannel")) 13 | , _rpcClient(rpcClient) 14 | { 15 | rpcClient->registerChannel(this); 16 | 17 | _client->setConnectionCallback(std::bind(&RpcChannel::onConnection, this, _1)); 18 | _client->setMessageCallback(std::bind(&RpcChannel::onMessage, this, _1, _2, _3)); 19 | _client->open(serverAddr); 20 | } 21 | 22 | RpcChannel::~RpcChannel() 23 | { 24 | _client->close(); 25 | _rpcClient->unregisterChannel(this); 26 | } 27 | 28 | void RpcChannel::CallMethod(const ::google::protobuf::MethodDescriptor* method, 29 | ::google::protobuf::RpcController* controller, 30 | const ::google::protobuf::Message* request, 31 | ::google::protobuf::Message* response, 32 | ::google::protobuf::Closure* done) 33 | { 34 | _rpcClient->CallMethod(_conn, method, dynamic_cast(controller), request, response, done); 35 | } 36 | 37 | void RpcChannel::setTaskManager(const TaskManagerPtr &taskManager) 38 | { 39 | _taskManager = taskManager; 40 | } 41 | 42 | void RpcChannel::onConnection(TcpConnection *conn) 43 | { 44 | _conn = conn; 45 | } 46 | 47 | void RpcChannel::onMessage(TcpConnection *conn, Buffer *buf, Timestamp recvTime) 48 | { 49 | while (RpcCodec::isValid(buf->peek(), buf->readableBytes())) { 50 | BoxPtr box(new rpc::Box()); 51 | size_t bufLen = buf->readableBytes(); 52 | if (RpcCodec::parseFromArray(buf->peek(), bufLen, box)) { 53 | _taskManager->pushBox(conn, recvTime, box); 54 | buf->retrieve(bufLen); 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /rpc/rpc_channel.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_RPC_RPCCHANNEL_H_ 2 | #define _THEFOX_RPC_RPCCHANNEL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace thefox 12 | { 13 | 14 | class RpcClient; 15 | 16 | class RpcChannel : public gpb::RpcChannel 17 | { 18 | public: 19 | RpcChannel(RpcClient *rpcClient, const InetAddress &serverAddr); 20 | ~RpcChannel(); 21 | 22 | void CallMethod(const ::google::protobuf::MethodDescriptor* method, 23 | ::google::protobuf::RpcController* controller, 24 | const ::google::protobuf::Message* request, 25 | ::google::protobuf::Message* response, 26 | ::google::protobuf::Closure* done); 27 | 28 | void setTaskManager(const TaskManagerPtr &taskManager); 29 | 30 | private: 31 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel); 32 | void onConnection(TcpConnection *conn); 33 | void onMessage(TcpConnection *conn, Buffer *buf, Timestamp recvTime); 34 | 35 | TcpConnection *_conn; 36 | std::shared_ptr _client; 37 | RpcClient *_rpcClient; 38 | TaskManagerPtr _taskManager; 39 | }; 40 | 41 | } // namespace thefox 42 | 43 | #endif // _THEFOX_RPC_RPCCHANNEL_H_ 44 | -------------------------------------------------------------------------------- /rpc/rpc_client.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace thefox; 8 | 9 | RpcClient::RpcClient(EventLoop *loop) 10 | : _loop(loop) 11 | { 12 | _taskManager = std::make_shared( 13 | NULL, std::bind(&RpcClient::handleReplyMessage, this, _1, _2, _3)); 14 | } 15 | 16 | RpcClient::~RpcClient() 17 | {} 18 | 19 | void RpcClient::registerChannel(RpcChannel *channel) 20 | { 21 | channel->setTaskManager(_taskManager); 22 | _channels.push_back(channel); 23 | } 24 | 25 | void RpcClient::unregisterChannel(RpcChannel *channel) 26 | { 27 | _channels.remove(channel); 28 | } 29 | 30 | void RpcClient::CallMethod(TcpConnection *conn, 31 | const ::google::protobuf::MethodDescriptor* method, 32 | RpcController *controller, 33 | const ::google::protobuf::Message* request, 34 | ::google::protobuf::Message* response, 35 | ::google::protobuf::Closure* done) 36 | { 37 | rpc::Call *call = new rpc::Call(); 38 | 39 | int64_t id = _id.inc(); 40 | call->set_id(id); 41 | call->set_service(method->service()->name()); 42 | call->set_method(method->name()); 43 | call->set_request(request->SerializeAsString()); 44 | call->set_timeout(controller->timeout()); 45 | 46 | RequestWaitPtr reqWait(new RequestWait(response, done)); 47 | 48 | { 49 | MutexGuard lock(_mutex); 50 | _requests[id] = reqWait; 51 | } 52 | 53 | rpc::Box box; 54 | box.set_allocated_call(call); 55 | conn->send(RpcCodec::encode(box)); 56 | 57 | if (NULL == done) // synchronize 58 | reqWait->doneEvent.wait(); 59 | } 60 | 61 | void RpcClient::handleReplyMessage(TcpConnection *conn, const rpc::Reply &reply, Timestamp recvTime) 62 | { 63 | const int64_t id = reply.id(); 64 | 65 | RequestWaitPtr reqWait; 66 | 67 | { 68 | MutexGuard lock(_mutex); 69 | RequestWaitMap::iterator it = _requests.find(id); 70 | if (it != _requests.end()) { 71 | reqWait = it->second; 72 | _requests.erase(it); 73 | } 74 | } 75 | 76 | if (reqWait) { 77 | reqWait->response->ParseFromString(reply.response()); 78 | reqWait->doneEvent.set(); 79 | if (reqWait->done) 80 | reqWait->done->Run(); 81 | } 82 | } -------------------------------------------------------------------------------- /rpc/rpc_client.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_RPC_RPCCLIENT_H_ 2 | #define _THEFOX_RPC_RPCCLIENT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace thefox 12 | { 13 | 14 | class EventLoop; 15 | class TaskManager; 16 | class RpcController; 17 | 18 | class RpcClient 19 | { 20 | public: 21 | friend class RpcChannel; 22 | 23 | RpcClient(EventLoop *loop); 24 | ~RpcClient(); 25 | 26 | EventLoop *eventloop() { return _loop; } 27 | 28 | void registerChannel(RpcChannel *channel); 29 | void unregisterChannel(RpcChannel *channel); 30 | 31 | private: 32 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(RpcClient); 33 | void CallMethod(TcpConnection *conn, 34 | const ::google::protobuf::MethodDescriptor* method, 35 | RpcController *controller, 36 | const ::google::protobuf::Message* request, 37 | ::google::protobuf::Message* response, 38 | ::google::protobuf::Closure* done); 39 | void handleReplyMessage(TcpConnection *conn, 40 | const rpc::Reply &reply, 41 | Timestamp recvTime); 42 | class RequestWait 43 | { 44 | public: 45 | RequestWait(gpb::Message* response, gpb::Closure *done) 46 | : response(response) 47 | , done(done) 48 | {} 49 | gpb::Message* response; 50 | gpb::Closure *done; 51 | Event doneEvent; 52 | }; 53 | typedef std::shared_ptr RequestWaitPtr; 54 | typedef std::map RequestWaitMap; 55 | typedef std::list RpcChannelList; 56 | 57 | AtomicInt32 _id; 58 | Mutex _mutex; 59 | RequestWaitMap _requests; 60 | EventLoop *_loop; 61 | RpcChannelList _channels; 62 | TaskManagerPtr _taskManager; 63 | }; 64 | 65 | } // namespace thefox 66 | 67 | #endif // _THEFOX_RPC_RPCCLIENT_H_ 68 | -------------------------------------------------------------------------------- /rpc/rpc_codec.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/rpc_codec.h -------------------------------------------------------------------------------- /rpc/rpc_controller.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace thefox; 5 | 6 | RpcController::RpcController() 7 | : _timeout(30*1000) 8 | { 9 | } 10 | 11 | RpcController::~RpcController() 12 | { 13 | } -------------------------------------------------------------------------------- /rpc/rpc_controller.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_RPC_RPCCONTROLLER_H_ 2 | #define _THEFOX_RPC_RPCCONTROLLER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace thefox 10 | { 11 | 12 | class RpcController : public google::protobuf::RpcController 13 | { 14 | public: 15 | RpcController(); 16 | virtual ~RpcController(); 17 | 18 | // Client-side methods --------------------------------------------- 19 | // These calls may be made from the client side only. Their results 20 | // are undefined on the server side (may crash). 21 | 22 | // Resets the RpcController to its initial state so that it may be reused in 23 | // a new call. Must not be called while an RPC is in progress. 24 | virtual void Reset() {} 25 | 26 | // After a call has finished, returns true if the call failed. The possible 27 | // reasons for failure depend on the RPC implementation. Failed() must not 28 | // be called before a call has finished. If Failed() returns true, the 29 | // contents of the response message are undefined. 30 | virtual bool Failed() const { return !_reason.empty(); } 31 | 32 | // If Failed() is true, returns a human-readable description of the error. 33 | virtual std::string ErrorText() const { return _reason; } 34 | 35 | // Advises the RPC system that the caller desires that the RPC call be 36 | // canceled. The RPC system may cancel it immediately, may wait awhile and 37 | // then cancel it, or may not even cancel the call at all. If the call is 38 | // canceled, the "done" callback will still be called and the RpcController 39 | // will indicate that the call failed at that time. 40 | virtual void StartCancel() {} 41 | 42 | // Server-side methods --------------------------------------------- 43 | // These calls may be made from the server side only. Their results 44 | // are undefined on the client side (may crash). 45 | 46 | // Causes Failed() to return true on the client side. "reason" will be 47 | // incorporated into the message returned by ErrorText(). If you find 48 | // you need to return machine-readable information about failures, you 49 | // should incorporate it into your response protocol buffer and should 50 | // NOT call SetFailed(). 51 | virtual void SetFailed(const std::string& reason) { _reason = reason; } 52 | 53 | // If true, indicates that the client canceled the RPC, so the server may 54 | // as well give up on replying to it. The server should still call the 55 | // final "done" callback. 56 | virtual bool IsCanceled() const { return false; } 57 | 58 | // Asks that the given callback be called when the RPC is canceled. The 59 | // callback will always be called exactly once. If the RPC completes without 60 | // being canceled, the callback will be called after completion. If the RPC 61 | // has already been canceled when NotifyOnCancel() is called, the callback 62 | // will be called immediately. 63 | // 64 | // NotifyOnCancel() must be called no more than once per request. 65 | virtual void NotifyOnCancel(google::protobuf::Closure* callback) 66 | { callback->Run(); } 67 | 68 | int errorCode() const { return _errorCode; } 69 | void setErrorCode(int errorCode) { _errorCode = errorCode; } 70 | 71 | int32_t timeout() const { return _timeout; } 72 | void setTimeout(int32_t timeout) { _timeout = timeout; } 73 | 74 | TcpConnection *connection() const { return _conn; } 75 | void setConnection(TcpConnection *conn) { _conn = conn; } 76 | 77 | const Timestamp &receiveTime() const { return _receiveTime; } 78 | void setReceiveTime(const Timestamp &receiveTime) { _receiveTime = receiveTime; } 79 | 80 | private: 81 | int _errorCode; 82 | int32_t _timeout; 83 | Timestamp _receiveTime; 84 | std::string _reason; 85 | TcpConnection *_conn; 86 | }; 87 | 88 | } // namespace thefox 89 | 90 | #endif // _THEFOX_RPC_RPCCONTROLLER_H_ 91 | -------------------------------------------------------------------------------- /rpc/rpc_server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace thefox; 11 | 12 | RpcServer::RpcServer(EventLoop *loop, const InetAddress &listenAddr) 13 | : _server(new TcpServer(loop, listenAddr, "thefoxRpcServer")) 14 | , _serviceManager(new RpcServiceManager()) 15 | , _rpcServiceImpl(new RpcServiceImpl(_serviceManager)) 16 | { 17 | registerService(_rpcServiceImpl.get()); 18 | _taskManager = std::make_shared( 19 | std::bind(&RpcServer::handleCallMessage, this, _1, _2, _3), NULL); 20 | } 21 | 22 | RpcServer::~RpcServer() 23 | {} 24 | 25 | void RpcServer::registerService(gpb::Service *service) 26 | { 27 | _serviceManager->registerService(service); 28 | } 29 | void RpcServer::setHearthBeathCallback(const HeartBeathCallback &cb) 30 | { 31 | _rpcServiceImpl->setHearthBeathCallback(cb); 32 | } 33 | 34 | bool RpcServer::start() 35 | { 36 | _server->setConnectionCallback(std::bind(&RpcServer::onConnection, this, _1)); 37 | _server->setMessageCallback(std::bind(&RpcServer::onMessage, this, _1, _2, _3)); 38 | 39 | return _server->start(); 40 | } 41 | 42 | void RpcServer::sendOneway(TcpConnection *conn, const gpb::Message *message) 43 | { 44 | const std::string& typeName = message->GetTypeName(); 45 | rpc::OnewayMessage *oneway = new rpc::OnewayMessage(); 46 | oneway->set_type(typeName); 47 | oneway->set_body(message->SerializeAsString()); 48 | 49 | rpc::Box box; 50 | box.set_allocated_oneway(oneway); 51 | conn->send(RpcCodec::encode(box)); 52 | } 53 | 54 | void RpcServer::onConnection(TcpConnection *conn) 55 | {} 56 | 57 | void RpcServer::onMessage(TcpConnection *conn, Buffer *buf, const Timestamp recvTime) 58 | { 59 | while (RpcCodec::isValid(buf->peek(), buf->readableBytes())) { 60 | BoxPtr box(new rpc::Box()); 61 | size_t bufLen = buf->readableBytes(); 62 | if (RpcCodec::parseFromArray(buf->peek(), bufLen, box)) { 63 | _taskManager->pushBox(conn, recvTime, box); 64 | buf->retrieve(bufLen); 65 | } 66 | } 67 | } 68 | 69 | void RpcServer::handleCallMessage(TcpConnection *conn, const rpc::Call &call, Timestamp receiveTime) 70 | { 71 | if (NULL == _serviceManager) 72 | return; 73 | 74 | gpb::Service *service = _serviceManager->findService(call.service()); 75 | if (NULL != service) { 76 | const gpb::ServiceDescriptor *desc = service->GetDescriptor(); 77 | const gpb::MethodDescriptor *method = desc->FindMethodByName(call.method()); 78 | 79 | if (method) { 80 | gpb::Message *request(service->GetRequestPrototype(method).New()); 81 | request->ParseFromString(call.request()); 82 | 83 | gpb::Message *response(service->GetResponsePrototype(method).New()); 84 | 85 | service->CallMethod(method, NULL, request, response, gpb::NewCallback(&gpb::DoNothing)); 86 | 87 | //done 88 | 89 | rpc::Reply *reply = new rpc::Reply(); 90 | reply->set_id(call.id()); 91 | reply->set_result(rpc::Reply_Result_kOk); 92 | reply->set_response(response->SerializeAsString()); 93 | 94 | rpc::Box box; 95 | box.set_allocated_reply(reply); 96 | conn->send(RpcCodec::encode(box)); 97 | 98 | delete request; 99 | delete response; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /rpc/rpc_server.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/rpc_server.h -------------------------------------------------------------------------------- /rpc/rpc_service.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace thefox 5 | { 6 | 7 | void defaultHeartBeathCallback() 8 | {} 9 | 10 | } // namespace thefox 11 | 12 | using namespace thefox; 13 | 14 | RpcServiceImpl::RpcServiceImpl(const ServiceManagerPtr &sm) 15 | : _serviceManager(sm) 16 | , _heartBeathCallback(defaultHeartBeathCallback) 17 | {} 18 | 19 | void RpcServiceImpl::heartBeath(::google::protobuf::RpcController* controller, 20 | const ::thefox::rpc::HeartBeath* request, 21 | ::thefox::rpc::HeartBeath* response, 22 | ::google::protobuf::Closure* done) 23 | { 24 | _heartBeathCallback(); 25 | done->Run(); 26 | } 27 | 28 | void RpcServiceImpl::listRpc(::google::protobuf::RpcController* controller, 29 | const ::thefox::rpc::Placeholder* request, 30 | ::thefox::rpc::RpcList* response, 31 | ::google::protobuf::Closure* done) 32 | { 33 | _serviceManager->getRpcList(response); 34 | done->Run(); 35 | } 36 | -------------------------------------------------------------------------------- /rpc/rpc_service.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_RPC_RPCSERVICE_H_ 2 | #define _THEFOX_NET_RPC_RPCSERVICE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace thefox { 9 | 10 | class RpcServiceImpl : public rpc::RpcService 11 | { 12 | public: 13 | RpcServiceImpl(const ServiceManagerPtr &sm); 14 | 15 | void heartBeath(::google::protobuf::RpcController* controller, 16 | const ::thefox::rpc::HeartBeath* request, 17 | ::thefox::rpc::HeartBeath* response, 18 | ::google::protobuf::Closure* done); 19 | 20 | void listRpc(::google::protobuf::RpcController* controller, 21 | const ::thefox::rpc::Placeholder* request, 22 | ::thefox::rpc::RpcList* response, 23 | ::google::protobuf::Closure* done); 24 | 25 | void setHearthBeathCallback(const HeartBeathCallback &cb) 26 | { _heartBeathCallback = cb; } 27 | 28 | private: 29 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(RpcServiceImpl); 30 | ServiceManagerPtr _serviceManager; 31 | HeartBeathCallback _heartBeathCallback; 32 | }; 33 | 34 | } // namespace thefox 35 | 36 | #endif // _THEFOX_NET_RPC_RPCSERVICE_H_ -------------------------------------------------------------------------------- /rpc/rpc_service_manager.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace thefox; 6 | 7 | RpcServiceManager::RpcServiceManager() 8 | { 9 | } 10 | 11 | RpcServiceManager::~RpcServiceManager() 12 | { 13 | MutexGuard lock(_mutex); 14 | for (ServiceMap::iterator it = _services.begin(); it != _services.end(); ++it) { 15 | delete it->second; 16 | } 17 | _services.clear(); 18 | } 19 | 20 | void RpcServiceManager::registerService(gpb::Service *service) 21 | { 22 | MutexGuard lock(_mutex); 23 | _services[service->GetDescriptor()->name()] = service; 24 | } 25 | 26 | gpb::Service *RpcServiceManager::findService(const std::string &serviceName) 27 | { 28 | MutexGuard lock(_mutex); 29 | ServiceMap::const_iterator it = _services.find(serviceName); 30 | if (it != _services.end()) 31 | return it->second; 32 | 33 | return NULL; 34 | } 35 | 36 | void RpcServiceManager::getRpcList(rpc::RpcList *list) 37 | { 38 | MutexGuard lock(_mutex); 39 | for (ServiceMap::iterator it = _services.begin(); it != _services.end(); ++it) 40 | list->add_service(it->first); 41 | } -------------------------------------------------------------------------------- /rpc/rpc_service_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_RPC_RPCSERVICEMANAGER_H_ 2 | #define _THEFOX_RPC_RPCSERVICEMANAGER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace thefox 11 | { 12 | 13 | namespace rpc 14 | { 15 | class RpcList; 16 | } 17 | 18 | class RpcServiceManager 19 | { 20 | public: 21 | RpcServiceManager(); 22 | ~RpcServiceManager(); 23 | 24 | void registerService(gpb::Service *service); 25 | gpb::Service *findService(const std::string &serviceName); 26 | 27 | void getRpcList(rpc::RpcList *list); 28 | 29 | private: 30 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(RpcServiceManager); 31 | typedef std::map ServiceMap; 32 | 33 | Mutex _mutex; 34 | ServiceMap _services; 35 | }; 36 | 37 | } // namespace thefox 38 | 39 | #endif // _THEFOX_RPC_RPCSERVICEMANAGER_H_ 40 | 41 | -------------------------------------------------------------------------------- /rpc/task.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xrw67/thefoxframework/45136060c4d521095291b06738cb878ea3cf78cd/rpc/task.h -------------------------------------------------------------------------------- /rpc/task_manager.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace thefox { 4 | namespace detail { 5 | 6 | void defaultOnewayCallback(TcpConnection *sender, 7 | const std::string &type, 8 | const gpb::Message *message, 9 | const Timestamp &receiveTime) 10 | {} 11 | 12 | } 13 | } 14 | 15 | using namespace thefox; 16 | 17 | TaskManager::TaskManager(const CallCallback &callCb, const ReplyCallback &replyCb) 18 | : _dispatcher(detail::defaultOnewayCallback) 19 | , _callCallback(callCb) 20 | , _replyCallback(replyCb) 21 | , _started(true) 22 | 23 | { 24 | _msgLoopThread.reset(new Thread(std::bind(&TaskManager::loop, this), "mqmanager.loop")); 25 | _msgLoopThread->start(); 26 | } 27 | 28 | TaskManager::~TaskManager() 29 | { 30 | _started = false; 31 | _msgLoopThread->stop(); 32 | } 33 | 34 | void TaskManager::pushBox(TcpConnection *sender, const Timestamp &receiveTime, const BoxPtr &msg) 35 | { 36 | MutexGuard lock(_mutex); 37 | TaskPtr box(new Task(sender,receiveTime, msg)); 38 | _tasks.push(box); 39 | _event.set(); 40 | } 41 | 42 | TaskPtr TaskManager::popBox() 43 | { 44 | MutexGuard lock(_mutex); 45 | TaskPtr msg(_tasks.front()); 46 | _tasks.pop(); 47 | return msg; 48 | } 49 | 50 | void TaskManager::setDefaultOnewayCallback(const OnewayCallback &cb) 51 | { 52 | _dispatcher.setDefaultCallback(cb); 53 | } 54 | 55 | void TaskManager::registerOnewayCallback(const gpb::Descriptor *desc, const OnewayCallback &cb) 56 | { 57 | _dispatcher.registerCallback(desc, cb); 58 | } 59 | 60 | void TaskManager::loop() 61 | { 62 | while (_started) { 63 | TaskPtr msg; 64 | while (_event.wait()) { 65 | { 66 | MutexGuard lock(_mutex); 67 | if (_tasks.empty()) { 68 | _event.reset(); 69 | continue; 70 | } 71 | } 72 | 73 | if ((msg = popBox()) != NULL) { 74 | if (msg->hasCall()) 75 | _callCallback(msg->sender(), msg->call(), msg->time()); 76 | if (msg->hasReply()) 77 | _replyCallback(msg->sender(), msg->reply(), msg->time()); 78 | if (msg->hasOneway()) 79 | _dispatcher.onMessage(msg->sender(), msg->oneway(), msg->time()); 80 | } 81 | 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /rpc/task_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEFOX_NET_RPC_TASKMANAGER_H_ 2 | #define _THEFOX_NET_RPC_TASKMANAGER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace thefox 13 | { 14 | 15 | class OnewayDispatcher; 16 | 17 | class TaskManager 18 | { 19 | public: 20 | TaskManager(const CallCallback &callCb, const ReplyCallback &replyCb); 21 | ~TaskManager(); 22 | 23 | void pushBox(TcpConnection *sender, const Timestamp &receiveTime, const BoxPtr &msg); 24 | TaskPtr popBox(); 25 | void setDefaultOnewayCallback(const OnewayCallback &cb); 26 | void registerOnewayCallback(const gpb::Descriptor *desc, const OnewayCallback &cb); 27 | 28 | private: 29 | THEFOX_DISALLOW_EVIL_CONSTRUCTORS(TaskManager); 30 | void loop(); 31 | 32 | typedef std::queue TaskQueue; 33 | TaskQueue _tasks; 34 | Mutex _mutex; 35 | bool _started; 36 | Event _event; 37 | OnewayDispatcher _dispatcher; 38 | std::unique_ptr _msgLoopThread; 39 | 40 | CallCallback _callCallback; 41 | ReplyCallback _replyCallback; 42 | }; 43 | 44 | typedef std::shared_ptr TaskManagerPtr; 45 | 46 | }// namespace thefox 47 | 48 | #endif // _THEFOX_NET_RPC_TASKMANAGER_H_ -------------------------------------------------------------------------------- /rpc/test/echo.proto: -------------------------------------------------------------------------------- 1 | package echo; 2 | 3 | option cc_generic_services = true; 4 | 5 | message EchoRequest { 6 | required string message = 1; 7 | } 8 | 9 | message EchoResponse { 10 | required string response = 1; 11 | } 12 | 13 | service EchoService { 14 | rpc echo (EchoRequest) returns (EchoResponse); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /rpc/test/testrpcclient.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace thefox; 11 | 12 | int main(int argc, char **argv) 13 | { 14 | SocketLibrary::startup(); 15 | 16 | EventLoop loop; 17 | loop.start(); 18 | 19 | RpcClient client(&loop); 20 | RpcChannel channel(&client, InetAddress("127.0.0.1", 7903)); 21 | 22 | 23 | echo::EchoService::Stub echoChannel(&channel); 24 | echo::EchoRequest request; 25 | request.set_message("hello"); 26 | echo::EchoResponse response; 27 | RpcController controller; 28 | echoChannel.echo(&controller, &request, &response, NULL); 29 | 30 | loop.join(); 31 | 32 | SocketLibrary::shutdown(); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /rpc/test/testrpcserver.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace thefox; 9 | 10 | class EchoSerivceImpl : public echo::EchoService 11 | { 12 | virtual void echo(gpb::RpcController *controller, 13 | const echo::EchoRequest *request, 14 | echo::EchoResponse *response, 15 | gpb::Closure *done) 16 | { 17 | response->set_response(request->message()); 18 | done->Run(); 19 | } 20 | }; 21 | 22 | int main(int argc, char **argv) 23 | { 24 | SocketLibrary::startup(); 25 | 26 | EventLoop loop; 27 | loop.start(); 28 | 29 | RpcServer rpcServer(&loop); 30 | 31 | EchoSerivceImpl echoService; 32 | rpcServer.registerService(&echoService); 33 | 34 | rpcServer.start(InetAddress(7903)); 35 | 36 | loop.join(); 37 | 38 | SocketLibrary::shutdown(); 39 | return 0; 40 | } -------------------------------------------------------------------------------- /snmp/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | 3 | CFLAGS= -g 4 | #DFLAGS=-fPIC -shared 5 | INCLUDE=./.. -I/usr/local/include/ 6 | 7 | LIBRARY=netsnmp 8 | 9 | all: snmp 10 | 11 | snmp: test.cpp 12 | $(CC) $(CFLAGS) $(DFLAGS) -std=c++0x -o $@ $^ -I$(INCLUDE) -l$(LIBRARY) 13 | 14 | msg: 15 | protoc --cpp_out=. ./NmsMsg.proto 16 | 17 | clean: 18 | rm -rf *.o snmp -------------------------------------------------------------------------------- /snmp/README.md: -------------------------------------------------------------------------------- 1 | # netsnmppp # 2 | - 一个netsnmp的C++封装的实现 3 | 4 | - 使用C++的封装来简化snmp客户端和snmp agent的开发。 5 | 6 | - 编译需要依赖net-snmp库、stl。 7 | -------------------------------------------------------------------------------- /snmp/test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace thefox; 4 | 5 | int main(int argc, char **argv) 6 | { 7 | Snmp snmp; 8 | if (snmp.open1("192.168.88.96","public")) 9 | { 10 | std::cout<<"open1 success"< values; 82 | 83 | if (snmp.getTable(oids, values)) 84 | { 85 | while (values.fetchRow()) 86 | { 87 | std::cout<<"oid:"<oid<<" value:"<value<<" | oid:"<oid<<"value:"<value<oid = ".1.3.6.1.2.1.1.5.0";//oid 101 | ptr->type = SNMP_TYPE_STRING; 102 | ptr->value = "srdit.net"; 103 | input.push_back(ptr); 104 | 105 | // String inOid = ".1.3.6.1.2.1.1.5.0"; 106 | // char type = SNMP_TYPE_STRING;//'s' 107 | // String value = "linux"; 108 | if (snmp.set(input)) 109 | //if (snmp.set(inOid, type, value)) 110 | { 111 | std::cout<<"snmpset success"<