diff --git a/src/connect.rs b/src/connect.rs index cc067f7..af17461 100644 --- a/src/connect.rs +++ b/src/connect.rs @@ -255,16 +255,23 @@ async fn receive_loop( ) { let mut buf = [0u8; MAX_EVENT_SIZE]; while conn.recv(&mut buf).await.is_ok() { - if let Ok(event) = buf.try_into() { - log::trace!("{addr} <==<==<== {event}"); - match event { - ProtoEvent::Pong(b) => { - client_manager.set_active_addr(handle, Some(addr)); - client_manager.set_alive(handle, b); - ping_response.borrow_mut().insert(addr); + match buf.try_into() { + Ok(event) => { + log::trace!("{addr} <==<==<== {event}"); + match event { + ProtoEvent::Pong(b) => { + client_manager.set_active_addr(handle, Some(addr)); + client_manager.set_alive(handle, b); + ping_response.borrow_mut().insert(addr); + } + event => tx.send((handle, event)).expect("channel closed"), } - event => tx.send((handle, event)).expect("channel closed"), } + // Skip undecodable datagrams without dropping the + // connection. Each DTLS recv is one framed message, so + // skipping is safe and keeps us forward-compatible with + // peers that send event types we don't yet know about. + Err(e) => log::debug!("ignoring undecodable event from {addr}: {e}"), } } log::warn!("recv error"); diff --git a/src/listen.rs b/src/listen.rs index bd50858..e0a9475 100644 --- a/src/listen.rs +++ b/src/listen.rs @@ -259,8 +259,16 @@ async fn read_loop( .send(ListenEvent::Msg { event, addr }) .expect("channel closed"), Err(e) => { - log::warn!("error receiving event: {e}"); - break; + // Skip the malformed/unknown datagram and keep + // listening. Each DTLS recv returns one full + // datagram, so a parse error here can't desync a + // stream; the next call gets a fresh, framed + // message. This makes the protocol forward- + // compatible: a peer running a newer Lan Mouse + // version can introduce additional event types + // and old peers will simply ignore them rather + // than dropping the connection. + log::debug!("ignoring undecodable event from {addr}: {e}"); } } }