1use std::{
2 collections::VecDeque,
3 io,
4 pin::Pin,
5 task::{Context, Poll, Waker},
6};
7
8use futures::{
9 AsyncRead, AsyncWrite, FutureExt, SinkExt, StreamExt,
10 channel::{mpsc, oneshot},
11 future::{self, BoxFuture},
12 ready,
13};
14use volans_codec::Bytes;
15use volans_core::{
16 Listener, ListenerEvent, Multiaddr, PeerId, Transport, TransportError, multiaddr::Protocol,
17};
18use volans_swarm::Substream;
19
20use crate::{
21 MultiaddrExt,
22 protocol::{Circuit, ConnectError},
23};
24
25pub struct Config {
26 behavior_sender: mpsc::Sender<TransportRequest>,
27}
28
29impl Config {
30 pub fn new() -> (Self, mpsc::Receiver<TransportRequest>) {
31 let (behavior_sender, behavior_receiver) = mpsc::channel(1000);
32 (Self { behavior_sender }, behavior_receiver)
33 }
34}
35
36impl Transport for Config {
45 type Output = Connection;
46 type Error = Error;
47 type Dial = future::BoxFuture<'static, Result<Self::Output, Self::Error>>;
48 type Incoming = future::Ready<Result<Self::Output, Self::Error>>;
49 type Listener = ListenerBackend;
50
51 fn dial(&self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
52 let RelayedMultiaddr {
55 relay_peer_id,
56 relay_addr,
57 dst_peer_id,
58 } = parse_relayed_multiaddr(addr)?;
59 let relay_peer_id = relay_peer_id.ok_or(Error::MissingRelayPeerId)?;
60 let dst_peer_id = dst_peer_id.ok_or(Error::MissingDstPeerId)?;
61 let relay_addr = relay_addr.ok_or(Error::InvalidMultiaddr)?;
62
63 let mut behavior_sender = self.behavior_sender.clone();
64
65 Ok(async move {
66 let (tx, rx) = oneshot::channel();
67 let request = TransportRequest::DialRequest {
68 relay_addr,
69 relay_peer_id,
70 dst_peer_id,
71 send_back: tx,
72 };
73 behavior_sender.send(request).await?;
74 let stream = rx.await??;
75 tracing::info!("Dialed relay peer: {}", dst_peer_id);
76 Ok(stream)
77 }
78 .boxed())
79 }
80 fn listen(&self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
81 if !addr.is_circuit() {
82 return Err(TransportError::NotSupported(addr));
83 }
84
85 let (listener_sender, incoming_stream) = mpsc::channel(100);
86
87 let listen_request = TransportRequest::ListenRequest {
88 local_addr: addr.clone(),
89 listener_sender,
90 };
91 tracing::trace!("new circuit listener addr: {}", addr);
92
93 let listener = ListenerBackend {
94 local_addr: addr,
95 pending_request: Some(listen_request),
96 behavior_sender: self.behavior_sender.clone(),
97 incoming_stream,
98 closed: false,
99 waker: None,
100 pending_events: VecDeque::new(),
101 };
102 Ok(listener)
103 }
104}
105
106pub struct ListenerBackend {
107 local_addr: Multiaddr,
108 pending_request: Option<TransportRequest>,
109 behavior_sender: mpsc::Sender<TransportRequest>,
110 incoming_stream: mpsc::Receiver<IncomingRelayedConnection>,
111 closed: bool,
112 waker: Option<Waker>,
113 pending_events: VecDeque<ListenerEvent<<Self as Listener>::Upgrade, <Self as Listener>::Error>>,
114}
115
116impl Listener for ListenerBackend {
117 type Output = Connection;
118 type Error = Error;
119 type Upgrade = future::Ready<Result<Self::Output, Self::Error>>;
120
121 fn poll_event(
122 mut self: Pin<&mut Self>,
123 cx: &mut Context<'_>,
124 ) -> Poll<ListenerEvent<Self::Upgrade, Self::Error>> {
125 loop {
126 if let Some(event) = self.pending_events.pop_front() {
127 return Poll::Ready(event);
128 }
129 if self.closed {
130 self.waker = None;
131 return Poll::Ready(ListenerEvent::Closed(Ok(())));
132 }
133
134 if self.pending_request.is_some() {
135 if self.behavior_sender.poll_ready(cx).is_ready() {
136 if let Some(request) = self.pending_request.take() {
137 let _ = self.behavior_sender.start_send(request);
138 let addr = self.local_addr.clone();
139 self.pending_events
140 .push_back(ListenerEvent::NewAddress(addr));
141 continue;
142 }
143 }
144 }
145
146 match self.incoming_stream.poll_next_unpin(cx) {
147 Poll::Ready(Some(IncomingRelayedConnection {
148 stream,
149 src_peer_id,
150 _relay_peer_id: _,
151 relay_addr,
152 })) => {
153 tracing::info!("Received incoming relayed connection from: {}", src_peer_id);
154 self.pending_events.push_back(ListenerEvent::Incoming {
155 local_addr: relay_addr.with(Protocol::Circuit),
156 remote_addr: Protocol::Peer(src_peer_id).into(),
157 upgrade: future::ready(Ok(stream)),
158 });
159 continue;
160 }
161 Poll::Ready(None) => {
162 self.pending_events.push_back(ListenerEvent::Closed(Ok(())));
163 self.closed = true;
164 continue;
165 }
166 Poll::Pending => {
167 self.waker = Some(cx.waker().clone());
168 }
169 };
170 return Poll::Pending;
171 }
172 }
173
174 fn poll_close(
175 mut self: Pin<&mut Self>,
176 _cx: &mut Context<'_>,
177 ) -> Poll<Result<(), Self::Error>> {
178 self.pending_events.push_back(ListenerEvent::Closed(Ok(())));
179 self.closed = true;
180 if let Some(waker) = self.waker.take() {
181 waker.wake();
182 }
183 Poll::Ready(Ok(()))
184 }
185}
186
187pub struct IncomingRelayedConnection {
188 stream: Connection,
189 src_peer_id: PeerId,
191 _relay_peer_id: PeerId,
193 relay_addr: Multiaddr,
195}
196
197impl IncomingRelayedConnection {
198 pub fn new(
199 stream: Connection,
200 src_peer_id: PeerId,
201 relay_peer_id: PeerId,
202 relay_addr: Multiaddr,
203 ) -> Self {
204 Self {
205 stream,
206 src_peer_id,
207 _relay_peer_id: relay_peer_id,
208 relay_addr,
209 }
210 }
211}
212
213pub enum TransportRequest {
214 DialRequest {
215 relay_addr: Multiaddr,
216 relay_peer_id: PeerId,
217 dst_peer_id: PeerId,
218 send_back: oneshot::Sender<Result<Connection, ConnectError>>,
219 },
220 ListenRequest {
221 local_addr: Multiaddr,
222 listener_sender: mpsc::Sender<IncomingRelayedConnection>,
223 },
224}
225
226#[derive(Debug, thiserror::Error)]
227pub enum Error {
228 #[error("Missing relay peer id")]
229 MissingRelayPeerId,
230 #[error("Missing destination peer id")]
231 MissingDstPeerId,
232 #[error("Multiple circuit addresses found")]
233 MultipleCircuit,
234 #[error("Invalid circuit multiaddr format")]
235 InvalidMultiaddr,
236 #[error("Transport not supported for address: {0}")]
237 BehaviorSend(#[from] mpsc::SendError),
238 #[error("Transport error: {0}")]
239 BehaviorResponse(#[from] oneshot::Canceled),
240 #[error("Transport error: {0}")]
241 ConnectError(#[from] ConnectError),
242 #[error("I/O error: {0}")]
243 Io(#[from] io::Error),
244}
245
246#[derive(Default)]
247struct RelayedMultiaddr {
248 relay_peer_id: Option<PeerId>,
249 relay_addr: Option<Multiaddr>,
250 dst_peer_id: Option<PeerId>,
251}
252
253fn parse_relayed_multiaddr(addr: Multiaddr) -> Result<RelayedMultiaddr, TransportError<Error>> {
254 if !addr.is_circuit() {
255 return Err(TransportError::NotSupported(addr));
256 }
257
258 let mut relayed_multiaddr = RelayedMultiaddr::default();
259 let mut before_circuit = true;
260 for protocol in addr.into_iter() {
261 match protocol {
262 Protocol::Circuit => {
263 if before_circuit {
264 before_circuit = false;
265 } else {
266 return Err(Error::MultipleCircuit.into());
267 }
268 }
269 Protocol::Peer(peer_id) if before_circuit => {
270 if relayed_multiaddr.relay_peer_id.is_some() {
271 return Err(Error::InvalidMultiaddr.into());
272 }
273 relayed_multiaddr.relay_peer_id = Some(peer_id);
274 }
275 Protocol::Peer(peer_id) if !before_circuit => {
276 if relayed_multiaddr.dst_peer_id.is_some() {
277 return Err(Error::InvalidMultiaddr.into());
278 }
279 relayed_multiaddr.dst_peer_id = Some(peer_id);
280 }
281 p => {
282 if before_circuit {
283 relayed_multiaddr
284 .relay_addr
285 .get_or_insert(Multiaddr::empty())
286 .push(p);
287 } else {
288 return Err(Error::InvalidMultiaddr.into());
289 }
290 }
291 }
292 }
293 Ok(relayed_multiaddr)
294}
295
296pub struct Connection {
297 pub(crate) state: ConnectionState,
298}
299
300impl Connection {
301 pub(crate) fn new_accepting(circuit: Circuit) -> Self {
302 Connection {
303 state: ConnectionState::Accepting {
304 accept: async {
305 let (substream, read_buffer) = circuit.accept().await?;
306 Ok(ConnectionState::Accepted {
307 read_buffer,
308 substream,
309 })
310 }
311 .boxed(),
312 },
313 }
314 }
315
316 pub(crate) fn new_accepted(substream: Substream, read_buffer: Bytes) -> Self {
317 Connection {
318 state: ConnectionState::Accepted {
319 read_buffer,
320 substream,
321 },
322 }
323 }
324}
325
326pub(crate) enum ConnectionState {
327 Accepting {
328 accept: BoxFuture<'static, Result<ConnectionState, io::Error>>,
329 },
330 Accepted {
331 read_buffer: Bytes,
332 substream: Substream,
333 },
334}
335
336impl Unpin for ConnectionState {}
337
338impl AsyncWrite for Connection {
339 fn poll_write(
340 mut self: Pin<&mut Self>,
341 cx: &mut Context<'_>,
342 buf: &[u8],
343 ) -> Poll<io::Result<usize>> {
344 loop {
345 match &mut self.state {
346 ConnectionState::Accepting { accept } => {
347 *self = Connection {
348 state: ready!(accept.poll_unpin(cx))?,
349 };
350 }
351 ConnectionState::Accepted { substream, .. } => {
352 return Pin::new(substream).poll_write(cx, buf);
353 }
354 }
355 }
356 }
357
358 fn poll_write_vectored(
359 mut self: Pin<&mut Self>,
360 cx: &mut Context<'_>,
361 bufs: &[io::IoSlice<'_>],
362 ) -> Poll<io::Result<usize>> {
363 loop {
364 match &mut self.state {
365 ConnectionState::Accepting { accept } => {
366 *self = Connection {
367 state: ready!(accept.poll_unpin(cx))?,
368 };
369 }
370 ConnectionState::Accepted { substream, .. } => {
371 return Pin::new(substream).poll_write_vectored(cx, bufs);
372 }
373 }
374 }
375 }
376
377 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
378 loop {
379 match &mut self.state {
380 ConnectionState::Accepting { accept } => {
381 *self = Connection {
382 state: ready!(accept.poll_unpin(cx))?,
383 };
384 }
385 ConnectionState::Accepted { substream, .. } => {
386 return Pin::new(substream).poll_flush(cx);
387 }
388 }
389 }
390 }
391
392 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
393 loop {
394 match &mut self.state {
395 ConnectionState::Accepting { accept } => {
396 *self = Connection {
397 state: ready!(accept.poll_unpin(cx))?,
398 };
399 }
400 ConnectionState::Accepted { substream, .. } => {
401 return Pin::new(substream).poll_close(cx);
402 }
403 }
404 }
405 }
406}
407
408impl AsyncRead for Connection {
409 fn poll_read(
410 mut self: Pin<&mut Self>,
411 cx: &mut Context<'_>,
412 buf: &mut [u8],
413 ) -> Poll<io::Result<usize>> {
414 loop {
415 match &mut self.state {
416 ConnectionState::Accepting { accept } => {
417 *self = Connection {
418 state: ready!(accept.poll_unpin(cx))?,
419 };
420 }
421 ConnectionState::Accepted {
422 read_buffer,
423 substream,
424 } => {
425 if !read_buffer.is_empty() {
427 let n = read_buffer.len().min(buf.len());
428 let data = read_buffer.split_to(n);
429 buf[0..n].copy_from_slice(&data[..]);
430 return Poll::Ready(Ok(n));
431 }
432 return Pin::new(substream).poll_read(cx, buf);
433 }
434 }
435 }
436 }
437}