|
2 | 2 | use super::{DeviceEnrollment, Error, Result, ServerPairUrl};
|
3 | 3 | use crate::NetworkAccount;
|
4 | 4 | use futures::{
|
5 |
| - select, |
6 | 5 | stream::{SplitSink, SplitStream},
|
7 |
| - FutureExt, SinkExt, StreamExt, |
| 6 | + SinkExt, StreamExt, |
8 | 7 | };
|
9 | 8 | use prost::bytes::Bytes;
|
10 | 9 | use snow::{Builder, HandshakeState, Keypair, TransportState};
|
@@ -70,7 +69,7 @@ enum IncomingAction {
|
70 | 69 | HandleMessage(PairingMessage),
|
71 | 70 | }
|
72 | 71 |
|
73 |
| -/// Listen for incoming messages on the stream. |
| 72 | +/// Listen for incoming messages on the websocket stream. |
74 | 73 | async fn listen(
|
75 | 74 | mut rx: WsStream,
|
76 | 75 | tx: mpsc::Sender<RelayPacket>,
|
@@ -102,6 +101,7 @@ async fn listen(
|
102 | 101 | }
|
103 | 102 | }
|
104 | 103 | }
|
| 104 | + tracing::debug!("pairing::websocket::connection_closed"); |
105 | 105 | }
|
106 | 106 |
|
107 | 107 | /// Offer is the device that is authenticated and can
|
@@ -217,26 +217,29 @@ impl<'a> OfferPairing<'a> {
|
217 | 217 | let (close_tx, mut close_rx) = mpsc::channel::<()>(1);
|
218 | 218 | tokio::task::spawn(listen(stream, offer_tx, close_tx));
|
219 | 219 | loop {
|
220 |
| - select! { |
221 |
| - event = offer_rx.recv().fuse() => { |
222 |
| - if let Some(event) = event { |
223 |
| - self.incoming(event).await?; |
224 |
| - if self.is_finished() { |
225 |
| - break; |
226 |
| - } |
| 220 | + tokio::select! { |
| 221 | + biased; |
| 222 | + // Explicit shutdown notification |
| 223 | + Some(_) = shutdown_rx.recv() => { |
| 224 | + tracing::debug!("pairing::offer::shutdown_received"); |
| 225 | + if let Err(error) = self.tx.send(Message::Close(Some(CloseFrame { |
| 226 | + code: CloseCode::Normal, |
| 227 | + reason: Utf8Bytes::from_static("closed"), |
| 228 | + }))).await { |
| 229 | + tracing::error!( |
| 230 | + error = %error, |
| 231 | + "pairing::offer::websocket_close_frame::error"); |
227 | 232 | }
|
| 233 | + break; |
228 | 234 | }
|
229 |
| - event = close_rx.recv().fuse() => { |
230 |
| - if event.is_some() { |
231 |
| - break; |
232 |
| - } |
| 235 | + // Close signal from the websocket stream |
| 236 | + Some(_) = close_rx.recv() => { |
| 237 | + break; |
233 | 238 | }
|
234 |
| - event = shutdown_rx.recv().fuse() => { |
235 |
| - if event.is_some() { |
236 |
| - let _ = self.tx.send(Message::Close(Some(CloseFrame { |
237 |
| - code: CloseCode::Normal, |
238 |
| - reason: Utf8Bytes::from_static("closed"), |
239 |
| - }))).await; |
| 239 | + // Incoming event |
| 240 | + Some(event) = offer_rx.recv() => { |
| 241 | + self.incoming(event).await?; |
| 242 | + if self.is_finished() { |
240 | 243 | break;
|
241 | 244 | }
|
242 | 245 | }
|
@@ -633,26 +636,27 @@ impl<'a> AcceptPairing<'a> {
|
633 | 636 | tokio::task::spawn(listen(stream, offer_tx, close_tx));
|
634 | 637 |
|
635 | 638 | loop {
|
636 |
| - select! { |
637 |
| - event = offer_rx.recv().fuse() => { |
| 639 | + tokio::select! { |
| 640 | + biased; |
| 641 | + event = shutdown_rx.recv() => { |
| 642 | + if event.is_some() { |
| 643 | + let _ = self.tx.send(Message::Close(Some(CloseFrame { |
| 644 | + code: CloseCode::Normal, |
| 645 | + reason: Utf8Bytes::from_static("closed"), |
| 646 | + }))).await; |
| 647 | + break; |
| 648 | + } |
| 649 | + } |
| 650 | + event = offer_rx.recv() => { |
638 | 651 | if let Some(event) = event {
|
639 | 652 | self.incoming(event).await?;
|
640 | 653 | if self.is_finished() {
|
641 | 654 | break;
|
642 | 655 | }
|
643 | 656 | }
|
644 | 657 | }
|
645 |
| - event = close_rx.recv().fuse() => { |
646 |
| - if event.is_some() { |
647 |
| - break; |
648 |
| - } |
649 |
| - } |
650 |
| - event = shutdown_rx.recv().fuse() => { |
| 658 | + event = close_rx.recv() => { |
651 | 659 | if event.is_some() {
|
652 |
| - let _ = self.tx.send(Message::Close(Some(CloseFrame { |
653 |
| - code: CloseCode::Normal, |
654 |
| - reason: Utf8Bytes::from_static("closed"), |
655 |
| - }))).await; |
656 | 660 | break;
|
657 | 661 | }
|
658 | 662 | }
|
|
0 commit comments