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