diff --git a/repos/os/src/server/nic_router/link.cc b/repos/os/src/server/nic_router/link.cc index 7c11bb297..707d039f3 100644 --- a/repos/os/src/server/nic_router/link.cc +++ b/repos/os/src/server/nic_router/link.cc @@ -218,46 +218,34 @@ Tcp_link::Tcp_link(Interface &cln_interface, { } -void Tcp_link::_fin_acked() +void Tcp_link::_tcp_packet(Tcp_packet &tcp, + Peer &sender, + Peer &receiver) { - if (_server_fin_acked && _client_fin_acked) { - _dissolve_timeout.schedule(Microseconds(_config().tcp_max_segm_lifetime().value << 1)); - _closed = true; - } -} - - -void Tcp_link::server_packet(Tcp_packet &tcp) -{ - if (_closed) { + if (_state == State::CLOSED) { return; } - if (tcp.fin()) { - _server_fin = true; } - - if (tcp.ack() && _client_fin) { - _client_fin_acked = true; - _fin_acked(); + if (tcp.rst()) { + _state = State::CLOSED; + } else { + if (tcp.fin()) { + sender.fin = true; + _state = State::CLOSING; + } + if (receiver.fin && tcp.ack()) { + receiver.fin_acked = true; + if (sender.fin_acked) { + _state = State::CLOSED; } + else { + _state = State::CLOSING; } + } } - if (!_closed) { - _packet(); } -} - - -void Tcp_link::client_packet(Tcp_packet &tcp) -{ - if (_closed) { - return; } - - if (tcp.fin()) { - _client_fin = true; } - - if (tcp.ack() && _server_fin) { - _server_fin_acked = true; - _fin_acked(); + if (_state == State::OPEN) { + _packet(); + } else { + _dissolve_timeout.schedule( + Microseconds(_config().tcp_max_segm_lifetime().value << 1)); } - if (!_closed) { - _packet(); } } diff --git a/repos/os/src/server/nic_router/link.h b/repos/os/src/server/nic_router/link.h index 079a74203..e53120006 100644 --- a/repos/os/src/server/nic_router/link.h +++ b/repos/os/src/server/nic_router/link.h @@ -200,13 +200,21 @@ class Net::Tcp_link : public Link { private: - bool _client_fin { false }; - bool _server_fin { false }; - bool _client_fin_acked { false }; - bool _server_fin_acked { false }; - bool _closed { false }; + enum class State : Genode::uint8_t { OPEN, CLOSING, CLOSED, }; - void _fin_acked(); + struct Peer + { + bool fin { false }; + bool fin_acked { false }; + }; + + State _state { State::OPEN }; + Peer _client { }; + Peer _server { }; + + void _tcp_packet(Tcp_packet &tcp, + Peer &sender, + Peer &receiver); public: @@ -219,9 +227,9 @@ class Net::Tcp_link : public Link Configuration &config, L3_protocol const protocol); - void client_packet(Tcp_packet &tcp); + void client_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _client, _server); } - void server_packet(Tcp_packet &tcp); + void server_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _server, _client); } };