fn send_and_schedule_retransmission<R: Rng>(
        self,
        transaction_id: [u8; 3],
        options_to_request: &[v6::OptionCode],
        rng: &mut R,
    ) -> Transition {
        let mut options = vec![v6::DhcpOption::ClientId(&self.client_id)];

        let elapsed_time = match self.first_solicit_time {
            None => 0,
            Some(first_solicit_time) => u16::try_from(
                Instant::now()
                    .duration_since(first_solicit_time)
                    .as_millis()
                    .checked_div(ELAPSED_TIME_DENOMINATOR)
                    .expect("division should succeed"),
            )
            .unwrap_or(u16::MAX),
        };
        options.push(v6::DhcpOption::ElapsedTime(elapsed_time));

        // TODO(https://fxbug.dev/86945): remove `address_hint` construction
        // once `IanaSerializer::new()` takes options by value.
        let mut address_hint = HashMap::new();
        for (iaid, addr_opt) in &self.configured_addresses {
            let entry = address_hint.insert(
                *iaid,
                addr_opt.map(|addr| {
                    [v6::DhcpOption::IaAddr(v6::IaAddrSerializer::new(addr, 0, 0, &[]))]
                }),
            );
            assert_matches!(entry, None);
        }

        // Adds IA_NA options: one IA_NA per address hint, plus IA_NA options
        // without hints, up to the configured `address_count`, as described in
        // https://datatracker.ietf.org/doc/html/rfc8415#section-6.6.
        for (iaid, addr_hint) in &address_hint {
            options.push(v6::DhcpOption::Iana(v6::IanaSerializer::new(
                *iaid,
                0,
                0,
                addr_hint.as_ref().map_or(&[], AsRef::as_ref),
            )));
        }

        let mut oro = vec![v6::OptionCode::SolMaxRt];
        oro.extend_from_slice(options_to_request);
        options.push(v6::DhcpOption::Oro(&oro));

        let builder = v6::MessageBuilder::new(v6::MessageType::Solicit, transaction_id, &options);
        let mut buf = vec![0; builder.bytes_len()];
        let () = builder.serialize(&mut buf);

        let retrans_timeout = self.retransmission_timeout(rng);
        let first_solicit_time = self.first_solicit_time.unwrap_or(Instant::now());

        Transition {
            state: ClientState::ServerDiscovery(ServerDiscovery {
                client_id: self.client_id,
                configured_addresses: self.configured_addresses,
                first_solicit_time: Some(first_solicit_time),
                retrans_timeout,
            }),
            actions: vec![
                Action::SendMessage(buf),
                Action::ScheduleTimer(ClientTimerType::Retransmission, retrans_timeout),
            ],
        }
    }
/// Returns a transition back to `ServerDiscovery`, with actions to send a
/// solicit and schedule retransmission.
Returns a transition back to `ServerDiscovery`, with actions to send a
solicit and schedule retransmission.
Returns a transition back to ` ServerDiscovery ` with actions to send a solicit and schedule retransmission .
fn send_and_schedule_retransmission<R: Rng>(
        self,
        transaction_id: [u8; 3],
        options_to_request: &[v6::OptionCode],
        rng: &mut R,
    ) -> Transition {
        let mut options = vec![v6::DhcpOption::ClientId(&self.client_id)];
        let elapsed_time = match self.first_solicit_time {
            None => 0,
            Some(first_solicit_time) => u16::try_from(
                Instant::now()
                    .duration_since(first_solicit_time)
                    .as_millis()
                    .checked_div(ELAPSED_TIME_DENOMINATOR)
                    .expect("division should succeed"),
            )
            .unwrap_or(u16::MAX),
        };
        options.push(v6::DhcpOption::ElapsedTime(elapsed_time));
        // TODO(https://fxbug.dev/86945): remove `address_hint` construction
        // once `IanaSerializer::new()` takes options by value.
        let mut address_hint = HashMap::new();
        for (iaid, addr_opt) in &self.configured_addresses {
            let entry = address_hint.insert(
                *iaid,
                addr_opt.map(|addr| {
                    [v6::DhcpOption::IaAddr(v6::IaAddrSerializer::new(addr, 0, 0, &[]))]
                }),
            );
            assert_matches!(entry, None);
        }
        // Adds IA_NA options: one IA_NA per address hint, plus IA_NA options
        // without hints, up to the configured `address_count`, as described in
        // https://datatracker.ietf.org/doc/html/rfc8415#section-6.6.
        for (iaid, addr_hint) in &address_hint {
            options.push(v6::DhcpOption::Iana(v6::IanaSerializer::new(
                *iaid,
                0,
                0,
                addr_hint.as_ref().map_or(&[], AsRef::as_ref),
            )));
        }
        let mut oro = vec![v6::OptionCode::SolMaxRt];
        oro.extend_from_slice(options_to_request);
        options.push(v6::DhcpOption::Oro(&oro));
        let builder = v6::MessageBuilder::new(v6::MessageType::Solicit, transaction_id, &options);
        let mut buf = vec![0; builder.bytes_len()];
        let () = builder.serialize(&mut buf);
        let retrans_timeout = self.retransmission_timeout(rng);
        let first_solicit_time = self.first_solicit_time.unwrap_or(Instant::now());
        Transition {
            state: ClientState::ServerDiscovery(ServerDiscovery {
                client_id: self.client_id,
                configured_addresses: self.configured_addresses,
                first_solicit_time: Some(first_solicit_time),
                retrans_timeout,
            }),
            actions: vec![
                Action::SendMessage(buf),
                Action::ScheduleTimer(ClientTimerType::Retransmission, retrans_timeout),
            ],
        }
    }
