mavlink_core/connection/tcp/
sync.rs1use crate::Dialect;
4use crate::MavlinkReader;
5use crate::connection::get_socket_addr;
6use crate::connection::sync::{Connectable, DialectConnection, SyncTransport, Transport};
7use std::io;
8use std::net::{TcpListener, TcpStream, ToSocketAddrs};
9use std::sync::Mutex;
10use std::time::Duration;
11
12use super::config::{TcpConfig, TcpMode};
13
14pub fn tcpout<T: ToSocketAddrs>(address: T) -> io::Result<TcpConnection> {
15 let socket = TcpStream::connect(get_socket_addr(&address)?)?;
16 socket.set_read_timeout(Some(Duration::from_millis(100)))?;
17 connection_from_stream(socket)
18}
19
20fn connection_from_stream(socket: TcpStream) -> io::Result<TcpConnection> {
21 Ok(TcpConnection {
22 reader: Mutex::new(MavlinkReader::new(socket.try_clone()?)),
23 writer: Mutex::new(socket),
24 })
25}
26
27pub fn tcpin<T: ToSocketAddrs>(address: T) -> io::Result<TcpConnection> {
28 let listener = TcpListener::bind(get_socket_addr(&address)?)?;
29 accept(listener)
30}
31
32fn accept(listener: TcpListener) -> io::Result<TcpConnection> {
33 for incoming in listener.incoming() {
34 match incoming {
35 Ok(socket) => return connection_from_stream(socket),
36 Err(e) => println!("listener err: {e}"),
37 }
38 }
39 Err(io::Error::new(
40 io::ErrorKind::NotConnected,
41 "No incoming connections!",
42 ))
43}
44
45pub struct TcpConnection {
46 reader: Mutex<MavlinkReader<TcpStream>>,
47 writer: Mutex<TcpStream>,
48}
49
50impl SyncTransport for TcpConnection {
51 type Reader = TcpStream;
52 type Writer = TcpStream;
53
54 fn reader(&self) -> std::sync::MutexGuard<'_, MavlinkReader<Self::Reader>> {
55 self.reader.lock().unwrap()
56 }
57
58 fn lock_writer(&self) -> Option<std::sync::MutexGuard<'_, Self::Writer>> {
59 Some(self.writer.lock().unwrap())
60 }
61
62 fn set_nonblocking(
63 &self,
64 reader: &mut MavlinkReader<Self::Reader>,
65 enabled: bool,
66 ) -> io::Result<()> {
67 reader.get_mut().set_nonblocking(enabled)
68 }
69}
70
71impl TcpConfig {
72 pub(crate) fn open(&self) -> io::Result<TcpConnection> {
73 match self.mode {
74 TcpMode::TcpIn => match self.take_listener()? {
75 Some(listener) => accept(listener),
76 None => tcpin(&self.address),
77 },
78 TcpMode::TcpOut => match self.take_stream()? {
79 Some(stream) => connection_from_stream(stream),
80 None => tcpout(&self.address),
81 },
82 }
83 }
84}
85
86impl Connectable for TcpConfig {
87 fn connect_with_dialect<D: Dialect + Send + Sync>(
88 &self,
89 dialect: D,
90 ) -> io::Result<DialectConnection<D>> {
91 Ok(DialectConnection::new(
92 Transport::Tcp(self.open()?),
93 dialect,
94 ))
95 }
96}