improve handling of some rare errors
This commit is contained in:
parent
002393b18e
commit
2a4e9ae4bc
78
src/lib.rs
78
src/lib.rs
@ -56,6 +56,7 @@ struct Status {
|
|||||||
|
|
||||||
const CONNECTION_LOST_ERRORS: &[ErrorKind] = &[
|
const CONNECTION_LOST_ERRORS: &[ErrorKind] = &[
|
||||||
ErrorKind::Interrupted,
|
ErrorKind::Interrupted,
|
||||||
|
ErrorKind::UnexpectedEOF, // server closes TLS connection without close_notify
|
||||||
ErrorKind::WouldBlock, // when a read times out
|
ErrorKind::WouldBlock, // when a read times out
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -157,7 +158,8 @@ pub fn run() -> AResult<()> {
|
|||||||
connection_status.lock().unwrap().connected = false;
|
connection_status.lock().unwrap().connected = false;
|
||||||
|
|
||||||
time_to_reconnect = 1;
|
time_to_reconnect = 1;
|
||||||
println!("Connection lost, reconnecting in {time_to_reconnect} seconds");
|
let error_kind = io_err.kind();
|
||||||
|
println!("Connection lost ({error_kind}), reconnecting in {time_to_reconnect} seconds");
|
||||||
thread::sleep(Duration::from_secs(time_to_reconnect));
|
thread::sleep(Duration::from_secs(time_to_reconnect));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -170,7 +172,9 @@ pub fn run() -> AResult<()> {
|
|||||||
if cli.verbose > 0 {
|
if cli.verbose > 0 {
|
||||||
println!("Error: {:?}", err);
|
println!("Error: {:?}", err);
|
||||||
}
|
}
|
||||||
println!("Cannot connect currently, retrying in {time_to_reconnect} seconds");
|
|
||||||
|
let error_kind = io_err.kind();
|
||||||
|
println!("Cannot connect currently ({error_kind}), retrying in {time_to_reconnect} seconds");
|
||||||
|
|
||||||
thread::sleep(Duration::from_secs(time_to_reconnect));
|
thread::sleep(Duration::from_secs(time_to_reconnect));
|
||||||
|
|
||||||
@ -235,11 +239,20 @@ pub fn connect_and_idle<F: Fn(), G: Fn()>(cli: &Cli, connected_callback: F, mail
|
|||||||
} else if tls_client.wants_read() {
|
} else if tls_client.wants_read() {
|
||||||
let _i = tls_client.read_tls(&mut socket)?;
|
let _i = tls_client.read_tls(&mut socket)?;
|
||||||
|
|
||||||
if tls_client.process_new_packets()?.plaintext_bytes_to_read() == 0 {
|
let bytes_to_read = tls_client.process_new_packets()?.plaintext_bytes_to_read();
|
||||||
|
if bytes_to_read == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let len = tls_client.reader().read(&mut buffer)?;
|
println!("Bytes to read: {bytes_to_read}");
|
||||||
|
|
||||||
|
let mut len = tls_client.reader().read(&mut buffer)?;
|
||||||
|
|
||||||
|
while len == buffer.len() {
|
||||||
|
println!("Buffer full, read again");
|
||||||
|
len = tls_client.reader().read(&mut buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let responses = buffer[0..len]
|
let responses = buffer[0..len]
|
||||||
.split(|&x|x == b'\r' || x == b'\n')
|
.split(|&x|x == b'\r' || x == b'\n')
|
||||||
@ -257,35 +270,44 @@ pub fn connect_and_idle<F: Fn(), G: Fn()>(cli: &Cli, connected_callback: F, mail
|
|||||||
}
|
}
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
ImapState::Unauthenticated => if response.starts_with(b"* OK") {
|
ImapState::Unauthenticated =>
|
||||||
let request = format!("A001 login {} {}\r\n", cli.username, cli.password);
|
if response.starts_with(b"* OK") {
|
||||||
tls_client.writer().write(request.as_bytes())?;
|
let request = format!("A001 login {} {}\r\n", cli.username, cli.password);
|
||||||
state = ImapState::Authenticated;
|
tls_client.writer().write(request.as_bytes())?;
|
||||||
},
|
state = ImapState::Authenticated;
|
||||||
ImapState::Authenticated => if response.starts_with(b"A001 OK") {
|
},
|
||||||
tls_client.writer().write(b"A002 select inbox\r\n")?;
|
ImapState::Authenticated =>
|
||||||
state = ImapState::Inbox;
|
if response.starts_with(b"A001 OK") {
|
||||||
} else if response.starts_with(b"A001") {
|
tls_client.writer().write(b"A002 select inbox\r\n")?;
|
||||||
bail!("The server rejected authentication");
|
state = ImapState::Authenticated;
|
||||||
},
|
} else if response.starts_with(b"A002 OK") {
|
||||||
ImapState::Inbox => if response.starts_with(b"A002 OK") {
|
tls_client.writer().write(b"A003 fetch 1:* all\r\n")?;
|
||||||
tls_client.writer().write(b"A003 idle\r\n")?;
|
state = ImapState::Inbox;
|
||||||
state = ImapState::Idling;
|
} else if response.starts_with(b"A001") || response.starts_with(b"A002") {
|
||||||
connected_callback();
|
bail!("The server rejected authentication");
|
||||||
// notify timer thread that we're live
|
},
|
||||||
} else if response.starts_with(b"A002") {
|
ImapState::Inbox =>
|
||||||
bail!("Selecting inbox failed");
|
if response.starts_with(b"A003 OK") {
|
||||||
},
|
tls_client.writer().write(b"A004 idle\r\n")?;
|
||||||
ImapState::Idling => if response.starts_with(b"+ idling") {
|
state = ImapState::Idling;
|
||||||
println!("Connected and idling ...");
|
connected_callback(); // notify timer thread that we're live
|
||||||
} else if response.starts_with(b"*") && response.ends_with(b"EXISTS") {
|
} else if response.starts_with(b"A002") {
|
||||||
mail_callback();
|
bail!("Selecting inbox failed");
|
||||||
}
|
},
|
||||||
|
ImapState::Idling =>
|
||||||
|
if response.starts_with(b"+ idling") {
|
||||||
|
println!("Connected and idling ...");
|
||||||
|
} else if response.starts_with(b"*") && response.ends_with(b"EXISTS") {
|
||||||
|
mail_callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if wants_read() and wants_write() are both false, this usually means the connection was closed
|
// if wants_read() and wants_write() are both false, this usually means the connection was closed
|
||||||
// so just return "Interrupted" and reconnect after a few seconds
|
// so just return "Interrupted" and reconnect after a few seconds
|
||||||
|
if cli.verbose > 0 {
|
||||||
|
println!("wants_read() and wants_write() are both false");
|
||||||
|
}
|
||||||
return Err(io::Error::new(ErrorKind::Interrupted, "Connection was closed by server").into());
|
return Err(io::Error::new(ErrorKind::Interrupted, "Connection was closed by server").into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user