|
|
|
|
@ -18,7 +18,6 @@
|
|
|
|
|
#include "../lib/debug_config.h" |
|
|
|
|
#include "../lib/mem.h" |
|
|
|
|
|
|
|
|
|
#define ECHO_PORT 19991 |
|
|
|
|
#define TIMEOUT_MS 8000 |
|
|
|
|
#define PAYLOAD_SIZE 64 |
|
|
|
|
|
|
|
|
|
@ -30,12 +29,7 @@ static uint8_t send_buf[PAYLOAD_SIZE];
|
|
|
|
|
static void* timeout_id = NULL; |
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
static void echo_server(void) { |
|
|
|
|
int srv = socket(AF_INET, SOCK_STREAM, 0); |
|
|
|
|
if (srv < 0) _exit(1); |
|
|
|
|
int opt = 1; setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); |
|
|
|
|
struct sockaddr_in a = {.sin_family = AF_INET, .sin_port = htons(ECHO_PORT), .sin_addr.s_addr = inet_addr("127.0.0.1")}; |
|
|
|
|
if (bind(srv, (struct sockaddr*)&a, sizeof(a)) < 0 || listen(srv, 1) < 0) { close(srv); _exit(1); } |
|
|
|
|
static void echo_server(socket_t srv) { |
|
|
|
|
int cli = accept(srv, NULL, NULL); |
|
|
|
|
if (cli < 0) { close(srv); _exit(1); } |
|
|
|
|
uint8_t buf[8192]; ssize_t n; |
|
|
|
|
@ -62,6 +56,7 @@ static int push_write(struct tcp_conn* tc, const uint8_t* data, size_t len) {
|
|
|
|
|
|
|
|
|
|
static void timeout_cb(void* arg) { |
|
|
|
|
(void)arg; |
|
|
|
|
timeout_id = NULL; |
|
|
|
|
printf("[FAIL] timeout\n"); |
|
|
|
|
g_done = -1; |
|
|
|
|
} |
|
|
|
|
@ -69,33 +64,47 @@ static void timeout_cb(void* arg) {
|
|
|
|
|
int main(void) { |
|
|
|
|
debug_config_init(); |
|
|
|
|
debug_set_level(DEBUG_LEVEL_WARN); |
|
|
|
|
struct UASYNC* ua = NULL; |
|
|
|
|
struct tcp_conn* tc = NULL; |
|
|
|
|
socket_t sock = SOCKET_INVALID; |
|
|
|
|
uint16_t echo_port = 0; |
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
printf("[SKIP] test_tcp_proxy_server — fork() not available on Windows\n"); |
|
|
|
|
return 0; |
|
|
|
|
#else |
|
|
|
|
socket_t listener = socket(AF_INET, SOCK_STREAM, 0); |
|
|
|
|
if (listener == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "echo socket: %s", strerror(errno)); return 1; } |
|
|
|
|
struct sockaddr_in a = {.sin_family = AF_INET, .sin_addr.s_addr = inet_addr("127.0.0.1")}; |
|
|
|
|
if (bind(listener, (struct sockaddr*)&a, sizeof(a)) < 0 || listen(listener, 1) < 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "echo listen: %s", strerror(errno)); socket_close_wrapper(listener); return 1; |
|
|
|
|
} |
|
|
|
|
echo_port = socket_get_bound_port(listener); |
|
|
|
|
if (!echo_port) { socket_close_wrapper(listener); return 1; } |
|
|
|
|
echo_pid = fork(); |
|
|
|
|
if (echo_pid == 0) { echo_server(); _exit(0); } |
|
|
|
|
usleep(50000); // даём серверу запуститься
|
|
|
|
|
if (echo_pid < 0) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "echo fork: %s", strerror(errno)); socket_close_wrapper(listener); return 1; } |
|
|
|
|
if (echo_pid == 0) { echo_server(listener); _exit(0); } |
|
|
|
|
socket_close_wrapper(listener); // Слушатель уже готов, дочерний процесс сохраняет его fd и порт.
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
struct UASYNC* ua = uasync_create(); |
|
|
|
|
if (!ua) return 1; |
|
|
|
|
ua = uasync_create(); |
|
|
|
|
if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_SYS, "echo test: uasync create failed"); goto done; } |
|
|
|
|
|
|
|
|
|
timeout_id = uasync_set_timeout(ua, TIMEOUT_MS * 10, NULL, timeout_cb, "timeout"); |
|
|
|
|
if (!timeout_id) { DEBUG_ERROR(DEBUG_CATEGORY_TIMERS, "echo test: timeout allocation failed"); goto done; } |
|
|
|
|
|
|
|
|
|
socket_t sock = socket(AF_INET, SOCK_STREAM, 0); |
|
|
|
|
if (sock == SOCKET_INVALID) return 1; |
|
|
|
|
sock = socket(AF_INET, SOCK_STREAM, 0); |
|
|
|
|
if (sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "echo client socket failed"); goto done; } |
|
|
|
|
socket_set_nonblocking(sock); |
|
|
|
|
|
|
|
|
|
struct tcp_conn* tc = tcp_conn_create(ua, sock, 1500, 8192, 32, 8, 0, on_fin_cb, on_error_cb, NULL); |
|
|
|
|
if (!tc) return 1; |
|
|
|
|
tc = tcp_conn_create(ua, sock, 1500, 8192, 32, 8, 0, on_fin_cb, on_error_cb, NULL); |
|
|
|
|
if (!tc) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "echo client tcp_conn create failed"); goto done; } |
|
|
|
|
|
|
|
|
|
struct sockaddr_in addr; |
|
|
|
|
memset(&addr, 0, sizeof(addr)); |
|
|
|
|
addr.sin_family = AF_INET; |
|
|
|
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
|
|
|
|
addr.sin_port = htons(ECHO_PORT); |
|
|
|
|
addr.sin_port = htons(echo_port); |
|
|
|
|
int ret = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); |
|
|
|
|
if (ret < 0 && errno != EINPROGRESS) { printf("[FAIL] connect: %s\n", strerror(errno)); g_done = -1; } |
|
|
|
|
|
|
|
|
|
@ -125,8 +134,11 @@ int main(void) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tcp_conn_destroy(tc); |
|
|
|
|
uasync_destroy(ua, 0); |
|
|
|
|
done: |
|
|
|
|
if (timeout_id) uasync_cancel_timeout(ua, timeout_id); |
|
|
|
|
if (tc) tcp_conn_destroy(tc); |
|
|
|
|
else if (sock != SOCKET_INVALID) socket_close_wrapper(sock); |
|
|
|
|
if (ua) uasync_destroy(ua, 0); |
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
kill(echo_pid, SIGKILL); |
|
|
|
|
waitpid(echo_pid, NULL, 0); |
|
|
|
|
|