mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 07:48:11 +00:00
IPv4: Basic implementation of TCP socket shutdown
We can now participate in the TCP connection closing handshake. :^) This implementation is definitely not complete and needs to handle a bunch of other cases. But it's a huge improvement over not being able to close connections at all. Note that we hold on to pending-close sockets indefinitely, until they are moved into the Closed state. This should also have a timeout but that's still a FIXME. :^) Fixes #428.
This commit is contained in:
parent
8325662186
commit
228a1e9099
7 changed files with 69 additions and 8 deletions
|
@ -55,6 +55,19 @@ void TCPSocket::set_state(State new_state)
|
|||
|
||||
if (new_state == State::Established && m_direction == Direction::Outgoing)
|
||||
m_role = Role::Connected;
|
||||
|
||||
if (new_state == State::Closed) {
|
||||
LOCKER(closing_sockets().lock());
|
||||
closing_sockets().resource().remove(tuple());
|
||||
}
|
||||
}
|
||||
|
||||
Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>& TCPSocket::closing_sockets()
|
||||
{
|
||||
static Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>* s_map;
|
||||
if (!s_map)
|
||||
s_map = new Lockable<HashMap<IPv4SocketTuple, RefPtr<TCPSocket>>>;
|
||||
return *s_map;
|
||||
}
|
||||
|
||||
Lockable<HashMap<IPv4SocketTuple, TCPSocket*>>& TCPSocket::sockets_by_tuple()
|
||||
|
@ -137,6 +150,10 @@ TCPSocket::~TCPSocket()
|
|||
{
|
||||
LOCKER(sockets_by_tuple().lock());
|
||||
sockets_by_tuple().resource().remove(tuple());
|
||||
|
||||
#ifdef TCP_SOCKET_DEBUG
|
||||
dbg() << "~TCPSocket in state " << to_string(state());
|
||||
#endif
|
||||
}
|
||||
|
||||
NonnullRefPtr<TCPSocket> TCPSocket::create(int protocol)
|
||||
|
@ -420,3 +437,27 @@ bool TCPSocket::protocol_is_disconnected() const
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSocket::shut_down_for_writing()
|
||||
{
|
||||
if (state() == State::Established) {
|
||||
dbg() << " Sending FIN/ACK from Established and moving into FinWait1";
|
||||
send_tcp_packet(TCPFlags::FIN | TCPFlags::ACK);
|
||||
set_state(State::FinWait1);
|
||||
} else {
|
||||
dbg() << " Shutting down TCPSocket for writing but not moving to FinWait1 since state is " << to_string(state());
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSocket::close()
|
||||
{
|
||||
IPv4Socket::close();
|
||||
if (state() == State::CloseWait) {
|
||||
dbg() << " Sending FIN from CloseWait and moving into LastAck";
|
||||
send_tcp_packet(TCPFlags::FIN | TCPFlags::ACK);
|
||||
set_state(State::LastAck);
|
||||
}
|
||||
|
||||
LOCKER(closing_sockets().lock());
|
||||
closing_sockets().resource().set(tuple(), *this);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue