feat(server): broker agent for inter-actor coordination
This commit is contained in:
@@ -6,7 +6,7 @@ use ed25519_dalek::VerifyingKey;
|
||||
use tracing::error;
|
||||
|
||||
use crate::actors::client::{
|
||||
ConnectionProps,
|
||||
ClientConnection,
|
||||
auth::state::{AuthContext, AuthStateMachine},
|
||||
session::ClientSession,
|
||||
};
|
||||
@@ -54,7 +54,7 @@ fn parse_auth_event(payload: ClientRequestPayload) -> Result<AuthEvents, Error>
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn authenticate(props: &mut ConnectionProps) -> Result<VerifyingKey, Error> {
|
||||
pub async fn authenticate(props: &mut ClientConnection) -> Result<VerifyingKey, Error> {
|
||||
let mut state = AuthStateMachine::new(AuthContext::new(props));
|
||||
|
||||
loop {
|
||||
@@ -93,7 +93,7 @@ pub async fn authenticate(props: &mut ConnectionProps) -> Result<VerifyingKey, E
|
||||
}
|
||||
|
||||
pub async fn authenticate_and_create(
|
||||
mut props: ConnectionProps,
|
||||
mut props: ClientConnection,
|
||||
) -> Result<ClientSession, Error> {
|
||||
let key = authenticate(&mut props).await?;
|
||||
let session = ClientSession::new(props, key);
|
||||
|
||||
@@ -8,7 +8,7 @@ use ed25519_dalek::VerifyingKey;
|
||||
use tracing::error;
|
||||
|
||||
use super::Error;
|
||||
use crate::{actors::client::ConnectionProps, db::schema};
|
||||
use crate::{actors::client::ClientConnection, db::schema};
|
||||
|
||||
pub struct ChallengeRequest {
|
||||
pub pubkey: VerifyingKey,
|
||||
@@ -68,11 +68,11 @@ async fn create_nonce(db: &crate::db::DatabasePool, pubkey_bytes: &[u8]) -> Resu
|
||||
}
|
||||
|
||||
pub struct AuthContext<'a> {
|
||||
pub(super) conn: &'a mut ConnectionProps,
|
||||
pub(super) conn: &'a mut ClientConnection,
|
||||
}
|
||||
|
||||
impl<'a> AuthContext<'a> {
|
||||
pub fn new(conn: &'a mut ConnectionProps) -> Self {
|
||||
pub fn new(conn: &'a mut ClientConnection) -> Self {
|
||||
Self { conn }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ use arbiter_proto::{
|
||||
use kameo::actor::Spawn;
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{actors::client::session::ClientSession, db};
|
||||
use crate::{
|
||||
actors::{GlobalActors, client::session::ClientSession},
|
||||
db,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
|
||||
pub enum ClientError {
|
||||
@@ -15,27 +18,34 @@ pub enum ClientError {
|
||||
UnexpectedRequestPayload,
|
||||
#[error("State machine error")]
|
||||
StateTransitionFailed,
|
||||
#[error("Connection registration failed")]
|
||||
ConnectionRegistrationFailed,
|
||||
#[error(transparent)]
|
||||
Auth(#[from] auth::Error),
|
||||
}
|
||||
|
||||
pub type Transport = Box<dyn Bi<ClientRequest, Result<ClientResponse, ClientError>> + Send>;
|
||||
|
||||
pub struct ConnectionProps {
|
||||
pub struct ClientConnection {
|
||||
pub(crate) db: db::DatabasePool,
|
||||
pub(crate) transport: Transport,
|
||||
pub(crate) actors: GlobalActors,
|
||||
}
|
||||
|
||||
impl ConnectionProps {
|
||||
pub fn new(db: db::DatabasePool, transport: Transport) -> Self {
|
||||
Self { db, transport }
|
||||
impl ClientConnection {
|
||||
pub fn new(db: db::DatabasePool, transport: Transport, actors: GlobalActors) -> Self {
|
||||
Self {
|
||||
db,
|
||||
transport,
|
||||
actors,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod auth;
|
||||
pub mod session;
|
||||
|
||||
pub async fn connect_client(props: ConnectionProps) {
|
||||
pub async fn connect_client(props: ClientConnection) {
|
||||
match auth::authenticate_and_create(props).await {
|
||||
Ok(session) => {
|
||||
ClientSession::spawn(session);
|
||||
|
||||
@@ -4,15 +4,17 @@ use kameo::Actor;
|
||||
use tokio::select;
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::actors::client::{ClientError, ConnectionProps};
|
||||
use crate::{actors::{
|
||||
GlobalActors, client::{ClientError, ClientConnection}, router::RegisterClient
|
||||
}, db};
|
||||
|
||||
pub struct ClientSession {
|
||||
props: ConnectionProps,
|
||||
props: ClientConnection,
|
||||
key: VerifyingKey,
|
||||
}
|
||||
|
||||
impl ClientSession {
|
||||
pub(crate) fn new(props: ConnectionProps, key: VerifyingKey) -> Self {
|
||||
pub(crate) fn new(props: ClientConnection, key: VerifyingKey) -> Self {
|
||||
Self { props, key }
|
||||
}
|
||||
|
||||
@@ -33,12 +35,18 @@ type Output = Result<ClientResponse, ClientError>;
|
||||
impl Actor for ClientSession {
|
||||
type Args = Self;
|
||||
|
||||
type Error = ();
|
||||
type Error = ClientError;
|
||||
|
||||
async fn on_start(
|
||||
args: Self::Args,
|
||||
_: kameo::prelude::ActorRef<Self>,
|
||||
this: kameo::prelude::ActorRef<Self>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
args.props
|
||||
.actors
|
||||
.router
|
||||
.ask(RegisterClient { actor: this })
|
||||
.await
|
||||
.map_err(|_| ClientError::ConnectionRegistrationFailed)?;
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
@@ -80,10 +88,10 @@ impl Actor for ClientSession {
|
||||
}
|
||||
|
||||
impl ClientSession {
|
||||
pub fn new_test(db: crate::db::DatabasePool) -> Self {
|
||||
pub fn new_test(db: db::DatabasePool, actors: GlobalActors) -> Self {
|
||||
use arbiter_proto::transport::DummyTransport;
|
||||
let transport: super::Transport = Box::new(DummyTransport::new());
|
||||
let props = ConnectionProps::new(db, transport);
|
||||
let props = ClientConnection::new(db, transport, actors);
|
||||
let key = VerifyingKey::from_bytes(&[0u8; 32]).unwrap();
|
||||
Self { props, key }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user