├── README.md ├── makefile ├── common.h ├── udpclient.h ├── udpsocket.h ├── udptask.h ├── udpserver.h ├── ikcp.h └── ikcp.c /README.md: -------------------------------------------------------------------------------- 1 | # 基于kcp的udp游戏网络库 2 | 3 | 4 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # This is makefile for kcpnet 2 | CC = /usr/bin/gcc 3 | CXX = /usr/bin/g++ 4 | AR = ar 5 | RANLIB = ranlib 6 | 7 | CCOBJS = ikcp.o 8 | CCFLAGS= 9 | 10 | CXXOBJS = 11 | CXXFLAGS= 12 | 13 | TARGET = libkcpnet.a 14 | 15 | all: $(TARGET) 16 | 17 | $(CCOBJS): %.o: %.c 18 | $(CC) -c $(CCFLAGS) $< -o $@ 19 | 20 | $(OBJS): %.o: %.cpp 21 | $(CXX) -c $(CXXFLAGS) $< -o $@ 22 | 23 | $(TARGET): $(CCOBJS) $(CXXOBJS) 24 | @rm -f $(TARGET) 25 | @$(AR) rc $(TARGET) $(CCOBJS) $(CXXOBJS) $(LDFLAGS) 26 | @$(RANLIB) $(TARGET) 27 | 28 | clean: 29 | rm -f *.o 30 | rm -f ${TARGET} 31 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include "ikcp.h" 5 | #include 6 | 7 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 8 | #include 9 | #elif !defined(__unix) 10 | #define __unix 11 | #endif 12 | 13 | #ifdef __unix 14 | #include 15 | #include 16 | #include 17 | #include 18 | #endif 19 | 20 | /* get system time */ 21 | static inline void itimeofday(long *sec, long *usec) 22 | { 23 | #if defined(__unix) 24 | struct timeval time; 25 | gettimeofday(&time, NULL); 26 | if (sec) *sec = time.tv_sec; 27 | if (usec) *usec = time.tv_usec; 28 | #else 29 | static long mode = 0, addsec = 0; 30 | BOOL retval; 31 | static IINT64 freq = 1; 32 | IINT64 qpc; 33 | if (mode == 0) { 34 | retval = QueryPerformanceFrequency((LARGE_INTEGER*)&freq); 35 | freq = (freq == 0) ? 1 : freq; 36 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 37 | addsec = (long)time(NULL); 38 | addsec = addsec - (long)((qpc / freq) & 0x7fffffff); 39 | mode = 1; 40 | } 41 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 42 | retval = retval * 2; 43 | if (sec) *sec = (long)(qpc / freq) + addsec; 44 | if (usec) *usec = (long)((qpc % freq) * 1000000 / freq); 45 | #endif 46 | } 47 | 48 | /* get clock in millisecond 64 */ 49 | static inline IINT64 iclock64(void) 50 | { 51 | long s, u; 52 | IINT64 value; 53 | itimeofday(&s, &u); 54 | value = ((IINT64)s) * 1000 + (u / 1000); 55 | return value; 56 | } 57 | 58 | static inline IUINT32 iclock() 59 | { 60 | return (IUINT32)(iclock64() & 0xfffffffful); 61 | } 62 | 63 | #endif -------------------------------------------------------------------------------- /udpclient.h: -------------------------------------------------------------------------------- 1 | #ifndef __UDPCLIENT_H__ 2 | #define __UDPCLIENT_H__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | #endif 7 | #include 8 | #include 9 | #include 10 | #include "udptask.h" 11 | 12 | template 13 | class udpclient 14 | { 15 | public: 16 | udpclient() :utask(NULL){} 17 | ~udpclient() 18 | { 19 | if (utask != NULL) 20 | { 21 | delete utask; 22 | } 23 | } 24 | bool connect(const char *addr, unsigned short int port, IUINT32 conv) 25 | { 26 | if (!udpsock.connect(addr, port)) 27 | { 28 | return false; 29 | } 30 | 31 | utask = new T; 32 | if (!utask->init(conv, &udpsock)) 33 | { 34 | return false; 35 | } 36 | 37 | isstop = false; 38 | 39 | _thread = std::thread(std::bind(&udpclient::run, this)); 40 | _threadtm = std::thread(std::bind(&udpclient::loop, this)); 41 | return true; 42 | } 43 | 44 | int send(const char *buf, int size) 45 | { 46 | _mutex.lock(); 47 | int ret = utask->send(buf, size); 48 | _mutex.unlock(); 49 | return ret; 50 | } 51 | 52 | void shutdown() 53 | { 54 | isstop = true; 55 | udpsock.shutdown(); 56 | _thread.join(); 57 | _threadtm.join(); 58 | } 59 | 60 | void loop() 61 | { 62 | for (; !isstop;) 63 | { 64 | _mutex.lock(); 65 | utask->timerloop(); 66 | _mutex.unlock(); 67 | std::chrono::milliseconds dura(1); 68 | std::this_thread::sleep_for(dura); 69 | } 70 | } 71 | 72 | void run() 73 | { 74 | char buff[65536] = { 0 }; 75 | struct sockaddr_in seraddr; 76 | for (; !isstop;) 77 | { 78 | socklen_t len = sizeof(struct sockaddr_in); 79 | int size = udpsock.recvfrom(buff, sizeof(buff), (struct sockaddr*)&seraddr, &len); 80 | if (size == 0) 81 | { 82 | continue; 83 | } 84 | if (size < 0) 85 | { 86 | printf("接收失败 %d,%d \n", udpsock.getsocket(), size); 87 | continue; 88 | } 89 | _mutex.lock(); 90 | utask->recv(buff, size); 91 | _mutex.unlock(); 92 | } 93 | } 94 | 95 | bool isalive() 96 | { 97 | _mutex.lock(); 98 | bool alive = utask->isalive(); 99 | _mutex.unlock(); 100 | return alive; 101 | } 102 | 103 | virtual int parsemsg(const char *buf, int len) 104 | { 105 | printf("收到数据 %s,%d\n", buf, len); 106 | return 0; 107 | } 108 | private: 109 | udpsocket udpsock; 110 | udptask* utask; 111 | std::thread _thread; 112 | std::thread _threadtm; 113 | std::mutex _mutex; 114 | volatile bool isstop; 115 | }; 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /udpsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef __UDPSOCKET_H__ 2 | #define __UDPSOCKET_H__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | #pragma comment(lib,"ws2_32.lib") 7 | #define close(x) closesocket(x) 8 | typedef int socklen_t; 9 | #else 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | typedef int SOCKET; 24 | #endif 25 | 26 | class udpsocket 27 | { 28 | public: 29 | udpsocket() 30 | { 31 | this->udpsock = 0; 32 | } 33 | udpsocket(SOCKET udpsock, struct sockaddr_in *paddr) 34 | { 35 | this->udpsock = udpsock; 36 | this->sockaddr = *paddr; 37 | } 38 | 39 | ~udpsocket() 40 | { 41 | 42 | } 43 | 44 | bool bind(const char *addr, unsigned int short port) 45 | { 46 | udpsock = socket(AF_INET, SOCK_DGRAM, 0); 47 | if (udpsock <= 0) 48 | { 49 | return false; 50 | } 51 | 52 | unsigned int yes = 1; 53 | setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); 54 | 55 | memset(&sockaddr, 0, sizeof(sockaddr)); 56 | sockaddr.sin_family = AF_INET; 57 | sockaddr.sin_addr.s_addr = inet_addr(addr); 58 | sockaddr.sin_port = htons(port); 59 | if (::bind(udpsock, (struct sockaddr*)&sockaddr, sizeof(struct sockaddr)) < 0) 60 | { 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | bool connect(const char *addr, unsigned short int port) 68 | { 69 | if (!this->bind("0.0.0.0", 0)) 70 | { 71 | return false; 72 | } 73 | 74 | memset(&sockaddr, 0, sizeof(sockaddr)); 75 | sockaddr.sin_family = AF_INET; 76 | sockaddr.sin_addr.s_addr = inet_addr(addr); 77 | sockaddr.sin_port = htons(port); 78 | 79 | return true; 80 | } 81 | 82 | void shutdown() 83 | { 84 | ::close(udpsock); 85 | } 86 | 87 | int recvfrom(char * buf, int len, struct sockaddr * from, socklen_t* fromlen) 88 | { 89 | return ::recvfrom(udpsock, buf, len, 0, from, fromlen); 90 | } 91 | 92 | int sendto(const char * buf, int len) 93 | { 94 | return ::sendto(udpsock, buf, len, 0, (const struct sockaddr *)&sockaddr, sizeof(sockaddr)); 95 | } 96 | 97 | SOCKET getsocket() 98 | { 99 | return udpsock; 100 | } 101 | 102 | private: 103 | SOCKET udpsock; 104 | struct sockaddr_in sockaddr; 105 | }; 106 | 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /udptask.h: -------------------------------------------------------------------------------- 1 | #ifndef __UDPTASK_H__ 2 | #define __UDPTASK_H__ 3 | 4 | #include 5 | #include "ikcp.h" 6 | #include "common.h" 7 | #include "udpsocket.h" 8 | 9 | class udptask 10 | { 11 | public: 12 | udptask() 13 | { 14 | conv = 0; 15 | kcp = NULL; 16 | current = 0; 17 | nexttime = 0; 18 | alivetime = nexttime + 10000; 19 | memset(buffer, 0, sizeof(buffer)); 20 | } 21 | 22 | ~udptask() 23 | { 24 | if (kcp != NULL) 25 | { 26 | ikcp_flush(kcp); 27 | ikcp_release(kcp); 28 | } 29 | printf("关闭连接 %d\n", conv); 30 | } 31 | 32 | bool init(IUINT32 conv, udpsocket *udpsock, int mode = 2) 33 | { 34 | if (udpsock == NULL) 35 | { 36 | return false; 37 | } 38 | this->conv = conv; 39 | this->nexttime = 0; 40 | 41 | kcp = ikcp_create(conv, (void*)udpsock); 42 | 43 | kcp->output = &udptask::udp_output; 44 | //kcp->logmask = 0xffff; 45 | //kcp->writelog = &udptask::writelog; 46 | 47 | ikcp_wndsize(kcp, 128, 128); 48 | 49 | switch (mode) 50 | { 51 | case 0: 52 | // 默认模式 53 | ikcp_nodelay(kcp, 0, 10, 0, 0); 54 | break; 55 | case 1: 56 | // 普通模式,关闭流控等 57 | ikcp_nodelay(kcp, 0, 10, 0, 1); 58 | break; 59 | case 2: 60 | // 启动快速模式 61 | // 第二个参数 nodelay-启用以后若干常规加速将启动 62 | // 第三个参数 interval为内部处理时钟,默认设置为 10ms 63 | // 第四个参数 resend为快速重传指标,设置为2 64 | // 第五个参数 为是否禁用常规流控,这里禁止 65 | //ikcp_nodelay(kcp, 0, 10, 0, 0); 66 | //ikcp_nodelay(kcp, 0, 10, 0, 1); 67 | //ikcp_nodelay(kcp, 1, 10, 2, 1); 68 | ikcp_nodelay(kcp, 1, 5, 1, 1); // 设置成1次ACK跨越直接重传, 这样反应速度会更快. 内部时钟5毫秒. 69 | 70 | kcp->rx_minrto = 10; 71 | kcp->fastresend = 1; 72 | break; 73 | default: 74 | printf("%d,%d 模式错误!\n", conv,mode); 75 | } 76 | 77 | printf("新建连接 %d\n", conv); 78 | return true; 79 | } 80 | 81 | int recv(const char * buf, int len) 82 | { 83 | int nret = ikcp_input(kcp, buf, len); 84 | if (nret == 0) 85 | { 86 | nexttime = iclock(); 87 | alivetime = nexttime + 10000; 88 | } 89 | return nret; 90 | } 91 | 92 | int send(const char * buf, int len) 93 | { 94 | int nret = ikcp_send(kcp, buf, len); 95 | if (nret == 0) 96 | { 97 | nexttime = iclock(); 98 | alivetime = nexttime + 10000; 99 | } 100 | //printf("发送数据 %d,%d,%d\n", conv, len, nret); 101 | return nret; 102 | } 103 | 104 | void timerloop() 105 | { 106 | current = iclock(); 107 | 108 | if (nexttime > current) 109 | { 110 | return; 111 | } 112 | 113 | nexttime = ikcp_check(kcp, current); 114 | if (nexttime != current) 115 | { 116 | return; 117 | } 118 | 119 | ikcp_update(kcp, current); 120 | 121 | while (true) { 122 | int nrecv = ikcp_recv(kcp, buffer, sizeof(buffer)); 123 | if (nrecv < 0) 124 | { 125 | if (nrecv == -3) 126 | { 127 | printf("buffer太小 %d,%d\n", conv, sizeof(buffer)); 128 | } 129 | break; 130 | } 131 | parsemsg(buffer, nrecv); 132 | } 133 | } 134 | 135 | public: 136 | virtual bool isalive() 137 | { 138 | return alivetime > current; 139 | } 140 | virtual int parsemsg(const char *buf, int len) = 0; 141 | 142 | private: 143 | static int udp_output(const char *buf, int len, ikcpcb *kcp, void *user) 144 | { 145 | return ((udpsocket*)user)->sendto(buf, len); 146 | } 147 | 148 | static void writelog(const char *log, struct IKCPCB *kcp, void *user) 149 | { 150 | printf("%s\n", log); 151 | } 152 | 153 | private: 154 | IUINT32 conv; 155 | ikcpcb *kcp; 156 | IUINT32 nexttime; 157 | IUINT32 current; 158 | IUINT32 alivetime; 159 | char buffer[65536]; 160 | }; 161 | 162 | #endif -------------------------------------------------------------------------------- /udpserver.h: -------------------------------------------------------------------------------- 1 | #ifndef __UDPSERVER_H__ 2 | #define __UDPSERVER_H__ 3 | 4 | #ifdef _WIN32 5 | #include 6 | #endif 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "udptask.h" 13 | 14 | template 15 | class handlethread 16 | { 17 | public: 18 | void init() 19 | { 20 | isstop = false; 21 | _thread = std::thread(std::bind(&handlethread::loop, this)); 22 | } 23 | void shutdown() 24 | { 25 | isstop = true; 26 | _thread.join(); 27 | _mutex.lock(); 28 | for (std::map::iterator iter = clients.begin(); 29 | iter != clients.end(); ++iter) 30 | { 31 | delete iter->second; 32 | } 33 | _mutex.unlock(); 34 | } 35 | void loop() 36 | { 37 | for (; !isstop;) 38 | { 39 | _mutex.lock(); 40 | for (std::map::iterator iter = clients.begin(); 41 | iter != clients.end();) 42 | { 43 | if (!iter->second->isalive()) 44 | { 45 | delete iter->second; 46 | iter = clients.erase(iter); 47 | } 48 | else 49 | { 50 | iter->second->timerloop(); 51 | ++iter; 52 | } 53 | } 54 | _mutex.unlock(); 55 | std::chrono::microseconds dura(10); 56 | std::this_thread::sleep_for(dura); 57 | } 58 | } 59 | void recv(SOCKET udpsock, struct sockaddr_in *paddr, IUINT32 conv, const char *buff, int size) 60 | { 61 | udptask *pclient = NULL; 62 | _mutex.lock(); 63 | std::map::iterator iter = clients.find(conv); 64 | if (iter == clients.end()) 65 | { 66 | pclient = new T(conv, udpsock, paddr); 67 | clients.insert(std::map::value_type(conv, pclient)); 68 | } 69 | else 70 | { 71 | pclient = iter->second; 72 | } 73 | pclient->recv(buff, size); 74 | _mutex.unlock(); 75 | } 76 | public: 77 | volatile bool isstop; 78 | std::mutex _mutex; 79 | std::thread _thread; 80 | std::map clients; 81 | }; 82 | 83 | template 84 | class udpserver 85 | { 86 | public: 87 | bool bind(const char *addr, unsigned int short port) 88 | { 89 | if (!udpsock.bind(addr, port)) 90 | { 91 | return false; 92 | } 93 | 94 | isstop = false; 95 | _thread = std::thread(std::bind(&udpserver::run, this)); 96 | 97 | maxtdnum = 10; 98 | for (unsigned int i = 0; i < maxtdnum; i++) 99 | { 100 | handlethread* hthread = new handlethread; 101 | hthread->init(); 102 | timerthreads.push_back(hthread); 103 | } 104 | 105 | return true; 106 | } 107 | 108 | void shutdown() 109 | { 110 | isstop = true; 111 | udpsock.shutdown(); 112 | _thread.join(); 113 | for (typename std::vector*>::iterator iter = timerthreads.begin(); 114 | iter != timerthreads.end(); ++iter) 115 | { 116 | (*iter)->shutdown(); 117 | delete *iter; 118 | } 119 | } 120 | 121 | void run() 122 | { 123 | char buff[65536] = { 0 }; 124 | struct sockaddr_in cliaddr; 125 | for (; !isstop;) 126 | { 127 | socklen_t len = sizeof(struct sockaddr_in); 128 | int size = udpsock.recvfrom(buff, sizeof(buff), (struct sockaddr*)&cliaddr, &len); 129 | if (size == 0) 130 | { 131 | continue; 132 | } 133 | if (size < 0) 134 | { 135 | printf("接收失败 %d,%d \n", udpsock.getsocket(), size); 136 | continue; 137 | } 138 | IUINT32 conv = ikcp_getconv(buff); 139 | timerthreads[conv % maxtdnum]->recv(udpsock.getsocket(), &cliaddr, conv, buff, size); 140 | } 141 | } 142 | 143 | private: 144 | udpsocket udpsock; 145 | std::thread _thread; 146 | volatile bool isstop; 147 | unsigned int maxtdnum; 148 | std::vector*> timerthreads; 149 | }; 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /ikcp.h: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // KCP - A Better ARQ Protocol Implementation 4 | // skywind3000 (at) gmail.com, 2010-2011 5 | // 6 | // Features: 7 | // + Average RTT reduce 30% - 40% vs traditional ARQ like tcp. 8 | // + Maximum RTT reduce three times vs tcp. 9 | // + Lightweight, distributed as a single source file. 10 | // 11 | //===================================================================== 12 | #ifndef __IKCP_H__ 13 | #define __IKCP_H__ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | //===================================================================== 21 | // 32BIT INTEGER DEFINITION 22 | //===================================================================== 23 | #ifndef __INTEGER_32_BITS__ 24 | #define __INTEGER_32_BITS__ 25 | #if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \ 26 | defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \ 27 | defined(_M_AMD64) 28 | typedef unsigned int ISTDUINT32; 29 | typedef int ISTDINT32; 30 | #elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \ 31 | defined(__i386) || defined(_M_X86) 32 | typedef unsigned long ISTDUINT32; 33 | typedef long ISTDINT32; 34 | #elif defined(__MACOS__) 35 | typedef UInt32 ISTDUINT32; 36 | typedef SInt32 ISTDINT32; 37 | #elif defined(__APPLE__) && defined(__MACH__) 38 | #include 39 | typedef u_int32_t ISTDUINT32; 40 | typedef int32_t ISTDINT32; 41 | #elif defined(__BEOS__) 42 | #include 43 | typedef u_int32_t ISTDUINT32; 44 | typedef int32_t ISTDINT32; 45 | #elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__)) 46 | typedef unsigned __int32 ISTDUINT32; 47 | typedef __int32 ISTDINT32; 48 | #elif defined(__GNUC__) 49 | #include 50 | typedef uint32_t ISTDUINT32; 51 | typedef int32_t ISTDINT32; 52 | #else 53 | typedef unsigned long ISTDUINT32; 54 | typedef long ISTDINT32; 55 | #endif 56 | #endif 57 | 58 | 59 | //===================================================================== 60 | // Integer Definition 61 | //===================================================================== 62 | #ifndef __IINT8_DEFINED 63 | #define __IINT8_DEFINED 64 | typedef char IINT8; 65 | #endif 66 | 67 | #ifndef __IUINT8_DEFINED 68 | #define __IUINT8_DEFINED 69 | typedef unsigned char IUINT8; 70 | #endif 71 | 72 | #ifndef __IUINT16_DEFINED 73 | #define __IUINT16_DEFINED 74 | typedef unsigned short IUINT16; 75 | #endif 76 | 77 | #ifndef __IINT16_DEFINED 78 | #define __IINT16_DEFINED 79 | typedef short IINT16; 80 | #endif 81 | 82 | #ifndef __IINT32_DEFINED 83 | #define __IINT32_DEFINED 84 | typedef ISTDINT32 IINT32; 85 | #endif 86 | 87 | #ifndef __IUINT32_DEFINED 88 | #define __IUINT32_DEFINED 89 | typedef ISTDUINT32 IUINT32; 90 | #endif 91 | 92 | #ifndef __IINT64_DEFINED 93 | #define __IINT64_DEFINED 94 | #if defined(_MSC_VER) || defined(__BORLANDC__) 95 | typedef __int64 IINT64; 96 | #else 97 | typedef long long IINT64; 98 | #endif 99 | #endif 100 | 101 | #ifndef __IUINT64_DEFINED 102 | #define __IUINT64_DEFINED 103 | #if defined(_MSC_VER) || defined(__BORLANDC__) 104 | typedef unsigned __int64 IUINT64; 105 | #else 106 | typedef unsigned long long IUINT64; 107 | #endif 108 | #endif 109 | 110 | #ifndef INLINE 111 | #if defined(__GNUC__) 112 | 113 | #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) 114 | #define INLINE __inline__ __attribute__((always_inline)) 115 | #else 116 | #define INLINE __inline__ 117 | #endif 118 | 119 | #elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__)) 120 | #define INLINE __inline 121 | #else 122 | #define INLINE 123 | #endif 124 | #endif 125 | 126 | #if (!defined(__cplusplus)) && (!defined(inline)) 127 | #define inline INLINE 128 | #endif 129 | 130 | 131 | //===================================================================== 132 | // QUEUE DEFINITION 133 | //===================================================================== 134 | #ifndef __IQUEUE_DEF__ 135 | #define __IQUEUE_DEF__ 136 | 137 | struct IQUEUEHEAD { 138 | struct IQUEUEHEAD *next, *prev; 139 | }; 140 | 141 | typedef struct IQUEUEHEAD iqueue_head; 142 | 143 | 144 | //--------------------------------------------------------------------- 145 | // queue init 146 | //--------------------------------------------------------------------- 147 | #define IQUEUE_HEAD_INIT(name) { &(name), &(name) } 148 | #define IQUEUE_HEAD(name) \ 149 | struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name) 150 | 151 | #define IQUEUE_INIT(ptr) ( \ 152 | (ptr)->next = (ptr), (ptr)->prev = (ptr)) 153 | 154 | #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 155 | 156 | #define ICONTAINEROF(ptr, type, member) ( \ 157 | (type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) ) 158 | 159 | #define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member) 160 | 161 | 162 | //--------------------------------------------------------------------- 163 | // queue operation 164 | //--------------------------------------------------------------------- 165 | #define IQUEUE_ADD(node, head) ( \ 166 | (node)->prev = (head), (node)->next = (head)->next, \ 167 | (head)->next->prev = (node), (head)->next = (node)) 168 | 169 | #define IQUEUE_ADD_TAIL(node, head) ( \ 170 | (node)->prev = (head)->prev, (node)->next = (head), \ 171 | (head)->prev->next = (node), (head)->prev = (node)) 172 | 173 | #define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n)) 174 | 175 | #define IQUEUE_DEL(entry) (\ 176 | (entry)->next->prev = (entry)->prev, \ 177 | (entry)->prev->next = (entry)->next, \ 178 | (entry)->next = 0, (entry)->prev = 0) 179 | 180 | #define IQUEUE_DEL_INIT(entry) do { \ 181 | IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0) 182 | 183 | #define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next) 184 | 185 | #define iqueue_init IQUEUE_INIT 186 | #define iqueue_entry IQUEUE_ENTRY 187 | #define iqueue_add IQUEUE_ADD 188 | #define iqueue_add_tail IQUEUE_ADD_TAIL 189 | #define iqueue_del IQUEUE_DEL 190 | #define iqueue_del_init IQUEUE_DEL_INIT 191 | #define iqueue_is_empty IQUEUE_IS_EMPTY 192 | 193 | #define IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) \ 194 | for ((iterator) = iqueue_entry((head)->next, TYPE, MEMBER); \ 195 | &((iterator)->MEMBER) != (head); \ 196 | (iterator) = iqueue_entry((iterator)->MEMBER.next, TYPE, MEMBER)) 197 | 198 | #define iqueue_foreach(iterator, head, TYPE, MEMBER) \ 199 | IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) 200 | 201 | #define iqueue_foreach_entry(pos, head) \ 202 | for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next ) 203 | 204 | 205 | #define __iqueue_splice(list, head) do { \ 206 | iqueue_head *first = (list)->next, *last = (list)->prev; \ 207 | iqueue_head *at = (head)->next; \ 208 | (first)->prev = (head), (head)->next = (first); \ 209 | (last)->next = (at), (at)->prev = (last); } while (0) 210 | 211 | #define iqueue_splice(list, head) do { \ 212 | if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0) 213 | 214 | #define iqueue_splice_init(list, head) do { \ 215 | iqueue_splice(list, head); iqueue_init(list); } while (0) 216 | 217 | 218 | #ifdef _MSC_VER 219 | #pragma warning(disable:4311) 220 | #pragma warning(disable:4312) 221 | #pragma warning(disable:4996) 222 | #endif 223 | 224 | #endif 225 | 226 | 227 | //--------------------------------------------------------------------- 228 | // WORD ORDER 229 | //--------------------------------------------------------------------- 230 | #ifndef IWORDS_BIG_ENDIAN 231 | #ifdef _BIG_ENDIAN_ 232 | #if _BIG_ENDIAN_ 233 | #define IWORDS_BIG_ENDIAN 1 234 | #endif 235 | #endif 236 | #ifndef IWORDS_BIG_ENDIAN 237 | #if defined(__hppa__) || \ 238 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ 239 | (defined(__MIPS__) && defined(__MISPEB__)) || \ 240 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ 241 | defined(__sparc__) || defined(__powerpc__) || \ 242 | defined(__mc68000__) || defined(__s390x__) || defined(__s390__) 243 | #define IWORDS_BIG_ENDIAN 1 244 | #endif 245 | #endif 246 | #ifndef IWORDS_BIG_ENDIAN 247 | #define IWORDS_BIG_ENDIAN 0 248 | #endif 249 | #endif 250 | 251 | 252 | 253 | //===================================================================== 254 | // SEGMENT 255 | //===================================================================== 256 | struct IKCPSEG 257 | { 258 | struct IQUEUEHEAD node; 259 | IUINT32 conv; 260 | IUINT32 cmd; 261 | IUINT32 frg; 262 | IUINT32 wnd; 263 | IUINT32 ts; 264 | IUINT32 sn; 265 | IUINT32 una; 266 | IUINT32 len; 267 | IUINT32 resendts; 268 | IUINT32 rto; 269 | IUINT32 fastack; 270 | IUINT32 xmit; 271 | char data[1]; 272 | }; 273 | 274 | 275 | //--------------------------------------------------------------------- 276 | // IKCPCB 277 | //--------------------------------------------------------------------- 278 | struct IKCPCB 279 | { 280 | IUINT32 conv, mtu, mss, state; 281 | IUINT32 snd_una, snd_nxt, rcv_nxt; 282 | IUINT32 ts_recent, ts_lastack, ssthresh; 283 | IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto; 284 | IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe; 285 | IUINT32 current, interval, ts_flush, xmit; 286 | IUINT32 nrcv_buf, nsnd_buf; 287 | IUINT32 nrcv_que, nsnd_que; 288 | IUINT32 nodelay, updated; 289 | IUINT32 ts_probe, probe_wait; 290 | IUINT32 dead_link, incr; 291 | struct IQUEUEHEAD snd_queue; 292 | struct IQUEUEHEAD rcv_queue; 293 | struct IQUEUEHEAD snd_buf; 294 | struct IQUEUEHEAD rcv_buf; 295 | IUINT32 *acklist; 296 | IUINT32 ackcount; 297 | IUINT32 ackblock; 298 | void *user; 299 | char *buffer; 300 | int fastresend; 301 | int nocwnd, stream; 302 | int logmask; 303 | int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user); 304 | void (*writelog)(const char *log, struct IKCPCB *kcp, void *user); 305 | }; 306 | 307 | 308 | typedef struct IKCPCB ikcpcb; 309 | 310 | #define IKCP_LOG_OUTPUT 1 311 | #define IKCP_LOG_INPUT 2 312 | #define IKCP_LOG_SEND 4 313 | #define IKCP_LOG_RECV 8 314 | #define IKCP_LOG_IN_DATA 16 315 | #define IKCP_LOG_IN_ACK 32 316 | #define IKCP_LOG_IN_PROBE 64 317 | #define IKCP_LOG_IN_WINS 128 318 | #define IKCP_LOG_OUT_DATA 256 319 | #define IKCP_LOG_OUT_ACK 512 320 | #define IKCP_LOG_OUT_PROBE 1024 321 | #define IKCP_LOG_OUT_WINS 2048 322 | 323 | #ifdef __cplusplus 324 | extern "C" { 325 | #endif 326 | 327 | //--------------------------------------------------------------------- 328 | // interface 329 | //--------------------------------------------------------------------- 330 | 331 | // create a new kcp control object, 'conv' must equal in two endpoint 332 | // from the same connection. 'user' will be passed to the output callback 333 | // output callback can be setup like this: 'kcp->output = my_udp_output' 334 | ikcpcb* ikcp_create(IUINT32 conv, void *user); 335 | 336 | // release kcp control object 337 | void ikcp_release(ikcpcb *kcp); 338 | 339 | // set output callback, which will be invoked by kcp 340 | void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len, 341 | ikcpcb *kcp, void *user)); 342 | 343 | // user/upper level recv: returns size, returns below zero for EAGAIN 344 | int ikcp_recv(ikcpcb *kcp, char *buffer, int len); 345 | 346 | // user/upper level send, returns below zero for error 347 | int ikcp_send(ikcpcb *kcp, const char *buffer, int len); 348 | 349 | // update state (call it repeatedly, every 10ms-100ms), or you can ask 350 | // ikcp_check when to call it again (without ikcp_input/_send calling). 351 | // 'current' - current timestamp in millisec. 352 | void ikcp_update(ikcpcb *kcp, IUINT32 current); 353 | 354 | // Determine when should you invoke ikcp_update: 355 | // returns when you should invoke ikcp_update in millisec, if there 356 | // is no ikcp_input/_send calling. you can call ikcp_update in that 357 | // time, instead of call update repeatly. 358 | // Important to reduce unnacessary ikcp_update invoking. use it to 359 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 360 | // or optimize ikcp_update when handling massive kcp connections) 361 | IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current); 362 | 363 | // when you received a low level packet (eg. UDP packet), call it 364 | int ikcp_input(ikcpcb *kcp, const char *data, long size); 365 | 366 | // flush pending data 367 | void ikcp_flush(ikcpcb *kcp); 368 | 369 | // check the size of next message in the recv queue 370 | int ikcp_peeksize(const ikcpcb *kcp); 371 | 372 | // change MTU size, default is 1400 373 | int ikcp_setmtu(ikcpcb *kcp, int mtu); 374 | 375 | // set maximum window size: sndwnd=32, rcvwnd=32 by default 376 | int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); 377 | 378 | // get how many packet is waiting to be sent 379 | int ikcp_waitsnd(const ikcpcb *kcp); 380 | 381 | // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) 382 | // nodelay: 0:disable(default), 1:enable 383 | // interval: internal update timer interval in millisec, default is 100ms 384 | // resend: 0:disable fast resend(default), 1:enable fast resend 385 | // nc: 0:normal congestion control(default), 1:disable congestion control 386 | int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc); 387 | 388 | int ikcp_rcvbuf_count(const ikcpcb *kcp); 389 | int ikcp_sndbuf_count(const ikcpcb *kcp); 390 | 391 | void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...); 392 | 393 | // setup allocator 394 | void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*)); 395 | 396 | // read conv 397 | IUINT32 ikcp_getconv(const void *ptr); 398 | 399 | 400 | #ifdef __cplusplus 401 | } 402 | #endif 403 | 404 | #endif 405 | 406 | 407 | -------------------------------------------------------------------------------- /ikcp.c: -------------------------------------------------------------------------------- 1 | //===================================================================== 2 | // 3 | // KCP - A Better ARQ Protocol Implementation 4 | // skywind3000 (at) gmail.com, 2010-2011 5 | // 6 | // Features: 7 | // + Average RTT reduce 30% - 40% vs traditional ARQ like tcp. 8 | // + Maximum RTT reduce three times vs tcp. 9 | // + Lightweight, distributed as a single source file. 10 | // 11 | //===================================================================== 12 | #include "ikcp.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | 22 | //===================================================================== 23 | // KCP BASIC 24 | //===================================================================== 25 | const IUINT32 IKCP_RTO_NDL = 30; // no delay min rto 26 | const IUINT32 IKCP_RTO_MIN = 100; // normal min rto 27 | const IUINT32 IKCP_RTO_DEF = 200; 28 | const IUINT32 IKCP_RTO_MAX = 60000; 29 | const IUINT32 IKCP_CMD_PUSH = 81; // cmd: push data 30 | const IUINT32 IKCP_CMD_ACK = 82; // cmd: ack 31 | const IUINT32 IKCP_CMD_WASK = 83; // cmd: window probe (ask) 32 | const IUINT32 IKCP_CMD_WINS = 84; // cmd: window size (tell) 33 | const IUINT32 IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK 34 | const IUINT32 IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS 35 | const IUINT32 IKCP_WND_SND = 32; 36 | const IUINT32 IKCP_WND_RCV = 32; 37 | const IUINT32 IKCP_MTU_DEF = 1400; 38 | const IUINT32 IKCP_ACK_FAST = 3; 39 | const IUINT32 IKCP_INTERVAL = 100; 40 | const IUINT32 IKCP_OVERHEAD = 24; 41 | const IUINT32 IKCP_DEADLINK = 20; 42 | const IUINT32 IKCP_THRESH_INIT = 2; 43 | const IUINT32 IKCP_THRESH_MIN = 2; 44 | const IUINT32 IKCP_PROBE_INIT = 7000; // 7 secs to probe window size 45 | const IUINT32 IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window 46 | 47 | 48 | //--------------------------------------------------------------------- 49 | // encode / decode 50 | //--------------------------------------------------------------------- 51 | 52 | /* encode 8 bits unsigned int */ 53 | static inline char *ikcp_encode8u(char *p, unsigned char c) 54 | { 55 | *(unsigned char*)p++ = c; 56 | return p; 57 | } 58 | 59 | /* decode 8 bits unsigned int */ 60 | static inline const char *ikcp_decode8u(const char *p, unsigned char *c) 61 | { 62 | *c = *(unsigned char*)p++; 63 | return p; 64 | } 65 | 66 | /* encode 16 bits unsigned int (lsb) */ 67 | static inline char *ikcp_encode16u(char *p, unsigned short w) 68 | { 69 | #if IWORDS_BIG_ENDIAN 70 | *(unsigned char*)(p + 0) = (w & 255); 71 | *(unsigned char*)(p + 1) = (w >> 8); 72 | #else 73 | *(unsigned short*)(p) = w; 74 | #endif 75 | p += 2; 76 | return p; 77 | } 78 | 79 | /* decode 16 bits unsigned int (lsb) */ 80 | static inline const char *ikcp_decode16u(const char *p, unsigned short *w) 81 | { 82 | #if IWORDS_BIG_ENDIAN 83 | *w = *(const unsigned char*)(p + 1); 84 | *w = *(const unsigned char*)(p + 0) + (*w << 8); 85 | #else 86 | *w = *(const unsigned short*)p; 87 | #endif 88 | p += 2; 89 | return p; 90 | } 91 | 92 | /* encode 32 bits unsigned int (lsb) */ 93 | static inline char *ikcp_encode32u(char *p, IUINT32 l) 94 | { 95 | #if IWORDS_BIG_ENDIAN 96 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff); 97 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); 98 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff); 99 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff); 100 | #else 101 | *(IUINT32*)p = l; 102 | #endif 103 | p += 4; 104 | return p; 105 | } 106 | 107 | /* decode 32 bits unsigned int (lsb) */ 108 | static inline const char *ikcp_decode32u(const char *p, IUINT32 *l) 109 | { 110 | #if IWORDS_BIG_ENDIAN 111 | *l = *(const unsigned char*)(p + 3); 112 | *l = *(const unsigned char*)(p + 2) + (*l << 8); 113 | *l = *(const unsigned char*)(p + 1) + (*l << 8); 114 | *l = *(const unsigned char*)(p + 0) + (*l << 8); 115 | #else 116 | *l = *(const IUINT32*)p; 117 | #endif 118 | p += 4; 119 | return p; 120 | } 121 | 122 | static inline IUINT32 _imin_(IUINT32 a, IUINT32 b) { 123 | return a <= b ? a : b; 124 | } 125 | 126 | static inline IUINT32 _imax_(IUINT32 a, IUINT32 b) { 127 | return a >= b ? a : b; 128 | } 129 | 130 | static inline IUINT32 _ibound_(IUINT32 lower, IUINT32 middle, IUINT32 upper) 131 | { 132 | return _imin_(_imax_(lower, middle), upper); 133 | } 134 | 135 | static inline long _itimediff(IUINT32 later, IUINT32 earlier) 136 | { 137 | return ((IINT32)(later - earlier)); 138 | } 139 | 140 | //--------------------------------------------------------------------- 141 | // manage segment 142 | //--------------------------------------------------------------------- 143 | typedef struct IKCPSEG IKCPSEG; 144 | 145 | static void* (*ikcp_malloc_hook)(size_t) = NULL; 146 | static void (*ikcp_free_hook)(void *) = NULL; 147 | 148 | // internal malloc 149 | static void* ikcp_malloc(size_t size) { 150 | if (ikcp_malloc_hook) 151 | return ikcp_malloc_hook(size); 152 | return malloc(size); 153 | } 154 | 155 | // internal free 156 | static void ikcp_free(void *ptr) { 157 | if (ikcp_free_hook) { 158 | ikcp_free_hook(ptr); 159 | } else { 160 | free(ptr); 161 | } 162 | } 163 | 164 | // redefine allocator 165 | void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*)) 166 | { 167 | ikcp_malloc_hook = new_malloc; 168 | ikcp_free_hook = new_free; 169 | } 170 | 171 | // allocate a new kcp segment 172 | static IKCPSEG* ikcp_segment_new(ikcpcb *kcp, int size) 173 | { 174 | return (IKCPSEG*)ikcp_malloc(sizeof(IKCPSEG) + size); 175 | } 176 | 177 | // delete a segment 178 | static void ikcp_segment_delete(ikcpcb *kcp, IKCPSEG *seg) 179 | { 180 | ikcp_free(seg); 181 | } 182 | 183 | // write log 184 | void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...) 185 | { 186 | char buffer[1024]; 187 | va_list argptr; 188 | if ((mask & kcp->logmask) == 0 || kcp->writelog == 0) return; 189 | va_start(argptr, fmt); 190 | vsprintf(buffer, fmt, argptr); 191 | va_end(argptr); 192 | kcp->writelog(buffer, kcp, kcp->user); 193 | } 194 | 195 | // check log mask 196 | static int ikcp_canlog(const ikcpcb *kcp, int mask) 197 | { 198 | if ((mask & kcp->logmask) == 0 || kcp->writelog == NULL) return 0; 199 | return 1; 200 | } 201 | 202 | // output segment 203 | static int ikcp_output(ikcpcb *kcp, const void *data, int size) 204 | { 205 | assert(kcp); 206 | assert(kcp->output); 207 | if (ikcp_canlog(kcp, IKCP_LOG_OUTPUT)) { 208 | ikcp_log(kcp, IKCP_LOG_OUTPUT, "[RO] %ld bytes", (long)size); 209 | } 210 | if (size == 0) return 0; 211 | return kcp->output((const char*)data, size, kcp, kcp->user); 212 | } 213 | 214 | // output queue 215 | void ikcp_qprint(const char *name, const struct IQUEUEHEAD *head) 216 | { 217 | #if 0 218 | const struct IQUEUEHEAD *p; 219 | printf("<%s>: [", name); 220 | for (p = head->next; p != head; p = p->next) { 221 | const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node); 222 | printf("(%lu %d)", (unsigned long)seg->sn, (int)(seg->ts % 10000)); 223 | if (p->next != head) printf(","); 224 | } 225 | printf("]\n"); 226 | #endif 227 | } 228 | 229 | 230 | //--------------------------------------------------------------------- 231 | // create a new kcpcb 232 | //--------------------------------------------------------------------- 233 | ikcpcb* ikcp_create(IUINT32 conv, void *user) 234 | { 235 | ikcpcb *kcp = (ikcpcb*)ikcp_malloc(sizeof(struct IKCPCB)); 236 | if (kcp == NULL) return NULL; 237 | kcp->conv = conv; 238 | kcp->user = user; 239 | kcp->snd_una = 0; 240 | kcp->snd_nxt = 0; 241 | kcp->rcv_nxt = 0; 242 | kcp->ts_recent = 0; 243 | kcp->ts_lastack = 0; 244 | kcp->ts_probe = 0; 245 | kcp->probe_wait = 0; 246 | kcp->snd_wnd = IKCP_WND_SND; 247 | kcp->rcv_wnd = IKCP_WND_RCV; 248 | kcp->rmt_wnd = IKCP_WND_RCV; 249 | kcp->cwnd = 0; 250 | kcp->incr = 0; 251 | kcp->probe = 0; 252 | kcp->mtu = IKCP_MTU_DEF; 253 | kcp->mss = kcp->mtu - IKCP_OVERHEAD; 254 | kcp->stream = 0; 255 | 256 | kcp->buffer = (char*)ikcp_malloc((kcp->mtu + IKCP_OVERHEAD) * 3); 257 | if (kcp->buffer == NULL) { 258 | ikcp_free(kcp); 259 | return NULL; 260 | } 261 | 262 | iqueue_init(&kcp->snd_queue); 263 | iqueue_init(&kcp->rcv_queue); 264 | iqueue_init(&kcp->snd_buf); 265 | iqueue_init(&kcp->rcv_buf); 266 | kcp->nrcv_buf = 0; 267 | kcp->nsnd_buf = 0; 268 | kcp->nrcv_que = 0; 269 | kcp->nsnd_que = 0; 270 | kcp->state = 0; 271 | kcp->acklist = NULL; 272 | kcp->ackblock = 0; 273 | kcp->ackcount = 0; 274 | kcp->rx_srtt = 0; 275 | kcp->rx_rttval = 0; 276 | kcp->rx_rto = IKCP_RTO_DEF; 277 | kcp->rx_minrto = IKCP_RTO_MIN; 278 | kcp->current = 0; 279 | kcp->interval = IKCP_INTERVAL; 280 | kcp->ts_flush = IKCP_INTERVAL; 281 | kcp->nodelay = 0; 282 | kcp->updated = 0; 283 | kcp->logmask = 0; 284 | kcp->ssthresh = IKCP_THRESH_INIT; 285 | kcp->fastresend = 0; 286 | kcp->nocwnd = 0; 287 | kcp->xmit = 0; 288 | kcp->dead_link = IKCP_DEADLINK; 289 | kcp->output = NULL; 290 | kcp->writelog = NULL; 291 | 292 | return kcp; 293 | } 294 | 295 | 296 | //--------------------------------------------------------------------- 297 | // release a new kcpcb 298 | //--------------------------------------------------------------------- 299 | void ikcp_release(ikcpcb *kcp) 300 | { 301 | assert(kcp); 302 | if (kcp) { 303 | IKCPSEG *seg; 304 | while (!iqueue_is_empty(&kcp->snd_buf)) { 305 | seg = iqueue_entry(kcp->snd_buf.next, IKCPSEG, node); 306 | iqueue_del(&seg->node); 307 | ikcp_segment_delete(kcp, seg); 308 | } 309 | while (!iqueue_is_empty(&kcp->rcv_buf)) { 310 | seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node); 311 | iqueue_del(&seg->node); 312 | ikcp_segment_delete(kcp, seg); 313 | } 314 | while (!iqueue_is_empty(&kcp->snd_queue)) { 315 | seg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node); 316 | iqueue_del(&seg->node); 317 | ikcp_segment_delete(kcp, seg); 318 | } 319 | while (!iqueue_is_empty(&kcp->rcv_queue)) { 320 | seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node); 321 | iqueue_del(&seg->node); 322 | ikcp_segment_delete(kcp, seg); 323 | } 324 | if (kcp->buffer) { 325 | ikcp_free(kcp->buffer); 326 | } 327 | if (kcp->acklist) { 328 | ikcp_free(kcp->acklist); 329 | } 330 | 331 | kcp->nrcv_buf = 0; 332 | kcp->nsnd_buf = 0; 333 | kcp->nrcv_que = 0; 334 | kcp->nsnd_que = 0; 335 | kcp->ackcount = 0; 336 | kcp->buffer = NULL; 337 | kcp->acklist = NULL; 338 | ikcp_free(kcp); 339 | } 340 | } 341 | 342 | 343 | //--------------------------------------------------------------------- 344 | // set output callback, which will be invoked by kcp 345 | //--------------------------------------------------------------------- 346 | void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len, 347 | ikcpcb *kcp, void *user)) 348 | { 349 | kcp->output = output; 350 | } 351 | 352 | 353 | //--------------------------------------------------------------------- 354 | // user/upper level recv: returns size, returns below zero for EAGAIN 355 | //--------------------------------------------------------------------- 356 | int ikcp_recv(ikcpcb *kcp, char *buffer, int len) 357 | { 358 | struct IQUEUEHEAD *p; 359 | int ispeek = (len < 0)? 1 : 0; 360 | int peeksize; 361 | int recover = 0; 362 | IKCPSEG *seg; 363 | assert(kcp); 364 | 365 | if (iqueue_is_empty(&kcp->rcv_queue)) 366 | return -1; 367 | 368 | if (len < 0) len = -len; 369 | 370 | peeksize = ikcp_peeksize(kcp); 371 | 372 | if (peeksize < 0) 373 | return -2; 374 | 375 | if (peeksize > len) 376 | return -3; 377 | 378 | if (kcp->nrcv_que >= kcp->rcv_wnd) 379 | recover = 1; 380 | 381 | // merge fragment 382 | for (len = 0, p = kcp->rcv_queue.next; p != &kcp->rcv_queue; ) { 383 | int fragment; 384 | seg = iqueue_entry(p, IKCPSEG, node); 385 | p = p->next; 386 | 387 | if (buffer) { 388 | memcpy(buffer, seg->data, seg->len); 389 | buffer += seg->len; 390 | } 391 | 392 | len += seg->len; 393 | fragment = seg->frg; 394 | 395 | if (ikcp_canlog(kcp, IKCP_LOG_RECV)) { 396 | ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", seg->sn); 397 | } 398 | 399 | if (ispeek == 0) { 400 | iqueue_del(&seg->node); 401 | ikcp_segment_delete(kcp, seg); 402 | kcp->nrcv_que--; 403 | } 404 | 405 | if (fragment == 0) 406 | break; 407 | } 408 | 409 | assert(len == peeksize); 410 | 411 | // move available data from rcv_buf -> rcv_queue 412 | while (! iqueue_is_empty(&kcp->rcv_buf)) { 413 | IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node); 414 | if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) { 415 | iqueue_del(&seg->node); 416 | kcp->nrcv_buf--; 417 | iqueue_add_tail(&seg->node, &kcp->rcv_queue); 418 | kcp->nrcv_que++; 419 | kcp->rcv_nxt++; 420 | } else { 421 | break; 422 | } 423 | } 424 | 425 | // fast recover 426 | if (kcp->nrcv_que < kcp->rcv_wnd && recover) { 427 | // ready to send back IKCP_CMD_WINS in ikcp_flush 428 | // tell remote my window size 429 | kcp->probe |= IKCP_ASK_TELL; 430 | } 431 | 432 | return len; 433 | } 434 | 435 | 436 | //--------------------------------------------------------------------- 437 | // peek data size 438 | //--------------------------------------------------------------------- 439 | int ikcp_peeksize(const ikcpcb *kcp) 440 | { 441 | struct IQUEUEHEAD *p; 442 | IKCPSEG *seg; 443 | int length = 0; 444 | 445 | assert(kcp); 446 | 447 | if (iqueue_is_empty(&kcp->rcv_queue)) return -1; 448 | 449 | seg = iqueue_entry(kcp->rcv_queue.next, IKCPSEG, node); 450 | if (seg->frg == 0) return seg->len; 451 | 452 | if (kcp->nrcv_que < seg->frg + 1) return -1; 453 | 454 | for (p = kcp->rcv_queue.next; p != &kcp->rcv_queue; p = p->next) { 455 | seg = iqueue_entry(p, IKCPSEG, node); 456 | length += seg->len; 457 | if (seg->frg == 0) break; 458 | } 459 | 460 | return length; 461 | } 462 | 463 | 464 | //--------------------------------------------------------------------- 465 | // user/upper level send, returns below zero for error 466 | //--------------------------------------------------------------------- 467 | int ikcp_send(ikcpcb *kcp, const char *buffer, int len) 468 | { 469 | IKCPSEG *seg; 470 | int count, i; 471 | 472 | assert(kcp->mss > 0); 473 | if (len < 0) return -1; 474 | 475 | // append to previous segment in streaming mode (if possible) 476 | if (kcp->stream != 0) { 477 | if (!iqueue_is_empty(&kcp->snd_queue)) { 478 | IKCPSEG *old = iqueue_entry(kcp->snd_queue.prev, IKCPSEG, node); 479 | if (old->len < kcp->mss) { 480 | int capacity = kcp->mss - old->len; 481 | int extend = (len < capacity)? len : capacity; 482 | seg = ikcp_segment_new(kcp, old->len + extend); 483 | assert(seg); 484 | if (seg == NULL) { 485 | return -2; 486 | } 487 | iqueue_add_tail(&seg->node, &kcp->snd_queue); 488 | memcpy(seg->data, old->data, old->len); 489 | if (buffer) { 490 | memcpy(seg->data + old->len, buffer, extend); 491 | buffer += extend; 492 | } 493 | seg->len = old->len + extend; 494 | seg->frg = 0; 495 | len -= extend; 496 | iqueue_del_init(&old->node); 497 | ikcp_segment_delete(kcp, old); 498 | } 499 | } 500 | if (len <= 0) { 501 | return 0; 502 | } 503 | } 504 | 505 | if (len <= (int)kcp->mss) count = 1; 506 | else count = (len + kcp->mss - 1) / kcp->mss; 507 | 508 | if (count > 255) return -2; 509 | 510 | if (count == 0) count = 1; 511 | 512 | // fragment 513 | for (i = 0; i < count; i++) { 514 | int size = len > (int)kcp->mss ? (int)kcp->mss : len; 515 | seg = ikcp_segment_new(kcp, size); 516 | assert(seg); 517 | if (seg == NULL) { 518 | return -2; 519 | } 520 | if (buffer && len > 0) { 521 | memcpy(seg->data, buffer, size); 522 | } 523 | seg->len = size; 524 | seg->frg = (kcp->stream == 0)? (count - i - 1) : 0; 525 | iqueue_init(&seg->node); 526 | iqueue_add_tail(&seg->node, &kcp->snd_queue); 527 | kcp->nsnd_que++; 528 | if (buffer) { 529 | buffer += size; 530 | } 531 | len -= size; 532 | } 533 | 534 | return 0; 535 | } 536 | 537 | 538 | //--------------------------------------------------------------------- 539 | // parse ack 540 | //--------------------------------------------------------------------- 541 | static void ikcp_update_ack(ikcpcb *kcp, IINT32 rtt) 542 | { 543 | IINT32 rto = 0; 544 | if (kcp->rx_srtt == 0) { 545 | kcp->rx_srtt = rtt; 546 | kcp->rx_rttval = rtt / 2; 547 | } else { 548 | long delta = rtt - kcp->rx_srtt; 549 | if (delta < 0) delta = -delta; 550 | kcp->rx_rttval = (3 * kcp->rx_rttval + delta) / 4; 551 | kcp->rx_srtt = (7 * kcp->rx_srtt + rtt) / 8; 552 | if (kcp->rx_srtt < 1) kcp->rx_srtt = 1; 553 | } 554 | rto = kcp->rx_srtt + _imax_(kcp->interval, 4 * kcp->rx_rttval); 555 | kcp->rx_rto = _ibound_(kcp->rx_minrto, rto, IKCP_RTO_MAX); 556 | } 557 | 558 | static void ikcp_shrink_buf(ikcpcb *kcp) 559 | { 560 | struct IQUEUEHEAD *p = kcp->snd_buf.next; 561 | if (p != &kcp->snd_buf) { 562 | IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); 563 | kcp->snd_una = seg->sn; 564 | } else { 565 | kcp->snd_una = kcp->snd_nxt; 566 | } 567 | } 568 | 569 | static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn) 570 | { 571 | struct IQUEUEHEAD *p, *next; 572 | 573 | if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0) 574 | return; 575 | 576 | for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { 577 | IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); 578 | next = p->next; 579 | if (sn == seg->sn) { 580 | iqueue_del(p); 581 | ikcp_segment_delete(kcp, seg); 582 | kcp->nsnd_buf--; 583 | break; 584 | } 585 | if (_itimediff(sn, seg->sn) < 0) { 586 | break; 587 | } 588 | } 589 | } 590 | 591 | static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una) 592 | { 593 | struct IQUEUEHEAD *p, *next; 594 | for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { 595 | IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); 596 | next = p->next; 597 | if (_itimediff(una, seg->sn) > 0) { 598 | iqueue_del(p); 599 | ikcp_segment_delete(kcp, seg); 600 | kcp->nsnd_buf--; 601 | } else { 602 | break; 603 | } 604 | } 605 | } 606 | 607 | static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn) 608 | { 609 | struct IQUEUEHEAD *p, *next; 610 | 611 | if (_itimediff(sn, kcp->snd_una) < 0 || _itimediff(sn, kcp->snd_nxt) >= 0) 612 | return; 613 | 614 | for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = next) { 615 | IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); 616 | next = p->next; 617 | if (_itimediff(sn, seg->sn) < 0) { 618 | break; 619 | } 620 | else if (sn != seg->sn) { 621 | seg->fastack++; 622 | } 623 | } 624 | } 625 | 626 | 627 | //--------------------------------------------------------------------- 628 | // ack append 629 | //--------------------------------------------------------------------- 630 | static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts) 631 | { 632 | size_t newsize = kcp->ackcount + 1; 633 | IUINT32 *ptr; 634 | 635 | if (newsize > kcp->ackblock) { 636 | IUINT32 *acklist; 637 | size_t newblock; 638 | 639 | for (newblock = 8; newblock < newsize; newblock <<= 1); 640 | acklist = (IUINT32*)ikcp_malloc(newblock * sizeof(IUINT32) * 2); 641 | 642 | if (acklist == NULL) { 643 | assert(acklist != NULL); 644 | abort(); 645 | } 646 | 647 | if (kcp->acklist != NULL) { 648 | size_t x; 649 | for (x = 0; x < kcp->ackcount; x++) { 650 | acklist[x * 2 + 0] = kcp->acklist[x * 2 + 0]; 651 | acklist[x * 2 + 1] = kcp->acklist[x * 2 + 1]; 652 | } 653 | ikcp_free(kcp->acklist); 654 | } 655 | 656 | kcp->acklist = acklist; 657 | kcp->ackblock = newblock; 658 | } 659 | 660 | ptr = &kcp->acklist[kcp->ackcount * 2]; 661 | ptr[0] = sn; 662 | ptr[1] = ts; 663 | kcp->ackcount++; 664 | } 665 | 666 | static void ikcp_ack_get(const ikcpcb *kcp, int p, IUINT32 *sn, IUINT32 *ts) 667 | { 668 | if (sn) sn[0] = kcp->acklist[p * 2 + 0]; 669 | if (ts) ts[0] = kcp->acklist[p * 2 + 1]; 670 | } 671 | 672 | 673 | //--------------------------------------------------------------------- 674 | // parse data 675 | //--------------------------------------------------------------------- 676 | void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg) 677 | { 678 | struct IQUEUEHEAD *p, *prev; 679 | IUINT32 sn = newseg->sn; 680 | int repeat = 0; 681 | 682 | if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) >= 0 || 683 | _itimediff(sn, kcp->rcv_nxt) < 0) { 684 | ikcp_segment_delete(kcp, newseg); 685 | return; 686 | } 687 | 688 | for (p = kcp->rcv_buf.prev; p != &kcp->rcv_buf; p = prev) { 689 | IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node); 690 | prev = p->prev; 691 | if (seg->sn == sn) { 692 | repeat = 1; 693 | break; 694 | } 695 | if (_itimediff(sn, seg->sn) > 0) { 696 | break; 697 | } 698 | } 699 | 700 | if (repeat == 0) { 701 | iqueue_init(&newseg->node); 702 | iqueue_add(&newseg->node, p); 703 | kcp->nrcv_buf++; 704 | } else { 705 | ikcp_segment_delete(kcp, newseg); 706 | } 707 | 708 | #if 0 709 | ikcp_qprint("rcvbuf", &kcp->rcv_buf); 710 | printf("rcv_nxt=%lu\n", kcp->rcv_nxt); 711 | #endif 712 | 713 | // move available data from rcv_buf -> rcv_queue 714 | while (! iqueue_is_empty(&kcp->rcv_buf)) { 715 | IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node); 716 | if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) { 717 | iqueue_del(&seg->node); 718 | kcp->nrcv_buf--; 719 | iqueue_add_tail(&seg->node, &kcp->rcv_queue); 720 | kcp->nrcv_que++; 721 | kcp->rcv_nxt++; 722 | } else { 723 | break; 724 | } 725 | } 726 | 727 | #if 0 728 | ikcp_qprint("queue", &kcp->rcv_queue); 729 | printf("rcv_nxt=%lu\n", kcp->rcv_nxt); 730 | #endif 731 | 732 | #if 1 733 | // printf("snd(buf=%d, queue=%d)\n", kcp->nsnd_buf, kcp->nsnd_que); 734 | // printf("rcv(buf=%d, queue=%d)\n", kcp->nrcv_buf, kcp->nrcv_que); 735 | #endif 736 | } 737 | 738 | 739 | //--------------------------------------------------------------------- 740 | // input data 741 | //--------------------------------------------------------------------- 742 | int ikcp_input(ikcpcb *kcp, const char *data, long size) 743 | { 744 | IUINT32 una = kcp->snd_una; 745 | IUINT32 maxack = 0; 746 | int flag = 0; 747 | 748 | if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) { 749 | ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", size); 750 | } 751 | 752 | if (data == NULL || size < IKCP_OVERHEAD) return -1; 753 | 754 | while (1) { 755 | IUINT32 ts, sn, len, una, conv; 756 | IUINT16 wnd; 757 | IUINT8 cmd, frg; 758 | IKCPSEG *seg; 759 | 760 | if (size < (int)IKCP_OVERHEAD) break; 761 | 762 | data = ikcp_decode32u(data, &conv); 763 | if (conv != kcp->conv) return -1; 764 | 765 | data = ikcp_decode8u(data, &cmd); 766 | data = ikcp_decode8u(data, &frg); 767 | data = ikcp_decode16u(data, &wnd); 768 | data = ikcp_decode32u(data, &ts); 769 | data = ikcp_decode32u(data, &sn); 770 | data = ikcp_decode32u(data, &una); 771 | data = ikcp_decode32u(data, &len); 772 | 773 | size -= IKCP_OVERHEAD; 774 | 775 | if ((long)size < (long)len) return -2; 776 | 777 | if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK && 778 | cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS) 779 | return -3; 780 | 781 | kcp->rmt_wnd = wnd; 782 | ikcp_parse_una(kcp, una); 783 | ikcp_shrink_buf(kcp); 784 | 785 | if (cmd == IKCP_CMD_ACK) { 786 | if (_itimediff(kcp->current, ts) >= 0) { 787 | ikcp_update_ack(kcp, _itimediff(kcp->current, ts)); 788 | } 789 | ikcp_parse_ack(kcp, sn); 790 | ikcp_shrink_buf(kcp); 791 | if (flag == 0) { 792 | flag = 1; 793 | maxack = sn; 794 | } else { 795 | if (_itimediff(sn, maxack) > 0) { 796 | maxack = sn; 797 | } 798 | } 799 | if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) { 800 | ikcp_log(kcp, IKCP_LOG_IN_DATA, 801 | "input ack: sn=%lu rtt=%ld rto=%ld", sn, 802 | (long)_itimediff(kcp->current, ts), 803 | (long)kcp->rx_rto); 804 | } 805 | } 806 | else if (cmd == IKCP_CMD_PUSH) { 807 | if (ikcp_canlog(kcp, IKCP_LOG_IN_DATA)) { 808 | ikcp_log(kcp, IKCP_LOG_IN_DATA, 809 | "input psh: sn=%lu ts=%lu", sn, ts); 810 | } 811 | if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) < 0) { 812 | ikcp_ack_push(kcp, sn, ts); 813 | if (_itimediff(sn, kcp->rcv_nxt) >= 0) { 814 | seg = ikcp_segment_new(kcp, len); 815 | seg->conv = conv; 816 | seg->cmd = cmd; 817 | seg->frg = frg; 818 | seg->wnd = wnd; 819 | seg->ts = ts; 820 | seg->sn = sn; 821 | seg->una = una; 822 | seg->len = len; 823 | 824 | if (len > 0) { 825 | memcpy(seg->data, data, len); 826 | } 827 | 828 | ikcp_parse_data(kcp, seg); 829 | } 830 | } 831 | } 832 | else if (cmd == IKCP_CMD_WASK) { 833 | // ready to send back IKCP_CMD_WINS in ikcp_flush 834 | // tell remote my window size 835 | kcp->probe |= IKCP_ASK_TELL; 836 | if (ikcp_canlog(kcp, IKCP_LOG_IN_PROBE)) { 837 | ikcp_log(kcp, IKCP_LOG_IN_PROBE, "input probe"); 838 | } 839 | } 840 | else if (cmd == IKCP_CMD_WINS) { 841 | // do nothing 842 | if (ikcp_canlog(kcp, IKCP_LOG_IN_WINS)) { 843 | ikcp_log(kcp, IKCP_LOG_IN_WINS, 844 | "input wins: %lu", (IUINT32)(wnd)); 845 | } 846 | } 847 | else { 848 | return -3; 849 | } 850 | 851 | data += len; 852 | size -= len; 853 | } 854 | 855 | if (flag != 0) { 856 | ikcp_parse_fastack(kcp, maxack); 857 | } 858 | 859 | if (_itimediff(kcp->snd_una, una) > 0) { 860 | if (kcp->cwnd < kcp->rmt_wnd) { 861 | IUINT32 mss = kcp->mss; 862 | if (kcp->cwnd < kcp->ssthresh) { 863 | kcp->cwnd++; 864 | kcp->incr += mss; 865 | } else { 866 | if (kcp->incr < mss) kcp->incr = mss; 867 | kcp->incr += (mss * mss) / kcp->incr + (mss / 16); 868 | if ((kcp->cwnd + 1) * mss <= kcp->incr) { 869 | kcp->cwnd++; 870 | } 871 | } 872 | if (kcp->cwnd > kcp->rmt_wnd) { 873 | kcp->cwnd = kcp->rmt_wnd; 874 | kcp->incr = kcp->rmt_wnd * mss; 875 | } 876 | } 877 | } 878 | 879 | return 0; 880 | } 881 | 882 | 883 | //--------------------------------------------------------------------- 884 | // ikcp_encode_seg 885 | //--------------------------------------------------------------------- 886 | static char *ikcp_encode_seg(char *ptr, const IKCPSEG *seg) 887 | { 888 | ptr = ikcp_encode32u(ptr, seg->conv); 889 | ptr = ikcp_encode8u(ptr, (IUINT8)seg->cmd); 890 | ptr = ikcp_encode8u(ptr, (IUINT8)seg->frg); 891 | ptr = ikcp_encode16u(ptr, (IUINT16)seg->wnd); 892 | ptr = ikcp_encode32u(ptr, seg->ts); 893 | ptr = ikcp_encode32u(ptr, seg->sn); 894 | ptr = ikcp_encode32u(ptr, seg->una); 895 | ptr = ikcp_encode32u(ptr, seg->len); 896 | return ptr; 897 | } 898 | 899 | static int ikcp_wnd_unused(const ikcpcb *kcp) 900 | { 901 | if (kcp->nrcv_que < kcp->rcv_wnd) { 902 | return kcp->rcv_wnd - kcp->nrcv_que; 903 | } 904 | return 0; 905 | } 906 | 907 | 908 | //--------------------------------------------------------------------- 909 | // ikcp_flush 910 | //--------------------------------------------------------------------- 911 | void ikcp_flush(ikcpcb *kcp) 912 | { 913 | IUINT32 current = kcp->current; 914 | char *buffer = kcp->buffer; 915 | char *ptr = buffer; 916 | int count, size, i; 917 | IUINT32 resent, cwnd; 918 | IUINT32 rtomin; 919 | struct IQUEUEHEAD *p; 920 | int change = 0; 921 | int lost = 0; 922 | IKCPSEG seg; 923 | 924 | // 'ikcp_update' haven't been called. 925 | if (kcp->updated == 0) return; 926 | 927 | seg.conv = kcp->conv; 928 | seg.cmd = IKCP_CMD_ACK; 929 | seg.frg = 0; 930 | seg.wnd = ikcp_wnd_unused(kcp); 931 | seg.una = kcp->rcv_nxt; 932 | seg.len = 0; 933 | seg.sn = 0; 934 | seg.ts = 0; 935 | 936 | // flush acknowledges 937 | count = kcp->ackcount; 938 | for (i = 0; i < count; i++) { 939 | size = (int)(ptr - buffer); 940 | if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { 941 | ikcp_output(kcp, buffer, size); 942 | ptr = buffer; 943 | } 944 | ikcp_ack_get(kcp, i, &seg.sn, &seg.ts); 945 | ptr = ikcp_encode_seg(ptr, &seg); 946 | } 947 | 948 | kcp->ackcount = 0; 949 | 950 | // probe window size (if remote window size equals zero) 951 | if (kcp->rmt_wnd == 0) { 952 | if (kcp->probe_wait == 0) { 953 | kcp->probe_wait = IKCP_PROBE_INIT; 954 | kcp->ts_probe = kcp->current + kcp->probe_wait; 955 | } 956 | else { 957 | if (_itimediff(kcp->current, kcp->ts_probe) >= 0) { 958 | if (kcp->probe_wait < IKCP_PROBE_INIT) 959 | kcp->probe_wait = IKCP_PROBE_INIT; 960 | kcp->probe_wait += kcp->probe_wait / 2; 961 | if (kcp->probe_wait > IKCP_PROBE_LIMIT) 962 | kcp->probe_wait = IKCP_PROBE_LIMIT; 963 | kcp->ts_probe = kcp->current + kcp->probe_wait; 964 | kcp->probe |= IKCP_ASK_SEND; 965 | } 966 | } 967 | } else { 968 | kcp->ts_probe = 0; 969 | kcp->probe_wait = 0; 970 | } 971 | 972 | // flush window probing commands 973 | if (kcp->probe & IKCP_ASK_SEND) { 974 | seg.cmd = IKCP_CMD_WASK; 975 | size = (int)(ptr - buffer); 976 | if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { 977 | ikcp_output(kcp, buffer, size); 978 | ptr = buffer; 979 | } 980 | ptr = ikcp_encode_seg(ptr, &seg); 981 | } 982 | 983 | // flush window probing commands 984 | if (kcp->probe & IKCP_ASK_TELL) { 985 | seg.cmd = IKCP_CMD_WINS; 986 | size = (int)(ptr - buffer); 987 | if (size + (int)IKCP_OVERHEAD > (int)kcp->mtu) { 988 | ikcp_output(kcp, buffer, size); 989 | ptr = buffer; 990 | } 991 | ptr = ikcp_encode_seg(ptr, &seg); 992 | } 993 | 994 | kcp->probe = 0; 995 | 996 | // calculate window size 997 | cwnd = _imin_(kcp->snd_wnd, kcp->rmt_wnd); 998 | if (kcp->nocwnd == 0) cwnd = _imin_(kcp->cwnd, cwnd); 999 | 1000 | // move data from snd_queue to snd_buf 1001 | while (_itimediff(kcp->snd_nxt, kcp->snd_una + cwnd) < 0) { 1002 | IKCPSEG *newseg; 1003 | if (iqueue_is_empty(&kcp->snd_queue)) break; 1004 | 1005 | newseg = iqueue_entry(kcp->snd_queue.next, IKCPSEG, node); 1006 | 1007 | iqueue_del(&newseg->node); 1008 | iqueue_add_tail(&newseg->node, &kcp->snd_buf); 1009 | kcp->nsnd_que--; 1010 | kcp->nsnd_buf++; 1011 | 1012 | newseg->conv = kcp->conv; 1013 | newseg->cmd = IKCP_CMD_PUSH; 1014 | newseg->wnd = seg.wnd; 1015 | newseg->ts = current; 1016 | newseg->sn = kcp->snd_nxt++; 1017 | newseg->una = kcp->rcv_nxt; 1018 | newseg->resendts = current; 1019 | newseg->rto = kcp->rx_rto; 1020 | newseg->fastack = 0; 1021 | newseg->xmit = 0; 1022 | } 1023 | 1024 | // calculate resent 1025 | resent = (kcp->fastresend > 0)? (IUINT32)kcp->fastresend : 0xffffffff; 1026 | rtomin = (kcp->nodelay == 0)? (kcp->rx_rto >> 3) : 0; 1027 | 1028 | // flush data segments 1029 | for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) { 1030 | IKCPSEG *segment = iqueue_entry(p, IKCPSEG, node); 1031 | int needsend = 0; 1032 | if (segment->xmit == 0) { 1033 | needsend = 1; 1034 | segment->xmit++; 1035 | segment->rto = kcp->rx_rto; 1036 | segment->resendts = current + segment->rto + rtomin; 1037 | } 1038 | else if (_itimediff(current, segment->resendts) >= 0) { 1039 | needsend = 1; 1040 | segment->xmit++; 1041 | kcp->xmit++; 1042 | if (kcp->nodelay == 0) { 1043 | segment->rto += kcp->rx_rto; 1044 | } else { 1045 | segment->rto += kcp->rx_rto / 2; 1046 | } 1047 | segment->resendts = current + segment->rto; 1048 | lost = 1; 1049 | } 1050 | else if (segment->fastack >= resent) { 1051 | needsend = 1; 1052 | segment->xmit++; 1053 | segment->fastack = 0; 1054 | segment->resendts = current + segment->rto; 1055 | change++; 1056 | } 1057 | 1058 | if (needsend) { 1059 | int size, need; 1060 | segment->ts = current; 1061 | segment->wnd = seg.wnd; 1062 | segment->una = kcp->rcv_nxt; 1063 | 1064 | size = (int)(ptr - buffer); 1065 | need = IKCP_OVERHEAD + segment->len; 1066 | 1067 | if (size + need > (int)kcp->mtu) { 1068 | ikcp_output(kcp, buffer, size); 1069 | ptr = buffer; 1070 | } 1071 | 1072 | ptr = ikcp_encode_seg(ptr, segment); 1073 | 1074 | if (segment->len > 0) { 1075 | memcpy(ptr, segment->data, segment->len); 1076 | ptr += segment->len; 1077 | } 1078 | 1079 | if (segment->xmit >= kcp->dead_link) { 1080 | kcp->state = -1; 1081 | } 1082 | } 1083 | } 1084 | 1085 | // flash remain segments 1086 | size = (int)(ptr - buffer); 1087 | if (size > 0) { 1088 | ikcp_output(kcp, buffer, size); 1089 | } 1090 | 1091 | // update ssthresh 1092 | if (change) { 1093 | IUINT32 inflight = kcp->snd_nxt - kcp->snd_una; 1094 | kcp->ssthresh = inflight / 2; 1095 | if (kcp->ssthresh < IKCP_THRESH_MIN) 1096 | kcp->ssthresh = IKCP_THRESH_MIN; 1097 | kcp->cwnd = kcp->ssthresh + resent; 1098 | kcp->incr = kcp->cwnd * kcp->mss; 1099 | } 1100 | 1101 | if (lost) { 1102 | kcp->ssthresh = cwnd / 2; 1103 | if (kcp->ssthresh < IKCP_THRESH_MIN) 1104 | kcp->ssthresh = IKCP_THRESH_MIN; 1105 | kcp->cwnd = 1; 1106 | kcp->incr = kcp->mss; 1107 | } 1108 | 1109 | if (kcp->cwnd < 1) { 1110 | kcp->cwnd = 1; 1111 | kcp->incr = kcp->mss; 1112 | } 1113 | } 1114 | 1115 | 1116 | //--------------------------------------------------------------------- 1117 | // update state (call it repeatedly, every 10ms-100ms), or you can ask 1118 | // ikcp_check when to call it again (without ikcp_input/_send calling). 1119 | // 'current' - current timestamp in millisec. 1120 | //--------------------------------------------------------------------- 1121 | void ikcp_update(ikcpcb *kcp, IUINT32 current) 1122 | { 1123 | IINT32 slap; 1124 | 1125 | kcp->current = current; 1126 | 1127 | if (kcp->updated == 0) { 1128 | kcp->updated = 1; 1129 | kcp->ts_flush = kcp->current; 1130 | } 1131 | 1132 | slap = _itimediff(kcp->current, kcp->ts_flush); 1133 | 1134 | if (slap >= 10000 || slap < -10000) { 1135 | kcp->ts_flush = kcp->current; 1136 | slap = 0; 1137 | } 1138 | 1139 | if (slap >= 0) { 1140 | kcp->ts_flush += kcp->interval; 1141 | if (_itimediff(kcp->current, kcp->ts_flush) >= 0) { 1142 | kcp->ts_flush = kcp->current + kcp->interval; 1143 | } 1144 | ikcp_flush(kcp); 1145 | } 1146 | } 1147 | 1148 | 1149 | //--------------------------------------------------------------------- 1150 | // Determine when should you invoke ikcp_update: 1151 | // returns when you should invoke ikcp_update in millisec, if there 1152 | // is no ikcp_input/_send calling. you can call ikcp_update in that 1153 | // time, instead of call update repeatly. 1154 | // Important to reduce unnacessary ikcp_update invoking. use it to 1155 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 1156 | // or optimize ikcp_update when handling massive kcp connections) 1157 | //--------------------------------------------------------------------- 1158 | IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current) 1159 | { 1160 | IUINT32 ts_flush = kcp->ts_flush; 1161 | IINT32 tm_flush = 0x7fffffff; 1162 | IINT32 tm_packet = 0x7fffffff; 1163 | IUINT32 minimal = 0; 1164 | struct IQUEUEHEAD *p; 1165 | 1166 | if (kcp->updated == 0) { 1167 | return current; 1168 | } 1169 | 1170 | if (_itimediff(current, ts_flush) >= 10000 || 1171 | _itimediff(current, ts_flush) < -10000) { 1172 | ts_flush = current; 1173 | } 1174 | 1175 | if (_itimediff(current, ts_flush) >= 0) { 1176 | return current; 1177 | } 1178 | 1179 | tm_flush = _itimediff(ts_flush, current); 1180 | 1181 | for (p = kcp->snd_buf.next; p != &kcp->snd_buf; p = p->next) { 1182 | const IKCPSEG *seg = iqueue_entry(p, const IKCPSEG, node); 1183 | IINT32 diff = _itimediff(seg->resendts, current); 1184 | if (diff <= 0) { 1185 | return current; 1186 | } 1187 | if (diff < tm_packet) tm_packet = diff; 1188 | } 1189 | 1190 | minimal = (IUINT32)(tm_packet < tm_flush ? tm_packet : tm_flush); 1191 | if (minimal >= kcp->interval) minimal = kcp->interval; 1192 | 1193 | return current + minimal; 1194 | } 1195 | 1196 | 1197 | 1198 | int ikcp_setmtu(ikcpcb *kcp, int mtu) 1199 | { 1200 | char *buffer; 1201 | if (mtu < 50 || mtu < (int)IKCP_OVERHEAD) 1202 | return -1; 1203 | buffer = (char*)ikcp_malloc((mtu + IKCP_OVERHEAD) * 3); 1204 | if (buffer == NULL) 1205 | return -2; 1206 | kcp->mtu = mtu; 1207 | kcp->mss = kcp->mtu - IKCP_OVERHEAD; 1208 | ikcp_free(kcp->buffer); 1209 | kcp->buffer = buffer; 1210 | return 0; 1211 | } 1212 | 1213 | int ikcp_interval(ikcpcb *kcp, int interval) 1214 | { 1215 | if (interval > 5000) interval = 5000; 1216 | else if (interval < 10) interval = 10; 1217 | kcp->interval = interval; 1218 | return 0; 1219 | } 1220 | 1221 | int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc) 1222 | { 1223 | if (nodelay >= 0) { 1224 | kcp->nodelay = nodelay; 1225 | if (nodelay) { 1226 | kcp->rx_minrto = IKCP_RTO_NDL; 1227 | } 1228 | else { 1229 | kcp->rx_minrto = IKCP_RTO_MIN; 1230 | } 1231 | } 1232 | if (interval >= 0) { 1233 | if (interval > 5000) interval = 5000; 1234 | else if (interval < 10) interval = 10; 1235 | kcp->interval = interval; 1236 | } 1237 | if (resend >= 0) { 1238 | kcp->fastresend = resend; 1239 | } 1240 | if (nc >= 0) { 1241 | kcp->nocwnd = nc; 1242 | } 1243 | return 0; 1244 | } 1245 | 1246 | 1247 | int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd) 1248 | { 1249 | if (kcp) { 1250 | if (sndwnd > 0) { 1251 | kcp->snd_wnd = sndwnd; 1252 | } 1253 | if (rcvwnd > 0) { 1254 | kcp->rcv_wnd = rcvwnd; 1255 | } 1256 | } 1257 | return 0; 1258 | } 1259 | 1260 | int ikcp_waitsnd(const ikcpcb *kcp) 1261 | { 1262 | return kcp->nsnd_buf + kcp->nsnd_que; 1263 | } 1264 | 1265 | 1266 | // read conv 1267 | IUINT32 ikcp_getconv(const void *ptr) 1268 | { 1269 | IUINT32 conv; 1270 | ikcp_decode32u((const char*)ptr, &conv); 1271 | return conv; 1272 | } 1273 | 1274 | 1275 | --------------------------------------------------------------------------------