refactor network manager
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
mod block_store;
|
||||
mod network;
|
||||
mod protected_store;
|
||||
mod system;
|
||||
mod table_store;
|
||||
|
||||
pub mod utils;
|
||||
|
||||
pub use block_store::*;
|
||||
pub use network::*;
|
||||
pub use protected_store::*;
|
||||
pub use system::*;
|
||||
pub use table_store::*;
|
||||
|
@@ -1,235 +0,0 @@
|
||||
mod protocol;
|
||||
|
||||
use crate::connection_manager::*;
|
||||
use crate::network_manager::*;
|
||||
use crate::routing_table::*;
|
||||
use crate::intf::*;
|
||||
use crate::*;
|
||||
use protocol::ws::WebsocketProtocolHandler;
|
||||
pub use protocol::*;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
struct NetworkInner {
|
||||
network_manager: NetworkManager,
|
||||
stop_network: Eventual,
|
||||
network_started: bool,
|
||||
network_needs_restart: bool,
|
||||
protocol_config: Option<ProtocolConfig>,
|
||||
//join_handle: TryJoin?
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Network {
|
||||
config: VeilidConfig,
|
||||
inner: Arc<Mutex<NetworkInner>>,
|
||||
}
|
||||
|
||||
impl Network {
|
||||
fn new_inner(network_manager: NetworkManager) -> NetworkInner {
|
||||
NetworkInner {
|
||||
network_manager,
|
||||
stop_network: Eventual::new(),
|
||||
network_started: false,
|
||||
network_needs_restart: false,
|
||||
protocol_config: None, //join_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(network_manager: NetworkManager) -> Self {
|
||||
Self {
|
||||
config: network_manager.config(),
|
||||
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn network_manager(&self) -> NetworkManager {
|
||||
self.inner.lock().network_manager.clone()
|
||||
}
|
||||
fn connection_manager(&self) -> ConnectionManager {
|
||||
self.inner.lock().network_manager.connection_manager()
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
pub async fn send_data_unbound_to_dial_info(
|
||||
&self,
|
||||
dial_info: DialInfo,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), String> {
|
||||
let data_len = data.len();
|
||||
|
||||
let res = match dial_info.protocol_type() {
|
||||
ProtocolType::UDP => {
|
||||
return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
ProtocolType::TCP => {
|
||||
return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
ProtocolType::WS | ProtocolType::WSS => {
|
||||
WebsocketProtocolHandler::send_unbound_message(dial_info.clone(), data)
|
||||
.await
|
||||
.map_err(logthru_net!())
|
||||
}
|
||||
};
|
||||
if res.is_ok() {
|
||||
// Network accounting
|
||||
self.network_manager()
|
||||
.stats_packet_sent(dial_info.to_ip_addr(), data_len as u64);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub async fn send_data_to_existing_connection(
|
||||
&self,
|
||||
descriptor: ConnectionDescriptor,
|
||||
data: Vec<u8>,
|
||||
) -> Result<Option<Vec<u8>>, String> {
|
||||
let data_len = data.len();
|
||||
match descriptor.protocol_type() {
|
||||
ProtocolType::UDP => {
|
||||
return Err("no support for udp protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
ProtocolType::TCP => {
|
||||
return Err("no support for tcp protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Handle connection-oriented protocols
|
||||
|
||||
// Try to send to the exact existing connection if one exists
|
||||
if let Some(conn) = self.connection_manager().get_connection(descriptor).await {
|
||||
// connection exists, send over it
|
||||
conn.send(data).await.map_err(logthru_net!())?;
|
||||
|
||||
// Network accounting
|
||||
self.network_manager()
|
||||
.stats_packet_sent(descriptor.remote.to_socket_addr().ip(), data_len as u64);
|
||||
|
||||
// Data was consumed
|
||||
Ok(None)
|
||||
} else {
|
||||
// Connection or didn't exist
|
||||
// Pass the data back out so we don't own it any more
|
||||
Ok(Some(data))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_data_to_dial_info(
|
||||
&self,
|
||||
dial_info: DialInfo,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), String> {
|
||||
let data_len = data.len();
|
||||
if dial_info.protocol_type() == ProtocolType::UDP {
|
||||
return Err("no support for UDP protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
if dial_info.protocol_type() == ProtocolType::TCP {
|
||||
return Err("no support for TCP protocol".to_owned()).map_err(logthru_net!(error))
|
||||
}
|
||||
|
||||
// Handle connection-oriented protocols
|
||||
let conn = self
|
||||
.connection_manager()
|
||||
.get_or_create_connection(None, dial_info.clone())
|
||||
.await?;
|
||||
|
||||
let res = conn.send(data).await.map_err(logthru_net!(error));
|
||||
if res.is_ok() {
|
||||
// Network accounting
|
||||
self.network_manager()
|
||||
.stats_packet_sent(dial_info.to_ip_addr(), data_len as u64);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
pub async fn startup(&self) -> Result<(), String> {
|
||||
// get protocol config
|
||||
self.inner.lock().protocol_config = Some({
|
||||
let c = self.config.get();
|
||||
let inbound = ProtocolSet::new();
|
||||
let mut outbound = ProtocolSet::new();
|
||||
|
||||
if c.network.protocol.ws.connect && c.capabilities.protocol_connect_ws {
|
||||
outbound.insert(ProtocolType::WS);
|
||||
}
|
||||
if c.network.protocol.wss.connect && c.capabilities.protocol_connect_wss {
|
||||
outbound.insert(ProtocolType::WSS);
|
||||
}
|
||||
|
||||
ProtocolConfig { inbound, outbound }
|
||||
});
|
||||
|
||||
self.inner.lock().network_started = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn needs_restart(&self) -> bool {
|
||||
self.inner.lock().network_needs_restart
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().network_started
|
||||
}
|
||||
|
||||
pub fn restart_network(&self) {
|
||||
self.inner.lock().network_needs_restart = true;
|
||||
}
|
||||
|
||||
pub async fn shutdown(&self) {
|
||||
trace!("stopping network");
|
||||
|
||||
// Reset state
|
||||
let network_manager = self.inner.lock().network_manager.clone();
|
||||
let routing_table = network_manager.routing_table();
|
||||
|
||||
// Drop all dial info
|
||||
routing_table.clear_dial_info_details(RoutingDomain::PublicInternet);
|
||||
routing_table.clear_dial_info_details(RoutingDomain::LocalNetwork);
|
||||
|
||||
// Cancels all async background tasks by dropping join handles
|
||||
*self.inner.lock() = Self::new_inner(network_manager);
|
||||
|
||||
trace!("network stopped");
|
||||
}
|
||||
|
||||
pub fn with_interface_addresses<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&[IpAddr]) -> R,
|
||||
{
|
||||
f(&[])
|
||||
}
|
||||
|
||||
pub async fn check_interface_addresses(&self) -> Result<bool, String> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
pub fn get_network_class(&self) -> Option<NetworkClass> {
|
||||
// xxx eventually detect tor browser?
|
||||
return if self.inner.lock().network_started {
|
||||
Some(NetworkClass::WebApp)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
pub fn reset_network_class(&self) {
|
||||
//let mut inner = self.inner.lock();
|
||||
//inner.network_class = None;
|
||||
}
|
||||
|
||||
pub fn get_protocol_config(&self) -> Option<ProtocolConfig> {
|
||||
self.inner.lock().protocol_config.clone()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
pub async fn tick(&self) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
pub mod wrtc;
|
||||
pub mod ws;
|
||||
|
||||
use crate::network_connection::*;
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProtocolNetworkConnection {
|
||||
Dummy(DummyNetworkConnection),
|
||||
Ws(ws::WebsocketNetworkConnection),
|
||||
//WebRTC(wrtc::WebRTCNetworkConnection),
|
||||
}
|
||||
|
||||
impl ProtocolNetworkConnection {
|
||||
pub async fn connect(
|
||||
local_address: Option<SocketAddr>,
|
||||
dial_info: DialInfo,
|
||||
) -> Result<NetworkConnection, String> {
|
||||
match dial_info.protocol_type() {
|
||||
ProtocolType::UDP => {
|
||||
panic!("UDP dial info is not support on WASM targets");
|
||||
}
|
||||
ProtocolType::TCP => {
|
||||
panic!("TCP dial info is not support on WASM targets");
|
||||
}
|
||||
ProtocolType::WS | ProtocolType::WSS => {
|
||||
ws::WebsocketProtocolHandler::connect(local_address, dial_info).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_unbound_message(
|
||||
dial_info: DialInfo,
|
||||
data: Vec<u8>,
|
||||
) -> Result<(), String> {
|
||||
match dial_info.protocol_type() {
|
||||
ProtocolType::UDP => {
|
||||
panic!("UDP dial info is not support on WASM targets");
|
||||
}
|
||||
ProtocolType::TCP => {
|
||||
panic!("TCP dial info is not support on WASM targets");
|
||||
}
|
||||
ProtocolType::WS | ProtocolType::WSS => {
|
||||
ws::WebsocketProtocolHandler::send_unbound_message(dial_info, data).await
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.close(),
|
||||
Self::Ws(w) => w.close().await,
|
||||
}
|
||||
}
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.send(message),
|
||||
Self::Ws(w) => w.send(message).await,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
match self {
|
||||
Self::Dummy(d) => d.recv(),
|
||||
Self::Ws(w) => w.recv().await,
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,123 +0,0 @@
|
||||
use crate::intf::*;
|
||||
use crate::network_connection::*;
|
||||
use crate::network_manager::MAX_MESSAGE_SIZE;
|
||||
use crate::*;
|
||||
use alloc::fmt;
|
||||
use ws_stream_wasm::*;
|
||||
use futures_util::{StreamExt, SinkExt};
|
||||
|
||||
struct WebsocketNetworkConnectionInner {
|
||||
ws_meta: WsMeta,
|
||||
ws_stream: CloneStream<WsStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WebsocketNetworkConnection {
|
||||
inner: Arc<WebsocketNetworkConnectionInner>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for WebsocketNetworkConnection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", core::any::type_name::<Self>())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebsocketNetworkConnection {
|
||||
pub fn new(ws_meta: WsMeta, ws_stream: WsStream) -> Self {
|
||||
Self {
|
||||
inner: Arc::new(WebsocketNetworkConnectionInner {
|
||||
ws_meta,
|
||||
ws_stream: CloneStream::new(ws_stream),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn close(&self) -> Result<(), String> {
|
||||
self.inner.ws_meta.close().await.map_err(map_to_string).map(drop)
|
||||
}
|
||||
|
||||
pub async fn send(&self, message: Vec<u8>) -> Result<(), String> {
|
||||
if message.len() > MAX_MESSAGE_SIZE {
|
||||
return Err("sending too large WS message".to_owned()).map_err(logthru_net!(error));
|
||||
}
|
||||
self.inner.ws_stream.clone()
|
||||
.send(WsMessage::Binary(message)).await
|
||||
.map_err(|_| "failed to send to websocket".to_owned())
|
||||
.map_err(logthru_net!(error))
|
||||
}
|
||||
pub async fn recv(&self) -> Result<Vec<u8>, String> {
|
||||
let out = match self.inner.ws_stream.clone().next().await {
|
||||
Some(WsMessage::Binary(v)) => v,
|
||||
Some(_) => {
|
||||
return Err("Unexpected WS message type".to_owned())
|
||||
.map_err(logthru_net!(error));
|
||||
}
|
||||
None => {
|
||||
return Err("WS stream closed".to_owned()).map_err(logthru_net!(error));
|
||||
}
|
||||
};
|
||||
if out.len() > MAX_MESSAGE_SIZE {
|
||||
Err("sending too large WS message".to_owned()).map_err(logthru_net!(error))
|
||||
} else {
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///
|
||||
|
||||
pub struct WebsocketProtocolHandler {}
|
||||
|
||||
impl WebsocketProtocolHandler {
|
||||
pub async fn connect(
|
||||
local_address: Option<SocketAddr>,
|
||||
dial_info: DialInfo,
|
||||
) -> Result<NetworkConnection, String> {
|
||||
|
||||
assert!(local_address.is_none());
|
||||
|
||||
// Split dial info up
|
||||
let (_tls, scheme) = match &dial_info {
|
||||
DialInfo::WS(_) => (false, "ws"),
|
||||
DialInfo::WSS(_) => (true, "wss"),
|
||||
_ => panic!("invalid dialinfo for WS/WSS protocol"),
|
||||
};
|
||||
let request = dial_info.request().unwrap();
|
||||
let split_url = SplitUrl::from_str(&request)?;
|
||||
if split_url.scheme != scheme {
|
||||
return Err("invalid websocket url scheme".to_string());
|
||||
}
|
||||
|
||||
let (wsmeta, wsio) = WsMeta::connect(request, None)
|
||||
.await
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!(error))?;
|
||||
|
||||
// Make our connection descriptor
|
||||
|
||||
Ok(NetworkConnection::from_protocol(ConnectionDescriptor {
|
||||
local: None,
|
||||
remote: dial_info.to_peer_address(),
|
||||
},ProtocolNetworkConnection::Ws(WebsocketNetworkConnection::new(wsmeta, wsio))))
|
||||
}
|
||||
|
||||
pub async fn send_unbound_message(dial_info: DialInfo, data: Vec<u8>) -> Result<(), String> {
|
||||
if data.len() > MAX_MESSAGE_SIZE {
|
||||
return Err("sending too large unbound WS message".to_owned());
|
||||
}
|
||||
trace!(
|
||||
"sending unbound websocket message of length {} to {}",
|
||||
data.len(),
|
||||
dial_info,
|
||||
);
|
||||
|
||||
// Make the real connection
|
||||
let conn = Self::connect(None, dial_info)
|
||||
.await
|
||||
.map_err(|e| format!("failed to connect websocket for unbound message: {}", e))?;
|
||||
|
||||
conn.send(data).await
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user