connection mechanism with FSM and Actors

pull/19/head
Niko 2 years ago
parent a3e6ec98a0
commit 905d7eb613
  1. 38
      Cargo.lock
  2. 99
      p2p-broker/src/auth.rs
  3. 118
      p2p-broker/src/server.rs
  4. 4
      p2p-client-ws/src/remote_ws.rs
  5. 6
      p2p-client-ws/src/remote_ws_wasm.rs
  6. 9
      p2p-client/src/lib.rs
  7. 2
      p2p-net/Cargo.toml
  8. 140
      p2p-net/src/actor.rs
  9. 3
      p2p-net/src/actors/mod.rs
  10. 48
      p2p-net/src/actors/noise.rs
  11. 166
      p2p-net/src/actors/start.rs
  12. 1
      p2p-net/src/broker.rs
  13. 292
      p2p-net/src/connection.rs
  14. 2
      p2p-net/src/errors.rs
  15. 184
      p2p-net/src/types.rs

38
Cargo.lock generated

@ -1123,6 +1123,31 @@ dependencies = [
"p2p-net", "p2p-net",
] ]
[[package]]
name = "noise-protocol"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb474d36dfe51bb4d7e733fee2b0dfd92ee1b95c716030a70e92737dea1a52b"
dependencies = [
"arrayvec",
]
[[package]]
name = "noise-rust-crypto"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e7cfeb8e6a63b4a5ccef34ed7a22d084a129b1e53a000c080bbc54c0da6f8c"
dependencies = [
"aes-gcm",
"blake2",
"chacha20poly1305",
"getrandom 0.2.8",
"noise-protocol",
"sha2 0.10.6",
"x25519-dalek",
"zeroize",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -1254,6 +1279,8 @@ dependencies = [
"debug_print", "debug_print",
"futures", "futures",
"gloo-timers", "gloo-timers",
"noise-protocol",
"noise-rust-crypto",
"num_enum", "num_enum",
"once_cell", "once_cell",
"p2p-repo", "p2p-repo",
@ -2291,6 +2318,17 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "x25519-dalek"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077"
dependencies = [
"curve25519-dalek 3.2.1",
"rand_core 0.5.1",
"zeroize",
]
[[package]] [[package]]
name = "xactor" name = "xactor"
version = "0.7.11" version = "0.7.11"

@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers // Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved. // All rights reserved.
// Licensed under the Apache License, Version 2.0 // Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> // <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, // or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such // at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
@ -13,10 +13,11 @@ use debug_print::*;
use futures::future::BoxFuture; use futures::future::BoxFuture;
use futures::future::OptionFuture; use futures::future::OptionFuture;
use futures::FutureExt; use futures::FutureExt;
use p2p_repo::types::*; use p2p_net::actors::*;
use p2p_repo::utils::*;
use p2p_net::errors::*; use p2p_net::errors::*;
use p2p_net::types::*; use p2p_net::types::*;
use p2p_repo::types::*;
use p2p_repo::utils::*;
use rust_fsm::*; use rust_fsm::*;
// state_machine! { // state_machine! {
@ -113,52 +114,52 @@ impl AuthProtocolHandler {
) -> Result<Vec<u8>, ProtocolError> { ) -> Result<Vec<u8>, ProtocolError> {
// match handler.machine.state() { // match handler.machine.state() {
// &AuthProtocolServerState::ServerHelloSent => { // &AuthProtocolServerState::ServerHelloSent => {
let message = serde_bare::from_slice::<ClientAuth>(&frame)?; let message = serde_bare::from_slice::<ClientAuth>(&frame)?;
// let _ = handler // let _ = handler
// .machine // .machine
// .consume(&AuthProtocolServerInput::ClientAuthReceived) // .consume(&AuthProtocolServerInput::ClientAuthReceived)
// .map_err(|_e| ProtocolError::InvalidState)?; // .map_err(|_e| ProtocolError::InvalidState)?;
// verifying client auth // verifying client auth
debug_println!("verifying client auth"); debug_println!("verifying client auth");
let _ = verify( let _ = verify(
&serde_bare::to_vec(&message.content_v0()).unwrap(), &serde_bare::to_vec(&message.content_v0()).unwrap(),
message.sig(), message.sig(),
message.user(), message.user(),
) )
.map_err(|_e| ProtocolError::AccessDenied)?; .map_err(|_e| ProtocolError::AccessDenied)?;
// debug_println!( // debug_println!(
// "matching nonce : {:?} {:?}", // "matching nonce : {:?} {:?}",
// message.nonce(), // message.nonce(),
// handler.nonce.as_ref().unwrap() // handler.nonce.as_ref().unwrap()
// ); // );
if message.nonce() != handler.nonce.as_ref().unwrap() { if message.nonce() != handler.nonce.as_ref().unwrap() {
// let _ = handler // let _ = handler
// .machine // .machine
// .consume(&AuthProtocolServerInput::Error) // .consume(&AuthProtocolServerInput::Error)
// .map_err(|_e| ProtocolError::InvalidState); // .map_err(|_e| ProtocolError::InvalidState);
return Err(ProtocolError::AccessDenied); return Err(ProtocolError::AccessDenied);
} }
// TODO check that the device has been registered for this user. if not, return AccessDenied // TODO check that the device has been registered for this user. if not, return AccessDenied
// all is good, we advance the FSM and send back response // all is good, we advance the FSM and send back response
// let _ = handler // let _ = handler
// .machine // .machine
// .consume(&AuthProtocolServerInput::Ok) // .consume(&AuthProtocolServerInput::Ok)
// .map_err(|_e| ProtocolError::InvalidState)?; // .map_err(|_e| ProtocolError::InvalidState)?;
handler.user = Some(message.user()); handler.user = Some(message.user());
Ok(vec![]) // without any metadata Ok(vec![]) // without any metadata
//} //}
//_ => Err(ProtocolError::InvalidState), //_ => Err(ProtocolError::InvalidState),
//} //}
} }
let res = process_state(self, frame); let res = process_state(self, frame);

@ -1,7 +1,7 @@
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers // Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved. // All rights reserved.
// Licensed under the Apache License, Version 2.0 // Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> // <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, // or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such // at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
@ -16,27 +16,28 @@ use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::sync::RwLock; use std::sync::RwLock;
use crate::broker_store::account::Account;
use crate::auth::*; use crate::auth::*;
use crate::broker_store::account::Account;
use crate::broker_store::config::Config; use crate::broker_store::config::Config;
use crate::broker_store::config::ConfigMode; use crate::broker_store::config::ConfigMode;
use crate::connection_local::BrokerConnectionLocal;
use crate::broker_store::overlay::Overlay; use crate::broker_store::overlay::Overlay;
use crate::broker_store::peer::Peer; use crate::broker_store::peer::Peer;
use crate::broker_store::repostoreinfo::RepoStoreInfo; use crate::broker_store::repostoreinfo::RepoStoreInfo;
use crate::connection_local::BrokerConnectionLocal;
use async_std::task; use async_std::task;
use debug_print::*; use debug_print::*;
use futures::future::BoxFuture; use futures::future::BoxFuture;
use futures::future::OptionFuture; use futures::future::OptionFuture;
use futures::FutureExt; use futures::FutureExt;
use futures::Stream; use futures::Stream;
use p2p_net::actors::*;
use p2p_net::errors::*;
use p2p_net::types::*;
use p2p_repo::object::Object; use p2p_repo::object::Object;
use p2p_repo::store::RepoStore; use p2p_repo::store::RepoStore;
use p2p_repo::store::StorageError; use p2p_repo::store::StorageError;
use p2p_repo::types::*; use p2p_repo::types::*;
use p2p_repo::utils::*; use p2p_repo::utils::*;
use p2p_net::errors::*;
use p2p_net::types::*;
use p2p_stores_lmdb::broker_store::LmdbBrokerStore; use p2p_stores_lmdb::broker_store::LmdbBrokerStore;
use p2p_stores_lmdb::repo_store::LmdbRepoStore; use p2p_stores_lmdb::repo_store::LmdbRepoStore;
@ -87,7 +88,6 @@ pub struct ProtocolHandler {
} }
impl ProtocolHandler { impl ProtocolHandler {
pub fn register(&mut self, addr: SocketAddr) { pub fn register(&mut self, addr: SocketAddr) {
self.addr = Some(addr); self.addr = Some(addr);
} }
@ -97,8 +97,12 @@ impl ProtocolHandler {
ProtocolType::Start => (), ProtocolType::Start => (),
ProtocolType::Auth => (), ProtocolType::Auth => (),
ProtocolType::Broker => { ProtocolType::Broker => {
let _ = self.broker_protocol.as_ref().unwrap().deregister(self.addr.unwrap()); let _ = self
}, .broker_protocol
.as_ref()
.unwrap()
.deregister(self.addr.unwrap());
}
ProtocolType::Ext => (), ProtocolType::Ext => (),
ProtocolType::Core => (), ProtocolType::Core => (),
} }
@ -122,7 +126,7 @@ impl ProtocolHandler {
ProtocolType::Start => { ProtocolType::Start => {
let message = serde_bare::from_slice::<StartProtocol>(&frame); let message = serde_bare::from_slice::<StartProtocol>(&frame);
match message { match message {
Ok(StartProtocol::Auth(b)) => { Ok(StartProtocol::Client(b)) => {
self.protocol = ProtocolType::Auth; self.protocol = ProtocolType::Auth;
self.auth_protocol = Some(AuthProtocolHandler::new()); self.auth_protocol = Some(AuthProtocolHandler::new());
return ( return (
@ -140,7 +144,10 @@ impl ProtocolHandler {
); );
} }
Err(e) => { Err(e) => {
return (Err(ProtocolError::SerializationError),OptionFuture::from(None)) return (
Err(ProtocolError::SerializationError),
OptionFuture::from(None),
)
} }
} }
} }
@ -160,12 +167,18 @@ impl ProtocolHandler {
self.protocol = ProtocolType::Broker; self.protocol = ProtocolType::Broker;
self.broker_protocol = Some(Arc::clone(&bp)); self.broker_protocol = Some(Arc::clone(&bp));
self.auth_protocol = None; self.auth_protocol = None;
return (res.0, OptionFuture::from(None)) return (res.0, OptionFuture::from(None));
}, }
Err(e) => { Err(e) => {
let val = e.clone() as u16; let val = e.clone() as u16;
let reply = AuthResult::V0(AuthResultV0 { result:val, metadata:vec![] }); let reply = AuthResult::V0(AuthResultV0 {
return (Ok(serde_bare::to_vec(&reply).unwrap()), OptionFuture::from(Some(async move { val }.boxed()))) result: val,
metadata: vec![],
});
return (
Ok(serde_bare::to_vec(&reply).unwrap()),
OptionFuture::from(Some(async move { val }.boxed())),
);
} }
} }
} }
@ -184,9 +197,10 @@ impl ProtocolHandler {
.await; .await;
(Ok(serde_bare::to_vec(&reply.0).unwrap()), reply.1) (Ok(serde_bare::to_vec(&reply.0).unwrap()), reply.1)
} }
Err(e_) => { Err(e_) => (
(Err(ProtocolError::SerializationError),OptionFuture::from(None)) Err(ProtocolError::SerializationError),
} OptionFuture::from(None),
),
} }
} }
ProtocolType::Ext => { ProtocolType::Ext => {
@ -204,7 +218,7 @@ impl ProtocolHandler {
pub struct ExtProtocolHandler {} pub struct ExtProtocolHandler {}
impl ExtProtocolHandler { impl ExtProtocolHandler {
pub fn handle_incoming(&self, msg: ExtRequest) -> ExtResponse { pub fn handle_incoming(&self, msg: ExtHello) -> ExtResponse {
unimplemented!() unimplemented!()
} }
} }
@ -219,7 +233,7 @@ use std::{thread, time};
impl BrokerProtocolHandler { impl BrokerProtocolHandler {
fn prepare_reply_broker_message( fn prepare_reply_broker_message(
res: Result<(), ProtocolError>, res: Result<(), ProtocolError>,
id: u64, id: i64,
padding_size: usize, padding_size: usize,
) -> BrokerMessage { ) -> BrokerMessage {
let result = match res { let result = match res {
@ -238,7 +252,7 @@ impl BrokerProtocolHandler {
fn prepare_reply_broker_overlay_message( fn prepare_reply_broker_overlay_message(
res: Result<(), ProtocolError>, res: Result<(), ProtocolError>,
id: u64, id: i64,
overlay: OverlayId, overlay: OverlayId,
block: Option<Block>, block: Option<Block>,
padding_size: usize, padding_size: usize,
@ -271,7 +285,7 @@ impl BrokerProtocolHandler {
fn prepare_reply_broker_overlay_message_stream( fn prepare_reply_broker_overlay_message_stream(
res: Result<Block, ProtocolError>, res: Result<Block, ProtocolError>,
id: u64, id: i64,
overlay: OverlayId, overlay: OverlayId,
padding_size: usize, padding_size: usize,
) -> BrokerMessage { ) -> BrokerMessage {
@ -304,7 +318,7 @@ impl BrokerProtocolHandler {
async fn send_block_stream_response_to_client( async fn send_block_stream_response_to_client(
&self, &self,
res: Result<async_channel::Receiver<Block>, ProtocolError>, res: Result<async_channel::Receiver<Block>, ProtocolError>,
id: u64, id: i64,
overlay: OverlayId, overlay: OverlayId,
padding_size: usize, padding_size: usize,
) -> (BrokerMessage, OptionFuture<BoxFuture<'static, u16>>) { ) -> (BrokerMessage, OptionFuture<BoxFuture<'static, u16>>) {
@ -364,23 +378,23 @@ impl BrokerProtocolHandler {
); );
} }
pub fn register(self: Arc<Self>, addr: SocketAddr) -> Result<(),ProtocolError> { pub fn register(self: Arc<Self>, addr: SocketAddr) -> Result<(), ProtocolError> {
//FIXME: peer_id must be real one //FIXME: peer_id must be real one
self.broker.add_client_peer(PubKey::Ed25519PubKey([0;32]), Arc::clone(&self)) self.broker
.add_client_peer(PubKey::Ed25519PubKey([0; 32]), Arc::clone(&self))
} }
pub fn deregister(&self, addr: SocketAddr) -> Result<(),ProtocolError> { pub fn deregister(&self, addr: SocketAddr) -> Result<(), ProtocolError> {
self.broker
self.broker.remove_client_peer(PubKey::Ed25519PubKey([0;32])); .remove_client_peer(PubKey::Ed25519PubKey([0; 32]));
Ok(()) Ok(())
} }
pub async fn handle_incoming( pub async fn handle_incoming(
&self, &self,
msg: BrokerMessage, msg: BrokerMessage,
) -> (BrokerMessage, OptionFuture<BoxFuture<'static, u16>>) { ) -> (BrokerMessage, OptionFuture<BoxFuture<'static, u16>>) {
let padding_size = 20; // TODO randomize, if config of server contains padding_max let padding_size = 20; // TODO randomize, if config of server contains padding_max
let id = msg.id(); let id = msg.id();
@ -508,7 +522,6 @@ pub enum PeerConnection {
pub struct BrokerPeerInfo { pub struct BrokerPeerInfo {
lastPeerAdvert: Option<PeerAdvert>, lastPeerAdvert: Option<PeerAdvert>,
connected: PeerConnection, connected: PeerConnection,
} }
const REPO_STORES_SUBDIR: &str = "repos"; const REPO_STORES_SUBDIR: &str = "repos";
@ -522,32 +535,30 @@ pub struct BrokerServer {
//overlayid_to_repostore: HashMap<RepoStoreId, &'a LmdbRepoStore>, //overlayid_to_repostore: HashMap<RepoStoreId, &'a LmdbRepoStore>,
//overlayid_to_repostore: Arc<RwLock<HashMap<OverlayId, RepoStoreId>>>, //overlayid_to_repostore: Arc<RwLock<HashMap<OverlayId, RepoStoreId>>>,
peers: RwLock<HashMap<DirectPeerId, BrokerPeerInfo>>, peers: RwLock<HashMap<DirectPeerId, BrokerPeerInfo>>,
//local_connections:
//local_connections:
} }
impl BrokerServer { impl BrokerServer {
pub fn add_client_peer(
pub fn add_client_peer(&self, peer_id: DirectPeerId, bph: Arc<BrokerProtocolHandler>) -> Result<(),ProtocolError> { &self,
peer_id: DirectPeerId,
bph: Arc<BrokerProtocolHandler>,
) -> Result<(), ProtocolError> {
let mut writer = self.peers.write().expect("write peers hashmap"); let mut writer = self.peers.write().expect("write peers hashmap");
let bpi = BrokerPeerInfo { let bpi = BrokerPeerInfo {
lastPeerAdvert: None, //TODO: load from store lastPeerAdvert: None, //TODO: load from store
connected: PeerConnection::CLIENT(bph) connected: PeerConnection::CLIENT(bph),
}; };
if !writer.get(&peer_id).is_none() { if !writer.get(&peer_id).is_none() {
return Err(ProtocolError::PeerAlreadyConnected); return Err(ProtocolError::PeerAlreadyConnected);
} }
writer.insert(peer_id.clone(), bpi); writer.insert(peer_id.clone(), bpi);
Ok(()) Ok(())
} }
pub fn remove_client_peer(&self, peer_id: DirectPeerId) { pub fn remove_client_peer(&self, peer_id: DirectPeerId) {
let mut writer = self.peers.write().expect("write peers hashmap"); let mut writer = self.peers.write().expect("write peers hashmap");
writer.remove(&peer_id); writer.remove(&peer_id);
} }
pub fn new(store: LmdbBrokerStore, mode: ConfigMode) -> Result<BrokerServer, BrokerError> { pub fn new(store: LmdbBrokerStore, mode: ConfigMode) -> Result<BrokerServer, BrokerError> {
@ -561,15 +572,11 @@ impl BrokerServer {
mode: configmode, mode: configmode,
repo_stores: Arc::new(RwLock::new(HashMap::new())), repo_stores: Arc::new(RwLock::new(HashMap::new())),
//overlayid_to_repostore: Arc::new(RwLock::new(HashMap::new())), //overlayid_to_repostore: Arc::new(RwLock::new(HashMap::new())),
peers: RwLock::new(HashMap::new()) peers: RwLock::new(HashMap::new()),
}) })
} }
fn open_or_create_repostore<F, R>( fn open_or_create_repostore<F, R>(&self, repo_hash: RepoHash, f: F) -> Result<R, ProtocolError>
&self,
repo_hash: RepoHash,
f: F,
) -> Result<R, ProtocolError>
where where
F: FnOnce(&LmdbRepoStore) -> Result<R, ProtocolError>, F: FnOnce(&LmdbRepoStore) -> Result<R, ProtocolError>,
{ {
@ -580,7 +587,7 @@ impl BrokerServer {
let mut path = self.store.path(); let mut path = self.store.path();
path.push(REPO_STORES_SUBDIR); path.push(REPO_STORES_SUBDIR);
path.push::<String>(repo_hash.clone().into()); path.push::<String>(repo_hash.clone().into());
std::fs::create_dir_all(path.clone()).map_err(|_e| ProtocolError::WriteError )?; std::fs::create_dir_all(path.clone()).map_err(|_e| ProtocolError::WriteError)?;
println!("path for repo store: {}", path.to_str().unwrap()); println!("path for repo store: {}", path.to_str().unwrap());
let repo = LmdbRepoStore::open(&path, *key.slice()); let repo = LmdbRepoStore::open(&path, *key.slice());
let mut writer = self.repo_stores.write().expect("write repo_store hashmap"); let mut writer = self.repo_stores.write().expect("write repo_store hashmap");
@ -602,14 +609,13 @@ impl BrokerServer {
let reader = self.repo_stores.read().expect("read repo_store hashmap"); let reader = self.repo_stores.read().expect("read repo_store hashmap");
let rep = reader.get(&repostore_id); let rep = reader.get(&repostore_id);
if let Some(repo) = rep { if let Some(repo) = rep {
return f(repo) return f(repo);
} }
} }
// we need to open/create it // we need to open/create it
// TODO: last_access // TODO: last_access
return self.open_or_create_repostore(repostore_id, |repo| f(repo)); return self.open_or_create_repostore(repostore_id, |repo| f(repo));
// } else { // } else {
// // it is ConfigMode::Local // // it is ConfigMode::Local
// { // {
@ -654,7 +660,7 @@ impl BrokerServer {
pub fn protocol_handler(self: Arc<Self>) -> ProtocolHandler { pub fn protocol_handler(self: Arc<Self>) -> ProtocolHandler {
let (s, r) = async_channel::unbounded::<Vec<u8>>(); let (s, r) = async_channel::unbounded::<Vec<u8>>();
return ProtocolHandler { return ProtocolHandler {
addr:None, addr: None,
broker: Arc::clone(&self), broker: Arc::clone(&self),
protocol: ProtocolType::Start, protocol: ProtocolType::Start,
auth_protocol: None, auth_protocol: None,
@ -943,12 +949,8 @@ impl BrokerServer {
getrandom::getrandom(&mut random_buf).unwrap(); getrandom::getrandom(&mut random_buf).unwrap();
let key = SymKey::ChaCha20Key(random_buf); let key = SymKey::ChaCha20Key(random_buf);
let _ = RepoStoreInfo::create( let _ = RepoStoreInfo::create(&overlay_id, &key, &self.store)?; // TODO in case of error, delete the previously created Overlay
&overlay_id, //debug_println!("KEY ADDED");
&key,
&self.store,
)?; // TODO in case of error, delete the previously created Overlay
//debug_println!("KEY ADDED");
over over
} }
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),

@ -127,8 +127,6 @@ impl IConnection for ConnectionWebSocket {
//spawn_and_log_error(ws_loop(ws, cnx.take_sender(), cnx.take_receiver())); //spawn_and_log_error(ws_loop(ws, cnx.take_sender(), cnx.take_receiver()));
log!("sending...");
// //
//cnx.close().await; //cnx.close().await;
@ -288,7 +286,7 @@ async fn ws_loop(
code = ProtocolError::OtherError as u16; code = ProtocolError::OtherError as u16;
} }
close_ws(&mut ws, &mut receiver, code + 4000, &proto_err.to_string()).await?; close_ws(&mut ws, &mut receiver, code + 4000, &proto_err.to_string()).await?;
return Err(NetError::ProtocolError); //return Err(NetError::ProtocolError);
} }
} }
Err(e) => { Err(e) => {

@ -83,9 +83,9 @@ impl IConnection for ConnectionWebSocket {
// StartProtocol::Auth(ClientHello::V0()), // StartProtocol::Auth(ClientHello::V0()),
// ))) // )))
// .await; // .await;
log!("waiting..."); //log!("waiting...");
//let res = join.next().await; //let res = join.next().await;
log!("finished..."); //log!("finished...");
//log!("JOIN SHUTDOWN {:?}", res); //log!("JOIN SHUTDOWN {:?}", res);
// Note that since WsMeta::connect resolves to an opened connection, we don't see // Note that since WsMeta::connect resolves to an opened connection, we don't see
// any Open events here. // any Open events here.
@ -214,7 +214,7 @@ async fn ws_loop(
if let ConnectionCommand::Error(err) = last_command.clone() { if let ConnectionCommand::Error(err) = last_command.clone() {
let _ = shutdown.send(err).await; let _ = shutdown.send(err).await;
} else if let ConnectionCommand::ProtocolError(err) = last_command.clone() { } else if let ConnectionCommand::ProtocolError(err) = last_command.clone() {
let _ = shutdown.send(NetError::ProtocolError).await; //let _ = shutdown.send(NetError::ProtocolError).await;
} // otherwise, shutdown gracefully (with None). it is done automatically during destroy of shutdown } // otherwise, shutdown gracefully (with None). it is done automatically during destroy of shutdown
receiver receiver

@ -1,6 +1,6 @@
// All rights reserved. // All rights reserved.
// Licensed under the Apache License, Version 2.0 // Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> // <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, // or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such // at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
@ -32,7 +32,9 @@ macro_rules! after {
$addr.wait_for_stop().await; // TODO add timeout and close connection if there's no reply $addr.wait_for_stop().await; // TODO add timeout and close connection if there's no reply
let r = $receiver.await; let r = $receiver.await;
if r.is_err() { return Err(ProtocolError::Closing);} if r.is_err() {
return Err(ProtocolError::Closing);
}
let $reply = r.unwrap(); let $reply = r.unwrap();
//debug_println!("reply arrived {:?}", $reply); //debug_println!("reply arrived {:?}", $reply);
{ {
@ -42,5 +44,4 @@ macro_rules! after {
}; };
} }
pub mod connection_remote; //pub mod connection_remote;

@ -22,6 +22,8 @@ async-std = { version = "1.12.0", features = ["attributes","unstable"] }
wasm-bindgen = "0.2" wasm-bindgen = "0.2"
unique_id = "0.1.5" unique_id = "0.1.5"
once_cell = "1.17.1" once_cell = "1.17.1"
noise-protocol = "0.1.4"
noise-rust-crypto = "0.5.0"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
gloo-timers = "0.2.6" gloo-timers = "0.2.6"

@ -1,47 +1,97 @@
use async_std::stream::StreamExt;
use async_std::sync::{Mutex, MutexGuard};
use futures::{channel::mpsc, SinkExt}; use futures::{channel::mpsc, SinkExt};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::any::{Any, TypeId};
use std::convert::From;
use std::sync::Arc;
use crate::{connection::*, errors::ProtocolError}; use crate::{connection::*, errors::ProtocolError, log, types::ProtocolMessage};
use std::marker::PhantomData; use std::marker::PhantomData;
pub trait BrokerRequest: DeserializeOwned {} pub trait BrokerRequest: std::fmt::Debug {
fn send(&self) -> ProtocolMessage;
pub trait BrokerResponse: DeserializeOwned {
fn test(&self);
} }
impl BrokerResponse for () { //pub trait BrokerResponse: TryFrom<ProtocolMessage> + std::fmt::Debug {}
fn test(&self) {}
impl TryFrom<ProtocolMessage> for () {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
Ok(())
}
} }
pub trait IActor: EActor { pub trait IActor: EActor {
fn process_request(&self) {} //fn process_request(&self, req: Box<dyn BrokerRequest>) -> Box<dyn BrokerResponse> {}
} }
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EActor { pub trait EActor: Send + Sync + std::fmt::Debug {
async fn handle(&mut self, cmd: ConnectionCommand); //type T: TryFrom<ProtocolMessage, Error = ProtocolError> + std::fmt::Debug;
//async fn handle(&mut self, msg: ProtocolMessage);
async fn respond(
&mut self,
msg: ProtocolMessage,
//stream: Option<impl BrokerRequest + std::marker::Send>,
fsm: Arc<Mutex<NoiseFSM>>,
) -> Result<(), ProtocolError>;
} }
pub struct Actor<'a, A: BrokerRequest, B: BrokerResponse> { #[derive(Debug)]
pub struct Actor<
'a,
A: BrokerRequest,
B: TryFrom<ProtocolMessage, Error = ProtocolError> + std::fmt::Debug + std::marker::Sync,
> {
id: i64, id: i64,
phantom_a: PhantomData<&'a A>, phantom_a: PhantomData<&'a A>,
phantom_b: PhantomData<&'a B>, phantom_b: PhantomData<&'a B>,
receiver: Receiver<ConnectionCommand>, receiver: Receiver<ConnectionCommand>,
receiver_tx: Sender<ConnectionCommand>, receiver_tx: Sender<ConnectionCommand>,
initiator: bool,
} }
#[async_trait::async_trait] // #[async_trait::async_trait]
impl<A: BrokerRequest + std::marker::Sync, B: BrokerResponse + std::marker::Sync> EActor // impl<
for Actor<'_, A, B> // A: BrokerRequest + std::marker::Sync + 'static,
{ // B: TryFrom<ProtocolMessage, Error = ProtocolError>
async fn handle(&mut self, cmd: ConnectionCommand) { // + std::fmt::Debug
let _ = self.receiver_tx.send(cmd).await; // + std::marker::Sync
} // + 'static,
} // > EActor for Actor<'_, A, B>
// {
// //type T = B;
// // async fn handle(&mut self, msg: ProtocolMessage) {
// // if self.initiator && msg.type_id() == TypeId::of::<B>()
// // || !self.initiator && msg.type_id() == TypeId::of::<A>()
// // {
// // let _ = self.receiver_tx.send(ConnectionCommand::Msg(msg)).await;
// // } else {
// // log!("NOT OK");
// // }
// // }
// // async fn respond(id: i64, msg: A) -> Result<B, ProtocolError> {
// // let mut actor = Box::new(Actor::<A, B>::new(id, false));
// // //actor.process_request
// // match self.receiver.next().await {
// // Some(msg) => B::receive(msg),
// // _ => Err(ProtocolError::ActorError),
// // }
// // }
// }
impl<A: BrokerRequest, B: BrokerResponse> Actor<'_, A, B> { impl<
pub fn new(id: i64) -> Self { A: BrokerRequest + 'static,
B: TryFrom<ProtocolMessage, Error = ProtocolError>
+ std::marker::Sync
+ std::fmt::Debug
+ 'static,
> Actor<'_, A, B>
{
pub fn new(id: i64, initiator: bool) -> Self {
let (mut receiver_tx, receiver) = mpsc::unbounded::<ConnectionCommand>(); let (mut receiver_tx, receiver) = mpsc::unbounded::<ConnectionCommand>();
Self { Self {
id, id,
@ -49,12 +99,52 @@ impl<A: BrokerRequest, B: BrokerResponse> Actor<'_, A, B> {
receiver_tx, receiver_tx,
phantom_a: PhantomData, phantom_a: PhantomData,
phantom_b: PhantomData, phantom_b: PhantomData,
initiator,
}
}
pub fn verify(&self, msg: ProtocolMessage) -> bool {
self.initiator && msg.type_id() == TypeId::of::<B>()
|| !self.initiator && msg.type_id() == TypeId::of::<A>()
}
pub async fn request(
&mut self,
msg: impl BrokerRequest + std::marker::Sync + std::marker::Send,
stream: Option<impl BrokerRequest + std::marker::Send>,
fsm: Arc<Mutex<NoiseFSM>>,
) -> Result<B, ProtocolError> {
//sender.send(ConnectionCommand::Msg(msg.send())).await;
fsm.lock().await.send(msg.send()).await?;
match self.receiver.next().await {
Some(ConnectionCommand::Msg(msg)) => msg.try_into(),
_ => Err(ProtocolError::ActorError),
} }
} }
pub fn request(&self, msg: A, stream: Option<A>) -> Result<B, ProtocolError> { pub fn new_responder() -> Box<Self> {
let b: Vec<u8> = vec![]; Box::new(Self::new(0, false))
let a = serde_bare::from_slice::<B>(&b).unwrap(); }
Ok(a)
pub fn get_receiver_tx(&self) -> Sender<ConnectionCommand> {
self.receiver_tx.clone()
}
}
mod test {
use crate::actor::*;
use crate::actors::*;
use crate::types::*;
#[async_std::test]
pub async fn test_actor() {
let mut a = Actor::<Noise, Noise>::new(1, true);
// a.handle(ProtocolMessage::Start(StartProtocol::Client(
// ClientHello::Noise3(Noise::V0(NoiseV0 { data: vec![] })),
// )))
// .await;
// a.handle(ProtocolMessage::Noise(Noise::V0(NoiseV0 { data: vec![] })))
// .await;
} }
} }

@ -1,2 +1,5 @@
pub mod noise; pub mod noise;
pub use noise::*; pub use noise::*;
pub mod start;
pub use start::*;

@ -1,9 +1,13 @@
use crate::{actor::*, errors::ProtocolError}; use std::sync::Arc;
use crate::{actor::*, connection::NoiseFSM, errors::ProtocolError, types::ProtocolMessage};
use async_std::sync::Mutex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NoiseV0 { pub struct NoiseV0 {
data: Vec<u8>, // contains the handshake messages or the encrypted content of a ProtocolMessage
pub data: Vec<u8>,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -11,10 +15,42 @@ pub enum Noise {
V0(NoiseV0), V0(NoiseV0),
} }
impl BrokerRequest for Noise {} impl BrokerRequest for Noise {
fn send(&self) -> ProtocolMessage {
ProtocolMessage::Noise(self.clone())
}
}
impl TryFrom<ProtocolMessage> for Noise {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::Noise(n) = msg {
Ok(n)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
impl Actor<'_, Noise, Noise> {}
// impl IActor for Actor<'_, Noise, Noise> {
// // fn process_request(&self, req: Box<dyn BrokerRequest>) -> Box<dyn BrokerResponse> {
// // //let r = req as Noise;
// // }
// }
impl Actor<'_, Noise, ()> {} #[async_trait::async_trait]
impl EActor for Actor<'_, Noise, Noise> {
// fn process_request(&self, req: Box<dyn BrokerRequest>) -> Box<dyn BrokerResponse> {
// //let r = req as Noise;
// }
impl IActor for Actor<'_, Noise, ()> { async fn respond(
//fn process_request(&self) {} &mut self,
msg: ProtocolMessage,
fsm: Arc<Mutex<NoiseFSM>>,
) -> Result<(), ProtocolError> {
Ok(())
}
} }

@ -0,0 +1,166 @@
use crate::actors::noise::Noise;
use crate::connection::NoiseFSM;
use crate::types::ExtResponse;
use crate::{actor::*, errors::ProtocolError, types::ProtocolMessage};
use async_std::sync::Mutex;
use serde::{Deserialize, Serialize};
use std::any::{Any, TypeId};
use std::sync::Arc;
pub struct Noise3(Noise);
/// Start chosen protocol
/// First message sent by the client
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum StartProtocol {
Client(ClientHello),
Ext(ExtHello),
}
impl StartProtocol {
pub fn type_id(&self) -> TypeId {
match self {
StartProtocol::Client(a) => a.type_id(),
StartProtocol::Ext(a) => a.type_id(),
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
match self {
StartProtocol::Client(a) => a.get_actor(),
StartProtocol::Ext(a) => a.get_actor(),
}
}
}
/// External Hello (finalizes the Noise handshake and send first ExtRequest)
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtHello {
// contains the 3rd Noise handshake message "s,se"
pub noise: Noise,
/// Noise encrypted payload (an ExtRequest)
pub payload: Vec<u8>,
}
impl ExtHello {
pub fn get_actor(&self) -> Box<dyn EActor> {
Actor::<ExtHello, ExtResponse>::new_responder()
}
}
impl BrokerRequest for ExtHello {
fn send(&self) -> ProtocolMessage {
ProtocolMessage::Start(StartProtocol::Ext(self.clone()))
}
}
/// Client Hello
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ClientHello {
// contains the 3rd Noise handshake message "s,se"
Noise3(Noise),
Local,
}
impl ClientHello {
pub fn type_id(&self) -> TypeId {
match self {
ClientHello::Noise3(a) => a.type_id(),
ClientHello::Local => TypeId::of::<ClientHello>(),
}
}
pub fn get_actor(&self) -> Box<dyn EActor> {
Actor::<ClientHello, ServerHello>::new_responder()
}
}
/// Server hello sent upon a client connection
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ServerHelloV0 {
/// Nonce for ClientAuth
#[serde(with = "serde_bytes")]
pub nonce: Vec<u8>,
}
/// Server hello sent upon a client connection
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ServerHello {
V0(ServerHelloV0),
}
impl ServerHello {
pub fn nonce(&self) -> &Vec<u8> {
match self {
ServerHello::V0(o) => &o.nonce,
}
}
}
impl BrokerRequest for ClientHello {
fn send(&self) -> ProtocolMessage {
ProtocolMessage::Start(StartProtocol::Client(ClientHello::Local))
}
}
impl TryFrom<ProtocolMessage> for ClientHello {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::Start(StartProtocol::Client(a)) = msg {
Ok(a)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
impl TryFrom<ProtocolMessage> for ServerHello {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ServerHello(server_hello) = msg {
Ok(server_hello)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
impl BrokerRequest for ServerHello {
fn send(&self) -> ProtocolMessage {
ProtocolMessage::ServerHello(self.clone())
}
}
impl From<ServerHello> for ProtocolMessage {
fn from(msg: ServerHello) -> ProtocolMessage {
ProtocolMessage::ServerHello(msg)
}
}
impl Actor<'_, ClientHello, ServerHello> {}
#[async_trait::async_trait]
impl EActor for Actor<'_, ClientHello, ServerHello> {
async fn respond(
&mut self,
msg: ProtocolMessage,
fsm: Arc<Mutex<NoiseFSM>>,
) -> Result<(), ProtocolError> {
let req = ClientHello::try_from(msg)?;
let res = ServerHello::V0(ServerHelloV0 { nonce: vec![] });
fsm.lock().await.send(res.into()).await?;
Ok(())
}
}
impl Actor<'_, ExtHello, ExtResponse> {}
#[async_trait::async_trait]
impl EActor for Actor<'_, ExtHello, ExtResponse> {
async fn respond(
&mut self,
msg: ProtocolMessage,
fsm: Arc<Mutex<NoiseFSM>>,
) -> Result<(), ProtocolError> {
Ok(())
}
}

@ -41,7 +41,6 @@ pub struct DirectConnection {
pub static BROKER: Lazy<Arc<RwLock<Broker>>> = Lazy::new(|| Arc::new(RwLock::new(Broker::new()))); pub static BROKER: Lazy<Arc<RwLock<Broker>>> = Lazy::new(|| Arc::new(RwLock::new(Broker::new())));
pub struct Broker { pub struct Broker {
//actors: Arc<RwLock<HashMap<i64, Box<dyn IActor>>>>,
direct_connections: HashMap<IP, DirectConnection>, direct_connections: HashMap<IP, DirectConnection>,
peers: HashMap<DirectPeerId, BrokerPeerInfo>, peers: HashMap<DirectPeerId, BrokerPeerInfo>,
shutdown: Option<Receiver<ProtocolError>>, shutdown: Option<Receiver<ProtocolError>>,

@ -1,7 +1,10 @@
static NOISE_CONFIG: &'static str = "Noise_XK_25519_ChaChaPoly_BLAKE2b"; static NOISE_CONFIG: &'static str = "Noise_XK_25519_ChaChaPoly_BLAKE2b";
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use crate::actor::{Actor, EActor};
use crate::actors::*; use crate::actors::*;
use crate::errors::NetError; use crate::errors::NetError;
use crate::errors::ProtocolError; use crate::errors::ProtocolError;
@ -9,7 +12,10 @@ use crate::log;
use crate::types::*; use crate::types::*;
use crate::utils::*; use crate::utils::*;
use async_std::stream::StreamExt; use async_std::stream::StreamExt;
use async_std::sync::Mutex;
use futures::{channel::mpsc, select, Future, FutureExt, SinkExt}; use futures::{channel::mpsc, select, Future, FutureExt, SinkExt};
use noise_protocol::{CipherState, HandshakeState};
use noise_rust_crypto::*;
use p2p_repo::types::{PrivKey, PubKey}; use p2p_repo::types::{PrivKey, PubKey};
use unique_id::sequence::SequenceGenerator; use unique_id::sequence::SequenceGenerator;
use unique_id::Generator; use unique_id::Generator;
@ -39,14 +45,167 @@ pub trait IConnection: Send + Sync {
async fn accept(&self) -> Result<ConnectionBase, NetError>; async fn accept(&self) -> Result<ConnectionBase, NetError>;
} }
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug, Clone)]
pub enum ConnectionDir { pub enum ConnectionDir {
Server, Server,
Client, Client,
} }
impl ConnectionDir {
pub fn is_server(&self) -> bool {
*self == ConnectionDir::Server
}
}
#[derive(Debug, PartialEq)]
pub enum FSMstate {
Local0,
Noise0,
Noise1,
Noise2,
Noise3,
ExtRequest,
ExtResponse,
ClientHello,
ServerHello,
ClientAuth,
AuthResult,
}
pub struct NoiseFSM {
state: FSMstate,
dir: ConnectionDir,
sender: Sender<ConnectionCommand>,
noise_handshake_state: Option<HandshakeState<X25519, ChaCha20Poly1305, Blake2b>>,
noise_cipher_state: Option<CipherState<ChaCha20Poly1305>>,
}
impl fmt::Debug for NoiseFSM {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NoiseFSM")
.field("state", &self.state)
.field("dir", &self.dir)
.finish()
}
}
pub enum StepReply {
Responder(ProtocolMessage),
Response(ProtocolMessage),
NONE,
}
impl NoiseFSM {
pub fn new(
tp: TransportProtocol,
dir: ConnectionDir,
sender: Sender<ConnectionCommand>,
) -> Self {
Self {
state: if tp == TransportProtocol::Local {
FSMstate::Local0
} else {
FSMstate::Noise0
},
dir,
sender,
noise_handshake_state: None,
noise_cipher_state: None,
}
}
fn decrypt(&mut self, ciphertext: &Noise) -> ProtocolMessage {
unimplemented!();
}
fn encrypt(&mut self, plaintext: ProtocolMessage) -> Noise {
unimplemented!();
}
pub async fn send(&mut self, msg: ProtocolMessage) -> Result<(), ProtocolError> {
if self.state == FSMstate::AuthResult && self.noise_cipher_state.is_some() {
let cipher = self.encrypt(msg);
self.sender
.send(ConnectionCommand::Msg(ProtocolMessage::Noise(cipher)))
.await;
return Ok(());
} else {
return Err(ProtocolError::InvalidState);
}
}
pub async fn receive(
&mut self,
msg: ProtocolMessage,
) -> Result<ProtocolMessage, ProtocolError> {
if self.state == FSMstate::AuthResult && self.noise_cipher_state.is_some() {
if let ProtocolMessage::Noise(noise) = msg {
let new = self.decrypt(&noise);
Ok(new)
} else {
Err(ProtocolError::MustBeEncrypted)
}
} else {
Err(ProtocolError::InvalidState)
}
}
pub fn step(
&mut self,
mut msg_opt: Option<ProtocolMessage>,
) -> Result<StepReply, ProtocolError> {
if self.noise_cipher_state.is_some() {
if let Some(ProtocolMessage::Noise(noise)) = msg_opt.as_ref() {
let new = self.decrypt(noise);
msg_opt.replace(new);
} else {
return Err(ProtocolError::MustBeEncrypted);
}
}
match self.state {
// TODO verify that ID is zero
FSMstate::Local0 => {
if let Some(msg) = msg_opt.as_ref() {
if self.dir.is_server() && msg.type_id() == ClientHello::Local.type_id() {
self.state = FSMstate::ServerHello;
Box::new(Actor::<ClientHello, ServerHello>::new(msg.id(), false));
return Ok(StepReply::NONE);
}
} else if !self.dir.is_server() && msg_opt.is_none() {
self.state = FSMstate::ClientHello;
Box::new(Actor::<ClientHello, ServerHello>::new(0, true));
return Ok(StepReply::NONE);
}
}
FSMstate::Noise0 => {}
FSMstate::Noise1 => {}
FSMstate::Noise2 => {}
FSMstate::Noise3 => {}
FSMstate::ExtRequest => {}
FSMstate::ExtResponse => {}
FSMstate::ClientHello => {}
FSMstate::ServerHello => {}
FSMstate::ClientAuth => {}
FSMstate::AuthResult => {
if let Some(msg) = msg_opt {
let id = msg.id();
if self.dir.is_server() && id > 0 || !self.dir.is_server() && id < 0 {
return Ok(StepReply::Responder(msg));
} else if id != 0 {
return Ok(StepReply::Response(msg));
}
}
}
}
Err(ProtocolError::InvalidState)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ConnectionBase { pub struct ConnectionBase {
fsm: Option<Arc<Mutex<NoiseFSM>>>,
sender: Option<Receiver<ConnectionCommand>>, sender: Option<Receiver<ConnectionCommand>>,
receiver: Option<Sender<ConnectionCommand>>, receiver: Option<Sender<ConnectionCommand>>,
sender_tx: Option<Sender<ConnectionCommand>>, sender_tx: Option<Sender<ConnectionCommand>>,
@ -55,11 +214,14 @@ pub struct ConnectionBase {
dir: ConnectionDir, dir: ConnectionDir,
next_request_id: SequenceGenerator, next_request_id: SequenceGenerator,
tp: TransportProtocol, tp: TransportProtocol,
actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>,
} }
impl ConnectionBase { impl ConnectionBase {
pub fn new(dir: ConnectionDir, tp: TransportProtocol) -> Self { pub fn new(dir: ConnectionDir, tp: TransportProtocol) -> Self {
Self { Self {
fsm: None,
receiver: None, receiver: None,
sender: None, sender: None,
sender_tx: None, sender_tx: None,
@ -68,6 +230,7 @@ impl ConnectionBase {
next_request_id: SequenceGenerator::new(1), next_request_id: SequenceGenerator::new(1),
dir, dir,
tp, tp,
actors: Arc::new(Mutex::new(HashMap::new())),
} }
} }
@ -111,29 +274,103 @@ impl ConnectionBase {
async fn read_loop( async fn read_loop(
mut receiver: Receiver<ConnectionCommand>, mut receiver: Receiver<ConnectionCommand>,
mut sender: Sender<ConnectionCommand>, mut sender: Sender<ConnectionCommand>,
actors: Arc<Mutex<HashMap<i64, Sender<ConnectionCommand>>>>,
fsm: Arc<Mutex<NoiseFSM>>,
) -> ResultSend<()> { ) -> ResultSend<()> {
while let Some(msg) = receiver.next().await { while let Some(msg) = receiver.next().await {
log!("RECEIVED: {:?}", msg); log!("RECEIVED: {:?}", msg);
// sender
// .send(ConnectionCommand::Close)
// .await
// .map_err(|e| "channel send error")?
if let ConnectionCommand::Close = msg { if let ConnectionCommand::Close = msg {
log!("EXIT READ LOOP"); log!("EXIT READ LOOP");
break; break;
} else if let ConnectionCommand::Msg(proto_msg) = msg {
let res;
{
let mut locked_fsm = fsm.lock().await;
res = locked_fsm.step(Some(proto_msg));
}
match res {
Err(e) => {
if sender
.send(ConnectionCommand::ProtocolError(e))
.await
.is_err()
{
break; //TODO test that sending a ProtocolError effectively closes the connection (with ConnectionCommand::Close)
}
}
Ok(StepReply::NONE) => {}
Ok(StepReply::Responder(responder)) => {
let r = responder
.get_actor()
.respond(responder, Arc::clone(&fsm))
.await;
if r.is_err() {
if sender
.send(ConnectionCommand::ProtocolError(r.unwrap_err()))
.await
.is_err()
{
break;
}
}
}
Ok(StepReply::Response(response)) => {
let mut lock = actors.lock().await;
let exists = lock.get_mut(&response.id());
match exists {
Some(actor_sender) => {
if actor_sender
.send(ConnectionCommand::Msg(response))
.await
.is_err()
{
break;
}
}
None => {
if sender
.send(ConnectionCommand::ProtocolError(
ProtocolError::ActorError,
))
.await
.is_err()
{
break;
}
}
}
}
}
} }
} }
Ok(()) Ok(())
} }
pub async fn request(&mut self) { pub async fn request<
A: crate::actor::BrokerRequest + std::marker::Sync + std::marker::Send + 'static,
B: TryFrom<ProtocolMessage, Error = ProtocolError>
+ std::fmt::Debug
+ std::marker::Sync
+ 'static,
>(
&self,
msg: A,
stream: Option<A>,
) -> Result<B, ProtocolError> {
if self.fsm.is_none() {
return Err(ProtocolError::FsmNotReady);
}
let mut id = self.next_request_id.next_id(); let mut id = self.next_request_id.next_id();
if self.dir == ConnectionDir::Server { if self.dir == ConnectionDir::Server {
id = !id + 1; id = !id + 1;
} }
// id let mut actor = Box::new(Actor::<A, B>::new(id, true));
self.actors.lock().await.insert(id, actor.get_receiver_tx());
actor
.request(msg, stream, Arc::clone(self.fsm.as_ref().unwrap()))
.await
} }
pub async fn send(&mut self, cmd: ConnectionCommand) { pub async fn send(&mut self, cmd: ConnectionCommand) {
@ -162,6 +399,43 @@ impl ConnectionBase {
self.sender_tx = Some(sender_tx.clone()); self.sender_tx = Some(sender_tx.clone());
self.receiver_tx = Some(receiver_tx); self.receiver_tx = Some(receiver_tx);
spawn_and_log_error(Self::read_loop(receiver_rx, sender_tx)); let fsm = Arc::new(Mutex::new(NoiseFSM::new(
self.tp,
self.dir.clone(),
sender_tx.clone(),
)));
self.fsm = Some(Arc::clone(&fsm));
spawn_and_log_error(Self::read_loop(
receiver_rx,
sender_tx,
Arc::clone(&self.actors),
fsm,
));
}
}
mod test {
use crate::actor::*;
use crate::actors::*;
use crate::log;
use crate::types::*;
use std::any::{Any, TypeId};
#[async_std::test]
pub async fn test_connection() {}
#[async_std::test]
pub async fn test_typeid() {
log!(
"{:?}",
ClientHello::Noise3(Noise::V0(NoiseV0 { data: vec![] })).type_id()
);
let a = Noise::V0(NoiseV0 { data: [].to_vec() });
log!("{:?}", a.type_id());
log!("{:?}", TypeId::of::<Noise>());
log!("{:?}", ClientHello::Local.type_id());
log!("{:?}", TypeId::of::<ClientHello>());
} }
} }

@ -71,6 +71,8 @@ pub enum ProtocolError {
NoError, NoError,
OtherError, OtherError,
Closing, Closing,
FsmNotReady,
MustBeEncrypted,
} //MAX 949 ProtocolErrors } //MAX 949 ProtocolErrors
impl ProtocolError { impl ProtocolError {

@ -14,9 +14,12 @@
//! Corresponds to the BARE schema //! Corresponds to the BARE schema
use core::fmt; use core::fmt;
use std::net::IpAddr; use std::{
any::{Any, TypeId},
net::IpAddr,
};
use crate::actors::*; use crate::{actor::EActor, actors::*, errors::ProtocolError};
use p2p_repo::types::*; use p2p_repo::types::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -102,6 +105,7 @@ impl From<&IP> for IpAddr {
pub enum TransportProtocol { pub enum TransportProtocol {
WS, WS,
QUIC, QUIC,
Local,
} }
/// IP transport address /// IP transport address
@ -482,7 +486,7 @@ pub enum OverlayRequestContentV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OverlayRequestV0 { pub struct OverlayRequestV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Request content /// Request content
pub content: OverlayRequestContentV0, pub content: OverlayRequestContentV0,
@ -506,7 +510,7 @@ pub enum OverlayResponseContentV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OverlayResponseV0 { pub struct OverlayResponseV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Result /// Result
pub result: u8, pub result: u8,
@ -805,12 +809,22 @@ pub enum BrokerRequestContentV0 {
AddClient(AddClient), AddClient(AddClient),
DelClient(DelClient), DelClient(DelClient),
} }
impl BrokerRequestContentV0 {
pub fn type_id(&self) -> TypeId {
match self {
BrokerRequestContentV0::AddUser(a) => a.type_id(),
BrokerRequestContentV0::DelUser(a) => a.type_id(),
BrokerRequestContentV0::AddClient(a) => a.type_id(),
BrokerRequestContentV0::DelClient(a) => a.type_id(),
}
}
}
/// Broker request /// Broker request
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BrokerRequestV0 { pub struct BrokerRequestV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Request content /// Request content
pub content: BrokerRequestContentV0, pub content: BrokerRequestContentV0,
@ -823,11 +837,16 @@ pub enum BrokerRequest {
} }
impl BrokerRequest { impl BrokerRequest {
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerRequest::V0(o) => o.id, BrokerRequest::V0(o) => o.id,
} }
} }
pub fn type_id(&self) -> TypeId {
match self {
BrokerRequest::V0(o) => o.content.type_id(),
}
}
pub fn content_v0(&self) -> BrokerRequestContentV0 { pub fn content_v0(&self) -> BrokerRequestContentV0 {
match self { match self {
BrokerRequest::V0(o) => o.content.clone(), BrokerRequest::V0(o) => o.content.clone(),
@ -839,7 +858,7 @@ impl BrokerRequest {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BrokerResponseV0 { pub struct BrokerResponseV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Result (including but not limited to Result) /// Result (including but not limited to Result)
pub result: u16, pub result: u16,
@ -852,7 +871,7 @@ pub enum BrokerResponse {
} }
impl BrokerResponse { impl BrokerResponse {
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerResponse::V0(o) => o.id, BrokerResponse::V0(o) => o.id,
} }
@ -1157,7 +1176,7 @@ pub enum BrokerOverlayRequestContentV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BrokerOverlayRequestV0 { pub struct BrokerOverlayRequestV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Request content /// Request content
pub content: BrokerOverlayRequestContentV0, pub content: BrokerOverlayRequestContentV0,
@ -1170,7 +1189,7 @@ pub enum BrokerOverlayRequest {
} }
impl BrokerOverlayRequest { impl BrokerOverlayRequest {
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerOverlayRequest::V0(o) => o.id, BrokerOverlayRequest::V0(o) => o.id,
} }
@ -1194,7 +1213,7 @@ pub enum BrokerOverlayResponseContentV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BrokerOverlayResponseV0 { pub struct BrokerOverlayResponseV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Result (including but not limited to Result) /// Result (including but not limited to Result)
pub result: u16, pub result: u16,
@ -1210,7 +1229,7 @@ pub enum BrokerOverlayResponse {
} }
impl BrokerOverlayResponse { impl BrokerOverlayResponse {
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerOverlayResponse::V0(o) => o.id, BrokerOverlayResponse::V0(o) => o.id,
} }
@ -1299,7 +1318,7 @@ impl BrokerOverlayMessage {
), ),
} }
} }
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerOverlayMessage::V0(o) => match &o.content { BrokerOverlayMessage::V0(o) => match &o.content {
BrokerOverlayMessageContentV0::BrokerOverlayResponse(r) => r.id(), BrokerOverlayMessageContentV0::BrokerOverlayResponse(r) => r.id(),
@ -1374,10 +1393,20 @@ pub struct BrokerMessageV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BrokerMessage { pub enum BrokerMessage {
V0(BrokerMessageV0), V0(BrokerMessageV0),
Close, Close, //TODO: remove Close.
} }
impl BrokerMessage { impl BrokerMessage {
pub fn type_id(&self) -> TypeId {
match self {
BrokerMessage::V0(a) => match &a.content {
BrokerMessageContentV0::BrokerOverlayMessage(p) => p.type_id(),
BrokerMessageContentV0::BrokerResponse(p) => p.type_id(),
BrokerMessageContentV0::BrokerRequest(p) => p.type_id(),
},
BrokerMessage::Close => TypeId::of::<BrokerMessage>(),
}
}
pub fn is_close(&self) -> bool { pub fn is_close(&self) -> bool {
match self { match self {
BrokerMessage::V0(o) => false, BrokerMessage::V0(o) => false,
@ -1411,7 +1440,7 @@ impl BrokerMessage {
BrokerMessage::Close => panic!("Close not implemented"), BrokerMessage::Close => panic!("Close not implemented"),
} }
} }
pub fn id(&self) -> u64 { pub fn id(&self) -> i64 {
match self { match self {
BrokerMessage::V0(o) => match &o.content { BrokerMessage::V0(o) => match &o.content {
BrokerMessageContentV0::BrokerOverlayMessage(p) => p.id(), BrokerMessageContentV0::BrokerOverlayMessage(p) => p.id(),
@ -1520,28 +1549,36 @@ pub enum ExtRequestContentV0 {
ExtBranchSyncReq(ExtBranchSyncReq), ExtBranchSyncReq(ExtBranchSyncReq),
} }
/// External request authenticated by a MAC /// External Request Payload V0
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtRequestPayload {
content: ExtRequestContentV0,
// ...
}
/// External request with its request ID
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtRequestV0 { pub struct ExtRequestV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Request content /// Request payload
pub content: ExtRequestContentV0, pub payload: ExtRequestPayload,
/// BLAKE3 MAC over content
/// BLAKE3 keyed hash:
/// - key: BLAKE3 derive_key ("NextGraph ExtRequest BLAKE3 key",
/// repo_pubkey + repo_secret)
pub mac: Digest,
} }
/// External request authenticated by a MAC
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtRequest { pub enum ExtRequest {
V0(ExtRequestV0), V0(ExtRequestV0),
} }
impl ExtRequest {
pub fn id(&self) -> i64 {
match self {
ExtRequest::V0(v0) => v0.id,
}
}
}
/// Content of ExtResponseV0 /// Content of ExtResponseV0
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ExtResponseContentV0 { pub enum ExtResponseContentV0 {
@ -1554,7 +1591,7 @@ pub enum ExtResponseContentV0 {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ExtResponseV0 { pub struct ExtResponseV0 {
/// Request ID /// Request ID
pub id: u64, pub id: i64,
/// Result code /// Result code
pub result: u16, pub result: u16,
@ -1569,6 +1606,25 @@ pub enum ExtResponse {
V0(ExtResponseV0), V0(ExtResponseV0),
} }
impl ExtResponse {
pub fn id(&self) -> i64 {
match self {
ExtResponse::V0(v0) => v0.id,
}
}
}
impl TryFrom<ProtocolMessage> for ExtResponse {
type Error = ProtocolError;
fn try_from(msg: ProtocolMessage) -> Result<Self, Self::Error> {
if let ProtocolMessage::ExtResponse(ext_res) = msg {
Ok(ext_res)
} else {
Err(ProtocolError::InvalidValue)
}
}
}
/// ///
/// PROTOCOL MESSAGES /// PROTOCOL MESSAGES
/// ///
@ -1579,50 +1635,56 @@ pub enum ProtocolMessage {
ServerHello(ServerHello), ServerHello(ServerHello),
ClientAuth(ClientAuth), ClientAuth(ClientAuth),
AuthResult(AuthResult), AuthResult(AuthResult),
ExtRequest(ExtRequest),
ExtResponse(ExtResponse), ExtResponse(ExtResponse),
BrokerMessage(BrokerMessage), BrokerMessage(BrokerMessage),
} }
/// impl ProtocolMessage {
/// AUTHENTICATION MESSAGES pub fn id(&self) -> i64 {
/// match self {
ProtocolMessage::Noise(_) => 0,
/// Client Hello ProtocolMessage::Start(_) => 0,
#[derive(Clone, Debug, Serialize, Deserialize)] ProtocolMessage::ServerHello(_) => 0,
pub enum ClientHello { ProtocolMessage::ClientAuth(_) => 0,
V0(), ProtocolMessage::AuthResult(_) => 0,
} ProtocolMessage::ExtRequest(ext_req) => ext_req.id(),
ProtocolMessage::ExtResponse(ext_res) => ext_res.id(),
/// Start chosen protocol ProtocolMessage::BrokerMessage(broker_msg) => broker_msg.id(),
/// First message sent by the client }
#[derive(Clone, Debug, Serialize, Deserialize)] }
pub enum StartProtocol { pub fn type_id(&self) -> TypeId {
Auth(ClientHello), match self {
Ext(ExtRequest), ProtocolMessage::Noise(a) => a.type_id(),
} ProtocolMessage::Start(a) => a.type_id(),
ProtocolMessage::ServerHello(a) => a.type_id(),
/// Server hello sent upon a client connection ProtocolMessage::ClientAuth(a) => a.type_id(),
#[derive(Clone, Debug, Serialize, Deserialize)] ProtocolMessage::AuthResult(a) => a.type_id(),
pub struct ServerHelloV0 { ProtocolMessage::ExtRequest(a) => a.type_id(),
/// Nonce for ClientAuth ProtocolMessage::ExtResponse(a) => a.type_id(),
#[serde(with = "serde_bytes")] ProtocolMessage::BrokerMessage(a) => a.type_id(),
pub nonce: Vec<u8>, }
} }
/// Server hello sent upon a client connection
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ServerHello {
V0(ServerHelloV0),
}
impl ServerHello { pub fn get_actor(&self) -> Box<dyn EActor> {
pub fn nonce(&self) -> &Vec<u8> {
match self { match self {
ServerHello::V0(o) => &o.nonce, //ProtocolMessage::Noise(a) => a.get_actor(),
ProtocolMessage::Start(a) => a.get_actor(),
// ProtocolMessage::ServerHello(a) => a.get_actor(),
// ProtocolMessage::ClientAuth(a) => a.get_actor(),
// ProtocolMessage::AuthResult(a) => a.get_actor(),
// ProtocolMessage::ExtRequest(a) => a.get_actor(),
// ProtocolMessage::ExtResponse(a) => a.get_actor(),
// ProtocolMessage::BrokerMessage(a) => a.get_actor(),
_ => unimplemented!(),
} }
} }
} }
///
/// AUTHENTICATION MESSAGES
///
/// Content of ClientAuthV0 /// Content of ClientAuthV0
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientAuthContentV0 { pub struct ClientAuthContentV0 {

Loading…
Cancel
Save