1use crate::config::LimitsConfig;
4use liminal::protocol::{Frame, FrameHeader, ProtocolError, codec};
5use std::io::{Read, Write};
6use std::net::TcpStream;
7
8pub mod choice;
9mod reader;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum Carrier {
14 Wire,
16 Direct,
18 Relay,
20}
21
22#[derive(Debug, PartialEq, Eq)]
24pub enum CarrierReceive {
25 Sealed { subject: String, sealed: Vec<u8> },
27 Acknowledged {
29 message_id: u64,
30 durable_position: Option<u64>,
31 },
32 Refused {
34 reason_code: u16,
35 reason: Option<String>,
36 },
37 End { reason: String },
39}
40
41#[derive(Debug, thiserror::Error)]
43pub enum CarrierError {
44 #[error("wire link lifecycle failed: {0}")]
46 Lifecycle(String),
47 #[error("wire I/O failed: {0}")]
49 Io(#[from] std::io::Error),
50 #[error("wire framing refused: {0}")]
52 Protocol(#[from] ProtocolError),
53 #[error(transparent)]
55 Subject(#[from] crate::auth_lys::SubjectBindingError),
56 #[error("wire frame of {bytes} bytes exceeds bound {bound}")]
58 TooLarge { bytes: usize, bound: usize },
59 #[error("unexpected frame on wire link")]
61 UnexpectedFrame,
62 #[error("wire carrier has ended")]
64 Ended,
65}
66
67pub trait LinkCarrier: Send + std::fmt::Debug {
69 fn carrier(&self) -> Carrier;
71 fn refuse_unsolicited(&self) -> Result<(), CarrierError> {
74 Ok(())
75 }
76 fn send(&mut self, subject: &str, sealed: &[u8]) -> Result<(), CarrierError>;
81 fn receive(&mut self) -> Result<CarrierReceive, CarrierError>;
86}
87
88#[derive(Debug)]
90pub struct WireCarrier {
91 socket: TcpStream,
92 stream_id: u32,
93 ended: Option<String>,
94 life: Option<crate::link::LinkLife>,
95 reader: Option<reader::Reader>,
96}
97
98impl WireCarrier {
99 pub(crate) fn refuse_unsolicited(&self) -> Result<(), CarrierError> {
100 if let Some(reader) = &self.reader
101 && let Some(answer) = reader.try_receive()?
102 {
103 let error = match answer {
104 Ok(Some(_)) => CarrierError::UnexpectedFrame,
105 Ok(None) => CarrierError::Ended,
106 Err(error) => error,
107 };
108 self.failed(&error);
109 return Err(error);
110 }
111 Ok(())
112 }
113 pub(crate) fn install_life(&mut self, life: crate::link::LinkLife) -> Result<(), CarrierError> {
114 if self.life.is_some() {
115 return Err(CarrierError::Lifecycle(
116 "lifecycle already installed".to_owned(),
117 ));
118 }
119 self.life = Some(life.clone());
120 match reader::Reader::start(&self.socket, self.stream_id, life) {
121 Ok(reader) => self.reader = Some(reader),
122 Err(error) => {
123 self.end_life(crate::link::LinkEnd::Refused(error.to_string()));
124 return Err(error);
125 }
126 }
127 Ok(())
128 }
129
130 pub(crate) const fn life(&self) -> Option<&crate::link::LinkLife> {
131 self.life.as_ref()
132 }
133
134 fn end_life(&self, reason: crate::link::LinkEnd) {
135 if let Some(life) = &self.life
136 && let Err(error) = life.end(reason)
137 {
138 tracing::error!(%error, "wire link end observation failed");
139 }
140 }
141
142 fn failed(&self, error: &CarrierError) {
143 self.end_life(
144 if matches!(error, CarrierError::Io(_) | CarrierError::Ended) {
145 crate::link::LinkEnd::PeerGone
146 } else {
147 crate::link::LinkEnd::Refused(error.to_string())
148 },
149 );
150 }
151 pub fn interrupt_handle(&self) -> Result<TcpStream, CarrierError> {
156 Ok(self.socket.try_clone()?)
157 }
158 pub fn new(socket: TcpStream, stream_id: u32) -> Result<Self, CarrierError> {
163 liminal::protocol::validate_stream(liminal::protocol::FrameType::LinkMessage, stream_id)?;
164 Ok(Self {
165 socket,
166 stream_id,
167 ended: None,
168 life: None,
169 reader: None,
170 })
171 }
172}
173
174impl LinkCarrier for WireCarrier {
175 fn refuse_unsolicited(&self) -> Result<(), CarrierError> {
176 Self::refuse_unsolicited(self)
177 }
178 fn carrier(&self) -> Carrier {
179 Carrier::Wire
180 }
181
182 fn send(&mut self, subject: &str, sealed: &[u8]) -> Result<(), CarrierError> {
183 if self.ended.is_some() {
184 return Err(CarrierError::Ended);
185 }
186 if let Some(life) = &self.life
187 && life.reason().map_err(CarrierError::Lifecycle)?.is_some()
188 {
189 return Err(CarrierError::Ended);
190 }
191 crate::auth_lys::SubjectBinding::new(
192 "wire".to_owned(),
193 subject.to_owned(),
194 subject.to_owned(),
195 )?;
196 let result = write_frame(
197 &mut self.socket,
198 &Frame::LinkMessage {
199 flags: 0,
200 stream_id: self.stream_id,
201 subject: subject.to_owned(),
202 sealed: sealed.to_vec(),
203 },
204 );
205 if let Err(error) = &result {
206 self.failed(error);
207 }
208 result
209 }
210
211 fn receive(&mut self) -> Result<CarrierReceive, CarrierError> {
212 if let Some(reason) = &self.ended {
213 return Ok(CarrierReceive::End {
214 reason: reason.clone(),
215 });
216 }
217 let answer = if let Some(reader) = &self.reader {
218 reader.receive()
219 } else {
220 read_frame(&mut self.socket)
221 };
222 let frame = answer.inspect_err(|error| self.failed(error))?;
223 let reason = match frame {
224 Some(Frame::PublishAck {
225 stream_id,
226 message_id,
227 durable_position,
228 ..
229 }) if stream_id == self.stream_id => {
230 return Ok(CarrierReceive::Acknowledged {
231 message_id,
232 durable_position,
233 });
234 }
235 Some(Frame::PublishError {
236 stream_id,
237 reason_code,
238 message,
239 ..
240 }) if stream_id == self.stream_id => {
241 return Ok(CarrierReceive::Refused {
242 reason_code,
243 reason: message,
244 });
245 }
246 Some(Frame::LinkMessage {
247 stream_id,
248 subject,
249 sealed,
250 ..
251 }) if stream_id == self.stream_id => {
252 crate::auth_lys::SubjectBinding::new(
253 "wire".to_owned(),
254 subject.clone(),
255 subject.clone(),
256 )?;
257 return Ok(CarrierReceive::Sealed { subject, sealed });
258 }
259 Some(Frame::DisconnectReason { reason, .. }) => reason.name().to_owned(),
260 Some(Frame::Disconnect { .. }) => "peer_disconnect".to_owned(),
261 None => "wire_eof".to_owned(),
262 Some(_) => {
263 self.failed(&CarrierError::UnexpectedFrame);
264 return Err(CarrierError::UnexpectedFrame);
265 }
266 };
267 self.end_life(
268 if reason == "grant_revoked" || reason == "revocation_log_reset" {
269 crate::link::LinkEnd::Revoked
270 } else {
271 crate::link::LinkEnd::PeerGone
272 },
273 );
274 self.ended = Some(reason.clone());
275 Ok(CarrierReceive::End { reason })
276 }
277}
278
279impl Drop for WireCarrier {
280 fn drop(&mut self) {
281 self.end_life(crate::link::LinkEnd::Shutdown);
282 if let Some(reader) = self.reader.take() {
283 reader.close(&self.socket);
284 }
285 }
286}
287
288#[derive(Debug)]
290pub struct RelayCarrier {
291 wire: WireCarrier,
292 relay: crate::link_handshake::MachineIdentity,
293}
294
295impl RelayCarrier {
296 pub fn new(
301 socket: TcpStream,
302 stream_id: u32,
303 relay: crate::link_handshake::MachineIdentity,
304 ) -> Result<Self, CarrierError> {
305 Ok(Self {
306 wire: WireCarrier::new(socket, stream_id)?,
307 relay,
308 })
309 }
310
311 pub fn interrupt_handle(&self) -> Result<TcpStream, CarrierError> {
316 self.wire.interrupt_handle()
317 }
318
319 pub fn acknowledge(
324 &mut self,
325 message_id: u64,
326 durable_position: Option<u64>,
327 ) -> Result<(), CarrierError> {
328 self.reply(&Frame::PublishAck {
329 flags: 0,
330 stream_id: self.wire.stream_id,
331 message_id,
332 durable_position,
333 })
334 }
335
336 pub fn refuse(&mut self, reason_code: u16, reason: &str) -> Result<(), CarrierError> {
341 self.reply(&Frame::PublishError {
342 flags: 0,
343 stream_id: self.wire.stream_id,
344 reason_code,
345 message: Some(reason.to_owned()),
346 })
347 }
348
349 #[must_use]
351 pub fn topology(
352 &self,
353 local: crate::link_handshake::MachineIdentity,
354 peer: crate::link_handshake::MachineIdentity,
355 counters: crate::console::records::LinkCounters,
356 ) -> crate::console::records::Link {
357 crate::console::records::Link::federated(
358 &hex::encode(local.ed25519_public()),
359 &hex::encode(peer.ed25519_public()),
360 Some(crate::console::records::Carrier::Relay(hex::encode(
361 self.relay.ed25519_public(),
362 ))),
363 crate::console::records::LinkState::Up,
364 None,
365 counters,
366 )
367 }
368
369 fn reply(&mut self, frame: &Frame) -> Result<(), CarrierError> {
370 if self.wire.ended.is_some() {
371 return Err(CarrierError::Ended);
372 }
373 write_frame(&mut self.wire.socket, frame)
374 }
375}
376
377impl LinkCarrier for RelayCarrier {
378 fn refuse_unsolicited(&self) -> Result<(), CarrierError> {
379 self.wire.refuse_unsolicited()
380 }
381 fn carrier(&self) -> Carrier {
382 Carrier::Relay
383 }
384 fn send(&mut self, subject: &str, sealed: &[u8]) -> Result<(), CarrierError> {
385 self.wire.send(subject, sealed)
386 }
387 fn receive(&mut self) -> Result<CarrierReceive, CarrierError> {
388 self.wire.receive()
389 }
390}
391
392pub(crate) const WIRE_FRAME_BOUND: usize = LimitsConfig::DEFAULT_MAX_CONNECTION_INBOX_BYTES;
394
395pub(crate) fn write_frame(socket: &mut TcpStream, frame: &Frame) -> Result<(), CarrierError> {
396 let bytes = codec::encoded_len(frame)?;
397 if bytes > WIRE_FRAME_BOUND {
398 return Err(CarrierError::TooLarge {
399 bytes,
400 bound: WIRE_FRAME_BOUND,
401 });
402 }
403 let mut encoded = vec![0; bytes];
404 let length = codec::encode(frame, &mut encoded)?;
405 socket.write_all(&encoded[..length])?;
406 Ok(())
407}
408
409pub(crate) fn read_frame(socket: &mut TcpStream) -> Result<Option<Frame>, CarrierError> {
410 let mut header = [0; FrameHeader::WIRE_LEN];
411 loop {
413 match socket.read(&mut header[..1]) {
414 Ok(0) => return Ok(None),
415 Ok(_) => break,
416 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => {}
417 Err(error) => return Err(error.into()),
418 }
419 }
420 socket.read_exact(&mut header[1..])?;
421 let payload = u32::from_be_bytes([header[6], header[7], header[8], header[9]]);
422 let bytes = usize::try_from(payload)
423 .ok()
424 .and_then(|length| length.checked_add(header.len()))
425 .ok_or(CarrierError::TooLarge {
426 bytes: usize::MAX,
427 bound: WIRE_FRAME_BOUND,
428 })?;
429 if bytes > WIRE_FRAME_BOUND {
430 return Err(CarrierError::TooLarge {
431 bytes,
432 bound: WIRE_FRAME_BOUND,
433 });
434 }
435 let mut encoded = vec![0; bytes];
436 encoded[..header.len()].copy_from_slice(&header);
437 socket.read_exact(&mut encoded[header.len()..])?;
438 let (frame, _) = codec::decode(&encoded)?;
439 Ok(Some(frame))
440}