initial import of main veilid core

This commit is contained in:
John Smith
2021-11-22 11:28:30 -05:00
parent c4cd54e020
commit 9e94a6a96f
218 changed files with 34880 additions and 1 deletions

View File

@@ -0,0 +1,179 @@
mod protocol;
use crate::intf::*;
use crate::network_manager::*;
use crate::routing_table::*;
use crate::*;
use protocol::ws::WebsocketProtocolHandler;
pub use protocol::*;
/////////////////////////////////////////////////////////////////
struct NetworkInner {
network_manager: NetworkManager,
stop_network: Eventual,
network_needs_restart: bool,
//join_handle: TryJoin?
}
#[derive(Clone)]
pub struct Network {
inner: Arc<Mutex<NetworkInner>>,
}
impl Network {
fn new_inner(network_manager: NetworkManager) -> NetworkInner {
NetworkInner {
network_manager: network_manager,
stop_network: Eventual::new(),
network_needs_restart: false,
//join_handle: None,
}
}
pub fn new(network_manager: NetworkManager) -> Self {
Self {
inner: Arc::new(Mutex::new(Self::new_inner(network_manager))),
}
}
/////////////////////////////////////////////////////////////////
async fn send_data_to_existing_connection(
&self,
descriptor: &ConnectionDescriptor,
data: Vec<u8>,
) -> Result<Option<Vec<u8>>, String> {
match descriptor.protocol_type() {
ProtocolType::UDP => return Err("no support for udp protocol".to_owned()),
ProtocolType::TCP => return Err("no support for tcp protocol".to_owned()),
ProtocolType::WS | ProtocolType::WSS => {
// find an existing connection in the connection table if one exists
let network_manager = self.inner.lock().network_manager.clone();
if let Some(entry) = network_manager
.connection_table()
.get_connection(&descriptor)
{
// connection exists, send over it
entry
.conn
.send(data)
.await
.map_err(|_| "failed to send ws message".to_owned())?;
// Data was consumed
return Ok(None);
}
}
}
// connection or local socket didn't exist, we'll need to use dialinfo to create one
// Pass the data back out so we don't own it any more
Ok(Some(data))
}
pub async fn send_data_unbound_to_dial_info(
&self,
dial_info: &DialInfo,
data: Vec<u8>,
) -> Result<(), String> {
let network_manager = self.inner.lock().network_manager.clone();
match &dial_info {
DialInfo::UDP(_) => return Err("no support for UDP protocol".to_owned()),
DialInfo::TCP(_) => return Err("no support for TCP protocol".to_owned()),
DialInfo::WS(_) => Err("WS protocol does not support unbound messages".to_owned()),
DialInfo::WSS(_) => Err("WSS protocol does not support unbound messages".to_owned()),
}
}
pub async fn send_data_to_dial_info(
&self,
dial_info: &DialInfo,
data: Vec<u8>,
) -> Result<(), String> {
let network_manager = self.inner.lock().network_manager.clone();
let conn = match &dial_info {
DialInfo::UDP(_) => return Err("no support for UDP protocol".to_owned()),
DialInfo::TCP(_) => return Err("no support for TCP protocol".to_owned()),
DialInfo::WS(_) => WebsocketProtocolHandler::connect(network_manager, dial_info)
.await
.map_err(|_| "failed to connect to WS dial info".to_owned())?,
DialInfo::WSS(_) => WebsocketProtocolHandler::connect(network_manager, dial_info)
.await
.map_err(|_| "failed to connect to WSS dial info".to_owned())?,
};
conn.send(data)
.await
.map_err(|_| "failed to send data to dial info".to_owned())
}
pub async fn send_data(&self, node_ref: NodeRef, data: Vec<u8>) -> Result<(), String> {
let dial_info = node_ref.dial_info();
let descriptor = node_ref.last_connection();
// First try to send data to the last socket we've seen this peer on
let di_data = if let Some(descriptor) = descriptor {
match self
.clone()
.send_data_to_existing_connection(&descriptor, data)
.await?
{
None => {
return Ok(());
}
Some(d) => d,
}
} else {
data
};
// If that fails, try to make a connection or reach out to the peer via its dial info
if let Some(di) = dial_info {
self.clone().send_data_to_dial_info(&di, di_data).await
} else {
Err("couldn't send data, no dial info or peer address".to_owned())
}
}
/////////////////////////////////////////////////////////////////
pub async fn startup(&self) -> Result<(), String> {
//let network_manager = self.inner.lock().network_manager.clone();
//let config_shared = network_manager.core().config();
//let config = config_shared.get();
Ok(())
}
pub fn needs_restart(&self) -> bool {
self.inner.lock().network_needs_restart
}
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_local_dial_info();
routing_table.clear_public_dial_info();
// Cancels all async background tasks by dropping join handles
*self.inner.lock() = Self::new_inner(network_manager);
trace!("network stopped");
}
//////////////////////////////////////////
pub fn get_network_class(&self) -> NetworkClass {
// xxx eventually detect tor browser?
return NetworkClass::WebApp;
}
//////////////////////////////////////////
pub async fn tick(&self) -> Result<(), String> {
Ok(())
}
}

