@@ -16,18 +16,21 @@ use crate::{Options, Packet};
1616
1717/// Represents the additional network-related information that might be returned by the DHCP server.
1818#[ derive( Debug , Clone ) ]
19- pub struct NetworkInfo {
19+ #[ non_exhaustive]
20+ pub struct NetworkInfo < ' a > {
2021 pub gateway : Option < Ipv4Addr > ,
2122 pub subnet : Option < Ipv4Addr > ,
2223 pub dns1 : Option < Ipv4Addr > ,
2324 pub dns2 : Option < Ipv4Addr > ,
25+ pub captive_url : Option < & ' a str > ,
2426}
2527
2628/// Represents a DHCP IP lease.
2729///
2830/// This structure has a set of asynchronous methods that can utilize a supplied DHCP client instance and UDP socket to
2931/// transparently implement all aspects of negotiating an IP with the DHCP server and then keeping the lease of that IP up to date.
3032#[ derive( Debug , Clone ) ]
33+ #[ non_exhaustive]
3134pub struct Lease {
3235 pub ip : Ipv4Addr ,
3336 pub server_ip : Ipv4Addr ,
@@ -40,46 +43,57 @@ impl Lease {
4043 /// This is done by utilizing the supplied DHCP client instance and UDP socket.
4144 ///
4245 /// Note that the supplied UDP socket should be capable of sending and receiving broadcast UDP packets.
43- pub async fn new < T , S > (
46+ pub async fn new < ' a , T , S > (
4447 client : & mut dhcp:: client:: Client < T > ,
4548 socket : & mut S ,
46- buf : & mut [ u8 ] ,
47- ) -> Result < ( Self , NetworkInfo ) , Error < S :: Error > >
49+ buf : & ' a mut [ u8 ] ,
50+ ) -> Result < ( Self , NetworkInfo < ' a > ) , Error < S :: Error > >
4851 where
4952 T : RngCore ,
5053 S : UdpReceive + UdpSend ,
5154 {
5255 loop {
5356 let offer = Self :: discover ( client, socket, buf, Duration :: from_secs ( 3 ) ) . await ?;
57+ let server_ip = offer. server_ip . unwrap ( ) ;
58+ let ip = offer. ip ;
5459
5560 let now = Instant :: now ( ) ;
5661
57- if let Some ( settings) = Self :: request (
58- client,
59- socket,
60- buf,
61- offer. server_ip . unwrap ( ) ,
62- offer. ip ,
63- true ,
64- Duration :: from_secs ( 3 ) ,
65- 3 ,
66- )
67- . await ?
6862 {
69- break Ok ( (
70- Self {
71- ip : settings. ip ,
72- server_ip : settings. server_ip . unwrap ( ) ,
73- duration : Duration :: from_secs ( settings. lease_time_secs . unwrap_or ( 7200 ) as _ ) ,
74- acquired : now,
75- } ,
76- NetworkInfo {
77- gateway : settings. gateway ,
78- subnet : settings. subnet ,
79- dns1 : settings. dns1 ,
80- dns2 : settings. dns2 ,
81- } ,
82- ) ) ;
63+ // Nasty but necessary to avoid Rust's borrow checker not dealing
64+ // with the non-lexical lifetimes involved here
65+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
66+
67+ if let Some ( settings) = Self :: request (
68+ client,
69+ socket,
70+ buf,
71+ server_ip,
72+ ip,
73+ true ,
74+ Duration :: from_secs ( 3 ) ,
75+ 3 ,
76+ )
77+ . await ?
78+ {
79+ break Ok ( (
80+ Self {
81+ ip : settings. ip ,
82+ server_ip : settings. server_ip . unwrap ( ) ,
83+ duration : Duration :: from_secs (
84+ settings. lease_time_secs . unwrap_or ( 7200 ) as _
85+ ) ,
86+ acquired : now,
87+ } ,
88+ NetworkInfo {
89+ gateway : settings. gateway ,
90+ subnet : settings. subnet ,
91+ dns1 : settings. dns1 ,
92+ dns2 : settings. dns2 ,
93+ captive_url : settings. captive_url ,
94+ } ,
95+ ) ) ;
96+ }
8397 }
8498 }
8599 }
@@ -173,12 +187,12 @@ impl Lease {
173187 Ok ( ( ) )
174188 }
175189
176- async fn discover < T , S > (
190+ async fn discover < ' a , T , S > (
177191 client : & mut dhcp:: client:: Client < T > ,
178192 socket : & mut S ,
179- buf : & mut [ u8 ] ,
193+ buf : & ' a mut [ u8 ] ,
180194 timeout : Duration ,
181- ) -> Result < Settings , Error < S :: Error > >
195+ ) -> Result < Settings < ' a > , Error < S :: Error > >
182196 where
183197 T : RngCore ,
184198 S : UdpReceive + UdpSend ,
@@ -203,11 +217,15 @@ impl Lease {
203217
204218 if let Either :: First ( result) = select ( socket. receive ( buf) , Timer :: after ( timeout) ) . await
205219 {
220+ // Nasty but necessary to avoid Rust's borrow checker not dealing
221+ // with the non-lexical lifetimes involved here
222+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
223+
206224 let ( len, _remote) = result. map_err ( Error :: Io ) ?;
207225 let reply = Packet :: decode ( & buf[ ..len] ) ?;
208226
209227 if client. is_offer ( & reply, xid) {
210- let settings: Settings = ( & reply) . into ( ) ;
228+ let settings = Settings :: new ( & reply) ;
211229
212230 info ! (
213231 "IP {} offered by DHCP server {}" ,
@@ -224,16 +242,16 @@ impl Lease {
224242 }
225243
226244 #[ allow( clippy:: too_many_arguments) ]
227- async fn request < T , S > (
245+ async fn request < ' a , T , S > (
228246 client : & mut dhcp:: client:: Client < T > ,
229247 socket : & mut S ,
230- buf : & mut [ u8 ] ,
248+ buf : & ' a mut [ u8 ] ,
231249 server_ip : Ipv4Addr ,
232250 ip : Ipv4Addr ,
233251 broadcast : bool ,
234252 timeout : Duration ,
235253 retries : usize ,
236- ) -> Result < Option < Settings > , Error < S :: Error > >
254+ ) -> Result < Option < Settings < ' a > > , Error < S :: Error > >
237255 where
238256 T : RngCore ,
239257 S : UdpReceive + UdpSend ,
@@ -270,12 +288,17 @@ impl Lease {
270288 if let Either :: First ( result) = select ( socket. receive ( buf) , Timer :: after ( timeout) ) . await
271289 {
272290 let ( len, _remote) = result. map_err ( Error :: Io ) ?;
291+
292+ // Nasty but necessary to avoid Rust's borrow checker not dealing
293+ // with the non-lexical lifetimes involved here
294+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
295+
273296 let packet = & buf[ ..len] ;
274297
275298 let reply = Packet :: decode ( packet) ?;
276299
277300 if client. is_ack ( & reply, xid) {
278- let settings = ( & reply) . into ( ) ;
301+ let settings = Settings :: new ( & reply) ;
279302
280303 info ! ( "IP {} leased successfully" , ip) ;
281304
@@ -292,4 +315,11 @@ impl Lease {
292315
293316 Ok ( None )
294317 }
318+
319+ // Useful when Rust's borrow-checker still cannot handle some NLLs
320+ // https://rust-lang.github.io/rfcs/2094-nll.html
321+ unsafe fn unsafe_reborrow < ' a > ( buf : & mut [ u8 ] ) -> & ' a mut [ u8 ] {
322+ let len = buf. len ( ) ;
323+ unsafe { core:: slice:: from_raw_parts_mut ( buf. as_mut_ptr ( ) , len) }
324+ }
295325}
0 commit comments