pub struct Connection { /* private fields */ }Expand description
Contains the state information and implements the logic for a minimalist TCP connection.
One particular thing is that whenever the connection sends a RST segment, it will also stop
working itself. This is just a design decision for our envisioned use cases;
improvements/changes may happen in the future (this also goes for other aspects of the
current implementation).
A Connection object can only be created via passive open, and will not recognize/use any TCP
options except MSS during the handshake. The associated state machine is similar to how
TCP normally functions, but there are some differences:
- Since only passive opens are supported, a
Connectioncan only be instantiated in response to an incomingSYNsegment. If the segment is valid, it will start directly in a state calledSYN_RECEIVED. The valid events at this point are receiving a retransmission of the previousSYN(which does nothing), and getting the chance to write aSYNACK, which also moves the connection to theSYNACK_SENTstate. Any incoming segment which is not a copy of the previousSYNwill reset the connection. - In the
SYNACK_SENTstate, the connection awaits anACKfor theSYNACK. A retransmission of the originalSYNmoves the state back toSYN_RECEIVED. A validACKadvances the state toESTABLISHED. Any unexpected/invalid segment resets the connection. - While
ESTABLISHED, the connection will only reset if it receives aRSTor aSYN. Invalid segments are simply ignored.FINhandling is simplifed: whencloseis invoked the connection records theFINsequence number, and starts setting theFINflag (when possible) on outgoing segments. AFINfrom the other endpoint is only taken into consideration if it has the next expected sequence number. When the connection has both sent and received aFIN, it marks itself as being done. There’s no equivalent for theTIME_WAITTCP state.
The current implementation does not do any kind of congestion control, expects segments to
arrive in order, triggers a retransmission after the first duplicate ACK, and relies on the
user to supply an opaque u64 timestamp value when invoking send or receive functionality. The
timestamps must be non-decreasing, and are mainly used for retransmission timeouts.
See mmds-design for why we are able to make these simplifications. Specifically, we want to stress that no traffic handled by dumbo ever leaves a microVM.
Implementations§
Source§impl Connection
impl Connection
Sourcepub fn passive_open<T: NetworkBytes + Debug>(
segment: &TcpSegment<'_, T>,
local_rwnd_size: u32,
rto_period: NonZeroU64,
rto_count_max: NonZeroU16,
) -> Result<Self, PassiveOpenError>
pub fn passive_open<T: NetworkBytes + Debug>( segment: &TcpSegment<'_, T>, local_rwnd_size: u32, rto_period: NonZeroU64, rto_count_max: NonZeroU16, ) -> Result<Self, PassiveOpenError>
Attempts to create a new Connection in response to an incoming SYN segment.
§Arguments
segment- The incomingSYN.local_rwnd_size- Initial size of the local receive window.rto_period- How long the connection waits before a retransmission timeout fires for the first segment which has not been acknowledged yet. This uses an opaque time unit.rto_count_max- How many consecutive timeout-based retransmission may occur before the connection resets itself.
Sourcepub fn close(&mut self)
pub fn close(&mut self)
Closes this half of the connection.
Subsequent calls after the first one do not have any effect. The sequence number of the
FIN is the first sequence number not yet sent at this point.
Sourcepub fn make_rst_config(&self) -> RstConfig
pub fn make_rst_config(&self) -> RstConfig
Returns a valid configuration for a RST segment, which can be sent to the other
endpoint to signal the connection should be reset.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Specifies that a RST segment should be sent to the other endpoint, and then the
connection should be destroyed.
Sourcepub fn is_established(&self) -> bool
pub fn is_established(&self) -> bool
Returns true if the connection is past the ESTABLISHED point.
Sourcepub fn fin_received(&self) -> bool
pub fn fin_received(&self) -> bool
Returns true if a FIN has been received.
Sourcepub fn is_done(&self) -> bool
pub fn is_done(&self) -> bool
Returns true if the connection is done communicating with the other endpoint.
Maybe it would be a good idea to return true only after our FIN has also been ACKed? Otherwise, when using the TCP handler there’s pretty much always going to be an ACK for the FIN that’s going to trigger a gratuitous RST (best case), or can even be considered valid if a new connection is created meanwhile using the same tuple and we get very unlucky (worst case, extremely unlikely though).
Sourcepub fn first_not_sent(&self) -> Wrapping<u32>
pub fn first_not_sent(&self) -> Wrapping<u32>
Returns the first sequence number which has not been sent yet for the current window.
Sourcepub fn highest_ack_received(&self) -> Wrapping<u32>
pub fn highest_ack_received(&self) -> Wrapping<u32>
Returns the highest acknowledgement number received for the current window.
Sourcepub fn advance_local_rwnd_edge(&mut self, value: u32)
pub fn advance_local_rwnd_edge(&mut self, value: u32)
Advances the right edge of the local receive window.
This is effectively allowing the other endpoint to send more data, because no byte can be sent unless its sequence number falls into the receive window.
Sourcepub fn remote_rwnd_edge(&self) -> Wrapping<u32>
pub fn remote_rwnd_edge(&self) -> Wrapping<u32>
Returns the right edge of the receive window advertised by the other endpoint.
Sourcepub fn dup_ack_pending(&self) -> bool
pub fn dup_ack_pending(&self) -> bool
Returns true if a retransmission caused by the reception of a duplicate ACK is pending.
Sourcepub fn control_segment_or_timeout_status(&self) -> NextSegmentStatus
pub fn control_segment_or_timeout_status(&self) -> NextSegmentStatus
Describes whether a control segment can be sent immediately, a retransmission is pending, or there’s nothing to transmit until more segments are received.
This function does not tell whether any data segments can/will be sent, because the Connection itself does not control the send buffer. Thus the information returned here only pertains to control segments and timeout expiry. Data segment related status will be reported by higher level components, which also manage the contents of the send buffer.
Sourcepub fn receive_segment<T: NetworkBytes + Debug>(
&mut self,
s: &TcpSegment<'_, T>,
buf: &mut [u8],
now: u64,
) -> Result<(Option<NonZeroUsize>, RecvStatusFlags), RecvError>
pub fn receive_segment<T: NetworkBytes + Debug>( &mut self, s: &TcpSegment<'_, T>, buf: &mut [u8], now: u64, ) -> Result<(Option<NonZeroUsize>, RecvStatusFlags), RecvError>
Handles an incoming segment.
When no errors occur, returns a pair consisting of how many
bytes (if any) were received, and whether any unusual conditions arose while processing the
segment. Since a Connection does not have its own internal buffer, buf is required to
store any data carried by incoming segments.
§Arguments
s- The incoming segment.buf- The receive buffer where payload data (if any) fromsis going to be written.now- An opaque timestamp representing the current moment in time.
Sourcepub fn write_next_segment<'a, R: ByteBuffer + ?Sized + Debug>(
&mut self,
buf: &'a mut [u8],
mss_reserved: u16,
payload_src: PayloadSource<'_, R>,
now: u64,
) -> Result<Option<Incomplete<TcpSegment<'a, &'a mut [u8]>>>, WriteNextError>
pub fn write_next_segment<'a, R: ByteBuffer + ?Sized + Debug>( &mut self, buf: &'a mut [u8], mss_reserved: u16, payload_src: PayloadSource<'_, R>, now: u64, ) -> Result<Option<Incomplete<TcpSegment<'a, &'a mut [u8]>>>, WriteNextError>
Writes a new segment (if available) to the specified buffer.
The payload_src argument is required because the Connection does not have an internal
send buffer. If the payload source is present, the data referenced therein must not amount
to more than MAX_WINDOW_SIZE.
§Arguments
buf- The buffer where the segment is written.mss_reserved- How much (if anything) of the MSS value has been already used at the lower layers (by IP options, for example). This will be zero most of the time.payload_src- References a buffer which contains data to send, and also specifies the sequence number associated with the first byte from that buffer.now- An opaque timestamp representing the current moment in time.
Trait Implementations§
Source§impl Clone for Connection
impl Clone for Connection
Source§fn clone(&self) -> Connection
fn clone(&self) -> Connection
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for Connection
impl RefUnwindSafe for Connection
impl Send for Connection
impl Sync for Connection
impl Unpin for Connection
impl UnwindSafe for Connection
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.