Skip to main content

rings_node/onion/
gateway.rs

1//! Native node adapter for the runtime-neutral gateway Onion boundary.
2
3use std::sync::Arc;
4
5use rings_gateway::BoxGatewayDuplex;
6use rings_gateway::FlowId;
7use rings_gateway::GatewayError;
8use rings_gateway::OnionStreamConnector;
9
10use crate::onion::proxy::OnionProxyConfig;
11use crate::onion::tcp::NativeOnionCircuitHandle;
12use crate::onion::OnionProxyTarget;
13use crate::processor::Processor;
14
15/// Native connector that maps one captured target to one Rings Onion TCP stream.
16pub struct NativeOnionGatewayConnector {
17    processor: Arc<Processor>,
18    onion: NativeOnionCircuitHandle,
19    proxy: OnionProxyConfig,
20}
21
22impl NativeOnionGatewayConnector {
23    /// Bind a native processor and installed Onion runtime to gateway route options.
24    pub fn new(
25        processor: Arc<Processor>,
26        onion: NativeOnionCircuitHandle,
27        proxy: OnionProxyConfig,
28    ) -> Self {
29        Self {
30            processor,
31            onion,
32            proxy,
33        }
34    }
35
36    fn onion_error(flow: FlowId, error: impl std::fmt::Display) -> GatewayError {
37        GatewayError::OnionUnavailable {
38            target: flow.target,
39            message: error.to_string(),
40        }
41    }
42}
43
44#[async_trait::async_trait]
45impl OnionStreamConnector for NativeOnionGatewayConnector {
46    async fn open_stream(
47        &self,
48        flow: FlowId,
49        stream: BoxGatewayDuplex,
50    ) -> Result<(), GatewayError> {
51        let target = OnionProxyTarget::parse_authority(&flow.target.to_string())
52            .map_err(|error| Self::onion_error(flow, error))?;
53        let route = self
54            .processor
55            .build_onion_proxy_route(self.proxy.clone(), target)
56            .await
57            .map_err(|error| Self::onion_error(flow, error))?;
58        let opened = self
59            .onion
60            .open_tcp_stream(route.route, route.target)
61            .await
62            .map_err(|error| Self::onion_error(flow, error))?;
63        opened.relay(stream);
64        Ok(())
65    }
66}