Skip to main content

ap_client/
proxy.rs

1//! Proxy client trait and default implementation
2//!
3//! This module provides the `ProxyClient` trait for abstracting proxy communication,
4//! enabling dependency injection and easier testing.
5
6use ap_proxy_client::IncomingMessage;
7#[cfg(feature = "native-websocket")]
8use ap_proxy_client::ProxyProtocolClient;
9use ap_proxy_protocol::{IdentityFingerprint, IdentityKeyPair, RendezvousCode};
10use async_trait::async_trait;
11use tokio::sync::mpsc;
12
13use crate::error::ClientError;
14
15/// Trait abstracting the proxy client for communication between devices
16#[async_trait]
17pub trait ProxyClient: Send + Sync {
18    /// Connect to the proxy server, returning a receiver for incoming messages
19    async fn connect(
20        &mut self,
21        identity: IdentityKeyPair,
22    ) -> Result<mpsc::UnboundedReceiver<IncomingMessage>, ClientError>;
23
24    /// Request a rendezvous code from the proxy server
25    async fn request_rendezvous(&self) -> Result<(), ClientError>;
26
27    /// Request the identity associated with a rendezvous code
28    async fn request_identity(&self, code: RendezvousCode) -> Result<(), ClientError>;
29
30    /// Send a message to a peer by their fingerprint
31    async fn send_to(
32        &self,
33        fingerprint: IdentityFingerprint,
34        data: Vec<u8>,
35    ) -> Result<(), ClientError>;
36
37    /// Disconnect from the proxy server
38    async fn disconnect(&mut self) -> Result<(), ClientError>;
39}
40
41/// Default implementation using ProxyProtocolClient from ap-proxy
42#[cfg(feature = "native-websocket")]
43pub struct DefaultProxyClient {
44    inner: ProxyProtocolClient,
45}
46
47#[cfg(feature = "native-websocket")]
48impl DefaultProxyClient {
49    pub fn from_url(proxy_url: String) -> Self {
50        Self {
51            inner: ProxyProtocolClient::from_url(proxy_url),
52        }
53    }
54}
55
56#[cfg(feature = "native-websocket")]
57#[async_trait]
58impl ProxyClient for DefaultProxyClient {
59    async fn connect(
60        &mut self,
61        identity: IdentityKeyPair,
62    ) -> Result<mpsc::UnboundedReceiver<IncomingMessage>, ClientError> {
63        self.inner
64            .connect(identity)
65            .await
66            .map_err(ClientError::from)
67    }
68
69    async fn request_rendezvous(&self) -> Result<(), ClientError> {
70        self.inner
71            .request_rendezvous()
72            .await
73            .map_err(ClientError::from)
74    }
75
76    async fn request_identity(&self, code: RendezvousCode) -> Result<(), ClientError> {
77        self.inner
78            .request_identity(code)
79            .await
80            .map_err(ClientError::from)
81    }
82
83    async fn send_to(
84        &self,
85        fingerprint: IdentityFingerprint,
86        data: Vec<u8>,
87    ) -> Result<(), ClientError> {
88        self.inner
89            .send_to(fingerprint, data)
90            .await
91            .map_err(ClientError::from)
92    }
93
94    async fn disconnect(&mut self) -> Result<(), ClientError> {
95        self.inner.disconnect().await.map_err(ClientError::from)
96    }
97}