use std::cell::RefCell;
use std::rc::Rc;
use log::debug;
use wasm_bindgen::JsValue;
use wasm_peers_protocol::SessionId;
use web_sys::{RtcDataChannel, RtcPeerConnection, WebSocket};
use crate::one_to_one::callbacks::{
set_data_channel_on_error, set_data_channel_on_message, set_data_channel_on_open,
set_peer_connection_on_data_channel, set_peer_connection_on_ice_candidate,
set_peer_connection_on_ice_connection_state_change,
set_peer_connection_on_ice_gathering_state_change, set_peer_connection_on_negotiation_needed,
set_websocket_on_message, set_websocket_on_open,
};
use crate::utils::{create_peer_connection, ConnectionType};
mod callbacks;
mod websocket_handler;
#[derive(Debug, Clone)]
pub(crate) struct NetworkManagerInner {
session_id: SessionId,
websocket: WebSocket,
peer_connection: RtcPeerConnection,
pub(crate) data_channel: Option<RtcDataChannel>,
}
#[derive(Debug, Clone)]
pub struct NetworkManager {
pub(crate) inner: Rc<RefCell<NetworkManagerInner>>,
}
impl NetworkManager {
pub fn new(
signaling_server_url: &str,
session_id: SessionId,
connection_type: ConnectionType,
) -> Result<Self, JsValue> {
let peer_connection = create_peer_connection(&connection_type)?;
let websocket = WebSocket::new(signaling_server_url)?;
websocket.set_binary_type(web_sys::BinaryType::Arraybuffer);
Ok(NetworkManager {
inner: Rc::new(RefCell::new(NetworkManagerInner {
session_id,
websocket,
peer_connection,
data_channel: None,
})),
})
}
pub fn start(
&mut self,
on_open_callback: impl FnMut() + Clone + 'static,
on_message_callback: impl FnMut(String) + Clone + 'static,
) -> Result<(), JsValue> {
let NetworkManagerInner {
websocket,
peer_connection,
session_id,
..
} = self.inner.borrow().clone();
let data_channel = peer_connection.create_data_channel(&session_id.clone().into_inner());
debug!(
"data_channel created with label: {:?}",
data_channel.label()
);
set_data_channel_on_open(&data_channel, on_open_callback.clone());
set_data_channel_on_error(&data_channel);
set_data_channel_on_message(&data_channel, on_message_callback.clone());
self.inner.borrow_mut().data_channel = Some(data_channel);
set_peer_connection_on_data_channel(
&peer_connection,
self.clone(),
on_open_callback,
on_message_callback,
);
set_peer_connection_on_ice_candidate(
&peer_connection,
websocket.clone(),
session_id.clone(),
);
set_peer_connection_on_ice_connection_state_change(&peer_connection);
set_peer_connection_on_ice_gathering_state_change(&peer_connection);
set_peer_connection_on_negotiation_needed(&peer_connection);
set_websocket_on_open(&websocket, session_id);
set_websocket_on_message(&websocket, peer_connection);
Ok(())
}
fn datachannel(&self) -> Result<RtcDataChannel, JsValue> {
Ok(self
.inner
.borrow()
.data_channel
.as_ref()
.ok_or_else(|| JsValue::from_str("no data channel set on instance yet"))?
.clone())
}
pub fn send_message(&self, message: &str) -> Result<(), JsValue> {
debug!("server will try to send a message: {:?}", &message);
self.datachannel()?.send_with_str(&format!("x{}", message))
}
pub fn send_u8_array(&self, message: &[u8]) -> Result<(), JsValue> {
self.datachannel()?.send_with_u8_array(message)
}
}