pamoja_mavlink/drivers/
tcp.rs1use std::io;
9
10use tokio::io::{AsyncReadExt, AsyncWriteExt};
11use tokio::net::{TcpStream, ToSocketAddrs};
12
13use super::link_fault;
14use crate::error::Result;
15use crate::link::ByteLink;
16
17pub struct TcpLink {
19 stream: TcpStream,
20}
21
22impl TcpLink {
23 pub async fn connect(addr: impl ToSocketAddrs) -> io::Result<Self> {
40 let stream = TcpStream::connect(addr).await?;
41 let _ = stream.set_nodelay(true);
42 Ok(TcpLink { stream })
43 }
44
45 pub fn from_stream(stream: TcpStream) -> Self {
55 let _ = stream.set_nodelay(true);
56 TcpLink { stream }
57 }
58}
59
60impl ByteLink for TcpLink {
61 async fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
62 self.stream.read(buf).await.map_err(link_fault)
63 }
64
65 async fn write_all(&mut self, data: &[u8]) -> Result<()> {
66 self.stream.write_all(data).await.map_err(link_fault)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::dialect::{CommandAck, CommandLong, Message};
74 use crate::link::Connection;
75 use tokio::net::TcpListener;
76
77 #[tokio::test]
78 async fn a_command_round_trips_over_a_real_tcp_connection() {
79 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
82 let addr = listener.local_addr().unwrap();
83
84 let server = tokio::spawn(async move {
85 let (stream, _) = listener.accept().await.unwrap();
86 let mut vehicle = Connection::new(TcpLink::from_stream(stream), 1, 1);
87 let frame = vehicle.recv().await.unwrap();
88 let command = CommandLong::decode(frame.payload()).unwrap();
89 let ack = CommandAck {
90 command: command.command,
91 result: 0,
92 progress: 0,
93 result_param2: 0,
94 target_system: frame.system_id(),
95 target_component: frame.component_id(),
96 };
97 vehicle.send(&ack).await.unwrap();
98 });
99
100 let mut gcs = Connection::new(TcpLink::connect(addr).await.unwrap(), 255, 190);
101 let arm = CommandLong {
102 param1: 1.0,
103 param2: 0.0,
104 param3: 0.0,
105 param4: 0.0,
106 param5: 0.0,
107 param6: 0.0,
108 param7: 0.0,
109 command: 400,
110 target_system: 1,
111 target_component: 1,
112 confirmation: 0,
113 };
114 gcs.send(&arm).await.unwrap();
115 let frame = gcs.recv().await.unwrap();
116 assert_eq!(frame.message_id(), CommandAck::ID);
117 server.await.unwrap();
118 }
119}