refactor(server): removed grpc adapter and replaced with concrete implementations

This commit is contained in:
hdbg
2026-03-15 23:11:07 +01:00
parent 4db102b3d1
commit 549a0f5f52
29 changed files with 1002 additions and 1620 deletions

View File

@@ -1,13 +1,4 @@
use arbiter_proto::{
format_challenge,
proto::client::{
AuthChallenge, AuthChallengeSolution, ClientConnectError, ClientRequest, ClientResponse,
client_connect_error::Code as ConnectErrorCode,
client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload,
},
transport::expect_message,
};
use arbiter_proto::{format_challenge, transport::expect_message};
use diesel::{
ExpressionMethods as _, OptionalExtension as _, QueryDsl as _, dsl::insert_into, update,
};
@@ -18,7 +9,7 @@ use tracing::error;
use crate::{
actors::{
client::ClientConnection,
client::{ClientConnection, ConnectErrorCode, Request, Response},
router::{self, RequestClientApproval},
},
db::{self, schema::program_client},
@@ -155,15 +146,13 @@ async fn challenge_client(
pubkey: VerifyingKey,
nonce: i32,
) -> Result<(), Error> {
let challenge = AuthChallenge {
pubkey: pubkey.as_bytes().to_vec(),
nonce,
};
let challenge_pubkey = pubkey.as_bytes().to_vec();
props
.transport
.send(Ok(ClientResponse {
payload: Some(ClientResponsePayload::AuthChallenge(challenge.clone())),
.send(Ok(Response::AuthChallenge {
pubkey: challenge_pubkey.clone(),
nonce,
}))
.await
.map_err(|e| {
@@ -171,20 +160,17 @@ async fn challenge_client(
Error::Transport
})?;
let AuthChallengeSolution { signature } =
expect_message(&mut *props.transport, |req: ClientRequest| {
match req.payload? {
ClientRequestPayload::AuthChallengeSolution(s) => Some(s),
_ => None,
}
})
.await
.map_err(|e| {
error!(error = ?e, "Failed to receive challenge solution");
Error::Transport
})?;
let signature = expect_message(&mut *props.transport, |req: Request| match req {
Request::AuthChallengeSolution { signature } => Some(signature),
_ => None,
})
.await
.map_err(|e| {
error!(error = ?e, "Failed to receive challenge solution");
Error::Transport
})?;
let formatted = format_challenge(nonce, &challenge.pubkey);
let formatted = format_challenge(nonce, &challenge_pubkey);
let sig = signature.as_slice().try_into().map_err(|_| {
error!("Invalid signature length");
Error::InvalidChallengeSolution
@@ -209,15 +195,14 @@ fn connect_error_code(err: &Error) -> ConnectErrorCode {
}
async fn authenticate(props: &mut ClientConnection) -> Result<VerifyingKey, Error> {
let Some(ClientRequest {
payload: Some(ClientRequestPayload::AuthChallengeRequest(challenge)),
let Some(Request::AuthChallengeRequest {
pubkey: challenge_pubkey,
}) = props.transport.recv().await
else {
return Err(Error::Transport);
};
let pubkey_bytes = challenge
.pubkey
let pubkey_bytes = challenge_pubkey
.as_array()
.ok_or(Error::InvalidClientPubkeyLength)?;
let pubkey =
@@ -244,11 +229,7 @@ pub async fn authenticate_and_create(mut props: ClientConnection) -> Result<Clie
let code = connect_error_code(&err);
let _ = props
.transport
.send(Ok(ClientResponse {
payload: Some(ClientResponsePayload::ClientConnectError(
ClientConnectError { code: code.into() },
)),
}))
.send(Ok(Response::ClientConnectError { code }))
.await;
Err(err)
}

View File

@@ -1,7 +1,4 @@
use arbiter_proto::{
proto::client::{ClientRequest, ClientResponse},
transport::Bi,
};
use arbiter_proto::transport::Bi;
use kameo::actor::Spawn;
use tracing::{error, info};
@@ -24,7 +21,27 @@ pub enum ClientError {
Auth(#[from] auth::Error),
}
pub type Transport = Box<dyn Bi<ClientRequest, Result<ClientResponse, ClientError>> + Send>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectErrorCode {
Unknown,
ApprovalDenied,
NoUserAgentsOnline,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Request {
AuthChallengeRequest { pubkey: Vec<u8> },
AuthChallengeSolution { signature: Vec<u8> },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Response {
AuthChallenge { pubkey: Vec<u8>, nonce: i32 },
AuthOk,
ClientConnectError { code: ConnectErrorCode },
}
pub type Transport = Box<dyn Bi<Request, Result<Response, ClientError>> + Send>;
pub struct ClientConnection {
pub(crate) db: db::DatabasePool,

View File

@@ -1,11 +1,15 @@
use arbiter_proto::proto::client::{ClientRequest, ClientResponse};
use kameo::Actor;
use tokio::select;
use tracing::{error, info};
use crate::{actors::{
GlobalActors, client::{ClientError, ClientConnection}, router::RegisterClient
}, db};
use crate::{
actors::{
GlobalActors,
client::{ClientConnection, ClientError, Request, Response},
router::RegisterClient,
},
db,
};
pub struct ClientSession {
props: ClientConnection,
@@ -16,18 +20,13 @@ impl ClientSession {
Self { props }
}
pub async fn process_transport_inbound(&mut self, req: ClientRequest) -> Output {
let msg = req.payload.ok_or_else(|| {
error!(actor = "client", "Received message with no payload");
ClientError::MissingRequestPayload
})?;
let _ = msg;
pub async fn process_transport_inbound(&mut self, req: Request) -> Output {
let _ = req;
Err(ClientError::UnexpectedRequestPayload)
}
}
type Output = Result<ClientResponse, ClientError>;
type Output = Result<Response, ClientError>;
impl Actor for ClientSession {
type Args = Self;