CS144Lab/libsponge/tcp_helpers/tcp_state.cc
2021-10-19 18:08:12 -07:00

111 lines
4.4 KiB
C++

#include "tcp_state.hh"
using namespace std;
bool TCPState::operator==(const TCPState &other) const {
return _active == other._active and _linger_after_streams_finish == other._linger_after_streams_finish and
_sender == other._sender and _receiver == other._receiver;
}
bool TCPState::operator!=(const TCPState &other) const { return not operator==(other); }
string TCPState::name() const {
return "sender=`" + _sender + "`, receiver=`" + _receiver + "`, active=" + to_string(_active) +
", linger_after_streams_finish=" + to_string(_linger_after_streams_finish);
}
TCPState::TCPState(const TCPState::State state) {
switch (state) {
case TCPState::State::LISTEN:
_receiver = TCPReceiverStateSummary::LISTEN;
_sender = TCPSenderStateSummary::CLOSED;
break;
case TCPState::State::SYN_RCVD:
_receiver = TCPReceiverStateSummary::SYN_RECV;
_sender = TCPSenderStateSummary::SYN_SENT;
break;
case TCPState::State::SYN_SENT:
_receiver = TCPReceiverStateSummary::LISTEN;
_sender = TCPSenderStateSummary::SYN_SENT;
break;
case TCPState::State::ESTABLISHED:
_receiver = TCPReceiverStateSummary::SYN_RECV;
_sender = TCPSenderStateSummary::SYN_ACKED;
break;
case TCPState::State::CLOSE_WAIT:
_receiver = TCPReceiverStateSummary::FIN_RECV;
_sender = TCPSenderStateSummary::SYN_ACKED;
_linger_after_streams_finish = false;
break;
case TCPState::State::LAST_ACK:
_receiver = TCPReceiverStateSummary::FIN_RECV;
_sender = TCPSenderStateSummary::FIN_SENT;
_linger_after_streams_finish = false;
break;
case TCPState::State::CLOSING:
_receiver = TCPReceiverStateSummary::FIN_RECV;
_sender = TCPSenderStateSummary::FIN_SENT;
break;
case TCPState::State::FIN_WAIT_1:
_receiver = TCPReceiverStateSummary::SYN_RECV;
_sender = TCPSenderStateSummary::FIN_SENT;
break;
case TCPState::State::FIN_WAIT_2:
_receiver = TCPReceiverStateSummary::SYN_RECV;
_sender = TCPSenderStateSummary::FIN_ACKED;
break;
case TCPState::State::TIME_WAIT:
_receiver = TCPReceiverStateSummary::FIN_RECV;
_sender = TCPSenderStateSummary::FIN_ACKED;
break;
case TCPState::State::RESET:
_receiver = TCPReceiverStateSummary::ERROR;
_sender = TCPSenderStateSummary::ERROR;
_linger_after_streams_finish = false;
_active = false;
break;
case TCPState::State::CLOSED:
_receiver = TCPReceiverStateSummary::FIN_RECV;
_sender = TCPSenderStateSummary::FIN_ACKED;
_linger_after_streams_finish = false;
_active = false;
break;
}
}
TCPState::TCPState(const TCPSender &sender, const TCPReceiver &receiver, const bool active, const bool linger)
: _sender(state_summary(sender))
, _receiver(state_summary(receiver))
, _active(active)
, _linger_after_streams_finish(active ? linger : false) {}
string TCPState::state_summary(const TCPReceiver &receiver) {
if (receiver.stream_out().error()) {
return TCPReceiverStateSummary::ERROR;
} else if (not receiver.ackno().has_value()) {
return TCPReceiverStateSummary::LISTEN;
} else if (receiver.stream_out().input_ended()) {
return TCPReceiverStateSummary::FIN_RECV;
} else {
return TCPReceiverStateSummary::SYN_RECV;
}
}
string TCPState::state_summary(const TCPSender &sender) {
if (sender.stream_in().error()) {
return TCPSenderStateSummary::ERROR;
} else if (sender.next_seqno_absolute() == 0) {
return TCPSenderStateSummary::CLOSED;
} else if (sender.next_seqno_absolute() == sender.bytes_in_flight()) {
return TCPSenderStateSummary::SYN_SENT;
} else if (not sender.stream_in().eof()) {
return TCPSenderStateSummary::SYN_ACKED;
} else if (sender.next_seqno_absolute() < sender.stream_in().bytes_written() + 2) {
return TCPSenderStateSummary::SYN_ACKED;
} else if (sender.bytes_in_flight()) {
return TCPSenderStateSummary::FIN_SENT;
} else {
return TCPSenderStateSummary::FIN_ACKED;
}
}