mavlink_core/connection/tcp/
config.rs1use core::fmt::Display;
2use std::io;
3use std::net::{TcpListener, TcpStream};
4use std::sync::{Arc, Mutex};
5
6#[derive(Debug, Clone, Copy)]
8pub enum TcpMode {
9 TcpIn,
11 TcpOut,
13}
14
15#[derive(Debug, Clone)]
26pub struct TcpConfig {
27 pub(crate) address: String,
28 pub(crate) mode: TcpMode,
29 pub(crate) source: TcpSource,
30}
31
32#[derive(Debug, Clone)]
33pub(crate) enum TcpSource {
34 Address,
35 Stream(Arc<Mutex<Option<TcpStream>>>),
36 Listener(Arc<Mutex<Option<TcpListener>>>),
37}
38
39impl TcpConfig {
40 pub fn new(address: String, mode: TcpMode) -> Self {
42 Self {
43 address,
44 mode,
45 source: TcpSource::Address,
46 }
47 }
48
49 pub fn from_stream(stream: TcpStream) -> io::Result<Self> {
53 let address = stream.peer_addr()?.to_string();
54 Ok(Self {
55 address,
56 mode: TcpMode::TcpOut,
57 source: TcpSource::Stream(Arc::new(Mutex::new(Some(stream)))),
58 })
59 }
60
61 pub fn from_listener(listener: TcpListener) -> io::Result<Self> {
65 let address = listener.local_addr()?.to_string();
66 Ok(Self {
67 address,
68 mode: TcpMode::TcpIn,
69 source: TcpSource::Listener(Arc::new(Mutex::new(Some(listener)))),
70 })
71 }
72
73 pub(crate) fn take_stream(&self) -> io::Result<Option<TcpStream>> {
74 match &self.source {
75 TcpSource::Address => Ok(None),
76 TcpSource::Stream(stream) => stream
77 .lock()
78 .map_err(|_| io::Error::other("TCP stream lock poisoned"))?
79 .take()
80 .map(Some)
81 .ok_or_else(|| io::Error::other("TCP socket-backed configuration already used")),
82 TcpSource::Listener(_) => Err(io::Error::new(
83 io::ErrorKind::InvalidInput,
84 "TCP listener cannot be used as an outgoing connection",
85 )),
86 }
87 }
88
89 pub(crate) fn take_listener(&self) -> io::Result<Option<TcpListener>> {
90 match &self.source {
91 TcpSource::Address => Ok(None),
92 TcpSource::Listener(listener) => listener
93 .lock()
94 .map_err(|_| io::Error::other("TCP listener lock poisoned"))?
95 .take()
96 .map(Some)
97 .ok_or_else(|| io::Error::other("TCP socket-backed configuration already used")),
98 TcpSource::Stream(_) => Err(io::Error::new(
99 io::ErrorKind::InvalidInput,
100 "TCP stream cannot be used as an incoming connection",
101 )),
102 }
103 }
104}
105impl Display for TcpConfig {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 match self.mode {
108 TcpMode::TcpIn => write!(f, "tcpin:{}", self.address),
109 TcpMode::TcpOut => write!(f, "tcpout:{}", self.address),
110 }
111 }
112}