laylink/native/kcp/laylink_kcp.c
2026-05-30 18:09:09 +08:00

201 lines
4.8 KiB
C

#include "laylink_kcp.h"
#include "ikcp.h"
#include <stdlib.h>
#include <string.h>
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;
}