1 // Copyright 2023, Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Packet parsers and serializers.
16 
17 /// UCI packet parser and serializer.
18 pub mod uci {
19     #![allow(clippy::all)]
20     #![allow(non_upper_case_globals)]
21     #![allow(non_camel_case_types)]
22     #![allow(non_snake_case)]
23     #![allow(unused)]
24     #![allow(missing_docs)]
25 
26     include!(concat!(env!("OUT_DIR"), "/uci_packets.rs"));
27 
28     /// Size of common UCI packet header.
29     pub const COMMON_HEADER_SIZE: usize = 1;
30     /// Size of UCI packet headers.
31     pub const HEADER_SIZE: usize = 4;
32     /// Maximum size of an UCI control packet payload.
33     pub const MAX_CTRL_PACKET_PAYLOAD_SIZE: usize = 255;
34     /// Maximum size of an UCI data packet payload.
35     pub const MAX_DATA_PACKET_PAYLOAD_SIZE: usize = 1024;
36 
37     // Extract the message type from the first 3 bits of the passed (header) byte
parse_message_type(byte: u8) -> MessageType38     pub fn parse_message_type(byte: u8) -> MessageType {
39         MessageType::try_from((byte >> 5) & 0x7).unwrap_or(MessageType::Command)
40     }
41 
42     /// Read a single UCI packet from a TCP read half.
43     /// This function does not reassemble segmented packets.
read( mut socket: tokio::net::tcp::OwnedReadHalf, ) -> Option<(Vec<u8>, tokio::net::tcp::OwnedReadHalf)>44     pub async fn read(
45         mut socket: tokio::net::tcp::OwnedReadHalf,
46     ) -> Option<(Vec<u8>, tokio::net::tcp::OwnedReadHalf)> {
47         use tokio::io::AsyncReadExt;
48 
49         let mut packet = vec![0; HEADER_SIZE];
50 
51         // Read the common packet header.
52         socket.read_exact(&mut packet[0..HEADER_SIZE]).await.ok()?;
53 
54         let common_packet_header =
55             CommonPacketHeader::parse(&packet[0..COMMON_HEADER_SIZE]).ok()?;
56 
57         let payload_length = match common_packet_header.get_mt() {
58             MessageType::Data => {
59                 let data_packet_header = DataPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?;
60                 data_packet_header.get_payload_length() as usize
61             }
62             _ => {
63                 let control_packet_header =
64                     ControlPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?;
65                 control_packet_header.get_payload_length() as usize
66             }
67         };
68 
69         // Read the packet payload.
70         packet.resize(payload_length + HEADER_SIZE, 0);
71         socket.read_exact(&mut packet[HEADER_SIZE..]).await.ok()?;
72 
73         Some((packet, socket))
74     }
75 
76     /// Write a single UCI packet to a TCP write half.
77     /// This function accepts segmented packets only.
write( mut socket: tokio::net::tcp::OwnedWriteHalf, packet: Vec<u8>, ) -> std::result::Result<tokio::net::tcp::OwnedWriteHalf, anyhow::Error>78     pub async fn write(
79         mut socket: tokio::net::tcp::OwnedWriteHalf,
80         packet: Vec<u8>,
81     ) -> std::result::Result<tokio::net::tcp::OwnedWriteHalf, anyhow::Error> {
82         use tokio::io::AsyncWriteExt;
83 
84         socket.write_all(&packet).await?;
85 
86         Ok(socket)
87     }
88 }
89