pub fn receive_packet<T: NetworkBytes>(
        &mut self,
        packet: &IPv4Packet<T>,
        callback: fn(Request) -> Response,
    ) -> Result<RecvEvent, RecvError> {
        // TODO: We skip verifying the checksum, just in case the device model relies on offloading
        // checksum computation from the guest to some other entity. Clear this up at some point!
        // (Issue #520)
        let segment =
            TcpSegment::from_bytes(packet.payload(), None).map_err(RecvError::TcpSegment)?;

        if segment.destination_port() != self.local_port {
            return Err(RecvError::InvalidPort);
        }

        let tuple = ConnectionTuple::new(packet.source_address(), segment.source_port());

        let outcome = if let Some(endpoint) = self.connections.get_mut(&tuple) {
            endpoint.receive_segment(&segment, callback);
            if endpoint.is_done() {
                RecvSegmentOutcome::EndpointDone
            } else {
                RecvSegmentOutcome::EndpointRunning(endpoint.next_segment_status())
            }
        } else if segment.flags_after_ns() == TcpFlags::SYN {
            RecvSegmentOutcome::NewConnection
        } else {
            // We should send a RST for every non-RST unexpected segment we receive.
            RecvSegmentOutcome::UnexpectedSegment(
                !segment.flags_after_ns().intersects(TcpFlags::RST),
            )
        };

        match outcome {
            RecvSegmentOutcome::EndpointDone => {
                self.remove_connection(tuple);
                Ok(RecvEvent::EndpointDone)
            }
            RecvSegmentOutcome::EndpointRunning(status) => {
                if !self.check_next_segment_status(tuple, status) {
                    // The connection may not have been a member of active_connection, but it's
                    // more straightforward to cover both cases this way.
                    self.active_connections.remove(&tuple);
                }
                Ok(RecvEvent::Nothing)
            }
            RecvSegmentOutcome::NewConnection => {
                let endpoint = match Endpoint::new_with_defaults(&segment) {
                    Ok(endpoint) => endpoint,
                    Err(_) => return Ok(RecvEvent::FailedNewConnection),
                };

                if self.connections.len() >= self.max_connections {
                    if let Some(evict_tuple) = self.find_evictable_connection() {
                        let rst_config = self.connections[&evict_tuple]
                            .connection()
                            .make_rst_config();
                        self.enqueue_rst_config(evict_tuple, rst_config);
                        self.remove_connection(evict_tuple);
                        self.add_connection(tuple, endpoint);
                        Ok(RecvEvent::NewConnectionReplacing)
                    } else {
                        // No room to accept the new connection. Try to enqueue a RST, and forget
                        // about it.
                        self.enqueue_rst(tuple, &segment);
                        Ok(RecvEvent::NewConnectionDropped)
                    }
                } else {
                    self.add_connection(tuple, endpoint);
                    Ok(RecvEvent::NewConnectionSuccessful)
                }
            }
            RecvSegmentOutcome::UnexpectedSegment(enqueue_rst) => {
                if enqueue_rst {
                    self.enqueue_rst(tuple, &segment);
                }
                Ok(RecvEvent::UnexpectedSegment)
            }
        }
    }
/// Contains logic for handling incoming segments.
///
/// Any changes to the state if the handler are communicated through an `Ok(RecvEvent)`.
Contains logic for handling incoming segments.
Any changes to the state if the handler are communicated through an `Ok(RecvEvent)`.
Contains logic for handling incoming segments . Any changes to the state if the handler are communicated through an ` Ok ( RecvEvent ) ` .
pub fn receive_packet<T: NetworkBytes>(
        &mut self,
        packet: &IPv4Packet<T>,
        callback: fn(Request) -> Response,
    ) -> Result<RecvEvent, RecvError> {
        // TODO: We skip verifying the checksum, just in case the device model relies on offloading
        // checksum computation from the guest to some other entity. Clear this up at some point!
        // (Issue #520)
        let segment =
            TcpSegment::from_bytes(packet.payload(), None).map_err(RecvError::TcpSegment)?;
        if segment.destination_port() != self.local_port {
            return Err(RecvError::InvalidPort);
        }
        let tuple = ConnectionTuple::new(packet.source_address(), segment.source_port());
        let outcome = if let Some(endpoint) = self.connections.get_mut(&tuple) {
            endpoint.receive_segment(&segment, callback);
            if endpoint.is_done() {
                RecvSegmentOutcome::EndpointDone
            } else {
                RecvSegmentOutcome::EndpointRunning(endpoint.next_segment_status())
            }
        } else if segment.flags_after_ns() == TcpFlags::SYN {
            RecvSegmentOutcome::NewConnection
        } else {
            // We should send a RST for every non-RST unexpected segment we receive.
            RecvSegmentOutcome::UnexpectedSegment(
                !segment.flags_after_ns().intersects(TcpFlags::RST),
            )
        };
        match outcome {
            RecvSegmentOutcome::EndpointDone => {
                self.remove_connection(tuple);
                Ok(RecvEvent::EndpointDone)
            }
            RecvSegmentOutcome::EndpointRunning(status) => {
                if !self.check_next_segment_status(tuple, status) {
                    // The connection may not have been a member of active_connection, but it's
                    // more straightforward to cover both cases this way.
                    self.active_connections.remove(&tuple);
                }
                Ok(RecvEvent::Nothing)
            }
            RecvSegmentOutcome::NewConnection => {
                let endpoint = match Endpoint::new_with_defaults(&segment) {
                    Ok(endpoint) => endpoint,
                    Err(_) => return Ok(RecvEvent::FailedNewConnection),
                };
                if self.connections.len() >= self.max_connections {
                    if let Some(evict_tuple) = self.find_evictable_connection() {
                        let rst_config = self.connections[&evict_tuple]
                            .connection()
                            .make_rst_config();
                        self.enqueue_rst_config(evict_tuple, rst_config);
                        self.remove_connection(evict_tuple);
                        self.add_connection(tuple, endpoint);
                        Ok(RecvEvent::NewConnectionReplacing)
                    } else {
                        // No room to accept the new connection. Try to enqueue a RST, and forget
                        // about it.
                        self.enqueue_rst(tuple, &segment);
                        Ok(RecvEvent::NewConnectionDropped)
                    }
                } else {
                    self.add_connection(tuple, endpoint);
                    Ok(RecvEvent::NewConnectionSuccessful)
                }
            }
            RecvSegmentOutcome::UnexpectedSegment(enqueue_rst) => {
                if enqueue_rst {
                    self.enqueue_rst(tuple, &segment);
                }
                Ok(RecvEvent::UnexpectedSegment)
            }
        }
    }
