liminal_server/link_open/network/
backend.rs1use super::NetworkBackend;
3use crate::config::types::OutboundLinkConfig;
4use crate::link_carrier::{Carrier, RelayCarrier, read_frame, write_frame};
5use crate::link_dial::{LinkDialOutcome, LinkDialer};
6use crate::link_open::carriers::{DirectPath, StreamPath, named};
7use crate::link_open::{Backend, OpenError, Path, Stop};
8use liminal::protocol::Frame;
9use std::sync::Arc;
10impl Backend for NetworkBackend {
11 fn interrupt_handle(&self) -> Option<Stop> {
12 let network = Arc::clone(&self.network);
13 Some(Arc::new(move || network.stop()))
14 }
15 fn wire(
16 &mut self,
17 config: &OutboundLinkConfig,
18 address: &str,
19 ) -> Result<Box<dyn Path>, OpenError> {
20 self.require_config(config)?;
21 self.network.require_running()?;
22 let mut entry = config.clone();
23 entry.peer_address = Some(address.to_owned());
24 match LinkDialer::new(&self.network.host, &self.network.machine)
25 .with_network(&self.network)
26 .open(&entry)
27 .map_err(named)?
28 {
29 LinkDialOutcome::Opened(link) => {
30 let interrupt = self
31 .network
32 .retain(link.carrier.interrupt_handle().map_err(named)?)?;
33 Ok(Box::new(StreamPath::wire(*link).with_interrupt(interrupt)))
34 }
35 LinkDialOutcome::Held { grant, draft } => {
36 Err(OpenError(format!("link_held:{grant}:{draft}")))
37 }
38 LinkDialOutcome::Refused { reason } => Err(OpenError(format!("link_refused:{reason}"))),
39 }
40 }
41 fn lookup(&mut self, config: &OutboundLinkConfig) -> Result<Vec<String>, OpenError> {
42 self.require_config(config)?;
43 self.network.require_running()?;
44 let (mut broker, connections) = self.network.broker()?;
45 let result = broker
46 .call(
47 "net.broker.lookup",
48 &serde_json::json!({"device": hex::encode(self.peer.ed25519_public())}),
49 )
50 .map_err(named);
51 drop(connections);
52 let value = result?;
53 let addresses: Vec<String> = serde_json::from_value(
54 value
55 .get("addresses")
56 .cloned()
57 .ok_or_else(|| OpenError("invalid_broker_answer".to_owned()))?,
58 )
59 .map_err(|_| OpenError("invalid_broker_answer".to_owned()))?;
60 if addresses.len() > 64
61 || addresses
62 .iter()
63 .any(|address| address.is_empty() || address.len() > 2048)
64 {
65 return Err(OpenError("invalid_broker_addresses".to_owned()));
66 }
67 Ok(addresses)
68 }
69 fn punch(&mut self, config: &OutboundLinkConfig) -> Result<Box<dyn Path>, OpenError> {
70 self.require_config(config)?;
71 let index = {
72 let mut direct = self.network.direct.lock().map_err(named)?;
73 let index = direct.next;
74 direct.next = index
75 .checked_add(1)
76 .ok_or_else(|| OpenError("direct_indices_exhausted".to_owned()))?;
77 index
78 };
79 let peer_name = hex::encode(self.peer.ed25519_public());
80 self.network
81 .pending
82 .lock()
83 .map_err(named)?
84 .insert(peer_name.clone());
85 let result = self.network.with_puncher(|puncher| {
86 puncher.prepare_open().map_err(named)?;
87 let handshake_guard = self.network.handshakes.lock().map_err(named)?;
88 let link = puncher.punch(self.peer, index).map_err(named)?;
89 drop(handshake_guard);
90 let mut path =
91 DirectPath::new(puncher.shared_carrier().map_err(named)?, link.local_index)?;
92 let pass =
93 crate::link_pass::MachinePass::configured(&self.network.machine).map_err(named)?;
94 let token = pass.for_open().map_err(named)?;
95 let deadline = crate::link_open::Deadline::after(std::time::Duration::from_millis(
96 self.network.choice.crossing_deadline_ms,
97 ))?;
98 path.admit(
99 &self.network.host,
100 &self.network.machine.agent_id,
101 self.peer,
102 config,
103 &token,
104 deadline.expires(),
105 )?;
106 Ok(Box::new(path) as Box<dyn Path>)
107 });
108 self.network
109 .pending
110 .lock()
111 .map_err(named)?
112 .remove(&peer_name);
113 result
114 }
115 fn relay(&mut self, config: &OutboundLinkConfig) -> Result<Box<dyn Path>, OpenError> {
116 self.require_config(config)?;
117 self.network.require_running()?;
118 let choice = &self.network.choice;
119 let holder = choice
120 .relay_holder
121 .as_deref()
122 .ok_or_else(|| OpenError("relay_not_configured".to_owned()))?;
123 let relay = self
124 .network
125 .host
126 .recorded_machine(holder)
127 .ok_or_else(|| OpenError("relay_has_no_recorded_machine".to_owned()))?;
128 let address = choice
129 .relay_address
130 .as_deref()
131 .ok_or_else(|| OpenError("relay_address_not_configured".to_owned()))?;
132 let (mut socket, interrupt) = self.network.connect(address)?;
133 write_frame(
134 &mut socket,
135 &Frame::ConversationOpen {
136 flags: 0,
137 stream_id: 1,
138 conversation_id: 1,
139 subject: format!("net.relay.{}", hex::encode(self.peer.ed25519_public())),
140 },
141 )
142 .map_err(named)?;
143 write_frame(&mut socket, &Frame::Ping { flags: 0 }).map_err(named)?;
144 if !matches!(
145 read_frame(&mut socket).map_err(named)?,
146 Some(Frame::Pong { .. })
147 ) {
148 return Err(OpenError("relay_stream_not_marked".to_owned()));
149 }
150 let carrier = RelayCarrier::new(socket, 1, relay).map_err(named)?;
151 let link = crate::link_relay::open(carrier, self.network.host.local(), self.peer)
152 .map_err(named)?;
153 Ok(Box::new(
154 StreamPath::relay(link, hex::encode(relay.ed25519_public())).with_interrupt(interrupt),
155 ))
156 }
157 fn repunch(
158 &mut self,
159 config: &OutboundLinkConfig,
160 path: &mut dyn Path,
161 ) -> Result<(), OpenError> {
162 self.require_config(config)?;
163 let index = path
164 .direct_index()
165 .ok_or_else(|| OpenError("cannot_repunch_a_stream".to_owned()))?;
166 self.network
167 .with_puncher(|puncher| puncher.refresh(self.peer, index).map_err(named))
168 }
169 fn topology(
170 &mut self,
171 carrier: Option<Carrier>,
172 relay: Option<String>,
173 refusal: Option<&str>,
174 ) -> Result<(), OpenError> {
175 use crate::console::records::{Carrier as ObservedCarrier, Link, LinkCounters, LinkState};
176 if refusal.is_some() {
177 self.refused = self
178 .refused
179 .checked_add(1)
180 .ok_or_else(|| OpenError("carrier_refusal_count_exhausted".to_owned()))?;
181 }
182 let peer = hex::encode(self.peer.ed25519_public());
183 let local = self.services.console().device();
184 let carrier = match carrier {
185 Some(Carrier::Wire) => Some(ObservedCarrier::Wire),
186 Some(Carrier::Direct) => Some(ObservedCarrier::Direct),
187 Some(Carrier::Relay) => {
188 let device = relay.or_else(|| {
189 self.network
190 .choice
191 .relay_holder
192 .as_deref()
193 .and_then(|holder| self.network.host.recorded_machine(holder))
194 .map(|machine| hex::encode(machine.ed25519_public()))
195 });
196 if device.is_none() && refusal.is_none() {
197 return Err(OpenError("relay_topology_has_no_device".to_owned()));
198 }
199 device.map(ObservedCarrier::Relay)
200 }
201 None => None,
202 };
203 self.services
204 .console()
205 .emit(crate::console::TopologyChange::Link {
206 link_id: Link::to_peer(local, &peer).id,
207 peer,
208 carrier,
209 state: if refusal.is_some() {
210 LinkState::Down
211 } else {
212 LinkState::Up
213 },
214 reason: refusal.map(str::to_owned),
215 counters: LinkCounters {
216 refused: Some(self.refused),
217 ..LinkCounters::default()
218 },
219 })
220 .map_err(named)
221 }
222}