Handle connection errors gracefully
Some checks failed
moparisthebest/kiss-xmpp/pipeline/head There was a failure building this commit

This commit is contained in:
Travis Burtrum 2023-12-28 23:45:08 -05:00
parent fea60c40c5
commit 4a56a0ebee
Signed by: moparisthebest
GPG Key ID: 88C93BFE27BC8229

View File

@ -1,4 +1,4 @@
use anyhow::Result; use anyhow::{bail, Result};
use die::{die, Die}; use die::{die, Die};
use env_logger::{Builder, Env, Target}; use env_logger::{Builder, Env, Target};
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -49,7 +49,7 @@ impl Context {
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() {
let mut args = Args::default(); let mut args = Args::default();
if args.flags(&["-h", "--help"]) { if args.flags(&["-h", "--help"]) {
@ -93,45 +93,67 @@ async fn main() -> Result<()> {
let context = Context::new(bare_me, contact); let context = Context::new(bare_me, contact);
let mut client = Client::new(context.bare_me.clone(), &cfg.password);
client.set_reconnect(true);
// after calling this the program can only exit with die!(), not the normal way, see comment below
let stdin = io::stdin(); let stdin = io::stdin();
let reader = BufReader::new(stdin); let reader = BufReader::new(stdin);
let mut lines = reader.lines(); let mut lines = reader.lines();
let mut client = Client::new(context.bare_me.clone(), &cfg.password); // why am I doing stupid things instead of having main return Result<> like any normal rust program?
client.set_reconnect(true); // https://docs.rs/tokio/latest/tokio/io/fn.stdin.html
// blocks until a user hits enter, so they never see errors or that we've exited until they do...
loop { let res: Result<()> = async {
tokio::select! { loop {
Some(event) = client.next() => handle_xmpp(event, &mut client, &context).await?, tokio::select! {
Ok(Some(line)) = lines.next_line() => { event = client.next() => handle_xmpp(event, &mut client, &context).await?,
if handle_line(line, &mut client, &context).await? { Ok(Some(line)) = lines.next_line() => {
break; if handle_line(line, &mut client, &context).await? {
client.set_reconnect(false);
client.send_end().await.ok(); // ignore errors here, I guess
break Ok(());
}
}
} }
} }
}
} }
.await;
// Close client connection let exit_code = match res {
client.send_end().await.ok(); // ignore errors here, I guess Err(e) => {
println!("NOTICE: fatal error: {e}");
println!("NOTICE: potentially bad jid/password in config file?");
1
}
Ok(_) => 0,
};
println!("NOTICE: kiss-xmpp exiting, goodbye!");
Ok(()) die!(exit_code)
} }
async fn handle_xmpp(event: Event, client: &mut Client, context: &Context) -> Result<()> { async fn handle_xmpp(event: Option<Event>, client: &mut Client, context: &Context) -> Result<()> {
if event.is_online() { // println!("event: {event:?}");
if context.is_muc { match event {
let join = make_join(context.contact.clone()); Some(Event::Online { .. }) => {
client.send_stanza(join).await?; if context.is_muc {
println!("NOTICE: sent room join!"); let join = make_join(context.contact.clone());
} else { client.send_stanza(join).await?;
let presence = make_presence(); println!("NOTICE: sent room join!");
client.send_stanza(presence).await?; } else {
let carbons = make_carbons_enable(); let presence = make_presence();
client.send_stanza(carbons).await?; client.send_stanza(presence).await?;
println!("NOTICE: online!"); let carbons = make_carbons_enable();
client.send_stanza(carbons).await?;
println!("NOTICE: online!");
}
} }
} else if let Some(element) = event.into_stanza() { Some(Event::Stanza(element)) => {
handle_xmpp_element(element, context).await?; handle_xmpp_element(element, context).await?;
}
Some(Event::Disconnected(e)) => Err(e)?,
None => bail!("XMPP stream ended, shouldn't happen"),
} }
Ok(()) Ok(())
} }