From 9a4446871a5c78743875009d19b78cbe2a879a19 Mon Sep 17 00:00:00 2001 From: Niko Date: Thu, 4 May 2023 15:14:41 +0300 Subject: [PATCH] ClientAuth is working --- ng-app-js/src/lib.rs | 19 ++- p2p-broker/src/server.rs | 8 +- p2p-client-ws/src/connection_ws.rs | 34 +++-- p2p-client-ws/src/remote_ws.rs | 37 +++--- p2p-client-ws/src/remote_ws_wasm.rs | 17 ++- p2p-net/src/broker.rs | 2 + p2p-net/src/connection.rs | 185 ++++++++++++++++++++++++---- p2p-net/src/errors.rs | 7 +- p2p-net/src/types.rs | 12 ++ 9 files changed, 242 insertions(+), 79 deletions(-) diff --git a/ng-app-js/src/lib.rs b/ng-app-js/src/lib.rs index a961f07..d6fce95 100644 --- a/ng-app-js/src/lib.rs +++ b/ng-app-js/src/lib.rs @@ -4,6 +4,7 @@ use js_sys::Reflect; #[cfg(target_arch = "wasm32")] use p2p_client_ws::remote_ws_wasm::ConnectionWebSocket; use p2p_net::broker::*; +use p2p_net::connection::{ClientConfig, StartConfig}; use p2p_net::types::{DirectPeerId, IP}; use p2p_net::utils::{spawn_and_log_error, ResultSend}; use p2p_net::{log, sleep}; @@ -33,11 +34,14 @@ pub async fn greet(name: &str) { 241, 52, 155, 231, 83, 188, 189, 47, 135, 105, 213, 39, 91, ]); - log!("start connecting"); - //let cnx = Arc::new(); let keys = p2p_net::utils::gen_keys(); let pub_key = PubKey::Ed25519PubKey(keys.1); + let (client_priv_key, client_pub_key) = generate_keypair(); + let (user_priv_key, user_pub_key) = generate_keypair(); + + log!("start connecting"); + let res = BROKER .write() .await @@ -48,6 +52,11 @@ pub async fn greet(name: &str) { keys.0, pub_key, server_key, + StartConfig::Client(ClientConfig { + user: user_pub_key, + client: client_pub_key, + client_priv: client_priv_key, + }), ) .await; log!("broker.connect : {:?}", res); @@ -60,7 +69,7 @@ pub async fn greet(name: &str) { async fn timer_close(remote_peer_id: DirectPeerId) -> ResultSend<()> { async move { - sleep!(std::time::Duration::from_secs(10)); + sleep!(std::time::Duration::from_secs(3)); log!("timeout"); BROKER .write() @@ -71,11 +80,11 @@ pub async fn greet(name: &str) { .await; Ok(()) } - spawn_and_log_error(timer_close(pub_key)); + spawn_and_log_error(timer_close(server_key)); //Broker::graceful_shutdown().await; - Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(12)).await; + Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(5)).await; Ok(()) } diff --git a/p2p-broker/src/server.rs b/p2p-broker/src/server.rs index 15d6d67..c90db32 100644 --- a/p2p-broker/src/server.rs +++ b/p2p-broker/src/server.rs @@ -588,7 +588,7 @@ impl BrokerServer { let mut path = self.store.path(); path.push(REPO_STORES_SUBDIR); path.push::(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::IoError)?; println!("path for repo store: {}", path.to_str().unwrap()); let repo = LmdbRepoStore::open(&path, *key.slice()); let mut writer = self.repo_stores.write().expect("write repo_store hashmap"); @@ -846,7 +846,7 @@ impl BrokerServer { if !include_children { let block = store.get(&id)?; s.send_blocking(block) - .map_err(|_e| ProtocolError::WriteError)?; + .map_err(|_e| ProtocolError::IoError)?; Ok(r) } else { let obj = Object::load(id, None, store); @@ -863,7 +863,7 @@ impl BrokerServer { let id = block.id(); if deduplicated.get(&id).is_none() { s.send_blocking(block.clone()) - .map_err(|_e| ProtocolError::WriteError)?; + .map_err(|_e| ProtocolError::IoError)?; deduplicated.insert(id); } } @@ -902,7 +902,7 @@ impl BrokerServer { let id = block.id(); if deduplicated.get(&id).is_none() { s.send_blocking(block.clone()) - .map_err(|_e| ProtocolError::WriteError)?; + .map_err(|_e| ProtocolError::IoError)?; deduplicated.insert(id); } } diff --git a/p2p-client-ws/src/connection_ws.rs b/p2p-client-ws/src/connection_ws.rs index ac41cbe..80e22d3 100644 --- a/p2p-client-ws/src/connection_ws.rs +++ b/p2p-client-ws/src/connection_ws.rs @@ -2,7 +2,7 @@ * Copyright (c) 2022-2023 Niko Bonnieure, Par le Peuple, NextGraph.org developers * All rights reserved. * Licensed under the Apache License, Version 2.0 - * + * * or the MIT license , * at your option. All files in the project carrying such * notice may not be copied, modified, or distributed except @@ -13,27 +13,26 @@ use debug_print::*; -use p2p_repo::types::*; -use p2p_repo::utils::{generate_keypair, now_timestamp}; +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_net::broker_connection::*; -use p2p_client::connection_remote::*; -use futures::{future, pin_mut, stream, SinkExt, StreamExt}; +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 - { +pub struct BrokerConnectionWebSocket {} +impl BrokerConnectionWebSocket { + pub async fn open( + url: &str, + priv_key: PrivKey, + pub_key: PubKey, + ) -> Result { let res = connect_async(url).await; match (res) { @@ -78,9 +77,7 @@ impl BrokerConnectionWebSocket{ .await; match cnx_res { - Ok(mut cnx) => { - Ok(cnx) - } + Ok(mut cnx) => Ok(cnx), Err(e) => { debug_println!("cannot connect {:?}", e); Err(e) @@ -93,5 +90,4 @@ impl BrokerConnectionWebSocket{ } } } - -} \ No newline at end of file +} diff --git a/p2p-client-ws/src/remote_ws.rs b/p2p-client-ws/src/remote_ws.rs index 892ec47..1b37428 100644 --- a/p2p-client-ws/src/remote_ws.rs +++ b/p2p-client-ws/src/remote_ws.rs @@ -47,6 +47,7 @@ impl IConnect for ConnectionWebSocket { peer_privk: Sensitive<[u8; 32]>, peer_pubk: PubKey, remote_peer: DirectPeerId, + config: StartConfig, ) -> Result { let mut cnx = ConnectionBase::new(ConnectionDir::Client, TransportProtocol::WS); @@ -125,7 +126,7 @@ impl IConnect for ConnectionWebSocket { debug_println!("END of WS loop"); }); - cnx.start().await; + cnx.start(config).await; //spawn_and_log_error(ws_loop(ws, cnx.take_sender(), cnx.take_receiver())); @@ -240,11 +241,11 @@ async fn ws_loop( select! { r = stream.next().fuse() => match r { Some(Ok(msg)) => { - log!("GOT MESSAGE {:?}", msg); + //log!("GOT MESSAGE {:?}", msg); if msg.is_close() { if let Message::Close(Some(cf)) = msg { - log!("CLOSE from server with closeframe: {}",cf.reason); + log!("CLOSE from remote with closeframe: {}",cf.reason); let last_command = match cf.code { CloseCode::Normal => ConnectionCommand::Close, @@ -263,21 +264,20 @@ async fn ws_loop( } else { let _ = futures::SinkExt::send(receiver, ConnectionCommand::Close).await; - log!("CLOSE from server"); + log!("CLOSE from remote"); } return Ok(ProtocolError::Closing); } else { futures::SinkExt::send(receiver,ConnectionCommand::Msg(serde_bare::from_slice::(&msg.into_data())?)).await .map_err(|_e| NetError::IoError)?; } - //return Ok(ProtocolError::Closing); }, Some(Err(e)) => {log!("GOT ERROR {:?}",e);return Err(NetError::WsError);}, None => break }, s = sender.next().fuse() => match s { Some(msg) => { - log!("SENDING MESSAGE {:?}", msg); + //log!("SENDING MESSAGE {:?}", msg); match msg { ConnectionCommand::Msg(m) => { futures::SinkExt::send(&mut stream,Message::binary(serde_bare::to_vec(&m)?)).await.map_err(|_e| NetError::IoError)?; @@ -302,7 +302,6 @@ async fn ws_loop( match inner_loop(&mut ws, sender, &mut receiver).await { Ok(proto_err) => { if proto_err == ProtocolError::Closing { - //FIXME: remove this case log!("ProtocolError::Closing"); let _ = ws.close(None).await; } else if proto_err == ProtocolError::NoError { @@ -327,7 +326,7 @@ async fn ws_loop( return Err(e); } } - log!("END OF LOOP"); + //log!("END OF LOOP"); Ok(()) } @@ -347,8 +346,8 @@ mod test { #[async_std::test] pub async fn test_ws() -> Result<(), NetError> { - let mut random_buf = [0u8; 32]; - getrandom::getrandom(&mut random_buf).unwrap(); + // let mut random_buf = [0u8; 32]; + // getrandom::getrandom(&mut random_buf).unwrap(); let server_key = PubKey::Ed25519PubKey([ 22, 140, 190, 111, 82, 151, 27, 133, 83, 121, 71, 36, 209, 53, 53, 114, 52, 254, 218, @@ -356,11 +355,12 @@ mod test { ]); let keys = p2p_net::utils::gen_keys(); - let pub_key = PubKey::Ed25519PubKey(keys.1); + let (client_priv_key, client_pub_key) = generate_keypair(); + let (user_priv_key, user_pub_key) = generate_keypair(); + log!("start connecting"); - //let (priv_key, pub_key) = generate_keypair(); { let res = BROKER .write() @@ -372,15 +372,22 @@ mod test { keys.0, pub_key.clone(), server_key, + StartConfig::Client(ClientConfig { + user: user_pub_key, + client: client_pub_key, + client_priv: client_priv_key, + }), ) .await; log!("broker.connect : {:?}", res); res.expect("assume the connection succeeds"); } + BROKER.read().await.print_status(); + async fn timer_close(remote_peer_id: DirectPeerId) -> ResultSend<()> { async move { - sleep!(std::time::Duration::from_secs(10)); + sleep!(std::time::Duration::from_secs(3)); log!("timeout"); BROKER .write() @@ -391,11 +398,11 @@ mod test { .await; Ok(()) } - spawn_and_log_error(timer_close(pub_key)); + spawn_and_log_error(timer_close(server_key)); //Broker::graceful_shutdown().await; - Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(12)).await; + Broker::join_shutdown_with_timeout(std::time::Duration::from_secs(5)).await; Ok(()) } } diff --git a/p2p-client-ws/src/remote_ws_wasm.rs b/p2p-client-ws/src/remote_ws_wasm.rs index 41b0ad5..3b4c0be 100644 --- a/p2p-client-ws/src/remote_ws_wasm.rs +++ b/p2p-client-ws/src/remote_ws_wasm.rs @@ -18,7 +18,7 @@ use p2p_net::errors::*; use p2p_net::log; use p2p_net::types::*; use p2p_net::utils::*; -use p2p_net::{connection::*, WS_PORT}; +use p2p_net::WS_PORT; use p2p_repo::types::*; use p2p_repo::utils::{generate_keypair, now_timestamp}; use std::sync::Arc; @@ -40,6 +40,7 @@ impl IConnect for ConnectionWebSocket { peer_privk: Sensitive<[u8; 32]>, peer_pubk: PubKey, remote_peer: DirectPeerId, + config: StartConfig, ) -> Result { //pub async fn testt(url: &str) -> ResultSend<()> { let mut cnx = ConnectionBase::new(ConnectionDir::Client, TransportProtocol::WS); @@ -65,12 +66,10 @@ impl IConnect for ConnectionWebSocket { shutdown, )); - cnx.start().await; + cnx.start(config).await; //spawn_and_log_error(read_loop(receiver_rx, sender_tx.clone())); - log!("sending..."); - //cnx.close().await; // spawn_and_log_error(async move { // TimeoutFuture::new(10_000).await; @@ -113,11 +112,10 @@ async fn ws_loop( ) -> Result { //let mut rx_sender = sender.fuse(); loop { - log!("BEFORE SELECT"); select! { r = stream.next().fuse() => match r { Some(msg) => { - log!("GOT MESSAGE {:?}", msg); + //log!("GOT MESSAGE {:?}", msg); if let WsMessage::Binary(b) = msg { receiver.send(ConnectionCommand::Msg(serde_bare::from_slice::(&b)?)).await .map_err(|_e| NetError::IoError)?; @@ -130,7 +128,7 @@ async fn ws_loop( }, s = sender.next().fuse() => match s { Some(msg) => { - log!("SENDING MESSAGE {:?}", msg); + //log!("SENDING MESSAGE {:?}", msg); match msg { ConnectionCommand::Msg(m) => { @@ -152,16 +150,14 @@ async fn ws_loop( }, } } - log!("END SELECT"); Ok(ProtocolError::NoError) } - + log!("START of WS loop"); let mut events = ws .observe(ObserveConfig::default()) //.observe(Filter::Pointer(WsEvent::is_closed).into()) .await .expect_throw("observe"); - log!("OBSERVED"); match inner_loop(&mut stream, sender, receiver.clone()).await { Ok(proto_err) => { if proto_err == ProtocolError::NoError { @@ -220,5 +216,6 @@ async fn ws_loop( .await .map_err(|_e| NetError::IoError)?; + log!("END of WS loop"); Ok(()) } diff --git a/p2p-net/src/broker.rs b/p2p-net/src/broker.rs index 500c272..8dd080f 100644 --- a/p2p-net/src/broker.rs +++ b/p2p-net/src/broker.rs @@ -218,6 +218,7 @@ impl Broker { peer_privk: Sensitive<[u8; 32]>, peer_pubk: PubKey, remote_peer_id: DirectPeerId, + config: StartConfig, ) -> Result<(), NetError> { if self.closing { return Err(NetError::Closing); @@ -235,6 +236,7 @@ impl Broker { Sensitive::<[u8; 32]>::from_slice(peer_privk.deref()), peer_pubk, remote_peer_id, + config, ) .await?; diff --git a/p2p-net/src/connection.rs b/p2p-net/src/connection.rs index 20a25fd..1e39981 100644 --- a/p2p-net/src/connection.rs +++ b/p2p-net/src/connection.rs @@ -20,6 +20,7 @@ use noise_protocol::{patterns::noise_xk, CipherState, HandshakeState}; use noise_rust_crypto::sensitive::Sensitive; use noise_rust_crypto::*; use p2p_repo::types::{PrivKey, PubKey}; +use p2p_repo::utils::{sign, verify}; use serde_bare::from_slice; use unique_id::sequence::SequenceGenerator; use unique_id::Generator; @@ -42,6 +43,7 @@ pub trait IConnect: Send + Sync { peer_privk: Sensitive<[u8; 32]>, peer_pubk: PubKey, remote_peer: DirectPeerId, + config: StartConfig, ) -> Result; } @@ -97,6 +99,9 @@ pub struct NoiseFSM { from: Option>, to: Option, + + nonce_for_hello: Vec, + config: Option, } impl fmt::Debug for NoiseFSM { @@ -114,6 +119,25 @@ pub enum StepReply { NONE, } +pub struct ClientConfig { + pub user: PubKey, + pub client: PubKey, + pub client_priv: PrivKey, +} + +pub struct ExtConfig {} + +pub struct CoreConfig {} + +pub struct AdminConfig {} + +pub enum StartConfig { + Client(ClientConfig), + Ext(ExtConfig), + Core(CoreConfig), + Admin(AdminConfig), +} + impl NoiseFSM { pub fn new( tp: TransportProtocol, @@ -137,6 +161,8 @@ impl NoiseFSM { noise_cipher_state_dec: None, from: Some(from), to, + nonce_for_hello: vec![], + config: None, } } @@ -168,14 +194,20 @@ impl NoiseFSM { } pub async fn send(&mut self, msg: ProtocolMessage) -> Result<(), ProtocolError> { - if self.state == FSMstate::AuthResult && self.noise_cipher_state_enc.is_some() { + log!("SENDING: {:?}", msg); + if self.noise_cipher_state_enc.is_some() { let cipher = self.encrypt(msg)?; self.sender .send(ConnectionCommand::Msg(ProtocolMessage::Noise(cipher))) - .await; + .await + .map_err(|e| ProtocolError::IoError)?; return Ok(()); } else { - return Err(ProtocolError::InvalidState); + self.sender + .send(ConnectionCommand::Msg(msg)) + .await + .map_err(|e| ProtocolError::IoError)?; + return Ok(()); } } @@ -207,6 +239,9 @@ impl NoiseFSM { return Err(ProtocolError::MustBeEncrypted); } } + if msg_opt.is_some() { + log!("RECEIVED: {:?}", msg_opt.as_ref().unwrap()); + } match self.state { // TODO verify that ID is zero FSMstate::Local0 => { @@ -243,7 +278,7 @@ impl NoiseFSM { .map_err(|e| ProtocolError::NoiseHandshakeFailed)?; let noise = Noise::V0(NoiseV0 { data: payload }); - self.sender.send(ConnectionCommand::Msg(noise.into())).await; + self.send(noise.into()).await?; self.noise_handshake_state = Some(handshake); @@ -278,7 +313,7 @@ impl NoiseFSM { })?; let noise = Noise::V0(NoiseV0 { data: payload }); - self.sender.send(ConnectionCommand::Msg(noise.into())).await; + self.send(noise.into()).await?; self.noise_handshake_state = Some(handshake); @@ -309,19 +344,31 @@ impl NoiseFSM { return Err(ProtocolError::NoiseHandshakeFailed); } - let noise3 = ClientHello::Noise3(Noise::V0(NoiseV0 { data: payload })); - self.sender - .send(ConnectionCommand::Msg(noise3.into())) - .await; - let ciphers = handshake.get_ciphers(); + + match self.config.as_ref().unwrap() { + StartConfig::Client(client_config) => { + let noise3 = + ClientHello::Noise3(Noise::V0(NoiseV0 { data: payload })); + self.send(noise3.into()).await?; + self.state = FSMstate::ClientHello; + } + StartConfig::Ext(ext_config) => { + todo!(); + } + StartConfig::Core(core_config) => { + todo!(); + } + StartConfig::Admin(admin_config) => { + todo!(); + } + } + self.noise_cipher_state_enc = Some(ciphers.0); self.noise_cipher_state_dec = Some(ciphers.1); self.noise_handshake_state = None; - self.state = FSMstate::ClientHello; - return Ok(StepReply::NONE); } } @@ -356,14 +403,14 @@ impl NoiseFSM { let mut nonce_buf = [0u8; 32]; getrandom::getrandom(&mut nonce_buf).unwrap(); + self.nonce_for_hello = nonce_buf.to_vec(); + let server_hello = ServerHello::V0(ServerHelloV0 { - nonce: nonce_buf.to_vec(), + nonce: self.nonce_for_hello.clone(), }); - self.sender - .send(ConnectionCommand::Msg(server_hello.into())) - .await; self.state = FSMstate::ServerHello; + self.send(server_hello.into()).await?; return Ok(StepReply::NONE); } @@ -373,9 +420,92 @@ impl NoiseFSM { FSMstate::Noise3 => {} FSMstate::ExtRequest => {} FSMstate::ExtResponse => {} - FSMstate::ClientHello => {} - FSMstate::ServerHello => {} - FSMstate::ClientAuth => {} + FSMstate::ClientHello => { + if let Some(msg) = msg_opt.as_ref() { + if !self.dir.is_server() { + if let ProtocolMessage::ServerHello(hello) = msg { + if let StartConfig::Client(client_config) = + self.config.as_ref().unwrap() + { + let content = ClientAuthContentV0 { + user: client_config.user, + client: client_config.client, + /// Nonce from ServerHello + nonce: hello.nonce().clone(), + }; + let ser = serde_bare::to_vec(&content)?; + let sig = + sign(client_config.client_priv, client_config.client, &ser)?; + let client_auth = ClientAuth::V0(ClientAuthV0 { + content, + /// Signature by client key + sig, + }); + + self.state = FSMstate::ClientAuth; + self.send(client_auth.into()).await?; + + return Ok(StepReply::NONE); + } + } + } + } + } + FSMstate::ServerHello => { + if let Some(msg) = msg_opt.as_ref() { + if self.dir.is_server() { + if let ProtocolMessage::ClientAuth(client_auth) = msg { + if *client_auth.nonce() != self.nonce_for_hello { + return Err(ProtocolError::InvalidNonce); + } + + let ser = serde_bare::to_vec(&client_auth.content_v0())?; + + let mut result = ProtocolError::NoError; + let verif = verify(&ser, client_auth.sig(), client_auth.client()); + if verif.is_err() { + result = verif.unwrap_err().into(); + } else { + + // TODO check that the device has been registered for this user. if not, set result = AccessDenied + } + let auth_result = AuthResult::V0(AuthResultV0 { + result: result.clone() as u16, + metadata: vec![], + }); + self.send(auth_result.into()).await?; + + if (result.is_err()) { + return Err(result); + } + log!("AUTHENTICATION SUCCESSFUL ! waiting for requests on the server side"); + self.state = FSMstate::AuthResult; + return Ok(StepReply::NONE); + } + } + } + } + FSMstate::ClientAuth => { + if let Some(msg) = msg_opt.as_ref() { + if !self.dir.is_server() { + if let ProtocolMessage::AuthResult(auth_res) = msg { + if let StartConfig::Client(client_config) = + self.config.as_ref().unwrap() + { + if auth_res.result() != 0 { + return Err(ProtocolError::AccessDenied); + } + + self.state = FSMstate::AuthResult; + + log!("AUTHENTICATION SUCCESSFUL ! waiting for requests on the client side"); + + return Ok(StepReply::NONE); + } + } + } + } + } FSMstate::AuthResult => { if let Some(msg) = msg_opt { let id = msg.id(); @@ -467,12 +597,11 @@ impl ConnectionBase { fsm: Arc>, ) -> ResultSend<()> { while let Some(msg) = receiver.next().await { - log!("RECEIVED: {:?}", msg); match msg { ConnectionCommand::Close | ConnectionCommand::Error(_) | ConnectionCommand::ProtocolError(_) => { - log!("EXIT READ LOOP"); + log!("EXIT READ LOOP because : {:?}", msg); break; } ConnectionCommand::Msg(proto_msg) => { @@ -537,6 +666,7 @@ impl ConnectionBase { } } } + log!("END OF READ LOOP"); Ok(()) } @@ -584,15 +714,20 @@ impl ConnectionBase { self.send(ConnectionCommand::Close).await; } - pub async fn start(&mut self) { - // BOOTSTRAP the protocol + pub async fn start(&mut self, config: StartConfig) { + // BOOTSTRAP the protocol from client-side if !self.dir.is_server() { let res; - let fsm = self.fsm.as_ref().unwrap(); - res = fsm.lock().await.step(None).await; + { + let mut fsm = self.fsm.as_ref().unwrap().lock().await; + fsm.config = Some(config); + res = fsm.step(None).await; + } if let Err(err) = res { self.send(ConnectionCommand::ProtocolError(err)).await; } + } else { + panic!("cannot call start on a server-side connection"); } } diff --git a/p2p-net/src/errors.rs b/p2p-net/src/errors.rs index edebbb3..49bc714 100644 --- a/p2p-net/src/errors.rs +++ b/p2p-net/src/errors.rs @@ -47,7 +47,7 @@ pub enum ProtocolError { PartialContent, EndOfStream, - WriteError, + IoError, WsError, ActorError, InvalidState, @@ -77,12 +77,17 @@ pub enum ProtocolError { NoiseHandshakeFailed, DecryptionError, EncryptionError, + + InvalidNonce, } //MAX 949 ProtocolErrors impl ProtocolError { pub fn is_stream(&self) -> bool { *self == ProtocolError::PartialContent || *self == ProtocolError::EndOfStream } + pub fn is_err(&self) -> bool { + *self != ProtocolError::NoError + } } impl Error for ProtocolError {} diff --git a/p2p-net/src/types.rs b/p2p-net/src/types.rs index 30fab32..e825343 100644 --- a/p2p-net/src/types.rs +++ b/p2p-net/src/types.rs @@ -1822,6 +1822,12 @@ impl ClientAuth { } } +impl From for ProtocolMessage { + fn from(msg: ClientAuth) -> ProtocolMessage { + ProtocolMessage::ClientAuth(msg) + } +} + /// Authentication result #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AuthResultV0 { @@ -1849,6 +1855,12 @@ impl AuthResult { } } +impl From for ProtocolMessage { + fn from(msg: AuthResult) -> ProtocolMessage { + ProtocolMessage::AuthResult(msg) + } +} + // // DIRECT / OUT-OF-BAND MESSAGES //