initial commit
This commit is contained in:
21
third_party/libhv/event/kcp/LICENSE
vendored
Executable file
21
third_party/libhv/event/kcp/LICENSE
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Lin Wei (skywind3000 at gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
150
third_party/libhv/event/kcp/hkcp.c
vendored
Executable file
150
third_party/libhv/event/kcp/hkcp.c
vendored
Executable file
@@ -0,0 +1,150 @@
|
||||
#include "hkcp.h"
|
||||
|
||||
#if WITH_KCP
|
||||
|
||||
#include "hevent.h"
|
||||
#include "hlog.h"
|
||||
#include "hthread.h"
|
||||
|
||||
static kcp_setting_t s_kcp_setting;
|
||||
|
||||
static int __kcp_output(const char* buf, int len, ikcpcb* ikcp, void* userdata) {
|
||||
// printf("ikcp_output len=%d\n", len);
|
||||
rudp_entry_t* rudp = (rudp_entry_t*)userdata;
|
||||
assert(rudp != NULL && rudp->io != NULL);
|
||||
int nsend = sendto(rudp->io->fd, buf, len, 0, &rudp->addr.sa, SOCKADDR_LEN(&rudp->addr));
|
||||
// printf("sendto nsend=%d\n", nsend);
|
||||
return nsend;
|
||||
}
|
||||
|
||||
static void __kcp_update_timer_cb(htimer_t* timer) {
|
||||
rudp_entry_t* rudp = (rudp_entry_t*)timer->privdata;
|
||||
assert(rudp != NULL && rudp->io != NULL && rudp->kcp.ikcp != NULL);
|
||||
ikcp_update(rudp->kcp.ikcp, (IUINT32)(rudp->io->loop->cur_hrtime / 1000));
|
||||
}
|
||||
|
||||
void kcp_release(kcp_t* kcp) {
|
||||
if (kcp->ikcp == NULL) return;
|
||||
if (kcp->update_timer) {
|
||||
htimer_del(kcp->update_timer);
|
||||
kcp->update_timer = NULL;
|
||||
}
|
||||
HV_FREE(kcp->readbuf.base);
|
||||
kcp->readbuf.len = 0;
|
||||
// printf("ikcp_release ikcp=%p\n", kcp->ikcp);
|
||||
ikcp_release(kcp->ikcp);
|
||||
kcp->ikcp = NULL;
|
||||
}
|
||||
|
||||
int hio_set_kcp(hio_t* io, kcp_setting_t* setting) {
|
||||
io->io_type = HIO_TYPE_KCP;
|
||||
io->kcp_setting = setting;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kcp_t* hio_get_kcp(hio_t* io, uint32_t conv) {
|
||||
rudp_entry_t* rudp = hio_get_rudp(io);
|
||||
assert(rudp != NULL);
|
||||
kcp_t* kcp = &rudp->kcp;
|
||||
if (kcp->ikcp != NULL) return kcp;
|
||||
if (io->kcp_setting == NULL) {
|
||||
io->kcp_setting = &s_kcp_setting;
|
||||
}
|
||||
kcp_setting_t* setting = io->kcp_setting;
|
||||
kcp->ikcp = ikcp_create(conv, rudp);
|
||||
// printf("ikcp_create conv=%u ikcp=%p\n", conv, kcp->ikcp);
|
||||
kcp->ikcp->output = __kcp_output;
|
||||
kcp->conv = conv;
|
||||
if (setting->interval > 0) {
|
||||
ikcp_nodelay(kcp->ikcp, setting->nodelay, setting->interval, setting->fastresend, setting->nocwnd);
|
||||
}
|
||||
if (setting->sndwnd > 0 && setting->rcvwnd > 0) {
|
||||
ikcp_wndsize(kcp->ikcp, setting->sndwnd, setting->rcvwnd);
|
||||
}
|
||||
if (setting->mtu > 0) {
|
||||
ikcp_setmtu(kcp->ikcp, setting->mtu);
|
||||
}
|
||||
if (kcp->update_timer == NULL) {
|
||||
int update_interval = setting->update_interval;
|
||||
if (update_interval == 0) {
|
||||
update_interval = DEFAULT_KCP_UPDATE_INTERVAL;
|
||||
}
|
||||
kcp->update_timer = htimer_add(io->loop, __kcp_update_timer_cb, update_interval, INFINITE);
|
||||
kcp->update_timer->privdata = rudp;
|
||||
}
|
||||
// NOTE: alloc kcp->readbuf when hio_read_kcp
|
||||
return kcp;
|
||||
}
|
||||
|
||||
static void hio_write_kcp_event_cb(hevent_t* ev) {
|
||||
hio_t* io = (hio_t*)ev->userdata;
|
||||
hbuf_t* buf = (hbuf_t*)ev->privdata;
|
||||
|
||||
hio_write_kcp(io, buf->base, buf->len);
|
||||
|
||||
HV_FREE(buf);
|
||||
}
|
||||
|
||||
static int hio_write_kcp_async(hio_t* io, const void* data, size_t len) {
|
||||
hbuf_t* buf = NULL;
|
||||
HV_ALLOC(buf, sizeof(hbuf_t) + len);
|
||||
buf->base = (char*)buf + sizeof(hbuf_t);
|
||||
buf->len = len;
|
||||
memcpy(buf->base, data, len);
|
||||
|
||||
hevent_t ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.cb = hio_write_kcp_event_cb;
|
||||
ev.userdata = io;
|
||||
ev.privdata = buf;
|
||||
hloop_post_event(io->loop, &ev);
|
||||
return len;
|
||||
}
|
||||
|
||||
int hio_write_kcp(hio_t* io, const void* buf, size_t len) {
|
||||
if (hv_gettid() != io->loop->tid) {
|
||||
return hio_write_kcp_async(io, buf, len);
|
||||
}
|
||||
IUINT32 conv = io->kcp_setting ? io->kcp_setting->conv : 0;
|
||||
kcp_t* kcp = hio_get_kcp(io, conv);
|
||||
// printf("hio_write_kcp conv=%u=%u\n", conv, kcp->conv);
|
||||
int nsend = ikcp_send(kcp->ikcp, (const char*)buf, len);
|
||||
// printf("ikcp_send len=%d nsend=%d\n", (int)len, nsend);
|
||||
if (nsend < 0) {
|
||||
hloge("ikcp_send error: %d", nsend);
|
||||
return nsend;
|
||||
}
|
||||
ikcp_update(kcp->ikcp, (IUINT32)io->loop->cur_hrtime / 1000);
|
||||
return len;
|
||||
}
|
||||
|
||||
int hio_read_kcp (hio_t* io, void* buf, int readbytes) {
|
||||
IUINT32 conv = ikcp_getconv(buf);
|
||||
kcp_t* kcp = hio_get_kcp(io, conv);
|
||||
// printf("hio_read_kcp conv=%u=%u\n", conv, kcp->conv);
|
||||
if (kcp->conv != conv) {
|
||||
hloge("recv invalid kcp packet!");
|
||||
hio_close_rudp(io, io->peeraddr);
|
||||
return -1;
|
||||
}
|
||||
// printf("ikcp_input len=%d\n", readbytes);
|
||||
int ret = ikcp_input(kcp->ikcp, (const char*)buf, readbytes);
|
||||
// printf("ikcp_input ret=%d\n", ret);
|
||||
if (ret != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (kcp->readbuf.base == NULL || kcp->readbuf.len == 0) {
|
||||
kcp->readbuf.len = DEFAULT_KCP_READ_BUFSIZE;
|
||||
HV_ALLOC(kcp->readbuf.base, kcp->readbuf.len);
|
||||
}
|
||||
while (1) {
|
||||
int nrecv = ikcp_recv(kcp->ikcp, kcp->readbuf.base, kcp->readbuf.len);
|
||||
// printf("ikcp_recv nrecv=%d\n", nrecv);
|
||||
if (nrecv < 0) break;
|
||||
hio_read_cb(io, kcp->readbuf.base, nrecv);
|
||||
ret += nrecv;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
30
third_party/libhv/event/kcp/hkcp.h
vendored
Executable file
30
third_party/libhv/event/kcp/hkcp.h
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#ifndef HV_KCP_H_
|
||||
#define HV_KCP_H_
|
||||
|
||||
#include "hloop.h"
|
||||
|
||||
#if WITH_KCP
|
||||
|
||||
#include "ikcp.h"
|
||||
#include "hbuf.h"
|
||||
|
||||
#define DEFAULT_KCP_UPDATE_INTERVAL 10 // ms
|
||||
#define DEFAULT_KCP_READ_BUFSIZE 1400
|
||||
|
||||
typedef struct kcp_s {
|
||||
ikcpcb* ikcp;
|
||||
uint32_t conv;
|
||||
htimer_t* update_timer;
|
||||
hbuf_t readbuf;
|
||||
} kcp_t;
|
||||
|
||||
// NOTE: kcp_create in hio_get_kcp
|
||||
void kcp_release(kcp_t* kcp);
|
||||
|
||||
kcp_t* hio_get_kcp (hio_t* io, uint32_t conv);
|
||||
int hio_read_kcp (hio_t* io, void* buf, int readbytes);
|
||||
int hio_write_kcp(hio_t* io, const void* buf, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HV_KCP_H_
|
||||
1299
third_party/libhv/event/kcp/ikcp.c
vendored
Executable file
1299
third_party/libhv/event/kcp/ikcp.c
vendored
Executable file
File diff suppressed because it is too large
Load Diff
416
third_party/libhv/event/kcp/ikcp.h
vendored
Executable file
416
third_party/libhv/event/kcp/ikcp.h
vendored
Executable file
@@ -0,0 +1,416 @@
|
||||
//=====================================================================
|
||||
//
|
||||
// KCP - A Better ARQ Protocol Implementation
|
||||
// skywind3000 (at) gmail.com, 2010-2011
|
||||
//
|
||||
// Features:
|
||||
// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
|
||||
// + Maximum RTT reduce three times vs tcp.
|
||||
// + Lightweight, distributed as a single source file.
|
||||
//
|
||||
//=====================================================================
|
||||
#ifndef __IKCP_H__
|
||||
#define __IKCP_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// 32BIT INTEGER DEFINITION
|
||||
//=====================================================================
|
||||
#ifndef __INTEGER_32_BITS__
|
||||
#define __INTEGER_32_BITS__
|
||||
#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \
|
||||
defined(_M_AMD64)
|
||||
typedef unsigned int ISTDUINT32;
|
||||
typedef int ISTDINT32;
|
||||
#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \
|
||||
defined(__i386) || defined(_M_X86)
|
||||
typedef unsigned long ISTDUINT32;
|
||||
typedef long ISTDINT32;
|
||||
#elif defined(__MACOS__)
|
||||
typedef UInt32 ISTDUINT32;
|
||||
typedef SInt32 ISTDINT32;
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <sys/types.h>
|
||||
typedef u_int32_t ISTDUINT32;
|
||||
typedef int32_t ISTDINT32;
|
||||
#elif defined(__BEOS__)
|
||||
#include <sys/inttypes.h>
|
||||
typedef u_int32_t ISTDUINT32;
|
||||
typedef int32_t ISTDINT32;
|
||||
#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__))
|
||||
typedef unsigned __int32 ISTDUINT32;
|
||||
typedef __int32 ISTDINT32;
|
||||
#elif defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
typedef uint32_t ISTDUINT32;
|
||||
typedef int32_t ISTDINT32;
|
||||
#else
|
||||
typedef unsigned long ISTDUINT32;
|
||||
typedef long ISTDINT32;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// Integer Definition
|
||||
//=====================================================================
|
||||
#ifndef __IINT8_DEFINED
|
||||
#define __IINT8_DEFINED
|
||||
typedef char IINT8;
|
||||
#endif
|
||||
|
||||
#ifndef __IUINT8_DEFINED
|
||||
#define __IUINT8_DEFINED
|
||||
typedef unsigned char IUINT8;
|
||||
#endif
|
||||
|
||||
#ifndef __IUINT16_DEFINED
|
||||
#define __IUINT16_DEFINED
|
||||
typedef unsigned short IUINT16;
|
||||
#endif
|
||||
|
||||
#ifndef __IINT16_DEFINED
|
||||
#define __IINT16_DEFINED
|
||||
typedef short IINT16;
|
||||
#endif
|
||||
|
||||
#ifndef __IINT32_DEFINED
|
||||
#define __IINT32_DEFINED
|
||||
typedef ISTDINT32 IINT32;
|
||||
#endif
|
||||
|
||||
#ifndef __IUINT32_DEFINED
|
||||
#define __IUINT32_DEFINED
|
||||
typedef ISTDUINT32 IUINT32;
|
||||
#endif
|
||||
|
||||
#ifndef __IINT64_DEFINED
|
||||
#define __IINT64_DEFINED
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 IINT64;
|
||||
#else
|
||||
typedef long long IINT64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __IUINT64_DEFINED
|
||||
#define __IUINT64_DEFINED
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef unsigned __int64 IUINT64;
|
||||
#else
|
||||
typedef unsigned long long IUINT64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
#if defined(__GNUC__)
|
||||
|
||||
#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
|
||||
#define INLINE __inline__ __attribute__((always_inline))
|
||||
#else
|
||||
#define INLINE __inline__
|
||||
#endif
|
||||
|
||||
#elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__))
|
||||
#define INLINE __inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (!defined(__cplusplus)) && (!defined(inline))
|
||||
#define inline INLINE
|
||||
#endif
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// QUEUE DEFINITION
|
||||
//=====================================================================
|
||||
#ifndef __IQUEUE_DEF__
|
||||
#define __IQUEUE_DEF__
|
||||
|
||||
struct IQUEUEHEAD {
|
||||
struct IQUEUEHEAD *next, *prev;
|
||||
};
|
||||
|
||||
typedef struct IQUEUEHEAD iqueue_head;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// queue init
|
||||
//---------------------------------------------------------------------
|
||||
#define IQUEUE_HEAD_INIT(name) { &(name), &(name) }
|
||||
#define IQUEUE_HEAD(name) \
|
||||
struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
|
||||
|
||||
#define IQUEUE_INIT(ptr) ( \
|
||||
(ptr)->next = (ptr), (ptr)->prev = (ptr))
|
||||
|
||||
#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
|
||||
#define ICONTAINEROF(ptr, type, member) ( \
|
||||
(type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )
|
||||
|
||||
#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// queue operation
|
||||
//---------------------------------------------------------------------
|
||||
#define IQUEUE_ADD(node, head) ( \
|
||||
(node)->prev = (head), (node)->next = (head)->next, \
|
||||
(head)->next->prev = (node), (head)->next = (node))
|
||||
|
||||
#define IQUEUE_ADD_TAIL(node, head) ( \
|
||||
(node)->prev = (head)->prev, (node)->next = (head), \
|
||||
(head)->prev->next = (node), (head)->prev = (node))
|
||||
|
||||
#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
|
||||
|
||||
#define IQUEUE_DEL(entry) (\
|
||||
(entry)->next->prev = (entry)->prev, \
|
||||
(entry)->prev->next = (entry)->next, \
|
||||
(entry)->next = 0, (entry)->prev = 0)
|
||||
|
||||
#define IQUEUE_DEL_INIT(entry) do { \
|
||||
IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0)
|
||||
|
||||
#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
|
||||
|
||||
#define iqueue_init IQUEUE_INIT
|
||||
#define iqueue_entry IQUEUE_ENTRY
|
||||
#define iqueue_add IQUEUE_ADD
|
||||
#define iqueue_add_tail IQUEUE_ADD_TAIL
|
||||
#define iqueue_del IQUEUE_DEL
|
||||
#define iqueue_del_init IQUEUE_DEL_INIT
|
||||
#define iqueue_is_empty IQUEUE_IS_EMPTY
|
||||
|
||||
#define IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) \
|
||||
for ((iterator) = iqueue_entry((head)->next, TYPE, MEMBER); \
|
||||
&((iterator)->MEMBER) != (head); \
|
||||
(iterator) = iqueue_entry((iterator)->MEMBER.next, TYPE, MEMBER))
|
||||
|
||||
#define iqueue_foreach(iterator, head, TYPE, MEMBER) \
|
||||
IQUEUE_FOREACH(iterator, head, TYPE, MEMBER)
|
||||
|
||||
#define iqueue_foreach_entry(pos, head) \
|
||||
for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next )
|
||||
|
||||
|
||||
#define __iqueue_splice(list, head) do { \
|
||||
iqueue_head *first = (list)->next, *last = (list)->prev; \
|
||||
iqueue_head *at = (head)->next; \
|
||||
(first)->prev = (head), (head)->next = (first); \
|
||||
(last)->next = (at), (at)->prev = (last); } while (0)
|
||||
|
||||
#define iqueue_splice(list, head) do { \
|
||||
if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0)
|
||||
|
||||
#define iqueue_splice_init(list, head) do { \
|
||||
iqueue_splice(list, head); iqueue_init(list); } while (0)
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4311)
|
||||
#pragma warning(disable:4312)
|
||||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// BYTE ORDER & ALIGNMENT
|
||||
//---------------------------------------------------------------------
|
||||
#ifndef IWORDS_BIG_ENDIAN
|
||||
#ifdef _BIG_ENDIAN_
|
||||
#if _BIG_ENDIAN_
|
||||
#define IWORDS_BIG_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
#ifndef IWORDS_BIG_ENDIAN
|
||||
#if defined(__hppa__) || \
|
||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
||||
(defined(__MIPS__) && defined(__MIPSEB__)) || \
|
||||
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
|
||||
defined(__sparc__) || defined(__powerpc__) || \
|
||||
defined(__mc68000__) || defined(__s390x__) || defined(__s390__)
|
||||
#define IWORDS_BIG_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
#ifndef IWORDS_BIG_ENDIAN
|
||||
#define IWORDS_BIG_ENDIAN 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IWORDS_MUST_ALIGN
|
||||
#if defined(__i386__) || defined(__i386) || defined(_i386_)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#elif defined(_M_IX86) || defined(_X86_) || defined(__x86_64__)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#elif defined(__amd64) || defined(__amd64__)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#else
|
||||
#define IWORDS_MUST_ALIGN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//=====================================================================
|
||||
// SEGMENT
|
||||
//=====================================================================
|
||||
struct IKCPSEG
|
||||
{
|
||||
struct IQUEUEHEAD node;
|
||||
IUINT32 conv;
|
||||
IUINT32 cmd;
|
||||
IUINT32 frg;
|
||||
IUINT32 wnd;
|
||||
IUINT32 ts;
|
||||
IUINT32 sn;
|
||||
IUINT32 una;
|
||||
IUINT32 len;
|
||||
IUINT32 resendts;
|
||||
IUINT32 rto;
|
||||
IUINT32 fastack;
|
||||
IUINT32 xmit;
|
||||
char data[1];
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// IKCPCB
|
||||
//---------------------------------------------------------------------
|
||||
struct IKCPCB
|
||||
{
|
||||
IUINT32 conv, mtu, mss, state;
|
||||
IUINT32 snd_una, snd_nxt, rcv_nxt;
|
||||
IUINT32 ts_recent, ts_lastack, ssthresh;
|
||||
IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto;
|
||||
IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe;
|
||||
IUINT32 current, interval, ts_flush, xmit;
|
||||
IUINT32 nrcv_buf, nsnd_buf;
|
||||
IUINT32 nrcv_que, nsnd_que;
|
||||
IUINT32 nodelay, updated;
|
||||
IUINT32 ts_probe, probe_wait;
|
||||
IUINT32 dead_link, incr;
|
||||
struct IQUEUEHEAD snd_queue;
|
||||
struct IQUEUEHEAD rcv_queue;
|
||||
struct IQUEUEHEAD snd_buf;
|
||||
struct IQUEUEHEAD rcv_buf;
|
||||
IUINT32 *acklist;
|
||||
IUINT32 ackcount;
|
||||
IUINT32 ackblock;
|
||||
void *user;
|
||||
char *buffer;
|
||||
int fastresend;
|
||||
int fastlimit;
|
||||
int nocwnd, stream;
|
||||
int logmask;
|
||||
int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);
|
||||
void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);
|
||||
};
|
||||
|
||||
|
||||
typedef struct IKCPCB ikcpcb;
|
||||
|
||||
#define IKCP_LOG_OUTPUT 1
|
||||
#define IKCP_LOG_INPUT 2
|
||||
#define IKCP_LOG_SEND 4
|
||||
#define IKCP_LOG_RECV 8
|
||||
#define IKCP_LOG_IN_DATA 16
|
||||
#define IKCP_LOG_IN_ACK 32
|
||||
#define IKCP_LOG_IN_PROBE 64
|
||||
#define IKCP_LOG_IN_WINS 128
|
||||
#define IKCP_LOG_OUT_DATA 256
|
||||
#define IKCP_LOG_OUT_ACK 512
|
||||
#define IKCP_LOG_OUT_PROBE 1024
|
||||
#define IKCP_LOG_OUT_WINS 2048
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// create a new kcp control object, 'conv' must equal in two endpoint
|
||||
// from the same connection. 'user' will be passed to the output callback
|
||||
// output callback can be setup like this: 'kcp->output = my_udp_output'
|
||||
ikcpcb* ikcp_create(IUINT32 conv, void *user);
|
||||
|
||||
// release kcp control object
|
||||
void ikcp_release(ikcpcb *kcp);
|
||||
|
||||
// set output callback, which will be invoked by kcp
|
||||
void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
|
||||
ikcpcb *kcp, void *user));
|
||||
|
||||
// user/upper level recv: returns size, returns below zero for EAGAIN
|
||||
int ikcp_recv(ikcpcb *kcp, char *buffer, int len);
|
||||
|
||||
// user/upper level send, returns below zero for error
|
||||
int ikcp_send(ikcpcb *kcp, const char *buffer, int len);
|
||||
|
||||
// update state (call it repeatedly, every 10ms-100ms), or you can ask
|
||||
// ikcp_check when to call it again (without ikcp_input/_send calling).
|
||||
// 'current' - current timestamp in millisec.
|
||||
void ikcp_update(ikcpcb *kcp, IUINT32 current);
|
||||
|
||||
// Determine when should you invoke ikcp_update:
|
||||
// returns when you should invoke ikcp_update in millisec, if there
|
||||
// is no ikcp_input/_send calling. you can call ikcp_update in that
|
||||
// time, instead of call update repeatly.
|
||||
// Important to reduce unnacessary ikcp_update invoking. use it to
|
||||
// schedule ikcp_update (eg. implementing an epoll-like mechanism,
|
||||
// or optimize ikcp_update when handling massive kcp connections)
|
||||
IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current);
|
||||
|
||||
// when you received a low level packet (eg. UDP packet), call it
|
||||
int ikcp_input(ikcpcb *kcp, const char *data, long size);
|
||||
|
||||
// flush pending data
|
||||
void ikcp_flush(ikcpcb *kcp);
|
||||
|
||||
// check the size of next message in the recv queue
|
||||
int ikcp_peeksize(const ikcpcb *kcp);
|
||||
|
||||
// change MTU size, default is 1400
|
||||
int ikcp_setmtu(ikcpcb *kcp, int mtu);
|
||||
|
||||
// set maximum window size: sndwnd=32, rcvwnd=32 by default
|
||||
int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
|
||||
|
||||
// get how many packet is waiting to be sent
|
||||
int ikcp_waitsnd(const ikcpcb *kcp);
|
||||
|
||||
// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
|
||||
// nodelay: 0:disable(default), 1:enable
|
||||
// interval: internal update timer interval in millisec, default is 100ms
|
||||
// resend: 0:disable fast resend(default), 1:enable fast resend
|
||||
// nc: 0:normal congestion control(default), 1:disable congestion control
|
||||
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc);
|
||||
|
||||
|
||||
void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
|
||||
|
||||
// setup allocator
|
||||
void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*));
|
||||
|
||||
// read conv
|
||||
IUINT32 ikcp_getconv(const void *ptr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user