feat: add socket optimization functions for TCP_NODELAY and upstream handling

test: add tests for connection optimizations, caching, and cleanup
This commit is contained in:
2025-12-15 01:31:27 +01:00
parent 87e165dc52
commit c5af589ceb
3 changed files with 154 additions and 0 deletions
+8
View File
@@ -3,6 +3,14 @@
## Version 0.3.0 - 2025-12-15
Adds socket optimization functions that enable TCP_NODELAY for reduced connection latency and enhance upstream handling. Includes tests for connection optimizations, caching, and cleanup to verify functionality.
**Changes:** 2 files, 146 lines
**Languages:** C (146 lines)
## Version 0.2.0 - 2025-12-15
Optimizes performance through enhanced socket settings and caching, reducing latency in connections. Adds host header validation to client requests and improves DNS resolution error handling for more reliable network operations.
+2
View File
@@ -18,6 +18,8 @@ void connection_cleanup_idle(void);
int connection_set_non_blocking(int fd);
void connection_set_tcp_keepalive(int fd);
void connection_set_tcp_nodelay(int fd);
void connection_optimize_socket(int fd, int is_upstream);
void connection_add_to_epoll(int fd, uint32_t events);
void connection_modify_epoll(int fd, uint32_t events);
+144
View File
@@ -460,6 +460,144 @@ void test_connection_do_read_eagain(void) {
TEST_SUITE_END();
}
void test_connection_optimize_socket(void) {
TEST_SUITE_BEGIN("Connection Optimize Socket");
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT(sockfd >= 0, "Socket created");
connection_optimize_socket(sockfd, 0);
int optval;
socklen_t optlen = sizeof(optval);
getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, &optlen);
TEST_ASSERT_EQ(1, optval, "TCP_NODELAY is enabled for client");
close(sockfd);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT(sockfd >= 0, "Second socket created");
connection_optimize_socket(sockfd, 1);
getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, &optlen);
TEST_ASSERT_EQ(1, optval, "TCP_NODELAY is enabled for upstream");
close(sockfd);
TEST_SUITE_END();
}
extern time_t cached_time;
void connection_update_cached_time(void);
void test_connection_cached_time(void) {
TEST_SUITE_BEGIN("Connection Cached Time");
time_t before = time(NULL);
connection_update_cached_time();
time_t after = time(NULL);
TEST_ASSERT(cached_time >= before, "Cached time >= before");
TEST_ASSERT(cached_time <= after, "Cached time <= after");
TEST_SUITE_END();
}
void test_connection_epoll_event_caching(void) {
TEST_SUITE_BEGIN("Connection Epoll Event Caching");
connection_init_all();
int old_epoll = epoll_fd;
epoll_fd = epoll_create1(0);
TEST_ASSERT(epoll_fd >= 0, "Epoll created");
int sockfd[2];
int result = socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd);
TEST_ASSERT_EQ(0, result, "Socket pair created");
connection_add_to_epoll(sockfd[0], EPOLLIN);
TEST_ASSERT_EQ((uint32_t)EPOLLIN, connections[sockfd[0]].epoll_events, "Events cached on add");
connection_modify_epoll(sockfd[0], EPOLLIN | EPOLLOUT);
TEST_ASSERT_EQ((uint32_t)(EPOLLIN | EPOLLOUT), connections[sockfd[0]].epoll_events, "Events cached on modify");
connection_modify_epoll(sockfd[0], EPOLLIN | EPOLLOUT);
TEST_ASSERT(1, "Redundant modify doesn't crash");
close(sockfd[0]);
close(sockfd[1]);
close(epoll_fd);
epoll_fd = old_epoll;
TEST_SUITE_END();
}
void test_connection_splice_pipe_init(void) {
TEST_SUITE_BEGIN("Connection Splice Pipe Init");
connection_init_all();
TEST_ASSERT_EQ(-1, connections[0].splice_pipe[0], "Splice pipe[0] initialized to -1");
TEST_ASSERT_EQ(-1, connections[0].splice_pipe[1], "Splice pipe[1] initialized to -1");
TEST_ASSERT_EQ(0, connections[0].can_splice, "can_splice initialized to 0");
TEST_SUITE_END();
}
void test_connection_patch_buf_cleanup(void) {
TEST_SUITE_BEGIN("Connection Patch Buffer Cleanup");
connection_init_all();
int old_epoll = epoll_fd;
epoll_fd = epoll_create1(0);
TEST_ASSERT(epoll_fd >= 0, "Epoll created");
int sockfd[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd);
connection_t *conn = &connections[sockfd[0]];
memset(conn, 0, sizeof(connection_t));
conn->fd = sockfd[0];
conn->type = CONN_TYPE_CLIENT;
buffer_init(&conn->read_buf, 4096);
buffer_init(&conn->write_buf, 4096);
conn->patch_buf = malloc(1024);
conn->patch_buf_capacity = 1024;
struct epoll_event ev = { .events = EPOLLIN, .data.fd = sockfd[0] };
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd[0], &ev);
connection_close(sockfd[0]);
TEST_ASSERT_EQ(CONN_TYPE_UNUSED, conn->type, "Connection closed");
close(sockfd[1]);
close(epoll_fd);
epoll_fd = old_epoll;
TEST_SUITE_END();
}
void test_connection_tcp_nodelay(void) {
TEST_SUITE_BEGIN("Connection TCP NODELAY");
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT(sockfd >= 0, "Socket created");
connection_set_tcp_nodelay(sockfd);
int optval;
socklen_t optlen = sizeof(optval);
getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optval, &optlen);
TEST_ASSERT_EQ(1, optval, "TCP_NODELAY is set");
close(sockfd);
TEST_SUITE_END();
}
void run_connection_tests(void) {
test_connection_init_all();
test_connection_set_non_blocking();
@@ -479,4 +617,10 @@ void run_connection_tests(void) {
test_connection_do_write_full_buffer();
test_connection_multiple_error_responses();
test_connection_do_read_eagain();
test_connection_optimize_socket();
test_connection_cached_time();
test_connection_epoll_event_caching();
test_connection_splice_pipe_init();
test_connection_patch_buf_cleanup();
test_connection_tcp_nodelay();
}