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