├── .gitignore ├── LICENSE ├── README.md ├── common ├── ByteArray.h ├── KernelTimer.cpp ├── KernelTimer.h ├── PacketBuffer.h ├── QuickTimer.cpp ├── QuickTimer.h └── RingBuf.h ├── module ├── fec.c ├── fec.h ├── rs.c └── rs.h ├── network ├── Combinator.cpp ├── Combinator.h ├── FecCodec.cpp ├── FecCodec.h ├── FecCodecBuf.cpp ├── FecCodecBuf.h ├── FecPacket.cpp ├── FecPacket.h ├── FecTransmission.cpp ├── FecTransmission.h ├── NePingRouter.cpp ├── NePingRouter.h ├── NetFecCodec.cpp ├── NetFecCodec.h ├── PacketBuffer.h ├── ProtocolBasic.cpp ├── ProtocolBasic.h ├── ProtocolImp.cpp ├── ProtocolImp.h ├── QuickNet.cpp ├── QuickNet.h ├── QuickValidate.cpp ├── RequestRepeat.cpp ├── RequestRepeat.h ├── SessionDesc.cpp ├── SessionDesc.h ├── SessionManager.cpp ├── SessionManager.h ├── TransportUdp.cpp └── TransportUdp.h └── system ├── fec.c ├── fec.h ├── imembase.c ├── imembase.h ├── imemdata.c ├── imemdata.h ├── inetbase.c ├── inetbase.h ├── inetcode.c ├── inetcode.h ├── inetkcp.c ├── inetkcp.h ├── inetnot.c ├── inetnot.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 /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Linwei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickNet 2 | UDP Networking Library 3 | -------------------------------------------------------------------------------- /common/KernelTimer.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // KernelTimer.cpp - 4 | // 5 | // Last Modified: 2019/06/18 10:31:13 6 | // 7 | //===================================================================== 8 | #include "KernelTimer.h" 9 | #include 10 | 11 | NAMESPACE_BEGIN(AsyncNet); 12 | //--------------------------------------------------------------------- 13 | // 14 | //--------------------------------------------------------------------- 15 | KernelTimer::KernelTimer(Callback cb, void *obj, int reserved) 16 | { 17 | itimer_mgr_init(&_timer_mgr, 0, 1); 18 | _cb_fn = cb; 19 | _cb_obj = obj; 20 | _reserved = reserved; 21 | _index = reserved; 22 | _static_nodes.resize(reserved); 23 | for (int i = 0; i < reserved; i++) { 24 | Node *node = new Node(); 25 | node->id = i; 26 | node->tag = -1; 27 | node->repeat = 0; 28 | itimer_evt_init(&node->evt, _timer_callback, this, node); 29 | _static_nodes[i] = node; 30 | } 31 | } 32 | 33 | 34 | //--------------------------------------------------------------------- 35 | // 36 | //--------------------------------------------------------------------- 37 | KernelTimer::~KernelTimer() 38 | { 39 | while (!_timer_map.empty()) { 40 | Node *node = _timer_map.begin()->second; 41 | _node_delete(node->id); 42 | } 43 | _timer_map.clear(); 44 | for (int i = 0; i < (int)_static_nodes.size(); i++) { 45 | Node *node = _static_nodes[i]; 46 | if (node) { 47 | itimer_evt_destroy(&node->evt); 48 | delete node; 49 | } 50 | _static_nodes[i] = NULL; 51 | } 52 | itimer_mgr_destroy(&_timer_mgr); 53 | } 54 | 55 | 56 | //--------------------------------------------------------------------- 57 | // alloc node 58 | //--------------------------------------------------------------------- 59 | int KernelTimer::_node_alloc() 60 | { 61 | size_t limit = 0x7ffffff0 - _reserved; 62 | if (_timer_map.size() >= limit) 63 | return -1; 64 | while (1) { 65 | _index++; 66 | _index = std::max(_index, _reserved); 67 | if (_index >= 0x7fffffff) _index = _reserved; 68 | if (_node_find(_index) == NULL) { 69 | break; 70 | } 71 | } 72 | Node *node = new Node(); 73 | node->id = _index; 74 | node->tag = -1; 75 | node->repeat = 0; 76 | itimer_evt_init(&node->evt, _timer_callback, this, node); 77 | _timer_map[_index] = node; 78 | return _index; 79 | } 80 | 81 | 82 | //--------------------------------------------------------------------- 83 | // delete node 84 | //--------------------------------------------------------------------- 85 | int KernelTimer::_node_delete(int id) 86 | { 87 | if (id >= 0 && id < _reserved) { 88 | Node *node = _static_nodes[id]; 89 | if (node) { 90 | itimer_evt_stop(&_timer_mgr, &node->evt); 91 | } 92 | } 93 | else { 94 | TimerMap::iterator it = _timer_map.find(id); 95 | if (it == _timer_map.end()) 96 | return -1; 97 | Node *node = it->second; 98 | if (node) { 99 | itimer_evt_destroy(&node->evt); 100 | node->id = -1; 101 | delete node; 102 | } 103 | it->second = NULL; 104 | _timer_map.erase(it); 105 | } 106 | return 0; 107 | } 108 | 109 | 110 | //--------------------------------------------------------------------- 111 | // find 112 | //--------------------------------------------------------------------- 113 | KernelTimer::Node* KernelTimer::_node_find(int id) 114 | { 115 | if (id >= 0 && id < _reserved) { 116 | return _static_nodes[id]; 117 | } 118 | else { 119 | TimerMap::iterator it = _timer_map.find(id); 120 | if (it == _timer_map.end()) 121 | return NULL; 122 | return it->second; 123 | } 124 | } 125 | 126 | 127 | //--------------------------------------------------------------------- 128 | // find const 129 | //--------------------------------------------------------------------- 130 | const KernelTimer::Node* KernelTimer::_node_find(int id) const 131 | { 132 | if (id >= 0 && id < _reserved) { 133 | return _static_nodes[id]; 134 | } 135 | else { 136 | TimerMap::const_iterator it = _timer_map.find(id); 137 | if (it == _timer_map.end()) 138 | return NULL; 139 | return it->second; 140 | } 141 | } 142 | 143 | 144 | //--------------------------------------------------------------------- 145 | // 运行时钟 146 | //--------------------------------------------------------------------- 147 | void KernelTimer::run(uint32_t current) 148 | { 149 | _pending_remove.resize(0); 150 | itimer_mgr_run(&_timer_mgr, current); 151 | for (int i = 0; i < (int)_pending_remove.size(); i++) { 152 | int id = _pending_remove[i]; 153 | _node_delete(id); 154 | } 155 | } 156 | 157 | 158 | //--------------------------------------------------------------------- 159 | // static timer callback 160 | //--------------------------------------------------------------------- 161 | void KernelTimer::_timer_callback(void *data, void *user) 162 | { 163 | KernelTimer *self = reinterpret_cast(data); 164 | self->handle_timer(user); 165 | } 166 | 167 | 168 | //--------------------------------------------------------------------- 169 | // 执行时钟 170 | //--------------------------------------------------------------------- 171 | void KernelTimer::handle_timer(void *node) 172 | { 173 | Node *n = reinterpret_cast(node); 174 | if (_cb_fn) { 175 | _cb_fn(_cb_obj, n->id, n->tag); 176 | } 177 | } 178 | 179 | 180 | //--------------------------------------------------------------------- 181 | // 分配时钟 182 | //--------------------------------------------------------------------- 183 | int KernelTimer::create(int tag) 184 | { 185 | int id = _node_alloc(); 186 | if (id < 0) return -1; 187 | Node *node = _node_find(id); 188 | assert(node); 189 | node->tag = tag; 190 | return id; 191 | } 192 | 193 | 194 | //--------------------------------------------------------------------- 195 | // kill 196 | //--------------------------------------------------------------------- 197 | int KernelTimer::kill(int id) 198 | { 199 | return _node_delete(id); 200 | } 201 | 202 | 203 | //--------------------------------------------------------------------- 204 | // start 205 | //--------------------------------------------------------------------- 206 | int KernelTimer::start(int id, unsigned int period, int repeat) 207 | { 208 | Node *node = _node_find(id); 209 | if (node == NULL) { 210 | return -1; 211 | } 212 | itimer_evt_start(&_timer_mgr, &node->evt, period, repeat); 213 | node->repeat = (repeat <= 0)? -1 : repeat; 214 | return 0; 215 | } 216 | 217 | 218 | //--------------------------------------------------------------------- 219 | // stop 220 | //--------------------------------------------------------------------- 221 | int KernelTimer::stop(int id) 222 | { 223 | Node *node = _node_find(id); 224 | if (node == NULL) { 225 | return -1; 226 | } 227 | itimer_evt_stop(&_timer_mgr, &node->evt); 228 | return 0; 229 | } 230 | 231 | 232 | //--------------------------------------------------------------------- 233 | // 234 | //--------------------------------------------------------------------- 235 | int KernelTimer::set_tag(int id, int tag) 236 | { 237 | Node *node = _node_find(id); 238 | if (node == NULL) { 239 | return -1; 240 | } 241 | node->tag = tag; 242 | return 0; 243 | } 244 | 245 | 246 | //--------------------------------------------------------------------- 247 | // 检测是否存在 248 | //--------------------------------------------------------------------- 249 | bool KernelTimer::check_exists(int id) const 250 | { 251 | const Node *node = _node_find(id); 252 | return (node != NULL)? true : false; 253 | } 254 | 255 | 256 | //--------------------------------------------------------------------- 257 | // 检测是否活动 258 | //--------------------------------------------------------------------- 259 | bool KernelTimer::check_started(int id) const 260 | { 261 | const Node *node = _node_find(id); 262 | if (node == NULL) return false; 263 | if (node->evt.mgr == NULL) return false; 264 | return true; 265 | } 266 | 267 | 268 | 269 | NAMESPACE_END(AsyncNet); 270 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /common/KernelTimer.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // KernelTimer.h - 时钟轮封装 4 | // 5 | // Last Modified: 2019/06/18 10:30:34 6 | // 7 | //===================================================================== 8 | #ifndef _KERNEL_TIMER_H_ 9 | #define _KERNEL_TIMER_H_ 10 | 11 | #include "../system/itimer.h" 12 | #include "../system/system.h" 13 | 14 | #include 15 | #include 16 | 17 | 18 | NAMESPACE_BEGIN(AsyncNet); 19 | 20 | //--------------------------------------------------------------------- 21 | // KernelTimer 22 | //--------------------------------------------------------------------- 23 | class KernelTimer 24 | { 25 | public: 26 | virtual ~KernelTimer(); 27 | 28 | typedef void (*Callback)(void *obj, int id, int tag); 29 | 30 | KernelTimer(Callback cb, void *obj, int reserved = 1024); 31 | 32 | public: 33 | // 传入当前毫秒级时钟,32位整数,支持时钟回环 34 | void run(uint32_t current); 35 | 36 | // 分配时钟 37 | int create(int tag); 38 | 39 | // kill 40 | int kill(int id); 41 | 42 | // start 43 | int start(int id, unsigned int period, int repeat); 44 | 45 | // stop 46 | int stop(int id); 47 | 48 | // tag 49 | int set_tag(int id, int tag); 50 | 51 | // 检测是否存在 52 | bool check_exists(int id) const; 53 | 54 | // 检测是否活动 55 | bool check_started(int id) const; 56 | 57 | protected: 58 | KernelTimer(const KernelTimer &); 59 | 60 | Callback _cb_fn; 61 | void *_cb_obj; 62 | 63 | static void _timer_callback(void *data, void *user); 64 | void handle_timer(void *node); 65 | 66 | int _node_alloc(); 67 | int _node_delete(int id); 68 | 69 | struct Node { itimer_evt evt; int id; int tag; int repeat; }; 70 | Node *_node_find(int id); 71 | const Node *_node_find(int id) const; 72 | 73 | protected: 74 | itimer_mgr _timer_mgr; 75 | int _index; 76 | int _reserved; 77 | typedef std::unordered_map TimerMap; 78 | TimerMap _timer_map; 79 | std::vector _static_nodes; 80 | std::vector _pending_remove; 81 | }; 82 | 83 | 84 | NAMESPACE_END(AsyncNet); 85 | 86 | 87 | #endif 88 | 89 | 90 | -------------------------------------------------------------------------------- /common/QuickTimer.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // QuickTimer.cpp - 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #include "QuickTimer.h" 10 | #include 11 | 12 | namespace System { 13 | 14 | //--------------------------------------------------------------------- 15 | // init 16 | //--------------------------------------------------------------------- 17 | QuickTimerScheduler::QuickTimerScheduler() : 18 | _timer_mgr(std::make_unique()) 19 | { 20 | itimer_mgr_init(_timer_mgr.get(), 1); 21 | } 22 | 23 | 24 | //--------------------------------------------------------------------- 25 | // destroy 26 | //--------------------------------------------------------------------- 27 | QuickTimerScheduler::~QuickTimerScheduler() 28 | { 29 | itimer_mgr_destroy(_timer_mgr.get()); 30 | } 31 | 32 | 33 | //--------------------------------------------------------------------- 34 | // update timer 35 | //--------------------------------------------------------------------- 36 | void QuickTimerScheduler::Update(uint32_t now) 37 | { 38 | itimer_mgr_run(_timer_mgr.get(), now); 39 | } 40 | 41 | 42 | //--------------------------------------------------------------------- 43 | // returns timer manager 44 | //--------------------------------------------------------------------- 45 | itimer_mgr* QuickTimerScheduler::GetTimerManager() 46 | { 47 | return _timer_mgr.get(); 48 | } 49 | 50 | 51 | //--------------------------------------------------------------------- 52 | // init timer 53 | //--------------------------------------------------------------------- 54 | QuickTimer::QuickTimer(QuickTimerScheduler *scheduler) : 55 | _timer_id(std::make_unique()), 56 | _scheduler(scheduler) 57 | { 58 | itimer_evt_init(_timer_id.get(), TimerCallback, this, NULL); 59 | } 60 | 61 | 62 | //--------------------------------------------------------------------- 63 | // releae timer: remove itself from scheduler 64 | //--------------------------------------------------------------------- 65 | QuickTimer::~QuickTimer() 66 | { 67 | itimer_evt_destroy(_timer_id.get()); 68 | } 69 | 70 | 71 | //--------------------------------------------------------------------- 72 | // start timer 73 | //--------------------------------------------------------------------- 74 | void QuickTimer::StartTimer(uint32_t period, int repeat) 75 | { 76 | itimer_evt_start(_scheduler->GetTimerManager(), _timer_id.get(), period, repeat); 77 | } 78 | 79 | 80 | //--------------------------------------------------------------------- 81 | // stop timer 82 | //--------------------------------------------------------------------- 83 | void QuickTimer::StopTimer() 84 | { 85 | itimer_evt_stop(_scheduler->GetTimerManager(), _timer_id.get()); 86 | } 87 | 88 | 89 | //--------------------------------------------------------------------- 90 | // returns true if the timer is running 91 | //--------------------------------------------------------------------- 92 | bool QuickTimer::IsRunning() const 93 | { 94 | if (_scheduler) { 95 | return itimer_evt_status(_timer_id.get())? true : false; 96 | } 97 | return false; 98 | } 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // callback 103 | //--------------------------------------------------------------------- 104 | void QuickTimer::TimerCallback(void *data, void *user) 105 | { 106 | if (data) { 107 | QuickTimer *timer = (QuickTimer*)data; 108 | if (timer->_callback) { 109 | timer->_callback(timer, user); 110 | } 111 | } 112 | } 113 | 114 | 115 | 116 | //--------------------------------------------------------------------- 117 | // bind callback 118 | //--------------------------------------------------------------------- 119 | void QuickTimer::Bind(OnTimer func, void *user) 120 | { 121 | _callback = func; 122 | _user = user; 123 | } 124 | 125 | 126 | } 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /common/QuickTimer.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // QuickTimer.h - 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef _QUICK_TIMER_H_ 10 | #define _QUICK_TIMER_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "../system/itimer.h" 17 | 18 | 19 | namespace System { 20 | 21 | //--------------------------------------------------------------------- 22 | // timer scheduler 23 | //--------------------------------------------------------------------- 24 | class QuickTimerScheduler 25 | { 26 | public: 27 | QuickTimerScheduler(); 28 | virtual ~QuickTimerScheduler(); 29 | 30 | void Update(uint32_t now); 31 | 32 | itimer_mgr* GetTimerManager(); 33 | 34 | private: 35 | std::unique_ptr _timer_mgr; 36 | }; 37 | 38 | 39 | //--------------------------------------------------------------------- 40 | // timer event 41 | //--------------------------------------------------------------------- 42 | class QuickTimer 43 | { 44 | public: 45 | typedef std::function OnTimer; 46 | 47 | QuickTimer(QuickTimerScheduler *scheduler); 48 | virtual ~QuickTimer(); 49 | 50 | void Bind(OnTimer func, void *user = NULL); 51 | 52 | void StartTimer(uint32_t period, int repeat); 53 | void StopTimer(); 54 | bool IsRunning() const; 55 | 56 | private: 57 | static void TimerCallback(void *data, void *user); 58 | 59 | private: 60 | std::unique_ptr _timer_id; 61 | OnTimer _callback; 62 | QuickTimerScheduler *_scheduler; 63 | void *_user; 64 | }; 65 | 66 | 67 | 68 | } 69 | 70 | 71 | #endif 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /common/RingBuf.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // RingBuf.h - 4 | // 5 | // Last Modified: 2019/06/28 15:20:14 6 | // 7 | //===================================================================== 8 | #ifndef _RINGBUF_H_ 9 | #define _RINGBUF_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | 19 | namespace AsyncNet { 20 | //--------------------------------------------------------------------- 21 | // 环状缓存 22 | //--------------------------------------------------------------------- 23 | class RingBuffer 24 | { 25 | public: 26 | inline virtual ~RingBuffer(); 27 | inline RingBuffer(); 28 | inline RingBuffer(const RingBuffer &ring); 29 | inline RingBuffer& operator=(const RingBuffer &ring); 30 | 31 | #if __cplusplus >= 201100 32 | inline RingBuffer(RingBuffer &&ring); 33 | #endif 34 | 35 | 36 | public: 37 | inline int write(const void *ptr, int size); // 写入数据 38 | inline int read(void *ptr, int size); // 读取数据 (移动指针) 39 | inline int peek(void *ptr, int size) const; // 取得数据 (指针不变) 40 | inline int skip(int size); // 移动读指针 41 | inline int advance(int size); // 移动写指针 42 | 43 | inline int size() const; // 数据长度 44 | inline int capacity() const; // 缓存长度 45 | inline int space() const; // 可写长度:max(0, capacity - size - 1) 46 | 47 | inline int flat(void **pointer) const; // 取得空闲平面指针 48 | inline void reset(); // 复位 49 | inline bool resize(int size); // 改变大小 50 | 51 | // reader 指针加上偏移的位置 52 | inline unsigned char& operator[](int offset); 53 | inline const unsigned char& operator[](int offset) const; 54 | 55 | inline bool has_size(int required) const; // 是否有足够字节数的数据 56 | inline bool has_space(int required) const; // 是否有足够字节数的剩余空间 57 | 58 | inline void assert_size(int require) const; // 没有足够数据就异常 59 | inline void assert_space(int require) const; // 没有足够可写空间就异常 60 | 61 | unsigned char& writer(int offset); // 写指针的引用 62 | const unsigned char& writer(int offset) const; 63 | 64 | // 强制写入:如果空间不够就 resize 65 | int forcewrite(const void *ptr, int size); 66 | 67 | // MSB push data to writer 68 | inline void push_uint8(uint8_t c); 69 | inline void push_uint16(uint16_t c); 70 | inline void push_uint24(uint32_t c); 71 | inline void push_uint32(uint32_t c); 72 | 73 | // MSB pop data from reader 74 | inline uint8_t pop_uint8(); 75 | inline uint16_t pop_uint16(); 76 | inline uint32_t pop_uint24(); 77 | inline uint32_t pop_uint32(); 78 | 79 | inline uint8_t peek_uint8() const; 80 | inline uint16_t peek_uint16() const; 81 | inline uint32_t peek_uint24() const; 82 | inline uint32_t peek_uint32() const; 83 | 84 | protected: 85 | unsigned char *_data; 86 | int _size; // 缓存的长度,是2的整数次方,可用长度为 _size - 1 87 | int _mask; // 长度掩码 88 | int _reader; // 读指针 89 | int _writer; // 写指针 90 | }; 91 | 92 | 93 | 94 | //--------------------------------------------------------------------- 95 | // 接口实现 96 | //--------------------------------------------------------------------- 97 | 98 | // 构造 99 | inline RingBuffer::RingBuffer() 100 | { 101 | _data = NULL; 102 | _size = 0; 103 | _mask = 0; 104 | _reader = 0; 105 | _writer = 0; 106 | } 107 | 108 | inline RingBuffer::RingBuffer(const RingBuffer &ring) 109 | { 110 | _data = NULL; 111 | this->operator=(ring); 112 | } 113 | 114 | inline RingBuffer& RingBuffer::operator=(const RingBuffer &ring) 115 | { 116 | if (_data) delete _data; 117 | _data = new unsigned char[ring._size]; 118 | _size = ring._size; 119 | _mask = ring._mask; 120 | _reader = 0; 121 | _writer = ring.size(); 122 | ring.peek(_data, _writer); 123 | return *this; 124 | } 125 | 126 | #if __cplusplus >= 201100 127 | inline RingBuffer::RingBuffer(RingBuffer &&ring) 128 | { 129 | _data = ring._data; 130 | _mask = ring._mask; 131 | _size = ring._size; 132 | _reader = ring._reader; 133 | _writer = ring._writer; 134 | ring._data = NULL; 135 | ring._size = 0; 136 | ring._mask = 0; 137 | ring._reader = 0; 138 | ring._writer = 0; 139 | } 140 | 141 | #endif 142 | 143 | 144 | // 析构 145 | inline RingBuffer::~RingBuffer() 146 | { 147 | if (_data) delete []_data; 148 | _data = NULL; 149 | _size = 0; 150 | _mask = 0; 151 | _reader = 0; 152 | _writer = 0; 153 | } 154 | 155 | // 有多少字节的数据 156 | inline int RingBuffer::size() const 157 | { 158 | return (_size + _writer - _reader) & _mask; 159 | } 160 | 161 | // 总缓存长度 162 | inline int RingBuffer::capacity() const 163 | { 164 | return _size; 165 | } 166 | 167 | // 还可以写多少内容 168 | inline int RingBuffer::space() const 169 | { 170 | int available = _size - size() - 1; 171 | return (available < 0)? 0 : available; 172 | } 173 | 174 | // 读取数据(不删除) 175 | inline int RingBuffer::peek(void *ptr, int size) const 176 | { 177 | unsigned char *lptr = (unsigned char*)ptr; 178 | int canread = this->size(); 179 | int half = _size - _reader; 180 | 181 | if (canread == 0) return 0; 182 | if (size > canread) size = canread; 183 | 184 | if (half >= size) { 185 | if (lptr) memcpy(lptr, _data + _reader, size); 186 | } 187 | else { 188 | ptrdiff_t half = _size - _reader; 189 | if (lptr) { 190 | memcpy(lptr, _data + _reader, half); 191 | memcpy(lptr + half, _data, size - half); 192 | } 193 | } 194 | 195 | return size; 196 | } 197 | 198 | // 跳过数据 199 | inline int RingBuffer::skip(int size) 200 | { 201 | int canread = this->size(); 202 | size = (size > canread)? canread : size; 203 | _reader = (_reader + size) & _mask; 204 | return size; 205 | } 206 | 207 | // 移动写指针 208 | inline int RingBuffer::advance(int size) 209 | { 210 | _writer = (_writer + size) & _mask; 211 | return _writer; 212 | } 213 | 214 | // 读取数据并删除 215 | inline int RingBuffer::read(void *ptr, int size) 216 | { 217 | int canread = this->size(); 218 | if (canread == 0) return 0; 219 | if (size > canread) size = canread; 220 | peek(ptr, size); 221 | _reader = (_reader + size) & _mask; 222 | return size; 223 | } 224 | 225 | // 写数据 226 | inline int RingBuffer::write(const void *ptr, int size) 227 | { 228 | const unsigned char *lptr = (const unsigned char*)ptr; 229 | int canwrite = this->space(); 230 | int half = _size - _writer; 231 | if (canwrite == 0) { 232 | return 0; 233 | } 234 | if (size > canwrite) size = canwrite; 235 | if (lptr != NULL) { 236 | if (half >= size) { 237 | memcpy(_data + _writer, lptr, size); 238 | } else { 239 | memcpy(_data + _writer, lptr, half); 240 | memcpy(_data, lptr + half, size - half); 241 | } 242 | } 243 | _writer = (_writer + size) & _mask; 244 | return size; 245 | } 246 | 247 | 248 | // 取得指针 249 | inline int RingBuffer::flat(void **pointer) const 250 | { 251 | size_t size = this->size(); 252 | size_t half = _size - _reader; 253 | if (size == 0) return 0; 254 | if (pointer) *pointer = (void*)(_data + _reader); 255 | return (half <= size)? half : size; 256 | } 257 | 258 | // 复位指针 259 | inline void RingBuffer::reset() 260 | { 261 | _reader = _writer = 0; 262 | } 263 | 264 | // 调整大小 265 | inline bool RingBuffer::resize(int size) 266 | { 267 | if (size == 0) { 268 | if (_data) delete []_data; 269 | _data = 0; 270 | _size = _mask = 0; 271 | _reader = _writer = 0; 272 | } 273 | else { 274 | int require = size + 1; 275 | int newsize = 64; 276 | for (newsize = 64; newsize < require; ) 277 | newsize = newsize * 2; 278 | unsigned char *data = new unsigned char[newsize]; 279 | if (data == NULL) return false; 280 | int capacity = newsize - 1; 281 | int dsize = this->size(); 282 | int csize = (dsize < capacity)? dsize : capacity; 283 | if (dsize > 0) { 284 | read(data, csize); 285 | } 286 | if (_data) delete []_data; 287 | _data = data; 288 | _size = newsize; 289 | _mask = _size - 1; 290 | _reader = 0; 291 | _writer = csize; 292 | } 293 | return true; 294 | } 295 | 296 | inline unsigned char& RingBuffer::operator[](int offset) 297 | { 298 | return _data[(_reader + offset) & _mask]; 299 | } 300 | 301 | inline const unsigned char& RingBuffer::operator[](int offset) const 302 | { 303 | return _data[(_reader + offset) & _mask]; 304 | } 305 | 306 | inline unsigned char& RingBuffer::writer(int offset) 307 | { 308 | return _data[(_writer + offset) & _mask]; 309 | } 310 | 311 | inline const unsigned char& RingBuffer::writer(int offset) const 312 | { 313 | return _data[(_writer + offset) & _mask]; 314 | } 315 | 316 | 317 | // 强制写入:如果空间不够就 resize 318 | int RingBuffer::forcewrite(const void *ptr, int size) 319 | { 320 | int canwrite = this->space(); 321 | if (canwrite < size) { 322 | resize(this->size() + size); 323 | } 324 | canwrite = this->space(); 325 | if (canwrite < size) { 326 | throw std::out_of_range("RingBuffer resize error"); 327 | } 328 | return write(ptr, size); 329 | } 330 | 331 | 332 | // 是否有足够字节数的数据 333 | inline bool RingBuffer::has_size(int required) const 334 | { 335 | return (size() >= required); 336 | } 337 | 338 | // 是否有足够字节数的剩余空间 339 | inline bool RingBuffer::has_space(int required) const 340 | { 341 | return (space() >= required); 342 | } 343 | 344 | 345 | // 没有足够数据就异常 346 | inline void RingBuffer::assert_size(int required) const 347 | { 348 | if (size() < required) { 349 | throw std::length_error("not enough bytes in RingBuffer"); 350 | } 351 | } 352 | 353 | // 没有足够可写空间就异常 354 | inline void RingBuffer::assert_space(int required) const 355 | { 356 | if (space() < required) { 357 | throw std::length_error("not enough free space in RingBuffer"); 358 | } 359 | } 360 | 361 | // MSB push data to writer 362 | inline void RingBuffer::push_uint8(uint8_t c) 363 | { 364 | assert_space(1); 365 | writer(0) = c; 366 | advance(1); 367 | } 368 | 369 | inline void RingBuffer::push_uint16(uint16_t c) 370 | { 371 | assert_space(2); 372 | writer(0) = (c >> 8) & 0xff; 373 | writer(1) = (c >> 0) & 0xff; 374 | advance(2); 375 | } 376 | 377 | inline void RingBuffer::push_uint24(uint32_t c) 378 | { 379 | assert_space(3); 380 | writer(0) = (c >> 16) & 0xff; 381 | writer(1) = (c >> 8) & 0xff; 382 | writer(2) = (c >> 0) & 0xff; 383 | advance(3); 384 | } 385 | 386 | inline void RingBuffer::push_uint32(uint32_t c) 387 | { 388 | assert_space(4); 389 | writer(0) = (c >> 24) & 0xff; 390 | writer(1) = (c >> 16) & 0xff; 391 | writer(2) = (c >> 8) & 0xff; 392 | writer(3) = (c >> 0) & 0xff; 393 | advance(4); 394 | } 395 | 396 | 397 | // 读取数据但不移动指针 398 | inline uint8_t RingBuffer::peek_uint8() const 399 | { 400 | assert_size(1); 401 | uint8_t c = (*this)[0]; 402 | return c; 403 | } 404 | 405 | inline uint16_t RingBuffer::peek_uint16() const 406 | { 407 | assert_size(2); 408 | uint16_t c1 = (*this)[0]; 409 | uint16_t c2 = (*this)[1]; 410 | return (c1 << 8) | c2; 411 | } 412 | 413 | inline uint32_t RingBuffer::peek_uint24() const 414 | { 415 | assert_size(3); 416 | uint32_t c1 = (*this)[0]; 417 | uint32_t c2 = (*this)[1]; 418 | uint32_t c3 = (*this)[2]; 419 | return (c1 << 16) | (c2 << 8) | c3; 420 | } 421 | 422 | inline uint32_t RingBuffer::peek_uint32() const 423 | { 424 | assert_size(4); 425 | uint32_t c1 = (*this)[0]; 426 | uint32_t c2 = (*this)[1]; 427 | uint32_t c3 = (*this)[2]; 428 | uint32_t c4 = (*this)[3]; 429 | return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4; 430 | } 431 | 432 | 433 | // 读取数据并移动指针 434 | inline uint8_t RingBuffer::pop_uint8() 435 | { 436 | uint8_t c = peek_uint8(); 437 | skip(1); 438 | return c; 439 | } 440 | 441 | inline uint16_t RingBuffer::pop_uint16() 442 | { 443 | uint16_t c = peek_uint16(); 444 | skip(2); 445 | return c; 446 | } 447 | 448 | inline uint32_t RingBuffer::pop_uint24() 449 | { 450 | uint32_t c = peek_uint24(); 451 | skip(3); 452 | return c; 453 | } 454 | 455 | inline uint32_t RingBuffer::pop_uint32() 456 | { 457 | uint32_t c = peek_uint32(); 458 | skip(4); 459 | return c; 460 | } 461 | 462 | 463 | }; 464 | 465 | #endif 466 | 467 | 468 | 469 | -------------------------------------------------------------------------------- /module/fec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fec.c -- forward error correction based on Vandermonde matrices 3 | * 980614 4 | * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) 5 | * 6 | * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), 7 | * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari 8 | * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer in the documentation and/or other materials 19 | * provided with the distribution. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 26 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 | * OF SUCH DAMAGE. 33 | */ 34 | 35 | /* 36 | * The following parameter defines how many bits are used for 37 | * field elements. The code supports any value from 2 to 16 38 | * but fastest operation is achieved with 8 bit elements 39 | * This is the only parameter you may want to change. 40 | */ 41 | 42 | #ifndef __FEC_H__ 43 | #define __FEC_H__ 44 | 45 | #ifndef DEFS_H 46 | #define DEFS_H 47 | 48 | //#define HAVE_CONFIG_H 49 | //#ifdef HAVE_CONFIG_H 50 | //#include "config.h" 51 | /* Define if you don't have `vprintf' but do have `_doprnt.' */ 52 | #undef HAVE_DOPRNT 53 | 54 | /* Define if you have the header file. */ 55 | #undef HAVE_ERRNO_H 56 | 57 | /* Define if you have the `gettimeofday' function. */ 58 | #undef HAVE_GETTIMEOFDAY 59 | 60 | /* Define if you have the header file. */ 61 | #undef HAVE_INTTYPES_H 62 | 63 | /* Define if you have the header file. */ 64 | #define HAVE_MEMORY_H 65 | 66 | /* Define if you have the `memset' function. */ 67 | //#undef HAVE_MEMSET 68 | 69 | /* Define if you have the header file. */ 70 | //#undef HAVE_NETINET_IN_H 71 | 72 | /* Define if you have the header file. */ 73 | //#undef HAVE_STDINT_H 74 | 75 | /* Define if you have the header file. */ 76 | #define HAVE_STDLIB_H 77 | 78 | /* Define if you have the header file. */ 79 | #undef HAVE_STRINGS_H 80 | 81 | /* Define if you have the header file. */ 82 | #undef HAVE_STRING_H 83 | 84 | /* Define if you have the header file. */ 85 | #undef HAVE_SYS_STAT_H 86 | 87 | /* Define if you have the header file. */ 88 | #undef HAVE_SYS_TYPES_H 89 | 90 | /* Define if you have the header file. */ 91 | #undef HAVE_UNISTD_H 92 | 93 | /* Define if the system has the type `u_char'. */ 94 | #undef HAVE_U_CHAR 95 | 96 | /* Define if the system has the type `u_int32_t'. */ 97 | #undef HAVE_U_INT32_T 98 | 99 | /* Define if you have the `vprintf' function. */ 100 | #undef HAVE_VPRINTF 101 | 102 | /* The size of a `int', as computed by sizeof. */ 103 | #undef SIZEOF_INT 104 | 105 | /* The size of a `long', as computed by sizeof. */ 106 | #undef SIZEOF_LONG 107 | 108 | /* Define if you have the ANSI C header files. */ 109 | #undef STDC_HEADERS 110 | 111 | /* Define if you can safely include both and . */ 112 | #undef TIME_WITH_SYS_TIME 113 | 114 | /* Define to empty if `const' does not conform to ANSI C. */ 115 | #undef const 116 | 117 | /* Define as `__inline' if that's what the C compiler calls it, or to nothing 118 | if it is not supported. */ 119 | #undef inline 120 | 121 | /* Define to `long' if does not define. */ 122 | #undef off_t 123 | 124 | /* Define to `unsigned' if does not define. */ 125 | #undef size_t 126 | 127 | //#endif 128 | 129 | #include 130 | 131 | #if HAVE_SYS_TYPES_H 132 | # include 133 | #endif 134 | 135 | #if HAVE_SYS_STAT_H 136 | # include 137 | #endif 138 | 139 | #if STDC_HEADERS 140 | # include 141 | # include 142 | #else 143 | #ifdef HAVE_STDLIB_H 144 | # include 145 | # endif 146 | #endif 147 | 148 | #if HAVE_STRING_H 149 | # if !STDC_HEADERS && HAVE_MEMORY_H 150 | # include 151 | # endif 152 | # include 153 | #else 154 | # if HAVE_STRINGS_H 155 | # include 156 | # endif 157 | #endif 158 | 159 | #if HAVE_INTTYPES_H 160 | # include 161 | #else 162 | # if HAVE_STDINT_H 163 | # include 164 | # endif 165 | #endif 166 | 167 | #if HAVE_UNISTD_H 168 | # include 169 | #endif 170 | 171 | #if TIME_WITH_SYS_TIME 172 | # include 173 | # include 174 | #else 175 | # if HAVE_SYS_TIME_H 176 | # include 177 | # else 178 | # include 179 | # endif 180 | #endif 181 | //#define HAVE_MEMCPY 182 | #if STDC_HEADERS 183 | # include 184 | #else 185 | //# if !HAVE_MEMCPY 186 | //# define memcpy(d, s, n) bcopy ((s), (d), (n)) 187 | //# define memmove(d, s, n) bcopy ((s), (d), (n)) 188 | //# endif 189 | #endif 190 | #include 191 | 192 | //#define HAVE_MEMSET 193 | //#ifndef HAVE_BZERO 194 | //#ifdef HAVE_MEMSET 195 | #define bzero(d, siz) memset((d), 0, (siz)) 196 | #define bcopy(s, d, siz) memcpy((d), (s), (siz)) 197 | //#else 198 | //#error I need bzero or memset! 199 | //#endif 200 | //#endif 201 | 202 | #if HAVE_NETINET_IN_H 203 | # include /* for htonl and ntohl */ 204 | #endif 205 | 206 | #if HAVE_ERRNO_H 207 | # include 208 | #endif 209 | 210 | #if !HAVE_U_CHAR 211 | typedef unsigned char u_char; 212 | #endif 213 | 214 | #if !HAVE_U_INT32_T 215 | # if SIZEOF_INT == 4 216 | typedef unsigned int u_int32_t; 217 | # else 218 | # if SIZEOF_LONG == 4 219 | typedef unsigned long u_int32_t; 220 | # endif 221 | # endif 222 | #endif 223 | 224 | #endif /* DEFS_H */ 225 | 226 | 227 | #ifndef GF_BITS 228 | #define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */ 229 | #endif 230 | 231 | #define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */ 232 | 233 | #ifdef __cplusplus 234 | extern "C" { 235 | #endif 236 | 237 | void *fec_new(int k, int n); 238 | void fec_free(void *p); 239 | 240 | void fec_encode(void *code, u_char **src, u_char *dst, int index, int sz); 241 | int fec_decode(void *code, u_char **pkt, int *index, int sz); 242 | 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | 248 | #endif 249 | 250 | 251 | -------------------------------------------------------------------------------- /module/rs.h: -------------------------------------------------------------------------------- 1 | #ifndef __RS_H_ 2 | #define __RS_H_ 3 | 4 | /* use small value to save memory */ 5 | #define DATA_SHARDS_MAX 255 6 | 7 | typedef struct _reed_solomon { 8 | int data_shards; 9 | int parity_shards; 10 | int shards; 11 | unsigned char* m; 12 | unsigned char* parity; 13 | } reed_solomon; 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /** 20 | * MUST initial one time 21 | * */ 22 | void reed_solomon_init(void); 23 | 24 | reed_solomon* reed_solomon_new(int data_shards, int parity_shards); 25 | void reed_solomon_release(reed_solomon* rs); 26 | 27 | /** 28 | * encode a big size of buffer 29 | * input: 30 | * rs 31 | * nr_shards: assert(0 == nr_shards % rs->data_shards) 32 | * shards[nr_shards][block_size] 33 | * */ 34 | int reed_solomon_encode(reed_solomon* rs, unsigned char** shards, int nr_shards, int block_size); 35 | 36 | /** 37 | * reconstruct a big size of buffer 38 | * input: 39 | * rs 40 | * nr_shards: assert(0 == nr_shards % rs->data_shards) 41 | * shards[nr_shards][block_size] 42 | * marks[nr_shards] marks as errors 43 | * */ 44 | int reed_solomon_reconstruct(reed_solomon* rs, unsigned char** shards, unsigned char* marks, int nr_shards, int block_size); 45 | 46 | /** 47 | * get error number 48 | */ 49 | int reed_solomon_error(void); 50 | 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /network/Combinator.cpp: -------------------------------------------------------------------------------- 1 | #include "Combinator.h" 2 | 3 | NAMESPACE_BEGIN(QuickNet) 4 | 5 | 6 | //--------------------------------------------------------------------- 7 | // inline functions 8 | //--------------------------------------------------------------------- 9 | static inline int PacketSize(const ProtocolPacket *packet) { 10 | return packet->size() + 2; 11 | } 12 | 13 | 14 | //--------------------------------------------------------------------- 15 | // Constructor 16 | //--------------------------------------------------------------------- 17 | Combinator::Combinator(void *user) 18 | { 19 | _initialized = false; 20 | _user = user; 21 | _total_size = 0; 22 | _limit = 900; 23 | _current = 0; 24 | _timeslap = 0; 25 | _period = 20; 26 | PacketOutput = NULL; 27 | PacketDeliver = NULL; 28 | } 29 | 30 | 31 | //--------------------------------------------------------------------- 32 | // Destructor 33 | //--------------------------------------------------------------------- 34 | Combinator::~Combinator() 35 | { 36 | ProtocolUdp::ClearPacketVector(_pending); 37 | } 38 | 39 | 40 | //--------------------------------------------------------------------- 41 | // Update interval 42 | //--------------------------------------------------------------------- 43 | void Combinator::Update(IUINT32 current, bool flush) 44 | { 45 | _current = current; 46 | if (_initialized == false) { 47 | _timeslap = current; 48 | _initialized = true; 49 | } 50 | int need = 0; 51 | if (flush) { 52 | _timeslap = _current; 53 | } 54 | while (_current >= _timeslap) { 55 | need++; 56 | _timeslap += (_period < 1)? 1 : _period; 57 | } 58 | if (flush || need) { 59 | Flush(); 60 | } 61 | } 62 | 63 | 64 | //--------------------------------------------------------------------- 65 | // send to lower level 66 | //--------------------------------------------------------------------- 67 | void Combinator::Send(ProtocolPacket *packet) 68 | { 69 | if (_initialized == false) { 70 | delete packet; 71 | } 72 | else if (packet->protocol == QUICKNET_PROTOCOL_COMBINE) { 73 | delete packet; 74 | } 75 | else if (packet->protocol > 0xf) { 76 | Output(packet); 77 | } 78 | else if (packet->size() > 4096) { 79 | Flush(); 80 | Output(packet); 81 | } 82 | else { 83 | int size = PacketSize(packet); 84 | if (size + _total_size > _limit) { 85 | Flush(); 86 | } 87 | _pending.push_back(packet); 88 | _total_size += size; 89 | if (_total_size >= _limit) { 90 | Flush(); 91 | } 92 | } 93 | } 94 | 95 | 96 | //--------------------------------------------------------------------- 97 | // send to lower level 98 | //--------------------------------------------------------------------- 99 | void Combinator::Flush() 100 | { 101 | int count = (int)_pending.size(); 102 | if (count == 1) { 103 | ProtocolPacket *packet = _pending[0]; 104 | Output(packet); 105 | _pending.resize(0); 106 | _total_size = 0; 107 | } 108 | else if (count > 1) { 109 | ProtocolPacket *packet = new ProtocolPacket(_total_size + 8); 110 | for (int i = 0; i < count; i++) { 111 | ProtocolPacket *p = _pending[i]; 112 | int size = p->size(); 113 | packet->push_tail_uint16((size << 4) | (p->protocol & 0xf)); 114 | packet->push_tail(p->data(), size); 115 | delete p; 116 | } 117 | packet->protocol = QUICKNET_PROTOCOL_COMBINE; 118 | Output(packet); 119 | _pending.resize(0); 120 | _total_size = 0; 121 | } 122 | } 123 | 124 | 125 | //--------------------------------------------------------------------- 126 | // input from lower level packet 127 | //--------------------------------------------------------------------- 128 | void Combinator::Input(ProtocolPacket *packet) 129 | { 130 | if (packet->protocol != QUICKNET_PROTOCOL_COMBINE) { 131 | this->Deliver(packet->data(), packet->size(), packet->protocol); 132 | } 133 | else { 134 | while (1) { 135 | if (packet->size() < 2) break; 136 | int head = packet->pop_head_uint16(); 137 | int size = head >> 4; 138 | int protocol = head & 0xf; 139 | if (packet->size() < size) break; 140 | this->Deliver(packet->data(), size, protocol); 141 | packet->pop_head(NULL, size); 142 | } 143 | delete packet; 144 | } 145 | } 146 | 147 | 148 | //--------------------------------------------------------------------- 149 | // input from lower level packet 150 | //--------------------------------------------------------------------- 151 | int Combinator::Option(int opt, int value) 152 | { 153 | int hr = 0; 154 | switch (opt) { 155 | case 0: 156 | _limit = (value < 100)? 100 : ((value > 2048)? 2048 : value); 157 | break; 158 | case 1: 159 | _period = (value < 2)? 2 : ((value > 1000)? 1000 : value); 160 | break; 161 | case 2: 162 | hr = _limit; 163 | break; 164 | case 3: 165 | hr = _period; 166 | break; 167 | } 168 | return hr; 169 | } 170 | 171 | 172 | 173 | NAMESPACE_END(QuickNet) 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /network/Combinator.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMBINATOR_H__ 2 | #define __COMBINATOR_H__ 3 | 4 | #include "ProtocolBasic.h" 5 | 6 | NAMESPACE_BEGIN(QuickNet) 7 | 8 | //--------------------------------------------------------------------- 9 | // Combinator 10 | //--------------------------------------------------------------------- 11 | class Combinator 12 | { 13 | public: 14 | Combinator(void *user); 15 | virtual ~Combinator(); 16 | 17 | public: 18 | 19 | // update interval 20 | void Update(IUINT32 current, bool force); 21 | 22 | // send upper level 23 | void Send(ProtocolPacket *packet); 24 | 25 | // input from lower level packet 26 | void Input(ProtocolPacket *packet); 27 | 28 | // flush data 29 | void Flush(); 30 | 31 | // Option: 0(limit), 1(period) 32 | int Option(int opt, int value); 33 | 34 | public: 35 | // 输出下层协议的 packet,函数指针,外面提供 36 | void (*PacketOutput)(ProtocolPacket *packet, void *user); 37 | 38 | // 输出上层协议的 packet,函数指针,外面提供 39 | void (*PacketDeliver)(const void *data, int size, int protocol, void *user); 40 | 41 | // 输出下层数据包 42 | inline void Output(ProtocolPacket *packet) { 43 | if (PacketOutput) PacketOutput(packet, _user); 44 | else delete packet; 45 | } 46 | 47 | // 输出上层数据包 48 | inline void Deliver(const void *data, int size, int protocol) { 49 | if (PacketDeliver) { 50 | PacketDeliver(data, size, protocol, _user); 51 | } 52 | } 53 | 54 | protected: 55 | void *_user; 56 | PacketVector _pending; 57 | bool _initialized; 58 | int _limit; 59 | int _total_size; 60 | IUINT32 _current; 61 | IUINT32 _timeslap; 62 | IUINT32 _period; 63 | }; 64 | 65 | 66 | NAMESPACE_END(QuickNet) 67 | 68 | #endif 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /network/FecCodec.cpp: -------------------------------------------------------------------------------- 1 | #include "FecCodec.h" 2 | #include 3 | extern "C" 4 | { 5 | #include "../system/fec.h" 6 | } 7 | 8 | 9 | 10 | 11 | 12 | /** 13 | *遍历链表,找到相应的codec 14 | */ 15 | 16 | FecCodec* find_codec(FecCodecList& codecList, int k,int n) 17 | { 18 | FecCodec *p_ret = NULL; 19 | 20 | for( FecCodecList::iterator it = codecList.begin(); p_ret == NULL && it != codecList.end(); it++) 21 | { 22 | if (it->second == NULL) 23 | { 24 | continue; 25 | } 26 | if (it->second->k == k && it->second->n == n) 27 | { 28 | p_ret = it->second; 29 | } 30 | } 31 | return p_ret; 32 | } 33 | 34 | FecCodec* get_codec_by(FecCodecList& codecList, float lostRate) 35 | { 36 | FecCodec *p_ret = NULL; 37 | if (codecList.empty()) 38 | { 39 | return p_ret; 40 | } 41 | 42 | /** 43 | *lostRate <= 1-k/n; 44 | */ 45 | float lastRate = 0.0f; 46 | FecCodec *lastFecCodec = NULL; 47 | for( FecCodecList::iterator it = codecList.begin(); p_ret == NULL && it != codecList.end(); it++) 48 | { 49 | float curRate = it->first; 50 | if (it == codecList.begin()) 51 | { 52 | if (lostRate >= lastRate && lostRate <= curRate) 53 | { 54 | p_ret = it->second; 55 | } 56 | } 57 | else 58 | { 59 | if (lostRate > lastRate && lostRate <= curRate) 60 | { 61 | p_ret = it->second; 62 | } 63 | } 64 | lastRate = curRate; 65 | lastFecCodec = it->second; 66 | } 67 | if (p_ret == NULL) 68 | { 69 | p_ret = lastFecCodec; //最末尾的一个,冗余度最大的。 70 | } 71 | return p_ret; 72 | 73 | } 74 | 75 | /** 76 | *新建一个相应的codec,插入链表,返回链表头 77 | *此操作必定会增加链表长度 78 | */ 79 | FecCodec* add_new_codec(FecCodecList& codecList, int k, int n) 80 | { 81 | FecCodec *p_new_item = new FecCodec(); 82 | p_new_item->k = k; 83 | p_new_item->n = n; 84 | p_new_item->codec = fec_new(k, n); 85 | 86 | //冗余度: 87 | float key = 1.0f - float(k)/float(n); 88 | 89 | FecCodecList::iterator it = codecList.find(key); 90 | if (it != codecList.end()) 91 | { 92 | delete it->second; 93 | it->second = NULL; 94 | } 95 | codecList.insert( std::pair(key, p_new_item) ); 96 | return p_new_item; 97 | } 98 | 99 | int get_codec_count(FecCodecList& codecList) 100 | { 101 | int nRet = int(codecList.size()); 102 | return nRet; 103 | } 104 | 105 | 106 | FecCodec* get_codec(FecCodecList& codecList, int i) 107 | { 108 | int i_cur_item = 0; 109 | FecCodec * p_item = NULL; 110 | for( FecCodecList::iterator it = codecList.begin(); p_item == NULL && it != codecList.end(); it++) 111 | { 112 | if (i_cur_item == i) 113 | { 114 | p_item = it->second; 115 | } 116 | i_cur_item++; 117 | } 118 | return p_item; 119 | } 120 | 121 | /** 122 | *删除整个链表; 123 | *返回链表长度 124 | */ 125 | void release_all_codec(FecCodecList& codecList) 126 | { 127 | for( FecCodecList::iterator it = codecList.begin(); it != codecList.end(); it++) 128 | { 129 | if (it->second != NULL) 130 | { 131 | if (it->second->codec != NULL) 132 | { 133 | fec_free(it->second->codec); 134 | it->second->codec = NULL; 135 | } 136 | delete it->second; 137 | it->second = NULL; 138 | } 139 | } 140 | codecList.clear(); 141 | } 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /network/FecCodec.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _AUDIOMAIN_NETWORK_FEC_CODEC_H_ 3 | #define _AUDIOMAIN_NETWORK_FEC_CODEC_H_ 4 | #include 5 | typedef struct tagFecCodec 6 | { 7 | int k; 8 | int n; 9 | void *codec; 10 | }FecCodec; 11 | typedef std::map FecCodecList; 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | /** 18 | *遍历链表,找到相应的codec 19 | */ 20 | FecCodec* find_codec(FecCodecList& codecList, int k,int n); 21 | /** 22 | *根据冗余度找到最合适的codec 23 | *参数:冗余度, == 丢包率 == 1-k/n; 24 | */ 25 | FecCodec* get_codec_by(FecCodecList& codecList, float lostRate); 26 | 27 | /** 28 | *新建一个相应的codec,插入链表,返回链表头 29 | *此操作必定会增加链表长度 30 | */ 31 | FecCodec* add_new_codec(FecCodecList& codecList, int k, int n); 32 | // 33 | int get_codec_count(FecCodecList& codecList ); 34 | // 35 | FecCodec* get_codec(FecCodecList& codecList, int i); 36 | 37 | /** 38 | *删除整个链表; 39 | *返回链表长度 40 | */ 41 | void release_all_codec(FecCodecList& codecList); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | 48 | #endif 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /network/FecCodecBuf.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _AUDIOMAIN_NETWORK_FEC_CODEC_BUF_H_ 3 | #define _AUDIOMAIN_NETWORK_FEC_CODEC_BUF_H_ 4 | 5 | #include "../system/imemdata.h" 6 | 7 | const unsigned char tagFecPktHead = 0xEC; 8 | const unsigned char tagFecPktHeadCheksum = 0xED; 9 | const unsigned char tagFecOFFTag = 0x13; 10 | typedef struct tagFecCodecHead 11 | { 12 | IUINT32 sent_pkt_index; //当前包“总体”序号 4 BYTES 0 to 4,294,967,295 13 | IUINT32 src_pkt_index; //当前包“原始数据”序号,校验包 4 BYTES 0 to 4,294,967,295 14 | unsigned char codec_n; //fec 的nl 1*BYTE, 0-255; 15 | unsigned char codec_k; //fec 的k 1*BYTE, 0-255; 16 | unsigned char ik; //fec段内的序号,可以用来确定是否校验包 1*BYTE, 0-255; 17 | }FecCodecHead; 18 | 19 | typedef struct tagFecCodecBuf 20 | { 21 | int enc_pkt_size; //the size packed with head. 22 | int enc_kmax; 23 | bool is_checksum; //recv 24 | bool is_send_checksum; 25 | //--fec_encoder-- 26 | char **fec_en_buf; // k*PacketBytes 27 | char *sent_buf; 28 | char *en_check_pkt; 29 | //--- FEC decoder -- 30 | int dec_pkt_size; //the size packed with head. 31 | int dec_kmax; 32 | char **fecDecoderBuf; 33 | int *fecDecoderIndices; 34 | char *dec_buf; 35 | char *dec_check_pkt; 36 | }FecCodecBuf; 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /** 43 | *设定fec-encode buf ik,原始包 44 | */ 45 | const char* set_fec_enc_buf(FecCodecBuf& fecBuf, int ik, const void* pBuf, int size, int& en_size); 46 | const char* set_fec_dec_buf(FecCodecBuf& fecBuf, int index, const void* pBuf, int size, int ik); 47 | 48 | /** 49 | * 50 | */ 51 | bool is_fec_buf(const char* pbuf, int size); 52 | void reset_fec_dec_buf(FecCodecBuf& fecBuf); 53 | /** 54 | *获取fec-encoded的包 55 | */ 56 | const char* get_fec_encoded_pkt(FecCodecBuf& fecBuf, void *p_fec_codec, int ik, int groupMaxPktSize, int& en_size); 57 | 58 | //输入p_dec_buf, fec dec包,(参加fec decode运算的包) 59 | //output the source data in packet, decode the pkt size. Check packet by checksum; 60 | const char* dec_src_pkt_info(const char* p_dec_buf, FecCodecBuf& fecBuf, IUINT16& sizepkt); 61 | 62 | int fec_decode_pkts(FecCodecBuf& fecBuf, void *p_fec_codec,int maxsize); 63 | /** 64 | *获取fec-decoded后,第ik个包 65 | */ 66 | const char* get_fec_decoded_pkt(FecCodecBuf& fecBuf, int ik); 67 | /** 68 | */ 69 | const char* pack_fec_off_tag(FecCodecBuf& fecBuf,const char* p_buf, int buf_size, int& packed_size); 70 | const char* pack_fec_head(FecCodecBuf& fecBuf, const FecCodecHead& fec_head, const char* p_buf, int buf_size, int& packed_size); 71 | /** 72 | *p_buf, 73 | */ 74 | const char* unpack_fec_head(FecCodecBuf& fecBuf, FecCodecHead& fec_head, const char* p_buf, int buf_size, int& packed_size); 75 | 76 | 77 | void release_fec_enc_buf(FecCodecBuf& fecBuf); 78 | //-- FEC decode-- 79 | void release_fec_dec_buf(FecCodecBuf& fecBuf); 80 | 81 | void init_fec_buf(FecCodecBuf& fecBuf, int _max_pkt_size, int _kmax); 82 | void release_fec_buf(FecCodecBuf& fecBuf); 83 | /** 84 | *p_buf: IN 包; 85 | *fec_head OUT 86 | *return: 去掉包头后的paket; 87 | */ 88 | const char* unpack_fec_head(FecCodecBuf& fecBuf, FecCodecHead& fec_head, const char* p_buf, int buf_size, int& unpacked_size); 89 | 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | 95 | 96 | #endif 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /network/FecPacket.cpp: -------------------------------------------------------------------------------- 1 | #include "FecPacket.h" 2 | -------------------------------------------------------------------------------- /network/FecPacket.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUDIOMAIN_NETWORK_FEC_PACKET_H_ 2 | #define _AUDIOMAIN_NETWORK_FEC_PACKET_H_ 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class FecPacket 11 | { 12 | public: 13 | long iPacket; 14 | char* FecBuf; 15 | int BufSize; 16 | bool bValid; 17 | int MaxBufSize; 18 | bool bSourcePkt; 19 | long i_source_pkt; //对应的原始包号码 20 | bool bUsed; 21 | 22 | public: 23 | FecPacket(int size) 24 | { 25 | FecBuf = 0; 26 | bValid = false; 27 | MaxBufSize = size; 28 | FecBuf = NULL; 29 | BufSize = 0; 30 | iPacket = -1; 31 | bSourcePkt = true; 32 | bUsed = false; 33 | i_source_pkt = -1; 34 | } 35 | 36 | FecPacket(const FecPacket& right) 37 | { 38 | iPacket = right.iPacket; 39 | FecBuf = right.FecBuf; 40 | MaxBufSize = right.MaxBufSize; 41 | BufSize = right.BufSize; 42 | bValid = right.IsValid(); 43 | bSourcePkt = right.bSourcePkt; 44 | i_source_pkt = right.i_source_pkt; 45 | bUsed = right.bUsed; 46 | return; 47 | } 48 | 49 | FecPacket& operator= (const FecPacket& right) 50 | { 51 | iPacket = right.iPacket; 52 | int oldMaxBufSize = MaxBufSize; 53 | if (MaxBufSize != right.GetMaxSize()) 54 | { 55 | MaxBufSize = right.GetMaxSize(); 56 | } 57 | if (FecBuf == NULL) 58 | { 59 | FecBuf = (char*)calloc(MaxBufSize, sizeof(char)); 60 | memset(FecBuf, 0, MaxBufSize); 61 | } 62 | else 63 | { 64 | if (oldMaxBufSize != MaxBufSize) 65 | { 66 | FecBuf = (char*)realloc(FecBuf, MaxBufSize); 67 | } 68 | } 69 | memcpy(FecBuf, right.FecBuf, right.BufSize); 70 | BufSize = right.BufSize; 71 | bValid = right.IsValid(); 72 | bSourcePkt = right.bSourcePkt; 73 | i_source_pkt = right.i_source_pkt; 74 | bUsed = right.bUsed; 75 | return *this; 76 | } 77 | 78 | void SetPacket( const char* pBuf, int size) 79 | { 80 | if (pBuf == NULL) 81 | { 82 | return; 83 | } 84 | if (FecBuf == NULL) 85 | { 86 | FecBuf = (char*)calloc(MaxBufSize, sizeof(char)); 87 | memset(FecBuf,0,MaxBufSize); 88 | } 89 | if (size > MaxBufSize) 90 | { 91 | FecBuf = (char*)realloc(FecBuf, size); 92 | MaxBufSize = size; 93 | } 94 | memset(FecBuf,0, MaxBufSize); 95 | memcpy(FecBuf, pBuf, size); 96 | BufSize = size; 97 | bValid = true; 98 | bUsed = false; 99 | } 100 | void Reset(int max_size) 101 | { 102 | iPacket = -1; 103 | BufSize = 0; 104 | bValid = 0; 105 | if (FecBuf == NULL) 106 | { 107 | FecBuf = (char*)calloc(max_size, sizeof(char)); 108 | memset(FecBuf,0,max_size); 109 | } 110 | 111 | if (FecBuf) 112 | { 113 | if (MaxBufSize != max_size) 114 | { 115 | FecBuf = (char*)realloc(FecBuf, max_size); 116 | } 117 | memset(FecBuf,0,max_size); 118 | BufSize = 0; 119 | } 120 | MaxBufSize = max_size; 121 | bValid = false; 122 | bUsed = false; 123 | } 124 | bool IsValid() const 125 | { 126 | return FecBuf != NULL && bValid; 127 | } 128 | int GetMaxSize() const {return MaxBufSize; } 129 | }; 130 | 131 | 132 | #endif 133 | 134 | 135 | -------------------------------------------------------------------------------- /network/FecTransmission.cpp: -------------------------------------------------------------------------------- 1 | #include "FecTransmission.h" 2 | #include "ProtocolBasic.h" 3 | 4 | NAMESPACE_BEGIN(QuickNet) 5 | 6 | void FecTransmission::PacketInput(ProtocolPacket *packet) 7 | { 8 | if (packet == NULL) 9 | { 10 | return; 11 | } 12 | if (m_bZfec) 13 | { 14 | zfec_unpack_input(zfec, this, packet->data(), packet->size()); 15 | delete packet; 16 | } 17 | else 18 | { 19 | Deliver(packet); 20 | 21 | } 22 | 23 | } 24 | 25 | void FecTransmission::Send(ProtocolPacket *packet) 26 | { 27 | if (packet == NULL) 28 | { 29 | return; 30 | } 31 | if (m_bZfec) 32 | { 33 | zfec_pack_input(zfec,this, packet->data(), packet->size(), -1); 34 | delete packet; 35 | } 36 | else 37 | { 38 | Output(packet); 39 | 40 | } 41 | } 42 | 43 | void FecTransmission::Update(IUINT32 current) 44 | { 45 | //nothing to do. 46 | 47 | } 48 | 49 | int FecTransmission::GetOverhead() const 50 | { 51 | return 11;//FEC head : 11 Bytes; 52 | } 53 | 54 | // 设置 55 | int FecTransmission::Option(int option, int value) 56 | { 57 | int iRet = -1; 58 | switch(option) 59 | { 60 | case QUICKNET_OPT_FEC_MAXBUFSIZE: 61 | { 62 | break; 63 | } 64 | case QUICKNET_OPT_FEC_BUFITEM_NUM: 65 | { 66 | break; 67 | } 68 | case QUICKNET_OPT_FEC_MAXK: 69 | { 70 | break; 71 | } 72 | case QUICKNET_OPT_FEC_ENABLED: 73 | { 74 | enable_zfec(zfec, value != 0); 75 | iRet = 0; 76 | break; 77 | } 78 | case QUICKNET_OPT_FEC_SORTED: 79 | { 80 | enable_sorted_zfec(zfec, value != 0); 81 | iRet = 0; 82 | break; 83 | } 84 | case QUICKNET_OPT_FEC_LOST_RATE: 85 | { 86 | zfec.lost_rate = (float)(abs(value) )/100.0f; 87 | iRet = 0; 88 | break; 89 | } 90 | case QUICKNET_OPT_FEC_DYNKN: 91 | { 92 | enable_zfec_dynkn(zfec, value != 0); 93 | iRet = 0; 94 | break; 95 | } 96 | case QUICKNET_OPT_FEC_STATIC_K: 97 | { 98 | if (value <2 && value >= 7) 99 | { 100 | iRet = -1; 101 | break; 102 | } 103 | 104 | int curK = -1; 105 | int curN = -1; 106 | get_zfec_kn(zfec, curK,curN); 107 | if (curK != -1 && curN != -1) 108 | { 109 | if (value <= curN && (float)(value) >= (float)(curN)/2.0) 110 | { 111 | set_zfec_kn(zfec, value, curN, true); 112 | } 113 | else 114 | { 115 | set_zfec_kn(zfec, value, value+2, true); 116 | } 117 | } 118 | else 119 | { 120 | set_zfec_kn(zfec, value, value+2, true); 121 | } 122 | iRet = 0; 123 | break; 124 | } 125 | case QUICKNET_OPT_FEC_STATIC_N: 126 | { 127 | if (value <4 && value >= 10) 128 | { 129 | iRet = -1; 130 | break; 131 | } 132 | int n = value; 133 | int k = value%2 ==0? value/2 : value/2+1; 134 | 135 | int curK = -1; 136 | int curN = -1; 137 | get_zfec_kn(zfec, curK,curN); 138 | if (curK != -1 && curN != -1) 139 | { 140 | if (value > curK && (float)(value) <= (float)(curK)*2.0) 141 | { 142 | set_zfec_kn(zfec, curK, n, true); 143 | } 144 | else 145 | { 146 | set_zfec_kn(zfec, k, n, true); 147 | } 148 | } 149 | else 150 | { 151 | int k = value%2 ==0? value/2 : value/2+1; 152 | set_zfec_kn(zfec, k, value, true); 153 | } 154 | iRet = 0; 155 | break; 156 | } 157 | default: 158 | { 159 | 160 | } 161 | } 162 | return iRet; 163 | } 164 | 165 | // 取得状态 166 | int FecTransmission::GetStatus(int option) const 167 | { 168 | int iRet = -1; 169 | switch(option) 170 | { 171 | case QUICKNET_OPT_FEC_MAXBUFSIZE: 172 | { 173 | break; 174 | } 175 | case QUICKNET_OPT_FEC_BUFITEM_NUM: 176 | { 177 | break; 178 | } 179 | case QUICKNET_OPT_FEC_MAXK: 180 | { 181 | break; 182 | } 183 | case QUICKNET_OPT_FEC_ENABLED: 184 | { 185 | iRet = is_zfec_enabled(zfec); 186 | break; 187 | } 188 | case QUICKNET_OPT_FEC_SORTED: 189 | { 190 | iRet = is_sorted_zfec(zfec); 191 | break; 192 | } 193 | case QUICKNET_OPT_FEC_LOST_RATE: 194 | { 195 | iRet = int(zfec.lost_rate*100); 196 | break; 197 | } 198 | case QUICKNET_OPT_FEC_DYNKN: 199 | { 200 | iRet = is_zfec_dynkn(zfec); 201 | iRet = int(iRet); 202 | break; 203 | } 204 | case QUICKNET_OPT_FEC_STATIC_K: 205 | { 206 | int curK = -1; 207 | int curN = -1; 208 | get_zfec_kn(zfec, curK,curN); 209 | iRet = curK; 210 | break; 211 | } 212 | case QUICKNET_OPT_FEC_STATIC_N: 213 | { 214 | int curK = -1; 215 | int curN = -1; 216 | get_zfec_kn(zfec, curK,curN); 217 | iRet = curN; 218 | break; 219 | } 220 | case QUICKNET_OPT_FEC_RECV_PKT: 221 | { 222 | iRet = zfec.fec_src_count; 223 | break; 224 | } 225 | case QUICKNET_OPT_FEC_FEC_RESTORE_PKT: 226 | { 227 | iRet = zfec.fec_restore_count; 228 | break; 229 | } 230 | 231 | default: 232 | { 233 | 234 | } 235 | } 236 | return iRet; 237 | } 238 | 239 | 240 | void FecTransmission::Init(int maxSizePkt, int zfecBufItemNum, int maxk, int k, int n, bool enabled, bool is_sorted) 241 | { 242 | init_zfec_layer(zfec, maxSizePkt, zfecBufItemNum, maxk); 243 | zfec.trace = &Trace::Global; 244 | //创建候选k,n列表; 245 | /** 246 | *0.5,0.6,0.625,0.67,0.75,0.8,0.83,0.875 247 | */ 248 | int karray[8] = {2,3,5,4,3,4,5,7}; 249 | int narray[8] = {4,5,8,6,4,5,6,8}; 250 | for(int i = 0; i<8; i++) 251 | { 252 | set_zfec_kn(zfec, karray[i], narray[i],true); 253 | } 254 | set_zfec_kn(zfec, k, n,true); 255 | enable_zfec(zfec, enabled); 256 | enable_sorted_zfec(zfec, is_sorted); 257 | 258 | zfec.PackOutput = &(FecTransmission::zfecPackCallback); 259 | zfec.UnpackOutput = &(FecTransmission::zfecUnpackCallback); 260 | } 261 | 262 | FecTransmission::~FecTransmission() 263 | { 264 | release_z_fec_layer(zfec); 265 | } 266 | 267 | 268 | int FecTransmission::zfecPackCallback(void *p, const char* buf, unsigned int sizepkt) 269 | { 270 | int nRet = -1; 271 | 272 | FecTransmission *param = (FecTransmission*)p; 273 | if (param == NULL ) 274 | { 275 | return nRet; 276 | } 277 | 278 | ProtocolPacket *packet = new ProtocolPacket(sizepkt); 279 | packet->push_tail(buf, sizepkt); 280 | param->Output(packet); 281 | //把他们送给信道channel; 282 | return nRet; 283 | } 284 | 285 | 286 | int FecTransmission::zfecUnpackCallback(void *p, const char* buf, unsigned int sizepkt, IUINT32 i_src_pkt) 287 | { 288 | int nRet = -1; 289 | FecTransmission *param = (FecTransmission*)p; 290 | if (param == NULL ) 291 | { 292 | return nRet; 293 | } 294 | ProtocolPacket *packet = new ProtocolPacket(sizepkt); 295 | packet->push_tail(buf, sizepkt); 296 | param->Deliver(packet); 297 | 298 | return nRet; 299 | } 300 | 301 | 302 | Transmission* CreateFecTransmission() 303 | { 304 | FecTransmission* pFecTransmision = new FecTransmission(); 305 | if (pFecTransmision != NULL) 306 | { 307 | pFecTransmision->Init(2048, 48, 10, 4, 5, true,false); 308 | } 309 | return pFecTransmision; 310 | } 311 | 312 | 313 | NAMESPACE_END(QuickNet) 314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /network/FecTransmission.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUDIO_MAIN_NET_ZFEC_TRANSMISSION_H 2 | #define _AUDIO_MAIN_NET_ZFEC_TRANSMISSION_H 3 | 4 | #include "ProtocolBasic.h" 5 | #include "NetFecCodec.h" 6 | 7 | NAMESPACE_BEGIN(QuickNet) 8 | 9 | class FecTransmission : public Transmission 10 | { 11 | public: 12 | FecTransmission() { m_bZfec = true;} 13 | virtual ~FecTransmission(); 14 | 15 | void Init(int maxSizePkt, int zfecBufItemNum, int maxk, int k, int n, bool enabled, bool is_sorted); 16 | 17 | // 输入下层协议的 packet,由外层调用 18 | virtual void PacketInput(ProtocolPacket *packet); 19 | 20 | // 发送上层数据 21 | virtual void Send(ProtocolPacket *packet) ; 22 | 23 | // 更新状态 24 | virtual void Update(IUINT32 current) ; 25 | 26 | // 返回 OVERHEAD 27 | virtual int GetOverhead() const; 28 | 29 | // 设置 30 | virtual int Option(int option, int value); 31 | 32 | // 取得状态 33 | virtual int GetStatus(int option) const; 34 | 35 | static int zfecPackCallback(void *p, const char* buf, unsigned int sizepkt); 36 | 37 | static int zfecUnpackCallback(void *p, const char* buf, unsigned int sizepkt, IUINT32 i_src_pkt); 38 | 39 | private: 40 | NetFecCodecLayer zfec; 41 | bool m_bZfec; 42 | 43 | }; 44 | 45 | 46 | Transmission* CreateFecTransmission(); 47 | 48 | 49 | 50 | 51 | 52 | NAMESPACE_END(QuickNet) 53 | 54 | 55 | #endif 56 | 57 | 58 | -------------------------------------------------------------------------------- /network/NePingRouter.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUDIO_ENGINE_NE_PING_ROUTER_ 2 | #define _AUDIO_ENGINE_NE_PING_ROUTER_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../system/system.h" 8 | 9 | #ifdef _WIN32 10 | #include 11 | #include 12 | #endif 13 | 14 | 15 | // 16 | //此处是一个非常简单的表,仅中转一次,所以对使用者要求比较高; 17 | //路由算法也是非常粗略的。 18 | // 19 | class NeHostRouteTable 20 | { 21 | private: 22 | //p1), weight>; 23 | std::map< std::pair , std::vector > m_mapEdgesWeight; 24 | int m_nTime; 25 | protected: 26 | //根据weight历史,计算边的weight 27 | unsigned int CmpWeight( const std::vector & vecWeight); 28 | 29 | public: 30 | 31 | NeHostRouteTable(); 32 | ~NeHostRouteTable(); 33 | 34 | /** 35 | *在map中维护weight列表时,每次更新weight,保留的weight的个数 36 | */ 37 | void SetPingTimes(int right ) { m_nTime = right; } 38 | 39 | //设置某边的权重; 40 | void SetEdgeWeight( unsigned long nSIP, unsigned long nEIP, unsigned int nWeight); 41 | //寻找从snIP到nEIP的一边, 存在,就返回weight,否则返回-1; 42 | unsigned int GetEdgeWeight( unsigned long nSIP, unsigned long nEIP); 43 | //寻找从snIP到nEIP的一条路由, out: nNextIP; 返回weight; 44 | unsigned int GetRoute(unsigned long nSIP, unsigned long nEIP, unsigned long& nNextIP); 45 | }; 46 | 47 | 48 | 49 | class NePinger 50 | { 51 | private: 52 | //ip-> < SN, time used> 53 | //std::map< unsigned long, std::pair > m_mapHostWeight; 54 | 55 | NeHostRouteTable m_RouteTable; 56 | 57 | unsigned int m_nPingTimeout; // time out for ping; in milliion secons; 58 | int m_nRetryPing; 59 | int m_nPingSleep; 60 | 61 | std::map m_vecMidHostIP; //midle transfer host ip; 62 | std::map m_vecMidHost; 63 | std::pair m_szDestHostIP; //目的主机IP,sn; 64 | 65 | std::pair m_szCGIHost; 66 | 67 | iPosixThread *m_hThread; 68 | bool m_bStopWork; 69 | 70 | System::ReadWriteLock m_Lock; 71 | unsigned int m_nDestPort; 72 | unsigned int m_nCuteID; 73 | 74 | bool m_bRuning; 75 | 76 | std::pair m_TransferHost; 77 | 78 | 79 | protected: 80 | void processRecv(unsigned long _status, unsigned long _RTT, const char *pSrcIP, unsigned int nSN); 81 | 82 | //send ping and recv the replied information; 83 | bool wndSendPing(const char* pDestIP, unsigned short nID, unsigned int sn, unsigned int nTimeout); 84 | 85 | //添加和删除中间转发节点; 86 | void addTransferHostIP( const char* pDestIP ); 87 | void removeTransferHostIP( const char* pDestIP ); 88 | 89 | int openUrl(const char* pszAudioIP, unsigned int nAudioPort, unsigned int nCuteID, 90 | std::string& content, long& resp); 91 | 92 | 93 | void reqRttCGI(); 94 | 95 | static int WinThreadProc( void* lpParam ); 96 | 97 | bool isRunning(); 98 | void setRuning(bool right); 99 | const char* getDestHostIP(); 100 | unsigned int getDestPort(); 101 | int getPingTimes(); 102 | unsigned int getPingTimeout(); 103 | unsigned int getPingSleep(); 104 | // 105 | void setTransferHost(const std::string& ip, unsigned int port); 106 | //获取到目的地址的路由,并返回中间结点IP和RTT 107 | unsigned int getRouteRTT(std::string& szTransferIP, bool & bTransfer); 108 | 109 | bool isWorkStop(); 110 | 111 | public: 112 | NePinger(void); 113 | ~NePinger(void); 114 | 115 | void SetDestHostIP( const char * pDestIP ); 116 | void SetDestPort(unsigned int right ); 117 | void SetCuteID( unsigned int right ); 118 | unsigned int GetCuteID(); 119 | 120 | //http://192.168.35.247:8866/qnet/get_node_list?key= 121 | void SetCGIHost(const char* pszIP, int port); 122 | 123 | bool IsReady(); 124 | void SetPingTimes(int right); 125 | void SetPingTimeout( unsigned int nTimeout ); 126 | void SetPingSleep( int nMS); 127 | 128 | const char* GetTransferHostIP(); 129 | unsigned int GetTransferHostPort(); 130 | void ResetTransferHost(); 131 | 132 | void Run(); 133 | 134 | bool Start(); 135 | 136 | void PostTerminate(); 137 | }; 138 | 139 | 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /network/NetFecCodec.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _AUDIOMAIN_NETWORK_NET_FEC_CODEC_H_ 3 | #define _AUDIOMAIN_NETWORK_NET_FEC_CODEC_H_ 4 | 5 | #include "FecPacket.h" 6 | #include 7 | #include "FecCodec.h" 8 | #include "FecCodecBuf.h" 9 | #include "ProtocolBasic.h" 10 | //#define _DEBUG_BY_LOG 11 | 12 | #ifdef _DEBUG_BY_LOG 13 | class NetFecCodecTest; 14 | #endif 15 | 16 | 17 | typedef struct tagNetChannel 18 | { 19 | unsigned int dwLastTick; 20 | IUINT32 nSendPkt; 21 | IUINT32 nBegSentPkt; 22 | int nRecvPkt; 23 | float fChannelLost; 24 | }NetChannel; 25 | 26 | typedef struct tagNetFecCodec 27 | { 28 | FecCodec* fec_codec; //当前正在使用的fec_codec; 29 | IUINT32 i_sent_pkt; //发送包索引号,(包括check packets) 30 | IUINT32 i_sent_src_pkt; //已经发送的原始数据包个数 (excludes check packet, Only source packets; 31 | IUINT32 i_expected_packet; // 32 | IUINT32 i_recv_pkt; //收到包的最大总体序号。 33 | int max_pkt_size; 34 | IUINT32 i_cur_segment_beg; 35 | int nGroupMaxPktSize; //the max pkt size in current group; 36 | bool bChangeKNBaseLost; 37 | 38 | int n_fec_item_limit; //fec buf的上限 39 | /** 40 | *fec解析buf的在发送序列的起始和终止位置。 41 | */ 42 | std::pair< IUINT32, IUINT32> dec_buf_ipkt_range; 43 | std::vector dec_pkts_buf; 44 | bool is_enabled; 45 | /** 46 | *zfec包的控制 47 | */ 48 | float delay_threshold; //延迟阈值,用于限制n; 49 | float lost_rate; //当前网络丢包率,用于确定k; 50 | float cur_delay; //当前网络包的延迟 51 | 52 | bool is_sorted; //是否有序输出。 53 | 54 | FecCodecBuf codec_buf; //允许同一个进程有个zfec stack; 55 | /*** 56 | *按照冗余百分比(1- float(k)/float(n))从小到大排列。 57 | */ 58 | FecCodecList codecList; 59 | 60 | QuickNet::Trace *trace; 61 | #ifdef _DEBUG_BY_LOG 62 | NetFecCodecTest *tester; 63 | #endif 64 | NetChannel chnl_info; 65 | 66 | IINT32 fec_src_count; 67 | IINT32 fec_restore_count; 68 | /** 69 | *Fec codec output: 70 | *Encode: to lower level to sending encoded packet. 71 | */ 72 | int (*UnpackOutput)(void * p, const char* packet, unsigned int sizepkt, IUINT32 i_src_pkt); 73 | int (*PackOutput)(void * p, const char* packet, unsigned int sizepkt); 74 | }NetFecCodecLayer; 75 | 76 | 77 | 78 | #ifdef __cplusplus 79 | extern "C" { 80 | #endif 81 | 82 | void init_zfec_layer(NetFecCodecLayer & layer, int max_pkt_size, int fec_buf_limit, int k_max ); 83 | void release_z_fec_layer(NetFecCodecLayer & layer); 84 | 85 | 86 | bool is_zfec_packet(NetFecCodecLayer & zfec, const char* packet, int pktsize); 87 | 88 | 89 | 90 | /** 91 | *设定当前的网络状况 92 | *lostRate丢包率; 93 | *delay,当前网络延迟情况,可以用RTT值; 94 | */ 95 | void set_transimision_state(NetFecCodecLayer& zfec, float _lostRate, float delay); 96 | /** 97 | *设定允许fec层的延迟阈值 98 | */ 99 | void set_delay_threshold(NetFecCodecLayer& zfec, float delay); 100 | 101 | /** 102 | *计算zfec层统计丢包率 103 | */ 104 | float calc_zfec_channel_lost(NetFecCodecLayer& zfec); 105 | 106 | /** 107 | *设定k,n 108 | Param: add_new_codec? true: when failed to find the codec, new one; else, return -2; 109 | *if successs, return 0; else return: 110 | -1(wrong parameter) -2, failed get codecs; 111 | */ 112 | int set_zfec_kn(NetFecCodecLayer & zfec, int k, int n, bool add_new_codec); 113 | 114 | int get_zfec_kn(const NetFecCodecLayer & zfec, int& k, int& n) ; 115 | 116 | 117 | /** 118 | *Fec codec. 119 | *Encode: pack the "data" with fec-head and check packets and send them out by zfec::PackOutput. 120 | *sn: pachet sequence no. 121 | */ 122 | IUINT32 zfec_pack_input(NetFecCodecLayer & zfec, void *outpeer, const void *data, IUINT32 size, IUINT32 sn); 123 | 124 | 125 | /** 126 | *Fec codec. recv data from lower level to decode the packet; 127 | *Decode: recv data from lower level to decode the packet, 128 | *parse the fec header, transfer the content(excluded fec head) to high level by zfec::UnpackOutput; 129 | */ 130 | int zfec_unpack_input(NetFecCodecLayer & zfec, void* p, const char* packet, unsigned int sizepkt); 131 | 132 | /** 133 | *把解包缓冲区中所有可用的pkts冲掉 134 | */ 135 | bool zfec_flush_avail_unpack_pkts(NetFecCodecLayer & zfec,void *peer); 136 | 137 | /** 138 | *是否还有没有使用的pkt 139 | */ 140 | bool is_zfec_avail_unpack_pkts(NetFecCodecLayer & zfec); 141 | 142 | /** 143 | *收到结果是否要求排序 144 | */ 145 | bool is_sorted_zfec(const NetFecCodecLayer & zfec); 146 | void enable_sorted_zfec(NetFecCodecLayer & zfec, bool right); 147 | 148 | /** 149 | * 150 | */ 151 | void enable_zfec(NetFecCodecLayer & zfec, bool right); 152 | bool is_zfec_enabled(const NetFecCodecLayer & zfec); 153 | void enable_zfec_dynkn(NetFecCodecLayer & zfec, bool right); 154 | bool is_zfec_dynkn(const NetFecCodecLayer & zfec); 155 | 156 | void enable_zfec_debug(bool right); 157 | 158 | #ifdef __cplusplus 159 | }; 160 | #endif 161 | 162 | #endif 163 | 164 | 165 | -------------------------------------------------------------------------------- /network/ProtocolBasic.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ProtocolBasic.h - protocol packet defintion and I/O 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #ifndef __PROTOCOL_BASIC_H__ 10 | #define __PROTOCOL_BASIC_H__ 11 | 12 | #include "PacketBuffer.h" 13 | #include "TransportUdp.h" 14 | #include "../system/itoolbox.h" 15 | 16 | #include 17 | #include 18 | 19 | NAMESPACE_BEGIN(QuickNet) 20 | #define QUICKNET_OVERHEAD 48 21 | 22 | //--------------------------------------------------------------------- 23 | // ProtocolPacket:协议数据包 24 | //--------------------------------------------------------------------- 25 | class ProtocolPacket : public PacketBuffer 26 | { 27 | public: 28 | ProtocolPacket(int size): PacketBuffer(size, QUICKNET_OVERHEAD) {} 29 | 30 | // 第一层协议:验证数据包合法性,区别命令 31 | IUINT8 mask; // 掩码:将会和包内所有字节做异或 32 | IUINT8 checksum; // 验证:将所有二层协议以内的东西加起来 33 | IUINT8 cmd; // 命令编号 34 | IUINT8 protocol; // 协议编号 35 | // 第二层协议:判断命令:建立连接的关键部分 36 | IUINT32 conv; // 会话编号 37 | IUINT32 hid; // 目标 38 | // 第三层协议:FEC 39 | IUINT32 fec_v1; 40 | IUINT32 fec_v2; 41 | IUINT32 fec_v3; 42 | IUINT32 fec_v4; 43 | // 第四层协议:拉包 44 | IUINT32 sn; 45 | IUINT8 flag; 46 | // 反馈应用层协议 47 | int event; 48 | IUINT32 wparam; 49 | IUINT32 lparam; 50 | 51 | ProtocolPacket* copy() const { 52 | ProtocolPacket *p = new ProtocolPacket(_endup - _head); 53 | if (_tail > _head) p->push_tail(_head, _tail - _head); 54 | p->mask = mask; 55 | p->checksum = checksum; 56 | p->cmd = cmd; 57 | p->protocol = protocol; 58 | p->conv = conv; 59 | p->hid = hid; 60 | p->fec_v1 = fec_v1; 61 | p->fec_v2 = fec_v2; 62 | p->fec_v3 = fec_v3; 63 | p->fec_v4 = fec_v4; 64 | p->sn = sn; 65 | p->flag = flag; 66 | p->event = event; 67 | p->wparam = wparam; 68 | p->lparam = lparam; 69 | return p; 70 | } 71 | }; 72 | 73 | #define QUICKNET_FLAG_DATA 1 // 标志:数据 74 | #define QUICKNET_FLAG_PULL 2 // 标志:拉包 75 | 76 | #define QUICKNET_CMD_SYN1 0x16 // 命令:连接请求 77 | #define QUICKNET_CMD_ACK1 0x12 // 命令:连接反馈 78 | #define QUICKNET_CMD_SYN2 0x19 // 命令:连接确认 79 | #define QUICKNET_CMD_ACK2 0x17 // 命令:连接建立 80 | #define QUICKNET_CMD_PING 0x18 // 命令:PING发送 81 | #define QUICKNET_CMD_PACK 0x14 // 命令:PING返回 82 | #define QUICKNET_CMD_DATA 0x11 // 命令:协议数据 83 | #define QUICKNET_CMD_FIN 0x15 // 命令:结束 84 | #define QUICKNET_CMD_FACK 0x13 // 命令:结束验证 85 | #define QUICKNET_CMD_CHGIP 0x1A // 命令:改变IP 86 | #define QUICKNET_CMD_CHACK 0x1B // 命令:改变IP返回 87 | #define QUICKNET_CMD_HELLO 0x1D // 命令:HELLO 88 | #define QUICKNET_CMD_HBACK 0x1C // 命令:HELLO BACK 89 | #define QUICKNET_CMD_CHECK 0xA0 // 命令头部验证 90 | 91 | #define QUICKNET_PROTOCOL_RAW 0 // 协议:原始 UDP 92 | #define QUICKNET_PROTOCOL_KCP 1 // 协议:KCP协议 93 | #define QUICKNET_PROTOCOL_TCP 2 // 协议:TCP协议 94 | #define QUICKNET_PROTOCOL_NACK 3 // 协议:NACK协议 95 | #define QUICKNET_PROTOCOL_FEC 0xff // 协议:FEC协议 96 | #define QUICKNET_PROTOCOL_COMBINE 0xee // 协议:多帧协议 97 | 98 | #define SIZE_IP_OVERHEAD 20 99 | #define SIZE_UDP_OVERHEAD 8 100 | 101 | #define QUICKNET_SESSION_OVERHEAD 12 102 | #define QUICKNET_FEC_OVERHEAD 16 103 | 104 | 105 | //--------------------------------------------------------------------- 106 | // 包列表 107 | //--------------------------------------------------------------------- 108 | typedef std::list PacketList; 109 | typedef std::vector PacketVector; 110 | class Trace; 111 | 112 | 113 | //--------------------------------------------------------------------- 114 | // ProtocolUdp:接收发送第一层协议的数据包 115 | //--------------------------------------------------------------------- 116 | class ProtocolUdp 117 | { 118 | public: 119 | ProtocolUdp(); 120 | virtual ~ProtocolUdp(); 121 | 122 | // 绑定端口 123 | bool Open(int port, const char *ip = NULL); 124 | 125 | // 关闭连接 126 | void Close(); 127 | 128 | // 发送协议包:成功返回 true,阻塞返回 false 129 | // 内部会增加第一层协议头,发送完会删除 packet对象 130 | bool SendPacket(ProtocolPacket *packet, const System::SockAddress &remote, int compress = 0); 131 | 132 | // 接收协议包:如果是阻塞则返回 NULL 133 | ProtocolPacket* RecvPacket(System::SockAddress &remote); 134 | 135 | // PacketList清空 136 | static void ClearPacketList(PacketList &plist); 137 | 138 | // PacketVector 清空 139 | static void ClearPacketVector(PacketVector &packets); 140 | 141 | // PacketList 发送 142 | void SendPacketList(PacketList &plist, const System::SockAddress &remote); 143 | 144 | // 取得本地地址 145 | void LocalAddress(System::SockAddress &local); 146 | 147 | // 设置日志 148 | void SetTrace(Trace *trace); 149 | 150 | // 取得缓存长度 151 | bool GetSocketBuffer(int *sndbuf = NULL, int *rcvbuf = NULL); 152 | 153 | // 设置缓存长度 154 | bool SetSocketBuffer(int sndbuf = -1, int rcvbuf = -1); 155 | 156 | // 设置全局掩码 157 | void SetGlobalMask(IUINT32 mask); 158 | 159 | public: 160 | struct Statistic // 收发包统计 161 | { 162 | IINT64 out_count; 163 | IINT64 out_size; 164 | IINT64 out_data; 165 | IINT64 in_count; 166 | IINT64 in_size; 167 | IINT64 in_data; 168 | IINT64 discard_count; 169 | IINT64 discard_size; 170 | IINT64 discard_data; 171 | IINT64 per_sec_out_count; 172 | IINT64 per_sec_out_size; 173 | IINT64 per_sec_out_data; 174 | IINT64 per_sec_in_count; 175 | IINT64 per_sec_in_size; 176 | IINT64 per_sec_in_data; 177 | IINT64 per_sec_discard_count; 178 | IINT64 per_sec_discard_size; 179 | IINT64 per_sec_discard_data; 180 | IINT64 compress_src; 181 | IINT64 compress_out; 182 | }; 183 | 184 | // 统计 185 | void StatisticUpdate(Statistic &stat); 186 | 187 | // 统计复位 188 | void StatisticReset(); 189 | 190 | protected: 191 | static IUINT32 CheckSum(const void *data, int size); 192 | static IUINT32 CheckSum1(const void *data, int size); 193 | static IUINT32 CheckSum2(const void *data, int size); 194 | static void BytesXOR(void *data, int size, unsigned char mask); 195 | void InvalidPacket(const System::SockAddress &remote); 196 | 197 | protected: 198 | TransportUdp _transport; 199 | TransportUdp::statistic _stat_1; 200 | TransportUdp::statistic _stat_2; 201 | Statistic _stat; 202 | IUINT32 _stat_ts; 203 | Trace *trace; 204 | int compress_method; 205 | int compress_level; 206 | std::string compressed; 207 | unsigned char gmask; 208 | unsigned char *_buffer; 209 | }; 210 | 211 | 212 | #define QUICKNET_OPT_FEC_MAXBUFSIZE 0x1100 213 | #define QUICKNET_OPT_FEC_BUFITEM_NUM 0x1101 214 | #define QUICKNET_OPT_FEC_MAXK 0x1102 215 | #define QUICKNET_OPT_FEC_ENABLED 0x1103 //0 : fasle : non 0; true; 216 | #define QUICKNET_OPT_FEC_SORTED 0x1104 //0 : fasle : non 0; true; 217 | #define QUICKNET_OPT_FEC_LOST_RATE 0x1107 //[0-100], based on 100; 218 | #define QUICKNET_OPT_FEC_STATIC_K 0x1108 219 | #define QUICKNET_OPT_FEC_STATIC_N 0x1109 220 | #define QUICKNET_OPT_FEC_DYNKN 0x110A 221 | #define QUICKNET_OPT_FEC_RECV_PKT 0x110B 222 | #define QUICKNET_OPT_FEC_FEC_RESTORE_PKT 0x110C 223 | 224 | 225 | //--------------------------------------------------------------------- 226 | // Transmission:链路层协议(由 Session调用) 227 | //--------------------------------------------------------------------- 228 | class Transmission 229 | { 230 | public: 231 | Transmission() { user = NULL; PacketOutput = NULL; PacketDeliver = NULL;} 232 | virtual ~Transmission() {}; 233 | 234 | // 协议工厂 235 | typedef Transmission* (*Factory)(); 236 | 237 | // 输出下层协议的 packet,函数指针,外面提供 238 | void (*PacketOutput)(ProtocolPacket *packet, void *user); 239 | 240 | // 输出上层协议的 packet,函数指针,外面提供 241 | void (*PacketDeliver)(ProtocolPacket *packet, void *user); 242 | 243 | // 用户指针,用来调用 PacketOutput时传入最后的参数 244 | void *user; 245 | 246 | // 输出下层数据包 247 | inline void Output(ProtocolPacket *packet) { 248 | if (PacketOutput) PacketOutput(packet, user); 249 | else delete packet; 250 | } 251 | 252 | // 输出上层数据包 253 | inline void Deliver(ProtocolPacket *packet) { 254 | if (PacketDeliver) PacketDeliver(packet, user); 255 | else delete packet; 256 | } 257 | 258 | // 输入下层协议的 packet,由外层调用 259 | virtual void PacketInput(ProtocolPacket *packet) = 0; 260 | 261 | // 发送上层数据 262 | virtual void Send(ProtocolPacket *packet) = 0; 263 | 264 | // 更新状态 265 | virtual void Update(IUINT32 current) = 0; 266 | 267 | // 返回 OVERHEAD 268 | virtual int GetOverhead() const = 0; 269 | 270 | // 设置 271 | virtual int Option(int option, int value) = 0; 272 | 273 | // 取得状态 274 | virtual int GetStatus(int option) const = 0; 275 | }; 276 | 277 | 278 | //--------------------------------------------------------------------- 279 | // 日志输出 280 | //--------------------------------------------------------------------- 281 | class Trace 282 | { 283 | public: 284 | Trace(const char *prefix = NULL, bool STDOUT = false, int color = -1); 285 | virtual ~Trace(); 286 | 287 | typedef void (*TraceOut)(const char *text, void *user); 288 | 289 | bool available(int mask) const { return ((_mask & mask) && _output); } 290 | 291 | void setmask(int mask) { _mask = mask; } 292 | void enable(int mask) { _mask |= mask; } 293 | void disable(int mask) { _mask &= ~mask; } 294 | 295 | void setout(TraceOut out, void *user); 296 | void out(int mask, const char *fmt, ...); 297 | void binary(int mask, const void *bin, int size); 298 | 299 | // 如果 prefix == NULL则不向文件输出 300 | void open(const char *prefix, bool STDOUT = false); 301 | void close(); 302 | 303 | // 设置颜色,只用于控制台输出(open时 STDOUT=true),高四位为背景色,低四位为前景色 304 | // 色彩编码见:http://en.wikipedia.org/wiki/ANSI_escape_code,返回先前颜色 305 | int color(int color = -1); 306 | 307 | static Trace Global; 308 | static Trace Null; 309 | static Trace ConsoleWhite; 310 | static Trace LogFile; 311 | static Trace ConsoleMagenta; 312 | static Trace ConsoleGreen; 313 | 314 | protected: 315 | static void StaticOut(const char *text, void *user); 316 | 317 | protected: 318 | TraceOut _output; 319 | System::DateTime _saved_date; 320 | void *_user; 321 | char *_buffer; 322 | char *_prefix; 323 | bool _stdout; 324 | int _saved_day; 325 | FILE *_fp; 326 | char *_tmtext; 327 | char *_fntext; 328 | int _color; 329 | System::CriticalSection _lock; 330 | int _mask; 331 | }; 332 | 333 | 334 | #define TRACE_ERROR 1 335 | #define TRACE_WARNING 2 336 | #define TRACE_MGR_PACKET 4 337 | #define TRACE_MGR_SYN 8 338 | #define TRACE_MGR_EVENT 16 339 | #define TRACE_SESSION 32 340 | #define TRACE_KCP 64 341 | #define TRACE_SERVER 128 342 | #define TRACE_CLIENT 256 343 | #define TRACE_UDP_BASIC 512 344 | #define TRACE_UDP_BYTES 1024 345 | #define TRACE_UDP_ERROR 2048 346 | #define TRACE_RTT_REPORT 8192 347 | 348 | 349 | NAMESPACE_END(QuickNet) 350 | 351 | 352 | #endif 353 | 354 | 355 | -------------------------------------------------------------------------------- /network/ProtocolImp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // ProtocolImp.h - 传输协议实现模块 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file 7 | // 8 | //===================================================================== 9 | #ifndef __PROTOCOL_IMP_H__ 10 | #define __PROTOCOL_IMP_H__ 11 | 12 | #include "ProtocolBasic.h" 13 | #include "SessionManager.h" 14 | #include "NePingRouter.h" 15 | 16 | NAMESPACE_BEGIN(QuickNet) 17 | //--------------------------------------------------------------------- 18 | // QuickServer 19 | //--------------------------------------------------------------------- 20 | class QuickServer 21 | { 22 | public: 23 | QuickServer(); 24 | virtual ~QuickServer(); 25 | 26 | void SetTrace(Trace *trace); 27 | 28 | bool StartService(int port, const char *ip = NULL); 29 | void Shutdown(); 30 | 31 | // 更新状态,持续调用,建议10ms一次 32 | void Update(bool Force = false); 33 | 34 | // 发送数据 35 | bool Send(IINT32 hid, int protocol, const void *data, int size, int limit = -1); 36 | 37 | // 断开连接 38 | bool Close(IINT32 hid, int code); 39 | 40 | // 取得消息 直接方式,成功返回消息长度,返回-1代表没有消息,-2代表长度错误, 41 | // 如果 event, wparam, lparam 任意为 NULL 则返回消息长度 42 | // event会是:QUICKNET_EVENT_NEW/LEAVE/DATA 43 | int Read(int *event, IUINT32 *wparam, IUINT32 *lparam, void *data, int size); 44 | 45 | // 设置超时 46 | // idle是空闲超时,-1为不设置,0为取消空闲超时,>0为毫秒时间,超过这个时间收不到包的客户端断开 47 | // connect连接超时,-1为不设置,0为取消连接超时,>0为毫秒时间,超过这个时间没连接成功的客户端断开 48 | void SetTimeOut(int idle = -1, int connect = -1); 49 | 50 | // 设置周期,周期越短响应越快,但cpu占用越高 51 | void SetInterval(int interval); 52 | 53 | // 配置 54 | int Option(IUINT32 hid, int option, int value); 55 | int GetOption(IUINT32 hid, int option); 56 | 57 | // 字符串配置 58 | int Option(IUINT32 hid, const char *options); 59 | 60 | 61 | // 安装传输层协议 62 | void SetTransmission(Transmission::Factory factory); 63 | 64 | // 取得本地地址 65 | void LocalAddress(System::SockAddress &local); 66 | 67 | // 取得某 HID的状态:0关闭,1连接1,2连接2,3连接等待,4建立连接,5关闭等待。-1为错误 hid 68 | int GetState(IUINT32 hid) const; 69 | 70 | // 广播一群人,返回成功个数 71 | int GroupCast(const IUINT32 *hid, int count, int protocol, const void *data, int size, int limit = -1); 72 | 73 | // 广播所有人,返回成功个数 74 | int Broadcast(int protocol, const void *data, int size, int limit = -1); 75 | 76 | // 取得统计信息 77 | void Statistic(ProtocolUdp::Statistic &stat); 78 | 79 | // 全局掩码 80 | void SetGlobalMask(IUINT32 mask); 81 | 82 | // 取得KCP等待发送的数据 83 | int GetPending(IUINT32 hid, int what) const; 84 | 85 | protected: 86 | static void PacketOutput(ProtocolPacket *packet, const System::SockAddress &remote, void *user); 87 | void UpdateInterval(); 88 | void MakeUUID(int port); 89 | 90 | protected: 91 | Trace *trace; 92 | IUINT32 _current; 93 | IUINT32 _slap; 94 | IUINT32 _interval; 95 | std::string _uuid; 96 | int _port; 97 | ProtocolUdp::Statistic _stat; 98 | SessionManager *_manager; 99 | ProtocolUdp _network; 100 | }; 101 | 102 | 103 | 104 | //--------------------------------------------------------------------- 105 | // QuickClient 106 | //--------------------------------------------------------------------- 107 | class QuickClient 108 | { 109 | public: 110 | QuickClient(); 111 | virtual ~QuickClient(); 112 | 113 | void SetTrace(Trace *trace); 114 | 115 | bool Connect(const char *ip, int port); 116 | void Close(); 117 | 118 | // 设置超时 119 | // idle是空闲超时,-1为不设置,0为取消空闲超时,>0为毫秒时间,超过这个时间收不到包的客户端断开 120 | // connect连接超时,-1为不设置,0为取消连接超时,>0为毫秒时间,超过这个时间没连接成功的客户端断开 121 | void SetTimeOut(int idle = -1, int connect = -1); 122 | 123 | // 发送数据, 124 | // 如果 limit > 0,并且该连接的发送缓存还有 >=limit个待发数据包,则放弃本次发送 125 | bool Send(int protocol, const void *data, int size, int limit = -1); 126 | 127 | // 接收数据,返回数据长度,没有数据则返回-1 128 | int Recv(int *protocol, void *data, int size); 129 | 130 | // 更新状态,需要持续调用,建议 10ms一次 131 | void Update(); 132 | 133 | // 设置保活,单位毫秒,小于零为默认值 134 | void Keepalive(int interval = -1); 135 | 136 | // 安装传输层协议 137 | void SetTransmission(Transmission::Factory factory); 138 | 139 | // 配置 140 | int Option(int option, int value); 141 | 142 | // 取得配置 143 | int GetOption(int option) const; 144 | 145 | // 字符串配置 146 | int Option(const char *options); 147 | 148 | // 取得状态:0关闭,1连接1,2连接2,3连接等待,4建立连接,5关闭等待。 149 | int GetState() const; 150 | 151 | IUINT32 GetHid() const; 152 | 153 | // 是否连接:0为没有连接,1为已经连接 154 | int IsConnected() const; 155 | 156 | // 取得统计信息 157 | void Statistic(ProtocolUdp::Statistic &stat); 158 | 159 | // 取得 RTT 160 | int GetRtt() const; 161 | 162 | // 取得待发送数据 163 | int GetPending(int what) const; 164 | 165 | /* 166 | * @packets 总报文数 167 | * @pull 被拉过包的报文数 168 | * @pullpkts 实际拉包消息数,当前拉包策略下(仅仅参考) 169 | * @lost 实际丢包数 170 | * @pulltimeout 拉包后超时包个数(仅仅参考) 171 | * @skip 连续包忽略拉包次数 172 | * @totalskippkt 连续包忽略拉包总个数 173 | */ 174 | void GetNACKStatInfo(int* packets, int *pull, int* pullpkts, int *lost, int *pulltimeout, int *skip, int *totalskippkt); 175 | 176 | // 改变传输层的目标 ip:port地址,需要连接成功后调用 177 | bool SwitchTargetAddress(const char *ip, int port); 178 | 179 | // 取得目标地址,如果传入地址相同,返回真,否则返回假 180 | bool GetTargetAddress(System::SockAddress &address) const; 181 | 182 | NePinger& GetPingRouter(); 183 | 184 | // 全局掩码 185 | void SetGlobalMask(IUINT32 mask); 186 | 187 | protected: 188 | void CheckOutput(); 189 | 190 | protected: 191 | bool _started; 192 | Trace *trace; 193 | Timeout _ping_timer; 194 | Timeout _switch_ip; 195 | IUINT32 _keepalive; 196 | IUINT32 _current; 197 | Session *_session; 198 | System::SockAddress _target; 199 | ProtocolUdp::Statistic _stat; 200 | Transmission::Factory _factory; 201 | ProtocolUdp _network; 202 | unsigned char _mask; 203 | IUINT32 _time_max_idle; 204 | IUINT32 _time_max_connect; 205 | NePinger _pinger; 206 | mutable System::CriticalSection _lock; 207 | }; 208 | 209 | 210 | 211 | NAMESPACE_END(QuickNet) 212 | 213 | 214 | #endif 215 | 216 | 217 | -------------------------------------------------------------------------------- /network/RequestRepeat.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // RequestRepeat.cpp - Negitive Ack ARQ implementation 4 | // 5 | // NOTE: 6 | // 拉包协议实现,接收端发现序号不连续则发送 NACK到发送方。 7 | // 8 | //===================================================================== 9 | #include "RequestRepeat.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define NACK_LOG_DEBUG 1 16 | #define NACK_LOG_INFO 2 17 | #define NACK_LOG_ERROR 4 18 | 19 | NAMESPACE_BEGIN(QuickNet) 20 | //--------------------------------------------------------------------- 21 | // RequestRepeat 22 | //--------------------------------------------------------------------- 23 | 24 | RequestRepeat::RequestRepeat(void* user) 25 | { 26 | output = NULL; 27 | m_pUser = user; 28 | m_nSendPacketCounter = 0; 29 | m_nMaxPacketSn = 0; 30 | m_nLastRecvSn = 0; 31 | m_nPullSize = 160; 32 | m_listSendPacket.clear(); 33 | m_listSendPacketSn.clear(); 34 | m_listSecondPullPacketSn.clear(); 35 | m_mapSendPacket.clear(); 36 | m_mapRecvPacket.clear(); 37 | m_listRecvData.clear(); 38 | 39 | m_nTimesPull = 0; 40 | m_nPacketsLost = 0; 41 | m_nTimesRepeat = 0; 42 | m_nPacketsPullTimeout = 0; 43 | m_nTimesSkip = 0; 44 | m_nPacketsSkip = 0; 45 | m_nPacketsPull = 0; 46 | m_nSkipSize = QUICKNET_NACK_PKTNUM_PULL_SKIP; 47 | 48 | writelog = NULL; 49 | logmask = 0; 50 | } 51 | 52 | RequestRepeat::~RequestRepeat() 53 | { 54 | m_nTimesPull = 0; 55 | m_nPacketsLost = 0; 56 | m_nTimesRepeat = 0; 57 | m_nPacketsPullTimeout = 0; 58 | m_nTimesSkip = 0; 59 | m_nPacketsSkip = 0; 60 | m_nPacketsPull = 0; 61 | 62 | output = NULL; 63 | m_nSendPacketCounter = 0; 64 | m_nPullSize = 0; 65 | m_nSkipSize = 0; 66 | m_nMaxPacketSn = 0; 67 | m_nLastRecvSn = 0; 68 | m_listRecvData.clear(); 69 | m_listSendPacketSn.clear(); 70 | m_listSecondPullPacketSn.clear(); 71 | std::list::iterator itl = m_listSendPacket.begin(); 72 | for ( ; itl != m_listSendPacket.end(); itl++) { 73 | delete (ProtocolPacket*)*itl; 74 | } 75 | m_listSendPacket.clear(); 76 | //std::map::iterator it = m_mapSendPacket.begin(); 77 | PacketHash::iterator it = m_mapSendPacket.begin(); 78 | for ( ; it != m_mapSendPacket.end(); it++) { 79 | delete (ProtocolPacket*)it->second; 80 | } 81 | it = m_mapRecvPacket.begin(); 82 | for ( ; it != m_mapRecvPacket.end(); it++) { 83 | delete (ProtocolPacket*)it->second; 84 | } 85 | m_mapSendPacket.clear(); 86 | m_mapRecvPacket.clear(); 87 | 88 | writelog = NULL; 89 | logmask = 0; 90 | } 91 | 92 | void RequestRepeat::send_flag_pull(int sn) 93 | { 94 | ProtocolPacket *packet = new ProtocolPacket(0); 95 | packet->protocol = QUICKNET_PROTOCOL_NACK; 96 | packet->cmd = QUICKNET_CMD_DATA; 97 | packet->sn = sn; 98 | packet->flag = QUICKNET_FLAG_PULL; 99 | packet->push_head_uint32(packet->sn); 100 | packet->push_head_uint8(packet->flag); 101 | ++m_nTimesPull; 102 | if (output) output(packet, m_pUser); 103 | else delete packet; 104 | log(NACK_LOG_INFO, "send flag pull, sn:%d, times:%d", sn, m_nTimesPull); 105 | } 106 | 107 | void RequestRepeat::log(int mask, const char *fmt, ...) 108 | { 109 | char buffer[1024]; 110 | va_list argptr; 111 | if ((mask & logmask) == 0 || writelog == 0) return; 112 | va_start(argptr, fmt); 113 | vsprintf(buffer, fmt, argptr); 114 | va_end(argptr); 115 | writelog(buffer, m_pUser); 116 | } 117 | 118 | int RequestRepeat::input(ProtocolPacket *packet) 119 | { 120 | IUINT32 sn; 121 | IUINT8 flag; 122 | RecvSeq seq; 123 | RecvSeq second_seq; 124 | 125 | flag = packet->pop_head_uint8(); 126 | sn = packet->pop_head_uint32(); 127 | if (flag == QUICKNET_FLAG_DATA) { 128 | // 简单拉包策略 129 | if (m_nMaxPacketSn + 1 < sn) { 130 | int count = sn - m_nMaxPacketSn -1; 131 | for(int i = 1; i <= count; i++) 132 | { 133 | if (count >= m_nSkipSize) 134 | { 135 | seq.m_nSendTime = 0; 136 | if (m_nCurrent > QUICKNET_NACK_RTO_DEFAULT_MAX_X2) 137 | seq.m_nSendTime = m_nCurrent - QUICKNET_NACK_RTO_DEFAULT_MAX_X2; 138 | seq.m_nSn = m_nMaxPacketSn + i; 139 | m_listRecvData.push_back(seq); 140 | log(NACK_LOG_INFO, "packet input skip pull, count:%d sn:%d, max_sn:%d recv_sn:%d ", count, seq.m_nSn, m_nMaxPacketSn, m_nLastRecvSn); 141 | } 142 | else 143 | { 144 | send_flag_pull(m_nMaxPacketSn + i); 145 | send_flag_pull(m_nMaxPacketSn + i); 146 | m_nPacketsPull++; 147 | seq.m_nSendTime = m_nCurrent; 148 | seq.m_nSn = m_nMaxPacketSn + i; 149 | m_listRecvData.push_back(seq); 150 | // 第二次拉包相关 151 | second_seq.m_nSendTime = m_nCurrent + (m_nRtt * 3 / 5); 152 | second_seq.m_nSn = m_nMaxPacketSn + i; 153 | m_listSecondPullPacketSn.push_back(second_seq); 154 | } 155 | } 156 | if (count >= m_nSkipSize) 157 | { 158 | m_nTimesSkip++; 159 | m_nPacketsSkip += count; 160 | } 161 | //m_nMaxPacketSn = sn; 162 | } 163 | if (m_nLastRecvSn < sn) { 164 | // 进缓存 165 | seq.m_nSendTime = m_nCurrent; 166 | seq.m_nSn = sn; 167 | if (sn <= m_nMaxPacketSn) { 168 | //std::map::iterator it = m_mapRecvPacket.find(sn); 169 | PacketHash::iterator it = m_mapRecvPacket.find(sn); 170 | if (it == m_mapRecvPacket.end()) { 171 | //m_listRecvData.push_back(seq); 172 | m_mapRecvPacket[sn] = packet; 173 | log(NACK_LOG_INFO, "packet input repeat normal, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 174 | } else { 175 | ++m_nTimesRepeat; 176 | delete packet; 177 | log(NACK_LOG_INFO, "packet input repeat 2, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 178 | } 179 | } else { 180 | m_listRecvData.push_back(seq); 181 | m_mapRecvPacket[sn] = packet; 182 | m_nMaxPacketSn = sn; 183 | log(NACK_LOG_INFO, "packet input normal, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 184 | } 185 | } else { 186 | ++m_nPacketsPullTimeout; 187 | delete packet; 188 | log(NACK_LOG_INFO, "packet input repeat timeout, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 189 | } 190 | } else if (flag == QUICKNET_FLAG_PULL) { 191 | //std::map::iterator it = m_mapSendPacket.find(sn); 192 | PacketHash::iterator it = m_mapSendPacket.find(sn); 193 | log(NACK_LOG_INFO, "packet input ack, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 194 | if (it != m_mapSendPacket.end()) { 195 | log(NACK_LOG_INFO, "packet input ack output, sn:%d, max_sn:%d recv_sn:%d", sn, m_nMaxPacketSn, m_nLastRecvSn); 196 | // 只拉包一次的话,不需要重新分配了,直接在缓存删除,序号列表继续占位 197 | //if (output) output((ProtocolPacket*)it->second, m_pUser); 198 | //else delete (ProtocolPacket*)it->second; 199 | //m_mapSendPacket.erase(sn); 200 | // 2012.9.25 修改成两次拉包 201 | if (output) 202 | { 203 | ProtocolPacket *copy; 204 | copy = it->second->copy(); 205 | output(copy, m_pUser); 206 | } 207 | } 208 | delete packet; 209 | } else { 210 | delete packet; 211 | return -1; 212 | } 213 | return 0; 214 | } 215 | 216 | int RequestRepeat::send(ProtocolPacket *packet) 217 | { 218 | //m_listSendPacket.push_back(packet); 219 | 220 | ProtocolPacket *copy; 221 | m_nSendPacketCounter++; 222 | packet->sn = m_nSendPacketCounter; 223 | packet->flag = QUICKNET_FLAG_DATA; 224 | packet->push_head_uint32(packet->sn); 225 | packet->push_head_uint8(packet->flag); 226 | // 克隆 227 | copy = packet->copy(); 228 | if (output) output(packet, m_pUser); 229 | else delete packet; 230 | // 进入拉包缓存 231 | if ((int)m_mapSendPacket.size() >= m_nPullSize) { 232 | IUINT32 sn = *m_listSendPacketSn.begin(); 233 | m_listSendPacketSn.pop_front(); 234 | //std::map::iterator it = m_mapSendPacket.find(sn); 235 | PacketHash::iterator it = m_mapSendPacket.find(sn); 236 | // 已经被拉的包不需要再释放 237 | if (it != m_mapSendPacket.end()) { 238 | delete (ProtocolPacket*)it->second; 239 | m_mapSendPacket.erase(it); 240 | } 241 | } 242 | m_listSendPacketSn.push_back(m_nSendPacketCounter); 243 | m_mapSendPacket[m_nSendPacketCounter] = copy; 244 | //log(NACK_LOG_INFO, "send, sn:%d", m_nSendPacketCounter); 245 | return 0; 246 | } 247 | 248 | int RequestRepeat::update(IUINT32 current, int rto) 249 | { 250 | m_nCurrent = current; 251 | if (rto <= 0) m_nRtt = QUICKNET_NACK_RTO_DEFAULT; 252 | else if (rto < QUICKNET_NACK_RTO_DEFAULT_MIN) m_nRtt = QUICKNET_NACK_RTO_DEFAULT_MIN_X2; 253 | else m_nRtt = rto > QUICKNET_NACK_RTO_DEFAULT_MAX ? QUICKNET_NACK_RTO_DEFAULT_MAX_X2 : rto*2; 254 | // 更新第二次拉包 255 | while (!m_listSecondPullPacketSn.empty()) 256 | { 257 | RecvSeq seq; 258 | seq = *m_listSecondPullPacketSn.begin(); 259 | if (itimediff(m_nCurrent, seq.m_nSendTime) >= 0) { 260 | m_listSecondPullPacketSn.pop_front(); 261 | if (m_nLastRecvSn < seq.m_nSn) { 262 | PacketHash::iterator it = m_mapRecvPacket.find(seq.m_nSn); 263 | if (it == m_mapRecvPacket.end()) { 264 | send_flag_pull(seq.m_nSn); 265 | } 266 | } 267 | } else { 268 | break; 269 | } 270 | } 271 | return 0; 272 | } 273 | 274 | ProtocolPacket *RequestRepeat::recv_packet() 275 | { 276 | ProtocolPacket *packet; 277 | RecvSeq seq; 278 | 279 | while(m_mapRecvPacket.size() > 0) 280 | { 281 | PacketHash::iterator it; 282 | //std::map::iterator it; 283 | it = m_mapRecvPacket.find(m_nLastRecvSn + 1); 284 | if (it != m_mapRecvPacket.end()) { 285 | packet = (ProtocolPacket *)it->second; 286 | m_nLastRecvSn = it->first; 287 | seq = *m_listRecvData.begin(); 288 | if(seq.m_nSn != m_nLastRecvSn) 289 | { 290 | log(NACK_LOG_ERROR, "recv packet error, sn1:%d, sn2:%d", m_nLastRecvSn, seq.m_nSn); 291 | assert(false); 292 | } 293 | int size = m_listRecvData.size(); 294 | m_listRecvData.pop_front(); 295 | m_mapRecvPacket.erase(it); 296 | log(NACK_LOG_INFO, "recv packet exist, sn:%d size_old:%d size_new:%d", m_nLastRecvSn, size, m_listRecvData.size()); 297 | return packet; 298 | } 299 | if (m_listRecvData.empty()) 300 | { 301 | log(NACK_LOG_ERROR, "recv packet error, list is empty, but map has items"); 302 | assert(false); 303 | } 304 | seq = *m_listRecvData.begin(); 305 | if (itimediff(m_nCurrent, seq.m_nSendTime) >= (IINT32)m_nRtt) { 306 | m_listRecvData.pop_front(); 307 | m_nLastRecvSn = seq.m_nSn; 308 | ++m_nPacketsLost; 309 | log(NACK_LOG_INFO, "recv packet lost, sn:%d, lost:%d rtt:%d", m_nLastRecvSn, m_nPacketsLost, m_nRtt); 310 | } else { 311 | break; 312 | } 313 | } 314 | return NULL; 315 | } 316 | 317 | int RequestRepeat::set_pull_size(int size) 318 | { 319 | m_nPullSize = size; 320 | return 0; 321 | } 322 | 323 | int RequestRepeat::get_pull_size() 324 | { 325 | return m_nPullSize; 326 | } 327 | 328 | int RequestRepeat::get_skip_size() 329 | { 330 | return m_nSkipSize; 331 | } 332 | 333 | void RequestRepeat::set_skip_size(int size) 334 | { 335 | m_nSkipSize = size; 336 | } 337 | 338 | 339 | void RequestRepeat::get_stat_info(int* packets, int *pull, int* pullpkts, int *lost, int *pulltimeout, int *skip, int *totalskippkt) 340 | { 341 | *packets = m_nLastRecvSn; 342 | *pull = m_nPacketsPull; 343 | *pullpkts = m_nTimesPull; 344 | *lost = m_nPacketsLost; 345 | *pulltimeout = m_nPacketsPullTimeout; 346 | *skip = m_nTimesSkip; 347 | *totalskippkt = m_nPacketsSkip; 348 | } 349 | 350 | NAMESPACE_END(QuickNet) 351 | 352 | -------------------------------------------------------------------------------- /network/RequestRepeat.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // RequestRepeat.h - Negitive Ack ARQ implementation 4 | // 5 | // NOTE: 6 | // 拉包协议实现,接收端发现序号不连续则发送 NACK到发送方。 7 | // 8 | //===================================================================== 9 | #ifndef __REQUEST_REPEAT_H__ 10 | #define __REQUEST_REPEAT_H__ 11 | 12 | #include "PacketBuffer.h" 13 | #include "ProtocolBasic.h" 14 | 15 | #include 16 | #include 17 | 18 | #ifdef __GNUC__ 19 | #ifdef __DEPRECATED 20 | #undef __DEPRECATED 21 | #endif 22 | #include 23 | namespace stdext { using namespace __gnu_cxx; } 24 | namespace __gnu_cxx { 25 | template<> struct hash< std::string > { 26 | size_t operator()( const std::string& x ) const { 27 | return hash< const char* >()( x.c_str() ); 28 | } 29 | }; 30 | } 31 | #else 32 | #ifndef _MSC_VER 33 | #include 34 | #elif (_MSC_VER < 1300) 35 | #include 36 | #define IHAVE_NOT_HASH_MAP 37 | #else 38 | #include 39 | #endif 40 | #endif 41 | 42 | NAMESPACE_BEGIN(QuickNet) 43 | 44 | #ifdef __GNUC__ 45 | using namespace __gnu_cxx; 46 | typedef hash_map PacketHash; 47 | #else 48 | using namespace stdext; 49 | typedef hash_map PacketHash; 50 | #endif 51 | 52 | struct RecvSeq 53 | { 54 | IUINT32 m_nSendTime; 55 | IUINT32 m_nSn; 56 | }; 57 | 58 | //--------------------------------------------------------------------- 59 | // RequestRepeat 60 | //--------------------------------------------------------------------- 61 | class RequestRepeat 62 | { 63 | public: 64 | RequestRepeat(void* user); 65 | ~RequestRepeat(); 66 | public: 67 | // session 接口 68 | int input(ProtocolPacket *packet); 69 | int send(ProtocolPacket *packet); 70 | ProtocolPacket *recv_packet(); 71 | int update(IUINT32 current, int rto); 72 | // 设置拉包缓存大小 73 | int set_pull_size(int size); 74 | void send_flag_pull(int sn); 75 | int get_pull_size(); 76 | 77 | int get_skip_size(); 78 | void set_skip_size(int size); 79 | /* 80 | * @packets 总报文数 81 | * @pull 被拉过包的报文数 82 | * @pullpkts 实际拉包消息数,当前拉包策略下(仅仅参考) 83 | * @lost 实际丢包数 84 | * @pulltimeout 拉包后超时包个数(仅仅参考) 85 | * @skip 连续包忽略拉包次数 86 | * @totalskippkt 连续包忽略拉包总个数 87 | */ 88 | void get_stat_info(int* packets, int *pull, int* pullpkts, int *lost, int *pulltimeout, int *skip, int *totalskippkt); 89 | 90 | void log(int mask, const char *fmt, ...); 91 | 92 | public: 93 | // session接口 94 | int (*output)(ProtocolPacket *packet, void *user); 95 | void (*writelog)(const char *log, void *user); 96 | int logmask; 97 | 98 | IUINT32 m_nSendPacketCounter; // 发包计数 99 | int m_nPullSize; // 拉包缓存大小 100 | int m_nSkipSize; // 拉包忽略大小 101 | void *m_pUser; 102 | IUINT32 m_nMaxPacketSn; // 最大包大小 103 | IUINT32 m_nCurrent; // 当前时间戳 104 | IUINT32 m_nRtt; // 当前回射周期 105 | IUINT32 m_nLastRecvSn; // 上一个接受的序列号 106 | 107 | std::list m_listSendPacket; // 待发送包 108 | std::list m_listSendPacketSn; // 已发送包序号 109 | std::list m_listRecvData; // 待接收数据 110 | std::list m_listSecondPullPacketSn; // 等待第2次拉包序号 111 | PacketHash m_mapSendPacket; // 已发送包字典 112 | PacketHash m_mapRecvPacket; // 接收包字典 113 | //std::map m_mapSendPacket; // 已发送包字典 114 | //std::map m_mapRecvPacket; // 接收包字典 115 | 116 | int m_nTimesPull; // 拉包次数 117 | int m_nPacketsLost; // 丢包次数 118 | int m_nTimesRepeat; // 重包次数 119 | int m_nPacketsPullTimeout; // 超时拉包 120 | int m_nTimesSkip; // 忽略拉包次数 121 | int m_nPacketsSkip; // 忽略拉包的总个数 122 | int m_nPacketsPull; // 拉的包数 123 | }; 124 | 125 | #define QUICKNET_NACK_RTO_DEFAULT 300 126 | #define QUICKNET_NACK_RTO_DEFAULT_MIN 100 127 | #define QUICKNET_NACK_RTO_DEFAULT_MIN_X2 200 128 | #define QUICKNET_NACK_RTO_DEFAULT_MAX 250 129 | #define QUICKNET_NACK_RTO_DEFAULT_MAX_X2 500 130 | 131 | #define QUICKNET_NACK_PKTNUM_PULL_SKIP 23 132 | 133 | NAMESPACE_END(QuickNet) 134 | 135 | #endif 136 | 137 | 138 | -------------------------------------------------------------------------------- /network/SessionDesc.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // SessionDesc.h - 会话模块,一个 Session就是一个链接 4 | // 5 | // NOTE: 6 | // Session 类用于描述一条 UDP连接,负责连接握手,连接保活,以及链路层 7 | // 传输,这是一个纯协议,没有网络部分。 8 | // SessionDict 是服务端用于管理所有连接的一个字典,用32位整数 hid来管 9 | // 理每一条连接的 Session对象。 10 | // 当接收到下层数据时,调用 PacketInput,PacketOutput用于输出到下层协 11 | // 议,上层协议发送调用 Send,上层协议接收调用 Recv 12 | // 13 | //===================================================================== 14 | #ifndef __SESSION_DESC_H__ 15 | #define __SESSION_DESC_H__ 16 | 17 | #include "ProtocolBasic.h" 18 | #include "../system/inetkcp.h" 19 | #include "../system/inettcp.h" 20 | #include "RequestRepeat.h" 21 | #include "Combinator.h" 22 | 23 | #include 24 | #include 25 | 26 | 27 | NAMESPACE_BEGIN(QuickNet) 28 | static const IUINT32 SESSION_MAX_CONN_TIME = 700000; // 默认最长连接时间 10秒 29 | static const IUINT32 SESSION_MAX_IDLE_TIME = 70000; // 默认最长空闲时间 70秒 30 | 31 | 32 | // 断开编码 33 | #define QNET_CODE_TIMEOUT 81 34 | #define QNET_CODE_CONNECT_FAIL 82 35 | #define QNET_CODE_RESEND_FAIL 83 36 | 37 | //--------------------------------------------------------------------- 38 | // 连接状态 39 | //--------------------------------------------------------------------- 40 | #define QUICK_SESSION_STATE_CLOSED 0 // 关闭 41 | #define QUICK_SESSION_STATE_SYN1 1 // 客户端:连接1 42 | #define QUICK_SESSION_STATE_SYN2 2 // 客户端:连接2 43 | #define QUICK_SESSION_STATE_SYNWAIT 3 // 服务端:半连接 44 | #define QUICK_SESSION_STATE_ESTAB 4 // 建立连接 45 | #define QUICK_SESSION_STATE_FINWAIT 5 // 等待关闭 46 | 47 | 48 | //--------------------------------------------------------------------- 49 | // 链接描述符:解析第二层协议 50 | //--------------------------------------------------------------------- 51 | class Session 52 | { 53 | public: 54 | Session(IUINT32 hid, IUINT32 conv); 55 | virtual ~Session(); 56 | 57 | IUINT32 hid() const { return _hid; } 58 | IUINT32 conv() const { return _conv; } 59 | int state() const { return _state; } 60 | 61 | //是否正在连接; 62 | bool IsConnecting() const; 63 | IINT32 LifeTime(IUINT32 current) const { 64 | if (_updated == false) return 0; 65 | return itimediff(_current, _tscreate); 66 | } 67 | 68 | IINT32 IdleTime(IUINT32 current) const { 69 | if (_updated == false) return 0; 70 | return itimediff(_current, _tsactive); 71 | } 72 | 73 | void SetTrace(Trace *trace); 74 | 75 | // 更新状态 76 | void Update(IUINT32 current, bool flush = true); 77 | 78 | // 输入并处理第二层协议(已经解出 hid, conv的数据包) 79 | void PacketInput(ProtocolPacket *packet); 80 | 81 | // 连接远端地址 82 | bool Connect(System::SockAddress &remote, IUINT32 conv); 83 | 84 | // 断开连接 85 | bool Disconnect(); 86 | 87 | // 接受连接 88 | bool AcceptSyn1(const System::SockAddress &remote); 89 | 90 | // 发送消息:需要带上 protocol 91 | bool Send(ProtocolPacket *packet, int limit = -1); 92 | 93 | // 发送数据: 94 | bool Send(int protocol, const void *data, int size, int limit = -1); 95 | 96 | // 接收消息 97 | ProtocolPacket* Recv(bool peek = false); 98 | 99 | // 开始 PING 100 | void RemotePing(); 101 | 102 | // 接收消息 直接接收 103 | // 成功返回消息长度,没有消息则返回-1,长度错误返回 -2 104 | // protocol为null则返回消息长度 105 | int Recv(int *protocol, void *data, int size); 106 | 107 | // 设置 MTU 108 | void SetMTU(int mtu); 109 | 110 | // 协议更新 111 | int Option(int option, int value); 112 | 113 | int GetOption(int option) const; 114 | 115 | // 安装协议 116 | bool TransmissionInstall(Transmission::Factory factory); 117 | 118 | // 取得 RTT 119 | int GetRtt() const; 120 | 121 | // 取得 KCP的待发送数据 122 | int GetPending(int what) const; 123 | 124 | /* 125 | * @packets 总报文数 126 | * @pull 被拉过包的报文数 127 | * @pullpkts 实际拉包消息数,当前拉包策略下(仅仅参考) 128 | * @lost 实际丢包数 129 | * @pulltimeout 拉包后超时包个数(仅仅参考) 130 | * @skip 连续包忽略拉包次数 131 | * @totalskippkt 连续包忽略拉包总个数 132 | */ 133 | void GetNACKStatInfo(int* packets, int *pull, int* pullpkts, int *lost, int *pulltimeout, int *skip, int *totalskippkt); 134 | 135 | 136 | protected: 137 | // 发送协议命令 138 | void SendCommand(int command, const void *data = NULL, int size = -1); 139 | 140 | // 加入第二层协议头:conv, hid并放入 output队列 141 | void PacketOutput(ProtocolPacket *packet); 142 | 143 | void OnConnected(); 144 | 145 | void OnDisconnected(); 146 | 147 | void InputCommandData(ProtocolPacket *packet); 148 | 149 | void InputCommandPack(ProtocolPacket *packet); 150 | 151 | // 自动判断是否有传输层 Transmission,否则直接调用 PacketOutput 152 | void Transport(ProtocolPacket *packet); 153 | 154 | // 传输层:接收上一层数据 155 | static void TransmissionDeliver(ProtocolPacket *packet, void *user); 156 | 157 | // 传输层:发送下一层数据 158 | static void TransmissionOutput(ProtocolPacket *packet, void *user); 159 | 160 | // 合并数据包传输,判断是否开启合并,开启的话就使用合并,下层调用 Transport 161 | void CombineTransport(ProtocolPacket *packet); 162 | 163 | // 接收到 Combinator 数据 164 | void CombineInput(ProtocolPacket *packet); 165 | 166 | // 合并层:传递上一层数据 167 | static void CombinatorDeliver(const void *data, int size, int protocol, void *user); 168 | 169 | // 合并层:发送下一层数据 170 | static void CombinatorOutput(ProtocolPacket *packet, void *user); 171 | 172 | void ProtocolInit(); 173 | void ProtocolDestroy(); 174 | bool ProtocolSend(int protocol, const void *data, int size, int limit = -1); 175 | void ProtocolUpdate(bool flush); 176 | void ProtocolInput(ProtocolPacket *packet); 177 | void ProtocolFlush(); 178 | 179 | static int TcpOutput(const char *buf, int len, struct ITCPCB *tcp, void *user); 180 | static int KcpOutput(const char *buf, int len, struct IKCPCB *kcp, void *user); 181 | static int NackOutput(ProtocolPacket *packet, void *user); 182 | static void KcpLog(const char *log, struct IKCPCB *kcp, void *user); 183 | static void NackLog(const char *log, void *user); 184 | 185 | public: 186 | PacketList output; // 需要发送的包列表 187 | System::SockAddress origin; // 原始目标地址:最开始Connect的地址 188 | System::SockAddress remote; // 当前目标地址:初始化为origin,或调整IP后的地址 189 | std::string ident; // 标志 190 | std::string token; // 秘钥 191 | int flags; // 给外面用的标志 192 | IUINT32 user; // 给外面用的标签 193 | bool deadmark; // 死亡标记 194 | IUINT32 deadcode; // 死亡编码 195 | std::list::iterator it; // 自己的迭代器 196 | 197 | protected: 198 | IUINT32 _hid; // server 端的索引编号 199 | IUINT32 _conv; // 会话验证码 200 | IUINT32 _tscreate; // 开始的时间 201 | IUINT32 _tsactive; // 最近活动时间 202 | IUINT8 _mask; // 加密序列 203 | IUINT32 _feature_local; // 本地特性 204 | IUINT32 _feature_remote; // 远程特性 205 | int _state; // 状态 206 | int _nodelay; // 是否快速模式 207 | int _mtu; // 最大传输单元 208 | int _mss; // 最大数据单元 209 | bool _connect; // 状态 210 | bool _ping; // 是否在 ping 211 | PacketList _events; // 接收到的消息 212 | TimeRto _rto; // 接收超时 213 | IUINT32 _current; // 当前时间 214 | int _nout_kcp; // KCP输出包技术 215 | Timeout _timeout; // 连接计时器 216 | Timeout _shutdown; // 关闭计时器 217 | Transmission *_transmission; // 扩展协议 218 | itcpcb *_tcp; // 原始TCP协议 219 | ikcpcb *_kcp; // 原始KCP协议 220 | RequestRepeat *_repeat; // 拉包协议 221 | Combinator *_combinator; // 合并数据 222 | bool _updated; // 是否更新过 223 | Trace *trace; // 日志输出器 224 | }; 225 | 226 | 227 | 228 | //--------------------------------------------------------------------- 229 | // 协议配置 230 | //--------------------------------------------------------------------- 231 | #define QUICKNET_OPT_NODELAY 0x1001 // 调用 send后立马发送:0、1 232 | #define QUICKNET_OPT_KCP_INTERVAL 0x1002 // 设置 KCP的内部时钟 233 | #define QUICKNET_OPT_KCP_NODELAY 0x1003 // 设置 KCP是否 nodelay 234 | #define QUICKNET_OPT_KCP_RESEND 0x1004 // 设置 KCP是否启用 resend 235 | #define QUICKNET_OPT_KCP_NC 0x1005 // 设置 KCP是否关闭流控 236 | #define QUICKNET_OPT_KCP_SNDWND 0x1006 // 设置 KCP的发送 237 | #define QUICKNET_OPT_KCP_RCVWND 0x1007 // 设置 KCP的接收窗口 238 | #define QUICKNET_OPT_KCP_MINRTO 0x1008 // 设置 KCP的最小RTO 239 | #define QUICKNET_OPT_KCP_LOG 0x1009 // 设置 KCP的日志 240 | #define QUICKNET_OPT_KCP_XMIT 0x100A // 设置 xmit sum in kcp send buffer 241 | #define QUICKNET_OPT_KCP_DEAD_LINK 0x100B // 设置 dead_link . 每个segment重发次xmit数超过此,则为dead_link. 242 | #define QUICKNET_OPT_KCP_STREAM 0x100C // 设置 使用流模式 243 | #define QUICKNET_OPT_TCP_NODELAY 0x1010 // 设置 TCP的 NODELAY模式:0,1 244 | #define QUICKNET_OPT_TCP_BUFSIZE 0x1011 // 设置 TCP的 缓存大小 245 | #define QUICKNET_OPT_NACK_BUFSIZE 0x1012 // 设置 拉包缓存大小 (单位:包个数) 246 | #define QUICKNET_OPT_NACK_LOG 0x1013 // 设置 拉包日志 247 | #define QUICKNET_OPT_NACK_SKIPSIZE 0x1014 // 设置 拉包忽略的包个数 248 | #define QUICKNET_OPT_KCP_RTO 0x1015 // 读取:KCP的 RTO 249 | #define QUICKNET_OPT_KCP_WAITSND 0x1016 // 读取:KCP的待发送数据大小 250 | #define QUICKNET_OPT_KCP_SNDPKT 0x1017 // 读取:KCP的总发送数据包 251 | #define QUICKNET_OPT_KCP_RTT 0x1018 // 读取:KCP的RTT 252 | #define QUICKNET_OPT_KCP_OUTWND 0x1019 // 读取:KCP的不在发送窗口中的数据包个数 253 | #define QUICKNET_OPT_KCP_WNDSND 0x1020 // 读取:KCP的当前窗口包数量 254 | #define QUICKNET_OPT_COMBINE_LIMIT 0x1022 // 设置:合包的限制(默认900) 255 | #define QUICKNET_OPT_COMBINE_PERIOD 0x1023 // 设置:合包的周期(默认20) 256 | #define QUICKNET_OPT_FEATURE_LOC 0x1084 // 设置:本地特性 257 | #define QUICKNET_OPT_FEATURE_RMT 0x1085 // 设置:远程特性 258 | 259 | #define QUICKNET_FEATURES 0x3 // 1 + 2 260 | 261 | #define QUICKNET_FEATURE_COMBINE_RECV 1 262 | #define QUICKNET_FEATURE_COMBINE_SEND 2 263 | 264 | 265 | //--------------------------------------------------------------------- 266 | // SessionDict 267 | // 用于服务端以整数 hid的方式管理所有 Session的容器 268 | //--------------------------------------------------------------------- 269 | class SessionDict 270 | { 271 | public: 272 | inline SessionDict(); 273 | inline virtual ~SessionDict(); 274 | 275 | // 根据 hid取得 session,不存在返回NULL 276 | inline Session* GetSession(IUINT32 hid); 277 | inline const Session* GetSession(IUINT32 hid) const; 278 | 279 | // 根据 hid取得 session,不存在返回NULL 280 | inline Session* operator[](IUINT32 hid); 281 | inline const Session* operator[](IUINT32 hid) const; 282 | 283 | // 新建 session,返回新 session的 hid 284 | inline IUINT32 NewSession(IUINT32 conv); 285 | inline bool DelSession(IUINT32 hid); 286 | 287 | // 迭代器 288 | inline IUINT32 First() const; 289 | inline IUINT32 Next(IUINT32 hid) const; 290 | inline int Count() const; 291 | inline void Clear(); 292 | 293 | typedef std::list SessionList; 294 | inline SessionList::const_iterator Begin() const; 295 | inline SessionList::const_iterator End() const; 296 | 297 | protected: 298 | IUINT32 _hiword; 299 | SessionList _list; 300 | System::MemNode _nodes; 301 | }; 302 | 303 | 304 | // 初始化 高位字节以及会话编号 305 | inline SessionDict::SessionDict() { 306 | _hiword = 1; 307 | } 308 | 309 | inline SessionDict::~SessionDict() { 310 | Clear(); 311 | } 312 | 313 | // 根据 hid取得 session,不存在返回NULL 314 | inline Session* SessionDict::GetSession(IUINT32 hid) { 315 | IUINT32 index = ((IUINT32)hid) & 0x3fff; 316 | //if (hid < 0) return NULL; 317 | if ((IINT32)index >= _nodes.node_max()) return NULL; 318 | Session *session = (Session*)_nodes[index]; 319 | if (session == NULL) return NULL; 320 | if (session->hid() != (IUINT32)hid) return NULL; 321 | return session; 322 | } 323 | 324 | // 根据 hid取得 session,不存在返回NULL 325 | inline const Session* SessionDict::GetSession(IUINT32 hid) const { 326 | IUINT32 index = ((IUINT32)hid) & 0x3fff; 327 | //if (hid < 0) return NULL; 328 | if ((IINT32)index >= _nodes.node_max()) return NULL; 329 | const Session *session = (const Session*)_nodes[index]; 330 | if (session == NULL) return NULL; 331 | if (session->hid() != (IUINT32)hid) return NULL; 332 | return session; 333 | } 334 | 335 | // 根据 hid取得 session,不存在返回NULL 336 | inline Session* SessionDict::operator[](IUINT32 hid) { 337 | return GetSession(hid); 338 | } 339 | 340 | // 根据 hid取得 session,不存在返回NULL 341 | inline const Session* SessionDict::operator[](IUINT32 hid) const { 342 | return GetSession(hid); 343 | } 344 | 345 | // 新建一个 Session(自动生成 hid并返回) 346 | inline IUINT32 SessionDict::NewSession(IUINT32 conv) { 347 | if (_nodes.size() >= 0x3fff) return 0; 348 | ilong id = _nodes.new_node(); 349 | if (id < 0) return 0; 350 | if (id >= 0x3fff) { 351 | SYSTEM_THROW("SessionDict::NewSession error new id", 10000); 352 | return 0; 353 | } 354 | IUINT32 hid = (IUINT32)id; 355 | hid |= _hiword << 14; 356 | _hiword++; 357 | if (_hiword > 0x1fff) { 358 | _hiword = 1; 359 | } 360 | Session *session = new Session(hid, conv); 361 | if (session == NULL) { 362 | _nodes.delete_node(id); 363 | SYSTEM_THROW("SessionDict::NewSession error new session", 10001); 364 | return 0; 365 | } 366 | _nodes[id] = session; 367 | session->it = _list.insert(_list.end(), session); 368 | return hid; 369 | } 370 | 371 | // 删除一个 Session 372 | inline bool SessionDict::DelSession(IUINT32 hid) { 373 | IUINT32 index = ((IUINT32)hid) & 0x3fff; 374 | //if (hid < 0) return false; 375 | if ((IUINT32)index >= (IUINT32)_nodes.node_max()) return false; 376 | Session *session = (Session*)_nodes[index]; 377 | if (session == NULL) return false; 378 | if (session->hid() != (IUINT32)hid) return false; 379 | _nodes[index] = NULL; 380 | _list.erase(session->it); 381 | session->it = _list.end(); 382 | delete session; 383 | _nodes.delete_node(index); 384 | return true; 385 | } 386 | 387 | // 取得第一个 hid 388 | inline IUINT32 SessionDict::First() const { 389 | ilong id = _nodes.head(); 390 | if (id < 0) return 0; 391 | const Session *session = (const Session*)_nodes[id]; 392 | if (session == NULL) { 393 | SYSTEM_THROW("SessionDict::First error", 10002); 394 | return 0; 395 | } 396 | return session->hid(); 397 | } 398 | 399 | // 取得下一个 hid 400 | inline IUINT32 SessionDict::Next(IUINT32 hid) const { 401 | ilong index = (ilong)(hid & 0x3fff); 402 | if (index < 0 || (IUINT32)index >= (IUINT32)_nodes.node_max()) return 0; 403 | const Session *session = (const Session*)_nodes[index]; 404 | if (session == NULL) return 0; 405 | if (session->hid() != (IUINT32)hid) return 0; 406 | index = _nodes.next(index); 407 | if (index < 0) return 0; 408 | session = (const Session*)_nodes[index]; 409 | if (session == NULL) { 410 | SYSTEM_THROW("SessionDict::Next error", 10003); 411 | return 0; 412 | } 413 | return session->hid(); 414 | } 415 | 416 | // 取得数量 417 | inline int SessionDict::Count() const { 418 | return _nodes.size(); 419 | } 420 | 421 | // 清空会话 422 | inline void SessionDict::Clear() { 423 | while (_nodes.size() > 0) { 424 | IUINT32 hid = First(); 425 | if (hid == 0) { 426 | SYSTEM_THROW("SessionDict::Clear error", 10004); 427 | return; 428 | } 429 | bool hr = DelSession(hid); 430 | if (hr == false) { 431 | SYSTEM_THROW("SessionDict::Clear delete error", 10005); 432 | return; 433 | } 434 | } 435 | } 436 | 437 | inline SessionDict::SessionList::const_iterator SessionDict::Begin() const { 438 | return _list.begin(); 439 | } 440 | 441 | inline SessionDict::SessionList::const_iterator SessionDict::End() const { 442 | return _list.end(); 443 | } 444 | 445 | NAMESPACE_END(QuickNet) 446 | 447 | 448 | 449 | #endif 450 | 451 | 452 | -------------------------------------------------------------------------------- /network/SessionManager.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // SessionManager.h - 会话管理模块 4 | // 5 | // NOTE: 6 | // 使用 SessionDict管理服务端的所有连接,并且提供协议解析还有消息 7 | // 8 | //===================================================================== 9 | #ifndef __SESSION_MANAGER_H__ 10 | #define __SESSION_MANAGER_H__ 11 | 12 | #include "SessionDesc.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | NAMESPACE_BEGIN(QuickNet) 20 | //--------------------------------------------------------------------- 21 | // 服务端消息 22 | //--------------------------------------------------------------------- 23 | #define QUICKNET_EVENT_NEW 0 // 有人加入:wparam = hid 24 | #define QUICKNET_EVENT_LEAVE 1 // 有人离开:wparam = hid 25 | #define QUICKNET_EVENT_DATA 2 // 收到数据:wparam = hid, lparam = protocol 26 | 27 | #define QUICKNET_MAX_SESSION 0x3fff // 最多连接数 16383个连接(不能更改和id生成规则有关) 28 | #define QUICKNET_MAX_BACKLOG 1024 // 最多同时连接数 29 | 30 | 31 | 32 | 33 | //--------------------------------------------------------------------- 34 | // 会话服务端:根据消息管理 Session和 SessionDict 35 | //--------------------------------------------------------------------- 36 | class SessionManager 37 | { 38 | public: 39 | SessionManager(void *user); 40 | virtual ~SessionManager(); 41 | 42 | void SetTrace(Trace *trace); 43 | 44 | void Update(IUINT32 current, bool force = false, bool flush = false); 45 | 46 | // 输入第一层协议的协议包,解码层第二层协议,传递给其他 47 | void PacketInput(ProtocolPacket *packet, const System::SockAddress &remote); 48 | 49 | // 取得消息 50 | ProtocolPacket *GetEvent(bool peek = false); 51 | 52 | // 取得消息 直接方式,成功返回消息长度,返回-1代表没有消息,-2代表长度错误, 53 | // 如果 event, wparam, lparam 任意为 NULL 则返回消息长度 54 | // event会是:QUICKNET_EVENT_NEW/LEAVE/DATA 55 | int ReadEvent(int *event, IUINT32 *wparam, IUINT32 *lparam, void *data, int size); 56 | 57 | // 关闭连接 58 | bool SessionClose(IUINT32 hid, IUINT32 code); 59 | 60 | // 发送数据 61 | bool SessionSend(IUINT32 hid, ProtocolPacket *packet, int limit = -1); 62 | 63 | // 发送数据 64 | bool SessionSend(IUINT32 hid, int protocol, const void *data, int size, int limit = -1); 65 | 66 | // 关闭服务 67 | void Shutdown(); 68 | 69 | // 设置超时 70 | // idle是空闲超时,-1为不设置,0为取消空闲超时,>0为毫秒时间,超过这个时间收不到包的客户端断开 71 | // connect连接超时,-1为不设置,0为取消连接超时,>0为毫秒时间,超过这个时间没连接成功的客户端断开 72 | void SetTimeOut(int idle = -1, int connect = -1); 73 | 74 | // 协议配置 75 | int Option(IUINT32 hid, int option, int value); 76 | int GetOption(IUINT32 hid, int option); 77 | 78 | // 设置 Interval 79 | void SetInterval(int interval); 80 | 81 | // 设置新协议工厂 82 | void SetTransmission(Transmission::Factory factory); 83 | 84 | // 取得状态:0关闭,1连接1,2连接2,3连接等待,4建立连接,5关闭等待。-1为错误 hid 85 | int GetState(IUINT32 hid) const; 86 | 87 | // 广播 传入 HID列表,进行广播,返回成功的个数 88 | int GroupCast(const IUINT32 *hid, int count, int protocol, const void *buffer, int size, int limit = -1); 89 | 90 | // 广播所有人,返回成功的个数 91 | int Broadcast(int protocol, const void *buffer, int size, int limit = -1); 92 | 93 | // 取得待发送数据 94 | int GetPending(IUINT32 hid, int what) const; 95 | 96 | public: 97 | void (*PacketOutput)(ProtocolPacket *packet, const System::SockAddress &remote, void *user); 98 | 99 | protected: 100 | void Output(ProtocolPacket *packet, const System::SockAddress &remote); 101 | void GetIdent(const System::SockAddress &remote, IUINT32 conv, std::string &ident); 102 | void HandleSyn1(ProtocolPacket *packet, const System::SockAddress &remote); 103 | void HandleSyn2(ProtocolPacket *packet, const System::SockAddress &remote); 104 | 105 | int SessionForward(Session *session, long limit = -1); // 检测 Session是否有网络包需要发送出去,有就转发 106 | void FetchEvents(Session *session); // 检测 Session是否有应用层数据,有就加入到 _events 107 | void PostEvent(ProtocolPacket *packet); // 向 _events链表发送一个事件 108 | void PostEvent(int event, IUINT32 wparam, IUINT32 lparam, const void *data, int size); 109 | 110 | void UpdateInterval(bool flush); 111 | 112 | void OnConnected(Session *session); 113 | void OnDisconnected(Session *session, IUINT32 code); 114 | void OnData(Session *session); 115 | 116 | protected: 117 | IUINT32 _current; 118 | IUINT32 _slap; 119 | IUINT32 _interval; 120 | IUINT32 _time_max_connect; 121 | IUINT32 _time_max_idle; 122 | bool _updated; 123 | void *_user; 124 | int _nlisten; 125 | Trace *trace; 126 | std::vector _remove; 127 | typedef std::map ListenBacklog; 128 | Transmission::Factory _factory; 129 | PacketList _events; 130 | ListenBacklog _listens; // ident to hid 131 | SessionDict _sessions; 132 | }; 133 | 134 | NAMESPACE_END(QuickNet) 135 | 136 | 137 | #endif 138 | 139 | 140 | -------------------------------------------------------------------------------- /network/TransportUdp.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // TransportUdp.cpp - UDP 传输以及 Qos设置 4 | // 5 | // NOTE: 6 | // for more information please see the readme file. 7 | // 8 | //===================================================================== 9 | #include "TransportUdp.h" 10 | 11 | NAMESPACE_BEGIN(QuickNet) 12 | 13 | const IUINT32 QUICKNET_UDP_OVERHEAD = 42; 14 | 15 | //--------------------------------------------------------------------- 16 | // TransportUdp 17 | //--------------------------------------------------------------------- 18 | TransportUdp::TransportUdp() 19 | { 20 | _sock = -1; 21 | _port = -1; 22 | _ip = 0; 23 | } 24 | 25 | TransportUdp::~TransportUdp() 26 | { 27 | close(); 28 | } 29 | 30 | bool TransportUdp::open(int port, IUINT32 ip, bool block) 31 | { 32 | sockaddr local; 33 | close(); 34 | memset(&local, 0, sizeof(local)); 35 | isockaddr_set(&local, ip, port); 36 | _sock = isocket_udp_open(&local, 0, block? 512 : 0); 37 | if (_sock < 0) { 38 | return false; 39 | } 40 | //ienable(_sock, ISOCK_REUSEADDR); 41 | isockname(_sock, _local_address.address(), NULL); 42 | _ip = ip; 43 | _port = port; 44 | set_tos(46, -1); // EF 45 | return true; 46 | } 47 | 48 | void TransportUdp::close() 49 | { 50 | memset(&_stat_current, 0, sizeof(_stat_current)); 51 | 52 | if (_sock >= 0) { 53 | iclose(_sock); 54 | _sock = -1; 55 | } 56 | 57 | _ip = 0; 58 | _port = -1; 59 | _local_address.set((unsigned long)0, 0); 60 | } 61 | 62 | int TransportUdp::set_tos(int dscp, int cos) 63 | { 64 | if (_sock < 0) return -1; 65 | #ifdef __APPLE__ 66 | return -1; 67 | #elif defined(__unix) && defined(SO_PRIORITY) 68 | if (dscp < 0 || dscp > 63) return -2; 69 | if (cos < -1 || cos > 7) return -3; 70 | int tos = dscp << 2; 71 | if(0 != isetsockopt(_sock, IPPROTO_IP, IP_TOS, (char*)&tos, 4 )) { 72 | return -4; 73 | } 74 | if (cos != -1) { 75 | if (0 != isetsockopt(_sock, SOL_SOCKET, SO_PRIORITY, (char*) &cos, 4)) { 76 | return -5; 77 | } 78 | } 79 | return 0; 80 | #else 81 | return -1; 82 | #endif 83 | } 84 | 85 | int TransportUdp::send(const void *data, int len, const sockaddr *addr) 86 | { 87 | if (_sock < 0) return -3; 88 | int hr = isendto(_sock, data, len, 0, addr, 0); 89 | if (hr < 0) { 90 | _stat_current.discard_count++; 91 | _stat_current.discard_size += len; 92 | _stat_current.discard_data += len + QUICKNET_UDP_OVERHEAD; 93 | if (ierrno() == IEAGAIN) { 94 | return -1; 95 | } 96 | return -2; 97 | } 98 | _stat_current.out_count++; 99 | _stat_current.out_size += len; 100 | _stat_current.out_data += len + QUICKNET_UDP_OVERHEAD; 101 | return hr; 102 | } 103 | 104 | int TransportUdp::send(const void *data, int len, IUINT32 ip, int port) 105 | { 106 | System::SockAddress remote(ip, port); 107 | return send(data, len, remote.address()); 108 | } 109 | 110 | int TransportUdp::send(const void *data, int len, const System::SockAddress &addr) 111 | { 112 | return send(data, len, addr.address()); 113 | } 114 | 115 | int TransportUdp::send(const void *data, int len, const char *ip, int port) 116 | { 117 | System::SockAddress remote(ip, port); 118 | return send(data, len, remote.address()); 119 | } 120 | 121 | int TransportUdp::recv(void *data, int len, sockaddr *addr) 122 | { 123 | if (_sock < 0) return -3; 124 | int hr = irecvfrom(_sock, data, len, 0, addr, 0); 125 | if (hr < 0) { 126 | if (ierrno() == IEAGAIN) return -1; 127 | return -2; 128 | } 129 | _stat_current.in_count++; 130 | _stat_current.in_size += hr; 131 | _stat_current.in_data += hr + QUICKNET_UDP_OVERHEAD; 132 | return hr; 133 | } 134 | 135 | int TransportUdp::recv(void *data, int len, IUINT32 *ip, int *port) 136 | { 137 | System::SockAddress remote; 138 | int hr = recv(data, len, remote.address()); 139 | ip[0] = remote.get_ip(); 140 | port[0] = remote.get_port(); 141 | return hr; 142 | } 143 | 144 | int TransportUdp::recv(void *data, int len, System::SockAddress &addr) 145 | { 146 | return recv(data, len, addr.address()); 147 | } 148 | 149 | int TransportUdp::recv(void *data, int len, char *ip, int *port) 150 | { 151 | System::SockAddress remote; 152 | int hr = recv(data, len, remote.address()); 153 | remote.get_ip_text(ip); 154 | port[0] = remote.get_port(); 155 | return hr; 156 | } 157 | 158 | int TransportUdp::set_buffer(int sndbuf, int rcvbuf) 159 | { 160 | return isocket_set_buffer(_sock, rcvbuf, sndbuf); 161 | } 162 | 163 | int TransportUdp::get_buffer(int *sndbuf, int *rcvbuf) 164 | { 165 | if (_sock < 0) return -1; 166 | if (sndbuf) { 167 | long bufsize = 0; 168 | int len = sizeof(long); 169 | int hr = igetsockopt(_sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, &len); 170 | if (hr < 0) return -2; 171 | *sndbuf = (int)bufsize; 172 | } 173 | if (rcvbuf) { 174 | long bufsize = 0; 175 | int len = sizeof(long); 176 | int hr = igetsockopt(_sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, &len); 177 | if (hr < 0) return -3; 178 | *rcvbuf = (int)bufsize; 179 | } 180 | return 0; 181 | } 182 | 183 | int TransportUdp::poll(int mask, IUINT32 millisec) 184 | { 185 | if (_sock < 0) return 0; 186 | return ipollfd(_sock, mask, millisec); 187 | } 188 | 189 | void TransportUdp::stat(statistic &st) 190 | { 191 | st = _stat_current; 192 | } 193 | 194 | void TransportUdp::local(System::SockAddress &address) 195 | { 196 | address = _local_address; 197 | } 198 | 199 | NAMESPACE_END(QuickNet) 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /network/TransportUdp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // TransportUdp.h - UDP 传输以及 Qos设置 4 | // 5 | // NOTE: 6 | // for more information please see the readme file. 7 | // 8 | //===================================================================== 9 | #ifndef __TRANSPORT_UDP_H__ 10 | #define __TRANSPORT_UDP_H__ 11 | 12 | #include "../system/system.h" 13 | 14 | NAMESPACE_BEGIN(QuickNet) 15 | //--------------------------------------------------------------------- 16 | // TransportUdp 17 | //--------------------------------------------------------------------- 18 | class TransportUdp 19 | { 20 | public: 21 | TransportUdp(); 22 | virtual ~TransportUdp(); 23 | 24 | // 打开并绑定端口 25 | bool open(int port, IUINT32 ip = 0, bool block = false); 26 | void close(); 27 | 28 | int set_tos(int dscp, int cos); 29 | 30 | int send(const void *data, int len, const sockaddr *addr); 31 | int send(const void *data, int len, IUINT32 ip, int port); 32 | int send(const void *data, int len, const System::SockAddress &addr); 33 | int send(const void *data, int len, const char *ip, int port); 34 | 35 | int recv(void *data, int len, sockaddr *addr); 36 | int recv(void *data, int len, IUINT32 *ip, int *port); 37 | int recv(void *data, int len, System::SockAddress &addr); 38 | int recv(void *data, int len, char *ip, int *port); 39 | 40 | int set_buffer(int sndbuf = -1, int rcvbuf = -1); 41 | int get_buffer(int *sndbuf = NULL, int *rcvbuf = NULL); 42 | 43 | int poll(int mask, IUINT32 millisec); 44 | 45 | void local(System::SockAddress &address); 46 | 47 | public: 48 | struct statistic { 49 | IUINT64 out_count; 50 | IUINT64 out_size; 51 | IUINT64 out_data; 52 | IUINT64 in_count; 53 | IUINT64 in_size; 54 | IUINT64 in_data; 55 | IUINT64 discard_count; 56 | IUINT64 discard_size; 57 | IUINT64 discard_data; 58 | }; 59 | 60 | void stat(statistic &st); 61 | 62 | protected: 63 | int _sock; 64 | int _port; 65 | IUINT32 _ip; 66 | System::SockAddress _local_address; 67 | statistic _stat_current; 68 | }; 69 | 70 | 71 | NAMESPACE_END(QuickNet) 72 | 73 | #endif 74 | 75 | 76 | -------------------------------------------------------------------------------- /system/fec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fec.c -- forward error correction based on Vandermonde matrices 3 | * 980614 4 | * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) 5 | * 6 | * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), 7 | * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari 8 | * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above 17 | * copyright notice, this list of conditions and the following 18 | * disclaimer in the documentation and/or other materials 19 | * provided with the distribution. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 26 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 | * OF SUCH DAMAGE. 33 | */ 34 | 35 | /* 36 | * The following parameter defines how many bits are used for 37 | * field elements. The code supports any value from 2 to 16 38 | * but fastest operation is achieved with 8 bit elements 39 | * This is the only parameter you may want to change. 40 | */ 41 | 42 | #ifndef __FEC_H__ 43 | #define __FEC_H__ 44 | 45 | #ifndef DEFS_H 46 | #define DEFS_H 47 | 48 | //#define HAVE_CONFIG_H 49 | //#ifdef HAVE_CONFIG_H 50 | //#include "config.h" 51 | /* Define if you don't have `vprintf' but do have `_doprnt.' */ 52 | #undef HAVE_DOPRNT 53 | 54 | /* Define if you have the header file. */ 55 | #undef HAVE_ERRNO_H 56 | 57 | /* Define if you have the `gettimeofday' function. */ 58 | #undef HAVE_GETTIMEOFDAY 59 | 60 | /* Define if you have the header file. */ 61 | #undef HAVE_INTTYPES_H 62 | 63 | /* Define if you have the header file. */ 64 | #define HAVE_MEMORY_H 65 | 66 | /* Define if you have the `memset' function. */ 67 | //#undef HAVE_MEMSET 68 | 69 | /* Define if you have the header file. */ 70 | //#undef HAVE_NETINET_IN_H 71 | 72 | /* Define if you have the header file. */ 73 | //#undef HAVE_STDINT_H 74 | 75 | /* Define if you have the header file. */ 76 | #define HAVE_STDLIB_H 77 | 78 | /* Define if you have the header file. */ 79 | #undef HAVE_STRINGS_H 80 | 81 | /* Define if you have the header file. */ 82 | #undef HAVE_STRING_H 83 | 84 | /* Define if you have the header file. */ 85 | #undef HAVE_SYS_STAT_H 86 | 87 | /* Define if you have the header file. */ 88 | #undef HAVE_SYS_TYPES_H 89 | 90 | /* Define if you have the header file. */ 91 | #undef HAVE_UNISTD_H 92 | 93 | /* Define if the system has the type `u_char'. */ 94 | #undef HAVE_U_CHAR 95 | 96 | /* Define if the system has the type `u_int32_t'. */ 97 | #undef HAVE_U_INT32_T 98 | 99 | /* Define if you have the `vprintf' function. */ 100 | #undef HAVE_VPRINTF 101 | 102 | /* The size of a `int', as computed by sizeof. */ 103 | #undef SIZEOF_INT 104 | 105 | /* The size of a `long', as computed by sizeof. */ 106 | #undef SIZEOF_LONG 107 | 108 | /* Define if you have the ANSI C header files. */ 109 | #undef STDC_HEADERS 110 | 111 | /* Define if you can safely include both and . */ 112 | #undef TIME_WITH_SYS_TIME 113 | 114 | /* Define to empty if `const' does not conform to ANSI C. */ 115 | #undef const 116 | 117 | /* Define as `__inline' if that's what the C compiler calls it, or to nothing 118 | if it is not supported. */ 119 | #undef inline 120 | 121 | /* Define to `long' if does not define. */ 122 | #undef off_t 123 | 124 | /* Define to `unsigned' if does not define. */ 125 | #undef size_t 126 | 127 | //#endif 128 | 129 | #include 130 | 131 | #if HAVE_SYS_TYPES_H 132 | # include 133 | #endif 134 | 135 | #if HAVE_SYS_STAT_H 136 | # include 137 | #endif 138 | 139 | #if STDC_HEADERS 140 | # include 141 | # include 142 | #else 143 | #ifdef HAVE_STDLIB_H 144 | # include 145 | # endif 146 | #endif 147 | 148 | #if HAVE_STRING_H 149 | # if !STDC_HEADERS && HAVE_MEMORY_H 150 | # include 151 | # endif 152 | # include 153 | #else 154 | # if HAVE_STRINGS_H 155 | # include 156 | # endif 157 | #endif 158 | 159 | #if HAVE_INTTYPES_H 160 | # include 161 | #else 162 | # if HAVE_STDINT_H 163 | # include 164 | # endif 165 | #endif 166 | 167 | #if HAVE_UNISTD_H 168 | # include 169 | #endif 170 | 171 | #if TIME_WITH_SYS_TIME 172 | # include 173 | # include 174 | #else 175 | # if HAVE_SYS_TIME_H 176 | # include 177 | # else 178 | # include 179 | # endif 180 | #endif 181 | //#define HAVE_MEMCPY 182 | #if STDC_HEADERS 183 | # include 184 | #else 185 | //# if !HAVE_MEMCPY 186 | //# define memcpy(d, s, n) bcopy ((s), (d), (n)) 187 | //# define memmove(d, s, n) bcopy ((s), (d), (n)) 188 | //# endif 189 | #endif 190 | #include 191 | 192 | //#define HAVE_MEMSET 193 | //#ifndef HAVE_BZERO 194 | //#ifdef HAVE_MEMSET 195 | #define bzero(d, siz) memset((d), 0, (siz)) 196 | #define bcopy(s, d, siz) memcpy((d), (s), (siz)) 197 | //#else 198 | //#error I need bzero or memset! 199 | //#endif 200 | //#endif 201 | 202 | #if HAVE_NETINET_IN_H 203 | # include /* for htonl and ntohl */ 204 | #endif 205 | 206 | #if HAVE_ERRNO_H 207 | # include 208 | #endif 209 | 210 | #if !HAVE_U_CHAR 211 | typedef unsigned char u_char; 212 | #endif 213 | 214 | #if !HAVE_U_INT32_T 215 | # if SIZEOF_INT == 4 216 | typedef unsigned int u_int32_t; 217 | # else 218 | # if SIZEOF_LONG == 4 219 | typedef unsigned long u_int32_t; 220 | # endif 221 | # endif 222 | #endif 223 | 224 | #endif /* DEFS_H */ 225 | 226 | 227 | #ifndef GF_BITS 228 | #define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */ 229 | #endif 230 | 231 | #define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */ 232 | 233 | #ifdef __cplusplus 234 | extern "C" { 235 | #endif 236 | 237 | void *fec_new(int k, int n); 238 | void fec_free(void *p); 239 | 240 | void fec_encode(void *code, u_char **src, u_char *dst, int index, int sz); 241 | int fec_decode(void *code, u_char **pkt, int *index, int sz); 242 | 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | 248 | #endif 249 | 250 | 251 | -------------------------------------------------------------------------------- /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/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(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/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 | iring_t scache; 127 | char *sbuf; 128 | 129 | IUINT32 rcv_nxt, rcv_wnd, last_recv, rlen; 130 | ilist_head rlist; 131 | iring_t 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 | 17 | /*-------------------------------------------------------------------*/ 18 | /* C99 Compatible */ 19 | /*-------------------------------------------------------------------*/ 20 | #if defined(linux) || defined(__linux) || defined(__linux__) 21 | #ifdef _POSIX_C_SOURCE 22 | #if _POSIX_C_SOURCE < 200112L 23 | #undef _POSIX_C_SOURCE 24 | #endif 25 | #endif 26 | 27 | #ifndef _POSIX_C_SOURCE 28 | #define _POSIX_C_SOURCE 200112L 29 | #endif 30 | 31 | #ifdef _GNU_SOURCE 32 | #undef _GNU_SOURCE 33 | #endif 34 | 35 | #ifdef _BSD_SOURCE 36 | #undef _BSD_SOURCE 37 | #endif 38 | 39 | #ifdef __BSD_VISIBLE 40 | #undef __BSD_VISIBLE 41 | #endif 42 | 43 | #ifdef _XOPEN_SOURCE 44 | #undef _XOPEN_SOURCE 45 | #endif 46 | 47 | #define _GNU_SOURCE 1 48 | #define _BSD_SOURCE 1 49 | #define __BSD_VISIBLE 1 50 | #define _XOPEN_SOURCE 600 51 | #endif 52 | 53 | 54 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 55 | //--------------------------------------------------------------------- 56 | // Global Definition 57 | //--------------------------------------------------------------------- 58 | #ifndef __INTEGER_32_BITS__ 59 | #define __INTEGER_32_BITS__ 60 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 61 | typedef __UINT32_TYPE__ ISTDUINT32; 62 | typedef __INT32_TYPE__ ISTDINT32; 63 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 64 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 65 | typedef __INT_FAST32_TYPE__ ISTDINT32; 66 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 67 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 68 | defined(_M_AMD64) 69 | typedef unsigned int ISTDUINT32; 70 | typedef int ISTDINT32; 71 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 72 | defined(__i386) || defined(_M_X86) 73 | typedef unsigned long ISTDUINT32; 74 | typedef long ISTDINT32; 75 | #elif defined(__MACOS__) 76 | typedef UInt32 ISTDUINT32; 77 | typedef SInt32 ISTDINT32; 78 | #elif defined(__APPLE__) && defined(__MACH__) 79 | #include 80 | typedef u_int32_t ISTDUINT32; 81 | typedef int32_t ISTDINT32; 82 | #elif defined(__BEOS__) 83 | #include 84 | typedef u_int32_t ISTDUINT32; 85 | typedef int32_t ISTDINT32; 86 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 87 | typedef unsigned __int32 ISTDUINT32; 88 | typedef __int32 ISTDINT32; 89 | #elif defined(__GNUC__) && (__GNUC__ > 3) 90 | #include 91 | typedef uint32_t ISTDUINT32; 92 | typedef int32_t ISTDINT32; 93 | #else 94 | typedef unsigned long ISTDUINT32; 95 | typedef long ISTDINT32; 96 | #endif 97 | #endif 98 | 99 | 100 | #if (defined(__APPLE__) && defined(__MACH__)) || defined(__MACOS__) 101 | #ifndef __unix 102 | #define __unix 1 103 | #endif 104 | #endif 105 | 106 | #if defined(__unix__) || defined(unix) || defined(__linux) 107 | #ifndef __unix 108 | #define __unix 1 109 | #endif 110 | #endif 111 | 112 | #include 113 | #ifdef __unix 114 | #include 115 | #define IPATHSEP '/' 116 | #else 117 | #include 118 | #if defined(_WIN32) 119 | #define IPATHSEP '\\' 120 | #else 121 | #define IPATHSEP '/' 122 | #endif 123 | #endif 124 | 125 | 126 | #ifndef __IINT8_DEFINED 127 | #define __IINT8_DEFINED 128 | typedef char IINT8; 129 | #endif 130 | 131 | #ifndef __IUINT8_DEFINED 132 | #define __IUINT8_DEFINED 133 | typedef unsigned char IUINT8; 134 | #endif 135 | 136 | #ifndef __IUINT16_DEFINED 137 | #define __IUINT16_DEFINED 138 | typedef unsigned short IUINT16; 139 | #endif 140 | 141 | #ifndef __IINT16_DEFINED 142 | #define __IINT16_DEFINED 143 | typedef short IINT16; 144 | #endif 145 | 146 | #ifndef __IINT32_DEFINED 147 | #define __IINT32_DEFINED 148 | typedef ISTDINT32 IINT32; 149 | #endif 150 | 151 | #ifndef __IUINT32_DEFINED 152 | #define __IUINT32_DEFINED 153 | typedef ISTDUINT32 IUINT32; 154 | #endif 155 | 156 | #ifndef __IINT64_DEFINED 157 | #define __IINT64_DEFINED 158 | #if defined(_MSC_VER) || defined(__BORLANDC__) 159 | typedef __int64 IINT64; 160 | #else 161 | typedef long long IINT64; 162 | #endif 163 | #endif 164 | 165 | #ifndef __IUINT64_DEFINED 166 | #define __IUINT64_DEFINED 167 | #if defined(_MSC_VER) || defined(__BORLANDC__) 168 | typedef unsigned __int64 IUINT64; 169 | #else 170 | typedef unsigned long long IUINT64; 171 | #endif 172 | #endif 173 | 174 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 175 | #ifndef _WIN32 176 | #define _WIN32 177 | #endif 178 | #endif 179 | 180 | 181 | #ifdef __cplusplus 182 | extern "C" { 183 | #endif 184 | 185 | //--------------------------------------------------------------------- 186 | // Posix Stat 187 | //--------------------------------------------------------------------- 188 | #define ISTAT_IFMT 0170000 // file type mask 189 | #define ISTAT_IFIFO 0010000 // named pipe (fifo) 190 | #define ISTAT_IFCHR 0020000 // charactor special 191 | #define ISTAT_IFDIR 0040000 // directory 192 | #define ISTAT_IFBLK 0060000 // block special 193 | #define ISTAT_IFREG 0100000 // regular 194 | #define ISTAT_IFLNK 0120000 // symbolic link 195 | #define ISTAT_IFSOCK 0140000 // socket 196 | #define ISTAT_IFWHT 0160000 // whiteout 197 | #define ISTAT_ISUID 0004000 // set user id on execution 198 | #define ISTAT_ISGID 0002000 // set group id on execution 199 | #define ISTAT_ISVXT 0001000 // swapped text even after use 200 | #define ISTAT_IRWXU 0000700 // owner RWX mask 201 | #define ISTAT_IRUSR 0000400 // owner read permission 202 | #define ISTAT_IWUSR 0000200 // owner writer permission 203 | #define ISTAT_IXUSR 0000100 // owner execution permission 204 | #define ISTAT_IRWXG 0000070 // group RWX mask 205 | #define ISTAT_IRGRP 0000040 // group read permission 206 | #define ISTAT_IWGRP 0000020 // group write permission 207 | #define ISTAT_IXGRP 0000010 // group execution permission 208 | #define ISTAT_IRWXO 0000007 // other RWX mask 209 | #define ISTAT_IROTH 0000004 // other read permission 210 | #define ISTAT_IWOTH 0000002 // other writer permission 211 | #define ISTAT_IXOTH 0000001 // other execution permission 212 | 213 | #define ISTAT_ISFMT(m, t) (((m) & ISTAT_IFMT) == (t)) 214 | #define ISTAT_ISDIR(m) ISTAT_ISFMT(m, ISTAT_IFDIR) 215 | #define ISTAT_ISCHR(m) ISTAT_ISFMT(m, ISTAT_IFCHR) 216 | #define ISTAT_ISBLK(m) ISTAT_ISFMT(m, ISTAT_IFBLK) 217 | #define ISTAT_ISREG(m) ISTAT_ISFMT(m, ISTAT_IFREG) 218 | #define ISTAT_ISFIFO(m) ISTAT_ISFMT(m, ISTAT_IFIFO) 219 | #define ISTAT_ISLNK(m) ISTAT_ISFMT(m, ISTAT_IFLNK) 220 | #define ISTAT_ISSOCK(m) ISTAT_ISFMT(m, ISTAT_IFSOCK) 221 | #define ISTAT_ISWHT(m) ISTAT_ISFMT(m, ISTAT_IFWHT) 222 | 223 | struct IPOSIX_STAT 224 | { 225 | IUINT32 st_mode; 226 | IUINT64 st_ino; 227 | IUINT32 st_dev; 228 | IUINT32 st_nlink; 229 | IUINT32 st_uid; 230 | IUINT32 st_gid; 231 | IUINT64 st_size; 232 | IUINT32 atime; 233 | IUINT32 mtime; 234 | IUINT32 ctime; 235 | IUINT32 st_blocks; 236 | IUINT32 st_blksize; 237 | IUINT32 st_rdev; 238 | IUINT32 st_flags; 239 | }; 240 | 241 | typedef struct IPOSIX_STAT iposix_stat_t; 242 | 243 | #define IPOSIX_MAXPATH 1024 244 | #define IPOSIX_MAXBUFF ((IPOSIX_MAXPATH) + 8) 245 | 246 | 247 | // returns 0 for success, -1 for error 248 | int iposix_stat(const char *path, iposix_stat_t *ostat); 249 | 250 | // returns 0 for success, -1 for error 251 | int iposix_lstat(const char *path, iposix_stat_t *ostat); 252 | 253 | // returns 0 for success, -1 for error 254 | int iposix_fstat(int fd, iposix_stat_t *ostat); 255 | 256 | // get current directory 257 | char *iposix_getcwd(char *path, int size); 258 | 259 | // create directory 260 | int iposix_mkdir(const char *path, int mode); 261 | 262 | // change directory 263 | int iposix_chdir(const char *path); 264 | 265 | #ifndef F_OK 266 | #define F_OK 0 267 | #endif 268 | 269 | #ifndef X_OK 270 | #define X_OK 1 271 | #endif 272 | 273 | #ifndef W_OK 274 | #define W_OK 2 275 | #endif 276 | 277 | #ifndef R_OK 278 | #define R_OK 4 279 | #endif 280 | 281 | // check access 282 | int iposix_access(const char *path, int mode); 283 | 284 | 285 | // returns 1 for true 0 for false, -1 for not exist 286 | int iposix_path_isdir(const char *path); 287 | 288 | // returns 1 for true 0 for false, -1 for not exist 289 | int iposix_path_isfile(const char *path); 290 | 291 | // returns 1 for true 0 for false, -1 for not exist 292 | int iposix_path_islink(const char *path); 293 | 294 | // returns 1 for true 0 for false 295 | int iposix_path_exists(const char *path); 296 | 297 | // returns file size, -1 for error 298 | IINT64 iposix_path_getsize(const char *path); 299 | 300 | 301 | //--------------------------------------------------------------------- 302 | // Posix Path 303 | //--------------------------------------------------------------------- 304 | 305 | // 是否是绝对路径,如果是的话返回1,否则返回0 306 | int iposix_path_isabs(const char *path); 307 | 308 | // 绝对路径 309 | char *iposix_path_abspath(const char *srcpath, char *path, int maxsize); 310 | 311 | // 归一化路径:去掉重复斜杠,以及处理掉".", ".."等。 312 | char *iposix_path_normal(const char *srcpath, char *path, int maxsize); 313 | 314 | // 连接路径 315 | char *iposix_path_join(const char *p1, const char *p2, char *path, int len); 316 | 317 | // 路径分割:从右向左找到第一个"/"分成两个字符串 318 | int iposix_path_split(const char *path, char *p1, int l1, char *p2, int l2); 319 | 320 | // 扩展分割:分割文件主名与扩展名 321 | int iposix_path_splitext(const char *path, char *p1, int l1, 322 | char *p2, int l2); 323 | 324 | 325 | //--------------------------------------------------------------------- 326 | // platform special 327 | //--------------------------------------------------------------------- 328 | 329 | // 取得进程可执行文件的文件名 330 | int iposix_path_exepath(char *ptr, int size); 331 | 332 | // 取得进程可执行文件的目录 333 | int iposix_path_execwd(char *ptr, int size); 334 | 335 | // 递归创建路径 336 | int iposix_path_mkdir(const char *path, int mode); 337 | 338 | // 精简版取得可执行路径 339 | const char *iposix_get_exepath(void); 340 | 341 | // 精简版取得可执行目录 342 | const char *iposix_get_execwd(void); 343 | 344 | 345 | // 文件路径格式化: 346 | // out - 输出路径,长度不小于 IPOSIX_MAXPATH 347 | // root - 根路径 348 | // ... - 后续的相对路径 349 | // 返回 - out 350 | // 假设可执行路径位于 /home/abc/work,那么: 351 | // iposix_path_format(out, iposix_get_execwd(), "images/%s", "abc.jpg") 352 | // 结果就是 /home/abc/work/images/abc.jpg 353 | char *iposix_path_format(char *out, const char *root, const char *fmt, ...); 354 | 355 | 356 | 357 | //--------------------------------------------------------------------- 358 | // System Utilities 359 | //--------------------------------------------------------------------- 360 | 361 | #ifndef IDISABLE_SHARED_LIBRARY 362 | 363 | /* LoadLibraryA */ 364 | void *iposix_shared_open(const char *dllname); 365 | 366 | /* GetProcAddress */ 367 | void *iposix_shared_get(void *shared, const char *name); 368 | 369 | /* FreeLibrary */ 370 | void iposix_shared_close(void *shared); 371 | 372 | #endif 373 | 374 | #ifndef IDISABLE_FILE_SYSTEM_ACCESS 375 | 376 | /* load file content, use free to dispose */ 377 | void *iposix_file_load_content(const char *filename, long *size); 378 | 379 | /* save file content */ 380 | int iposix_file_save_content(const char *filename, const void *data, long size); 381 | 382 | /* cross os GetModuleFileName, returns size for success, -1 for error */ 383 | int iposix_get_proc_pathname(char *ptr, int size); 384 | 385 | #endif 386 | 387 | 388 | 389 | #ifdef __cplusplus 390 | } 391 | #endif 392 | 393 | 394 | #endif 395 | 396 | 397 | #endif 398 | 399 | 400 | 401 | 402 | -------------------------------------------------------------------------------- /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_Final(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_Crypto(const void *key, int keylen, const void *in, 257 | void *out, size_t size, int ntimes); 258 | 259 | 260 | 261 | //===================================================================== 262 | // CRYPTO XTEA: https://en.wikipedia.org/wiki/XTEA 263 | //===================================================================== 264 | 265 | void CRYPTO_XTEA_Encipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 266 | 267 | void CRYPTO_XTEA_Decipher(int nrounds, const IUINT32 key[4], IUINT32 v[2]); 268 | 269 | 270 | //===================================================================== 271 | // LCG: https://en.wikipedia.org/wiki/Linear_congruential_generator 272 | //===================================================================== 273 | 274 | // rand() in stdlib.h (c99), output range: 0 <= x <= 32767 275 | IUINT32 random_std_c99(IUINT32 *seed); 276 | 277 | // rand() in stdlib.h (msvc), output range: 0 <= x <= 32767 278 | IUINT32 random_std_msvc(IUINT32 *seed); 279 | 280 | // minstd_rand in C++, output range: 0 <= x < 0x7fffffff 281 | IUINT32 random_std_cpp(IUINT32 *seed); 282 | 283 | 284 | //===================================================================== 285 | // Statistically perfect random generator 286 | //===================================================================== 287 | typedef struct 288 | { 289 | IUINT32 seed; // random seed 290 | IUINT32 size; // array size 291 | IUINT32 avail; // available numbers 292 | IUINT32 *state; // states array 293 | } RANDOM_BOX; 294 | 295 | 296 | // initialize random box 297 | void RANDOM_BOX_Init(RANDOM_BOX *box, IUINT32 *state, IUINT32 size); 298 | 299 | // change seed 300 | void RANDOM_BOX_Seed(RANDOM_BOX *box, IUINT32 seed); 301 | 302 | // next random number within 0 <= x < size 303 | IUINT32 RANDOM_BOX_Next(RANDOM_BOX *box); 304 | 305 | 306 | //===================================================================== 307 | // PCG: PCG is a family of simple fast statistically good algorithms 308 | //===================================================================== 309 | typedef struct 310 | { 311 | IUINT64 state; // RNG state. All values are possible. 312 | IUINT64 inc; // Must *always* be odd. 313 | } RANDOM_PCG; 314 | 315 | // initialize pcg 316 | void RANDOM_PCG_Init(RANDOM_PCG *pcg, IUINT64 initstate, IUINT64 initseq); 317 | 318 | // next random number 319 | IUINT32 RANDOM_PCG_Next(RANDOM_PCG *pcg); 320 | 321 | // next random number within 0 <= x < bound 322 | IUINT32 RANDOM_PCG_RANGE(RANDOM_PCG *pcg, IUINT32 bound); 323 | 324 | 325 | #ifdef __cplusplus 326 | } 327 | #endif 328 | 329 | #endif 330 | 331 | 332 | -------------------------------------------------------------------------------- /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 = expires - core->timer_jiffies; 180 | ilist_head *vec = NULL; 181 | 182 | if (idx < ITVR_SIZE) { 183 | int i = expires & ITVR_MASK; 184 | vec = core->tv1.vec + i; 185 | } 186 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS))) { 187 | int i = (expires >> ITVR_BITS) & ITVN_MASK; 188 | vec = core->tv2.vec + i; 189 | } 190 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 2))) { 191 | int i = (expires >> (ITVR_BITS + ITVN_BITS)) & ITVN_MASK; 192 | vec = core->tv3.vec + i; 193 | } 194 | else if (idx < (1 << (ITVR_BITS + ITVN_BITS * 3))) { 195 | int i = (expires >> (ITVR_BITS + ITVN_BITS * 2)) & ITVN_MASK; 196 | vec = core->tv4.vec + i; 197 | } 198 | else if ((IINT32)idx < 0) { 199 | vec = core->tv1.vec + (core->timer_jiffies & ITVR_MASK); 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 | //===================================================================== 275 | // Timer Manager 276 | //===================================================================== 277 | 278 | // initialize timer manager 279 | // interval - internal working interval 280 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval) 281 | { 282 | mgr->current = 0; 283 | mgr->interval = (interval < 1)? 1 : interval; 284 | mgr->jiffies = 0; 285 | mgr->millisec = 0; 286 | mgr->initialized = 0; 287 | itimer_core_init(&mgr->core, mgr->jiffies); 288 | } 289 | 290 | // destroy timer manager 291 | void itimer_mgr_destroy(itimer_mgr *mgr) 292 | { 293 | itimer_core_destroy(&mgr->core); 294 | } 295 | 296 | #ifndef ITIMER_MGR_LIMIT 297 | #define ITIMER_MGR_LIMIT 60000 // 60 seconds 298 | #endif 299 | 300 | // run timer events 301 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec) 302 | { 303 | IUINT32 interval = mgr->interval; 304 | IINT32 limit = ITIMER_MGR_LIMIT + (IINT32)interval * 64; 305 | // first time to be called 306 | if (mgr->initialized == 0) { 307 | mgr->millisec = millisec; 308 | mgr->initialized = 1; 309 | } 310 | else { 311 | IINT32 diff = (IINT32)(millisec - mgr->millisec); 312 | // recover from long-time sleep 313 | if (diff > limit || diff < -limit) { 314 | mgr->millisec = millisec; 315 | } 316 | } 317 | // update core timer 318 | while ((IINT32)(millisec - mgr->millisec) >= 0) { 319 | itimer_core_run(&mgr->core, mgr->jiffies); 320 | mgr->jiffies++; 321 | mgr->current += mgr->interval; 322 | mgr->millisec += mgr->interval; 323 | } 324 | } 325 | 326 | // callback 327 | static void itimer_evt_cb(void *p) 328 | { 329 | itimer_evt *evt = (itimer_evt*)p; 330 | itimer_mgr *mgr = evt->mgr; 331 | IUINT32 current = mgr->current; 332 | int fire = 0; 333 | int stop = 0; 334 | 335 | // time compensation, comparision takes care of uint32 overflow 336 | while (((IINT32)(current - evt->slap)) >= 0) { 337 | evt->slap += evt->period; 338 | fire = 1; 339 | } 340 | 341 | // need invoke callback ? 342 | if (fire) { 343 | if (evt->repeat == 0) { 344 | fire = 0; 345 | stop = 1; 346 | } 347 | else if (evt->repeat > 0) { 348 | evt->repeat--; 349 | if (evt->repeat == 0) { 350 | stop = 1; 351 | } 352 | } 353 | } 354 | 355 | // reschedule or stop ? 356 | if (stop == 0) { 357 | IUINT32 interval = mgr->interval; 358 | IUINT32 expires = (evt->slap - current + interval - 1) / interval; 359 | if (expires >= 0x70000000) expires = 0x70000000; 360 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 361 | } else { 362 | itimer_evt_stop(mgr, evt); 363 | } 364 | 365 | // need invoke callback ? 366 | if (fire) { 367 | if (evt->callback) { 368 | evt->callback(evt->data, evt->user); 369 | } 370 | } 371 | } 372 | 373 | // initialize timer event 374 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 375 | void *data, void *user) 376 | { 377 | itimer_node_init(&evt->node, itimer_evt_cb, evt); 378 | evt->callback = fn; 379 | evt->data = data; 380 | evt->user = user; 381 | evt->mgr = NULL; 382 | evt->period = 0; 383 | evt->slap = 0; 384 | evt->repeat = 0; 385 | evt->running = 0; 386 | } 387 | 388 | // destroy timer event 389 | void itimer_evt_destroy(itimer_evt *evt) 390 | { 391 | itimer_node_destroy(&evt->node); 392 | evt->callback = NULL; 393 | evt->data = NULL; 394 | evt->user = NULL; 395 | evt->mgr = NULL; 396 | evt->period = 0; 397 | evt->slap = 0; 398 | evt->repeat = 0; 399 | evt->running = 0; 400 | } 401 | 402 | // start timer: repeat <= 0 (infinite repeat) 403 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 404 | IUINT32 period, int repeat) 405 | { 406 | IUINT32 interval = mgr->interval; 407 | IUINT32 expires; 408 | if (evt->mgr) { 409 | itimer_evt_stop(evt->mgr, evt); 410 | } 411 | evt->period = (period < 1)? 1 : period; 412 | evt->repeat = (repeat <= 0)? -1 : repeat; 413 | evt->slap = mgr->current + period; 414 | evt->mgr = mgr; 415 | expires = (evt->slap - mgr->current + interval - 1) / interval; 416 | if (expires >= 0x70000000) expires = 0x70000000; 417 | itimer_node_add(&mgr->core, &evt->node, mgr->jiffies + expires); 418 | evt->running = 0; 419 | } 420 | 421 | // stop timer 422 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt) 423 | { 424 | if (evt->mgr) { 425 | itimer_node_del(&evt->mgr->core, &evt->node); 426 | evt->mgr = NULL; 427 | } 428 | evt->running = 0; 429 | } 430 | 431 | // returns 0 for stopped and 1 for running 432 | int itimer_evt_status(const itimer_evt *evt) 433 | { 434 | return (evt->mgr == NULL)? 0 : 1; 435 | } 436 | 437 | 438 | 439 | -------------------------------------------------------------------------------- /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 | #include 13 | 14 | 15 | //===================================================================== 16 | // 32BIT INTEGER DEFINITION 17 | //===================================================================== 18 | #ifndef __INTEGER_32_BITS__ 19 | #define __INTEGER_32_BITS__ 20 | #if defined(__UINT32_TYPE__) && defined(__UINT32_TYPE__) 21 | typedef __UINT32_TYPE__ ISTDUINT32; 22 | typedef __INT32_TYPE__ ISTDINT32; 23 | #elif defined(__UINT_FAST32_TYPE__) && defined(__INT_FAST32_TYPE__) 24 | typedef __UINT_FAST32_TYPE__ ISTDUINT32; 25 | typedef __INT_FAST32_TYPE__ ISTDINT32; 26 | #elif defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 27 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 28 | defined(_M_AMD64) 29 | typedef unsigned int ISTDUINT32; 30 | typedef int ISTDINT32; 31 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 32 | defined(__i386) || defined(_M_X86) 33 | typedef unsigned long ISTDUINT32; 34 | typedef long ISTDINT32; 35 | #elif defined(__MACOS__) 36 | typedef UInt32 ISTDUINT32; 37 | typedef SInt32 ISTDINT32; 38 | #elif defined(__APPLE__) && defined(__MACH__) 39 | #include 40 | typedef u_int32_t ISTDUINT32; 41 | typedef int32_t ISTDINT32; 42 | #elif defined(__BEOS__) 43 | #include 44 | typedef u_int32_t ISTDUINT32; 45 | typedef int32_t ISTDINT32; 46 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 47 | typedef unsigned __int32 ISTDUINT32; 48 | typedef __int32 ISTDINT32; 49 | #elif defined(__GNUC__) && (__GNUC__ > 3) 50 | #include 51 | typedef uint32_t ISTDUINT32; 52 | typedef int32_t ISTDINT32; 53 | #else 54 | typedef unsigned long ISTDUINT32; 55 | typedef long ISTDINT32; 56 | #endif 57 | #endif 58 | 59 | 60 | //===================================================================== 61 | // Integer Definition 62 | //===================================================================== 63 | #ifndef __IINT8_DEFINED 64 | #define __IINT8_DEFINED 65 | typedef char IINT8; 66 | #endif 67 | 68 | #ifndef __IUINT8_DEFINED 69 | #define __IUINT8_DEFINED 70 | typedef unsigned char IUINT8; 71 | #endif 72 | 73 | #ifndef __IUINT16_DEFINED 74 | #define __IUINT16_DEFINED 75 | typedef unsigned short IUINT16; 76 | #endif 77 | 78 | #ifndef __IINT16_DEFINED 79 | #define __IINT16_DEFINED 80 | typedef short IINT16; 81 | #endif 82 | 83 | #ifndef __IINT32_DEFINED 84 | #define __IINT32_DEFINED 85 | typedef ISTDINT32 IINT32; 86 | #endif 87 | 88 | #ifndef __IUINT32_DEFINED 89 | #define __IUINT32_DEFINED 90 | typedef ISTDUINT32 IUINT32; 91 | #endif 92 | 93 | 94 | /*====================================================================*/ 95 | /* LIST DEFINITION */ 96 | /*====================================================================*/ 97 | #ifndef __ILIST_DEF__ 98 | #define __ILIST_DEF__ 99 | 100 | struct ILISTHEAD { 101 | struct ILISTHEAD *next, *prev; 102 | }; 103 | 104 | typedef struct ILISTHEAD ilist_head; 105 | 106 | 107 | /*--------------------------------------------------------------------*/ 108 | /* list init */ 109 | /*--------------------------------------------------------------------*/ 110 | #define ILIST_HEAD_INIT(name) { &(name), &(name) } 111 | #define ILIST_HEAD(name) \ 112 | struct ILISTHEAD name = ILIST_HEAD_INIT(name) 113 | 114 | #define ILIST_INIT(ptr) ( \ 115 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 116 | 117 | #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 118 | 119 | #define ICONTAINEROF(ptr, type, member) ( \ 120 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 121 | 122 | #define ILIST_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 123 | 124 | 125 | /*--------------------------------------------------------------------*/ 126 | /* list operation */ 127 | /*--------------------------------------------------------------------*/ 128 | #define ILIST_ADD(node, head) ( \ 129 | (node)->prev = (head), (node)->next = (head)->next, \ 130 | (head)->next->prev = (node), (head)->next = (node)) 131 | 132 | #define ILIST_ADD_TAIL(node, head) ( \ 133 | (node)->prev = (head)->prev, (node)->next = (head), \ 134 | (head)->prev->next = (node), (head)->prev = (node)) 135 | 136 | #define ILIST_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 137 | 138 | #define ILIST_DEL(entry) (\ 139 | (entry)->next->prev = (entry)->prev, \ 140 | (entry)->prev->next = (entry)->next, \ 141 | (entry)->next = 0, (entry)->prev = 0) 142 | 143 | #define ILIST_DEL_INIT(entry) do { \ 144 | ILIST_DEL(entry); ILIST_INIT(entry); } while (0) 145 | 146 | #define ILIST_IS_EMPTY(entry) ((entry) == (entry)->next) 147 | 148 | #define ilist_init ILIST_INIT 149 | #define ilist_entry ILIST_ENTRY 150 | #define ilist_add ILIST_ADD 151 | #define ilist_add_tail ILIST_ADD_TAIL 152 | #define ilist_del ILIST_DEL 153 | #define ilist_del_init ILIST_DEL_INIT 154 | #define ilist_is_empty ILIST_IS_EMPTY 155 | 156 | #define ILIST_FOREACH(iterator, head, TYPE, MEMBER) \ 157 | for ((iterator) = ilist_entry((head)->next, TYPE, MEMBER); \ 158 | &((iterator)->MEMBER) != (head); \ 159 | (iterator) = ilist_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 160 | 161 | #define ilist_foreach(iterator, head, TYPE, MEMBER) \ 162 | ILIST_FOREACH(iterator, head, TYPE, MEMBER) 163 | 164 | #define ilist_foreach_entry(pos, head) \ 165 | for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) 166 | 167 | 168 | #define __ilist_splice(list, head) do { \ 169 | ilist_head *first = (list)->next, *last = (list)->prev; \ 170 | ilist_head *at = (head)->next; \ 171 | (first)->prev = (head), (head)->next = (first); \ 172 | (last)->next = (at), (at)->prev = (last); } while (0) 173 | 174 | #define ilist_splice(list, head) do { \ 175 | if (!ilist_is_empty(list)) __ilist_splice(list, head); } while (0) 176 | 177 | #define ilist_splice_init(list, head) do { \ 178 | ilist_splice(list, head); ilist_init(list); } while (0) 179 | 180 | 181 | #ifdef _MSC_VER 182 | #pragma warning(disable:4311) 183 | #pragma warning(disable:4312) 184 | #pragma warning(disable:4996) 185 | #endif 186 | 187 | #endif 188 | 189 | 190 | //===================================================================== 191 | // Timer Vector 192 | //===================================================================== 193 | #define ITVN_BITS 6 194 | #define ITVR_BITS 8 195 | #define ITVN_SIZE (1 << ITVN_BITS) 196 | #define ITVR_SIZE (1 << ITVR_BITS) 197 | #define ITVN_MASK (ITVN_SIZE - 1) 198 | #define ITVR_MASK (ITVR_SIZE - 1) 199 | 200 | struct itimer_vec { 201 | ilist_head vec[ITVN_SIZE]; 202 | }; 203 | 204 | struct itimer_vec_root { 205 | ilist_head vec[ITVR_SIZE]; 206 | }; 207 | 208 | struct itimer_core { 209 | IUINT32 timer_jiffies; 210 | struct itimer_vec *tvecs[6]; 211 | struct itimer_vec_root tv1; 212 | struct itimer_vec tv2; 213 | struct itimer_vec tv3; 214 | struct itimer_vec tv4; 215 | struct itimer_vec tv5; 216 | }; 217 | 218 | struct itimer_node { 219 | ilist_head head; 220 | IUINT32 expires; 221 | IUINT32 state; 222 | void *data; 223 | void (*callback)(void *data); 224 | struct itimer_core *core; 225 | }; 226 | 227 | 228 | //===================================================================== 229 | // global definition 230 | //===================================================================== 231 | typedef struct itimer_core itimer_core; 232 | typedef struct itimer_node itimer_node; 233 | 234 | #define itimer_core_jiffies(core) ((core)->jiffies) 235 | #define itimer_node_pending(node) (!iqueue_is_empty(&(node)->head)) 236 | 237 | 238 | #ifdef __cplusplus 239 | extern "C" { 240 | #endif 241 | 242 | //===================================================================== 243 | // Core Timer 244 | //===================================================================== 245 | 246 | // initialize timer core 247 | void itimer_core_init(itimer_core *core, IUINT32 jiffies); 248 | 249 | // destroy timer core 250 | void itimer_core_destroy(itimer_core *core); 251 | 252 | // run timer core 253 | void itimer_core_run(itimer_core *core, IUINT32 jiffies); 254 | 255 | 256 | // initialize node 257 | void itimer_node_init(itimer_node *node, void (*fn)(void*), void *data); 258 | 259 | // destroy node 260 | void itimer_node_destroy(itimer_node *node); 261 | 262 | // add node to core 263 | void itimer_node_add(itimer_core *core, itimer_node *node, IUINT32 expires); 264 | 265 | // remove node from core 266 | int itimer_node_del(itimer_core *core, itimer_node *node); 267 | 268 | // modify node 269 | int itimer_node_mod(itimer_core *core, itimer_node *node, IUINT32 expires); 270 | 271 | 272 | 273 | //===================================================================== 274 | // Timer Manager 275 | //===================================================================== 276 | struct itimer_mgr 277 | { 278 | IUINT32 interval; 279 | IUINT32 current; 280 | IUINT32 millisec; 281 | IUINT32 jiffies; 282 | int initialized; 283 | itimer_core core; 284 | }; 285 | 286 | struct itimer_evt 287 | { 288 | IUINT32 period; 289 | IUINT32 slap; 290 | int repeat; 291 | int running; 292 | void (*callback)(void *data, void *user); 293 | void *data; 294 | void *user; 295 | struct itimer_mgr *mgr; 296 | itimer_node node; 297 | }; 298 | 299 | // type defines 300 | typedef struct itimer_mgr itimer_mgr; 301 | typedef struct itimer_evt itimer_evt; 302 | 303 | // initialize timer manager 304 | // interval - internal working interval 305 | void itimer_mgr_init(itimer_mgr *mgr, IUINT32 interval); 306 | 307 | // destroy timer manager 308 | void itimer_mgr_destroy(itimer_mgr *mgr); 309 | 310 | // run timer events: 311 | // millisec - current time stamp 312 | void itimer_mgr_run(itimer_mgr *mgr, IUINT32 millisec); 313 | 314 | 315 | // initialize timer event 316 | void itimer_evt_init(itimer_evt *evt, void (*fn)(void *data, void *user), 317 | void *data, void *user); 318 | 319 | // destroy timer event 320 | void itimer_evt_destroy(itimer_evt *evt); 321 | 322 | // start timer: repeat <= 0 (infinite repeat) 323 | void itimer_evt_start(itimer_mgr *mgr, itimer_evt *evt, 324 | IUINT32 period, int repeat); 325 | 326 | // stop timer 327 | void itimer_evt_stop(itimer_mgr *mgr, itimer_evt *evt); 328 | 329 | // returns 0 for stopped and 1 for running 330 | int itimer_evt_status(const itimer_evt *evt); 331 | 332 | 333 | #ifdef __cplusplus 334 | } 335 | #endif 336 | 337 | #endif 338 | 339 | 340 | -------------------------------------------------------------------------------- /system/itoolbox.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // itoolbox.h - 工具函数大集合 4 | // 5 | // NOTE: 6 | // for more information, please see the readme file. 7 | // 8 | //===================================================================== 9 | 10 | #ifndef __ITOOLBOX_H__ 11 | #define __ITOOLBOX_H__ 12 | 13 | #include "imemdata.h" 14 | #include "inetcode.h" 15 | #include "iposix.h" 16 | 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | //===================================================================== 23 | // 控制台工具集 24 | //===================================================================== 25 | 26 | // 前景颜色定义 27 | #define CTEXT_BLACK 0 28 | #define CTEXT_RED 1 29 | #define CTEXT_GREEN 2 30 | #define CTEXT_YELLOW 3 31 | #define CTEXT_BLUE 4 32 | #define CTEXT_MAGENTA 5 33 | #define CTEXT_CYAN 6 34 | #define CTEXT_WHITE 7 35 | #define CTEXT_BOLD 8 36 | #define CTEXT_BOLD_RED 9 37 | #define CTEXT_BOLD_GREEN 10 38 | #define CTEXT_BOLD_YELLO 11 39 | #define CTEXT_BOLD_BLUE 12 40 | #define CTEXT_BOLD_MAGENTA 13 41 | #define CTEXT_BOLD_CYAN 14 42 | #define CTEXT_BOLD_WHITE 15 43 | 44 | // 背景颜色定义 45 | #define CBG_BLACK 0 46 | #define CBG_RED (1 << 4) 47 | #define CBG_GREEN (2 << 4) 48 | #define CBG_YELLO (3 << 4) 49 | #define CBG_BLUE (4 << 4) 50 | #define CBG_MAGENTA (5 << 4) 51 | #define CBG_CYAN (6 << 4) 52 | #define CBG_WHITE (7 << 4) 53 | 54 | 55 | // 设置颜色:低4位是文字颜色,高4位是背景颜色 56 | // 具体编码可以搜索 ansi color或者 57 | // http://en.wikipedia.org/wiki/ANSI_escape_code 58 | void console_set_color(int color); 59 | 60 | 61 | // 设置光标位置左上角是,行与列都是从1开始计数的 62 | void console_cursor(int row, int col); 63 | 64 | // 恢复屏幕颜色 65 | void console_reset(void); 66 | 67 | // 清屏 68 | void console_clear(int color); 69 | 70 | 71 | 72 | //===================================================================== 73 | // CSV Reader/Writer 74 | //===================================================================== 75 | struct iCsvReader; 76 | struct iCsvWriter; 77 | 78 | typedef struct iCsvReader iCsvReader; 79 | typedef struct iCsvWriter iCsvWriter; 80 | 81 | 82 | // open csv reader from file 83 | iCsvReader *icsv_reader_open_file(const char *filename); 84 | 85 | // open csv reader from memory 86 | iCsvReader *icsv_reader_open_memory(const char *text, ilong size); 87 | 88 | // close csv reader 89 | void icsv_reader_close(iCsvReader *reader); 90 | 91 | // read csv row 92 | int icsv_reader_read(iCsvReader *reader); 93 | 94 | // get column count in current row 95 | int icsv_reader_size(const iCsvReader *reader); 96 | 97 | // returns 1 for end of file, 0 for not end. 98 | int icsv_reader_eof(const iCsvReader *reader); 99 | 100 | // get column string 101 | ivalue_t *icsv_reader_get(iCsvReader *reader, int pos); 102 | 103 | // get column string 104 | const ivalue_t *icsv_reader_get_const(const iCsvReader *reader, int pos); 105 | 106 | // return column string size, -1 for error 107 | int icsv_reader_get_size(const iCsvReader *reader, int pos); 108 | 109 | // return column string, returns string size for success, -1 for error 110 | int icsv_reader_get_string(const iCsvReader *reader, int pos, ivalue_t *out); 111 | 112 | // return column string, returns string size for success, -1 for error 113 | int icsv_reader_get_cstr(const iCsvReader *reader, int pos, 114 | char *out, int size); 115 | 116 | // utils for reader 117 | int icsv_reader_get_long(const iCsvReader *reader, int i, long *x); 118 | int icsv_reader_get_ulong(const iCsvReader *reader, int i, unsigned long *x); 119 | int icsv_reader_get_int(const iCsvReader *reader, int i, int *x); 120 | int icsv_reader_get_uint(const iCsvReader *reader, int i, unsigned int *x); 121 | int icsv_reader_get_int64(const iCsvReader *reader, int i, IINT64 *x); 122 | int icsv_reader_get_uint64(const iCsvReader *reader, int i, IUINT64 *x); 123 | int icsv_reader_get_float(const iCsvReader *reader, int i, float *x); 124 | int icsv_reader_get_double(const iCsvReader *reader, int i, double *x); 125 | 126 | 127 | // open csv writer from file: if filename is NULL, it will open in memory 128 | iCsvWriter *icsv_writer_open(const char *filename, int append); 129 | 130 | // close csv writer 131 | void icsv_writer_close(iCsvWriter *writer); 132 | 133 | // write row and reset 134 | int icsv_writer_write(iCsvWriter *writer); 135 | 136 | // return column count in current row 137 | int icsv_writer_size(iCsvWriter *writer); 138 | 139 | // clear columns in current row 140 | void icsv_writer_clear(iCsvWriter *writer); 141 | 142 | // dump output 143 | void icsv_writer_dump(iCsvWriter *writer, ivalue_t *out); 144 | 145 | // clear output 146 | void icsv_writer_empty(iCsvWriter *writer); 147 | 148 | // push string 149 | int icsv_writer_push(iCsvWriter *writer, const ivalue_t *str); 150 | 151 | // push c string 152 | int icsv_writer_push_cstr(iCsvWriter *writer, const char *ptr, int size); 153 | 154 | 155 | // utils for writer 156 | int icsv_writer_push_long(iCsvWriter *writer, long x, int radix); 157 | int icsv_writer_push_ulong(iCsvWriter *writer, unsigned long x, int radix); 158 | int icsv_writer_push_int(iCsvWriter *writer, int x, int radix); 159 | int icsv_writer_push_uint(iCsvWriter *writer, unsigned int x, int radix); 160 | int icsv_writer_push_int64(iCsvWriter *writer, IINT64 x, int radix); 161 | int icsv_writer_push_uint64(iCsvWriter *writer, IUINT64 x, int radix); 162 | int icsv_writer_push_float(iCsvWriter *writer, float x); 163 | int icsv_writer_push_double(iCsvWriter *writer, double x); 164 | 165 | 166 | //===================================================================== 167 | // 兼容接口实现 168 | //===================================================================== 169 | int inet_open_port(unsigned short port, unsigned long ip, int flag); 170 | int inet_tcp_estab(int fd); 171 | int inet_init(void); 172 | int inet_set_bufsize(int fd, long recvbuf, long sndbuf); 173 | int inet_updateaddr(int resolvename); 174 | int inet_sockpair(int fds[2]); 175 | 176 | 177 | //===================================================================== 178 | // Protocol Reader 179 | //===================================================================== 180 | struct CAsyncReader; 181 | typedef struct CAsyncReader CAsyncReader; 182 | 183 | CAsyncReader *async_reader_new(ib_memnode *fnode); 184 | 185 | void async_reader_delete(CAsyncReader *reader); 186 | 187 | 188 | #define ISTREAM_READ_BYTE 0 189 | #define ISTREAM_READ_LINE 1 190 | #define ISTREAM_READ_BLOCK 2 191 | 192 | void async_reader_mode(CAsyncReader *reader, int mode, ilong what); 193 | 194 | long async_reader_read(CAsyncReader *reader, void *data, long maxsize); 195 | 196 | void async_reader_feed(CAsyncReader *reader, const void *data, long len); 197 | 198 | 199 | 200 | //===================================================================== 201 | // Redis Reader 202 | //===================================================================== 203 | struct CRedisReader; 204 | typedef struct CRedisReader CRedisReader; 205 | 206 | CRedisReader *redis_reader_new(ib_memnode *fnode); 207 | 208 | void redis_reader_delete(CRedisReader *rr); 209 | 210 | 211 | long redis_reader_read(CRedisReader *rr, int *mode, void *data, long maxsize); 212 | 213 | void redis_reader_feed(CRedisReader *rr, const void *data, long len); 214 | 215 | 216 | 217 | #ifdef __cplusplus 218 | } 219 | #endif 220 | 221 | 222 | #endif 223 | 224 | 225 | --------------------------------------------------------------------------------