fn send_and_schedule_retransmission < R : Rng > ( self , transaction_id : [ u8 ; 3 ] , options_to_request : & [ v6 :: OptionCode ] , rng : & mut R , ) -> Transition { let mut options = vec ! [ v6 DhcpOption ClientId ( self client_id ) ] ; let elapsed_time = match self . first_solicit_time { None => 0 , Some ( first_solicit_time ) => u16 :: try_from ( Instant :: now ( ) . duration_since ( first_solicit_time ) . as_millis ( ) . checked_div ( ELAPSED_TIME_DENOMINATOR ) . expect ( " " ) , ) . unwrap_or ( u16 :: MAX ) , } ; options . push ( v6 :: DhcpOption :: ElapsedTime ( elapsed_time ) ) ; // TODO(https://fxbug.dev/86945): remove `address_hint` construction // once `IanaSerializer::new()` takes options by value. let mut address_hint = HashMap :: new ( ) ; for ( iaid , addr_opt ) in & self . configured_addresses { let entry = address_hint . insert ( * iaid , addr_opt . map ( | addr | { [ v6 :: DhcpOption :: IaAddr ( v6 :: IaAddrSerializer :: new ( addr , 0 , 0 , & [ ] ) ) ] } ) , ) ; assert_matches ! ( entry None ) ; } // Adds IA_NA options: one IA_NA per address hint, plus IA_NA options // without hints, up to the configured `address_count`, as described in // https://datatracker.ietf.org/doc/html/rfc8415#section-6.6. for ( iaid , addr_hint ) in & address_hint { options . push ( v6 :: DhcpOption :: Iana ( v6 :: IanaSerializer :: new ( * iaid , 0 , 0 , addr_hint . as_ref ( ) . map_or ( & [ ] , AsRef :: as_ref ) , ) ) ) ; } let mut oro = vec ! [ v6 OptionCode SolMaxRt ] ; oro . extend_from_slice ( options_to_request ) ; options . push ( v6 :: DhcpOption :: Oro ( & oro ) ) ; let builder = v6 :: MessageBuilder :: new ( v6 :: MessageType :: Solicit , transaction_id , & options ) ; let mut buf = vec ! [ 0 builder bytes_len ( ) ] ; let ( ) = builder . serialize ( & mut buf ) ; let retrans_timeout = self . retransmission_timeout ( rng ) ; let first_solicit_time = self . first_solicit_time . unwrap_or ( Instant :: now ( ) ) ; Transition { state : ClientState :: ServerDiscovery ( ServerDiscovery { client_id : self . client_id , configured_addresses : self . configured_addresses , first_solicit_time : Some ( first_solicit_time ) , retrans_timeout , } ) , actions : vec ! [ Action SendMessage ( buf ) Action ScheduleTimer ( ClientTimerType Retransmission retrans_timeout ) ] , } }
Returns a transition back to `ServerDiscovery`, with actions to send a
solicit and schedule retransmission.
Returns a transition back to ` ServerDiscovery ` with actions to send a solicit and schedule retransmission .
self
transaction_id
[u8; 3]
options_to_request
&[v6::OptionCode]
rng
&mut R
self
transaction_id
[u8; 3]
options_to_request
&[v6::OptionCode]
rng
&mut R