Skip to content

Commit 6c7788d

Browse files
committed
nstun: add missing TCP state - TcpState::CLOSING
1 parent 2ee9590 commit 6c7788d

6 files changed

Lines changed: 36 additions & 12 deletions

File tree

nstun/icmp.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "icmp.h"
22

3+
#include <errno.h>
34
#include <netinet/in.h>
45
#include <string.h>
56
#include <sys/epoll.h>

nstun/net_defs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ inline uint16_t compute_checksum(const void* buf, size_t len, uint32_t sum = 0)
102102
return finalize_checksum(compute_checksum_part(buf, len, sum));
103103
}
104104

105-
} // namespace nstun
106-
107105
inline bool is_loopback_addr(uint32_t addr_net) {
108106
return (ntohl(addr_net) & 0xFF000000) == 0x7F000000;
109107
}
110108

109+
} // namespace nstun
110+
111111
#endif /* NSTUN_NET_DEFS_H_ */

nstun/nstun.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ namespace nstun {
3535

3636
Context::~Context() {
3737
for (auto& pair : udp_flows_by_key) {
38-
if (pair.second->host_fd != -1) close(pair.second->host_fd);
38+
if (pair.second->host_fd != -1 && !pair.second->host_fd_is_listener) {
39+
close(pair.second->host_fd);
40+
}
3941
if (pair.second->tcp_fd != -1) close(pair.second->tcp_fd);
4042
delete pair.second;
4143
}
@@ -47,6 +49,9 @@ Context::~Context() {
4749
if (pair.second->host_fd != -1) close(pair.second->host_fd);
4850
delete pair.second;
4951
}
52+
for (auto& [fd, _] : host_listener_fd_to_rule) {
53+
close(fd);
54+
}
5055
}
5156

5257
RuleResult evaluate_rules(Context* ctx, nstun_direction_t dir, nstun_proto_t proto, uint32_t src_ip,
@@ -83,7 +88,9 @@ static void garbage_collect(Context* ctx) {
8388
timeout = 5;
8489
} else if (flow->state == TcpState::CLOSE_WAIT ||
8590
flow->state == TcpState::LAST_ACK ||
86-
flow->state == TcpState::TIME_WAIT) {
91+
flow->state == TcpState::FIN_WAIT_1 ||
92+
flow->state == TcpState::FIN_WAIT_2 ||
93+
flow->state == TcpState::CLOSING || flow->state == TcpState::TIME_WAIT) {
8794
timeout = 10;
8895
}
8996
if (now - flow->last_active > timeout) {

nstun/tcp.cc

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,34 @@ void tcp_send_packet(Context* ctx, TcpFlow* flow, uint8_t flags, const uint8_t*
3333
return;
3434
}
3535

36+
constexpr uint8_t TCP_OPT_NOP = 1;
37+
constexpr uint8_t TCP_OPT_MSS = 2;
38+
constexpr uint8_t TCP_OPT_MSS_LEN = 4;
39+
constexpr uint8_t TCP_OPT_WSCALE = 3;
40+
constexpr uint8_t TCP_OPT_WSCALE_LEN = 3;
41+
3642
size_t opt_len = 0;
3743
uint8_t options[40];
3844
if (flags & NSTUN_TCP_FLAG_SYN) {
3945
/* Add MSS option (Kind=2, Length=4, MSS=65495) */
40-
options[opt_len++] = 2;
41-
options[opt_len++] = 4;
46+
options[opt_len++] = TCP_OPT_MSS;
47+
options[opt_len++] = TCP_OPT_MSS_LEN;
4248
uint16_t mss = htons(65495);
4349
memcpy(&options[opt_len], &mss, 2);
4450
opt_len += 2;
4551

46-
/* Add NOP (Kind=1) for 32-bit alignment */
47-
options[opt_len++] = 1;
52+
/* Add NOP for 32-bit alignment */
53+
options[opt_len++] = TCP_OPT_NOP;
4854

4955
/* Add Window Scale option (Kind=3, Length=3, Shift=8) */
50-
options[opt_len++] = 3;
51-
options[opt_len++] = 3;
56+
options[opt_len++] = TCP_OPT_WSCALE;
57+
options[opt_len++] = TCP_OPT_WSCALE_LEN;
5258
options[opt_len++] = 8;
5359
}
5460

5561
size_t frame_len = sizeof(ip4_hdr) + sizeof(tcp_hdr) + opt_len + len;
56-
uint8_t frame_buf[sizeof(ip4_hdr) + sizeof(tcp_hdr) + sizeof(options) + NSTUN_MTU];
62+
/* Single-threaded network loop: use static buffer to avoid 63KB stack allocation */
63+
static thread_local uint8_t frame_buf[sizeof(ip4_hdr) + sizeof(tcp_hdr) + 40 + NSTUN_MTU];
5764

5865
ip4_hdr* r_ip = reinterpret_cast<ip4_hdr*>(frame_buf);
5966
tcp_hdr* r_tcp = reinterpret_cast<tcp_hdr*>(frame_buf + sizeof(ip4_hdr));
@@ -496,6 +503,10 @@ void handle_tcp(Context* ctx, const ip4_hdr* ip, const uint8_t* payload, size_t
496503

497504
if (flow->state == TcpState::ESTABLISHED) {
498505
flow->state = TcpState::CLOSE_WAIT;
506+
} else if (flow->state == TcpState::FIN_WAIT_1) {
507+
flow->state = TcpState::CLOSING;
508+
} else if (flow->state == TcpState::FIN_WAIT_2) {
509+
flow->state = TcpState::TIME_WAIT;
499510
}
500511

501512
push_to_guest(ctx, flow);
@@ -630,7 +641,6 @@ void handle_host_tcp_data(Context* ctx, TcpFlow* flow, int fd) {
630641
(flow->inbound && flow->state == TcpState::SYN_SENT)) {
631642
uint8_t buf[65536];
632643
ssize_t recv_len = recv(fd, buf, sizeof(buf), 0);
633-
LOG_D("recv_len=%zd errno=%d", recv_len, errno);
634644
if (recv_len == 0) goto eof;
635645
if (recv_len < 0) {
636646
if (errno == EAGAIN || errno == EWOULDBLOCK) return;
@@ -757,6 +767,10 @@ void handle_host_tcp_accept(Context* ctx, int listen_fd, const nstun_rule_t& rul
757767
}
758768

759769
LOG_D("Accepted fd=%d", fd);
770+
771+
int opt = 1;
772+
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
773+
760774
struct sockaddr_in server_addr = {};
761775
socklen_t servlen = sizeof(server_addr);
762776
getsockname(fd, (struct sockaddr*)&server_addr, &servlen);

nstun/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum class TcpState {
1616
ESTABLISHED,
1717
FIN_WAIT_1,
1818
FIN_WAIT_2,
19+
CLOSING,
1920
TIME_WAIT,
2021
CLOSE_WAIT,
2122
LAST_ACK

nstun/udp.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "udp.h"
22

33
#include <arpa/inet.h>
4+
#include <errno.h>
45
#include <netinet/in.h>
56
#include <string.h>
67
#include <sys/epoll.h>

0 commit comments

Comments
 (0)