├── .gitignore ├── AsyncNet.py ├── LICENSE ├── README.md ├── build ├── AsyncNet.mak ├── AsyncNet.sln ├── AsyncNet.vcxproj └── AsyncNet.vcxproj.filters ├── example ├── IndexMap │ └── IndexMap.h └── KernelTimer │ ├── CoreTimer.cpp │ ├── CoreTimer.h │ └── main.cpp ├── source ├── AsyncEvt.cpp ├── AsyncEvt.h ├── AsyncExport.cpp ├── AsyncExport.h ├── AsyncKit.cpp ├── AsyncKit.h ├── AsyncNet.cpp ├── AsyncNet.h ├── AsyncSub.cpp ├── AsyncSub.h ├── ByteArray.h ├── PacketBuffer.h ├── TraceLog.cpp ├── TraceLog.h └── main.cpp ├── system ├── imembase.c ├── imembase.h ├── imemdata.c ├── imemdata.h ├── imemkind.c ├── imemkind.h ├── inetbase.c ├── inetbase.h ├── inetcode.c ├── inetcode.h ├── inetevt.c ├── inetevt.h ├── inetkcp.c ├── inetkcp.h ├── inetkit.c ├── inetkit.h ├── inetnot.c ├── inetnot.h ├── inetsub.c ├── inetsub.h ├── inettcp.c ├── inettcp.h ├── ineturl.c ├── ineturl.h ├── iposix.c ├── iposix.h ├── isecure.c ├── isecure.h ├── itimer.c ├── itimer.h ├── itoolbox.c ├── itoolbox.h └── system.h └── tools ├── AsyncLoader.c ├── AsyncLoader.h ├── AsyncLoader.i ├── GenLoader.py ├── GenerateC.bat └── emake.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AsyncNet 2 | ======== 3 | 4 | AsyncNet 5 | 6 | 7 | Build 8 | ===== 9 | 10 | ```bash 11 | # git clone https://github.com/skywind3000/AsyncNet.git AsyncNet 12 | # cd AsyncNet 13 | # python tools/emake.py build/AsyncNet.mak 14 | ``` 15 | 16 | Demo 17 | ==== 18 | 19 | ```bash 20 | python AsyncNet.py 21 | ``` 22 | 23 | check test_async_core() and test_async_notify() in AsyncNet.py for more. 24 | 25 | C/C++ Library 26 | =========== 27 | 28 | use tools/AsyncLoader.h tools/AsyncLoader.c in your code. 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /build/AsyncNet.mak: -------------------------------------------------------------------------------- 1 | mode: dll 2 | flag: -O3, -Wall 3 | link: stdc++ 4 | int: ../build/objs/$(target) 5 | linux/link: rt, pthread 6 | darwin/link: pthread 7 | 8 | win32/flag: -s 9 | unix/flag: -g 10 | 11 | out: ../AsyncNet.$(target) 12 | 13 | src: ../source/AsyncExport.cpp 14 | src: ../source/TraceLog.cpp 15 | 16 | src: ../system/imembase.c 17 | src: ../system/imemdata.c 18 | src: ../system/inetbase.c 19 | src: ../system/inetcode.c 20 | src: ../system/inetkcp.c 21 | src: ../system/inetnot.c 22 | src: ../system/iposix.c 23 | src: ../system/itoolbox.c 24 | src: ../system/ineturl.c 25 | src: ../system/isecure.c 26 | 27 | src: 28 | color: 13 29 | echo: ___ _ __ __ 30 | echo: / | _______ ______ _____ / | / /__ / /_ 31 | echo: / /| | / ___/ / / / __ \/ ___/ / |/ / _ \/ __/ 32 | echo: / ___ |(__ ) /_/ / / / / /__ / /| / __/ /_ 33 | echo: /_/ |_/____/\__, /_/ /_/\___/ /_/ |_/\___/\__/ 34 | echo: /____/ 35 | color: -1 36 | 37 | 38 | -------------------------------------------------------------------------------- /build/AsyncNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AsyncNet", "AsyncNet.vcxproj", "{C90CE71D-814A-49BD-A668-051373DEB430}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C90CE71D-814A-49BD-A668-051373DEB430}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {C90CE71D-814A-49BD-A668-051373DEB430}.Debug|Win32.Build.0 = Debug|Win32 14 | {C90CE71D-814A-49BD-A668-051373DEB430}.Release|Win32.ActiveCfg = Release|Win32 15 | {C90CE71D-814A-49BD-A668-051373DEB430}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /build/AsyncNet.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {C90CE71D-814A-49BD-A668-051373DEB430} 15 | Win32Proj 16 | AsyncNet 17 | 18 | 19 | 20 | DynamicLibrary 21 | true 22 | Unicode 23 | v143 24 | 25 | 26 | DynamicLibrary 27 | false 28 | true 29 | Unicode 30 | v143 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | $(SolutionDir)$(Configuration)\ 45 | $(ProjectName)_d 46 | .win32 47 | 48 | 49 | false 50 | $(SolutionDir)$(Configuration)\ 51 | .win32 52 | 53 | 54 | 55 | 56 | 57 | Level3 58 | Disabled 59 | WIN32;_DEBUG;_WINDOWS;_USRDLL;ASYNCNET_EXPORTS;%(PreprocessorDefinitions) 60 | 61 | 62 | Windows 63 | true 64 | 65 | 66 | copy $(SolutionDir)$(Configuration)\$(TargetFileName) ..\ 67 | 68 | 69 | copy files 70 | 71 | 72 | 73 | 74 | Level3 75 | 76 | 77 | MaxSpeed 78 | true 79 | true 80 | WIN32;NDEBUG;_WINDOWS;_USRDLL;ASYNCNET_EXPORTS;%(PreprocessorDefinitions) 81 | 82 | 83 | Windows 84 | true 85 | true 86 | true 87 | 88 | 89 | copy $(SolutionDir)$(Configuration)\$(TargetFileName) ..\ 90 | copy files 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /build/AsyncNet.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 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 11 | 12 | 13 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 14 | h;hpp;hxx;hm;inl;inc;xsd 15 | 16 | 17 | 18 | 19 | system 20 | 21 | 22 | system 23 | 24 | 25 | system 26 | 27 | 28 | system 29 | 30 | 31 | system 32 | 33 | 34 | system 35 | 36 | 37 | system 38 | 39 | 40 | system 41 | 42 | 43 | system 44 | 45 | 46 | system 47 | 48 | 49 | system 50 | 51 | 52 | source 53 | 54 | 55 | source 56 | 57 | 58 | 59 | 60 | system 61 | 62 | 63 | system 64 | 65 | 66 | system 67 | 68 | 69 | system 70 | 71 | 72 | system 73 | 74 | 75 | system 76 | 77 | 78 | system 79 | 80 | 81 | system 82 | 83 | 84 | system 85 | 86 | 87 | system 88 | 89 | 90 | system 91 | 92 | 93 | system 94 | 95 | 96 | source 97 | 98 | 99 | source 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/IndexMap/IndexMap.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // IndexMap.h - 4 | // 5 | // Created by skywind on 2021/12/02 6 | // Last Modified: 2021/12/02 17:41:32 7 | // 8 | //===================================================================== 9 | #ifndef _INDEX_MAP_H_ 10 | #define _INDEX_MAP_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | 21 | //--------------------------------------------------------------------- 22 | // global definition 23 | //--------------------------------------------------------------------- 24 | #define INDEX_ID_SHIFT 8 25 | #define INDEX_ID_MASK ((1 << INDEX_ID_SHIFT) - 1) 26 | 27 | 28 | //--------------------------------------------------------------------- 29 | // state 30 | //--------------------------------------------------------------------- 31 | enum NodeState { 32 | NS_FREE, 33 | NS_USED, 34 | }; 35 | 36 | 37 | //--------------------------------------------------------------------- 38 | // node 39 | //--------------------------------------------------------------------- 40 | struct IndexNode 41 | { 42 | NodeState state; 43 | void *obj; 44 | int32_t index; 45 | std::list::iterator it; 46 | }; 47 | 48 | 49 | //--------------------------------------------------------------------- 50 | // index map 51 | //--------------------------------------------------------------------- 52 | class IndexMap 53 | { 54 | public: 55 | inline IndexMap(); 56 | inline virtual ~IndexMap(); 57 | 58 | public: 59 | 60 | inline int32_t alloc(); 61 | 62 | inline void free(int32_t index); 63 | 64 | inline void* get(int32_t index); 65 | inline const void* get(int32_t index) const; 66 | 67 | inline void set(int32_t index, void *obj); 68 | inline bool contains(int32_t index); 69 | 70 | inline void* & operator[](int32_t index); 71 | inline const void* operator[](int32_t index) const; 72 | 73 | inline int capacity() const { return _capacity; } 74 | inline int num_used() const { return _num_used; } 75 | inline int num_free() const { return _num_free; } 76 | 77 | int32_t index_first() const; 78 | int32_t index_last() const; 79 | int32_t index_next(int32_t index) const; 80 | int32_t index_prev(int32_t index) const; 81 | 82 | private: 83 | inline int32_t index_to_version(int32_t index) const; 84 | inline int32_t index_to_id(int32_t index) const; 85 | inline const IndexNode *index_to_node(int32_t index) const; 86 | inline IndexNode *index_to_node(int32_t index); 87 | inline void grow(); 88 | 89 | private: 90 | int _capacity; 91 | int _num_used; 92 | int _num_free; 93 | IndexNode **_nodes; 94 | void *_dummy; 95 | std::vector _array; 96 | std::list _free_list; 97 | std::list _used_list; 98 | }; 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // implements 103 | //--------------------------------------------------------------------- 104 | 105 | // ctor 106 | inline IndexMap::IndexMap() { 107 | _capacity = 0; 108 | _num_used = 0; 109 | _num_free = 0; 110 | _dummy = NULL; 111 | _nodes = NULL; 112 | } 113 | 114 | // dtor 115 | inline IndexMap::~IndexMap() { 116 | for (int i = 0; i < _capacity; i++) { 117 | IndexNode *node = _array[i]; 118 | if (node->state == NS_FREE) { 119 | _free_list.erase(node->it); 120 | } else { 121 | _used_list.erase(node->it); 122 | } 123 | delete node; 124 | _array[i] = NULL; 125 | } 126 | _array.resize(0); 127 | _nodes = NULL; 128 | assert(_free_list.size() == 0); 129 | assert(_used_list.size() == 0); 130 | _capacity = 0; 131 | _num_used = 0; 132 | _num_free = 0; 133 | } 134 | 135 | inline int32_t IndexMap::index_to_version(int32_t index) const { 136 | return index & INDEX_ID_MASK; 137 | } 138 | 139 | inline int32_t IndexMap::index_to_id(int32_t index) const { 140 | return index >> INDEX_ID_SHIFT; 141 | } 142 | 143 | inline const IndexNode *IndexMap::index_to_node(int32_t index) const { 144 | int32_t id = index_to_id(index); 145 | if (id < 0 || id >= _capacity) return NULL; 146 | const IndexNode *node = _nodes[id]; 147 | if (node->index != index) return NULL; 148 | return node; 149 | } 150 | 151 | inline IndexNode *IndexMap::index_to_node(int32_t index) { 152 | const IndexNode *node = 153 | static_cast(*this).index_to_node(index); 154 | return const_cast(node); 155 | } 156 | 157 | // grow 158 | inline void IndexMap::grow() { 159 | int newcap = (_capacity < 8)? 8 : _capacity * 2; 160 | _array.resize(newcap); 161 | _nodes = &_array[0]; 162 | for (int i = _capacity; i < newcap; i++) { 163 | IndexNode *node = new IndexNode; 164 | _array[i] = node; 165 | node->state = NS_FREE; 166 | node->index = i << INDEX_ID_SHIFT; 167 | node->obj = NULL; 168 | _free_list.push_back(node); 169 | node->it = _free_list.end(); 170 | node->it--; 171 | assert(*(node->it) == node); 172 | _num_free++; 173 | } 174 | _capacity = newcap; 175 | } 176 | 177 | 178 | // alloc 179 | int32_t IndexMap::alloc() { 180 | if (num_free() == 0) { 181 | grow(); 182 | } 183 | if (num_used() * 2 >= _capacity) { 184 | grow(); 185 | } 186 | assert(_num_free > 0); 187 | std::list::iterator it = _free_list.begin(); 188 | IndexNode *node = *it; 189 | _free_list.erase(it); 190 | _used_list.push_back(node); 191 | node->it = _used_list.end(); 192 | node->it--; 193 | assert(*(node->it) == node); 194 | node->state = NS_USED; 195 | node->obj = NULL; 196 | _num_used++; 197 | _num_free--; 198 | int32_t version = index_to_version(node->index); 199 | int32_t id = index_to_id(node->index); 200 | version = (version + 1) & INDEX_ID_MASK; 201 | node->index = (id << INDEX_ID_SHIFT) | version; 202 | return node->index; 203 | } 204 | 205 | 206 | inline void IndexMap::free(int32_t index) 207 | { 208 | IndexNode *node = index_to_node(index); 209 | if (node == NULL) { 210 | assert(node); 211 | return; 212 | } 213 | if (node->state != NS_USED) { 214 | assert(node->state == NS_USED); 215 | return; 216 | } 217 | _used_list.erase(node->it); 218 | _free_list.push_back(node); 219 | node->it = _free_list.end(); 220 | node->it--; 221 | assert(*(node->it) == node); 222 | _num_used--; 223 | _num_free++; 224 | node->state = NS_FREE; 225 | node->obj = NULL; 226 | } 227 | 228 | int32_t IndexMap::index_first() const { 229 | std::list::const_iterator it = _used_list.begin(); 230 | if (it == _used_list.end()) return -1; 231 | return (*it)->index; 232 | } 233 | 234 | int32_t IndexMap::index_last() const { 235 | std::list::const_iterator it = _used_list.end(); 236 | if (it == _used_list.begin()) return -1; 237 | it--; 238 | return (*it)->index; 239 | } 240 | 241 | int32_t IndexMap::index_next(int32_t index) const { 242 | const IndexNode *node = index_to_node(index); 243 | if (node == NULL) return -1; 244 | if (node->state != NS_USED) return -1; 245 | std::list::const_iterator it = node->it; 246 | it++; 247 | if (it == _used_list.end()) return -1; 248 | return (*it)->index; 249 | } 250 | 251 | int32_t IndexMap::index_prev(int32_t index) const { 252 | const IndexNode *node = index_to_node(index); 253 | if (node == NULL) return -1; 254 | if (node->state != NS_USED) return -1; 255 | std::list::const_iterator it = node->it; 256 | if (it == _used_list.begin()) return -1; 257 | it--; 258 | return (*it)->index; 259 | } 260 | 261 | 262 | inline void* IndexMap::get(int32_t index) { 263 | const void *obj = static_cast(*this).get(index); 264 | return const_cast(obj); 265 | } 266 | 267 | inline const void* IndexMap::get(int32_t index) const { 268 | const IndexNode *node = index_to_node(index); 269 | if (node == NULL) { 270 | assert(node); 271 | return NULL; 272 | } 273 | return node->obj; 274 | } 275 | 276 | inline void IndexMap::set(int32_t index, void *obj) { 277 | IndexNode *node = index_to_node(index); 278 | if (node == NULL) { 279 | assert(node); 280 | return; 281 | } 282 | node->obj = obj; 283 | } 284 | 285 | inline bool IndexMap::contains(int32_t index) { 286 | IndexNode *node = index_to_node(index); 287 | return (node != NULL)? true : false; 288 | } 289 | 290 | inline void* & IndexMap::operator[](int32_t index) { 291 | IndexNode *node = index_to_node(index); 292 | if (node == NULL) { 293 | assert(node != NULL); 294 | return _dummy; 295 | } 296 | return node->obj; 297 | } 298 | 299 | inline const void* IndexMap::operator[](int32_t index) const { 300 | const IndexNode *node = index_to_node(index); 301 | if (node == NULL) { 302 | assert(node); 303 | return _dummy; 304 | } 305 | return node->obj; 306 | } 307 | 308 | 309 | //--------------------------------------------------------------------- 310 | // 311 | //--------------------------------------------------------------------- 312 | 313 | 314 | #endif 315 | 316 | 317 | 318 | 319 | -------------------------------------------------------------------------------- /example/KernelTimer/CoreTimer.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // CoreTimer.cpp - 4 | // 5 | // Created by skywind on 2021/12/01 6 | // Last Modified: 2021/12/01 17:44:14 7 | // 8 | //===================================================================== 9 | 10 | #include 11 | #include 12 | 13 | #include "CoreTimer.h" 14 | 15 | 16 | //--------------------------------------------------------------------- 17 | // ctor 18 | //--------------------------------------------------------------------- 19 | Timer::Timer(Scheduler *sched) 20 | { 21 | _sched = sched; 22 | callback = NULL; 23 | user = NULL; 24 | timestamp = 0; 25 | itimer_evt_init(&_evt, evt_callback, this, NULL); 26 | } 27 | 28 | 29 | //--------------------------------------------------------------------- 30 | // dtor 31 | //--------------------------------------------------------------------- 32 | Timer::~Timer() 33 | { 34 | stop(); 35 | user = NULL; 36 | callback = NULL; 37 | _sched = NULL; 38 | } 39 | 40 | 41 | //--------------------------------------------------------------------- 42 | // callback 43 | //--------------------------------------------------------------------- 44 | void Timer::evt_callback(void *obj, void *user) 45 | { 46 | Timer *self = (Timer*)obj; 47 | if (self->callback) { 48 | if (self->_sched) { 49 | // 更新标准时间戳 50 | self->timestamp = self->_sched->_mgr.current; 51 | } 52 | self->callback(self); 53 | } 54 | } 55 | 56 | 57 | //--------------------------------------------------------------------- 58 | // start timer 59 | //--------------------------------------------------------------------- 60 | bool Timer::start(uint32_t period, int repeat) 61 | { 62 | assert(_sched != NULL); 63 | if (_sched == NULL) { 64 | return false; 65 | } 66 | itimer_evt_start(&(_sched->_mgr), &_evt, period, repeat); 67 | return true; 68 | } 69 | 70 | 71 | //--------------------------------------------------------------------- 72 | // stop timer 73 | //--------------------------------------------------------------------- 74 | void Timer::stop() 75 | { 76 | assert(_sched != NULL); 77 | itimer_evt_stop(&(_sched->_mgr), &_evt); 78 | } 79 | 80 | 81 | //--------------------------------------------------------------------- 82 | // check is running 83 | //--------------------------------------------------------------------- 84 | bool Timer::is_running() const 85 | { 86 | if (_sched) { 87 | return itimer_evt_status(&_evt)? true : false; 88 | } 89 | return false; 90 | } 91 | 92 | 93 | //--------------------------------------------------------------------- 94 | // 返回还剩多少次调用 95 | //--------------------------------------------------------------------- 96 | int Timer::remain() const 97 | { 98 | return _evt.repeat; 99 | } 100 | 101 | 102 | //--------------------------------------------------------------------- 103 | // ctor 104 | //--------------------------------------------------------------------- 105 | Scheduler::Scheduler(uint32_t interval) 106 | { 107 | itimer_mgr_init(&_mgr, interval); 108 | _interval = interval; 109 | } 110 | 111 | 112 | //--------------------------------------------------------------------- 113 | // dtor 114 | //--------------------------------------------------------------------- 115 | Scheduler::~Scheduler() 116 | { 117 | itimer_mgr_destroy(&_mgr); 118 | } 119 | 120 | 121 | //--------------------------------------------------------------------- 122 | // update timers 123 | //--------------------------------------------------------------------- 124 | void Scheduler::update(uint32_t current) 125 | { 126 | itimer_mgr_run(&_mgr, current); 127 | } 128 | 129 | 130 | //--------------------------------------------------------------------- 131 | // 132 | //--------------------------------------------------------------------- 133 | void Scheduler::reset() 134 | { 135 | itimer_mgr_destroy(&_mgr); 136 | itimer_mgr_init(&_mgr, _interval); 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /example/KernelTimer/CoreTimer.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // CoreTimer.h - 4 | // 5 | // Created by skywind on 2021/12/01 6 | // Last Modified: 2021/12/01 17:44:07 7 | // 8 | //===================================================================== 9 | #ifndef _CORE_TIMER_H_ 10 | #define _CORE_TIMER_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "../../system/itimer.h" 18 | 19 | 20 | //--------------------------------------------------------------------- 21 | // Declaration 22 | //--------------------------------------------------------------------- 23 | class Scheduler; // 时钟管理器,管理 itimer_mgr; 24 | class Timer; // 封装 itimer_evt 25 | 26 | 27 | //--------------------------------------------------------------------- 28 | // Timer - 封装 itimer_evt,要点是独立操作 start/stop 以及析构时 stop 29 | // 每个 Entity/Node 之类的对象内都会有多个本地的 timer 实例,那么析构 30 | // 时需要确保调用 stop 移除 itimer_mgr 的调度队列。 31 | //--------------------------------------------------------------------- 32 | class Timer 33 | { 34 | public: 35 | virtual ~Timer(); 36 | Timer(Scheduler *sched); 37 | 38 | public: 39 | 40 | // 之所以把 start/stop 之类的操作放在具体的 timer 里,是因为 41 | // 启停操作相对频繁,使用时无需频繁引用 scheduler。 42 | // Timer 会作为参数传递到 callback 里,callback 操作停止之类的 43 | // 直接操作就行了,不用再去引用 scheduler. 44 | bool start(uint32_t period, int repeat = 0); 45 | 46 | void stop(); 47 | 48 | bool is_running() const; 49 | 50 | // 返回 repeat 调用时还剩多少次调用,0 的话证明最后一次, 51 | // 如果是 -1 的话,代表无限循环,方便 callback 中检查是否是 52 | // 最后一次调用。 53 | int remain() const; 54 | 55 | public: 56 | // 回调函数定义 57 | typedef std::function OnTimer; 58 | 59 | OnTimer callback; // 时钟回调函数,需要设置 60 | uint32_t timestamp; // 标准时间戳,内部工作用的 61 | void *user; // 用户随意设置的指针 62 | 63 | protected: 64 | static void evt_callback(void *obj, void *user); 65 | 66 | protected: 67 | Scheduler *_sched; 68 | itimer_evt _evt; 69 | }; 70 | 71 | 72 | //--------------------------------------------------------------------- 73 | // Scheduler 74 | //--------------------------------------------------------------------- 75 | class Scheduler 76 | { 77 | public: 78 | virtual ~Scheduler(); 79 | Scheduler(uint32_t interval = 5); 80 | 81 | public: 82 | 83 | void update(uint32_t current); 84 | 85 | void reset(); 86 | 87 | private: 88 | friend Timer; 89 | uint32_t _interval; 90 | itimer_mgr _mgr; 91 | }; 92 | 93 | 94 | 95 | #endif 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /example/KernelTimer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../../system/itimer.c" 6 | #include "CoreTimer.cpp" 7 | 8 | Scheduler sched(1); 9 | 10 | class Node 11 | { 12 | public: 13 | Node(): timer_ping(&sched) { 14 | 15 | // 第一种写法 std::function 调用成员函数 16 | timer_ping.callback = [this](Timer *timer) { 17 | on_timer(timer); 18 | }; 19 | 20 | // 第二种写法 std::function 直接指向成员函数 21 | timer_ping.callback = std::bind(&Node::on_timer, this, std::placeholders::_1); 22 | 23 | timer_ping.start(1000, 5); 24 | } 25 | 26 | void on_timer(Timer *timer) { 27 | printf("ping remain: %d ts: %d\n", timer->remain(), timer->timestamp); 28 | } 29 | 30 | private: 31 | Timer timer_ping; 32 | }; 33 | 34 | 35 | int main() 36 | { 37 | Node node; 38 | while (1) { 39 | Sleep(10); 40 | sched.update(timeGetTime()); 41 | } 42 | return 0; 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /source/AsyncEvt.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncEvt.h - Asynchronous Event Loop and Event Handling 4 | // Last Modified: 2025/07/03 17:23:57 5 | // 6 | // 本文件是对 (system/inetevt.h) 异步消息库的 C++ 封装: 7 | // 8 | // - 使用 RAII 管理事件对象,在析构时能正确的从消息循环注销自己。 9 | // - 使用 std::function / lambda 代替 C 回调,用起来更紧凑和简单。 10 | // - 妥善管理回调生命周期,支持回调里删除对象自己。 11 | // 12 | // 在 AsyncLoop 这个消息分发器的基础上(类似 libevent 的 event_base) 13 | // 提供了下面几个最核心的异步事件原语: 14 | // 15 | // - AsyncEvent:用于 socket/fd 的 I/O 消息:ASYNC_EVENT_READ/WRITE 16 | // - AsyncTimer:使用类 Linux 时间轮实现的高性能时钟消息 17 | // - AsyncSemaphore:用于从其他线程唤醒 AsyncLoop::RunOnce 的信号量 18 | // - AsyncPostpone:在 AsyncLoop::RunOnce 结束前安排一次稍后运行的任务 19 | // - AsyncOnce:每次在 AsyncLoop::RunOnce 结束前都会运行的事件 20 | // - AsyncIdle:在消息循环空闲的时候调用的事件 21 | // 22 | // 这几个事件基本上是一个最小化异步事件库的必备功能了,任何复杂的业务 23 | // 都可以用上面几个事件组合完成,比如 AsyncKit.h 里面的高级功能。 24 | // 25 | //===================================================================== 26 | #ifndef _ASYNC_EVT_H_ 27 | #define _ASYNC_EVT_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "../system/inetevt.h" 37 | #include "../system/system.h" 38 | 39 | 40 | 41 | NAMESPACE_BEGIN(System); 42 | 43 | //--------------------------------------------------------------------- 44 | // AsyncLoop - 消息循环(消息分发器) 45 | // 消息循环类的核心功能就是 RunOnce,调用一次会处理一轮消息循环: 46 | // 47 | // - 首先等待事件,就是用 select/poll/epoll_wait 之类接口等待 I/O 事件 48 | // - 分发所有捕获到的 I/O 事件(AsyncEvent) 49 | // - 分发所有到期的时钟事件(AsyncTimer) 50 | // - 分发所有延期事件(AsyncPostpone)和信号量(AsyncSemaphore) 51 | // - 如果上面没有任何消息被分发,则调度一次 AsyncIdle 事件 52 | // - 结束前分发所有注册过的 AsyncOnce 事件 53 | // 54 | // 而 AsyncLoop 里的 RunEndless 接口就是不停的调用 RunOnce,直到 Exit 55 | // 标志被设置(AsyncLoop::Exit)。 56 | //--------------------------------------------------------------------- 57 | class AsyncLoop 58 | { 59 | public: 60 | virtual ~AsyncLoop(); 61 | AsyncLoop(); 62 | AsyncLoop(CAsyncLoop *loop); 63 | AsyncLoop(AsyncLoop &&src); 64 | 65 | AsyncLoop(const AsyncLoop &) = delete; 66 | AsyncLoop& operator=(const AsyncLoop &) = delete; 67 | 68 | public: 69 | 70 | // 取得内部 C 对象指针,即 CAsyncLoop 这个 inetevt.h 里的结构体 71 | inline CAsyncLoop *GetLoop() { return _loop; } 72 | inline const CAsyncLoop *GetLoop() const { return _loop; } 73 | 74 | // 取得默认消息循环对象(线程本地变量,每个线程一个独立实例) 75 | static AsyncLoop& GetDefaultLoop(); 76 | 77 | // 取得一个假对象,该对象 IsDummy() 接口会返回 true。 78 | static AsyncLoop& GetDummyLoop(); 79 | 80 | // 判断是不是 Dummy 对象,即由上面 GetDummyLoop() 返回的实例 81 | // 这个 Dummy 功能是方便 C++ 某些特性设置的,在 inetevt.h 的 82 | // C 接口里并没有对应概念 83 | bool IsDummy() const; 84 | 85 | // 运行一次迭代(iteration),即调用一次 epoll_wait 捕获所有被激活 86 | // 的事件并进行分发,参数 millisec 是等待时间 87 | void RunOnce(uint32_t millisec = 10); 88 | 89 | // 不停的调用 RunOnce 直到退出标志被设置 90 | void RunEndless(); 91 | 92 | // 通知 RunEndless() 退出 93 | void Exit(); 94 | 95 | // 设置 RunEndless 里调用 RunOnce 时传入的等待时间,如果开启 96 | // Tickless 模式,则 interval 失效,采取动态计算等待时间 97 | void SetInterval(int millisec); 98 | 99 | // 是否开启无 tick 模式 100 | void SetTickless(bool enabled); 101 | 102 | // 写日志 103 | void Log(int channel, const char *fmt, ...); 104 | 105 | // 设置日志掩码,当前掩码和 Log(channel, ...) 里的 channel 做 and 运算 106 | // 不为零时才会真的打印该日志 107 | void SetLogMask(int mask); 108 | 109 | // 检查日志掩码是否被设置,用于某些高频调用代码,提前判断是否需要输出 110 | // 日志,不输出的话就跳过,只有需要输出时才回去具体调用 Log 接口,处理 111 | // 各种日志文本和参数 112 | inline bool CheckLogMask(int channel) const { 113 | return ((_loop->logmask & channel) != 0); 114 | } 115 | 116 | // 取得时间戳,该时间戳在每次 RunOnce 里的 epoll_wait 结束后更新,因为 117 | // 取时钟系统调用成本太高,用不着每次都调用,这里提供一个统一值,免得 118 | // 程序其他地方重复进行系统调用,参数 monotonic 为 false 时返回实时时钟 119 | // 这个实时时钟就是对应真实世界里的时钟,会被修改系统时间影响到,也不连续 120 | // 休眠再唤醒会出现跳变;而如果把 monotonic 设置成 true 时返回单调递增 121 | // 时钟,不会受休眠,系统时间修改等因素影响。 122 | int64_t Timestamp(bool monotonic) const { 123 | return monotonic? _loop->monotonic : _loop->timestamp; 124 | } 125 | 126 | // 取得当前的 jiffies 计时,每毫秒递增 1,用于驱动内部的 Linux 时间轮 127 | uint32_t Jiffies() const { return _loop->jiffies; } 128 | 129 | // 取得迭代次数,即一共运行了多少次 RunOnce 函数 130 | int64_t GetIteration() const { return _loop->iteration; } 131 | 132 | // 设置日志接口 133 | void SetLogHandler(std::function handler); 134 | 135 | // 设置一个函数,该函数每次调用 RunOnce(每轮迭代)末尾会被调用。 136 | void SetOnceHandler(std::function handler); 137 | 138 | // 设置一个函数,每次循环空闲时会被调用(RunOnce 一次没事情时) 139 | void SetIdleHandler(std::function handler); 140 | 141 | // 设置一个函数,每次 jiffies 改变时被调用(即毫秒更新) 142 | void SetTimerHandler(std::function handler); 143 | 144 | // inline ptr helper 145 | inline const void *Ptr() const { return _ptr; } 146 | inline void *Ptr() { return _ptr; } 147 | inline void Ptr(void *ptr) { _ptr = ptr; } 148 | 149 | 150 | private: 151 | std::function _cb_log; 152 | std::function _cb_idle; 153 | std::function _cb_once; 154 | std::function _cb_timer; 155 | 156 | std::string _log_cache; 157 | void *_ptr = NULL; 158 | 159 | static void OnLog(void *logger, const char *text); 160 | static void OnOnce(CAsyncLoop *loop); 161 | static void OnTimer(CAsyncLoop *loop); 162 | static void OnIdle(CAsyncLoop *loop); 163 | 164 | protected: 165 | CAsyncLoop *_loop = NULL; 166 | bool _borrow = false; 167 | }; 168 | 169 | 170 | 171 | //--------------------------------------------------------------------- 172 | // AsyncEvent - 文件和 socket 的 I/O 事件 173 | // 可以针对一个 fd 捕获 ASYNC_EVENT_READ / ASYNC_EVENT_WRITE 两种事件 174 | // 构造时传如 AsyncLoop 的实例,构造完后先 SetCallback 设置回调, 175 | // 然后 Set 函数设置要捕获的 fd 和事件,然后 Start 开始监听,完了以后 176 | // 用 Stop 停止监听。 177 | //--------------------------------------------------------------------- 178 | class AsyncEvent final 179 | { 180 | public: 181 | ~AsyncEvent(); 182 | 183 | AsyncEvent(CAsyncLoop *loop); 184 | AsyncEvent(AsyncLoop &loop); 185 | 186 | AsyncEvent(AsyncEvent &&src) = delete; 187 | AsyncEvent(const AsyncEvent &) = delete; 188 | AsyncEvent& operator=(const AsyncEvent &) = delete; 189 | 190 | public: 191 | 192 | // 设置回调,该回调接受一个参数,就是捕获到的事件,该参数可能的值为: 193 | // ASYNC_EVENT_READ 或者 ASYNC_EVENT_WRITE 或者二者的或运算(都发生) 194 | void SetCallback(std::function callback); 195 | 196 | // 设置要捕获的事件:fd 为文件句柄或者套接字,mask 是要捕获的事件, 197 | // 可能的值有三个:ASYNC_EVENT_READ, ASYNC_EVENT_WRITE 或者 198 | // 二者的或运算(ASYNC_EVENT_READ | ASYNC_EVENT_WRITE) 199 | // 必须在未激活时调用(调用 Start 之前,或者 Stop 之后) 200 | bool Set(int fd, int mask); 201 | 202 | // 只修改事件掩码,不修改 fd,实际上是用老的 fd 调用前面的 Set 函数 203 | bool Modify(int mask); 204 | 205 | // 开始捕获事件,将自己注册到 AsyncLoop 消息循环 206 | int Start(); 207 | 208 | // 停止捕获事件,将自己从 AsyncLoop 那里注销掉 209 | int Stop(); 210 | 211 | // 是否正在捕获事件,active 的意思是是否调用了 Start 将自己注册到 Loop 了 212 | inline bool IsActive() const { return async_event_is_active(&_event); } 213 | 214 | // 取得底层事件对象 215 | const CAsyncEvent *GetEvent() const { return &_event; } 216 | CAsyncEvent *GetEvent() { return &_event; } 217 | 218 | private: 219 | static void EventCB(CAsyncLoop *loop, CAsyncEvent *evt, int event); 220 | 221 | private: 222 | typedef std::function Callback; 223 | std::shared_ptr _cb_ptr = std::make_shared(); 224 | 225 | CAsyncLoop *_loop = NULL; 226 | CAsyncEvent _event; 227 | }; 228 | 229 | 230 | //--------------------------------------------------------------------- 231 | // AsyncTimer - 高性能时钟事件,可以 O(1) 的复杂度调度成千上万的时钟 232 | //--------------------------------------------------------------------- 233 | class AsyncTimer final 234 | { 235 | public: 236 | ~AsyncTimer(); 237 | AsyncTimer(AsyncLoop &loop); 238 | AsyncTimer(CAsyncLoop *loop); 239 | 240 | AsyncTimer(AsyncTimer &&src) = delete; 241 | AsyncTimer(const AsyncTimer &) = delete; 242 | AsyncTimer& operator=(const AsyncTimer &) = delete; 243 | 244 | public: 245 | 246 | // 设置回调 247 | void SetCallback(std::function callback); 248 | 249 | // 开启时钟,period 是间隔时间,单位是毫秒, 250 | // repeat 是重复次数,0 表示无限次,1 表示只执行一次 251 | int Start(uint32_t period, int repeat); 252 | 253 | // 停止时钟 254 | int Stop(); 255 | 256 | // 检测时钟是否正在运行 257 | inline bool IsActive() const { return async_timer_is_active(&_timer); } 258 | 259 | private: 260 | static void TimerCB(CAsyncLoop *loop, CAsyncTimer *timer); 261 | 262 | private: 263 | typedef std::function Callback; 264 | std::shared_ptr _cb_ptr = std::make_shared(); 265 | 266 | CAsyncLoop *_loop = NULL; 267 | CAsyncTimer _timer; 268 | }; 269 | 270 | 271 | //--------------------------------------------------------------------- 272 | // AsyncSemaphore - 信号量,用于多线程协同,如果另一个线程调用了该对象 273 | // 的 Post() 函数,则正在等待消息的 AsyncLoop::RunOnce 会被唤醒,该对 274 | // 象的回调函数会被调用(在被唤醒的 RunOnce 函数里调用)。 275 | //--------------------------------------------------------------------- 276 | class AsyncSemaphore final 277 | { 278 | public: 279 | ~AsyncSemaphore(); 280 | AsyncSemaphore(AsyncLoop &loop); 281 | AsyncSemaphore(CAsyncLoop *loop); 282 | 283 | AsyncSemaphore(AsyncSemaphore &&src) = delete; 284 | AsyncSemaphore(const AsyncSemaphore &) = delete; 285 | AsyncSemaphore& operator=(const AsyncSemaphore &) = delete; 286 | 287 | public: 288 | 289 | // 设置回调函数,该函数会在 Post() 被调用时在 RunOnce 内被执行 290 | void SetCallback(std::function callback); 291 | 292 | // 开始监听信号量,等待其他线程调用 Post() 函数 293 | int Start(); 294 | 295 | // 停止监听信号量,取消等待其他线程调用 Post() 函数 296 | int Stop(); 297 | 298 | // 向信号量发送一个消息,一般从其它线程调用。 299 | int Post(); 300 | 301 | // 检查信号量是否正在等待消息 302 | inline bool IsActive() const { return async_sem_is_active(&_sem); } 303 | 304 | private: 305 | 306 | static void NotifyCB(CAsyncLoop *loop, CAsyncSemaphore *msg); 307 | 308 | private: 309 | typedef std::function Callback; 310 | std::shared_ptr _cb_ptr = std::make_shared(); 311 | 312 | CAsyncLoop *_loop = NULL; 313 | CAsyncSemaphore _sem; 314 | }; 315 | 316 | 317 | 318 | //--------------------------------------------------------------------- 319 | // AsyncPostpone - 延期事件,将一个事件安排在本轮事件循环结束前执行, 320 | // 就是说它会在本次 RunOnce 结束前被调用,通常用于在 RunOnce 结束前安 321 | // 排一些需要在当前事件循环结束前执行的任务,比如不方便在当前事件回调 322 | // 里处理的东西像删除对象之类的,可以安排在这一轮事件循环结束前执行, 323 | // 避免潜在问题;又或者你多次向网络缓存里写了数据,需要稍后 Flush 一 324 | // 下缓存,放到 timer 里稍行执行会增加延迟,每次写了数据立即 Flush 又 325 | // 会影响性能,那么用 AsyncPostpone 就可以在 RunOnce 前安排一次 Flush 326 | // 操作,保证数据被发送出去,但又不会增加延迟。注意 Start 后回调只有 327 | // 一次就会自动 Stop 掉。 328 | //--------------------------------------------------------------------- 329 | class AsyncPostpone final 330 | { 331 | public: 332 | ~AsyncPostpone(); 333 | AsyncPostpone(AsyncLoop &loop); 334 | AsyncPostpone(CAsyncLoop *loop); 335 | 336 | AsyncPostpone(AsyncPostpone &&src) = delete; 337 | AsyncPostpone(const AsyncPostpone &) = delete; 338 | AsyncPostpone& operator=(AsyncPostpone &src) = delete; 339 | 340 | public: 341 | 342 | // 设置回调 343 | void SetCallback(std::function callback); 344 | 345 | // 开启延期事件,安排在当前 RunOnce 结束前执行,只执行一次,完了自动 Stop 346 | int Start(); 347 | 348 | // 停止延期事件,如果还没执行完则取消掉 349 | int Stop(); 350 | 351 | // 检查延期事件是否正在等待执行,即 Start 之后和 Stop 之前的状态 352 | inline bool IsActive() const { return async_post_is_active(&_postpone); } 353 | 354 | 355 | private: 356 | static void InternalCB(CAsyncLoop *loop, CAsyncPostpone *postpone); 357 | 358 | typedef std::function Callback; 359 | std::shared_ptr _cb_ptr = std::make_shared(); 360 | 361 | CAsyncLoop *_loop = NULL; 362 | 363 | CAsyncPostpone _postpone; 364 | }; 365 | 366 | 367 | //--------------------------------------------------------------------- 368 | // AsyncIdle - 空闲事件,在一轮消息循环中没有任何事件被分发时会被调用, 369 | // 也就是 RunOnce 一次没有任何事件被捕获和分发时,结束前会调用该事件。 370 | //--------------------------------------------------------------------- 371 | class AsyncIdle final 372 | { 373 | public: 374 | ~AsyncIdle(); 375 | AsyncIdle(AsyncLoop &loop); 376 | AsyncIdle(CAsyncLoop *loop); 377 | 378 | AsyncIdle(AsyncIdle &&src) = delete; 379 | AsyncIdle(const AsyncIdle &) = delete; 380 | AsyncIdle& operator=(AsyncIdle &src) = delete; 381 | 382 | public: 383 | 384 | // setup callback 385 | void SetCallback(std::function callback); 386 | 387 | // 开启事件,注册到 AsyncLoop 中 388 | int Start(); 389 | 390 | // 结束事件,从 AsyncLoop 中注销掉 391 | int Stop(); 392 | 393 | // is watching ? 394 | inline bool IsActive() const { return async_idle_is_active(&_idle); } 395 | 396 | 397 | private: 398 | static void InternalCB(CAsyncLoop *loop, CAsyncIdle *idle); 399 | 400 | typedef std::function Callback; 401 | std::shared_ptr _cb_ptr = std::make_shared(); 402 | 403 | CAsyncLoop *_loop = NULL; 404 | CAsyncIdle _idle; 405 | }; 406 | 407 | 408 | //--------------------------------------------------------------------- 409 | // AsyncOnce - 每次 RunOnce 结束前都会被调用的事件,用于每轮消息循环处 410 | // 理完后安排执行一些事情,注意这个 once 的意思不是调用一次,而是每次 411 | // RunOnce 结束前都会被调用。 412 | //--------------------------------------------------------------------- 413 | class AsyncOnce final 414 | { 415 | public: 416 | ~AsyncOnce(); 417 | AsyncOnce(AsyncLoop &loop); 418 | AsyncOnce(CAsyncLoop *loop); 419 | 420 | AsyncOnce(AsyncOnce &&src) = delete; 421 | AsyncOnce(const AsyncOnce &) = delete; 422 | AsyncOnce& operator=(AsyncOnce &src) = delete; 423 | 424 | public: 425 | 426 | // setup callback 427 | void SetCallback(std::function callback); 428 | 429 | // start watching 430 | int Start(); 431 | 432 | // stop watching 433 | int Stop(); 434 | 435 | // is watching ? 436 | inline bool IsActive() const { return async_once_is_active(&_once); } 437 | 438 | // set priority: ASYNC_ONCE_HIGH/NORMAL/LOW 439 | int SetPriority(int priority); 440 | 441 | private: 442 | static void InternalCB(CAsyncLoop *loop, CAsyncOnce *idle); 443 | 444 | typedef std::function Callback; 445 | std::shared_ptr _cb_ptr = std::make_shared(); 446 | 447 | CAsyncLoop *_loop = NULL; 448 | CAsyncOnce _once; 449 | }; 450 | 451 | 452 | 453 | NAMESPACE_END(System); 454 | 455 | 456 | 457 | #endif 458 | -------------------------------------------------------------------------------- /source/AsyncExport.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // ___ _ __ __ 3 | // / | _______ ______ _____ / | / /__ / /_ 4 | // / /| | / ___/ / / / __ \/ ___/ / |/ / _ \/ __/ 5 | // / ___ |(__ ) /_/ / / / / /__ / /| / __/ /_ 6 | // /_/ |_/____/\__, /_/ /_/\___/ /_/ |_/\___/\__/ 7 | // /____/ 8 | // 9 | // AsyncNet.h - AsyncNet 网络接口 10 | // 11 | // NOTE: 12 | // for more information, please see the readme file. 13 | // 14 | //===================================================================== 15 | #ifndef __ASYNCNET_H__ 16 | #define __ASYNCNET_H__ 17 | 18 | // No interface will be exported if ASYNCNET_INTERNAL defined 19 | #ifdef ASYNCNET_INTERNAL 20 | #define ANETAPI 21 | #elif defined(_WIN32) || defined(WIN32) || defined(WIN64) || defined(_WIN64) 22 | #ifndef ASYNCNET_EXPORT 23 | #define ANETAPI __declspec( dllimport ) 24 | #ifdef __cplusplus 25 | #define ANETAPI_CPLUS extern "C" __declspec( dllimport ) 26 | #else 27 | #define ANETAPI_CPLUS __declspec( dllimport ) 28 | #endif 29 | #else 30 | #define ANETAPI __declspec( dllexport ) 31 | #ifdef __cplusplus 32 | #define ANETAPI_CPLUS extern "C" __declspec( dllexport ) 33 | #else 34 | #define ANETAPI_CPLUS __declspec( dllexport ) 35 | #endif 36 | #endif 37 | #else 38 | #define ANETAPI 39 | #ifdef __cplusplus 40 | #define ANETAPI_CPLUS extern "C" 41 | #else 42 | #define ANETAPI_CPLUS 43 | #endif 44 | #endif 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | 51 | //===================================================================== 52 | // AsyncCore 53 | //===================================================================== 54 | #define ASYNCCORE_EVT_NEW 0 // new: (hid, tag) 55 | #define ASYNCCORE_EVT_LEAVE 1 // leave: (hid, tag) 56 | #define ASYNCCORE_EVT_ESTAB 2 // estab: (hid, tag) 57 | #define ASYNCCORE_EVT_DATA 3 // data: (hid, tag) 58 | 59 | #define ASYNCCORE_NODE_IN 1 // accepted node 60 | #define ASYNCCORE_NODE_OUT 2 // connected out node 61 | #define ASYNCCORE_NODE_LISTEN4 3 // ipv4 listener 62 | #define ASYNCCORE_NODE_LISTEN6 4 // ipv6 listener 63 | 64 | // AsyncCore Definition 65 | typedef void AsyncCore; 66 | 67 | // Remote IP Validator: returns 1 to accept it, 0 to reject 68 | typedef int (*AsyncValidator)(const void *remote, int len, 69 | AsyncCore *core, long listenhid, void *user); 70 | 71 | // new AsyncCore object 72 | ANETAPI AsyncCore* asn_core_new(void); 73 | 74 | // delete async core 75 | ANETAPI void asn_core_delete(AsyncCore *core); 76 | 77 | 78 | // wait for events for millisec ms. and process events, 79 | // if millisec equals zero, no wait. 80 | ANETAPI void asn_core_wait(AsyncCore *core, unsigned long millisec); 81 | 82 | // wake-up from asn_core_wait 83 | ANETAPI void asn_core_notify(AsyncCore *core); 84 | 85 | // read events, returns data length of the message, 86 | // and returns -1 for no event, -2 for buffer size too small, 87 | ANETAPI long asn_core_read(AsyncCore *core, int *event, long *wparam, 88 | long *lparam, void *data, long size); 89 | 90 | 91 | // send data to given hid 92 | ANETAPI long asn_core_send(AsyncCore *core, long hid, const void *ptr, long len); 93 | 94 | // close given hid 95 | ANETAPI int asn_core_close(AsyncCore *core, long hid, int code); 96 | 97 | // send vector 98 | ANETAPI long asn_core_send_vector(AsyncCore *core, long hid, const void *vecptr[], 99 | const long veclen[], int count, int mask); 100 | 101 | 102 | // send data with mask 103 | ANETAPI long asn_core_send_mask(AsyncCore *core, long hid, const void *ptr, long len, 104 | int mask); 105 | 106 | 107 | // new connection to the target address, returns hid 108 | ANETAPI long asn_core_new_connect(AsyncCore *core, const char *ip, int port, int header); 109 | 110 | // new listener, returns hid 111 | ANETAPI long asn_core_new_listen(AsyncCore *core, const char *ip, int port, int header); 112 | 113 | // new assign, returns hid 114 | ANETAPI long asn_core_new_assign(AsyncCore *core, int fd, int header, int check_estab); 115 | 116 | // queue an ASYNC_CORE_EVT_PUSH event and wake async_core_wait up 117 | ANETAPI int asn_core_post(AsyncCore *core, long wparam, long lparam, const char *data, long size); 118 | 119 | // get node mode: ASYNCCORE_NODE_IN/OUT/LISTEN4/LISTEN6 120 | ANETAPI int asn_core_get_mode(const AsyncCore *core, long hid); 121 | 122 | // returns connection tag, -1 for hid not exist 123 | ANETAPI long asn_core_get_tag(const AsyncCore *core, long hid); 124 | 125 | // set connection tag 126 | ANETAPI void asn_core_set_tag(AsyncCore *core, long hid, long tag); 127 | 128 | // get send queue size 129 | ANETAPI long asn_core_remain(const AsyncCore *core, long hid); 130 | 131 | // set default buffer limit and max packet size 132 | ANETAPI void asn_core_limit(AsyncCore *core, long limited, long maxsize); 133 | 134 | 135 | 136 | // get first node 137 | ANETAPI long asn_core_node_head(const AsyncCore *core); 138 | 139 | // get next node 140 | ANETAPI long asn_core_node_next(const AsyncCore *core, long hid); 141 | 142 | // get prev node 143 | ANETAPI long asn_core_node_prev(const AsyncCore *core, long hid); 144 | 145 | 146 | #define ASYNCCORE_OPTION_NODELAY 1 147 | #define ASYNCCORE_OPTION_REUSEADDR 2 148 | #define ASYNCCORE_OPTION_KEEPALIVE 3 149 | #define ASYNCCORE_OPTION_SYSSNDBUF 4 150 | #define ASYNCCORE_OPTION_SYSRCVBUF 5 151 | #define ASYNCCORE_OPTION_LIMITED 6 152 | #define ASYNCCORE_OPTION_MAXSIZE 7 153 | 154 | // set connection socket option 155 | ANETAPI int asn_core_option(AsyncCore *core, long hid, int opt, long value); 156 | 157 | // get connection socket status 158 | ANETAPI int asn_core_status(AsyncCore *core, long hid, int opt); 159 | 160 | // set connection rc4 send key 161 | ANETAPI int asn_core_rc4_set_skey(AsyncCore *core, long hid, 162 | const unsigned char *key, int keylen); 163 | 164 | // set connection rc4 recv key 165 | ANETAPI int asn_core_rc4_set_rkey(AsyncCore *core, long hid, 166 | const unsigned char *key, int keylen); 167 | 168 | // set remote ip validator 169 | ANETAPI void asn_core_firewall(AsyncCore *core, AsyncValidator v, void *user); 170 | 171 | // set timeout 172 | ANETAPI void asn_core_timeout(AsyncCore *core, long seconds); 173 | 174 | // get sockname 175 | ANETAPI int asn_core_sockname(const AsyncCore *core, long hid, char *out); 176 | 177 | // get peername 178 | ANETAPI int asn_core_peername(const AsyncCore *core, long hid, char *out); 179 | 180 | // disable read poll event 181 | ANETAPI int asn_core_disable(AsyncCore *core, long hid, int value); 182 | 183 | 184 | // get number of connections 185 | ANETAPI int asn_core_nfds(const AsyncCore *core); 186 | 187 | 188 | 189 | //===================================================================== 190 | // AsyncNotify 191 | //===================================================================== 192 | typedef void AsyncNotify; 193 | 194 | // create object 195 | ANETAPI AsyncNotify* asn_notify_new(int serverid); 196 | 197 | // delete object 198 | ANETAPI void asn_notify_delete(AsyncNotify *notify); 199 | 200 | 201 | #define ACN_NOTIFY_EVT_DATA 1 // (wp=sid, lp=cmd) 202 | #define ACN_NOTIFY_EVT_NEW_IN 2 // (wp=sid, lp=hid) 203 | #define ACN_NOTIFY_EVT_NEW_OUT 4 // (wp=sid, lp=hid) 204 | #define ACN_NOTIFY_EVT_CLOSED_IN 8 // (wp=sid, lp=hid) 205 | #define ACN_NOTIFY_EVT_CLOSED_OUT 16 // (wp=sid, lp=hid) 206 | #define ACN_NOTIFY_EVT_ERROR 32 // (wp=sid, lp=why) 207 | #define ACN_NOTIFY_EVT_CORE 64 208 | 209 | // wait events 210 | ANETAPI void asn_notify_wait(AsyncNotify *notify, unsigned long millisec); 211 | 212 | // wake-up from waiting 213 | ANETAPI void asn_notify_wake(AsyncNotify *notify); 214 | 215 | // read events, returns data length of the message, 216 | // and returns -1 for no event, -2 for buffer size too small, 217 | // returns data size when data equals NULL. 218 | ANETAPI long asn_notify_read(AsyncNotify *notify, int *event, long *wparam, 219 | long *lparam, void *data, long maxsize); 220 | 221 | 222 | // new listen: return id(-1 error, -2 port conflict), flag&1(reuse) 223 | ANETAPI long asn_notify_listen(AsyncNotify *notify, const char *addr, int port, int flag); 224 | 225 | // remove listening port 226 | ANETAPI int asn_notify_remove(AsyncNotify *notify, long listenid, int code); 227 | 228 | // setup self server id 229 | ANETAPI void asn_notify_change(AsyncNotify *notify, int new_server_id); 230 | 231 | 232 | // send message to server 233 | ANETAPI int asn_notify_send(AsyncNotify *notify, int sid, short cmd, 234 | const void *data, long size); 235 | 236 | // close server connection 237 | ANETAPI int asn_notify_close(AsyncNotify *notify, int sid, int mode, int code); 238 | 239 | // get listening port 240 | ANETAPI int asn_notify_get_port(AsyncNotify *notify, long listenid); 241 | 242 | 243 | // clear ip allow table 244 | ANETAPI void asn_notify_allow_clear(AsyncNotify *notify); 245 | 246 | // add or update ip in allow table 247 | ANETAPI void asn_notify_allow_add(AsyncNotify *notify, const char *ip); 248 | 249 | // remove ip from table 250 | ANETAPI void asn_notify_allow_del(AsyncNotify *notify, const char *ip); 251 | 252 | // ip table enable: enable is 0(disable allow table) otherwise(enable) 253 | ANETAPI void asn_notify_allow_enable(AsyncNotify *notify, int enable); 254 | 255 | 256 | // add or update a sid into sid2addr 257 | ANETAPI void asn_notify_sid_add(AsyncNotify *notify, int sid, const char *ip, int port); 258 | 259 | // add or update a sid into sid2addr 260 | ANETAPI void asn_notify_sid_del(AsyncNotify *notify, int sid); 261 | 262 | // list sids into an array 263 | ANETAPI int asn_notify_sid_list(AsyncNotify *notify, int *sids, int maxsize); 264 | 265 | // clear sid list 266 | ANETAPI void asn_notify_sid_clear(AsyncNotify *notify); 267 | 268 | 269 | #define ACN_NOTIFY_OPT_PROFILE 0 270 | #define ACN_NOTIFY_OPT_TIMEOUT_IDLE 1 271 | #define ACN_NOTIFY_OPT_TIMEOUT_PING 2 272 | #define ACN_NOTIFY_OPT_SOCK_KEEPALIVE 3 273 | #define ACN_NOTIFY_OPT_SND_BUFSIZE 4 274 | #define ACN_NOTIFY_OPT_RCV_BUFSIZE 5 275 | #define ACN_NOTIFY_OPT_BUFFER_LIMIT 6 276 | #define ACN_NOTIFY_OPT_SIGN_TIMEOUT 7 277 | #define ACN_NOTIFY_OPT_RETRY_TIMEOUT 8 278 | #define ACN_NOTIFY_OPT_NET_TIMEOUT 9 279 | #define ACN_NOTIFY_OPT_EVT_MASK 10 280 | #define ACN_NOTIFY_OPT_LOG_MASK 11 281 | #define ACN_NOTIFY_OPT_GET_PING 12 282 | #define ACN_NOTIFY_OPT_GET_OUT_COUNT 13 283 | #define ACN_NOTIFY_OPT_GET_IN_COUNT 14 284 | 285 | #define ACN_NOTIFY_LOG_INFO 1 286 | #define ACN_NOTIFY_LOG_REJECT 2 287 | #define ACN_NOTIFY_LOG_ERROR 4 288 | #define ACN_NOTIFY_LOG_WARNING 8 289 | 290 | // config 291 | ANETAPI int asn_notify_option(AsyncNotify *notify, int type, long value); 292 | 293 | // set login token 294 | ANETAPI void asn_notify_token(AsyncNotify *notify, const char *token, int size); 295 | 296 | // set logging 297 | ANETAPI void asn_notify_trace(AsyncNotify *notify, const char *prefix, int STDOUT, int color); 298 | 299 | 300 | 301 | //===================================================================== 302 | // AsyncSock 303 | //===================================================================== 304 | typedef void AsyncSock; 305 | 306 | 307 | ANETAPI AsyncSock* asn_sock_new(void); 308 | 309 | ANETAPI void asn_sock_delete(AsyncSock *sock); 310 | 311 | ANETAPI int asn_sock_connect(AsyncSock *sock, const char *ip, int port, int head); 312 | 313 | ANETAPI int asn_sock_assign(AsyncSock *sock, int fd, int head); 314 | 315 | ANETAPI void asn_sock_close(AsyncSock *sock); 316 | 317 | 318 | ANETAPI int asn_sock_state(const AsyncSock *sock); 319 | 320 | ANETAPI int asn_sock_fd(const AsyncSock *sock); 321 | 322 | ANETAPI long asn_sock_remain(const AsyncSock *sock); 323 | 324 | 325 | 326 | // send data 327 | ANETAPI long asn_sock_send(AsyncSock *sock, const void *ptr, long size, int mask); 328 | 329 | // recv vector: returns packet size, -1 for not enough data, -2 for 330 | // buffer size too small, -3 for packet size error, -4 for size over limit, 331 | // returns packet size if ptr equals NULL. 332 | ANETAPI long asn_sock_recv(AsyncSock *sock, void *ptr, int size); 333 | 334 | 335 | // send vector 336 | ANETAPI long asn_sock_send_vector(AsyncSock *sock, const void *vecptr[], 337 | const long veclen[], int count, int mask); 338 | 339 | // recv vector: returns packet size, -1 for not enough data, -2 for 340 | // buffer size too small, -3 for packet size error, -4 for size over limit, 341 | // returns packet size if vecptr equals NULL. 342 | ANETAPI long asn_sock_recv_vector(AsyncSock *sock, void *vecptr[], 343 | const long veclen[], int count); 344 | 345 | 346 | // update 347 | ANETAPI int asn_sock_update(AsyncSock *sock, int what); 348 | 349 | // process 350 | ANETAPI void asn_sock_process(AsyncSock *sock); 351 | 352 | 353 | // set send cryption key 354 | ANETAPI void asn_sock_rc4_set_skey(AsyncSock *sock, const unsigned char *key, 355 | int keylen); 356 | 357 | // set recv cryption key 358 | ANETAPI void asn_sock_rc4_set_rkey(AsyncSock *sock, const unsigned char *key, 359 | int keylen); 360 | 361 | // set nodelay 362 | ANETAPI int asn_sock_nodelay(AsyncSock *sock, int nodelay); 363 | 364 | // set buf size 365 | ANETAPI int asn_sock_sys_buffer(AsyncSock *sock, long rcvbuf, long sndbuf); 366 | 367 | // set keepalive 368 | ANETAPI int asn_sock_keepalive(AsyncSock *sock, int keepcnt, int idle, int intvl); 369 | 370 | 371 | #ifdef __cplusplus 372 | } 373 | #endif 374 | 375 | 376 | //===================================================================== 377 | // C++接口 378 | //===================================================================== 379 | #ifdef __cplusplus 380 | 381 | namespace AsyncNet { 382 | }; 383 | 384 | 385 | #endif 386 | 387 | #endif 388 | 389 | 390 | -------------------------------------------------------------------------------- /source/AsyncKit.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncKit.h - 4 | // 5 | // Last Modified: 2025/04/25 15:32:00 6 | // 7 | //===================================================================== 8 | #ifndef _ASYNCKIT_H_ 9 | #define _ASYNCKIT_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "../system/inetevt.h" 15 | #include "../system/inetkit.h" 16 | #include "../system/wrappers.h" 17 | 18 | #include "AsyncEvt.h" 19 | 20 | NAMESPACE_BEGIN(System); 21 | 22 | 23 | //--------------------------------------------------------------------- 24 | // AsyncStream 25 | //--------------------------------------------------------------------- 26 | class AsyncStream final 27 | { 28 | public: 29 | ~AsyncStream(); 30 | AsyncStream(AsyncLoop &loop); 31 | AsyncStream(CAsyncLoop *loop); 32 | AsyncStream(AsyncStream &&src); 33 | 34 | AsyncStream(const AsyncStream &) = delete; 35 | AsyncStream &operator=(const AsyncStream &) = delete; 36 | 37 | public: 38 | 39 | inline const CAsyncStream *GetStream() const { return _stream; } 40 | inline CAsyncStream *GetStream() { return _stream; } 41 | 42 | inline int GetError() const { return _stream ? _stream->error : -1; } 43 | inline int GetDirection() const { return _stream ? _stream->direction : 0; } 44 | inline int GetEof(int dir) const { return _stream ? (_stream->eof & dir): 0; } 45 | inline uint32_t GetName() const { return _stream ? (uint32_t)_stream->name : 0; } 46 | 47 | inline bool CanRead() const { return (GetDirection() & ASYNC_STREAM_INPUT) != 0; } 48 | inline bool CanWrite() const { return (GetDirection() & ASYNC_STREAM_OUTPUT) != 0; } 49 | inline bool EndOfInput() const { return (GetEof(ASYNC_STREAM_INPUT) != 0); } 50 | inline bool EndOfOutput() const { return (GetEof(ASYNC_STREAM_OUTPUT) != 0); } 51 | 52 | // get the underlying socket fd, returns -1 if not a TCP stream 53 | inline int GetFd() const { return async_stream_tcp_getfd(_stream); } 54 | 55 | // inline int GetFd() const { return _stream->fd; } 56 | // inline int GetError() const { return _stream->error; } 57 | 58 | void SetCallback(std::function cb); 59 | 60 | // create a new stream based on CAsyncStream object 61 | int NewStream(CAsyncStream *stream, bool borrow = false); 62 | 63 | // create a paired stream 64 | int NewPair(AsyncStream &partner); 65 | 66 | // create a TCP stream and assign an existing socket 67 | int NewAssign(int fd, bool IsEstablished = false); 68 | 69 | // create a TCP stream and connect to remote address 70 | int NewConnect(const sockaddr *addr, int addrlen); 71 | 72 | // create a TCP stream and connect to remote address 73 | int NewConnect(int family, const char *text, int port); 74 | 75 | // create a TCP stream and connect to remote address 76 | int NewConnect(const PosixAddress &addr); 77 | 78 | // close stream 79 | void Close(); 80 | 81 | // how many bytes remain in the recv buffer 82 | inline long Remain() const { return _async_stream_remain(_stream); } 83 | 84 | // how many bytes remain in the send buffer 85 | inline long Pending() const { return _async_stream_pending(_stream); } 86 | 87 | // read data from recv buffer 88 | long Read(void *ptr, long size); 89 | 90 | // write data into send buffer 91 | long Write(const void *ptr, long size); 92 | 93 | // peek data from recv buffer without removing them 94 | long Peek(void *ptr, long size); 95 | 96 | // enable ASYNC_EVENT_READ/WRITE 97 | void Enable(int event); 98 | 99 | // disable ASYNC_EVENT_READ/WRITE 100 | void Disable(int event); 101 | 102 | // move data from recv buffer to send buffer 103 | long Move(long size); 104 | 105 | // set high water 106 | void WaterMark(int hiwater, int lowater); 107 | 108 | 109 | private: 110 | static void TcpCB(CAsyncStream *tcp, int event, int args); 111 | 112 | typedef std::function Callback; 113 | std::shared_ptr _cb_ptr = std::make_shared(); 114 | 115 | bool _borrow = false; 116 | CAsyncLoop *_loop = NULL; 117 | CAsyncStream *_stream = NULL; 118 | }; 119 | 120 | 121 | //--------------------------------------------------------------------- 122 | // AsyncListener 123 | //--------------------------------------------------------------------- 124 | class AsyncListener final 125 | { 126 | public: 127 | ~AsyncListener(); 128 | AsyncListener(AsyncLoop &loop); 129 | AsyncListener(CAsyncLoop *loop); 130 | AsyncListener(AsyncListener &&src); 131 | 132 | AsyncListener(const AsyncListener &) = delete; 133 | AsyncListener &operator=(const AsyncListener &) = delete; 134 | 135 | public: 136 | 137 | void SetCallback(std::function cb); 138 | 139 | inline int GetFd() const { return _listener->fd; } 140 | inline int GetError() const { return _listener->error; } 141 | inline int GetFamily() const { return _listener->family; } 142 | 143 | // start listening 144 | int Start(int flags, const sockaddr *addr, int addrlen); 145 | 146 | // start listening 147 | int Start(int flags, const PosixAddress &addr); 148 | 149 | // start listening 150 | int Start(int flags, int family, const char *text, int port); 151 | 152 | // stop listening 153 | void Stop(); 154 | 155 | // pause/resume accepting new connections if the argument is true/false 156 | void Pause(bool pause); 157 | 158 | private: 159 | 160 | static void ListenCB(CAsyncListener *listener, int fd, const sockaddr *addr, int len); 161 | typedef std::function Callback; 162 | std::shared_ptr _cb_ptr = std::make_shared(); 163 | 164 | CAsyncListener *_listener = NULL; 165 | CAsyncLoop *_loop = NULL; 166 | }; 167 | 168 | 169 | 170 | //--------------------------------------------------------------------- 171 | // AsyncUdp 172 | //--------------------------------------------------------------------- 173 | class AsyncUdp final 174 | { 175 | public: 176 | ~AsyncUdp(); 177 | AsyncUdp(AsyncLoop &loop); 178 | AsyncUdp(CAsyncLoop *loop); 179 | AsyncUdp(AsyncUdp &&src); 180 | 181 | AsyncUdp(const AsyncUdp &) = delete; 182 | AsyncUdp &operator=(const AsyncUdp &) = delete; 183 | 184 | public: 185 | 186 | // setup callback 187 | void SetCallback(std::function cb); 188 | 189 | // setup receiver 190 | void SetReceiver(std::function receiver); 191 | 192 | inline const CAsyncUdp *GetUdp() const { return _udp; } 193 | inline CAsyncUdp *GetUdp() { return _udp; } 194 | 195 | inline int GetFd() const { return _udp->fd; } 196 | 197 | // close udp socket 198 | void Close(); 199 | 200 | // assign existing socket 201 | int Assign(int fd); 202 | 203 | // open an udp socket 204 | int Open(const sockaddr *addr, int addrlen, int flags); 205 | 206 | // open an udp socket 207 | int Open(const System::PosixAddress &addr, int flags); 208 | 209 | // open an udp socket 210 | int Open(int family, const char *text, int port, int flags); 211 | 212 | // enable ASYNC_EVENT_READ/WRITE 213 | void Enable(int event); 214 | 215 | // disable ASYNC_EVENT_READ/WRITE 216 | void Disable(int event); 217 | 218 | // send data 219 | int SendTo(const void *ptr, long size, const sockaddr *addr, int addrlen); 220 | 221 | // send data 222 | int SendTo(const void *ptr, long size, const PosixAddress &addr); 223 | 224 | // receive data 225 | int RecvFrom(void *ptr, long size, sockaddr *addr, int *addrlen); 226 | 227 | // receive data 228 | int RecvFrom(void *ptr, long size, PosixAddress &addr); 229 | 230 | private: 231 | 232 | static void UdpCB(CAsyncUdp *udp, int event, int args); 233 | static void UdpReceiver(CAsyncUdp *udp, void *data, long size, const sockaddr *addr, int addrlen); 234 | 235 | typedef std::function Callback; 236 | typedef std::function Receiver; 237 | 238 | std::shared_ptr _cb_ptr = std::make_shared(); 239 | std::shared_ptr _receiver_ptr = std::make_shared(); 240 | 241 | CAsyncLoop *_loop = NULL; 242 | CAsyncUdp *_udp = NULL; 243 | }; 244 | 245 | 246 | 247 | //--------------------------------------------------------------------- 248 | // AsyncMessage 249 | //--------------------------------------------------------------------- 250 | class AsyncMessage final 251 | { 252 | public: 253 | ~AsyncMessage(); 254 | AsyncMessage(AsyncLoop &loop); 255 | AsyncMessage(CAsyncLoop *loop); 256 | AsyncMessage(AsyncMessage &&src); 257 | 258 | AsyncMessage(const AsyncMessage &) = delete; 259 | AsyncMessage &operator=(const AsyncMessage &) = delete; 260 | 261 | public: 262 | 263 | // setup callback 264 | void SetCallback(std::function cb); 265 | 266 | // get internal msg object 267 | inline CAsyncMessage *GetMsg() { return _msg; } 268 | 269 | // get internal msg object 270 | inline const CAsyncMessage *GetMsg() const { return _msg; } 271 | 272 | // start message listening 273 | bool Start(); 274 | 275 | // stop message listening 276 | bool Stop(); 277 | 278 | // post message 279 | int Post(int mid, int wparam, int lparam, const void *ptr, int size); 280 | 281 | // post message 282 | int Post(int mid, int wparam, int lparam, const char *text); 283 | 284 | // post message 285 | int Post(int mid, int wparam, int lparam, const std::string &text); 286 | 287 | private: 288 | static int MsgCB(CAsyncMessage *msg, int mid, IINT32 wparam, IINT32 lparam, const void *ptr, int size); 289 | typedef std::function Callback; 290 | 291 | std::shared_ptr _cb_ptr = std::make_shared(); 292 | 293 | CAsyncMessage *_msg = NULL; 294 | }; 295 | 296 | 297 | 298 | 299 | NAMESPACE_END(System); 300 | 301 | #endif 302 | 303 | 304 | -------------------------------------------------------------------------------- /source/AsyncNet.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncNet.cpp - 4 | // 5 | // Created by skywind on 2018/12/13 6 | // Last Modified: 2018/12/13 15:26:15 7 | // 8 | //===================================================================== 9 | #include "AsyncNet.h" 10 | 11 | NAMESPACE_BEGIN(AsyncNet); 12 | 13 | 14 | //--------------------------------------------------------------------- 15 | // ctor 16 | //--------------------------------------------------------------------- 17 | AsyncNet::AsyncNet(): _core(0) 18 | { 19 | 20 | } 21 | 22 | 23 | //--------------------------------------------------------------------- 24 | // dtor 25 | //--------------------------------------------------------------------- 26 | AsyncNet::~AsyncNet() 27 | { 28 | 29 | } 30 | 31 | 32 | 33 | NAMESPACE_END(AsyncNet); 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /source/AsyncNet.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncNet.h - 4 | // 5 | // Created by skywind on 2018/12/13 6 | // Last Modified: 2018/12/13 15:25:44 7 | // 8 | //===================================================================== 9 | #ifndef ASYNC_NET_H 10 | #define ASYNC_NET_H 11 | 12 | #include "EventBasic.h" 13 | 14 | NAMESPACE_BEGIN(AsyncNet); 15 | 16 | //--------------------------------------------------------------------- 17 | // AsyncEvent 18 | //--------------------------------------------------------------------- 19 | class AsyncNet 20 | { 21 | public: 22 | AsyncNet(); 23 | virtual ~AsyncNet(); 24 | 25 | 26 | 27 | private: 28 | AsyncNet(const AsyncNet &); 29 | AsyncNet& operator=(const AsyncNet &); 30 | 31 | protected: 32 | ConnectionDict _connections; 33 | System::AsyncCore _core; 34 | System::CriticalSection _lock; 35 | }; 36 | 37 | 38 | NAMESPACE_END(AsyncNet); 39 | 40 | 41 | #endif 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /source/AsyncSub.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncSub.h - 4 | // 5 | // Last Modified: 2025/06/10 11:11:28 6 | // 7 | //===================================================================== 8 | #include 9 | 10 | #include "AsyncSub.h" 11 | 12 | NAMESPACE_BEGIN(System); 13 | 14 | //===================================================================== 15 | // AsyncTopic 16 | //===================================================================== 17 | 18 | 19 | //--------------------------------------------------------------------- 20 | // dtor 21 | //--------------------------------------------------------------------- 22 | AsyncTopic::~AsyncTopic() 23 | { 24 | if (_topic) { 25 | async_topic_delete(_topic); 26 | _topic = NULL; 27 | } 28 | } 29 | 30 | 31 | //--------------------------------------------------------------------- 32 | // ctor 33 | //--------------------------------------------------------------------- 34 | AsyncTopic::AsyncTopic(AsyncLoop &loop) 35 | { 36 | _topic = async_topic_new(loop.GetLoop()); 37 | } 38 | 39 | 40 | //--------------------------------------------------------------------- 41 | // ctor 42 | //--------------------------------------------------------------------- 43 | AsyncTopic::AsyncTopic(CAsyncLoop *loop) 44 | { 45 | _topic = async_topic_new(loop); 46 | } 47 | 48 | 49 | //--------------------------------------------------------------------- 50 | // move ctor 51 | //--------------------------------------------------------------------- 52 | AsyncTopic::AsyncTopic(AsyncTopic &&src) 53 | { 54 | _topic = src._topic; 55 | src._topic = NULL; 56 | } 57 | 58 | 59 | //--------------------------------------------------------------------- 60 | // publish data to a topic 61 | //--------------------------------------------------------------------- 62 | void AsyncTopic::Publish(int tid, IINT32 wparam, IINT32 lparam, const void *data, int size) 63 | { 64 | if (_topic) { 65 | async_topic_publish(_topic, tid, wparam, lparam, data, size); 66 | } 67 | } 68 | 69 | 70 | 71 | //===================================================================== 72 | // AsyncSubscribe 73 | //===================================================================== 74 | 75 | 76 | //--------------------------------------------------------------------- 77 | // dtor 78 | //--------------------------------------------------------------------- 79 | AsyncSubscribe::~AsyncSubscribe() 80 | { 81 | if (_sub_ptr.get() != NULL) { 82 | CAsyncSubscribe *sub = _sub_ptr.get(); 83 | if (async_sub_is_active(sub)) { 84 | async_sub_deregister(sub); 85 | } 86 | } 87 | } 88 | 89 | 90 | //--------------------------------------------------------------------- 91 | // ctor 92 | //--------------------------------------------------------------------- 93 | AsyncSubscribe::AsyncSubscribe(): _sub_ptr(std::make_shared()) 94 | { 95 | async_sub_init(_sub_ptr.get(), SubCB); 96 | _sub_ptr.get()->user = this; 97 | } 98 | 99 | 100 | //--------------------------------------------------------------------- 101 | // move ctor 102 | //--------------------------------------------------------------------- 103 | AsyncSubscribe::AsyncSubscribe(AsyncSubscribe &&src): 104 | _cb_ptr(std::move(src._cb_ptr)), 105 | _sub_ptr(std::move(src._sub_ptr)) 106 | { 107 | (*src._cb_ptr) = nullptr; 108 | if (_sub_ptr.get()) { 109 | _sub_ptr.get()->user = this; 110 | _sub_ptr.get()->callback = SubCB; 111 | } 112 | } 113 | 114 | 115 | //--------------------------------------------------------------------- 116 | // set callback 117 | //--------------------------------------------------------------------- 118 | void AsyncSubscribe::SetCallback(std::function cb) 119 | { 120 | (*_cb_ptr) = cb; 121 | } 122 | 123 | 124 | //--------------------------------------------------------------------- 125 | // internal callback 126 | //--------------------------------------------------------------------- 127 | int AsyncSubscribe::SubCB(CAsyncSubscribe *sub, IINT32 wparam, IINT32 lparam, const void *data, int size) 128 | { 129 | AsyncSubscribe *self = (AsyncSubscribe*)sub->user; 130 | if ((*self->_cb_ptr) != nullptr) { 131 | auto ref_ptr = self->_cb_ptr; 132 | auto ref_sub = self->_sub_ptr; 133 | return (*ref_ptr)(wparam, lparam, data, size); 134 | } 135 | return 0; // no callback 136 | } 137 | 138 | 139 | //--------------------------------------------------------------------- 140 | // Register to a topic 141 | //--------------------------------------------------------------------- 142 | void AsyncSubscribe::Register(AsyncTopic &topic, int tid) 143 | { 144 | CAsyncSubscribe *sub = _sub_ptr.get(); 145 | assert(sub != NULL); 146 | async_sub_register(topic.GetTopic(), sub, tid); 147 | } 148 | 149 | 150 | //--------------------------------------------------------------------- 151 | // Unregister from a topic 152 | //--------------------------------------------------------------------- 153 | void AsyncSubscribe::Deregister() 154 | { 155 | CAsyncSubscribe *sub = _sub_ptr.get(); 156 | assert(sub != NULL); 157 | if (async_sub_is_active(sub)) { 158 | async_sub_deregister(sub); 159 | } 160 | } 161 | 162 | 163 | //===================================================================== 164 | // AsyncSignal 165 | //===================================================================== 166 | 167 | //--------------------------------------------------------------------- 168 | // dtor 169 | //--------------------------------------------------------------------- 170 | AsyncSignal::~AsyncSignal() 171 | { 172 | if (_signal) { 173 | async_signal_delete(_signal); 174 | _signal = NULL; 175 | } 176 | _callbacks.clear(); 177 | } 178 | 179 | 180 | //--------------------------------------------------------------------- 181 | // ctor 182 | //--------------------------------------------------------------------- 183 | AsyncSignal::AsyncSignal(AsyncLoop &loop) 184 | { 185 | _signal = async_signal_new(loop.GetLoop(), SignalCB); 186 | _signal->user = this; 187 | } 188 | 189 | 190 | //--------------------------------------------------------------------- 191 | // ctor 192 | //--------------------------------------------------------------------- 193 | AsyncSignal::AsyncSignal(CAsyncLoop *loop) 194 | { 195 | _signal = async_signal_new(loop, SignalCB); 196 | _signal->user = this; 197 | } 198 | 199 | 200 | //--------------------------------------------------------------------- 201 | // move ctor 202 | //--------------------------------------------------------------------- 203 | AsyncSignal::AsyncSignal(AsyncSignal &&src): 204 | _callbacks(std::move(src._callbacks)) 205 | { 206 | _signal = src._signal; 207 | _signal->user = this; 208 | src._signal = NULL; 209 | } 210 | 211 | 212 | //--------------------------------------------------------------------- 213 | // callback 214 | //--------------------------------------------------------------------- 215 | void AsyncSignal::SignalCB(CAsyncSignal *signal, int signum) 216 | { 217 | AsyncSignal *self = (AsyncSignal*)signal->user; 218 | if (signum >= 0 && signum < CASYNC_SIGNAL_MAX) { 219 | int installed = self->_signal->installed[signum]; 220 | if (installed == 1) { 221 | auto it = self->_callbacks.find(signum); 222 | if (it != self->_callbacks.end()) { 223 | if (it->second != nullptr) { 224 | it->second(signum); 225 | } 226 | } 227 | } 228 | else if (installed == 2) { 229 | // ignored 230 | } 231 | } 232 | } 233 | 234 | 235 | //--------------------------------------------------------------------- 236 | // only one AsyncSignal can be started at the same time 237 | //--------------------------------------------------------------------- 238 | bool AsyncSignal::Start() 239 | { 240 | int hr = async_signal_start(_signal); 241 | return (hr == 0); 242 | } 243 | 244 | 245 | //--------------------------------------------------------------------- 246 | // stop signal handling 247 | //--------------------------------------------------------------------- 248 | bool AsyncSignal::Stop() 249 | { 250 | int hr = async_signal_stop(_signal); 251 | return (hr == 0); 252 | } 253 | 254 | 255 | //--------------------------------------------------------------------- 256 | // install a signal callback 257 | //--------------------------------------------------------------------- 258 | bool AsyncSignal::Install(int signum, std::function cb) 259 | { 260 | if (cb == nullptr) return Ignore(signum); 261 | int hr = async_signal_install(_signal, signum); 262 | if (hr != 0) return false; 263 | _callbacks[signum] = cb; 264 | return true; 265 | } 266 | 267 | 268 | //--------------------------------------------------------------------- 269 | // Remove a signal callback 270 | //--------------------------------------------------------------------- 271 | bool AsyncSignal::Remove(int signum) 272 | { 273 | int hr = async_signal_remove(_signal, signum); 274 | if (hr != 0) return false; 275 | auto it = _callbacks.find(signum); 276 | if (it != _callbacks.end()) { 277 | _callbacks.erase(it); 278 | } 279 | return true; 280 | } 281 | 282 | 283 | //--------------------------------------------------------------------- 284 | // Ignore a signal 285 | //--------------------------------------------------------------------- 286 | bool AsyncSignal::Ignore(int signum) 287 | { 288 | int hr = async_signal_ignore(_signal, signum); 289 | if (hr != 0) return false; 290 | auto it = _callbacks.find(signum); 291 | if (it != _callbacks.end()) { 292 | _callbacks.erase(it); 293 | } 294 | return true; 295 | } 296 | 297 | 298 | NAMESPACE_END(System); 299 | 300 | 301 | 302 | -------------------------------------------------------------------------------- /source/AsyncSub.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // AsyncSub.h - 4 | // 5 | // Last Modified: 2025/06/10 11:11:28 6 | // 7 | //===================================================================== 8 | #ifndef _ASYNCSUB_H_ 9 | #define _ASYNCSUB_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "../system/inetsub.h" 15 | 16 | #include "AsyncEvt.h" 17 | #include "AsyncKit.h" 18 | 19 | 20 | NAMESPACE_BEGIN(System); 21 | 22 | //--------------------------------------------------------------------- 23 | // AsyncTopic 24 | //--------------------------------------------------------------------- 25 | class AsyncTopic final 26 | { 27 | public: 28 | ~AsyncTopic(); 29 | AsyncTopic(AsyncLoop &loop); 30 | AsyncTopic(CAsyncLoop *loop); 31 | AsyncTopic(AsyncTopic &&src); 32 | 33 | AsyncTopic(const AsyncTopic &) = delete; 34 | AsyncTopic &operator=(const AsyncTopic &) = delete; 35 | 36 | public: 37 | 38 | CAsyncTopic *GetTopic() { return _topic; } 39 | const CAsyncTopic *GetTopic() const { return _topic; } 40 | 41 | // publish data to a topic 42 | void Publish(int tid, IINT32 wparam, IINT32 lparam, const void *data, int size); 43 | 44 | private: 45 | CAsyncTopic *_topic = NULL; 46 | }; 47 | 48 | 49 | //--------------------------------------------------------------------- 50 | // AsyncSubscribe 51 | //--------------------------------------------------------------------- 52 | class AsyncSubscribe final 53 | { 54 | public: 55 | ~AsyncSubscribe(); 56 | AsyncSubscribe(); 57 | AsyncSubscribe(AsyncSubscribe &&src); 58 | 59 | public: 60 | 61 | // set callback 62 | void SetCallback(std::function cb); 63 | 64 | // Register to a topic 65 | void Register(AsyncTopic &topic, int tid); 66 | 67 | // Unregister from a topic 68 | void Deregister(); 69 | 70 | // IsActive? 71 | bool IsActive() const { return (_sub_ptr.get() && async_sub_is_active(_sub_ptr.get())); } 72 | 73 | private: 74 | static int SubCB(CAsyncSubscribe *sub, IINT32 wparam, IINT32 lparam, const void *data, int size); 75 | 76 | typedef std::function Callback; 77 | std::shared_ptr _cb_ptr = std::make_shared(); 78 | std::shared_ptr _sub_ptr; 79 | }; 80 | 81 | 82 | //--------------------------------------------------------------------- 83 | // AsyncSignal 84 | //--------------------------------------------------------------------- 85 | class AsyncSignal final 86 | { 87 | public: 88 | ~AsyncSignal(); 89 | AsyncSignal(AsyncLoop &loop); 90 | AsyncSignal(CAsyncLoop *loop); 91 | AsyncSignal(AsyncSignal &&src); 92 | 93 | public: 94 | 95 | // Get the underlying CAsyncSignal pointer 96 | CAsyncSignal *GetSignal() { return _signal; } 97 | const CAsyncSignal *GetSignal() const { return _signal; } 98 | 99 | // only one AsyncSignal can be started at the same time 100 | bool Start(); 101 | 102 | // stop signal handling 103 | bool Stop(); 104 | 105 | // install a signal callback 106 | bool Install(int signum, std::function cb); 107 | 108 | // Remove a signal callback 109 | bool Remove(int signum); 110 | 111 | // Ignore a signal 112 | bool Ignore(int signum); 113 | 114 | // IsActive? 115 | bool IsActive() const { return (_signal && _signal->active != 0); } 116 | 117 | // IsInstalled? 118 | bool IsInstalled(int signum) const { 119 | if (_signal == NULL) return false; 120 | if (signum < 0 || signum >= CASYNC_SIGNAL_MAX) return false; 121 | return (_signal->installed[signum] == 1); 122 | } 123 | 124 | // IsIgnored? 125 | bool IsIgnored(int signum) const { 126 | if (_signal == NULL) return false; 127 | if (signum < 0 || signum >= CASYNC_SIGNAL_MAX) return false; 128 | return (_signal->installed[signum] == 2); 129 | } 130 | 131 | private: 132 | typedef std::function Callback; 133 | std::unordered_map _callbacks; 134 | static void SignalCB(CAsyncSignal *signal, int signum); 135 | CAsyncSignal *_signal = NULL; 136 | }; 137 | 138 | 139 | NAMESPACE_END(System); 140 | 141 | #endif 142 | 143 | 144 | -------------------------------------------------------------------------------- /source/TraceLog.cpp: -------------------------------------------------------------------------------- 1 | #include "TraceLog.h" 2 | 3 | #include 4 | 5 | 6 | NAMESPACE_BEGIN(AsyncNet) 7 | 8 | //--------------------------------------------------------------------- 9 | // Logging:日志输出 10 | //--------------------------------------------------------------------- 11 | Trace Trace::Global; 12 | Trace Trace::Null; 13 | Trace Trace::ConsoleWhite(NULL, true, CTEXT_WHITE); 14 | Trace Trace::LogFile("RttTrace_", false, CTEXT_WHITE); 15 | Trace Trace::ConsoleMagenta(NULL, true, CTEXT_BOLD_MAGENTA); 16 | Trace Trace::ConsoleGreen(NULL, true, CTEXT_BOLD_GREEN); 17 | 18 | Trace::Trace(const char *prefix, bool STDOUT, int color) 19 | { 20 | _mask = 0; 21 | _user = NULL; 22 | _buffer = new char [8192]; 23 | _output = NULL; 24 | _prefix = NULL; 25 | _fp = NULL; 26 | _tmtext = NULL; 27 | _fntext = NULL; 28 | _stdout = false; 29 | _color = -1; 30 | if (prefix || STDOUT) { 31 | open(prefix, STDOUT); 32 | } 33 | if (color >= 0) { 34 | this->color(color); 35 | } 36 | } 37 | 38 | Trace::~Trace() 39 | { 40 | close(); 41 | _mask = 0; 42 | _user = NULL; 43 | _output = NULL; 44 | delete []_buffer; 45 | _buffer = NULL; 46 | } 47 | 48 | void Trace::close() 49 | { 50 | if (_fp) fclose(_fp); 51 | if (_prefix) delete []_prefix; 52 | if (_tmtext) delete []_tmtext; 53 | if (_fntext) delete []_fntext; 54 | _fp = NULL; 55 | _prefix = NULL; 56 | _tmtext = NULL; 57 | _fntext = NULL; 58 | _stdout = false; 59 | setout(NULL, NULL); 60 | } 61 | 62 | void Trace::open(const char *prefix, bool STDOUT) 63 | { 64 | close(); 65 | if (prefix != NULL) { 66 | //prefix = ""; 67 | int size = strlen(prefix); 68 | _prefix = new char [size + 1]; 69 | memcpy(_prefix, prefix, size + 1); 70 | } 71 | else { 72 | if (_prefix) delete _prefix; 73 | _prefix = NULL; 74 | } 75 | _tmtext = new char [64]; 76 | _fntext = new char [1024]; 77 | _saved_date.datetime = 0; 78 | _fntext[0] = 0; 79 | _stdout = STDOUT; 80 | setout(StaticOut, this); 81 | } 82 | 83 | void Trace::setout(TraceOut out, void *user) 84 | { 85 | _output = out; 86 | _user = user; 87 | } 88 | 89 | void Trace::out(int mask, const char *fmt, ...) 90 | { 91 | if ((mask & _mask) != 0 && _output != NULL) { 92 | System::CriticalScope scope_lock(_lock); 93 | va_list argptr; 94 | va_start(argptr, fmt); 95 | vsprintf(_buffer, fmt, argptr); 96 | va_end(argptr); 97 | _output(_buffer, _user); 98 | } 99 | } 100 | 101 | void Trace::binary(int mask, const void *bin, int size) 102 | { 103 | static const char hex[17] = "0123456789ABCDEF"; 104 | if ((mask & _mask) != 0 || _output != NULL) { 105 | System::CriticalScope scope_lock(_lock); 106 | const unsigned char *src = (const unsigned char*)bin; 107 | char line[100]; 108 | int count = (size + 15) / 16; 109 | int offset = 0; 110 | for (int i = 0; i < count; i++, src += 16, offset += 16) { 111 | int length = size > 16? 16 : size; 112 | memset(line, ' ', 99); 113 | line[99] = 0; 114 | line[0] = hex[(offset >> 12) & 15]; 115 | line[1] = hex[(offset >> 8) & 15]; 116 | line[2] = hex[(offset >> 4) & 15]; 117 | line[3] = hex[(offset >> 0) & 15]; 118 | for (int j = 0; j < 16 && j < length; j++) { 119 | int start = 6 + j * 3; 120 | line[start + 0] = hex[src[j] >> 4]; 121 | line[start + 1] = hex[src[j] & 15]; 122 | if (j == 8) line[start - 1] = '-'; 123 | } 124 | line[6 + length * 3] = '\0'; 125 | _output(line, _user); 126 | } 127 | } 128 | } 129 | 130 | void Trace::StaticOut(const char *text, void *user) 131 | { 132 | Trace *self = (Trace*)user; 133 | 134 | System::DateTime now; 135 | 136 | now.localtime(); 137 | 138 | if (now.datetime != self->_saved_date.datetime) { 139 | self->_saved_date.datetime = now.datetime; 140 | sprintf(self->_tmtext, "%02d:%02d:%02d:%03d", now.hour(), 141 | now.minute(), now.second(), now.millisec()); 142 | int nowday = now.mday() + now.month() * 32; 143 | if (self->_saved_day != nowday) { 144 | self->_saved_day = nowday; 145 | self->_fntext[0] = 0; 146 | } 147 | } 148 | 149 | if (self->_prefix) { 150 | if (self->_fntext[0] == 0) { 151 | if (self->_fp) fclose(self->_fp); 152 | self->_fp = NULL; 153 | sprintf(self->_fntext, "%s%04d%02d%02d.log", 154 | self->_prefix, now.year(), now.month(), now.mday()); 155 | self->_fp = fopen(self->_fntext, "a"); 156 | if (self->_fp) { 157 | fseek(self->_fp, 0, SEEK_END); 158 | } 159 | } 160 | 161 | if (self->_fp) { 162 | fprintf(self->_fp, "[%s] %s\n", self->_tmtext, text); 163 | fflush(self->_fp); 164 | } 165 | } 166 | 167 | if (self->_stdout) { 168 | if (self->_color >= 0) { 169 | console_set_color(self->_color); 170 | } 171 | printf("[%s] %s\n", self->_tmtext, text); 172 | if (self->_color >= 0) { 173 | console_reset(); 174 | } 175 | fflush(stdout); 176 | } 177 | } 178 | 179 | 180 | // 设置颜色,只用于控制台输出(open时 STDOUT=true),高四位为背景色,低四位为前景色 181 | // 色彩编码见:http://en.wikipedia.org/wiki/ANSI_escape_code 182 | int Trace::color(int color) 183 | { 184 | int old = _color; 185 | _color = color; 186 | return old; 187 | } 188 | 189 | 190 | NAMESPACE_END(AsyncNet) 191 | 192 | -------------------------------------------------------------------------------- /source/TraceLog.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRACELOG_H__ 2 | #define __TRACELOG_H__ 3 | 4 | #include "../system/system.h" 5 | 6 | NAMESPACE_BEGIN(AsyncNet) 7 | 8 | //--------------------------------------------------------------------- 9 | // 日志输出 10 | //--------------------------------------------------------------------- 11 | class Trace 12 | { 13 | public: 14 | Trace(const char *prefix = NULL, bool STDOUT = false, int color = -1); 15 | virtual ~Trace(); 16 | 17 | typedef void (*TraceOut)(const char *text, void *user); 18 | 19 | bool available(int mask) const { return ((_mask & mask) && _output); } 20 | 21 | void setmask(int mask) { _mask = mask; } 22 | void enable(int mask) { _mask |= mask; } 23 | void disable(int mask) { _mask &= ~mask; } 24 | 25 | void setout(TraceOut out, void *user); 26 | void out(int mask, const char *fmt, ...); 27 | void binary(int mask, const void *bin, int size); 28 | 29 | // 如果 prefix == NULL则不向文件输出 30 | void open(const char *prefix, bool STDOUT = false); 31 | void close(); 32 | 33 | // 设置颜色,只用于控制台输出(open时 STDOUT=true),高四位为背景色,低四位为前景色 34 | // 色彩编码见:http://en.wikipedia.org/wiki/ANSI_escape_code,返回先前颜色 35 | int color(int color = -1); 36 | 37 | static Trace Global; 38 | static Trace Null; 39 | static Trace ConsoleWhite; 40 | static Trace LogFile; 41 | static Trace ConsoleMagenta; 42 | static Trace ConsoleGreen; 43 | 44 | protected: 45 | static void StaticOut(const char *text, void *user); 46 | 47 | protected: 48 | TraceOut _output; 49 | System::DateTime _saved_date; 50 | void *_user; 51 | char *_buffer; 52 | char *_prefix; 53 | bool _stdout; 54 | int _saved_day; 55 | FILE *_fp; 56 | char *_tmtext; 57 | char *_fntext; 58 | int _color; 59 | System::CriticalSection _lock; 60 | int _mask; 61 | }; 62 | 63 | 64 | #define TRACE_ERROR 1 65 | #define TRACE_WARNING 2 66 | #define TRACE_MGR_PACKET 4 67 | #define TRACE_MGR_SYN 8 68 | #define TRACE_MGR_EVENT 16 69 | #define TRACE_SESSION 32 70 | #define TRACE_KCP 64 71 | #define TRACE_SERVER 128 72 | #define TRACE_CLIENT 256 73 | #define TRACE_UDP_BASIC 512 74 | #define TRACE_UDP_BYTES 1024 75 | #define TRACE_UDP_ERROR 2048 76 | #define TRACE_RTT_REPORT 8192 77 | 78 | 79 | NAMESPACE_END(AsyncNet) 80 | 81 | 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../system/system.h" 3 | #include "../system/inetbase.c" 4 | #include "PacketBuffer.h" 5 | 6 | int main() 7 | { 8 | System::CriticalSection lock; 9 | std::vector locks; 10 | printf("Hello, World !\n"); 11 | // locks.resize(1000); 12 | // locks.push_back(lock); 13 | return 0; 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /system/imemkind.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // imemkind.h - utilities for imemdata.c and imembase.c 4 | // 5 | // NOTE: 6 | // For more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #include 10 | 11 | #include "imemkind.h" 12 | 13 | 14 | //===================================================================== 15 | // Utilities 16 | //===================================================================== 17 | 18 | 19 | -------------------------------------------------------------------------------- /system/imemkind.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // imemkind.h - utilities for imemdata.c and imembase.c 4 | // 5 | // NOTE: 6 | // For more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef _IMEMKIND_H_ 10 | #define _IMEMKIND_H_ 11 | 12 | #include 13 | 14 | #include "imembase.h" 15 | #include "imemdata.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | //--------------------------------------------------------------------- 23 | // Utilities 24 | //--------------------------------------------------------------------- 25 | 26 | // push message into stream 27 | void iposix_msg_push(struct IMSTREAM *queue, IINT32 msg, IINT32 wparam, 28 | IINT32 lparam, const void *data, IINT32 size); 29 | 30 | 31 | // read message from stream 32 | IINT32 iposix_msg_read(struct IMSTREAM *queue, IINT32 *msg, 33 | IINT32 *wparam, IINT32 *lparam, void *data, IINT32 maxsize); 34 | 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | 41 | #endif 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /system/inetevt.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetevt.h - Compact async event library for efficient I/O handling 4 | // skywind3000 (at) gmail.com, 2006-2016 5 | // 6 | // DESCRIPTION: 7 | // 8 | // This library provides an event-driven I/O framework similar to 9 | // libev, offering efficient event management and processing 10 | // capabilities. 11 | // 12 | // FEATURE INCLUDE: 13 | // 14 | // - Asynchronous event processing for socket/file descriptors 15 | // - Timer management for scheduling time-based events 16 | // - Semaphores for thread synchronization 17 | // - Idle event handling for background tasks 18 | // - One-time event execution 19 | // - Cross-platform support 20 | // 21 | // The CAsyncLoop serves as the central event dispatcher, managing 22 | // all registered event types (socket/file I/O events, timers, 23 | // semaphores, etc.) and providing a unified API for event-based 24 | // programming. 25 | // 26 | // For more information, please see the readme file. 27 | // 28 | //===================================================================== 29 | #ifndef _INETEVT_H_ 30 | #define _INETEVT_H_ 31 | 32 | #ifdef IHAVE_CONFIG_H 33 | #include "config.h" 34 | #endif 35 | 36 | #include 37 | 38 | #include "imembase.h" 39 | #include "imemdata.h" 40 | #include "inetbase.h" 41 | #include "itimer.h" 42 | 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | 48 | 49 | //--------------------------------------------------------------------- 50 | // Definitions 51 | //--------------------------------------------------------------------- 52 | #define ASYNC_EVENT_READ IPOLL_IN // 0x01 for reading events 53 | #define ASYNC_EVENT_WRITE IPOLL_OUT // 0x02 for writing events 54 | 55 | #define ASYNC_ONCE_HIGH 0 // 0 for high priority once event 56 | #define ASYNC_ONCE_NORMAL 1 // 1 for normal priority once event 57 | #define ASYNC_ONCE_LOW 2 // 2 for low priority once event 58 | 59 | 60 | //--------------------------------------------------------------------- 61 | // Configuration 62 | //--------------------------------------------------------------------- 63 | #ifndef ASYNC_LOOP_BUFFER_SIZE 64 | #define ASYNC_LOOP_BUFFER_SIZE 0x200000 65 | #endif 66 | 67 | 68 | //--------------------------------------------------------------------- 69 | // CAsyncLoop / CAsyncEvent 70 | //--------------------------------------------------------------------- 71 | struct CAsyncLoop; 72 | struct CAsyncEvent; 73 | struct CAsyncTimer; 74 | struct CAsyncSemaphore; 75 | struct CAsyncPostpone; 76 | struct CAsyncIdle; 77 | struct CAsyncOnce; 78 | 79 | typedef struct CAsyncLoop CAsyncLoop; 80 | typedef struct CAsyncEvent CAsyncEvent; 81 | typedef struct CAsyncTimer CAsyncTimer; 82 | typedef struct CAsyncSemaphore CAsyncSemaphore; 83 | typedef struct CAsyncPostpone CAsyncPostpone; 84 | typedef struct CAsyncIdle CAsyncIdle; 85 | typedef struct CAsyncOnce CAsyncOnce; 86 | 87 | 88 | //--------------------------------------------------------------------- 89 | // CAsyncEvent - for I/O events ASYNC_EVENT_READ/WRITE 90 | //--------------------------------------------------------------------- 91 | struct CAsyncEvent { 92 | ilist_head node; 93 | int active; 94 | int pending; 95 | void (*callback)(CAsyncLoop *loop, CAsyncEvent *evt, int event); 96 | void *user; 97 | int fd; 98 | int mask; 99 | }; 100 | 101 | 102 | //--------------------------------------------------------------------- 103 | // file descriptor - internal usage 104 | //--------------------------------------------------------------------- 105 | typedef struct CAsyncEntry { 106 | int fd; 107 | int mask; 108 | int dirty; 109 | ilist_head watchers; 110 | } CAsyncEntry; 111 | 112 | 113 | //--------------------------------------------------------------------- 114 | // pending event - internal usage 115 | //--------------------------------------------------------------------- 116 | typedef struct CAsyncPending { 117 | CAsyncEvent *evt; 118 | int event; 119 | } CAsyncPending; 120 | 121 | 122 | //--------------------------------------------------------------------- 123 | // CAsyncTimer 124 | //--------------------------------------------------------------------- 125 | struct CAsyncTimer { 126 | void (*callback)(CAsyncLoop *loop, CAsyncTimer *evt); 127 | itimer_evt timer_node; 128 | void *user; 129 | }; 130 | 131 | 132 | //--------------------------------------------------------------------- 133 | // CAsyncSemaphore - for multi-thread synchronization 134 | //--------------------------------------------------------------------- 135 | struct CAsyncSemaphore { 136 | IINT32 uid; 137 | IINT32 sid; 138 | void (*callback)(CAsyncLoop *loop, CAsyncSemaphore *notify); 139 | void *user; 140 | CAsyncLoop *loop; 141 | IMUTEX_TYPE lock; 142 | }; 143 | 144 | 145 | //--------------------------------------------------------------------- 146 | // CAsyncPostpone - will be scheduled at the end of an iteration 147 | //--------------------------------------------------------------------- 148 | struct CAsyncPostpone { 149 | ilist_head node; 150 | int active; 151 | void (*callback)(CAsyncLoop *loop, CAsyncPostpone *postpone); 152 | void *user; 153 | }; 154 | 155 | 156 | //--------------------------------------------------------------------- 157 | // CAsyncIdle - will be called when the loop is idle 158 | //--------------------------------------------------------------------- 159 | struct CAsyncIdle { 160 | ilist_head node; 161 | int active; 162 | int pending; 163 | void (*callback)(CAsyncLoop *loop, CAsyncIdle *idle); 164 | void *user; 165 | }; 166 | 167 | 168 | //--------------------------------------------------------------------- 169 | // CAsyncOnce - will be called every iteration 170 | //--------------------------------------------------------------------- 171 | struct CAsyncOnce { 172 | ilist_head node; 173 | int active; 174 | int pending; 175 | int priority; // 0 for high, 1 for normal, 2 for low 176 | void (*callback)(CAsyncLoop *loop, CAsyncOnce *once); 177 | void *user; 178 | }; 179 | 180 | 181 | //--------------------------------------------------------------------- 182 | // CAsyncLoop - centralized event manager and dispatcher 183 | //--------------------------------------------------------------------- 184 | struct CAsyncLoop { 185 | CAsyncEntry *fds; // file descriptor entries 186 | int fds_size; // size of fds array 187 | CAsyncPending *pending; // pending events 188 | int pending_size; // size of pending array 189 | int pending_index; // index of pending events 190 | int *changes; // changes of file descriptors 191 | int changes_size; // size of changes array 192 | int changes_index; // index of changes 193 | int xfd[4]; // extra file descriptors for wakeup 194 | int watching; // number of watching events 195 | int depth; // depth of the loop 196 | int num_events; // number of events 197 | int num_timers; // number of timers 198 | int num_semaphore; // number of semaphores 199 | int num_postpone; // number of postpone events 200 | int exiting; // exit flag 201 | int instant; // set to non-zero for instant mode 202 | int tickless; // tickless mode (no interval any more) 203 | char *internal; // a static buffer for internal usage 204 | char *buffer; // a static buffer for arbitrary usage 205 | char *cache; // an extra buffer for external usage 206 | ipolld poller; // poller for I/O events 207 | IUINT32 sid_index; // sid index 208 | IUINT32 current; // current time in milliseconds 209 | IUINT32 jiffies; // jiffies for timers 210 | IINT64 timestamp; // current time in nanoseconds 211 | IINT64 monotonic; // monotonic time in nanoseconds; 212 | IINT64 iteration; // iteration count 213 | IINT64 reseted; // fd reset count 214 | IINT64 proceeds; // number of events dispatched 215 | IINT32 interval; // interval for timer (default to 1ms) 216 | IMUTEX_TYPE lock_xfd; // lock for xfd 217 | IMUTEX_TYPE lock_queue; // lock for pending queue 218 | ib_array *sem_dict; // semaphore dictionary 219 | ib_array *array_idle; // idle array 220 | ib_array *array_once; // once array 221 | ilist_head list_post; // postpone list 222 | ilist_head list_idle; // idle list 223 | ilist_head list_once; // once list 224 | struct IVECTOR v_pending; // pending events vector 225 | struct IVECTOR v_changes; // changes vector 226 | struct IVECTOR v_queue; // queue vector for pending events 227 | struct IVECTOR v_semaphore; // semaphore vector for semaphores 228 | struct IMEMNODE semnode; // semaphore memory node 229 | struct IMEMNODE memnode; // memory node for internal usage 230 | void *self; // this pointer for loop object (for C++ wrapper) 231 | void *user; // user data pointer for loop object 232 | void *extension; // external data pointer for extension; 233 | int logmask; // log mask for loop object 234 | void *logger; // logger for loop object, can be NULL 235 | void (*writelog)(void *logger, const char *msg); 236 | void (*on_once)(CAsyncLoop *loop); 237 | void (*on_timer)(CAsyncLoop *loop); 238 | void (*on_idle)(CAsyncLoop *loop); 239 | itimer_mgr timer_mgr; 240 | }; 241 | 242 | 243 | //--------------------------------------------------------------------- 244 | // utilities 245 | //--------------------------------------------------------------------- 246 | #define async_loop_timestamp(loop) ((loop)->timestamp) 247 | #define async_loop_monotonic(loop) ((loop)->monotonic) 248 | #define async_loop_iteration(loop) ((loop)->iteration) 249 | #define async_loop_jiffies(loop) ((loop)->jiffies) 250 | #define async_loop_current(loop) ((loop)->current) 251 | #define async_loop_logable(loop, channel) ((loop)->logmask & (channel)) 252 | 253 | #define async_event_is_active(e) ((e)->active != 0) 254 | #define async_timer_is_active(e) ((e)->timer_node.mgr != NULL) 255 | #define async_sem_is_active(e) ((e)->loop != NULL) 256 | #define async_post_is_active(e) ((e)->active != 0) 257 | #define async_once_is_active(e) ((e)->active != 0) 258 | #define async_idle_is_active(e) ((e)->active != 0) 259 | 260 | 261 | //--------------------------------------------------------------------- 262 | // LOG MASK 263 | //--------------------------------------------------------------------- 264 | #define ASYNC_LOOP_LOG_ERROR 0x01 265 | #define ASYNC_LOOP_LOG_WARN 0x02 266 | #define ASYNC_LOOP_LOG_INFO 0x04 267 | #define ASYNC_LOOP_LOG_DEBUG 0x08 268 | #define ASYNC_LOOP_LOG_POLL 0x10 269 | #define ASYNC_LOOP_LOG_EVENT 0x20 270 | #define ASYNC_LOOP_LOG_TIMER 0x40 271 | #define ASYNC_LOOP_LOG_SEM 0x80 272 | #define ASYNC_LOOP_LOG_POST 0x100 273 | #define ASYNC_LOOP_LOG_IDLE 0x200 274 | #define ASYNC_LOOP_LOG_ONCE 0x400 275 | #define ASYNC_LOOP_LOG_USER 0x800 276 | 277 | #define ASYNC_LOOP_LOG_CUSTOMIZE(n) ((ASYNC_LOOP_LOG_USER) << (n)) 278 | 279 | 280 | //--------------------------------------------------------------------- 281 | // CAsyncLoop - centralized event manager and dispatcher 282 | //--------------------------------------------------------------------- 283 | 284 | // CAsyncLoop ctor 285 | CAsyncLoop* async_loop_new(void); 286 | 287 | // CAsyncLoop dtor 288 | void async_loop_delete(CAsyncLoop *loop); 289 | 290 | // Run an iteration, receive available events and dispatch them 291 | int async_loop_once(CAsyncLoop *loop, IINT32 millisec); 292 | 293 | // Run async_loop_once() repeatedly until async_loop_exit is called 294 | void async_loop_run(CAsyncLoop *loop); 295 | 296 | // Stop the loop 297 | void async_loop_exit(CAsyncLoop *loop); 298 | 299 | // setup interval (async_loop_once wait time, aka. epoll wait time) 300 | void async_loop_interval(CAsyncLoop *loop, IINT32 millisec); 301 | 302 | // write log 303 | void async_loop_log(CAsyncLoop *loop, int channel, const char *fmt, ...); 304 | 305 | 306 | //--------------------------------------------------------------------- 307 | // CAsyncEvent - for I/O events ASYNC_EVENT_READ/WRITE 308 | //--------------------------------------------------------------------- 309 | 310 | // init event 311 | void async_event_init(CAsyncEvent *evt, 312 | void (*cb)(CAsyncLoop*, CAsyncEvent*, int), 313 | int fd, int mask); 314 | 315 | // must be called when it is not started 316 | int async_event_set(CAsyncEvent *evt, int fd, int mask); 317 | 318 | // must be called when it is not started 319 | int async_event_modify(CAsyncEvent *evt, int mask); 320 | 321 | // start watching events 322 | int async_event_start(CAsyncLoop *loop, CAsyncEvent *evt); 323 | 324 | // stop watching events 325 | int async_event_stop(CAsyncLoop *loop, CAsyncEvent *evt); 326 | 327 | // returns non-zero if the event is active 328 | int async_event_active(const CAsyncEvent *evt); 329 | 330 | 331 | //--------------------------------------------------------------------- 332 | // CAsyncTimer 333 | //--------------------------------------------------------------------- 334 | 335 | // timer initialize 336 | void async_timer_init(CAsyncTimer *timer, 337 | void (*callback)(CAsyncLoop *loop, CAsyncTimer *evt)); 338 | 339 | // start timer 340 | int async_timer_start(CAsyncLoop *loop, CAsyncTimer *timer, 341 | IUINT32 period, int repeat); 342 | 343 | // stop timer 344 | int async_timer_stop(CAsyncLoop *loop, CAsyncTimer *timer); 345 | 346 | // returns non-zero if the timer is active 347 | int async_timer_active(const CAsyncTimer *timer); 348 | 349 | 350 | //--------------------------------------------------------------------- 351 | // CAsyncSemaphore - for multi-thread synchronization 352 | //--------------------------------------------------------------------- 353 | 354 | // initialize semaphore 355 | void async_sem_init(CAsyncSemaphore *sem, 356 | void (*callback)(CAsyncLoop *loop, CAsyncSemaphore *sem)); 357 | 358 | // destroy is required when the semaphore is not used 359 | void async_sem_destroy(CAsyncSemaphore *sem); 360 | 361 | // start semaphore listening 362 | int async_sem_start(CAsyncLoop *loop, CAsyncSemaphore *sem); 363 | 364 | // stop semaphore listening 365 | int async_sem_stop(CAsyncLoop *loop, CAsyncSemaphore *sem); 366 | 367 | // returns non-zero if the semaphore is active 368 | int async_sem_active(const CAsyncSemaphore *sem); 369 | 370 | // post semaphore from another thread 371 | int async_sem_post(CAsyncSemaphore *sem); 372 | 373 | 374 | //--------------------------------------------------------------------- 375 | // CAsyncPostpone - will be called at the end of an iteration 376 | //--------------------------------------------------------------------- 377 | 378 | // initialize a CAsyncPostpone object 379 | void async_post_init(CAsyncPostpone *postpone, 380 | void (*callback)(CAsyncLoop *loop, CAsyncPostpone *postpone)); 381 | 382 | // start watching postpone events 383 | int async_post_start(CAsyncLoop *loop, CAsyncPostpone *postpone); 384 | 385 | // stop watching postpone events 386 | int async_post_stop(CAsyncLoop *loop, CAsyncPostpone *postpone); 387 | 388 | // returns is the postpone is active 389 | int async_post_active(const CAsyncPostpone *postpone); 390 | 391 | 392 | //--------------------------------------------------------------------- 393 | // CAsyncIdle - will be called when the loop is idle 394 | //--------------------------------------------------------------------- 395 | 396 | // initialize a CAsyndIdle object 397 | void async_idle_init(CAsyncIdle *idle, 398 | void (*callback)(CAsyncLoop *loop, CAsyncIdle *idle)); 399 | 400 | // start watching idle events 401 | int async_idle_start(CAsyncLoop *loop, CAsyncIdle *idle); 402 | 403 | // stop watching idle events 404 | int async_idle_stop(CAsyncLoop *loop, CAsyncIdle *idle); 405 | 406 | // returns non-zero if the idle is active 407 | int async_idle_active(const CAsyncIdle *idle); 408 | 409 | 410 | //--------------------------------------------------------------------- 411 | // CAsyncOnce - will be called every iteration 412 | //--------------------------------------------------------------------- 413 | 414 | // initialize a CAsyncOnce object 415 | void async_once_init(CAsyncOnce *once, 416 | void (*callback)(CAsyncLoop *loop, CAsyncOnce *once)); 417 | 418 | // set priority for once event: ASYNC_ONCE_HIGH/NORMAL/LOW 419 | int async_once_priority(CAsyncOnce *once, int priority); 420 | 421 | // start watching once events 422 | int async_once_start(CAsyncLoop *loop, CAsyncOnce *once); 423 | 424 | // stop watching once events 425 | int async_once_stop(CAsyncLoop *loop, CAsyncOnce *once); 426 | 427 | // returns non-zero if the once is active 428 | int async_once_active(const CAsyncOnce *once); 429 | 430 | 431 | 432 | #ifdef __cplusplus 433 | } 434 | #endif 435 | 436 | #endif 437 | 438 | 439 | 440 | -------------------------------------------------------------------------------- /system/inetkcp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetkcp.h - fast ARQ protocol implementation 4 | // 5 | // skywind3000 (at) gmail.com, 2009 6 | // 7 | // NOTE: 8 | // for more information, please see the readme file 9 | // 10 | //===================================================================== 11 | #ifndef __INETKCP_H__ 12 | #define __INETKCP_H__ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "imemdata.h" 19 | 20 | 21 | 22 | //--------------------------------------------------------------------- 23 | // segment 24 | //--------------------------------------------------------------------- 25 | struct IKCPSEG 26 | { 27 | struct ILISTHEAD node; 28 | IUINT32 conv; 29 | IUINT32 cmd; 30 | IUINT32 frg; 31 | IUINT32 wnd; 32 | IUINT32 ts; 33 | IUINT32 sn; 34 | IUINT32 una; 35 | IUINT32 len; 36 | IUINT32 resendts; 37 | IUINT32 rto; 38 | IUINT32 fastack; 39 | IUINT32 xmit; 40 | char data[1]; 41 | }; 42 | 43 | 44 | //--------------------------------------------------------------------- 45 | // IKCPCB 46 | //--------------------------------------------------------------------- 47 | struct IKCPCB 48 | { 49 | IUINT32 conv, mtu, mss, state; 50 | IUINT32 snd_una, snd_nxt, rcv_nxt; 51 | IUINT32 ts_recent, ts_lastack, ssthresh; 52 | IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto; 53 | IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe; 54 | IUINT32 current, interval, ts_flush, xmit; 55 | IUINT32 nrcv_buf, nsnd_buf; 56 | IUINT32 nrcv_que, nsnd_que; 57 | IUINT32 nodelay, updated; 58 | IUINT32 ts_probe, probe_wait; 59 | IUINT32 dead_link, incr, rx_rtt; 60 | struct ILISTHEAD snd_queue; 61 | struct ILISTHEAD rcv_queue; 62 | struct ILISTHEAD snd_buf; 63 | struct ILISTHEAD rcv_buf; 64 | ib_vector *acklist; 65 | IUINT32 ackcount; 66 | void *user; 67 | char *buffer; 68 | int fastresend; 69 | int fastlimit; 70 | int nocwnd, stream; 71 | int logmask; 72 | int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user); 73 | void (*writelog)(const char *log, struct IKCPCB *kcp, void *user); 74 | }; 75 | 76 | 77 | typedef struct IKCPCB ikcpcb; 78 | 79 | #define IKCP_LOG_OUTPUT 1 80 | #define IKCP_LOG_INPUT 2 81 | #define IKCP_LOG_SEND 4 82 | #define IKCP_LOG_RECV 8 83 | #define IKCP_LOG_IN_DATA 16 84 | #define IKCP_LOG_IN_ACK 32 85 | #define IKCP_LOG_IN_PROBE 64 86 | #define IKCP_LOG_IN_WINS 128 87 | #define IKCP_LOG_OUT_DATA 256 88 | #define IKCP_LOG_OUT_ACK 512 89 | #define IKCP_LOG_OUT_PROBE 1024 90 | #define IKCP_LOG_OUT_WINS 2048 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | //--------------------------------------------------------------------- 97 | // interface 98 | //--------------------------------------------------------------------- 99 | 100 | // create a new kcp control object, 'conv' must equal in two endpoint 101 | // from the same connection. 'user' will be passed to the output callback 102 | // output callback can be setup like this: 'kcp->output = my_udp_output' 103 | ikcpcb* ikcp_create(IUINT32 conv, void *user); 104 | 105 | // release kcp control object 106 | void ikcp_release(ikcpcb *kcp); 107 | 108 | // user/upper level recv: returns size, returns below zero for EAGAIN 109 | int ikcp_recv(ikcpcb *kcp, char *buffer, int len); 110 | 111 | // user/upper level send, returns below zero for error 112 | int ikcp_send(ikcpcb *kcp, const char *buffer, int len); 113 | 114 | // update state (call it repeatedly, every 10ms-100ms), or you can ask 115 | // ikcp_check when to call it again (without ikcp_input/_send calling). 116 | // 'current' - current timestamp in millisec. 117 | void ikcp_update(ikcpcb *kcp, IUINT32 current); 118 | 119 | // Determine when should you invoke ikcp_update: 120 | // returns when you should invoke ikcp_update in millisec, if there 121 | // is no ikcp_input/_send calling. you can call ikcp_update in that 122 | // time, instead of call update repeatly. 123 | // Important to reduce unnacessary ikcp_update invoking. use it to 124 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 125 | // or optimize ikcp_update when handling massive kcp connections) 126 | IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current); 127 | 128 | // when you received a low level packet (eg. UDP packet), call it 129 | int ikcp_input(ikcpcb *kcp, const char *data, long size); 130 | void ikcp_flush(ikcpcb *kcp); 131 | 132 | int ikcp_peeksize(const ikcpcb *kcp); 133 | 134 | // change MTU size, default is 1400 135 | int ikcp_setmtu(ikcpcb *kcp, int mtu); 136 | 137 | // set maximum window size: sndwnd=32, rcvwnd=32 by default 138 | int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); 139 | 140 | // get how many packet is waiting to be sent 141 | int ikcp_waitsnd(const ikcpcb *kcp); 142 | 143 | // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) 144 | // nodelay: 0:disable(default), 1:enable 145 | // interval: internal update timer interval in millisec, default is 100ms 146 | // resend: 0:disable fast resend(default), 1:enable fast resend 147 | // nc: 0:normal congestion control(default), 1:disable congestion control 148 | int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc); 149 | 150 | 151 | void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...); 152 | 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif 159 | 160 | 161 | -------------------------------------------------------------------------------- /system/inetkit.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetkit.h - 4 | // 5 | // Created by skywind on 2016/07/20 6 | // Last Modified: 2025/04/20 11:18:35 7 | // 8 | //===================================================================== 9 | #ifndef _INETKIT_H_ 10 | #define _INETKIT_H_ 11 | 12 | #include 13 | 14 | #include "inetbase.h" 15 | #include "inetevt.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | //--------------------------------------------------------------------- 23 | // Global Definition 24 | //--------------------------------------------------------------------- 25 | struct CAsyncStream; 26 | struct CAsyncListener; 27 | struct CAsyncSplit; 28 | struct CAsyncUdp; 29 | struct CAsyncMessage; 30 | 31 | typedef struct CAsyncStream CAsyncStream; 32 | typedef struct CAsyncListener CAsyncListener; 33 | typedef struct CAsyncSplit CAsyncSplit; 34 | typedef struct CAsyncUdp CAsyncUdp; 35 | typedef struct CAsyncMessage CAsyncMessage; 36 | 37 | #define ASYNC_LOOP_LOG_STREAM ASYNC_LOOP_LOG_CUSTOMIZE(0) 38 | #define ASYNC_LOOP_LOG_TCP ASYNC_LOOP_LOG_CUSTOMIZE(1) 39 | #define ASYNC_LOOP_LOG_LISTENER ASYNC_LOOP_LOG_CUSTOMIZE(2) 40 | #define ASYNC_LOOP_LOG_SPLIT ASYNC_LOOP_LOG_CUSTOMIZE(3) 41 | #define ASYNC_LOOP_LOG_UDP ASYNC_LOOP_LOG_CUSTOMIZE(4) 42 | #define ASYNC_LOOP_LOG_MSG ASYNC_LOOP_LOG_CUSTOMIZE(5) 43 | 44 | #define ASYNC_LOOP_LOG_NEXT(n) ASYNC_LOOP_LOG_CUSTOMIZE((n) + 6) 45 | 46 | 47 | //--------------------------------------------------------------------- 48 | // CAsyncStream 49 | //--------------------------------------------------------------------- 50 | struct CAsyncStream { 51 | IUINT32 name; // stream name, fourcc code 52 | CAsyncLoop *loop; // AsyncLoop object 53 | CAsyncStream *underlying; // underlying stream 54 | int underown; // close underlying stream when closed 55 | long hiwater; // high water mark, 0 means no limit 56 | long lowater; // low water mark, 0 means no limit, optional 57 | int state; // state, 0: closed, 1: connecting, 2: estab 58 | int direction; // 1: input, 2: output, 3: bidirectional 59 | int eof; // 1: input, 2: output, 3: both 60 | int error; // error code, 0 means no error 61 | int enabled; // enabled events, ASYNC_EVENT_READ 62 | void *instance; // instance data, for stream implementations 63 | void *user; // user data 64 | void (*callback)(CAsyncStream *self, int event, int args); 65 | void (*close)(CAsyncStream *self); 66 | long (*read)(CAsyncStream *self, void *ptr, long size); 67 | long (*write)(CAsyncStream *self, const void *ptr, long size); 68 | long (*peek)(CAsyncStream *self, void *ptr, long size); 69 | void (*enable)(CAsyncStream *self, int event); 70 | void (*disable)(CAsyncStream *self, int event); 71 | long (*remain)(const CAsyncStream *self); 72 | long (*pending)(const CAsyncStream *self); 73 | void (*watermark)(CAsyncStream *self, long hiwater, long lowater); 74 | long (*option)(CAsyncStream *self, int option, long value); 75 | }; 76 | 77 | 78 | // for stream->direction 79 | #define ASYNC_STREAM_INPUT 1 80 | #define ASYNC_STREAM_OUTPUT 2 81 | #define ASYNC_STREAM_BOTH 3 82 | 83 | // for stream->state 84 | #define ASYNC_STREAM_CLOSED 0 85 | #define ASYNC_STREAM_CONNECTING 1 86 | #define ASYNC_STREAM_ESTAB 2 87 | 88 | // fast inline functions 89 | #define _async_stream_close(s) (s)->close(s) 90 | #define _async_stream_read(s, p, n) (s)->read(s, p, n) 91 | #define _async_stream_write(s, p, n) (s)->write(s, p, n) 92 | #define _async_stream_peek(s, p, n) (s)->peek(s, p, n) 93 | #define _async_stream_enable(s, e) (s)->enable(s, e) 94 | #define _async_stream_disable(s, e) (s)->disable(s, e) 95 | #define _async_stream_remain(s) (s)->remain(s) 96 | #define _async_stream_pending(s) (s)->pending(s) 97 | #define _async_stream_watermark(s, h, l) (s)->watermark(s, h, l) 98 | #define _async_stream_option(s, o, v) (s)->option(s, o, v) 99 | 100 | #define async_stream_private(s, type) ((type*)((s)->instance)) 101 | #define async_stream_upcast(s, type, member) IB_ENTRY(s, type, member) 102 | 103 | #define async_stream_can_read(s) ((s)->direction & ASYNC_STREAM_INPUT) 104 | #define async_stream_can_write(s) ((s)->direction & ASYNC_STREAM_OUTPUT) 105 | #define async_stream_eof_read(s) ((s)->eof & ASYNC_STREAM_INPUT) 106 | #define async_stream_eof_write(s) ((s)->eof & ASYNC_STREAM_OUTPUT) 107 | 108 | #define ASYNC_STREAM_EVT_ESTAB 0x01 109 | #define ASYNC_STREAM_EVT_EOF 0x02 110 | #define ASYNC_STREAM_EVT_ERROR 0x04 111 | #define ASYNC_STREAM_EVT_READING 0x08 112 | #define ASYNC_STREAM_EVT_WRITING 0x10 113 | 114 | #define ASYNC_STREAM_NAME(c1, c2, c3, c4) \ 115 | ((IUINT32)( (((IUINT32)(c1)) << 0) | \ 116 | (((IUINT32)(c2)) << 8) | \ 117 | (((IUINT32)(c3)) << 16) | \ 118 | (((IUINT32)(c4)) << 24) )) 119 | 120 | // clear stream data 121 | void async_stream_zero(CAsyncStream *stream); 122 | 123 | // release and close stream 124 | void async_stream_close(CAsyncStream *stream); 125 | 126 | 127 | // read data from input buffer 128 | long async_stream_read(CAsyncStream *stream, void *ptr, long size); 129 | 130 | // write data into output buffer 131 | long async_stream_write(CAsyncStream *stream, const void *ptr, long size); 132 | 133 | // peek data from input buffer without removing them 134 | long async_stream_peek(CAsyncStream *stream, void *ptr, long size); 135 | 136 | // enable ASYNC_EVENT_READ/WRITE 137 | void async_stream_enable(CAsyncStream *stream, int event); 138 | 139 | // disable ASYNC_EVENT_READ/WRITE 140 | void async_stream_disable(CAsyncStream *stream, int event); 141 | 142 | // how many bytes available in the input buffer 143 | long async_stream_remain(const CAsyncStream *stream); 144 | 145 | // how many bytes pending in the output buffer 146 | long async_stream_pending(const CAsyncStream *stream); 147 | 148 | // set input watermark, 0 means no limit, below zero means skip 149 | void async_stream_watermark(CAsyncStream *stream, long high, long low); 150 | 151 | // set/get option 152 | long async_stream_option(CAsyncStream *stream, int option, long value); 153 | 154 | // get name, buffer must be at least 5 bytes 155 | const char *async_stream_name(const CAsyncStream *stream, char *buffer); 156 | 157 | 158 | 159 | //--------------------------------------------------------------------- 160 | // Pair Stream 161 | //--------------------------------------------------------------------- 162 | #define ASYNC_STREAM_NAME_PAIR ASYNC_STREAM_NAME('P', 'A', 'I', 'R') 163 | 164 | // create a paired stream, 165 | int async_stream_pair_new(CAsyncLoop *loop, CAsyncStream *pair[2]); 166 | 167 | // get partner stream 168 | CAsyncStream *async_stream_pair_partner(CAsyncStream *stream); 169 | 170 | 171 | //--------------------------------------------------------------------- 172 | // TCP Stream 173 | //--------------------------------------------------------------------- 174 | 175 | #define ASYNC_STREAM_NAME_TCP ASYNC_STREAM_NAME('T', 'C', 'P', 'S') 176 | 177 | 178 | // create a TCP stream and connect to remote address 179 | CAsyncStream *async_stream_tcp_connect(CAsyncLoop *loop, 180 | void (*callback)(CAsyncStream *stream, int event, int args), 181 | const struct sockaddr *remote, int addrlen); 182 | 183 | // create a TCP stream and assign an existing socket 184 | CAsyncStream *async_stream_tcp_assign(CAsyncLoop *loop, 185 | void (*callback)(CAsyncStream *stream, int event, int args), 186 | int fd, int estab); 187 | 188 | #define ASYNC_STREAM_OPT_TCP_MASK 0x3f010000 189 | #define ASYNC_STREAM_OPT_TCP_GETFD (ASYNC_STREAM_OPT_TCP_MASK | 1) 190 | #define ASYNC_STREAM_OPT_TCP_NODELAY (ASYNC_STREAM_OPT_TCP_MASK | 2) 191 | 192 | // move data from recv buffer to send buffer 193 | long async_stream_tcp_move(CAsyncStream *stream, long size); 194 | 195 | // get the underlying socket fd, returns -1 if not a TCP stream 196 | int async_stream_tcp_getfd(const CAsyncStream *stream); 197 | 198 | 199 | //--------------------------------------------------------------------- 200 | // Underlying Passthrough 201 | //--------------------------------------------------------------------- 202 | 203 | long async_stream_pass_read(CAsyncStream *stream, void *ptr, long size); 204 | long async_stream_pass_write(CAsyncStream *stream, const void *ptr, long size); 205 | long async_stream_pass_peek(CAsyncStream *stream, void *ptr, long size); 206 | void async_stream_pass_enable(CAsyncStream *stream, int event); 207 | void async_stream_pass_disable(CAsyncStream *stream, int event); 208 | long async_stream_pass_remain(const CAsyncStream *stream); 209 | long async_stream_pass_pending(const CAsyncStream *stream); 210 | void async_stream_pass_watermark(CAsyncStream *stream, long high, long low); 211 | long async_stream_pass_option(CAsyncStream *stream, int option, long value); 212 | 213 | 214 | 215 | //===================================================================== 216 | // CAsyncListener 217 | //===================================================================== 218 | struct CAsyncListener { 219 | int fd; 220 | int error; 221 | int family; 222 | void *user; 223 | CAsyncLoop *loop; 224 | CAsyncEvent evt_read; 225 | void (*callback)(CAsyncListener *listener, int fd, 226 | const struct sockaddr *addr, int len); 227 | void (*errorcb)(CAsyncListener *listener, int error); 228 | }; 229 | 230 | 231 | //--------------------------------------------------------------------- 232 | // listener management 233 | //--------------------------------------------------------------------- 234 | 235 | // create a new listener 236 | CAsyncListener *async_listener_new(CAsyncLoop *loop, 237 | void (*callback)(CAsyncListener *listener, int fd, 238 | const struct sockaddr *addr, int len)); 239 | 240 | // delete listener 241 | void async_listener_delete(CAsyncListener *listener); 242 | 243 | #define ASYNC_LISTENER_REUSEPORT 0x01 244 | #define ASYNC_LISTENER_IPV6ONLY 0x02 245 | 246 | // start listening on the socket 247 | int async_listener_start(CAsyncListener *listener, int backlog, 248 | int flags, const struct sockaddr *addr, int addrlen); 249 | 250 | // stop listening 251 | void async_listener_stop(CAsyncListener *listener); 252 | 253 | // pause/resume accepting new connections when argument pause is 1/0 254 | void async_listener_pause(CAsyncListener *listener, int pause); 255 | 256 | 257 | //--------------------------------------------------------------------- 258 | // CAsyncSplit 259 | //--------------------------------------------------------------------- 260 | struct CAsyncSplit { 261 | CAsyncLoop *loop; 262 | CAsyncStream *stream; 263 | int borrow; 264 | int header; 265 | int busy; 266 | int releasing; 267 | int error; 268 | void *user; 269 | struct IMSTREAM linesplit; 270 | struct IMSTREAM linecache; 271 | void (*callback)(CAsyncSplit *split, int event); 272 | void (*receiver)(CAsyncSplit *split, void *data, long size); 273 | }; 274 | 275 | 276 | #define ASYNC_SPLIT_WORDLSB 0 // header: 2 bytes LSB 277 | #define ASYNC_SPLIT_WORDMSB 1 // header: 2 bytes MSB 278 | #define ASYNC_SPLIT_DWORDLSB 2 // header: 4 bytes LSB 279 | #define ASYNC_SPLIT_DWORDMSB 3 // header: 4 bytes MSB 280 | #define ASYNC_SPLIT_BYTELSB 4 // header: 1 byte LSB 281 | #define ASYNC_SPLIT_BYTEMSB 5 // header: 1 byte MSB 282 | #define ASYNC_SPLIT_EWORDLSB 6 // header: 2 bytes LSB (exclude self) 283 | #define ASYNC_SPLIT_EWORDMSB 7 // header: 2 bytes MSB (exclude self) 284 | #define ASYNC_SPLIT_EDWORDLSB 8 // header: 4 bytes LSB (exclude self) 285 | #define ASYNC_SPLIT_EDWORDMSB 9 // header: 4 bytes MSB (exclude self) 286 | #define ASYNC_SPLIT_EBYTELSB 10 // header: 1 byte LSB (exclude self) 287 | #define ASYNC_SPLIT_EBYTEMSB 11 // header: 1 byte MSB (exclude self) 288 | #define ASYNC_SPLIT_DWORDMASK 12 // header: 4 bytes LSB (self and mask) 289 | #define ASYNC_SPLIT_LINESPLIT 13 // header: '\n' split 290 | #define ASYNC_SPLIT_PREMITIVE 14 // header: raw data in premitive mode 291 | 292 | 293 | //--------------------------------------------------------------------- 294 | // CAsyncSplit management 295 | //--------------------------------------------------------------------- 296 | 297 | // create a new split, the new split will take over the underlying 298 | // stream, and reset its user & callback field. If borrow is set to 0, 299 | // the underlying stream will be closed in async_split_delete(). 300 | CAsyncSplit *async_split_new(CAsyncStream *stream, int header, int borrow, 301 | void (*callback)(CAsyncSplit *split, int event), 302 | void (*receiver)(CAsyncSplit *split, void *data, long size)); 303 | 304 | // delete CAsyncSplit 305 | void async_split_delete(CAsyncSplit *split); 306 | 307 | // write message 308 | void async_split_write(CAsyncSplit *split, const void *ptr, long size); 309 | 310 | // write vector 311 | void async_split_write_vector(CAsyncSplit *split, 312 | const void * const vecptr[], const long veclen[], int count); 313 | 314 | // enable ASYNC_EVENT_READ/WRITE of the underlying stream 315 | // note: ASYNC_EVENT_READ is not enabled by default 316 | void async_split_enable(CAsyncSplit *split, int event); 317 | 318 | // disable ASYNC_EVENT_READ/WRITE of the underlying stream 319 | void async_split_disable(CAsyncSplit *split, int event); 320 | 321 | 322 | //--------------------------------------------------------------------- 323 | // CAsyncUdp 324 | //--------------------------------------------------------------------- 325 | struct CAsyncUdp { 326 | int fd; 327 | int error; 328 | int enabled; 329 | int busy; 330 | int releasing; 331 | void *data; 332 | void *user; 333 | CAsyncLoop *loop; 334 | CAsyncEvent evt_read; 335 | CAsyncEvent evt_write; 336 | void (*callback)(CAsyncUdp *udp, int event, int args); 337 | void (*receiver)(CAsyncUdp *udp, void *data, long size, 338 | const struct sockaddr *addr, int addrlen); 339 | }; 340 | 341 | 342 | //--------------------------------------------------------------------- 343 | // udp management 344 | //--------------------------------------------------------------------- 345 | 346 | // create a new CAsyncUdp object 347 | CAsyncUdp *async_udp_new(CAsyncLoop *loop, 348 | void (*callback)(CAsyncUdp *udp, int event, int args)); 349 | 350 | // delete CAsyncUdp object 351 | void async_udp_delete(CAsyncUdp *udp); 352 | 353 | #define ASYNC_UDP_FLAG_REUSEPORT 0x01 354 | #define ASYNC_UDP_FLAG_V6ONLY 0x02 355 | 356 | #define ASYNC_UDP_EVT_READ 0x01 357 | #define ASYNC_UDP_EVT_WRITE 0x02 358 | 359 | // open an udp socket 360 | int async_udp_open(CAsyncUdp *udp, const struct sockaddr *addr, int addrlen, int flags); 361 | 362 | // assign an existing socket 363 | int async_udp_assign(CAsyncUdp *udp, int fd); 364 | 365 | // close udp 366 | void async_udp_close(CAsyncUdp *udp); 367 | 368 | // enable ASYNC_EVENT_READ/WRITE 369 | void async_udp_enable(CAsyncUdp *udp, int event); 370 | 371 | // disable ASYNC_EVENT_READ/WRITE 372 | void async_udp_disable(CAsyncUdp *udp, int event); 373 | 374 | // send data 375 | int async_udp_sendto(CAsyncUdp *udp, const void *ptr, long size, 376 | const struct sockaddr *addr, int addrlen); 377 | 378 | // receive from 379 | int async_udp_recvfrom(CAsyncUdp *udp, void *ptr, long size, 380 | struct sockaddr *addr, int *addrlen); 381 | 382 | 383 | //--------------------------------------------------------------------- 384 | // CAsyncMessage - receive messages from another thread 385 | //--------------------------------------------------------------------- 386 | struct CAsyncMessage { 387 | CAsyncLoop *loop; 388 | CAsyncSemaphore evt_sem; 389 | void *user; 390 | int signaled; 391 | int busy; 392 | int releasing; 393 | volatile int active; 394 | IINT64 num_sem_post; 395 | IINT64 num_msg_post; 396 | IINT64 num_msg_read; 397 | IMUTEX_TYPE lock; 398 | struct IMSTREAM queue; 399 | int (*callback)(CAsyncMessage *message, int mid, 400 | IINT32 wparam, IINT32 lparam, const void *ptr, int size); 401 | }; 402 | 403 | 404 | //--------------------------------------------------------------------- 405 | // async message management 406 | //--------------------------------------------------------------------- 407 | 408 | // create a new message 409 | CAsyncMessage *async_msg_new(CAsyncLoop *loop, 410 | int (*callback)(CAsyncMessage *msg, int mid, IINT32 wparam, 411 | IINT32 lparam, const void *ptr, int size)); 412 | 413 | // delete message 414 | void async_msg_delete(CAsyncMessage *msg); 415 | 416 | // start message listening 417 | int async_msg_start(CAsyncMessage *msg); 418 | 419 | // stop message listening 420 | int async_msg_stop(CAsyncMessage *msg); 421 | 422 | // post message from another thread 423 | int async_msg_post(CAsyncMessage *msg, int mid, 424 | IINT32 wparam, IINT32 lparam, const void *ptr, int size); 425 | 426 | 427 | 428 | #ifdef __cplusplus 429 | } 430 | #endif 431 | 432 | 433 | #endif 434 | 435 | 436 | 437 | -------------------------------------------------------------------------------- /system/inetnot.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetnot.h - AsyncNotify implementation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __INETNOT_H__ 11 | #define __INETNOT_H__ 12 | 13 | #include "imemdata.h" 14 | #include "inetcode.h" 15 | 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | //===================================================================== 23 | // CAsyncNotify 24 | //===================================================================== 25 | struct CAsyncNotify; 26 | typedef struct CAsyncNotify CAsyncNotify; 27 | 28 | 29 | //===================================================================== 30 | // interfaces 31 | //===================================================================== 32 | 33 | // create object 34 | CAsyncNotify* async_notify_new(CAsyncLoop *loop, int serverid); 35 | 36 | // delete object 37 | void async_notify_delete(CAsyncNotify *notify); 38 | 39 | 40 | #define ASYNC_NOTIFY_EVT_DATA 1 // (wp=sid, lp=cmd) 41 | #define ASYNC_NOTIFY_EVT_NEW_IN 2 // (wp=sid, lp=hid) 42 | #define ASYNC_NOTIFY_EVT_NEW_OUT 4 // (wp=sid, lp=hid) 43 | #define ASYNC_NOTIFY_EVT_CLOSED_IN 8 // (wp=sid, lp=hid) 44 | #define ASYNC_NOTIFY_EVT_CLOSED_OUT 16 // (wp=sid, lp=hid) 45 | #define ASYNC_NOTIFY_EVT_ERROR 32 // (wp=sid, lp=why) 46 | #define ASYNC_NOTIFY_EVT_CORE 64 47 | 48 | // wait events 49 | void async_notify_wait(CAsyncNotify *notify, IUINT32 millisec); 50 | 51 | // wake-up from waiting 52 | void async_notify_wake(CAsyncNotify *notify); 53 | 54 | // read events, returns data length of the message, 55 | // and returns -1 for no event, -2 for buffer size too small, 56 | // returns data size when data equals NULL. 57 | long async_notify_read(CAsyncNotify *notify, int *event, long *wparam, 58 | long *lparam, void *data, long maxsize); 59 | 60 | 61 | // new listen: return id(-1 error, -2 port conflict), flag&1(reuse) 62 | long async_notify_listen(CAsyncNotify *notify, const struct sockaddr *addr, 63 | int addrlen, int flag); 64 | 65 | // remove listening port 66 | int async_notify_remove(CAsyncNotify *notify, long listenid, int code); 67 | 68 | // setup self server id 69 | void async_notify_change(CAsyncNotify *notify, int new_server_id); 70 | 71 | 72 | // send message to server 73 | int async_notify_send(CAsyncNotify *notify, int sid, short cmd, 74 | const void *data, long size); 75 | 76 | // close server connection 77 | int async_notify_close(CAsyncNotify *notify, int sid, int mode, int code); 78 | 79 | // get listening port 80 | int async_notify_get_port(CAsyncNotify *notify, long listenid); 81 | 82 | 83 | // clear ip allow table 84 | void async_notify_allow_clear(CAsyncNotify *notify); 85 | 86 | // add or update ip in allow table 87 | void async_notify_allow_add(CAsyncNotify *notify, const void *ip, int size); 88 | 89 | // remove ip from table 90 | void async_notify_allow_del(CAsyncNotify *notify, const void *ip, int size); 91 | 92 | // ip table enable: enable is 0(disable allow table) otherwise(enable) 93 | void async_notify_allow_enable(CAsyncNotify *notify, int enable); 94 | 95 | 96 | // add or update a sid into sid2addr 97 | void async_notify_sid_add(CAsyncNotify *notify, int sid, 98 | const struct sockaddr *remote, int size); 99 | 100 | // add or update a sid into sid2addr 101 | void async_notify_sid_del(CAsyncNotify *notify, int sid); 102 | 103 | // list sids into an array 104 | int async_notify_sid_list(CAsyncNotify *notify, int *sids, int maxsize); 105 | 106 | // sid clear 107 | void async_notify_sid_clear(CAsyncNotify *notify); 108 | 109 | 110 | #define ASYNC_NOTIFY_OPT_PROFILE 0 111 | #define ASYNC_NOTIFY_OPT_TIMEOUT_IDLE 1 112 | #define ASYNC_NOTIFY_OPT_TIMEOUT_PING 2 113 | #define ASYNC_NOTIFY_OPT_SOCK_KEEPALIVE 3 114 | #define ASYNC_NOTIFY_OPT_SND_BUFSIZE 4 115 | #define ASYNC_NOTIFY_OPT_RCV_BUFSIZE 5 116 | #define ASYNC_NOTIFY_OPT_BUFFER_LIMIT 6 117 | #define ASYNC_NOTIFY_OPT_SIGN_TIMEOUT 7 118 | #define ASYNC_NOTIFY_OPT_RETRY_TIMEOUT 8 119 | #define ASYNC_NOTIFY_OPT_NET_TIMEOUT 9 120 | #define ASYNC_NOTIFY_OPT_EVT_MASK 10 121 | #define ASYNC_NOTIFY_OPT_LOG_MASK 11 122 | #define ASYNC_NOTIFY_OPT_GET_PING 12 123 | #define ASYNC_NOTIFY_OPT_GET_OUT_COUNT 13 124 | #define ASYNC_NOTIFY_OPT_GET_IN_COUNT 14 125 | 126 | #define ASYNC_NOTIFY_LOG_INFO 1 127 | #define ASYNC_NOTIFY_LOG_REJECT 2 128 | #define ASYNC_NOTIFY_LOG_ERROR 4 129 | #define ASYNC_NOTIFY_LOG_WARNING 8 130 | #define ASYNC_NOTIFY_LOG_DEBUG 16 131 | 132 | 133 | // config 134 | int async_notify_option(CAsyncNotify *notify, int type, long value); 135 | 136 | // set login token 137 | void async_notify_token(CAsyncNotify *notify, const char *token, int size); 138 | 139 | 140 | // set log function 141 | typedef void (*CAsyncNotify_WriteLog)(const char *text, void *user); 142 | 143 | // set new function and return old one 144 | void *async_notify_install(CAsyncNotify *notify, CAsyncNotify_WriteLog func); 145 | 146 | // set new function and return old one 147 | void *async_notify_user(CAsyncNotify *notify, void *user); 148 | 149 | 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | 154 | 155 | #endif 156 | 157 | 158 | -------------------------------------------------------------------------------- /system/inetsub.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inetsub.h - 4 | // 5 | // Last Modified: 2025/06/10 11:08:09 6 | // 7 | //===================================================================== 8 | #ifndef _INETSUB_H_ 9 | #define _INETSUB_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "inetevt.h" 15 | #include "inetkit.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | //--------------------------------------------------------------------- 22 | // Global Definition 23 | //--------------------------------------------------------------------- 24 | struct CAsyncTopic; 25 | struct CAsyncSubscribe; 26 | struct CAsyncSignal; 27 | typedef struct CAsyncTopic CAsyncTopic; 28 | typedef struct CAsyncSubscribe CAsyncSubscribe; 29 | typedef struct CAsyncSignal CAsyncSignal; 30 | 31 | 32 | //--------------------------------------------------------------------- 33 | // AsyncTopic/Subscribe 34 | //--------------------------------------------------------------------- 35 | struct CAsyncTopic { 36 | CAsyncLoop *loop; 37 | CAsyncPostpone evt_postpone; 38 | int busy; 39 | int releasing; 40 | struct IMSTREAM queue; 41 | struct ib_array *pendings; 42 | struct ib_fastbin allocator; 43 | struct ib_hash_map hash_map; 44 | }; 45 | 46 | struct CAsyncSubscribe { 47 | CAsyncTopic *topic; 48 | ilist_head node; 49 | int pending; 50 | int tid; 51 | void *user; 52 | int (*callback)(CAsyncSubscribe *sub, IINT32 wparam, 53 | IINT32 lparam, const void *ptr, int size); 54 | }; 55 | 56 | 57 | //--------------------------------------------------------------------- 58 | // topic subscribe management 59 | //--------------------------------------------------------------------- 60 | 61 | // create a new topic object 62 | CAsyncTopic *async_topic_new(CAsyncLoop *loop); 63 | 64 | // delete topic object 65 | void async_topic_delete(CAsyncTopic *topic); 66 | 67 | // publish a message 68 | void async_topic_publish(CAsyncTopic *topic, int tid, 69 | IINT32 wparam, IINT32 lparam, const void *ptr, int size); 70 | 71 | // initialize a new subscriber 72 | void async_sub_init(CAsyncSubscribe *sub, int (*callback) 73 | (CAsyncSubscribe *sub, IINT32 wparam, IINT32 lparam, 74 | const void *ptr, int size)); 75 | 76 | // check activate 77 | #define async_sub_is_active(sub) ((sub)->topic != NULL) 78 | 79 | // register a subscriber to a topic 80 | void async_sub_register(CAsyncTopic *topic, CAsyncSubscribe *sub, int tid); 81 | 82 | // unregister a subscriber from a topic 83 | void async_sub_deregister(CAsyncSubscribe *sub); 84 | 85 | 86 | //--------------------------------------------------------------------- 87 | // CAsyncSignal 88 | //--------------------------------------------------------------------- 89 | #define CASYNC_SIGNAL_MAX 256 90 | struct CAsyncSignal { 91 | void (*callback)(CAsyncSignal *signal, int signum); 92 | int fd_reader; 93 | int fd_writer; 94 | CAsyncEvent evt_read; 95 | CAsyncLoop *loop; 96 | void *user; 97 | int active; 98 | int installed[CASYNC_SIGNAL_MAX]; 99 | volatile int signaled[CASYNC_SIGNAL_MAX]; 100 | }; 101 | 102 | 103 | // create a new signal object 104 | CAsyncSignal *async_signal_new(CAsyncLoop *loop, 105 | void (*callback)(CAsyncSignal *signal, int signum)); 106 | 107 | // delete signal object 108 | void async_signal_delete(CAsyncSignal *sig); 109 | 110 | // start wating system signals, only one CAsyncSignal 111 | // can be started at the same time. 112 | int async_signal_start(CAsyncSignal *sig); 113 | 114 | // stop from the system signal interface 115 | int async_signal_stop(CAsyncSignal *sig); 116 | 117 | // install a system signal 118 | int async_signal_install(CAsyncSignal *sig, int signum); 119 | 120 | // ignore a system signal 121 | int async_signal_ignore(CAsyncSignal *sig, int signum); 122 | 123 | // remove a system signal 124 | int async_signal_remove(CAsyncSignal *sig, int signum); 125 | 126 | // install default handler for a CAsyncLoop 127 | int async_signal_default(CAsyncLoop *loop); 128 | 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | #endif 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /system/inettcp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // inettcp.h - simple tcp protocol implementation 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __INETNTCP_H__ 11 | #define __INETNTCP_H__ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "imemdata.h" 18 | 19 | 20 | //===================================================================== 21 | // GLOBAL DEFINITION 22 | //===================================================================== 23 | #ifndef __IUINT32_DEFINED 24 | #define __IUINT32_DEFINED 25 | typedef unsigned long IUINT32; 26 | #endif 27 | 28 | #ifndef __IUINT16_DEFINED 29 | #define __IUINT16_DEFINED 30 | typedef unsigned short IUINT16; 31 | #endif 32 | 33 | #ifndef __IUINT8_DEFINED 34 | #define __IUINT8_DEFINED 35 | typedef unsigned char IUINT8; 36 | #endif 37 | 38 | 39 | #define ITCP_LISTEN 0 40 | #define ITCP_SYN_SENT 1 41 | #define ITCP_SYN_RECV 2 42 | #define ITCP_ESTAB 3 43 | #define ITCP_CLOSED 4 44 | 45 | #define IOUTPUT_OK 0 46 | #define IOUTPUT_BLOCKING 1 47 | #define IOUTPUT_TOOLARGE 2 48 | #define IOUTPUT_FAILED 3 49 | 50 | #define ISOCKERR -1 51 | #define IEINVAL 1001 52 | #define IENOTCONN 1002 53 | #define IEWOULDBLOCK 1003 54 | #define IECONNABORTED 1004 55 | #define IECONNREST 1005 56 | #define IEFATAL 1006 57 | 58 | #define ILOG_STATE 1 59 | #define ILOG_INFO 2 60 | #define ILOG_WARN 4 61 | #define ILOG_WINDOW 8 62 | #define ILOG_PACKET 16 63 | #define ILOG_RTT 32 64 | #define ILOG_ACK 64 65 | #define ILOG_DEBUG 128 66 | 67 | #define ITCP_CIRCLE 68 | 69 | 70 | #ifndef ASSERT 71 | #define ASSERT(x) assert((x)) 72 | #endif 73 | 74 | //--------------------------------------------------------------------- 75 | // Data Segment 76 | //--------------------------------------------------------------------- 77 | struct ISEGMENT 78 | { 79 | IUINT32 conv, seq, ack; 80 | IUINT32 wnd; 81 | IUINT16 flags; 82 | IUINT32 tsval, tsecr; 83 | IUINT32 len; 84 | char *data; 85 | }; 86 | 87 | //--------------------------------------------------------------------- 88 | // Output Segment 89 | //--------------------------------------------------------------------- 90 | struct ISEGOUT 91 | { 92 | ilist_head head; 93 | IUINT32 seq; 94 | IUINT32 len; 95 | IUINT16 xmit; 96 | IUINT16 bctl; 97 | }; 98 | 99 | //--------------------------------------------------------------------- 100 | // Input Segment 101 | //--------------------------------------------------------------------- 102 | struct ISEGIN 103 | { 104 | ilist_head head; 105 | IUINT32 seq, len; 106 | }; 107 | 108 | typedef struct ISEGMENT ISEGMENT; 109 | typedef struct ISEGOUT ISEGOUT; 110 | typedef struct ISEGIN ISEGIN; 111 | 112 | 113 | 114 | //--------------------------------------------------------------------- 115 | // TCP CONTROL BLOCK 116 | //--------------------------------------------------------------------- 117 | struct ITCPCB 118 | { 119 | IUINT32 conv, state; 120 | IUINT32 current; 121 | IUINT32 last_traffic; 122 | IUINT32 buf_size; 123 | 124 | IUINT32 snd_una, snd_nxt, snd_wnd, last_send, slen; 125 | ilist_head slist; 126 | struct IRING scache; 127 | char *sbuf; 128 | 129 | IUINT32 rcv_nxt, rcv_wnd, last_recv, rlen; 130 | ilist_head rlist; 131 | struct IRING rcache; 132 | char *rbuf; 133 | 134 | IUINT32 mtu, mss, omtu, largest; 135 | 136 | IUINT32 rto_base; 137 | int be_outgoing; 138 | IUINT32 ts_recent, ts_lastack, ts_acklocal; 139 | 140 | ilist_head sfree; 141 | int free_cnt; 142 | int free_max; 143 | char *buffer; 144 | 145 | long rx_rttval, rx_srtt, rx_rto, rx_minrto, rx_rtt; 146 | long rx_ackdelay; 147 | 148 | int be_readable; 149 | int be_writeable; 150 | int keepalive; 151 | int shutdown; 152 | int nodelay; 153 | 154 | IUINT32 ssthresh, cwnd; 155 | IUINT32 dup_acks; 156 | IUINT32 recover; 157 | IUINT32 t_ack; 158 | 159 | void *user; 160 | void *extra; 161 | int errcode, logmask, id; 162 | char *errmsg; 163 | 164 | int (*output)(const char *buf, int len, struct ITCPCB *tcp, void *user); 165 | int (*onopen)(struct ITCPCB *, void *user); 166 | int (*onclose)(struct ITCPCB *, void *user, int code); 167 | int (*oncanread)(struct ITCPCB *, void *user); 168 | int (*oncanwrite)(struct ITCPCB *, void *user); 169 | int (*writelog)(const char *log); 170 | }; 171 | 172 | 173 | typedef struct ITCPCB itcpcb; 174 | 175 | #ifdef __cplusplus 176 | extern "C" { 177 | #endif 178 | 179 | //--------------------------------------------------------------------- 180 | // TCP USER INTERFACE 181 | //--------------------------------------------------------------------- 182 | itcpcb *itcp_create(IUINT32 conv, const void *user); 183 | void itcp_release(itcpcb *tcp); 184 | 185 | int itcp_connect(itcpcb *tcp); 186 | void itcp_close(itcpcb *tcp); 187 | 188 | long itcp_recv(itcpcb *tcp, char *buffer, long len); 189 | long itcp_send(itcpcb *tcp, const char *buffer, long len); 190 | 191 | void itcp_update(itcpcb *tcp, IUINT32 millisec); 192 | int itcp_check(itcpcb *tcp); 193 | int itcp_input(itcpcb *tcp, const char *data, long size); 194 | void itcp_setmtu(itcpcb *tcp, long mtu); 195 | 196 | int itcp_setbuf(itcpcb *tcp, long bufsize); 197 | 198 | long itcp_dsize(const itcpcb *tcp); 199 | long itcp_peek(itcpcb *tcp, char *buffer, long len); 200 | long itcp_canwrite(const itcpcb *tcp); 201 | 202 | void itcp_option(itcpcb *tcp, int nodelay, int keepalive); 203 | 204 | 205 | 206 | #ifdef __cplusplus 207 | } 208 | #endif 209 | 210 | 211 | #endif 212 | 213 | 214 | -------------------------------------------------------------------------------- /system/ineturl.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ineturl.h - urllib 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #ifndef __INETURL_H__ 10 | #define __INETURL_H__ 11 | 12 | #include "imemdata.h" 13 | #include "inetbase.h" 14 | #include "inetcode.h" 15 | 16 | 17 | //===================================================================== 18 | // IHTTPSOCK 19 | //===================================================================== 20 | 21 | //--------------------------------------------------------------------- 22 | // IHTTPSOCK DEFINITION 23 | //--------------------------------------------------------------------- 24 | #define IHTTPSOCK_STATE_CLOSED 0 25 | #define IHTTPSOCK_STATE_CONNECTING 1 26 | #define IHTTPSOCK_STATE_CONNECTED 2 27 | 28 | 29 | struct IHTTPSOCK 30 | { 31 | int state; 32 | int sock; 33 | char *buffer; 34 | int bufsize; 35 | int endless; 36 | int error; 37 | IINT64 blocksize; 38 | IINT64 received; 39 | IINT64 conntime; 40 | int proxy_type; 41 | char *proxy_user; 42 | char *proxy_pass; 43 | struct ISOCKPROXY *proxy; 44 | struct sockaddr proxyd; 45 | struct sockaddr remote; 46 | struct IMSTREAM sendmsg; 47 | struct IMSTREAM recvmsg; 48 | }; 49 | 50 | typedef struct IHTTPSOCK IHTTPSOCK; 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | //--------------------------------------------------------------------- 56 | // IHTTPSOCK INTERFACE 57 | //--------------------------------------------------------------------- 58 | 59 | // create a http sock 60 | IHTTPSOCK *ihttpsock_new(struct IMEMNODE *nodes); 61 | 62 | // delete a http sock 63 | void ihttpsock_delete(IHTTPSOCK *httpsock); 64 | 65 | // update http sock state 66 | void ihttpsock_update(IHTTPSOCK *httpsock); 67 | 68 | 69 | // connect to remote address 70 | int ihttpsock_connect(IHTTPSOCK *httpsock, const struct sockaddr *remote); 71 | 72 | // close connection 73 | void ihttpsock_close(IHTTPSOCK *httpsock); 74 | 75 | // set proxy, call it befor calling ihttpsock_connect 76 | int ihttpsock_proxy(IHTTPSOCK *httpsock, int type, 77 | const struct sockaddr *addr, const char *user, const char *pass); 78 | 79 | // assign to a connected socket 80 | int ihttpsock_assign(IHTTPSOCK *httpsock, int sock); 81 | 82 | 83 | // returns zero if blocked 84 | // returns below zero if connection shutdown or error 85 | // returns received data size if data received 86 | long ihttpsock_recv(IHTTPSOCK *httpsock, void *data, long size); 87 | 88 | // send data 89 | long ihttpsock_send(IHTTPSOCK *httpsock, const void *data, long size); 90 | 91 | // poll socket 92 | int ihttpsock_poll(IHTTPSOCK *httpsock, int event, int millsec); 93 | 94 | // get data size in send buffer (nbytes of data which hasn't been sent) 95 | long ihttpsock_dsize(const IHTTPSOCK *httpsock); 96 | 97 | // change buffer size 98 | void ihttpsock_bufsize(IHTTPSOCK *httpsock, long bufsize); 99 | 100 | // get socket 101 | int ihttpsock_sock(const IHTTPSOCK *httpsock); 102 | 103 | 104 | // ihttpsock_block_* functions will returns these values or data size 105 | #define IHTTPSOCK_BLOCK_AGAIN -1 106 | #define IHTTPSOCK_BLOCK_DONE -2 107 | #define IHTTPSOCK_BLOCK_CLOSED -3 108 | 109 | // set block size 110 | int ihttpsock_block_set(IHTTPSOCK *httpsock, IINT64 blocksize); 111 | 112 | // returns equal or above zero for data size 113 | // returns IHTTPSOCK_BLOCK_AGAIN for block 114 | // returns IHTTPSOCK_BLOCK_DONE for job finished 115 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 116 | long ihttpsock_block_recv(IHTTPSOCK *httpsock, void *data, long size); 117 | 118 | 119 | // returns equal or above zero for data value, 120 | // returns IHTTPSOCK_BLOCK_AGAIN for block 121 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 122 | int ihttpsock_block_getch(IHTTPSOCK *httpsock); 123 | 124 | // returns IHTTPSOCK_BLOCK_AGAIN for block 125 | // returns IHTTPSOCK_BLOCK_DONE for job finished 126 | // returns IHTTPSOCK_BLOCK_CLOSED for connection shutdown or error 127 | int ihttpsock_block_gets(IHTTPSOCK *httpsock, ivalue_t *text); 128 | 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | 135 | //===================================================================== 136 | // IHTTPLIB 137 | //===================================================================== 138 | 139 | #define IHTTP_STATE_STOP 0 140 | #define IHTTP_STATE_CONNECTING 1 141 | #define IHTTP_STATE_CONNECTED 2 142 | 143 | #define IHTTP_SENDING_STATE_WAIT 0 144 | #define IHTTP_SENDING_STATE_HEADER 1 145 | #define IHTTP_SENDING_STATE_DATA 2 146 | #define IHTTP_RECVING_STATE_WAIT 0 147 | #define IHTTP_RECVING_STATE_HEADER 1 148 | #define IHTTP_RECVING_STATE_DATA 2 149 | 150 | #define IHTTP_CHUNK_STATE_HEAD 0 151 | #define IHTTP_CHUNK_STATE_DATA 1 152 | #define IHTTP_CHUNK_STATE_TAIL 2 153 | #define IHTTP_CHUNK_STATE_DONE 3 154 | 155 | #define IHTTP_RESULT_DONE 0 156 | #define IHTTP_RESULT_NOT_STARTED 1 157 | #define IHTTP_RESULT_NOT_COMPLETED 2 158 | #define IHTTP_RESULT_NOT_FIND 3 159 | #define IHTTP_RESULT_HTTP_ERROR 4 160 | #define IHTTP_RESULT_HTTP_UNSUPPORT 5 161 | #define IHTTP_RESULT_HTTP_OUTRANGE 6 162 | #define IHTTP_RESULT_HTTP_UNAUTH 7 163 | #define IHTTP_RESULT_HTTP_REDIR301 8 164 | #define IHTTP_RESULT_HTTP_REDIR302 9 165 | #define IHTTP_RESULT_ABORTED 10 166 | #define IHTTP_RESULT_SOCK_ERROR 11 167 | #define IHTTP_RESULT_INVALID_ADDR 12 168 | #define IHTTP_RESULT_CONNECT_FAIL 13 169 | #define IHTTP_RESULT_DISCONNECTED 14 170 | 171 | 172 | 173 | //--------------------------------------------------------------------- 174 | // URL Descriptor 175 | //--------------------------------------------------------------------- 176 | struct IHTTPLIB 177 | { 178 | int state; 179 | int result; 180 | int snext; 181 | int rnext; 182 | int cnext; 183 | int shutdown; 184 | int chunked; 185 | int httpver; 186 | int nosize; 187 | int code; 188 | int keepalive; 189 | int partial; 190 | int isredirect; 191 | int proxy_type; 192 | char *proxy_user; 193 | char *proxy_pass; 194 | IINT64 clength; 195 | IINT64 chunksize; 196 | IINT64 datasize; 197 | IINT64 range_start; 198 | IINT64 range_endup; 199 | IINT64 range_size; 200 | IHTTPSOCK *sock; 201 | ivalue_t host; 202 | ivalue_t line; 203 | ivalue_t ctype; 204 | ivalue_t sheader; 205 | ivalue_t rheader; 206 | ivalue_t location; 207 | ivalue_t buffer; 208 | struct sockaddr proxyd; 209 | }; 210 | 211 | typedef struct IHTTPLIB IHTTPLIB; 212 | 213 | 214 | 215 | #ifdef __cplusplus 216 | extern "C" { 217 | #endif 218 | //--------------------------------------------------------------------- 219 | // URL Interface 220 | //--------------------------------------------------------------------- 221 | IHTTPLIB *ihttplib_new(void); 222 | 223 | void ihttplib_delete(IHTTPLIB *http); 224 | 225 | int ihttplib_open(IHTTPLIB *http, const char *HOST); 226 | 227 | int ihttplib_close(IHTTPLIB *http); 228 | 229 | int ihttplib_proxy(IHTTPLIB *http, int type, const char *proxy, 230 | int port, const char *user, const char *pass); 231 | 232 | int ihttplib_update(IHTTPLIB *http, int wait); 233 | 234 | void ihttplib_header_reset(IHTTPLIB *http); 235 | 236 | void ihttplib_header_write(IHTTPLIB *http, const char *head); 237 | 238 | void ihttplib_header_send(IHTTPLIB *http); 239 | 240 | long ihttplib_send(IHTTPLIB *http, const void *data, long size); 241 | 242 | 243 | #define IHTTP_RECV_AGAIN -1 244 | #define IHTTP_RECV_DONE -2 245 | #define IHTTP_RECV_CLOSED -3 246 | #define IHTTP_RECV_NOTFIND -4 247 | #define IHTTP_RECV_ERROR -5 248 | #define IHTTP_RECV_TIMEOUT -6 249 | 250 | // returns IHTTP_RECV_AGAIN for block 251 | // returns IHTTP_RECV_DONE for okay 252 | // returns IHTTP_RECV_CLOSED for closed 253 | // returns IHTTP_RECV_NOTFIND for not find 254 | // returns IHTTP_RECV_ERROR for http error 255 | long ihttplib_recv(IHTTPLIB *http, void *data, long size); 256 | 257 | // returns data size in send buffer 258 | long ihttplib_dsize(IHTTPLIB *http); 259 | 260 | 261 | #define IHTTP_METHOD_GET 0 262 | #define IHTTP_METHOD_POST 1 263 | 264 | int ihttplib_request(IHTTPLIB *http, int method, const char *url, 265 | const void *body, long bodysize, const char *header); 266 | 267 | 268 | // returns IHTTP_RECV_AGAIN for block 269 | // returns IHTTP_RECV_DONE for okay 270 | // returns IHTTP_RECV_CLOSED for closed 271 | // returns IHTTP_RECV_NOTFIND for not find 272 | // returns IHTTP_RECV_ERROR for http error 273 | int ihttplib_getresponse(IHTTPLIB *http, ivalue_t *content, int waitms); 274 | 275 | 276 | #ifdef __cplusplus 277 | } 278 | #endif 279 | 280 | 281 | 282 | //===================================================================== 283 | // IURLLIB 284 | //===================================================================== 285 | struct IURLD 286 | { 287 | IHTTPLIB *http; 288 | int done; 289 | ivalue_t url; 290 | ivalue_t host; 291 | ivalue_t proxy; 292 | }; 293 | 294 | typedef struct IURLD IURLD; 295 | 296 | 297 | #ifdef __cplusplus 298 | extern "C" { 299 | #endif 300 | //--------------------------------------------------------------------- 301 | // URL Interface 302 | //--------------------------------------------------------------------- 303 | 304 | // open a url 305 | // POST mode: size >= 0 && data != NULL 306 | // GET mode: size < 0 || data == NULL 307 | // proxy format: a string: (type, addr, port [,user, passwd]) joined by "\n" 308 | // NULL for direct link. 'type' can be one of 'http', 'socks4' and 'socks5', 309 | // eg: type=http, proxyaddr=10.0.1.1, port=8080 -> "http\n10.0.1.1\n8080" 310 | // eg: "socks5\n10.0.0.1\n80\nuser1\npass1" "socks4\n127.0.0.1\n1081" 311 | IURLD *ineturl_open(const char *URL, const void *data, long size, 312 | const char *header, const char *proxy, int *errcode); 313 | 314 | void ineturl_close(IURLD *url); 315 | 316 | // returns IHTTP_RECV_AGAIN for block 317 | // returns IHTTP_RECV_DONE for okay 318 | // returns IHTTP_RECV_CLOSED for closed 319 | // returns IHTTP_RECV_NOTFIND for not find 320 | // returns IHTTP_RECV_ERROR for http error 321 | // returns > 0 for received data size 322 | long ineturl_read(IURLD *url, void *data, long size, int waitms); 323 | 324 | // writing extra post data 325 | // returns data size in send-buffer; 326 | long ineturl_write(IURLD *url, const void *data, long size); 327 | 328 | // flush: try to send data from buffer to network 329 | void ineturl_flush(IURLD *url); 330 | 331 | // check redirect 332 | int ineturl_location(IURLD *url, ivalue_t *location); 333 | 334 | 335 | #ifdef __cplusplus 336 | } 337 | #endif 338 | 339 | 340 | #ifdef __cplusplus 341 | extern "C" { 342 | #endif 343 | //--------------------------------------------------------------------- 344 | // TOOL AND DEMO 345 | //--------------------------------------------------------------------- 346 | 347 | // wget into a string 348 | // returns >= 0 for okay, below zero for errors: 349 | // returns IHTTP_RECV_CLOSED for closed 350 | // returns IHTTP_RECV_NOTFIND for not find 351 | // returns IHTTP_RECV_ERROR for http error 352 | int _urllib_wget(const char *URL, ivalue_t *ctx, const char *proxy, int time); 353 | 354 | 355 | // download to a file 356 | int _urllib_download(const char *URL, const char *filename); 357 | 358 | 359 | #ifdef __cplusplus 360 | } 361 | #endif 362 | 363 | 364 | 365 | #endif 366 | 367 | 368 | 369 | -------------------------------------------------------------------------------- /system/iposix.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // iposix.h - posix file system accessing 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __IPOSIX_H__ 10 | #define __IPOSIX_H__ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | #include "config.h" 14 | #endif 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(disable: 4819) 18 | #endif 19 | 20 | 21 | /*-------------------------------------------------------------------*/ 22 | /* C99 Compatible */ 23 | /*-------------------------------------------------------------------*/ 24 | #if defined(linux) || defined(__linux) || defined(__linux__) 25 | #ifdef _POSIX_C_SOURCE 26 | #if _POSIX_C_SOURCE < 200112L 27 | #undef _POSIX_C_SOURCE 28 | #endif 29 | #endif 30 | 31 | #ifndef _POSIX_C_SOURCE 32 | #define _POSIX_C_SOURCE 200112L 33 | #endif 34 | 35 | #ifdef _GNU_SOURCE 36 | #undef _GNU_SOURCE 37 | #endif 38 | 39 | #ifdef _BSD_SOURCE 40 | #undef _BSD_SOURCE 41 | #endif 42 | 43 | #ifdef __BSD_VISIBLE 44 | #undef __BSD_VISIBLE 45 | #endif 46 | 47 | #ifdef _XOPEN_SOURCE 48 | #undef _XOPEN_SOURCE 49 | #endif 50 | 51 | #define _GNU_SOURCE 1 52 | #define _BSD_SOURCE 1 53 | #define __BSD_VISIBLE 1 54 | #define _DEFAULT_SOURCE 1 55 | #define _XOPEN_SOURCE 600 56 | #endif 57 | 58 | 59 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 60 | //--------------------------------------------------------------------- 61 | // Global Definition 62 | //--------------------------------------------------------------------- 63 | #ifndef __INTEGER_32_BITS__ 64 | #define __INTEGER_32_BITS__ 65 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 66 | typedef __UINT32_TYPE__ ISTDUINT32; 67 | typedef __INT32_TYPE__ ISTDINT32; 68 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 69 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 70 | typedef __INT_FAST32_TYPE__ ISTDINT32; 71 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 72 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 73 | defined(_M_AMD64) 74 | typedef unsigned int ISTDUINT32; 75 | typedef int ISTDINT32; 76 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 77 | defined(__i386) || defined(_M_X86) 78 | typedef unsigned long ISTDUINT32; 79 | typedef long ISTDINT32; 80 | #elif defined(__MACOS__) 81 | typedef UInt32 ISTDUINT32; 82 | typedef SInt32 ISTDINT32; 83 | #elif defined(__APPLE__) && defined(__MACH__) 84 | #include 85 | typedef u_int32_t ISTDUINT32; 86 | typedef int32_t ISTDINT32; 87 | #elif defined(__BEOS__) 88 | #include 89 | typedef u_int32_t ISTDUINT32; 90 | typedef int32_t ISTDINT32; 91 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 92 | typedef unsigned __int32 ISTDUINT32; 93 | typedef __int32 ISTDINT32; 94 | #elif defined(__GNUC__) && (__GNUC__ > 3) 95 | #include 96 | typedef uint32_t ISTDUINT32; 97 | typedef int32_t ISTDINT32; 98 | #else 99 | typedef unsigned long ISTDUINT32; 100 | typedef long ISTDINT32; 101 | #endif 102 | #endif 103 | 104 | 105 | #if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOS__) 106 | #ifndef __unix 107 | #define __unix 1 108 | #endif 109 | #endif 110 | 111 | #if defined(__unix__) || defined(unix) || defined(__linux) 112 | #ifndef __unix 113 | #define __unix 1 114 | #endif 115 | #endif 116 | 117 | #include 118 | #ifdef __unix 119 | #include 120 | #define IPATHSEP '/' 121 | #else 122 | #include 123 | #if defined(_WIN32) 124 | #define IPATHSEP '\\' 125 | #else 126 | #define IPATHSEP '/' 127 | #endif 128 | #endif 129 | 130 | 131 | #ifndef __IINT8_DEFINED 132 | #define __IINT8_DEFINED 133 | typedef char IINT8; 134 | #endif 135 | 136 | #ifndef __IUINT8_DEFINED 137 | #define __IUINT8_DEFINED 138 | typedef unsigned char IUINT8; 139 | #endif 140 | 141 | #ifndef __IUINT16_DEFINED 142 | #define __IUINT16_DEFINED 143 | typedef unsigned short IUINT16; 144 | #endif 145 | 146 | #ifndef __IINT16_DEFINED 147 | #define __IINT16_DEFINED 148 | typedef short IINT16; 149 | #endif 150 | 151 | #ifndef __IINT32_DEFINED 152 | #define __IINT32_DEFINED 153 | typedef ISTDINT32 IINT32; 154 | #endif 155 | 156 | #ifndef __IUINT32_DEFINED 157 | #define __IUINT32_DEFINED 158 | typedef ISTDUINT32 IUINT32; 159 | #endif 160 | 161 | #ifndef __IINT64_DEFINED 162 | #define __IINT64_DEFINED 163 | #if defined(_MSC_VER) || defined(__BORLANDC__) 164 | typedef __int64 IINT64; 165 | #else 166 | typedef long long IINT64; 167 | #endif 168 | #endif 169 | 170 | #ifndef __IUINT64_DEFINED 171 | #define __IUINT64_DEFINED 172 | #if defined(_MSC_VER) || defined(__BORLANDC__) 173 | typedef unsigned __int64 IUINT64; 174 | #else 175 | typedef unsigned long long IUINT64; 176 | #endif 177 | #endif 178 | 179 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 180 | #ifndef _WIN32 181 | #define _WIN32 182 | #endif 183 | #endif 184 | 185 | 186 | #ifdef __cplusplus 187 | extern "C" { 188 | #endif 189 | 190 | //--------------------------------------------------------------------- 191 | // Posix Stat 192 | //--------------------------------------------------------------------- 193 | #define ISTAT_IFMT 0170000 // file type mask 194 | #define ISTAT_IFIFO 0010000 // named pipe (fifo) 195 | #define ISTAT_IFCHR 0020000 // charactor special 196 | #define ISTAT_IFDIR 0040000 // directory 197 | #define ISTAT_IFBLK 0060000 // block special 198 | #define ISTAT_IFREG 0100000 // regular 199 | #define ISTAT_IFLNK 0120000 // symbolic link 200 | #define ISTAT_IFSOCK 0140000 // socket 201 | #define ISTAT_IFWHT 0160000 // whiteout 202 | #define ISTAT_ISUID 0004000 // set user id on execution 203 | #define ISTAT_ISGID 0002000 // set group id on execution 204 | #define ISTAT_ISVXT 0001000 // swapped text even after use 205 | #define ISTAT_IRWXU 0000700 // owner RWX mask 206 | #define ISTAT_IRUSR 0000400 // owner read permission 207 | #define ISTAT_IWUSR 0000200 // owner writer permission 208 | #define ISTAT_IXUSR 0000100 // owner execution permission 209 | #define ISTAT_IRWXG 0000070 // group RWX mask 210 | #define ISTAT_IRGRP 0000040 // group read permission 211 | #define ISTAT_IWGRP 0000020 // group write permission 212 | #define ISTAT_IXGRP 0000010 // group execution permission 213 | #define ISTAT_IRWXO 0000007 // other RWX mask 214 | #define ISTAT_IROTH 0000004 // other read permission 215 | #define ISTAT_IWOTH 0000002 // other writer permission 216 | #define ISTAT_IXOTH 0000001 // other execution permission 217 | 218 | #define ISTAT_ISFMT(m, t) (((m) & ISTAT_IFMT) == (t)) 219 | #define ISTAT_ISDIR(m) ISTAT_ISFMT(m, ISTAT_IFDIR) 220 | #define ISTAT_ISCHR(m) ISTAT_ISFMT(m, ISTAT_IFCHR) 221 | #define ISTAT_ISBLK(m) ISTAT_ISFMT(m, ISTAT_IFBLK) 222 | #define ISTAT_ISREG(m) ISTAT_ISFMT(m, ISTAT_IFREG) 223 | #define ISTAT_ISFIFO(m) ISTAT_ISFMT(m, ISTAT_IFIFO) 224 | #define ISTAT_ISLNK(m) ISTAT_ISFMT(m, ISTAT_IFLNK) 225 | #define ISTAT_ISSOCK(m) ISTAT_ISFMT(m, ISTAT_IFSOCK) 226 | #define ISTAT_ISWHT(m) ISTAT_ISFMT(m, ISTAT_IFWHT) 227 | 228 | struct IPOSIX_STAT 229 | { 230 | IUINT32 st_mode; 231 | IUINT64 st_ino; 232 | IUINT32 st_dev; 233 | IUINT32 st_nlink; 234 | IUINT32 st_uid; 235 | IUINT32 st_gid; 236 | IUINT64 st_size; 237 | IUINT32 atime; 238 | IUINT32 mtime; 239 | IUINT32 ctime; 240 | IUINT32 st_blocks; 241 | IUINT32 st_blksize; 242 | IUINT32 st_rdev; 243 | IUINT32 st_flags; 244 | }; 245 | 246 | typedef struct IPOSIX_STAT iposix_stat_t; 247 | 248 | #define IPOSIX_MAXPATH 1024 249 | #define IPOSIX_MAXBUFF ((IPOSIX_MAXPATH) + 8) 250 | 251 | 252 | // returns 0 for success, -1 for error 253 | int iposix_stat(const char *path, iposix_stat_t *ostat); 254 | 255 | // returns 0 for success, -1 for error 256 | int iposix_lstat(const char *path, iposix_stat_t *ostat); 257 | 258 | // returns 0 for success, -1 for error 259 | int iposix_fstat(int fd, iposix_stat_t *ostat); 260 | 261 | // get current directory 262 | char *iposix_getcwd(char *path, int size); 263 | 264 | // create directory 265 | int iposix_mkdir(const char *path, int mode); 266 | 267 | // change directory 268 | int iposix_chdir(const char *path); 269 | 270 | #ifndef F_OK 271 | #define F_OK 0 272 | #endif 273 | 274 | #ifndef X_OK 275 | #define X_OK 1 276 | #endif 277 | 278 | #ifndef W_OK 279 | #define W_OK 2 280 | #endif 281 | 282 | #ifndef R_OK 283 | #define R_OK 4 284 | #endif 285 | 286 | // check access 287 | int iposix_access(const char *path, int mode); 288 | 289 | 290 | // returns 1 for true 0 for false, -1 for not exist 291 | int iposix_path_isdir(const char *path); 292 | 293 | // returns 1 for true 0 for false, -1 for not exist 294 | int iposix_path_isfile(const char *path); 295 | 296 | // returns 1 for true 0 for false, -1 for not exist 297 | int iposix_path_islink(const char *path); 298 | 299 | // returns 1 for true 0 for false 300 | int iposix_path_exists(const char *path); 301 | 302 | // returns file size, -1 for error 303 | IINT64 iposix_path_getsize(const char *path); 304 | 305 | 306 | //--------------------------------------------------------------------- 307 | // Posix Path 308 | //--------------------------------------------------------------------- 309 | 310 | // 是否是绝对路径,如果是的话返回1,否则返回0 311 | int iposix_path_isabs(const char *path); 312 | 313 | // 绝对路径 314 | char *iposix_path_abspath(const char *srcpath, char *path, int maxsize); 315 | 316 | // 归一化路径:去掉重复斜杠,以及处理掉".", ".."等。 317 | char *iposix_path_normal(const char *srcpath, char *path, int maxsize); 318 | 319 | // 连接路径 320 | char *iposix_path_join(const char *p1, const char *p2, char *path, int len); 321 | 322 | // 路径分割:从右向左找到第一个"/"分成两个字符串 323 | int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2); 324 | 325 | // 扩展分割:分割文件主名与扩展名 326 | int iposix_path_splitext(const char *path, char *p1, int l1, 327 | char *p2, int l2); 328 | 329 | 330 | //--------------------------------------------------------------------- 331 | // platform special 332 | //--------------------------------------------------------------------- 333 | 334 | // 取得进程可执行文件的文件名 335 | int iposix_path_exepath(char *ptr, int size); 336 | 337 | // 取得进程可执行文件的目录 338 | int iposix_path_execwd(char *ptr, int size); 339 | 340 | // 递归创建路径 341 | int iposix_path_mkdir(const char *path, int mode); 342 | 343 | // 精简版取得可执行路径 344 | const char *iposix_get_exepath(void); 345 | 346 | // 精简版取得可执行目录 347 | const char *iposix_get_execwd(void); 348 | 349 | 350 | // 文件路径格式化: 351 | // out - 输出路径,长度不小于 IPOSIX_MAXPATH 352 | // root - 根路径 353 | // ... - 后续的相对路径 354 | // 返回 - out 355 | // 假设可执行路径位于 /home/abc/work,那么: 356 | // iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") 357 | // 结果就是 /home/abc/work/images/abc.jpg 358 | char *iposix_path_format(char *out, const char *root, const char *fmt, ...); 359 | 360 | 361 | 362 | //--------------------------------------------------------------------- 363 | // System Utilities 364 | //--------------------------------------------------------------------- 365 | 366 | #ifndef IDISABLE_SHARED_LIBRARY 367 | 368 | /* LoadLibraryA */ 369 | void *iposix_shared_open(const char *dllname); 370 | 371 | /* GetProcAddress */ 372 | void *iposix_shared_get(void *shared, const char *name); 373 | 374 | /* FreeLibrary */ 375 | void iposix_shared_close(void *shared); 376 | 377 | #endif 378 | 379 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 380 | 381 | /* load file content, use free to dispose */ 382 | void *iposix_file_load_content(const char *filename, long *size); 383 | 384 | /* save file content */ 385 | int iposix_file_save_content(const char *filename, const void *data, long size); 386 | 387 | /* cross os GetModuleFileName, returns size for success, -1 for error */ 388 | int iposix_get_proc_pathname(char *ptr, int size); 389 | 390 | #endif 391 | 392 | 393 | 394 | #ifdef __cplusplus 395 | } 396 | #endif 397 | 398 | 399 | #endif 400 | 401 | 402 | #endif 403 | 404 | 405 | 406 | 407 | -------------------------------------------------------------------------------- /system/isecure.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // isecure.h - secure hash encrypt 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | // Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. 9 | // Copyright 2014 Melissa O'Neill 10 | // 11 | //===================================================================== 12 | #ifndef __ISECURE_H__ 13 | #define __ISECURE_H__ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | //===================================================================== 23 | // 32BIT INTEGER DEFINITION 24 | //===================================================================== 25 | #ifndef __INTEGER_32_BITS__ 26 | #define __INTEGER_32_BITS__ 27 | #if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 28 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 29 | defined(_M_AMD64) 30 | typedef unsigned int ISTDUINT32; 31 | typedef int ISTDINT32; 32 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 33 | defined(__i386) || defined(_M_X86) 34 | typedef unsigned long ISTDUINT32; 35 | typedef long ISTDINT32; 36 | #elif defined(__MACOS__) 37 | typedef UInt32 ISTDUINT32; 38 | typedef SInt32 ISTDINT32; 39 | #elif defined(__APPLE__) && defined(__MACH__) 40 | #include 41 | typedef u_int32_t ISTDUINT32; 42 | typedef int32_t ISTDINT32; 43 | #elif defined(__BEOS__) 44 | #include 45 | typedef u_int32_t ISTDUINT32; 46 | typedef int32_t ISTDINT32; 47 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 48 | typedef unsigned __int32 ISTDUINT32; 49 | typedef __int32 ISTDINT32; 50 | #elif defined(__GNUC__) 51 | #include 52 | typedef uint32_t ISTDUINT32; 53 | typedef int32_t ISTDINT32; 54 | #else 55 | typedef unsigned long ISTDUINT32; 56 | typedef long ISTDINT32; 57 | #endif 58 | #endif 59 | 60 | 61 | //===================================================================== 62 | // Global Macros 63 | //===================================================================== 64 | #ifndef __IINT8_DEFINED 65 | #define __IINT8_DEFINED 66 | typedef char IINT8; 67 | #endif 68 | 69 | #ifndef __IUINT8_DEFINED 70 | #define __IUINT8_DEFINED 71 | typedef unsigned char IUINT8; 72 | #endif 73 | 74 | #ifndef __IUINT16_DEFINED 75 | #define __IUINT16_DEFINED 76 | typedef unsigned short IUINT16; 77 | #endif 78 | 79 | #ifndef __IINT16_DEFINED 80 | #define __IINT16_DEFINED 81 | typedef short IINT16; 82 | #endif 83 | 84 | #ifndef __IINT32_DEFINED 85 | #define __IINT32_DEFINED 86 | typedef ISTDINT32 IINT32; 87 | #endif 88 | 89 | #ifndef __IUINT32_DEFINED 90 | #define __IUINT32_DEFINED 91 | typedef ISTDUINT32 IUINT32; 92 | #endif 93 | 94 | #ifndef __IINT64_DEFINED 95 | #define __IINT64_DEFINED 96 | #if defined(_MSC_VER) || defined(__BORLANDC__) 97 | typedef __int64 IINT64; 98 | #else 99 | typedef long long IINT64; 100 | #endif 101 | #endif 102 | 103 | #ifndef __IUINT64_DEFINED 104 | #define __IUINT64_DEFINED 105 | #if defined(_MSC_VER) || defined(__BORLANDC__) 106 | typedef unsigned __int64 IUINT64; 107 | #else 108 | typedef unsigned long long IUINT64; 109 | #endif 110 | #endif 111 | 112 | #ifndef INLINE 113 | #if defined(__GNUC__) 114 | 115 | #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) 116 | #define INLINE __inline__ __attribute__((always_inline)) 117 | #else 118 | #define INLINE __inline__ 119 | #endif 120 | 121 | #elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__)) 122 | #define INLINE __inline 123 | #else 124 | #define INLINE 125 | #endif 126 | #endif 127 | 128 | #if (!defined(__cplusplus)) && (!defined(inline)) 129 | #define inline INLINE 130 | #endif 131 | 132 | 133 | //===================================================================== 134 | // DETECTION WORD ORDER 135 | //===================================================================== 136 | #ifndef IWORDS_BIG_ENDIAN 137 | #ifdef _BIG_ENDIAN_ 138 | #if _BIG_ENDIAN_ 139 | #define IWORDS_BIG_ENDIAN 1 140 | #endif 141 | #endif 142 | #ifndef IWORDS_BIG_ENDIAN 143 | #if defined(__hppa__) || \ 144 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ 145 | (defined(__MIPS__) && defined(__MISPEB__)) || \ 146 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ 147 | defined(__sparc__) || defined(__powerpc__) || \ 148 | defined(__mc68000__) || defined(__s390x__) || defined(__s390__) 149 | #define IWORDS_BIG_ENDIAN 1 150 | #endif 151 | #endif 152 | #ifndef IWORDS_BIG_ENDIAN 153 | #define IWORDS_BIG_ENDIAN 0 154 | #endif 155 | #endif 156 | 157 | #ifndef IASSERT 158 | #define IASSERT(x) assert(x) 159 | #endif 160 | 161 | 162 | #ifdef __cplusplus 163 | extern "C" { 164 | #endif 165 | 166 | //===================================================================== 167 | // Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. 168 | //===================================================================== 169 | typedef struct 170 | { 171 | IUINT32 i[2]; /* Number of _bits_ handled mod 2^64 */ 172 | IUINT32 buf[4]; /* Scratch buffer */ 173 | unsigned char in[64]; /* Input buffer */ 174 | } HASH_MD5_CTX; 175 | 176 | void HASH_MD5_Init(HASH_MD5_CTX *ctx, unsigned long RandomNumber); 177 | void HASH_MD5_Update(HASH_MD5_CTX *ctx, const void *input, unsigned int len); 178 | void HASH_MD5_Final(HASH_MD5_CTX *ctx, unsigned char digest[16]); 179 | 180 | 181 | 182 | //===================================================================== 183 | // From http://www.mirrors.wiretapped.net/security/cryptography 184 | //===================================================================== 185 | typedef struct { 186 | IUINT32 state[5]; 187 | IUINT32 count[2]; 188 | unsigned char buffer[64]; 189 | } HASH_SHA1_CTX; 190 | 191 | void HASH_SHA1_Init(HASH_SHA1_CTX *ctx); 192 | void HASH_SHA1_Update(HASH_SHA1_CTX *ctx, const void *input, unsigned int len); 193 | void HASH_SHA1_Final(HASH_SHA1_CTX *ctx, unsigned char digest[20]); 194 | 195 | 196 | //===================================================================== 197 | // UTILITIES 198 | //===================================================================== 199 | 200 | // convert digests to string 201 | char* hash_digest_to_string(const unsigned char *in, int size, char *out); 202 | 203 | // calculate md5sum and convert digests to string 204 | char* hash_md5sum(const void *in, unsigned int len, char *out); 205 | 206 | // calculate sha1sum and convert digests to string 207 | char* hash_sha1sum(const void *in, unsigned int len, char *out); 208 | 209 | // calculate crc32 and return result 210 | IUINT32 hash_crc32(const void *in, unsigned int len); 211 | 212 | // sum all bytes together 213 | IUINT32 hash_checksum(const void *in, unsigned int len); 214 | 215 | 216 | //===================================================================== 217 | // Diffie-Hellman key exchange 218 | // http://zh.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange 219 | // usage: 1. get an local asymmetric-key a from DH_Random 220 | // 2. calculate A=(5 ^ a) % p by DH_Exchange 221 | // 3. send A to remote 222 | // 4. obtain symmetrical-key by DH_Key(local_key, RemoteA) 223 | //===================================================================== 224 | 225 | // returns random local key 226 | IUINT64 DH_Random(); 227 | 228 | // calculate A/B which will be sent to remote 229 | IUINT64 DH_Exchange(IUINT64 local); 230 | 231 | // get final symmetrical-key from local key and remote A/B 232 | IUINT64 DH_Key(IUINT64 local, IUINT64 remote); 233 | 234 | // get qword from hex string 235 | void DH_STR_TO_U64(const char *str, IUINT64 *x); 236 | 237 | // hex string from qword, capacity of str must above 17 238 | void DH_U64_TO_STR(IUINT64 x, char *str); 239 | 240 | 241 | //===================================================================== 242 | // CRYPTO RC4 243 | //===================================================================== 244 | typedef struct { 245 | int x; 246 | int y; 247 | unsigned char box[256]; 248 | } CRYPTO_RC4_CTX; 249 | 250 | 251 | void CRYPTO_RC4_Init(CRYPTO_RC4_CTX *ctx, const void *key, int keylen); 252 | 253 | void CRYPTO_RC4_Apply(CRYPTO_RC4_CTX *ctx, const void *in, void *out, 254 | size_t size); 255 | 256 | void CRYPTO_RC4_Direct(const void *key, int keylen, const void *in, 257 | void *out, size_t size, int ntimes); 258 | 259 | 260 | 261 | //===================================================================== 262 | // CRYPTO chacha20: 263 | //===================================================================== 264 | typedef struct { 265 | IUINT32 state[16]; 266 | IUINT8 keystream[64]; 267 | size_t position; 268 | } CRYPTO_CHACHA20_CTX; 269 | 270 | 271 | // key: 32 bytes, nonce: 12 bytes 272 | void CRYPTO_CHACHA20_Init(CRYPTO_CHACHA20_CTX *ctx, 273 | const IUINT8 *key, const IUINT8 *nonce, IUINT32 counter); 274 | 275 | // applay cipher 276 | void CRYPTO_CHACHA20_Apply(CRYPTO_CHACHA20_CTX *ctx, 277 | const void *in, void *out, size_t size); 278 | 279 | 280 | 281 | //===================================================================== 282 | // CRYPTO XTEA: https://en.wikipedia.org/wiki/XTEA 283 | //===================================================================== 284 | 285 | void CRYPTO_XTEA_Encipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 286 | 287 | void CRYPTO_XTEA_Decipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 288 | 289 | 290 | //===================================================================== 291 | // CRYPTO XOR: byte mask or string mask 292 | //===================================================================== 293 | 294 | // xor mask with each byte 295 | void CRYPTO_XOR_Byte(void *in, const void *out, int size, IUINT8 mask); 296 | 297 | // xor mask with each uint32 298 | void CRYPTO_XOR_DWord(void *in, const void *out, int size, IUINT32 mask); 299 | 300 | // xor string with each byte 301 | void CRYPTO_XOR_String(void *in, const void *out, int size, 302 | const unsigned char *mask, int msize, IUINT32 nonce); 303 | 304 | 305 | 306 | //===================================================================== 307 | // LCG: https://en.wikipedia.org/wiki/Linear_congruential_generator 308 | //===================================================================== 309 | 310 | // rand() in stdlib.h (c99), output range: 0 <= x <= 32767 311 | IUINT32 random_std_c99(IUINT32 *seed); 312 | 313 | // rand() in stdlib.h (msvc), output range: 0 <= x <= 32767 314 | IUINT32 random_std_msvc(IUINT32 *seed); 315 | 316 | // minstd_rand in C++, output range: 0 <= x < 0x7fffffff 317 | IUINT32 random_std_cpp(IUINT32 *seed); 318 | 319 | 320 | //===================================================================== 321 | // Statistically perfect random generator 322 | //===================================================================== 323 | typedef struct 324 | { 325 | IUINT32 seed; // random seed 326 | IUINT32 size; // array size 327 | IUINT32 avail; // available numbers 328 | IUINT32 *state; // states array 329 | } RANDOM_BOX; 330 | 331 | 332 | // initialize random box 333 | void RANDOM_BOX_Init(RANDOM_BOX *box, IUINT32 *state, IUINT32 size); 334 | 335 | // change seed 336 | void RANDOM_BOX_Seed(RANDOM_BOX *box, IUINT32 seed); 337 | 338 | // next random number within 0 <= x < size 339 | IUINT32 RANDOM_BOX_Next(RANDOM_BOX *box); 340 | 341 | 342 | //===================================================================== 343 | // PCG: PCG is a family of simple fast statistically good algorithms 344 | //===================================================================== 345 | typedef struct 346 | { 347 | IUINT64 state; // RNG state. All values are possible. 348 | IUINT64 inc; // Must *always* be odd. 349 | } RANDOM_PCG; 350 | 351 | // initialize pcg 352 | void RANDOM_PCG_Init(RANDOM_PCG *pcg, IUINT64 initstate, IUINT64 initseq); 353 | 354 | // next random number 355 | IUINT32 RANDOM_PCG_Next(RANDOM_PCG *pcg); 356 | 357 | // next random number within 0 <= x < bound 358 | IUINT32 RANDOM_PCG_RANGE(RANDOM_PCG *pcg, IUINT32 bound); 359 | 360 | 361 | 362 | 363 | 364 | #ifdef __cplusplus 365 | } 366 | #endif 367 | 368 | #endif 369 | 370 | 371 | -------------------------------------------------------------------------------- /system/itimer.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.c - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #include 10 | #include 11 | 12 | #include "itimer.h" 13 | 14 | //===================================================================== 15 | // Local Definition 16 | //===================================================================== 17 | #define ITIMER_NODE_STATE_OK 0x1981 18 | #define ITIMER_NODE_STATE_BAD 0x2014 19 | 20 | static void itimer_internal_add(itimer_core *core, itimer_node *node); 21 | static void itimer_internal_cascade(struct itimer_vec *vec, int index); 22 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies); 23 | 24 | 25 | //--------------------------------------------------------------------- 26 | // initialize timer core 27 | //--------------------------------------------------------------------- 28 | void itimer_core_init(itimer_core *core, IUINT32 jiffies) 29 | { 30 | union { struct itimer_vec *vn; struct itimer_vec_root *vr; } uv; 31 | int i; 32 | 33 | uv.vr = &core->tv1; 34 | core->timer_jiffies = jiffies; 35 | core->tvecs[0] = uv.vn; 36 | core->tvecs[1] = &core->tv2; 37 | core->tvecs[2] = &core->tv3; 38 | core->tvecs[3] = &core->tv4; 39 | core->tvecs[4] = &core->tv5; 40 | 41 | for (i = 0; i < ITVR_SIZE; i++) { 42 | ilist_init(&core->tv1.vec[i]); 43 | } 44 | 45 | for (i = 0; i < ITVN_SIZE; i++) { 46 | ilist_init(&core->tv2.vec[i]); 47 | ilist_init(&core->tv3.vec[i]); 48 | ilist_init(&core->tv4.vec[i]); 49 | ilist_init(&core->tv5.vec[i]); 50 | } 51 | } 52 | 53 | 54 | //--------------------------------------------------------------------- 55 | // destroy timer core 56 | //--------------------------------------------------------------------- 57 | void itimer_core_destroy(itimer_core *core) 58 | { 59 | int i, j; 60 | for (i = 0; i < 5; i++) { 61 | int count = (i == 0)? ITVR_SIZE : ITVN_SIZE; 62 | for (j = 0; j < count; j++) { 63 | ilist_head *root = &(core->tv1.vec[j]); 64 | if (i > 0) root = &(core->tvecs[i]->vec[j]); 65 | while (!ilist_is_empty(root)) { 66 | itimer_node *node = ilist_entry(root->next, 67 | itimer_node, head); 68 | if (!ilist_is_empty(&node->head)) { 69 | ilist_del_init(&node->head); 70 | } 71 | node->core = NULL; 72 | } 73 | } 74 | } 75 | } 76 | 77 | 78 | //--------------------------------------------------------------------- 79 | // run timer core 80 | //--------------------------------------------------------------------- 81 | void itimer_core_run(itimer_core *core, IUINT32 jiffies) 82 | { 83 | itimer_internal_update(core, jiffies); 84 | } 85 | 86 | 87 | //--------------------------------------------------------------------- 88 | // initialize node 89 | //--------------------------------------------------------------------- 90 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data) 91 | { 92 | ilist_init(&node->head); 93 | node->expires = 0; 94 | node->state = ITIMER_NODE_STATE_OK; 95 | node->callback = fn; 96 | node->data = data; 97 | node->core = NULL; 98 | } 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // destroy node 103 | //--------------------------------------------------------------------- 104 | void itimer_node_destroy(itimer_node *node) 105 | { 106 | if (node->state != ITIMER_NODE_STATE_OK) { 107 | assert(node->state == ITIMER_NODE_STATE_OK); 108 | return ; 109 | } 110 | if (!ilist_is_empty(&node->head)) { 111 | ilist_del_init(&node->head); 112 | node->core = NULL; 113 | } 114 | node->state = ITIMER_NODE_STATE_BAD; 115 | node->callback = NULL; 116 | node->data = NULL; 117 | node->core = NULL; 118 | node->expires = 0; 119 | } 120 | 121 | 122 | //--------------------------------------------------------------------- 123 | // add node to core 124 | //--------------------------------------------------------------------- 125 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires) 126 | { 127 | if (node->state != ITIMER_NODE_STATE_OK) { 128 | assert(node->state == ITIMER_NODE_STATE_OK); 129 | return ; 130 | } 131 | 132 | if (!ilist_is_empty(&node->head)) { 133 | ilist_del_init(&node->head); 134 | node->core = NULL; 135 | } 136 | 137 | node->expires = expires; 138 | 139 | itimer_internal_add(core, node); 140 | } 141 | 142 | 143 | //--------------------------------------------------------------------- 144 | // remove node from core 145 | //--------------------------------------------------------------------- 146 | int itimer_node_del(itimer_core *core, itimer_node *node) 147 | { 148 | if (node->state != ITIMER_NODE_STATE_OK) { 149 | assert(node->state == ITIMER_NODE_STATE_OK); 150 | return -1; 151 | } 152 | if (!ilist_is_empty(&node->head)) { 153 | assert(node->core != NULL); 154 | ilist_del_init(&node->head); 155 | node->core = NULL; 156 | return 1; 157 | } 158 | return 0; 159 | } 160 | 161 | 162 | //--------------------------------------------------------------------- 163 | // modify node 164 | //--------------------------------------------------------------------- 165 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires) 166 | { 167 | int ret = itimer_node_del(core, node); 168 | itimer_node_add(core, node, expires); 169 | return ret; 170 | } 171 | 172 | 173 | //--------------------------------------------------------------------- 174 | // itimer_internal_add 175 | //--------------------------------------------------------------------- 176 | static void itimer_internal_add(itimer_core *core, itimer_node *node) 177 | { 178 | IUINT32 expires = node->expires; 179 | IUINT32 idx = (IUINT32)(expires - core->timer_jiffies); 180 | ilist_head *vec = NULL; 181 | 182 | if (((IINT32)idx) < 0) { 183 | vec = core->tv1.vec + (core->timer_jiffies & ITVR_MASK); 184 | } 185 | else if (idx < ITVR_SIZE) { 186 | int i = expires & ITVR_MASK; 187 | vec = core->tv1.vec + i; 188 | } 189 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS))) { 190 | int i = (expires >> ITVR_BITS) & ITVN_MASK; 191 | vec = core->tv2.vec + i; 192 | } 193 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 2))) { 194 | int i = (expires >> (ITVR_BITS + ITVN_BITS)) & ITVN_MASK; 195 | vec = core->tv3.vec + i; 196 | } 197 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 3))) { 198 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 2)) & ITVN_MASK; 199 | vec = core->tv4.vec + i; 200 | } 201 | else { 202 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 3)) & ITVN_MASK; 203 | vec = core->tv5.vec + i; 204 | } 205 | 206 | ilist_add_tail(&node->head, vec); 207 | node->core = core; 208 | } 209 | 210 | 211 | //--------------------------------------------------------------------- 212 | // itimer_internal_cascade 213 | //--------------------------------------------------------------------- 214 | static void itimer_internal_cascade(struct itimer_vec *tv, int index) 215 | { 216 | ilist_head queued; 217 | ilist_init(&queued); 218 | ilist_splice_init(tv->vec + index, &queued); 219 | while (!ilist_is_empty(&queued)) { 220 | itimer_node *node; 221 | node = ilist_entry(queued.next, itimer_node, head); 222 | ilist_del_init(&node->head); 223 | itimer_internal_add(node->core, node); 224 | } 225 | } 226 | 227 | 228 | //--------------------------------------------------------------------- 229 | // itimer_internal_update 230 | //--------------------------------------------------------------------- 231 | static void itimer_internal_update(itimer_core *core, IUINT32 jiffies) 232 | { 233 | #define ITIMER_INDEX(C, N) \ 234 | (((C)->timer_jiffies >> (ITVR_BITS + (N) * ITVN_BITS)) & ITVN_MASK) 235 | while ((IINT32)(jiffies - core->timer_jiffies) >= 0) { 236 | ilist_head queued; 237 | int index = core->timer_jiffies & ITVR_MASK; 238 | ilist_init(&queued); 239 | if (index == 0) { 240 | int i = ITIMER_INDEX(core, 0); 241 | itimer_internal_cascade(&core->tv2, i); 242 | if (i == 0) { 243 | i = ITIMER_INDEX(core, 1); 244 | itimer_internal_cascade(&core->tv3, i); 245 | if (i == 0) { 246 | i = ITIMER_INDEX(core, 2); 247 | itimer_internal_cascade(&core->tv4, i); 248 | if (i == 0) { 249 | i = ITIMER_INDEX(core, 3); 250 | itimer_internal_cascade(&core->tv5, i); 251 | } 252 | } 253 | } 254 | } 255 | core->timer_jiffies++; 256 | ilist_splice_init(core->tv1.vec + index, &queued); 257 | while (!ilist_is_empty(&queued)) { 258 | itimer_node *node; 259 | void (*fn)(void*); 260 | void *data; 261 | node = ilist_entry(queued.next, itimer_node, head); 262 | fn = node->callback; 263 | data = node->data; 264 | ilist_del_init(&node->head); 265 | node->core = NULL; 266 | if (fn) fn(data); 267 | } 268 | } 269 | #undef ITIMER_INDEX 270 | } 271 | 272 | 273 | //--------------------------------------------------------------------- 274 | // how many jiffies to the nearest node (approximately) 275 | //--------------------------------------------------------------------- 276 | IUINT32 itimer_core_nearest(const itimer_core *core, IUINT32 limit) 277 | { 278 | IUINT32 avail = ITVR_SIZE - (core->timer_jiffies & ITVR_MASK); 279 | IUINT32 index = 0; 280 | for (index = 0; index < ITVR_SIZE; index++) { 281 | IUINT32 pos = (core->timer_jiffies + index) & ITVR_MASK; 282 | if (index >= limit && limit > 0) break; 283 | if (!ilist_is_empty(&(core->tv1.vec[pos]))) { 284 | break; 285 | } 286 | } 287 | return (index < avail)? index : avail; 288 | } 289 | 290 | 291 | 292 | //===================================================================== 293 | // Timer Manager 294 | //===================================================================== 295 | 296 | // initialize timer manager 297 | // interval - internal working interval 298 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval) 299 | { 300 | mgr->current = 0; 301 | mgr->interval = (interval < 1)? 1 : interval; 302 | mgr->jiffies = 0; 303 | mgr->millisec = 0; 304 | mgr->initialized = 0; 305 | mgr->counter = 0; 306 | itimer_core_init(&mgr->core, mgr->jiffies); 307 | } 308 | 309 | // destroy timer manager 310 | void itimer_mgr_destroy(itimer_mgr *mgr) 311 | { 312 | itimer_core_destroy(&mgr->core); 313 | } 314 | 315 | #ifndef ITIMER_MGR_LIMIT 316 | #define ITIMER_MGR_LIMIT 60000 // 60 seconds 317 | #endif 318 | 319 | // run timer events 320 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec) 321 | { 322 | IUINT32 interval = mgr->interval; 323 | IINT32 limit = ITIMER_MGR_LIMIT + (IINT32)interval * 64; 324 | // first time to be called 325 | if (mgr->initialized == 0) { 326 | mgr->millisec = millisec; 327 | mgr->initialized = 1; 328 | } 329 | else { 330 | IINT32 diff = (IINT32)(millisec - mgr->millisec); 331 | // recover from long-time sleep 332 | if (diff > limit || diff < -limit) { 333 | mgr->millisec = millisec; 334 | } 335 | } 336 | // reset counter 337 | mgr->counter = 0; 338 | // update core timer 339 | while ((IINT32)(millisec - mgr->millisec) >= 0) { 340 | itimer_core_run(&mgr->core, mgr->jiffies); 341 | mgr->jiffies++; 342 | mgr->current += mgr->interval; 343 | mgr->millisec += mgr->interval; 344 | } 345 | } 346 | 347 | // callback 348 | static void itimer_evt_cb(void *p) 349 | { 350 | itimer_evt *evt = (itimer_evt*)p; 351 | itimer_mgr *mgr = evt->mgr; 352 | IUINT32 current = mgr->current; 353 | int fire = 0; 354 | int stop = 0; 355 | 356 | // time compensation, comparision takes care of uint32 overflow 357 | while (((IINT32)(current - evt->slap)) >= 0) { 358 | evt->slap += evt->period; 359 | fire = 1; 360 | } 361 | 362 | // need invoke callback ? 363 | if (fire) { 364 | if (evt->repeat == 0) { 365 | fire = 0; 366 | stop = 1; 367 | } 368 | else if (evt->repeat > 0) { 369 | evt->repeat--; 370 | if (evt->repeat == 0) { 371 | stop = 1; 372 | } 373 | } 374 | } 375 | 376 | // reschedule or stop ? 377 | if (stop == 0) { 378 | IUINT32 interval = mgr->interval; 379 | IUINT32 expires = 0; 380 | if (interval > 1) { 381 | expires = (evt->slap - current + interval - 1) / interval; 382 | } else { 383 | expires = (evt->slap - current); 384 | } 385 | if (expires >= 0x70000000) expires = 0x70000000; 386 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 387 | } else { 388 | itimer_evt_stop(mgr, evt); 389 | } 390 | 391 | // need invoke callback ? 392 | if (fire) { 393 | mgr->counter++; 394 | if (evt->callback) { 395 | evt->callback(evt->data, evt->user); 396 | } 397 | } 398 | } 399 | 400 | // initialize timer event 401 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 402 | void *data, void *user) 403 | { 404 | itimer_node_init(&evt->node, itimer_evt_cb, evt); 405 | evt->callback = fn; 406 | evt->data = data; 407 | evt->user = user; 408 | evt->mgr = NULL; 409 | evt->period = 0; 410 | evt->slap = 0; 411 | evt->repeat = 0; 412 | evt->running = 0; 413 | } 414 | 415 | // destroy timer event 416 | void itimer_evt_destroy(itimer_evt *evt) 417 | { 418 | itimer_node_destroy(&evt->node); 419 | evt->callback = NULL; 420 | evt->data = NULL; 421 | evt->user = NULL; 422 | evt->mgr = NULL; 423 | evt->period = 0; 424 | evt->slap = 0; 425 | evt->repeat = 0; 426 | evt->running = 0; 427 | } 428 | 429 | // start timer: repeat <= 0 (infinite repeat) 430 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 431 | IUINT32 period, int repeat) 432 | { 433 | IUINT32 interval = mgr->interval; 434 | IUINT32 expires; 435 | if (evt->mgr) { 436 | itimer_evt_stop(evt->mgr, evt); 437 | } 438 | evt->period = (period < 1)? 1 : period; 439 | evt->repeat = (repeat <= 0)? -1 : repeat; 440 | evt->slap = mgr->current + period; 441 | evt->mgr = mgr; 442 | if (interval > 1) { 443 | expires = (evt->slap - mgr->current + interval - 1) / interval; 444 | } else { 445 | expires = (evt->slap - mgr->current); 446 | } 447 | if (expires >= 0x70000000) expires = 0x70000000; 448 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 449 | evt->running = 0; 450 | } 451 | 452 | // stop timer 453 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt) 454 | { 455 | if (evt->mgr) { 456 | itimer_node_del(&evt->mgr->core, &evt->node); 457 | evt->mgr = NULL; 458 | } 459 | evt->running = 0; 460 | } 461 | 462 | // returns 0 for stopped and 1 for running 463 | int itimer_evt_status(const itimer_evt *evt) 464 | { 465 | return (evt->mgr == NULL)? 0 : 1; 466 | } 467 | 468 | 469 | 470 | -------------------------------------------------------------------------------- /system/itimer.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itimer.h - Application Level Implementation of Linux Kernel Timer 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __ITIMER_H__ 10 | #define __ITIMER_H__ 11 | 12 | #ifdef IHAVE_CONFIG_H 13 | #include "config.h" 14 | #endif 15 | 16 | #include 17 | 18 | 19 | //===================================================================== 20 | // 32BIT INTEGER DEFINITION 21 | //===================================================================== 22 | #ifndef __INTEGER_32_BITS__ 23 | #define __INTEGER_32_BITS__ 24 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 25 | typedef __UINT32_TYPE__ ISTDUINT32; 26 | typedef __INT32_TYPE__ ISTDINT32; 27 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 28 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 29 | typedef __INT_FAST32_TYPE__ ISTDINT32; 30 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 31 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 32 | defined(_M_AMD64) 33 | typedef unsigned int ISTDUINT32; 34 | typedef int ISTDINT32; 35 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 36 | defined(__i386) || defined(_M_X86) 37 | typedef unsigned long ISTDUINT32; 38 | typedef long ISTDINT32; 39 | #elif defined(__MACOS__) 40 | typedef UInt32 ISTDUINT32; 41 | typedef SInt32 ISTDINT32; 42 | #elif defined(__APPLE__) && defined(__MACH__) 43 | #include 44 | typedef u_int32_t ISTDUINT32; 45 | typedef int32_t ISTDINT32; 46 | #elif defined(__BEOS__) 47 | #include 48 | typedef u_int32_t ISTDUINT32; 49 | typedef int32_t ISTDINT32; 50 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 51 | typedef unsigned __int32 ISTDUINT32; 52 | typedef __int32 ISTDINT32; 53 | #elif defined(__GNUC__) && (__GNUC__ > 3) 54 | #include 55 | typedef uint32_t ISTDUINT32; 56 | typedef int32_t ISTDINT32; 57 | #else 58 | typedef unsigned long ISTDUINT32; 59 | typedef long ISTDINT32; 60 | #endif 61 | #endif 62 | 63 | 64 | //===================================================================== 65 | // Integer Definition 66 | //===================================================================== 67 | #ifndef __IINT8_DEFINED 68 | #define __IINT8_DEFINED 69 | typedef char IINT8; 70 | #endif 71 | 72 | #ifndef __IUINT8_DEFINED 73 | #define __IUINT8_DEFINED 74 | typedef unsigned char IUINT8; 75 | #endif 76 | 77 | #ifndef __IUINT16_DEFINED 78 | #define __IUINT16_DEFINED 79 | typedef unsigned short IUINT16; 80 | #endif 81 | 82 | #ifndef __IINT16_DEFINED 83 | #define __IINT16_DEFINED 84 | typedef short IINT16; 85 | #endif 86 | 87 | #ifndef __IINT32_DEFINED 88 | #define __IINT32_DEFINED 89 | typedef ISTDINT32 IINT32; 90 | #endif 91 | 92 | #ifndef __IUINT32_DEFINED 93 | #define __IUINT32_DEFINED 94 | typedef ISTDUINT32 IUINT32; 95 | #endif 96 | 97 | 98 | /*====================================================================*/ 99 | /* LIST DEFINITION */ 100 | /*====================================================================*/ 101 | #ifndef __ILIST_DEF__ 102 | #define __ILIST_DEF__ 103 | 104 | struct ILISTHEAD { 105 | struct ILISTHEAD *next, *prev; 106 | }; 107 | 108 | typedef struct ILISTHEAD ilist_head; 109 | 110 | 111 | /*--------------------------------------------------------------------*/ 112 | /* list init */ 113 | /*--------------------------------------------------------------------*/ 114 | #define ILIST_HEAD_INIT(name) { &(name), &(name) } 115 | #define ILIST_HEAD(name) \ 116 | struct ILISTHEAD name = ILIST_HEAD_INIT(name) 117 | 118 | #define ILIST_INIT(ptr) ( \ 119 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 120 | 121 | #if (!defined(offsetof)) || (defined(IHAVE_NOT_OFFSETOF)) 122 | #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 123 | #else 124 | #define IOFFSETOF(TYPE, MEMBER) offsetof(TYPE, MEMBER) 125 | #endif 126 | 127 | #define ICONTAINEROF(ptr, type, member) ( \ 128 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 129 | 130 | #define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 131 | 132 | 133 | /*--------------------------------------------------------------------*/ 134 | /* list operation */ 135 | /*--------------------------------------------------------------------*/ 136 | #define ILIST_ADD(node, head) ( \ 137 | (node)->prev = (head), (node)->next = (head)->next, \ 138 | (head)->next->prev = (node), (head)->next = (node)) 139 | 140 | #define ILIST_ADD_TAIL(node, head) ( \ 141 | (node)->prev = (head)->prev, (node)->next = (head), \ 142 | (head)->prev->next = (node), (head)->prev = (node)) 143 | 144 | #define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 145 | 146 | #define ILIST_DEL(entry) (\ 147 | (entry)->next->prev = (entry)->prev, \ 148 | (entry)->prev->next = (entry)->next, \ 149 | (entry)->next = 0, (entry)->prev = 0) 150 | 151 | #define ILIST_DEL_INIT(entry) do { \ 152 | ILIST_DEL(entry); ILIST_INIT(entry); } while (0) 153 | 154 | #define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) 155 | 156 | #define ilist_init ILIST_INIT 157 | #define ilist_entry ILIST_ENTRY 158 | #define ilist_add ILIST_ADD 159 | #define ilist_add_tail ILIST_ADD_TAIL 160 | #define ilist_del ILIST_DEL 161 | #define ilist_del_init ILIST_DEL_INIT 162 | #define ilist_is_empty ILIST_IS_EMPTY 163 | 164 | #define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ 165 | for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ 166 | &((iterator)->MEMBER) != (head); \ 167 | (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 168 | 169 | #define ilist_foreach(iterator, head, TYPE, MEMBER) \ 170 | ILIST_FOREACH(iterator, head, TYPE, MEMBER) 171 | 172 | #define ilist_foreach_entry(pos, head) \ 173 | for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) 174 | 175 | 176 | #define __ilist_splice(list, head) do { \ 177 | ilist_head *first = (list)->next, *last = (list)->prev; \ 178 | ilist_head *at = (head)->next; \ 179 | (first)->prev = (head), (head)->next = (first); \ 180 | (last)->next = (at), (at)->prev = (last); } while (0) 181 | 182 | #define ilist_splice(list, head) do { \ 183 | if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) 184 | 185 | #define ilist_splice_init(list, head) do { \ 186 | ilist_splice(list, head); ilist_init(list); } while (0) 187 | 188 | 189 | #ifdef _MSC_VER 190 | #pragma warning(disable:4311) 191 | #pragma warning(disable:4312) 192 | #pragma warning(disable:4996) 193 | #endif 194 | 195 | #endif 196 | 197 | 198 | //===================================================================== 199 | // Timer Vector 200 | //===================================================================== 201 | #define ITVN_BITS 6 202 | #define ITVR_BITS 8 203 | #define ITVN_SIZE (1 << ITVN_BITS) 204 | #define ITVR_SIZE (1 << ITVR_BITS) 205 | #define ITVN_MASK (ITVN_SIZE - 1) 206 | #define ITVR_MASK (ITVR_SIZE - 1) 207 | 208 | struct itimer_vec { 209 | ilist_head vec[ITVN_SIZE]; 210 | }; 211 | 212 | struct itimer_vec_root { 213 | ilist_head vec[ITVR_SIZE]; 214 | }; 215 | 216 | struct itimer_core { 217 | IUINT32 timer_jiffies; 218 | struct itimer_vec *tvecs[6]; 219 | struct itimer_vec_root tv1; 220 | struct itimer_vec tv2; 221 | struct itimer_vec tv3; 222 | struct itimer_vec tv4; 223 | struct itimer_vec tv5; 224 | }; 225 | 226 | struct itimer_node { 227 | ilist_head head; 228 | IUINT32 expires; 229 | IUINT32 state; 230 | void *data; 231 | void (*callback)(void *data); 232 | struct itimer_core *core; 233 | }; 234 | 235 | 236 | //===================================================================== 237 | // global definition 238 | //===================================================================== 239 | typedef struct itimer_core itimer_core; 240 | typedef struct itimer_node itimer_node; 241 | 242 | #define itimer_core_jiffies(core) ((core)->jiffies) 243 | #define itimer_node_pending(node) (!iqueue_is_empty(&(node)->head)) 244 | 245 | 246 | #ifdef __cplusplus 247 | extern "C" { 248 | #endif 249 | 250 | //===================================================================== 251 | // Core Timer 252 | //===================================================================== 253 | 254 | // initialize timer core 255 | void itimer_core_init(itimer_core *core, IUINT32 jiffies); 256 | 257 | // destroy timer core 258 | void itimer_core_destroy(itimer_core *core); 259 | 260 | // run timer core 261 | void itimer_core_run(itimer_core *core, IUINT32 jiffies); 262 | 263 | // how many jiffies to the nearest node (approximately) 264 | IUINT32 itimer_core_nearest(const itimer_core *core, IUINT32 limit); 265 | 266 | 267 | // initialize node 268 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data); 269 | 270 | // destroy node 271 | void itimer_node_destroy(itimer_node *node); 272 | 273 | // add node to core 274 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires); 275 | 276 | // remove node from core 277 | int itimer_node_del(itimer_core *core, itimer_node *node); 278 | 279 | // modify node 280 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires); 281 | 282 | 283 | 284 | //===================================================================== 285 | // Timer Manager 286 | //===================================================================== 287 | struct itimer_mgr 288 | { 289 | IUINT32 interval; 290 | IUINT32 current; 291 | IUINT32 millisec; 292 | IUINT32 jiffies; 293 | IUINT32 counter; 294 | int initialized; 295 | itimer_core core; 296 | }; 297 | 298 | struct itimer_evt 299 | { 300 | IUINT32 period; 301 | IUINT32 slap; 302 | int repeat; 303 | int running; 304 | void (*callback)(void *data, void *user); 305 | void *data; 306 | void *user; 307 | struct itimer_mgr *mgr; 308 | itimer_node node; 309 | }; 310 | 311 | // type defines 312 | typedef struct itimer_mgr itimer_mgr; 313 | typedef struct itimer_evt itimer_evt; 314 | 315 | // initialize timer manager 316 | // interval - internal working interval 317 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval); 318 | 319 | // destroy timer manager 320 | void itimer_mgr_destroy(itimer_mgr *mgr); 321 | 322 | // run timer events: 323 | // millisec - current time stamp 324 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec); 325 | 326 | 327 | // initialize timer event 328 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 329 | void *data, void *user); 330 | 331 | // destroy timer event 332 | void itimer_evt_destroy(itimer_evt *evt); 333 | 334 | // start timer: repeat <= 0 (infinite repeat) 335 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 336 | IUINT32 period, int repeat); 337 | 338 | // stop timer 339 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt); 340 | 341 | // returns 0 for stopped and 1 for running 342 | int itimer_evt_status(const itimer_evt *evt); 343 | 344 | 345 | #ifdef __cplusplus 346 | } 347 | #endif 348 | 349 | #endif 350 | 351 | 352 | -------------------------------------------------------------------------------- /system/itoolbox.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itoolbox.h - 4 | // 5 | // Created by skywind on 2019/06/12 6 | // Last Modified: 2019/06/12 20:18:52 7 | // 8 | //===================================================================== 9 | #ifndef _ITOOLBOX_H_ 10 | #define _ITOOLBOX_H_ 11 | 12 | #include "imembase.h" 13 | #include "imemdata.h" 14 | #include "inetbase.h" 15 | #include "inetcode.h" 16 | #include "isecure.h" 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | //===================================================================== 24 | // Posix IPV4/IPV6 Compatible Socket Address 25 | //===================================================================== 26 | typedef union _iPosixAddress { 27 | struct sockaddr sa; 28 | struct sockaddr_in sin4; 29 | #ifdef AF_INET6 30 | struct sockaddr_in6 sin6; 31 | #endif 32 | } iPosixAddress; 33 | 34 | 35 | // get family from generic sockaddr 36 | #define iposix_addr_family(pa) ((pa)->sa.sa_family) 37 | 38 | #define iposix_addr_v4_ptr(pa) (&((pa)->sin4.sin_addr.s_addr)) 39 | #define iposix_addr_v4_vec(type, pa) ((type*)iposix_addr_v4_ptr(pa)) 40 | #define iposix_addr_v4_port(pa) ((pa)->sin4.sin_port) 41 | #define iposix_addr_v4_u8(pa) iposix_addr_v4_vec(unsigned char, pa) 42 | #define iposix_addr_v4_cu8(pa) iposix_addr_v4_vec(const unsigned char, pa) 43 | 44 | #ifdef AF_INET6 45 | #define iposix_addr_v6_ptr(pa) (((pa)->sin6.sin6_addr.s6_addr)) 46 | #define iposix_addr_v6_vec(type, pa) ((type*)iposix_addr_v6_ptr(pa)) 47 | #define iposix_addr_v6_port(pa) ((pa)->sin6.sin6_port) 48 | #define iposix_addr_v6_u8(pa) iposix_addr_v6_vec(unsigned char, pa) 49 | #define iposix_addr_v6_cu8(pa) iposix_addr_v6_vec(const unsigned char, pa) 50 | 51 | #define iposix_addr_size(pa) \ 52 | ((iposix_addr_family(pa) == AF_INET6)? \ 53 | sizeof(struct sockaddr_in6) : sizeof(struct sockaddr)) 54 | #else 55 | #define iposix_addr_size(pa) (sizeof(struct sockaddr)) 56 | #endif 57 | 58 | 59 | // memset(addr, 0, sizeof(iPosixAddress)) 60 | void iposix_addr_init(iPosixAddress *addr); 61 | 62 | void iposix_addr_set_family(iPosixAddress *addr, int family); 63 | void iposix_addr_set_ip(iPosixAddress *addr, const void *ip); 64 | void iposix_addr_set_port(iPosixAddress *addr, int port); 65 | void iposix_addr_set_scope(iPosixAddress *addr, int scope_id); 66 | 67 | int iposix_addr_get_family(const iPosixAddress *addr); 68 | int iposix_addr_get_ip(const iPosixAddress *addr, void *ip); 69 | int iposix_addr_get_port(const iPosixAddress *addr); 70 | int iposix_addr_get_size(const iPosixAddress *addr); 71 | int iposix_addr_get_scope(const iPosixAddress *addr); 72 | 73 | int iposix_addr_set_ip_text(iPosixAddress *addr, const char *text); 74 | char *iposix_addr_get_ip_text(const iPosixAddress *addr, char *text); 75 | 76 | int iposix_addr_make(iPosixAddress *addr, int family, const char *t, int p); 77 | char *iposix_addr_str(const iPosixAddress *addr, char *text); 78 | 79 | 80 | // returns zero if a1 equals to a2 81 | // returns 1 if a1 is greater than a2 82 | // returns -1 if a1 is less than a2 83 | int iposix_addr_compare(const iPosixAddress *a1, const iPosixAddress *a2); 84 | 85 | // returns 6 if the text contains colon (an IPv6 address string) 86 | // otherwise returns 4 87 | int iposix_addr_version(const char *text); 88 | 89 | 90 | //===================================================================== 91 | // DNS Resolve 92 | //===================================================================== 93 | typedef struct _iPosixRes 94 | { 95 | int size; 96 | int *family; 97 | unsigned char **address; 98 | } iPosixRes; 99 | 100 | // create new iPosixRes 101 | iPosixRes *iposix_res_new(int size); 102 | 103 | // remove res 104 | void iposix_res_free(iPosixRes *res); 105 | 106 | // omit duplications 107 | void iposix_res_unique(iPosixRes *res); 108 | 109 | 110 | // ipv = 0/any, 4/ipv4, 6/ipv6 111 | iPosixRes *iposix_res_get(const char *hostname, int ipv); 112 | 113 | 114 | //===================================================================== 115 | // Protocol Reader 116 | //===================================================================== 117 | struct CAsyncReader; 118 | typedef struct CAsyncReader CAsyncReader; 119 | 120 | CAsyncReader *async_reader_new(ib_memnode *fnode); 121 | 122 | void async_reader_delete(CAsyncReader *reader); 123 | 124 | 125 | #define ISTREAM_READ_BYTE 0 126 | #define ISTREAM_READ_LINE 1 127 | #define ISTREAM_READ_BLOCK 2 128 | 129 | void async_reader_mode(CAsyncReader *reader, int mode, ilong what); 130 | 131 | long async_reader_read(CAsyncReader *reader, void *data, long maxsize); 132 | 133 | void async_reader_feed(CAsyncReader *reader, const void *data, long len); 134 | 135 | void async_reader_clear(CAsyncReader *reader); 136 | 137 | 138 | //===================================================================== 139 | // utils 140 | //===================================================================== 141 | 142 | int isocket_pair_ex(int *pair); 143 | 144 | // can be used to wakeup select 145 | struct CSelectNotify; 146 | typedef struct CSelectNotify CSelectNotify; 147 | 148 | CSelectNotify* select_notify_new(void); 149 | 150 | void select_notify_delete(CSelectNotify *sn); 151 | 152 | int select_notify_wait(CSelectNotify *sn, const int *fds, 153 | const int *event, int *revent, int count, long millisec); 154 | 155 | int select_notify_wake(CSelectNotify *sn); 156 | 157 | 158 | //===================================================================== 159 | // Terminal Control 160 | //===================================================================== 161 | 162 | // colors 163 | #define CTEXT_BLACK 0 164 | #define CTEXT_RED 1 165 | #define CTEXT_GREEN 2 166 | #define CTEXT_YELLOW 3 167 | #define CTEXT_BLUE 4 168 | #define CTEXT_MAGENTA 5 169 | #define CTEXT_CYAN 6 170 | #define CTEXT_WHITE 7 171 | #define CTEXT_BOLD 8 172 | #define CTEXT_BOLD_RED 9 173 | #define CTEXT_BOLD_GREEN 10 174 | #define CTEXT_BOLD_YELLO 11 175 | #define CTEXT_BOLD_BLUE 12 176 | #define CTEXT_BOLD_MAGENTA 13 177 | #define CTEXT_BOLD_CYAN 14 178 | #define CTEXT_BOLD_WHITE 15 179 | 180 | // 背景颜色定义 181 | #define CBG_BLACK 0 182 | #define CBG_RED (1 << 4) 183 | #define CBG_GREEN (2 << 4) 184 | #define CBG_YELLO (3 << 4) 185 | #define CBG_BLUE (4 << 4) 186 | #define CBG_MAGENTA (5 << 4) 187 | #define CBG_CYAN (6 << 4) 188 | #define CBG_WHITE (7 << 4) 189 | 190 | 191 | // 设置颜色:低4位是文字颜色,高4位是背景颜色 192 | // 具体编码可以搜索 ansi color或者 193 | // http://en.wikipedia.org/wiki/ANSI_escape_code 194 | void console_set_color(int color); 195 | 196 | 197 | // 设置光标位置左上角是,行与列都是从1开始计数的 198 | void console_cursor(int row, int col); 199 | 200 | // 恢复屏幕颜色 201 | void console_reset(void); 202 | 203 | // 清屏 204 | void console_clear(int color); 205 | 206 | 207 | //===================================================================== 208 | // utilities 209 | //===================================================================== 210 | 211 | // generate a 40 bytes signature 212 | char* hash_signature_md5( 213 | char *out, // output string with size above 41 bytes 214 | const void *in, // input data 215 | int size, // input size 216 | const char *secret, // secret token 217 | int secret_size, // secret size 218 | IUINT32 timestamp); // time stamp in unix epoch seconds 219 | 220 | // extract timestamp from signature 221 | IUINT32 hash_signature_time(const char *signature); 222 | 223 | 224 | //--------------------------------------------------------------------- 225 | // signals 226 | //--------------------------------------------------------------------- 227 | void signal_init(); 228 | int signal_quiting(); 229 | 230 | 231 | #ifdef __cplusplus 232 | } 233 | #endif 234 | 235 | #endif 236 | 237 | 238 | -------------------------------------------------------------------------------- /tools/AsyncLoader.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/AsyncNet/b45260de0c70ef25fd1282ddcb48931f42d78271/tools/AsyncLoader.h -------------------------------------------------------------------------------- /tools/AsyncLoader.i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/AsyncNet/b45260de0c70ef25fd1282ddcb48931f42d78271/tools/AsyncLoader.i -------------------------------------------------------------------------------- /tools/GenLoader.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skywind3000/AsyncNet/b45260de0c70ef25fd1282ddcb48931f42d78271/tools/GenLoader.py -------------------------------------------------------------------------------- /tools/GenerateC.bat: -------------------------------------------------------------------------------- 1 | python GenLoader.py AsyncLoader.i 2 | 3 | --------------------------------------------------------------------------------