From fb674be4dd45103b588138644b3ed866c7c79b9c Mon Sep 17 00:00:00 2001
From: Louis Capitanchik <contact@louiscap.co>
Date: Sun, 31 Jul 2022 03:08:41 +0100
Subject: [PATCH] Handle disconnect for web target

---
 Cargo.toml  |  2 +-
 README.md   |  5 ++++-
 src/wasm.rs | 40 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 87b68ce..8640038 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,4 +19,4 @@ features = []
 websocket = { version = "0.26.5" , default-features = false, features = ["sync", "sync-ssl", "bytes", "native-tls"]}
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
-wasm-sockets = "0.2.2"
+wasm-sockets = { git = "https://lab.lcr.gr/microhacks/wasm-sockets.git", rev = "5c8bdb2a54c1acfd816587bfcd5f64a34b3740b4" }
diff --git a/README.md b/README.md
index 9b01bf5..078616b 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,10 @@ This library is quite immature; many features still need to be added for it to b
 - [x] WS Connection from wasm
 - [x] Frame independent event buffering
 - [x] User initiated disconnect on desktop
-- [ ] User initiated disconnect on wasm
+- [x] User initiated disconnect on wasm
+- [x] Handle remote disconnect
+- [ ] Emit events for non-user-initiated lifecycle events
+- [ ] Correctly track status of underlying connection
 - [ ] Automatic reconnection
 - [x] Map received events to user defined types
 - [x] Send events of a user defined type
diff --git a/src/wasm.rs b/src/wasm.rs
index 70629ae..68fcc40 100644
--- a/src/wasm.rs
+++ b/src/wasm.rs
@@ -1,5 +1,6 @@
 use std::fmt::Debug;
 use std::marker::PhantomData;
+use std::ops::Deref;
 use std::sync::{Arc, Mutex};
 
 use bevy::ecs::event::Events;
@@ -9,7 +10,7 @@ use bevy::prelude::{
 	IntoExclusiveSystem, NonSendMut, Plugin, ResMut, World,
 };
 use thiserror::Error;
-use wasm_sockets::Message;
+use wasm_sockets::{EventClient, Message};
 
 use crate::events::{FromSocketMessage, SocketControlEvent, SocketState, ToSocketMessage};
 
@@ -34,6 +35,21 @@ where
 	client: wasm_sockets::PollingClient,
 }
 
+pub trait ClosableExt {
+	fn close(&mut self);
+}
+
+impl<SentMessageType, ReceivedMessageType> Drop
+	for RemoteEventDispatcher<SentMessageType, ReceivedMessageType>
+where
+	ReceivedMessageType: FromSocketMessage + Send + Sync + 'static,
+	SentMessageType: ToSocketMessage + Send + Sync + 'static,
+{
+	fn drop(&mut self) {
+		self.client.close();
+	}
+}
+
 fn connect_to<SentMessageType, ReceivedMessageType, T: ToString>(
 	remote_host: T,
 ) -> crate::events::RemoteEventResult<RemoteEventDispatcher<SentMessageType, ReceivedMessageType>>
@@ -61,6 +77,7 @@ where
 	)> = SystemState::new(&mut world);
 
 	let mut client_to_insert = None;
+	let mut remove_client = false;
 
 	{
 		let (mut maybe_client, mut reader): (
@@ -68,6 +85,18 @@ where
 			EventReader<SocketControlEvent>,
 		) = state.get_mut(&mut world);
 
+		if let Some(ref client) = maybe_client {
+			if client.client.status.borrow().deref()
+				== &wasm_sockets::ConnectionStatus::Disconnected
+			{
+				#[rustfmt::skip]
+				// rustfmt breaks the ending "();" to put ");" on its own line...
+				let it = world.remove_non_send_resource::<RemoteEventDispatcher<SentMessageType, ReceivedMessageType>>();
+				drop(it);
+				return;
+			}
+		}
+
 		for event in reader.iter() {
 			match event {
 				SocketControlEvent::Create(url) => {
@@ -90,7 +119,7 @@ where
 				}
 				SocketControlEvent::Disconnect => match maybe_client {
 					Some(ref client) => {
-						log::warn!("NOT IMPLEMENTED: Disconnect");
+						remove_client = true;
 					}
 					None => {
 						log::warn!("There was no connection to disconnect from");
@@ -100,6 +129,13 @@ where
 		}
 	};
 
+	if remove_client {
+		#[rustfmt::skip]
+		// rustfmt breaks the ending "();" to put ");" on its own line...
+		let it = world.remove_non_send_resource::<RemoteEventDispatcher<SentMessageType, ReceivedMessageType>>();
+		drop(it);
+	}
+
 	if let Some(new_client) = client_to_insert {
 		world.insert_non_send_resource(new_client);
 	}
-- 
GitLab