186 lines
4.8 KiB
C
186 lines
4.8 KiB
C
/**
|
|
* @file kcp_server.c
|
|
* @author windows
|
|
* @brief usbip KCP port
|
|
* @version 0.1
|
|
* @date 2021-10-08
|
|
*
|
|
* @copyright Copyright (c) 2021
|
|
*
|
|
*/
|
|
|
|
#include "main/kcp_server.h"
|
|
#include "main/usbip_server.h"
|
|
#include "main/wifi_configuration.h"
|
|
|
|
#include "components/kcp/ikcp.h"
|
|
#include "components/kcp/ikcp_util.h"
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/event_groups.h"
|
|
#include "esp_system.h"
|
|
#include "esp_wifi.h"
|
|
#include "esp_event_loop.h"
|
|
#include "esp_log.h"
|
|
|
|
|
|
#include "lwip/err.h"
|
|
#include "lwip/sockets.h"
|
|
#include "lwip/sys.h"
|
|
#include <lwip/netdb.h>
|
|
|
|
extern TaskHandle_t kDAPTaskHandle;
|
|
extern int kRestartDAPHandle;
|
|
extern int kSock;
|
|
extern uint8_t kState;
|
|
|
|
static struct sockaddr_in client_addr = { 0 };
|
|
static char kcp_buffer[MTU_SIZE];
|
|
static ikcpcb *kcp1 = NULL;
|
|
|
|
|
|
static void set_non_blocking(int sockfd) {
|
|
int flag = fcntl(sockfd, F_GETFL, 0);
|
|
if (flag < 0) {
|
|
os_printf("fcntl F_GETFL fail\n");
|
|
return;
|
|
}
|
|
if (fcntl(sockfd, F_SETFL, flag | O_NONBLOCK) < 0) {
|
|
os_printf("fcntl F_SETFL fail\n");
|
|
}
|
|
}
|
|
|
|
static int udp_output(const char *buf, int len, ikcpcb *kcp, void *user)
|
|
{
|
|
int ret = -1;
|
|
int time = 10;
|
|
// Unfortunately, esp8266 often fails due to lack of memory
|
|
while (ret < 0) {
|
|
ret = sendto(kSock, buf, len, 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
|
|
if (ret < 0) {
|
|
// os_printf("fail to send, retry\r\n");
|
|
int errcode = errno;
|
|
if (errno != ENOMEM)
|
|
os_printf("unknown errcode %d\r\n", errcode);
|
|
vTaskDelay(pdMS_TO_TICKS(time));
|
|
time += 10;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int kcp_network_send(const char *buffer, int len) {
|
|
ikcp_send(kcp1, buffer, len);
|
|
ikcp_flush(kcp1);
|
|
return 0;
|
|
}
|
|
|
|
void kcp_server_task()
|
|
{
|
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
|
|
while (1) {
|
|
kSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
|
if (kSock < 0) {
|
|
os_printf("Unable to create socket: errno %d", errno);
|
|
break;
|
|
}
|
|
os_printf("Socket created\r\n");
|
|
|
|
set_non_blocking(kSock);
|
|
|
|
|
|
struct sockaddr_in server_addr;
|
|
memset(&server_addr, 0, sizeof(server_addr));
|
|
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
server_addr.sin_family = AF_INET;
|
|
server_addr.sin_port = htons(PORT);
|
|
|
|
socklen_t socklen = sizeof(client_addr);
|
|
|
|
|
|
int err = bind(kSock, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
|
if (err < 0) {
|
|
os_printf("Socket unable to bind: errno %d\r\n", errno);
|
|
}
|
|
os_printf("Socket binded\r\n");
|
|
|
|
// KCP init
|
|
if (kcp1 == NULL) {
|
|
kcp1 = ikcp_create(1, (void *)0);
|
|
}
|
|
if (kcp1 == NULL) {
|
|
os_printf("can not create kcp control block\r\n");
|
|
break;
|
|
}
|
|
kcp1->output = udp_output;
|
|
|
|
ikcp_wndsize(kcp1, 4096, 4096);
|
|
|
|
ikcp_nodelay(kcp1, 2, 2, 2, 1); // set fast mode
|
|
kcp1->interval = 0;
|
|
kcp1->rx_minrto = 1;
|
|
kcp1->fastresend = 1;
|
|
|
|
ikcp_setmtu(kcp1, 768);
|
|
|
|
|
|
|
|
int ret = -1;
|
|
// KCP task main loop
|
|
while (1) {
|
|
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1)); // we wanna sleep absolute time
|
|
ikcp_update(kcp1, iclock());
|
|
|
|
// recv data from udp
|
|
while (1) {
|
|
ret = recvfrom(kSock, kcp_buffer, MTU_SIZE, 0, (struct sockaddr *)&client_addr, &socklen);
|
|
if (ret < 0) {
|
|
break;
|
|
}
|
|
ikcp_input(kcp1, kcp_buffer, ret);
|
|
}
|
|
|
|
// recv data from kdp
|
|
while (1) {
|
|
ret = ikcp_recv(kcp1, kcp_buffer, MTU_SIZE);
|
|
if (ret < 0) {
|
|
break;
|
|
}
|
|
// recv user data, then handle it
|
|
switch (kState)
|
|
{
|
|
case EMULATING:
|
|
emulate((uint8_t *)kcp_buffer, ret);
|
|
break;
|
|
|
|
case ACCEPTING:
|
|
kState = ATTACHING;
|
|
case ATTACHING:
|
|
attach((uint8_t *)kcp_buffer, ret);
|
|
break;
|
|
|
|
default:
|
|
os_printf("unkonw kstate!\r\n");
|
|
}
|
|
}
|
|
}
|
|
if (kcp1) {
|
|
ikcp_release(kcp1);
|
|
}
|
|
if (kSock != -1) {
|
|
os_printf("Shutting down socket and restarting...\r\n");
|
|
shutdown(kSock, 0);
|
|
close(kSock);
|
|
|
|
if (kState == EMULATING)
|
|
kState = ACCEPTING;
|
|
// Restart DAP Handle
|
|
kRestartDAPHandle = 1;
|
|
if (kDAPTaskHandle)
|
|
xTaskNotifyGive(kDAPTaskHandle);
|
|
}
|
|
}
|
|
vTaskDelete(NULL);
|
|
} |