View File

@@ -0,0 +1,48 @@
pub mod wrtc;
pub mod ws;
use crate::veilid_api::ProtocolType;
use crate::xx::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DummyNetworkConnection {}
impl DummyNetworkConnection {
pub fn protocol_type(&self) -> ProtocolType {
ProtocolType::UDP
}
pub fn send(&self, _message: Vec<u8>) -> SystemPinBoxFuture<Result<(), ()>> {
Box::pin(async { Ok(()) })
}
pub fn recv(&self) -> SystemPinBoxFuture<Result<Vec<u8>, ()>> {
Box::pin(async { Ok(Vec::new()) })
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum NetworkConnection {
Dummy(DummyNetworkConnection),
WS(ws::WebsocketNetworkConnection),
//WebRTC(wrtc::WebRTCNetworkConnection),
}
impl NetworkConnection {
pub fn protocol_type(&self) -> ProtocolType {
match self {
Self::Dummy(d) => d.protocol_type(),
Self::WS(w) => w.protocol_type(),
}
}
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), ()>> {
match self {
Self::Dummy(d) => d.send(message),
Self::WS(w) => w.send(message),
}
}
pub fn recv(&self) -> SystemPinBoxFuture<Result<Vec<u8>, ()>> {
match self {
Self::Dummy(d) => d.recv(),
Self::WS(w) => w.recv(),
}
}
}

View File

@@ -0,0 +1,116 @@
use crate::intf::*;
use crate::network_manager::{NetworkManager, MAX_MESSAGE_SIZE};
use crate::*;
use alloc::fmt;
use futures_util::stream::StreamExt;
use web_sys::WebSocket;
use ws_stream_wasm::*;
struct WebsocketNetworkConnectionInner {
_ws_meta: WsMeta,
ws_stream: WsStream,
ws: WebSocket,
}
#[derive(Clone)]
pub struct WebsocketNetworkConnection {
tls: bool,
inner: Arc<Mutex<WebsocketNetworkConnectionInner>>,
}
impl fmt::Debug for WebsocketNetworkConnection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", core::any::type_name::<Self>())
}
}
impl PartialEq for WebsocketNetworkConnection {
fn eq(&self, other: &Self) -> bool {
self.tls == other.tls && Arc::as_ptr(&self.inner) == Arc::as_ptr(&other.inner)
}
}
impl Eq for WebsocketNetworkConnection {}
impl WebsocketNetworkConnection {
pub fn new(tls: bool, ws_meta: WsMeta, ws_stream: WsStream) -> Self {
let ws = ws_stream.wrapped().clone();
Self {
tls: tls,
inner: Arc::new(Mutex::new(WebsocketNetworkConnectionInner {
_ws_meta: ws_meta,
ws_stream: ws_stream,
ws: ws,
})),
}
}
}
impl WebsocketNetworkConnection {
pub fn protocol_type(&self) -> ProtocolType {
if self.tls {
ProtocolType::WSS
} else {
ProtocolType::WS
}
}
pub fn send(&self, message: Vec<u8>) -> SystemPinBoxFuture<Result<(), ()>> {
let inner = self.inner.clone();
Box::pin(async move {
if message.len() > MAX_MESSAGE_SIZE {
return Err(());
}
inner.lock().ws.send_with_u8_array(&message).map_err(drop)
})
}
pub fn recv(&self) -> SystemPinBoxFuture<Result<Vec<u8>, ()>> {
let inner = self.inner.clone();
Box::pin(async move {
let out = match inner.lock().ws_stream.next().await {
Some(WsMessage::Binary(v)) => v,
_ => {
trace!("websocket recv failed");
return Err(());
}
};
if out.len() > MAX_MESSAGE_SIZE {
Err(())
} else {
Ok(out)
}
})
}
}
///////////////////////////////////////////////////////////
///
pub struct WebsocketProtocolHandler {}
impl WebsocketProtocolHandler {
pub async fn connect(
network_manager: NetworkManager,
dial_info: &DialInfo,
) -> Result<NetworkConnection, ()> {
let url = dial_info.to_url_string(None);
let (tls, host, port, protocol_type) = match dial_info {
DialInfo::WS(ws) => (false, ws.fqdn.clone(), ws.port, ProtocolType::WS),
DialInfo::WSS(wss) => (true, wss.fqdn.clone(), wss.port, ProtocolType::WSS),
_ => return Err(()),
};
let peer_addr = PeerAddress::new(Address::from_str(&host)?, port, protocol_type);
let (ws, wsio) = match WsMeta::connect(url, None).await {
Ok(conn) => conn,
Err(_) => return Err(()),
};
let conn = NetworkConnection::WS(WebsocketNetworkConnection::new(tls, ws, wsio));
network_manager
.on_new_connection(ConnectionDescriptor::new_no_local(peer_addr), conn.clone())
.await?;
Ok(conn)
}
}