#include "laylink_kcp.h" #include "ikcp.h" #include #include typedef struct laylink_packet { int len; char* data; struct laylink_packet* next; } laylink_packet; struct laylink_kcp { ikcpcb* kcp; laylink_packet* output_head; laylink_packet* output_tail; }; static void laylink_packet_free(laylink_packet* packet) { if (packet == NULL) { return; } free(packet->data); free(packet); } static int laylink_kcp_output(const char* buffer, int len, ikcpcb* kcp, void* user) { (void)kcp; laylink_kcp* session = (laylink_kcp*)user; if (session == NULL || len <= 0) { return -1; } laylink_packet* packet = (laylink_packet*)malloc(sizeof(laylink_packet)); if (packet == NULL) { return -2; } packet->data = (char*)malloc((size_t)len); if (packet->data == NULL) { free(packet); return -3; } memcpy(packet->data, buffer, (size_t)len); packet->len = len; packet->next = NULL; if (session->output_tail != NULL) { session->output_tail->next = packet; } else { session->output_head = packet; } session->output_tail = packet; return 0; } laylink_kcp* laylink_kcp_create(unsigned int conv) { laylink_kcp* session = (laylink_kcp*)calloc(1, sizeof(laylink_kcp)); if (session == NULL) { return NULL; } session->kcp = ikcp_create(conv, session); if (session->kcp == NULL) { free(session); return NULL; } session->kcp->output = laylink_kcp_output; ikcp_nodelay(session->kcp, 1, 10, 2, 1); ikcp_wndsize(session->kcp, 1024, 1024); ikcp_setmtu(session->kcp, 1350); return session; } void laylink_kcp_release(laylink_kcp* session) { if (session == NULL) { return; } laylink_packet* packet = session->output_head; while (packet != NULL) { laylink_packet* next = packet->next; laylink_packet_free(packet); packet = next; } if (session->kcp != NULL) { ikcp_release(session->kcp); } free(session); } int laylink_kcp_nodelay(laylink_kcp* session, int nodelay, int interval, int resend, int nc) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_nodelay(session->kcp, nodelay, interval, resend, nc); } int laylink_kcp_wndsize(laylink_kcp* session, int sndwnd, int rcvwnd) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_wndsize(session->kcp, sndwnd, rcvwnd); } int laylink_kcp_setmtu(laylink_kcp* session, int mtu) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_setmtu(session->kcp, mtu); } int laylink_kcp_send(laylink_kcp* session, const char* buffer, int len) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_send(session->kcp, buffer, len); } int laylink_kcp_input(laylink_kcp* session, const char* buffer, long size) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_input(session->kcp, buffer, size); } void laylink_kcp_update(laylink_kcp* session, unsigned int current) { if (session == NULL || session->kcp == NULL) { return; } ikcp_update(session->kcp, current); } unsigned int laylink_kcp_check(laylink_kcp* session, unsigned int current) { if (session == NULL || session->kcp == NULL) { return current + 10; } return ikcp_check(session->kcp, current); } int laylink_kcp_peeksize(laylink_kcp* session) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_peeksize(session->kcp); } int laylink_kcp_recv(laylink_kcp* session, char* buffer, int len) { if (session == NULL || session->kcp == NULL) { return -1; } return ikcp_recv(session->kcp, buffer, len); } void laylink_kcp_flush(laylink_kcp* session) { if (session == NULL || session->kcp == NULL) { return; } ikcp_flush(session->kcp); } int laylink_kcp_waitsnd(laylink_kcp* session) { if (session == NULL || session->kcp == NULL) { return 0; } return ikcp_waitsnd(session->kcp); } int laylink_kcp_pending_output_size(laylink_kcp* session) { if (session == NULL || session->output_head == NULL) { return 0; } return session->output_head->len; } int laylink_kcp_pop_output(laylink_kcp* session, char* buffer, int len) { if (session == NULL || session->output_head == NULL) { return 0; } laylink_packet* packet = session->output_head; if (len < packet->len) { return -packet->len; } memcpy(buffer, packet->data, (size_t)packet->len); session->output_head = packet->next; if (session->output_head == NULL) { session->output_tail = NULL; } int packet_len = packet->len; laylink_packet_free(packet); return packet_len; }