parent
9a4446871a
commit
39764bfa0e
@ -1,3 +0,0 @@ |
||||
pub struct ClientConnection {} |
||||
|
||||
impl ClientConnection {} |
@ -1,180 +0,0 @@ |
||||
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 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>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::pin::Pin; |
||||
|
||||
use debug_print::*; |
||||
use futures::future::BoxFuture; |
||||
use futures::future::OptionFuture; |
||||
use futures::FutureExt; |
||||
use p2p_net::actors::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::*; |
||||
use rust_fsm::*; |
||||
|
||||
// state_machine! {
|
||||
// derive(Debug)
|
||||
// AuthProtocolClient(Ready)
|
||||
|
||||
// Ready(ClientHelloSent) => ClientHelloSent,
|
||||
// ClientHelloSent(ServerHelloReceived) => ServerHelloReceived,
|
||||
// ServerHelloReceived(ClientAuthSent) => ClientAuthSent,
|
||||
// ClientAuthSent(AuthResultReceived) => AuthResult,
|
||||
// AuthResult => {
|
||||
// Ok => BrokerProtocol,
|
||||
// Error => Closed,
|
||||
// },
|
||||
// }
|
||||
|
||||
// state_machine! {
|
||||
// derive(Debug)
|
||||
// AuthProtocolServer(Ready)
|
||||
|
||||
// Ready(ClientHelloReceived) => ClientHelloReceived,
|
||||
// ClientHelloReceived(ServerHelloSent) => ServerHelloSent,
|
||||
// ServerHelloSent(ClientAuthReceived) => ClientAuthReceived,
|
||||
// ClientAuthReceived => {
|
||||
// Ok => AuthResultOk,
|
||||
// Error => AuthResultError,
|
||||
// },
|
||||
// AuthResultOk(AuthResultSent) => BrokerProtocol,
|
||||
// AuthResultError(AuthResultSent) => Closed,
|
||||
// }
|
||||
|
||||
#[derive(Debug)] |
||||
pub struct AuthProtocolHandler { |
||||
//machine: StateMachine<AuthProtocolServer>,
|
||||
nonce: Option<Vec<u8>>, |
||||
user: Option<PubKey>, |
||||
} |
||||
|
||||
impl AuthProtocolHandler { |
||||
pub fn new() -> AuthProtocolHandler { |
||||
AuthProtocolHandler { |
||||
//machine: StateMachine::new(),
|
||||
nonce: None, |
||||
user: None, |
||||
} |
||||
} |
||||
|
||||
pub fn get_user(&self) -> Option<PubKey> { |
||||
self.user |
||||
} |
||||
|
||||
pub fn handle_init(&mut self, client_hello: ClientHello) -> Result<Vec<u8>, ProtocolError> { |
||||
// let _ = self
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ClientHelloReceived)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
let mut random_buf = [0u8; 32]; |
||||
getrandom::getrandom(&mut random_buf).unwrap(); |
||||
let nonce = random_buf.to_vec(); |
||||
let reply = ServerHello::V0(ServerHelloV0 { |
||||
nonce: nonce.clone(), |
||||
}); |
||||
self.nonce = Some(nonce); |
||||
|
||||
// let _ = self
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ServerHelloSent)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
//debug_println!("sending nonce to client: {:?}", self.nonce);
|
||||
|
||||
Ok(serde_bare::to_vec(&reply).unwrap()) |
||||
} |
||||
|
||||
pub fn handle_incoming( |
||||
&mut self, |
||||
frame: Vec<u8>, |
||||
) -> ( |
||||
Result<Vec<u8>, ProtocolError>, |
||||
Pin<Box<OptionFuture<BoxFuture<'static, u16>>>>, |
||||
) { |
||||
fn prepare_reply(res: Result<Vec<u8>, ProtocolError>) -> AuthResult { |
||||
let (result, metadata) = match res { |
||||
Ok(m) => (0, m), |
||||
Err(e) => (e.into(), vec![]), |
||||
}; |
||||
AuthResult::V0(AuthResultV0 { result, metadata }) |
||||
} |
||||
|
||||
fn process_state( |
||||
handler: &mut AuthProtocolHandler, |
||||
frame: Vec<u8>, |
||||
) -> Result<Vec<u8>, ProtocolError> { |
||||
// match handler.machine.state() {
|
||||
// &AuthProtocolServerState::ServerHelloSent => {
|
||||
let message = serde_bare::from_slice::<ClientAuth>(&frame)?; |
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::ClientAuthReceived)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
// verifying client auth
|
||||
|
||||
debug_println!("verifying client auth"); |
||||
|
||||
let _ = verify( |
||||
&serde_bare::to_vec(&message.content_v0()).unwrap(), |
||||
message.sig(), |
||||
message.user(), |
||||
) |
||||
.map_err(|_e| ProtocolError::AccessDenied)?; |
||||
|
||||
// debug_println!(
|
||||
// "matching nonce : {:?} {:?}",
|
||||
// message.nonce(),
|
||||
// handler.nonce.as_ref().unwrap()
|
||||
// );
|
||||
|
||||
if message.nonce() != handler.nonce.as_ref().unwrap() { |
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::Error)
|
||||
// .map_err(|_e| ProtocolError::InvalidState);
|
||||
|
||||
return Err(ProtocolError::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
|
||||
// let _ = handler
|
||||
// .machine
|
||||
// .consume(&AuthProtocolServerInput::Ok)
|
||||
// .map_err(|_e| ProtocolError::InvalidState)?;
|
||||
|
||||
handler.user = Some(message.user()); |
||||
|
||||
Ok(vec![]) // without any metadata
|
||||
//}
|
||||
//_ => Err(ProtocolError::InvalidState),
|
||||
//}
|
||||
} |
||||
|
||||
let res = process_state(self, frame); |
||||
let is_err = res.as_ref().err().cloned(); |
||||
let reply = prepare_reply(res); |
||||
let reply_ser: Result<Vec<u8>, ProtocolError> = Ok(serde_bare::to_vec(&reply).unwrap()); |
||||
if is_err.is_some() { |
||||
( |
||||
reply_ser, |
||||
Box::pin(OptionFuture::from(Some( |
||||
async move { reply.result() }.boxed(), |
||||
))), |
||||
) |
||||
} else { |
||||
(reply_ser, Box::pin(OptionFuture::from(None))) |
||||
} |
||||
} |
||||
} |
@ -1,147 +0,0 @@ |
||||
// Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 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>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
//! Local Connection to a Broker
|
||||
|
||||
use futures::{ |
||||
ready, |
||||
stream::Stream, |
||||
task::{Context, Poll}, |
||||
Future, |
||||
select, FutureExt, |
||||
}; |
||||
use futures::channel::mpsc; |
||||
use std::pin::Pin; |
||||
use std::{collections::HashSet, fmt::Debug}; |
||||
|
||||
use crate::server::BrokerServer; |
||||
use debug_print::*; |
||||
use futures::{pin_mut, stream, Sink, SinkExt, StreamExt}; |
||||
use p2p_repo::object::*; |
||||
use p2p_repo::store::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_net::broker_connection::*; |
||||
use std::collections::HashMap; |
||||
|
||||
|
||||
pub struct BrokerConnectionLocal<'a> { |
||||
broker: &'a mut BrokerServer, |
||||
user: PubKey, |
||||
} |
||||
|
||||
#[async_trait::async_trait] |
||||
impl<'a> BrokerConnection for BrokerConnectionLocal<'a> { |
||||
type OC = BrokerConnectionLocal<'a>; |
||||
type BlockStream = async_channel::Receiver<Block>; |
||||
|
||||
async fn close(&mut self) {} |
||||
|
||||
async fn add_user( |
||||
&mut self, |
||||
user_id: PubKey, |
||||
admin_user_pk: PrivKey, |
||||
) -> Result<(), ProtocolError> { |
||||
let op_content = AddUserContentV0 { user: user_id }; |
||||
let sig = sign(admin_user_pk, self.user, &serde_bare::to_vec(&op_content)?)?; |
||||
|
||||
self.broker.add_user(self.user, user_id, sig) |
||||
} |
||||
|
||||
async fn process_overlay_request( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<(), ProtocolError> { |
||||
match request { |
||||
BrokerOverlayRequestContentV0::OverlayConnect(_) => { |
||||
self.broker.connect_overlay(self.user, overlay) |
||||
} |
||||
BrokerOverlayRequestContentV0::OverlayJoin(j) => { |
||||
self.broker |
||||
.join_overlay(self.user, overlay, j.repo_pubkey(), j.secret(), j.peers()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectPin(op) => { |
||||
self.broker.pin_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectUnpin(op) => { |
||||
self.broker.unpin_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::ObjectDel(op) => { |
||||
self.broker.del_object(self.user, overlay, op.id()) |
||||
} |
||||
BrokerOverlayRequestContentV0::BlockPut(b) => { |
||||
self.broker.put_block(self.user, overlay, b.block()) |
||||
} |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn process_overlay_request_objectid_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<ObjectId, ProtocolError> { |
||||
match request { |
||||
BrokerOverlayRequestContentV0::ObjectCopy(oc) => { |
||||
self.broker |
||||
.copy_object(self.user, overlay, oc.id(), oc.expiry()) |
||||
} |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn process_overlay_request_stream_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<Pin<Box<Self::BlockStream>>, ProtocolError> { |
||||
match request { |
||||
|
||||
BrokerOverlayRequestContentV0::BlockGet(b) => self |
||||
.broker |
||||
.get_block(self.user, overlay, b.id(), b.include_children(), b.topic()) |
||||
.map(|r| Box::pin(r)), |
||||
BrokerOverlayRequestContentV0::BranchSyncReq(b) => self |
||||
.broker |
||||
.sync_branch( |
||||
self.user, |
||||
&overlay, |
||||
b.heads(), |
||||
b.known_heads(), |
||||
b.known_commits(), |
||||
) |
||||
.map(|r| Box::pin(r)), |
||||
_ => Err(ProtocolError::InvalidState), |
||||
} |
||||
} |
||||
|
||||
async fn del_user(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn add_client(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn del_client(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn overlay_connect( |
||||
&mut self, |
||||
repo_link: &RepoLink, |
||||
public: bool, |
||||
) -> Result<OverlayConnectionClient<BrokerConnectionLocal<'a>>, ProtocolError> { |
||||
let overlay = self.process_overlay_connect(repo_link, public).await?; |
||||
Ok(OverlayConnectionClient::create(self, overlay, repo_link.clone())) |
||||
} |
||||
} |
||||
|
||||
impl<'a> BrokerConnectionLocal<'a> { |
||||
pub fn new(broker: &'a mut BrokerServer, user: PubKey) -> BrokerConnectionLocal<'a> { |
||||
BrokerConnectionLocal { broker, user } |
||||
} |
||||
} |
@ -1,3 +0,0 @@ |
||||
pub struct ServerConnection {} |
||||
|
||||
impl ServerConnection {} |
@ -1,93 +0,0 @@ |
||||
/* |
||||
* Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||
* All rights reserved. |
||||
* Licensed under the Apache License, Version 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>,
|
||||
* at your option. All files in the project carrying such |
||||
* notice may not be copied, modified, or distributed except |
||||
* according to those terms. |
||||
*/ |
||||
|
||||
//! WebSocket Remote Connection to a Broker
|
||||
|
||||
use debug_print::*; |
||||
|
||||
use futures::{future, pin_mut, stream, SinkExt, StreamExt}; |
||||
use p2p_client::connection_remote::*; |
||||
use p2p_net::broker_connection::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::{generate_keypair, now_timestamp}; |
||||
|
||||
use async_tungstenite::async_std::connect_async; |
||||
use async_tungstenite::client_async; |
||||
use async_tungstenite::tungstenite::{Error, Message}; |
||||
|
||||
pub struct BrokerConnectionWebSocket {} |
||||
|
||||
impl BrokerConnectionWebSocket { |
||||
pub async fn open( |
||||
url: &str, |
||||
priv_key: PrivKey, |
||||
pub_key: PubKey, |
||||
) -> Result<impl BrokerConnection, ProtocolError> { |
||||
let res = connect_async(url).await; |
||||
|
||||
match (res) { |
||||
Ok((ws, _)) => { |
||||
debug_println!("WebSocket handshake completed"); |
||||
|
||||
let (write, read) = ws.split(); |
||||
let mut frames_stream_read = read.map(|msg_res| match msg_res { |
||||
Err(e) => { |
||||
debug_println!("ERROR {:?}", e); |
||||
vec![] |
||||
} |
||||
Ok(message) => { |
||||
if message.is_close() { |
||||
debug_println!("CLOSE FROM SERVER"); |
||||
vec![] |
||||
} else { |
||||
message.into_data() |
||||
} |
||||
} |
||||
}); |
||||
async fn transform(message: Vec<u8>) -> Result<Message, Error> { |
||||
if message.len() == 0 { |
||||
debug_println!("sending CLOSE message to SERVER"); |
||||
Ok(Message::Close(None)) |
||||
} else { |
||||
Ok(Message::binary(message)) |
||||
} |
||||
} |
||||
let frames_stream_write = write |
||||
.with(|message| transform(message)) |
||||
.sink_map_err(|e| ProtocolError::WriteError); |
||||
|
||||
let master_key: [u8; 32] = [0; 32]; |
||||
let mut cnx_res = ConnectionRemote::open_broker_connection( |
||||
frames_stream_write, |
||||
frames_stream_read, |
||||
pub_key, |
||||
priv_key, |
||||
PubKey::Ed25519PubKey([1; 32]), |
||||
) |
||||
.await; |
||||
|
||||
match cnx_res { |
||||
Ok(mut cnx) => Ok(cnx), |
||||
Err(e) => { |
||||
debug_println!("cannot connect {:?}", e); |
||||
Err(e) |
||||
} |
||||
} |
||||
} |
||||
Err(e) => { |
||||
debug_println!("Cannot connect: {:?}", e); |
||||
Err(ProtocolError::ConnectionError) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,25 +0,0 @@ |
||||
[package] |
||||
name = "p2p-client" |
||||
version = "0.1.0" |
||||
edition = "2021" |
||||
license = "MIT/Apache-2.0" |
||||
authors = ["Niko PLP <niko@nextgraph.org>"] |
||||
description = "P2P Client module of NextGraph" |
||||
repository = "https://git.nextgraph.org/NextGraph/nextgraph-rs" |
||||
|
||||
[dependencies] |
||||
debug_print = "1.0.0" |
||||
p2p-repo = { path = "../p2p-repo" } |
||||
p2p-net = { path = "../p2p-net" } |
||||
chacha20 = "0.9.0" |
||||
serde = { version = "1.0", features = ["derive"] } |
||||
serde_bare = "0.5.0" |
||||
serde_bytes = "0.11.7" |
||||
xactor = "0.7.11" |
||||
async-trait = "0.1.64" |
||||
async-std = { version = "1.12.0", features = ["attributes"] } |
||||
futures = "0.3.24" |
||||
async-channel = "1.7.1" |
||||
async-oneshot = "0.5.0" |
||||
snow = "0.9.2" |
||||
|
@ -1,598 +0,0 @@ |
||||
/* |
||||
* Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||
* All rights reserved. |
||||
* Licensed under the Apache License, Version 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>,
|
||||
* at your option. All files in the project carrying such |
||||
* notice may not be copied, modified, or distributed except |
||||
* according to those terms. |
||||
*/ |
||||
|
||||
//! Remote Connection to a Broker
|
||||
|
||||
use async_std::task; |
||||
use async_std::sync::Mutex; |
||||
use futures::{ |
||||
ready, |
||||
stream::Stream, |
||||
task::{Context, Poll}, |
||||
Future, |
||||
select, FutureExt, |
||||
}; |
||||
use futures::channel::mpsc; |
||||
use std::pin::Pin; |
||||
use std::{collections::HashSet, fmt::Debug}; |
||||
|
||||
use async_oneshot::oneshot; |
||||
use debug_print::*; |
||||
use futures::{pin_mut, stream, Sink, SinkExt, StreamExt}; |
||||
use p2p_repo::object::*; |
||||
use p2p_repo::store::*; |
||||
use p2p_repo::types::*; |
||||
use p2p_repo::utils::*; |
||||
use p2p_net::errors::*; |
||||
use p2p_net::types::*; |
||||
use p2p_net::broker_connection::*; |
||||
use std::collections::HashMap; |
||||
use std::sync::{Arc, RwLock}; |
||||
use xactor::{message, spawn, Actor, Addr, Handler, WeakAddr}; |
||||
|
||||
|
||||
#[message] |
||||
struct BrokerMessageXActor(BrokerMessage); |
||||
|
||||
struct BrokerMessageActor { |
||||
r: Option<async_oneshot::Receiver<BrokerMessage>>, |
||||
s: async_oneshot::Sender<BrokerMessage>, |
||||
} |
||||
|
||||
impl Actor for BrokerMessageActor {} |
||||
|
||||
impl BrokerMessageActor { |
||||
fn new() -> BrokerMessageActor { |
||||
let (s, r) = oneshot::<BrokerMessage>(); |
||||
BrokerMessageActor { r: Some(r), s } |
||||
} |
||||
fn resolve(&mut self, msg: BrokerMessage) { |
||||
let _ = self.s.send(msg); |
||||
} |
||||
|
||||
fn receiver(&mut self) -> async_oneshot::Receiver<BrokerMessage> { |
||||
self.r.take().unwrap() |
||||
} |
||||
} |
||||
|
||||
struct BrokerMessageStreamActor { |
||||
r: Option<async_channel::Receiver<Block>>, |
||||
s: async_channel::Sender<Block>, |
||||
error_r: Option<async_oneshot::Receiver<Option<ProtocolError>>>, |
||||
error_s: Option<async_oneshot::Sender<Option<ProtocolError>>>, |
||||
} |
||||
|
||||
impl Actor for BrokerMessageStreamActor {} |
||||
|
||||
impl BrokerMessageStreamActor { |
||||
fn new() -> BrokerMessageStreamActor { |
||||
let (s, r) = async_channel::unbounded::<Block>(); |
||||
let (error_s, error_r) = oneshot::<Option<ProtocolError>>(); |
||||
BrokerMessageStreamActor { |
||||
r: Some(r), |
||||
s, |
||||
error_r: Some(error_r), |
||||
error_s: Some(error_s), |
||||
} |
||||
} |
||||
async fn partial(&mut self, block: Block) -> Result<(), ProtocolError> { |
||||
//debug_println!("GOT PARTIAL {:?}", block.id());
|
||||
self.s |
||||
.send(block) |
||||
.await |
||||
.map_err(|e| ProtocolError::WriteError) |
||||
} |
||||
|
||||
fn receiver(&mut self) -> async_channel::Receiver<Block> { |
||||
self.r.take().unwrap() |
||||
} |
||||
|
||||
fn error_receiver(&mut self) -> async_oneshot::Receiver<Option<ProtocolError>> { |
||||
self.error_r.take().unwrap() |
||||
} |
||||
|
||||
fn send_error(&mut self, err: Option<ProtocolError>) { |
||||
if self.error_s.is_some() { |
||||
let _ = self.error_s.take().unwrap().send(err); |
||||
self.error_s = None; |
||||
} |
||||
} |
||||
|
||||
fn close(&mut self) { |
||||
self.s.close(); |
||||
} |
||||
} |
||||
|
||||
#[async_trait::async_trait] |
||||
impl Handler<BrokerMessageXActor> for BrokerMessageActor { |
||||
async fn handle(&mut self, ctx: &mut xactor::Context<Self>, msg: BrokerMessageXActor) { |
||||
//println!("handling {:?}", msg.0);
|
||||
self.resolve(msg.0); |
||||
ctx.stop(None); |
||||
} |
||||
} |
||||
|
||||
#[async_trait::async_trait] |
||||
impl Handler<BrokerMessageXActor> for BrokerMessageStreamActor { |
||||
async fn handle(&mut self, ctx: &mut xactor::Context<Self>, msg: BrokerMessageXActor) { |
||||
//println!("handling {:?}", msg.0);
|
||||
let res: Result<Option<Block>, ProtocolError> = msg.0.into(); |
||||
match res { |
||||
Err(e) => { |
||||
self.send_error(Some(e)); |
||||
ctx.stop(None); |
||||
self.close(); |
||||
} |
||||
Ok(Some(b)) => { |
||||
self.send_error(None); |
||||
// it must be a partial content
|
||||
let res = self.partial(b).await; |
||||
if let Err(e) = res { |
||||
ctx.stop(None); |
||||
self.close(); |
||||
} |
||||
} |
||||
Ok(None) => { |
||||
self.send_error(None); |
||||
ctx.stop(None); |
||||
self.close(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub struct ConnectionRemote {} |
||||
|
||||
impl ConnectionRemote { |
||||
pub async fn ext_request< |
||||
B: Stream<Item = Vec<u8>> + StreamExt + Send + Sync, |
||||
A: Sink<Vec<u8>, Error = ProtocolError> + Send, |
||||
>( |
||||
w: A, |
||||
r: B, |
||||
request: ExtRequest, |
||||
) -> Result<ExtResponse, ProtocolError> { |
||||
unimplemented!(); |
||||
} |
||||
|
||||
async fn close<S>(w: S, err: ProtocolError) -> ProtocolError |
||||
where |
||||
S: Sink<Vec<u8>, Error = ProtocolError>, |
||||
{ |
||||
let mut writer = Box::pin(w); |
||||
let _ = writer.send(vec![]); |
||||
let _ = writer.close().await; |
||||
err |
||||
} |
||||
|
||||
pub async fn open_broker_connection< |
||||
B: Stream<Item = Vec<u8>> + StreamExt + Send + Sync + 'static, |
||||
A: Sink<Vec<u8>, Error = ProtocolError> + Send + 'static, |
||||
>( |
||||
w: A, |
||||
r: B, |
||||
user: PubKey, |
||||
user_pk: PrivKey, |
||||
client: PubKey, |
||||
) -> Result<impl BrokerConnection, ProtocolError> { |
||||
let mut writer = Box::pin(w); |
||||
writer |
||||
.send(serde_bare::to_vec(&StartProtocol::Auth(ClientHello::V0()))?) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
let mut reader = Box::pin(r); |
||||
let answer = reader.next().await; |
||||
if answer.is_none() { |
||||
return Err(Self::close(writer, ProtocolError::InvalidState).await); |
||||
} |
||||
|
||||
let server_hello = serde_bare::from_slice::<ServerHello>(&answer.unwrap())?; |
||||
|
||||
//debug_println!("received nonce from server: {:?}", server_hello.nonce());
|
||||
|
||||
let content = ClientAuthContentV0 { |
||||
user, |
||||
client, |
||||
nonce: server_hello.nonce().clone(), |
||||
}; |
||||
|
||||
let sig = sign(user_pk, user, &serde_bare::to_vec(&content)?) |
||||
.map_err(|_e| ProtocolError::SignatureError)?; |
||||
|
||||
let auth_ser = serde_bare::to_vec(&ClientAuth::V0(ClientAuthV0 { content, sig }))?; |
||||
//debug_println!("AUTH SENT {:?}", auth_ser);
|
||||
writer |
||||
.send(auth_ser) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
let answer = reader.next().await; |
||||
if answer.is_none() { |
||||
//return Err(ProtocolError::InvalidState);
|
||||
return Err(Self::close(writer, ProtocolError::InvalidState).await); |
||||
} |
||||
|
||||
let auth_result = serde_bare::from_slice::<AuthResult>(&answer.unwrap())?; |
||||
|
||||
match auth_result.result() { |
||||
0 => { |
||||
async fn transform(message: BrokerMessage) -> Result<Vec<u8>, ProtocolError> { |
||||
if message.is_close() { |
||||
Ok(vec![]) |
||||
} else { |
||||
Ok(serde_bare::to_vec(&message)?) |
||||
} |
||||
} |
||||
let messages_stream_write = writer.with(|message| transform(message)); |
||||
|
||||
let mut messages_stream_read = reader.map(|message| { |
||||
if message.len() == 0 { |
||||
BrokerMessage::Close |
||||
} else { |
||||
match serde_bare::from_slice::<BrokerMessage>(&message) { |
||||
Err(e) => BrokerMessage::Close, |
||||
Ok(m) => m |
||||
} |
||||
} |
||||
}); |
||||
|
||||
let cnx = |
||||
BrokerConnectionRemote::open(messages_stream_write, messages_stream_read, user); |
||||
|
||||
Ok(cnx) |
||||
} |
||||
err => Err(Self::close(writer, ProtocolError::try_from(err).unwrap()).await), |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub struct BrokerConnectionRemote<T> |
||||
where |
||||
T: Sink<BrokerMessage> + Send + 'static, |
||||
{ |
||||
writer: Arc<Mutex<Pin<Box<T>>>>, |
||||
user: PubKey, |
||||
actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageActor>>>>, |
||||
stream_actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageStreamActor>>>>, |
||||
shutdown: mpsc::UnboundedSender<Void>, |
||||
} |
||||
|
||||
#[async_trait::async_trait] |
||||
impl<T> BrokerConnection for BrokerConnectionRemote<T> |
||||
where |
||||
T: Sink<BrokerMessage> + Send, |
||||
{ |
||||
type OC = BrokerConnectionRemote<T>; |
||||
type BlockStream = async_channel::Receiver<Block>; |
||||
|
||||
async fn close(&mut self) { |
||||
let _ = self.shutdown.close().await; |
||||
let mut w = self.writer.lock().await; |
||||
let _ = w.send(BrokerMessage::Close).await; |
||||
let _ = w.close().await; |
||||
} |
||||
|
||||
async fn process_overlay_request_stream_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<Pin<Box<Self::BlockStream>>, ProtocolError> { |
||||
let mut actor = BrokerMessageStreamActor::new(); |
||||
let receiver = actor.receiver(); |
||||
let error_receiver = actor.error_receiver(); |
||||
let mut addr = actor |
||||
.start() |
||||
.await |
||||
.map_err(|_e| ProtocolError::ActorError)?; |
||||
|
||||
let request_id = addr.actor_id(); |
||||
//debug_println!("actor ID {}", request_id);
|
||||
|
||||
{ |
||||
let mut map = self.stream_actors.write().expect("RwLock poisoned"); |
||||
map.insert(request_id, addr.downgrade()); |
||||
} |
||||
|
||||
let mut w = self.writer.lock().await; |
||||
w.send(BrokerMessage::V0(BrokerMessageV0 { |
||||
padding: vec![], //FIXME implement padding
|
||||
content: BrokerMessageContentV0::BrokerOverlayMessage(BrokerOverlayMessage::V0( |
||||
BrokerOverlayMessageV0 { |
||||
overlay, |
||||
content: BrokerOverlayMessageContentV0::BrokerOverlayRequest( |
||||
BrokerOverlayRequest::V0(BrokerOverlayRequestV0 { |
||||
id: request_id, |
||||
content: request, |
||||
}), |
||||
), |
||||
}, |
||||
)), |
||||
})) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
//debug_println!("waiting for first reply");
|
||||
let reply = error_receiver.await; |
||||
match reply { |
||||
Err(_e) => { |
||||
Err(ProtocolError::Closing) |
||||
} |
||||
Ok(Some(e)) => { |
||||
let mut map = self.stream_actors.write().expect("RwLock poisoned"); |
||||
map.remove(&request_id); |
||||
return Err(e); |
||||
} |
||||
Ok(None) => { |
||||
let stream_actors_in_thread = Arc::clone(&self.stream_actors); |
||||
task::spawn(async move { |
||||
addr.wait_for_stop().await; // TODO add timeout
|
||||
let mut map = stream_actors_in_thread.write().expect("RwLock poisoned"); |
||||
map.remove(&request_id); |
||||
}); |
||||
|
||||
Ok(Box::pin(receiver)) |
||||
} |
||||
} |
||||
} |
||||
|
||||
async fn process_overlay_request_objectid_response( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<ObjectId, ProtocolError> { |
||||
before!(self, request_id, addr, receiver); |
||||
|
||||
self.writer.lock().await |
||||
.send(BrokerMessage::V0(BrokerMessageV0 { |
||||
padding: vec![], // FIXME implement padding
|
||||
content: BrokerMessageContentV0::BrokerOverlayMessage(BrokerOverlayMessage::V0( |
||||
BrokerOverlayMessageV0 { |
||||
overlay, |
||||
content: BrokerOverlayMessageContentV0::BrokerOverlayRequest( |
||||
BrokerOverlayRequest::V0(BrokerOverlayRequestV0 { |
||||
id: request_id, |
||||
content: request, |
||||
}), |
||||
), |
||||
}, |
||||
)), |
||||
})) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
after!(self, request_id, addr, receiver, reply); |
||||
reply.into() |
||||
} |
||||
|
||||
async fn process_overlay_request( |
||||
&mut self, |
||||
overlay: OverlayId, |
||||
request: BrokerOverlayRequestContentV0, |
||||
) -> Result<(), ProtocolError> { |
||||
before!(self, request_id, addr, receiver); |
||||
|
||||
self.writer.lock().await |
||||
.send(BrokerMessage::V0(BrokerMessageV0 { |
||||
padding: vec![], // FIXME implement padding
|
||||
content: BrokerMessageContentV0::BrokerOverlayMessage(BrokerOverlayMessage::V0( |
||||
BrokerOverlayMessageV0 { |
||||
overlay, |
||||
content: BrokerOverlayMessageContentV0::BrokerOverlayRequest( |
||||
BrokerOverlayRequest::V0(BrokerOverlayRequestV0 { |
||||
id: request_id, |
||||
content: request, |
||||
}), |
||||
), |
||||
}, |
||||
)), |
||||
})) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
after!(self, request_id, addr, receiver, reply); |
||||
reply.into() |
||||
} |
||||
|
||||
async fn add_user( |
||||
&mut self, |
||||
user_id: PubKey, |
||||
admin_user_pk: PrivKey, |
||||
) -> Result<(), ProtocolError> { |
||||
before!(self, request_id, addr, receiver); |
||||
|
||||
let op_content = AddUserContentV0 { user: user_id }; |
||||
|
||||
let sig = sign( |
||||
admin_user_pk, |
||||
self.user, |
||||
&serde_bare::to_vec(&op_content)?, |
||||
)?; |
||||
|
||||
self.writer.lock().await |
||||
.send(BrokerMessage::V0(BrokerMessageV0 { |
||||
padding: vec![], // TODO implement padding
|
||||
content: BrokerMessageContentV0::BrokerRequest(BrokerRequest::V0( |
||||
BrokerRequestV0 { |
||||
id: request_id, |
||||
content: BrokerRequestContentV0::AddUser(AddUser::V0(AddUserV0 { |
||||
content: op_content, |
||||
sig, |
||||
})), |
||||
}, |
||||
)), |
||||
})) |
||||
.await |
||||
.map_err(|_e| ProtocolError::WriteError)?; |
||||
|
||||
after!(self, request_id, addr, receiver, reply); |
||||
reply.into() |
||||
} |
||||
|
||||
async fn del_user(&mut self, user_id: PubKey, admin_user_pk: PrivKey) {} |
||||
|
||||
async fn add_client(&mut self, client_id: ClientId, user_pk: PrivKey) {} |
||||
|
||||
async fn del_client(&mut self, client_id: ClientId, user_pk: PrivKey) {} |
||||
|
||||
async fn overlay_connect( |
||||
&mut self, |
||||
repo_link: &RepoLink, |
||||
public: bool, |
||||
) -> Result<OverlayConnectionClient<BrokerConnectionRemote<T>>, ProtocolError> { |
||||
let overlay = self.process_overlay_connect(repo_link, public).await?; |
||||
|
||||
Ok(OverlayConnectionClient::create(self, overlay,repo_link.clone() )) |
||||
} |
||||
} |
||||
|
||||
#[derive(Debug)] |
||||
enum Void {} |
||||
|
||||
impl<T> BrokerConnectionRemote<T> |
||||
where |
||||
T: Sink<BrokerMessage> + Send, |
||||
{ |
||||
async fn connection_reader_loop< |
||||
U: Stream<Item = BrokerMessage> + StreamExt + Send + Sync + Unpin + 'static, |
||||
>( |
||||
stream: U, |
||||
actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageActor>>>>, |
||||
stream_actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageStreamActor>>>>, |
||||
shutdown: mpsc::UnboundedReceiver<Void>, |
||||
) -> Result<(), ProtocolError> { |
||||
let mut s = stream.fuse(); |
||||
let mut shutdown = shutdown.fuse(); |
||||
loop { |
||||
select! { |
||||
void = shutdown.next().fuse() => match void { |
||||
Some(void) => match void {}, |
||||
None => break, |
||||
}, |
||||
message = s.next().fuse() => match message { |
||||
Some(message) =>
|
||||
{ |
||||
//debug_println!("GOT MESSAGE {:?}", message);
|
||||
|
||||
if message.is_close() { |
||||
// releasing the blocking calls on the actors
|
||||
|
||||
let map = actors.read().expect("RwLock poisoned"); |
||||
for (a) in map.values() { |
||||
if let Some(mut addr) = a.upgrade() { |
||||
let _ = addr.stop(Some(ProtocolError::Closing.into())); |
||||
} |
||||
} |
||||
let map2 = stream_actors.read().expect("RwLock poisoned"); |
||||
for (a) in map2.values() { |
||||
if let Some(mut addr) = a.upgrade() { |
||||
let _ = addr.stop(Some(ProtocolError::Closing.into())); |
||||
} |
||||
} |
||||
return Err(ProtocolError::Closing); |
||||
} |
||||
|
||||
if message.is_request() { |
||||
debug_println!("is request {}", message.id()); |
||||
// closing connection. a client is not supposed to receive requests.
|
||||
return Err(ProtocolError::Closing); |
||||
|
||||
} else if message.is_response() { |
||||
let id = message.id(); |
||||
//debug_println!("is response for {}", id);
|
||||
{ |
||||
let map = actors.read().expect("RwLock poisoned"); |
||||
match map.get(&id) { |
||||
Some(weak_addr) => match weak_addr.upgrade() { |
||||
Some(addr) => { |
||||
addr.send(BrokerMessageXActor(message)) |
||||
.map_err(|e| ProtocolError::Closing)? |
||||
//.expect("sending message back to actor failed");
|
||||
} |
||||
None => { |
||||
debug_println!("ERROR. Addr is dead for ID {}", id); |
||||
return Err(ProtocolError::Closing); |
||||
} |
||||
}, |
||||
None => { |
||||
let map2 = stream_actors.read().expect("RwLock poisoned"); |
||||
match map2.get(&id) { |
||||
Some(weak_addr) => match weak_addr.upgrade() { |
||||
Some(addr) => { |
||||
addr.send(BrokerMessageXActor(message)) |
||||
.map_err(|e| ProtocolError::Closing)? |
||||
//.expect("sending message back to stream actor failed");
|
||||
} |
||||
None => { |
||||
debug_println!( |
||||
"ERROR. Addr is dead for ID {} {:?}", |
||||
id, |
||||
message |
||||
); |
||||
return Err(ProtocolError::Closing); |
||||
} |
||||
}, |
||||
None => { |
||||
debug_println!("Actor ID not found {} {:?}", id, message); |
||||
return Err(ProtocolError::Closing); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
None => break, |
||||
} |
||||
} |
||||
} |
||||
Ok(()) |
||||
} |
||||
|
||||
pub fn open<U: Stream<Item = BrokerMessage> + StreamExt + Send + Sync + Unpin + 'static>( |
||||
writer: T, |
||||
reader: U, |
||||
user: PubKey, |
||||
) -> BrokerConnectionRemote<T> { |
||||
let actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageActor>>>> = |
||||
Arc::new(RwLock::new(HashMap::new())); |
||||
|
||||
let stream_actors: Arc<RwLock<HashMap<u64, WeakAddr<BrokerMessageStreamActor>>>> = |
||||
Arc::new(RwLock::new(HashMap::new())); |
||||
|
||||
let (shutdown_sender, shutdown_receiver) = mpsc::unbounded::<Void>(); |
||||
|
||||
let w = Arc::new(Mutex::new(Box::pin(writer))); |
||||
let ws_in_task = Arc::clone(&w); |
||||
|
||||
let actors_in_thread = Arc::clone(&actors); |
||||
let stream_actors_in_thread = Arc::clone(&stream_actors); |
||||
task::spawn(async move { |
||||
debug_println!("START of reader loop"); |
||||
if let Err(e) = |
||||
Self::connection_reader_loop(reader, actors_in_thread, stream_actors_in_thread, shutdown_receiver) |
||||
.await |
||||
{ |
||||
debug_println!("closing because of {}", e); |
||||
let _ = ws_in_task.lock().await.close().await; |
||||
} |
||||
debug_println!("END of reader loop"); |
||||
}); |
||||
|
||||
BrokerConnectionRemote::<T> { |
||||
writer: Arc::clone(&w), |
||||
user, |
||||
actors: Arc::clone(&actors), |
||||
stream_actors: Arc::clone(&stream_actors), |
||||
shutdown:shutdown_sender , |
||||
} |
||||
} |
||||
} |
@ -1,47 +0,0 @@ |
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 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>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
#[macro_export] |
||||
macro_rules! before { |
||||
( $self:expr, $request_id:ident, $addr:ident, $receiver:ident ) => { |
||||
let mut actor = BrokerMessageActor::new(); |
||||
let $receiver = actor.receiver(); |
||||
let mut $addr = actor |
||||
.start() |
||||
.await |
||||
.map_err(|_e| ProtocolError::ActorError)?; |
||||
|
||||
let $request_id = $addr.actor_id(); |
||||
//debug_println!("actor ID {}", $request_id);
|
||||
|
||||
{ |
||||
let mut map = $self.actors.write().expect("RwLock poisoned"); |
||||
map.insert($request_id, $addr.downgrade()); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
macro_rules! after { |
||||
( $self:expr, $request_id:ident, $addr:ident, $receiver:ident, $reply:ident ) => { |
||||
//debug_println!("waiting for reply");
|
||||
|
||||
$addr.wait_for_stop().await; // TODO add timeout and close connection if there's no reply
|
||||
let r = $receiver.await; |
||||
if r.is_err() { |
||||
return Err(ProtocolError::Closing); |
||||
} |
||||
let $reply = r.unwrap(); |
||||
//debug_println!("reply arrived {:?}", $reply);
|
||||
{ |
||||
let mut map = $self.actors.write().expect("RwLock poisoned"); |
||||
map.remove(&$request_id); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
//pub mod connection_remote;
|
Loading…
Reference in new issue