├── .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 |
--------------------------------------------------------------------------------