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.
|
/// 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.
|
/// In terms of the TCP state machine, the socket must be in the `LISTEN` state.
|
||||||
|
@ -787,6 +798,27 @@ impl<'a> TcpSocket<'a> {
|
||||||
payload: &[]
|
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) {
|
if self.retransmit.may_send_old(timestamp) {
|
||||||
// The retransmit timer has expired, so assume all in-flight data that
|
// The retransmit timer has expired, so assume all in-flight data that
|
||||||
// has not been acknowledged is lost.
|
// has not been acknowledged is lost.
|
||||||
|
@ -1517,6 +1549,19 @@ mod test {
|
||||||
sanity!(s, socket_fin_wait_1());
|
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.
|
// Tests for the FIN-WAIT-1 state.
|
||||||
// =========================================================================================//
|
// =========================================================================================//
|
||||||
|
|
Loading…
Reference in New Issue