pub fn receive_packet < T : NetworkBytes > ( & mut self , packet : & IPv4Packet < T > , callback : fn ( Request ) -> Response , ) -> Result < RecvEvent , RecvError > { // TODO: We skip verifying the checksum, just in case the device model relies on offloading // checksum computation from the guest to some other entity. Clear this up at some point! // (Issue #520) let segment = TcpSegment :: from_bytes ( packet . payload ( ) , None ) . map_err ( RecvError :: TcpSegment ) ? ; if segment . destination_port ( ) != self . local_port { return Err ( RecvError :: InvalidPort ) ; } let tuple = ConnectionTuple :: new ( packet . source_address ( ) , segment . source_port ( ) ) ; let outcome = if let Some ( endpoint ) = self . connections . get_mut ( & tuple ) { endpoint . receive_segment ( & segment , callback ) ; if endpoint . is_done ( ) { RecvSegmentOutcome :: EndpointDone } else { RecvSegmentOutcome :: EndpointRunning ( endpoint . next_segment_status ( ) ) } } else if segment . flags_after_ns ( ) == TcpFlags :: SYN { RecvSegmentOutcome :: NewConnection } else { // We should send a RST for every non-RST unexpected segment we receive. RecvSegmentOutcome :: UnexpectedSegment ( ! segment . flags_after_ns ( ) . intersects ( TcpFlags :: RST ) , ) } ; match outcome { RecvSegmentOutcome :: EndpointDone => { self . remove_connection ( tuple ) ; Ok ( RecvEvent :: EndpointDone ) } RecvSegmentOutcome :: EndpointRunning ( status ) => { if ! self . check_next_segment_status ( tuple , status ) { // The connection may not have been a member of active_connection, but it's // more straightforward to cover both cases this way. self . active_connections . remove ( & tuple ) ; } Ok ( RecvEvent :: Nothing ) } RecvSegmentOutcome :: NewConnection => { let endpoint = match Endpoint :: new_with_defaults ( & segment ) { Ok ( endpoint ) => endpoint , Err ( _ ) => return Ok ( RecvEvent :: FailedNewConnection ) , } ; if self . connections . len ( ) >= self . max_connections { if let Some ( evict_tuple ) = self . find_evictable_connection ( ) { let rst_config = self . connections [ & evict_tuple ] . connection ( ) . make_rst_config ( ) ; self . enqueue_rst_config ( evict_tuple , rst_config ) ; self . remove_connection ( evict_tuple ) ; self . add_connection ( tuple , endpoint ) ; Ok ( RecvEvent :: NewConnectionReplacing ) } else { // No room to accept the new connection. Try to enqueue a RST, and forget // about it. self . enqueue_rst ( tuple , & segment ) ; Ok ( RecvEvent :: NewConnectionDropped ) } } else { self . add_connection ( tuple , endpoint ) ; Ok ( RecvEvent :: NewConnectionSuccessful ) } } RecvSegmentOutcome :: UnexpectedSegment ( enqueue_rst ) => { if enqueue_rst { self . enqueue_rst ( tuple , & segment ) ; } Ok ( RecvEvent :: UnexpectedSegment ) } } }
Contains logic for handling incoming segments.
Contains logic for handling incoming segments .
&mut self
packet
&IPv4Packet<T>
callback
fn(Request) -> Response
&mut self
packet
&IPv4Packet<T>
callback
fn(Request) -> Response