refactor network manager

This commit is contained in:
John Smith
2022-05-31 19:54:52 -04:00
parent ad4b6328ac
commit 8148c37708
51 changed files with 500 additions and 389 deletions

View File

@@ -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::*;

View File

@@ -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(())
}
}

View File

@@ -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,
}
}
}

View File

@@ -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
}
}