@@ -19,10 +19,11 @@ use std::time::Duration;
1919/// specificed in [RFC 2177](https://tools.ietf.org/html/rfc2177) until the underlying server state
2020/// changes in some way.
2121///
22- /// Each of the `wait` functions takes a callback function which receives any responses
22+ /// The `wait_while` function takes a callback function which receives any responses
2323/// that arrive on the channel while IDLE. The callback function implements whatever
2424/// logic is needed to handle the IDLE response, and then returns a boolean
2525/// to continue idling (`true`) or stop (`false`).
26+ ///
2627/// For users that want the IDLE to exit on any change (the behavior proior to version 3.0),
2728/// a convenience callback function [`stop_on_any`] is provided.
2829///
@@ -37,25 +38,24 @@ use std::time::Duration;
3738/// imap.select("INBOX")
3839/// .expect("Could not select mailbox");
3940///
40- /// let idle = imap.idle().expect("Could not IDLE");
41- ///
42- /// // Exit on any mailbox change
43- /// let result = idle.wait_keepalive_while(idle::stop_on_any);
41+ /// // Exit on any mailbox change. By default, connections will be periodically
42+ /// // refreshed in the background.
43+ /// let result = imap.idle().wait_while(idle::stop_on_any);
4444/// # }
4545/// ```
4646///
4747/// Note that the server MAY consider a client inactive if it has an IDLE command running, and if
4848/// such a server has an inactivity timeout it MAY log the client off implicitly at the end of its
49- /// timeout period. Because of that, clients using IDLE are advised to terminate the IDLE and
50- /// re-issue it at least every 29 minutes to avoid being logged off. [`Handle::wait_keepalive_while`]
51- /// does this. This still allows a client to receive immediate mailbox updates even though it need
52- /// only "poll" at half hour intervals.
49+ /// timeout period. Because of that, clients using IDLE are advised to terminate the IDLE and
50+ /// re-issue it at least every 29 minutes to avoid being logged off. This is done by default, but
51+ /// can be disabled by calling [`Handle::keepalive`]
5352///
5453/// As long as a [`Handle`] is active, the mailbox cannot be otherwise accessed.
5554#[ derive( Debug ) ]
5655pub struct Handle < ' a , T : Read + Write > {
5756 session : & ' a mut Session < T > ,
58- keepalive : Duration ,
57+ timeout : Duration ,
58+ keepalive : bool ,
5959 done : bool ,
6060}
6161
@@ -73,11 +73,7 @@ pub fn stop_on_any(_response: UnsolicitedResponse) -> bool {
7373 false
7474}
7575
76- /// Must be implemented for a transport in order for a `Session` using that transport to support
77- /// operations with timeouts.
78- ///
79- /// Examples of where this is useful is for `Handle::wait_keepalive_while` and
80- /// `Handle::wait_timeout_while`.
76+ /// Must be implemented for a transport in order for a `Session` to use IDLE.
8177pub trait SetReadTimeout {
8278 /// Set the timeout for subsequent reads to the given one.
8379 ///
@@ -88,14 +84,13 @@ pub trait SetReadTimeout {
8884}
8985
9086impl < ' a , T : Read + Write + ' a > Handle < ' a , T > {
91- pub ( crate ) fn make ( session : & ' a mut Session < T > ) -> Result < Self > {
92- let mut h = Handle {
87+ pub ( crate ) fn make ( session : & ' a mut Session < T > ) -> Self {
88+ Handle {
9389 session,
94- keepalive : Duration :: from_secs ( 29 * 60 ) ,
90+ timeout : Duration :: from_secs ( 29 * 60 ) ,
91+ keepalive : true ,
9592 done : false ,
96- } ;
97- h. init ( ) ?;
98- Ok ( h)
93+ }
9994 }
10095
10196 fn init ( & mut self ) -> Result < ( ) > {
@@ -132,7 +127,7 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> {
132127
133128 /// Internal helper that doesn't consume self.
134129 ///
135- /// This is necessary so that we can keep using the inner `Session` in `wait_keepalive_while `.
130+ /// This is necessary so that we can keep using the inner `Session` in `wait_while `.
136131 fn wait_inner < F > ( & mut self , reconnect : bool , mut callback : F ) -> Result < WaitOutcome >
137132 where
138133 F : FnMut ( UnsolicitedResponse ) -> bool ,
@@ -196,73 +191,48 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> {
196191 ( _, result) => result,
197192 }
198193 }
199-
200- /// Block until the given callback returns `false`, or until a response
201- /// arrives that is not explicitly handled by [`UnsolicitedResponse`].
202- pub fn wait_while < F > ( mut self , callback : F ) -> Result < ( ) >
203- where
204- F : FnMut ( UnsolicitedResponse ) -> bool ,
205- {
206- self . wait_inner ( true , callback) . map ( |_| ( ) )
207- }
208194}
209195
210196impl < ' a , T : SetReadTimeout + Read + Write + ' a > Handle < ' a , T > {
211- /// Set the keep-alive interval to use when `wait_keepalive_while` is called.
197+ /// Set the timeout duration on the connection. This will also set the frequency
198+ /// at which the connection is refreshed.
212199 ///
213- /// The interval defaults to 29 minutes as dictated by RFC 2177.
214- pub fn set_keepalive ( & mut self , interval : Duration ) {
215- self . keepalive = interval;
200+ /// The interval defaults to 29 minutes as given in RFC 2177.
201+ pub fn timeout ( & mut self , interval : Duration ) -> & mut Self {
202+ self . timeout = interval;
203+ self
204+ }
205+
206+ /// Do not continuously refresh the IDLE connection in the background.
207+ ///
208+ /// By default, connections will periodically be refreshed in the background using the
209+ /// timeout duration set by [`Handle::timeout`]. If you do not want this behaviour, call
210+ /// this function and the connection will simply IDLE until `wait_while` returns or
211+ /// the timeout expires.
212+ pub fn keepalive ( & mut self , keepalive : bool ) -> & mut Self {
213+ self . keepalive = keepalive;
214+ self
216215 }
217216
218217 /// Block until the given callback returns `false`, or until a response
219218 /// arrives that is not explicitly handled by [`UnsolicitedResponse`].
220- ///
221- /// This method differs from [`Handle::wait_while`] in that it will periodically refresh the IDLE
222- /// connection, to prevent the server from timing out our connection. The keepalive interval is
223- /// set to 29 minutes by default, as dictated by RFC 2177, but can be changed using
224- /// [`Handle::set_keepalive`].
225- ///
226- /// This is the recommended method to use for waiting.
227- pub fn wait_keepalive_while < F > ( self , callback : F ) -> Result < ( ) >
219+ pub fn wait_while < F > ( & mut self , callback : F ) -> Result < WaitOutcome >
228220 where
229221 F : FnMut ( UnsolicitedResponse ) -> bool ,
230222 {
223+ self . init ( ) ?;
231224 // The server MAY consider a client inactive if it has an IDLE command
232225 // running, and if such a server has an inactivity timeout it MAY log
233226 // the client off implicitly at the end of its timeout period. Because
234227 // of that, clients using IDLE are advised to terminate the IDLE and
235228 // re-issue it at least every 29 minutes to avoid being logged off.
236229 // This still allows a client to receive immediate mailbox updates even
237230 // though it need only "poll" at half hour intervals.
238- let keepalive = self . keepalive ;
239- self . timed_wait ( keepalive, true , callback) . map ( |_| ( ) )
240- }
241-
242- /// Block until the given given amount of time has elapsed, the given callback
243- /// returns `false`, or until a response arrives that is not explicitly handled
244- /// by [`UnsolicitedResponse`].
245- pub fn wait_with_timeout_while < F > ( self , timeout : Duration , callback : F ) -> Result < WaitOutcome >
246- where
247- F : FnMut ( UnsolicitedResponse ) -> bool ,
248- {
249- self . timed_wait ( timeout, false , callback)
250- }
251-
252- fn timed_wait < F > (
253- mut self ,
254- timeout : Duration ,
255- reconnect : bool ,
256- callback : F ,
257- ) -> Result < WaitOutcome >
258- where
259- F : FnMut ( UnsolicitedResponse ) -> bool ,
260- {
261231 self . session
262232 . stream
263233 . get_mut ( )
264- . set_read_timeout ( Some ( timeout) ) ?;
265- let res = self . wait_inner ( reconnect , callback) ;
234+ . set_read_timeout ( Some ( self . timeout ) ) ?;
235+ let res = self . wait_inner ( self . keepalive , callback) ;
266236 let _ = self . session . stream . get_mut ( ) . set_read_timeout ( None ) . is_ok ( ) ;
267237 res
268238 }
0 commit comments