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 #[inline]
20 pub async fn connect<A>(&self, addr: A) -> io::Result<impl Reliable + '_>
21 where
22 A: Into<Address>,
23 {
24 use tokio::io::AsyncWriteExt;
25
26 let mut stream = self.transport.open_bidirectional().await?;
27
28 let request = Connect::with(self.secret, addr).to_bytes()?;
29 stream.write_all(&request).await?;
30
31 Ok(stream)
32 }
33
34 #[cfg(feature = "datagram")]
35 #[inline]
36 pub async fn associate(&self) -> io::Result<Datagram<impl Unreliable + '_>> {
37 let stream = self.transport.open_datagram().await?;
38
39 Ok(Datagram::with(self.secret, stream))
40 }
41}
42
43#[cfg(feature = "datagram")]
44pub struct Datagram<U: Unreliable>(Secret, U);
45
46#[cfg(feature = "datagram")]
47impl<U: Unreliable> Datagram<U> {
48 fn with(secret: Secret, stream: U) -> Self {
49 Self(secret, stream)
50 }
51
52 #[inline]
53 pub async fn send<A, B>(&self, data: B, addr: A) -> io::Result<()>
54 where
55 A: Into<Address>,
56 B: Into<bytes::Bytes>,
57 {
58 let packet = Associate::with(self.0, addr, data).to_bytes()?;
59
60 self.1.send(packet).await
61 }
62
63 #[inline]
64 pub async fn recv(&self) -> io::Result<(bytes::Bytes, Address)> {
65 match self.1.recv().await {
66 Ok(mut data) => {
67 let packet = Associate::from_bytes(&mut data)?;
68 Ok((packet.data, packet.address))
69 }
70 Err(error) => Err(error),
71 }
72 }
73}