Add TcpSocket::abort().
This commit is contained in:
parent
a75f7d4bf0
commit
74d1eb86b6
|
@ -354,6 +354,17 @@ impl<'a> TcpSocket<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Aborts the connection, if any.
|
||||
///
|
||||
/// This function instantly closes the socket. One reset packet will be sent to the remote
|
||||
/// endpoint.
|
||||
///
|
||||
/// In terms of the TCP state machine, the socket may be in any state and is moved to
|
||||
/// the `CLOSED` state.
|
||||
pub fn abort(&mut self) {
|
||||
self.set_state(State::Closed);
|
||||
}
|
||||
|
||||
/// Return whether the socket is passively listening for incoming connections.
|
||||
///
|
||||
/// In terms of the TCP state machine, the socket must be in the `LISTEN` state.
|
||||
|
@ -787,6 +798,27 @@ impl<'a> TcpSocket<'a> {
|
|||
payload: &[]
|
||||
};
|
||||
|
||||
if self.state == State::Closed {
|
||||
// If we have a specified local and remote endpoint, but are in the CLOSED state,
|
||||
// we've ended up here after aborting a connection. Send exactly one RST packet.
|
||||
net_trace!("[{}]{}:{}: sending RST",
|
||||
self.debug_id, self.local_endpoint, self.remote_endpoint);
|
||||
|
||||
repr.control = TcpControl::Rst;
|
||||
repr.ack_number = Some(self.remote_seq_no);
|
||||
let ip_repr = IpRepr::Unspecified {
|
||||
src_addr: self.local_endpoint.addr,
|
||||
dst_addr: self.remote_endpoint.addr,
|
||||
protocol: IpProtocol::Tcp,
|
||||
payload_len: repr.buffer_len()
|
||||
};
|
||||
let result = emit(&ip_repr, &repr);
|
||||
|
||||
self.local_endpoint = IpEndpoint::default();
|
||||
self.remote_endpoint = IpEndpoint::default();
|
||||
return result
|
||||
}
|
||||
|
||||
if self.retransmit.may_send_old(timestamp) {
|
||||
// The retransmit timer has expired, so assume all in-flight data that
|
||||
// has not been acknowledged is lost.
|
||||
|
@ -1517,6 +1549,19 @@ mod test {
|
|||
sanity!(s, socket_fin_wait_1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_established_abort() {
|
||||
let mut s = socket_established();
|
||||
s.abort();
|
||||
assert_eq!(s.state, State::Closed);
|
||||
recv!(s, [TcpRepr {
|
||||
control: TcpControl::Rst,
|
||||
seq_number: LOCAL_SEQ + 1,
|
||||
ack_number: Some(REMOTE_SEQ + 1),
|
||||
..RECV_TEMPL
|
||||
}]);
|
||||
}
|
||||
|
||||
// =========================================================================================//
|
||||
// Tests for the FIN-WAIT-1 state.
|
||||
// =========================================================================================//
|
||||
|
|
Loading…
Reference in New Issue