ombrac_client/
client.rs

1use std::io;
2
3use ombrac::prelude::*;
4use ombrac_transport::{Initiator, Reliable};
5
6#[cfg(feature = "datagram")]
7use ombrac_transport::Unreliable;
8
9pub struct Client<T> {
10    secret: Secret,
11    transport: T,
12}
13
14impl<T: Initiator> Client<T> {
15    pub fn new(secret: Secret, transport: T) -> Self {
16        Self { secret, transport }
17    }
18
19    pub async fn tcp_connect<A>(&self, addr: A) -> io::Result<impl Reliable + '_>
20    where
21        A: Into<Address>,
22    {
23        use tokio::io::AsyncWriteExt;
24
25        let mut stream = self.transport.open_bidirectional().await?;
26        let request = Connect::with(self.secret, addr).to_bytes()?;
27
28        stream.write_all(&request).await?;
29
30        Ok(stream)
31    }
32
33    #[cfg(feature = "datagram")]
34    pub async fn udp_associate(&self) -> io::Result<Datagram<impl Unreliable + '_>> {
35        let stream = self.transport.open_datagram().await?;
36
37        Ok(Datagram::with(self.secret, stream))
38    }
39}
40
41#[cfg(feature = "datagram")]
42pub struct Datagram<U: Unreliable>(Secret, U);
43
44#[cfg(feature = "datagram")]
45impl<U: Unreliable> Datagram<U> {
46    fn with(secret: Secret, stream: U) -> Self {
47        Self(secret, stream)
48    }
49
50    pub async fn send<A, B>(&self, addr: A, data: B) -> io::Result<()>
51    where
52        A: Into<Address>,
53        B: Into<bytes::Bytes>,
54    {
55        let packet = Packet::with(self.0, addr, data).to_bytes()?;
56
57        if let Err(error) = self.1.send(packet).await {
58            return Err(io::Error::other(error.to_string()));
59        };
60
61        Ok(())
62    }
63
64    pub async fn recv(&self) -> io::Result<(Address, bytes::Bytes)> {
65        match self.1.recv().await {
66            Ok(mut data) => {
67                let packet = Packet::from_bytes(&mut data)?;
68                Ok((packet.address, packet.data))
69            }
70            Err(error) => Err(io::Error::other(error.to_string())),
71        }
72    }
73}