1 /* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 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 16 /// provide C interface to C++ for calling 17 pub mod ffi; 18 pub(super) mod net_packet; 19 mod binding; 20 use hilog_rust::{error, hilog, debug, HiLogLabel, LogType}; 21 use std::ffi::{CString, c_char}; 22 use std::mem::size_of; 23 use binding::CSensorServiceClient; 24 use net_packet::{NetPacket, CNetPacket, PackHead}; 25 type ErrorStatus = crate::stream_buffer::ErrStatus; 26 /// function pointer alias 27 pub type ClientPacketCallBackFun = unsafe extern "C" fn ( 28 client: *const CSensorServiceClient, 29 pkt: *const CNetPacket, 30 ); 31 32 const ONCE_PROCESS_NETPACKET_LIMIT: i32 = 100; 33 const MAX_STREAM_BUF_SIZE: usize = 256; 34 /// max buffer size of packet 35 pub const MAX_PACKET_BUF_SIZE: usize = 256; 36 const PARAM_INPUT_INVALID: i32 = 5; 37 const MEM_OUT_OF_BOUNDS: i32 = 3; 38 const MEMCPY_SEC_FUN_FAIL: i32 = 4; 39 const STREAM_BUF_READ_FAIL: i32 = 1; 40 const MAX_VECTOR_SIZE: i32 = 10; 41 const LOG_LABEL: HiLogLabel = HiLogLabel { 42 log_type: LogType::LogCore, 43 domain: 0xD002700, 44 tag: "StreamBuffer" 45 }; 46 47 /// enum errstatus 48 #[derive(Copy, Clone, PartialEq)] 49 #[repr(C)] 50 pub enum ErrStatus { 51 /// status ok 52 Ok = 0, 53 /// readerror 54 Read = 1, 55 /// writeerror 56 Write = 2, 57 } 58 59 #[derive(Copy, Clone)] 60 #[repr(C)] 61 pub struct StreamBuffer { 62 rw_error_status: ErrorStatus, 63 r_count: usize, 64 w_count: usize, 65 r_pos: usize, 66 w_pos: usize, 67 sz_buff: [c_char; MAX_STREAM_BUF_SIZE + 1], 68 } 69 70 impl Default for StreamBuffer { default() -> Self71 fn default() -> Self { 72 Self { 73 rw_error_status: ErrorStatus::Ok, 74 r_count: 0, 75 w_count: 0, 76 r_pos: 0, 77 w_pos: 0, 78 sz_buff: [0; MAX_STREAM_BUF_SIZE + 1], 79 } 80 } 81 } 82 83 84 impl StreamBuffer { as_ref<'a>(object: *const Self) -> Option<&'a Self>85 fn as_ref<'a>(object: *const Self) -> Option<&'a Self> { 86 // SAFETY: as_ref has already done no-null verification inside 87 unsafe { 88 object.as_ref() 89 } 90 } as_mut<'a>(object: *mut Self) -> Option<&'a mut Self>91 fn as_mut<'a>(object: *mut Self) -> Option<&'a mut Self> { 92 // SAFETY: as_mut has already done no-null verification inside 93 unsafe { 94 object.as_mut() 95 } 96 } write<T>(&mut self, data: T)97 fn write<T>(&mut self, data: T) { 98 let data: *const c_char = &data as *const T as *const c_char; 99 let size = size_of::<T>(); 100 self.write_char_usize(data, size); 101 } reset(&mut self)102 fn reset(&mut self) { 103 self.r_pos = 0; 104 self.w_pos = 0; 105 self.r_count = 0; 106 self.w_count = 0; 107 self.rw_error_status = ErrorStatus::Ok; 108 } clean(&mut self)109 fn clean(&mut self) { 110 self.reset(); 111 let size = MAX_STREAM_BUF_SIZE + 1; 112 let reference = &(self.sz_buff); 113 let pointer = reference as *const c_char; 114 // SAFETY: memset_s is the security function of the C library 115 let ret = unsafe { 116 binding::memset_s(pointer as *mut libc::c_void, size, 0, size) 117 }; 118 if ret != 0 { 119 error!(LOG_LABEL, "Call memset_s fail"); 120 } 121 } seek_read_pos(&mut self, n: usize) -> bool122 fn seek_read_pos(&mut self, n: usize) -> bool { 123 let pos: usize = self.r_pos + n; 124 if pos > self.w_pos { 125 error!(LOG_LABEL, "The position in the calculation is not as expected. pos:{} [0, {}]", 126 pos, self.w_pos); 127 false 128 } else { 129 self.r_pos = pos; 130 true 131 } 132 } unread_size(&self) -> usize133 fn unread_size(&self) -> usize { 134 if self.w_pos <= self.r_pos { 135 0 136 } else { 137 self.w_pos - self.r_pos 138 } 139 } is_empty(&self) -> bool140 fn is_empty(&self) -> bool { 141 self.r_pos == self.w_pos 142 } write_streambuffer(&mut self, buf: &Self) -> bool143 fn write_streambuffer(&mut self, buf: &Self) -> bool { 144 self.write_char_usize(buf.data(), buf.size()) 145 } read_streambuffer(&self, buf: &mut Self) -> bool146 fn read_streambuffer(&self, buf: &mut Self) -> bool { 147 buf.write_char_usize(self.data(), self.size()) 148 } data(&self) -> *const c_char149 pub(crate) fn data(&self) -> *const c_char { 150 &(self.sz_buff[0]) as *const c_char 151 } size(&self) -> usize152 pub(crate) fn size(&self) -> usize { 153 self.w_pos 154 } chk_rwerror(&self) -> bool155 pub(crate) fn chk_rwerror(&self) -> bool { 156 self.rw_error_status != ErrorStatus::Ok 157 } get_available_buf_size(&self) -> usize158 fn get_available_buf_size(&self) -> usize { 159 if self.w_pos >= MAX_STREAM_BUF_SIZE { 160 0 161 } else { 162 MAX_STREAM_BUF_SIZE - self.w_pos 163 } 164 } get_error_status_remark(&self) -> *const c_char165 fn get_error_status_remark(&self) -> *const c_char { 166 // Creating a new C-compatible string will never fail, 167 // because the supplied bytes always contain greater than 0. 168 let s: CString = match self.rw_error_status { 169 ErrorStatus::Ok => CString::new("OK").unwrap_or_default(), 170 ErrorStatus::Read => CString::new("READ_ERROR").unwrap_or_default(), 171 ErrorStatus::Write => CString::new("WRITE_ERROR").unwrap_or_default(), 172 }; 173 s.as_ptr() 174 } read_buf(&self) -> *const c_char175 fn read_buf(&self) -> *const c_char { 176 &(self.sz_buff[self.r_pos]) as *const c_char 177 } write_char_usize(&mut self, buf: *const c_char, size: usize) -> bool178 fn write_char_usize(&mut self, buf: *const c_char, size: usize) -> bool { 179 if self.chk_rwerror() { 180 return false; 181 } 182 if buf.is_null() { 183 error!(LOG_LABEL, "Invalid input parameter buf=nullptr errCode:{}", PARAM_INPUT_INVALID); 184 self.rw_error_status = ErrorStatus::Write; 185 return false; 186 } 187 if size == 0 { 188 error!(LOG_LABEL, "Invalid input parameter size={} errCode:{}", size, PARAM_INPUT_INVALID); 189 self.rw_error_status = ErrorStatus::Write; 190 return false; 191 } 192 if (self.w_pos + size) > MAX_STREAM_BUF_SIZE { 193 error!(LOG_LABEL, "The write length exceeds buffer. wIdx:{} size:{} maxBufSize:{} errCode:{}", 194 self.w_pos, size, MAX_STREAM_BUF_SIZE, MEM_OUT_OF_BOUNDS); 195 self.rw_error_status = ErrorStatus::Write; 196 return false; 197 } 198 let pointer = &(self.sz_buff[0]) as *const c_char; 199 // SAFETY: memcpy_s is the security function of the C library 200 let ret = unsafe { 201 binding::memcpy_s(pointer.add(self.w_pos) as *mut libc::c_void, self.get_available_buf_size(), 202 buf as *mut libc::c_void, size) 203 }; 204 if ret != 0 { 205 error!(LOG_LABEL, "Failed to call memcpy_s. ret:{}", ret); 206 self.rw_error_status = ErrorStatus::Write; 207 return false; 208 } 209 self.w_pos += size; 210 self.w_count += 1; 211 true 212 } check_write(&mut self, size: usize) -> bool213 fn check_write(&mut self, size: usize) -> bool { 214 let buffer_size = size; 215 let mut avail_size = self.get_available_buf_size(); 216 if buffer_size > avail_size && self.r_pos > 0 { 217 self.copy_data_to_begin(); 218 avail_size = self.get_available_buf_size(); 219 } 220 avail_size >= buffer_size 221 } copy_data_to_begin(&mut self)222 fn copy_data_to_begin(&mut self) { 223 let unread_size = self.unread_size(); 224 if unread_size > 0 && self.r_pos > 0 { 225 for (index, value) in (self.r_pos..=self.w_pos).enumerate() { 226 self.sz_buff[index] = self.sz_buff[value]; 227 } 228 } 229 debug!(LOG_LABEL, "unread_size:{} rPos:{} wPos:{}", unread_size, self.r_pos, self.w_pos); 230 self.r_pos = 0; 231 self.w_pos = unread_size; 232 } read_char_usize(&mut self, buf: *const c_char, size: usize) -> bool233 fn read_char_usize(&mut self, buf: *const c_char, size: usize) -> bool { 234 if self.chk_rwerror() { 235 return false; 236 } 237 if buf.is_null() { 238 error!(LOG_LABEL, "Invalid input parameter buf=nullptr errCode:{}", PARAM_INPUT_INVALID); 239 self.rw_error_status = ErrorStatus::Read; 240 return false; 241 } 242 if size == 0 { 243 error!(LOG_LABEL, "Invalid input parameter size={} errCode:{}", size, PARAM_INPUT_INVALID); 244 self.rw_error_status = ErrorStatus::Read; 245 return false; 246 } 247 if (self.r_pos + size) > self.w_pos { 248 error!(LOG_LABEL, "Memory out of bounds on read... errCode:{}", MEM_OUT_OF_BOUNDS); 249 self.rw_error_status = ErrorStatus::Read; 250 return false; 251 } 252 // SAFETY: memcpy_s is the security function of the C library 253 let ret = unsafe { 254 binding::memcpy_s(buf as *mut libc::c_void, size, self.read_buf() as *const libc::c_void, size) 255 }; 256 if ret != 0 { 257 error!(LOG_LABEL, "Failed to call memcpy_s. ret:{}", ret); 258 self.rw_error_status = ErrorStatus::Read; 259 return false; 260 } 261 self.r_pos += size; 262 self.r_count += 1; 263 true 264 } circle_write(&mut self, buf: *const c_char, size: usize) -> bool265 fn circle_write(&mut self, buf: *const c_char, size: usize) -> bool { 266 if !self.check_write(size) { 267 error!(LOG_LABEL, "Out of buffer memory, availableSize:{}, size:{}, unreadSize:{}, rPos:{}, wPos:{}", 268 self.get_available_buf_size(), size, self.unread_size(), 269 self.r_pos, self.w_pos); 270 return false; 271 } 272 self.write_char_usize(buf, size) 273 } 274 read_client_packets(&mut self, client: *const CSensorServiceClient, callback_fun: ClientPacketCallBackFun)275 pub unsafe fn read_client_packets(&mut self, client: *const CSensorServiceClient, callback_fun: 276 ClientPacketCallBackFun) { 277 const HEAD_SIZE: usize = size_of::<PackHead>(); 278 for _i in 0..ONCE_PROCESS_NETPACKET_LIMIT { 279 let unread_size = self.unread_size(); 280 if unread_size < HEAD_SIZE { 281 break; 282 } 283 let data_size = unread_size - HEAD_SIZE; 284 let buf: *const c_char = self.read_buf(); 285 if buf.is_null() { 286 error!(LOG_LABEL, "buf is null, skip then break"); 287 break; 288 } 289 let head: *const PackHead = buf as *const PackHead; 290 if head.is_null() { 291 error!(LOG_LABEL, "head is null, skip then break"); 292 break; 293 } 294 // SAFETY: head pointer should be not null certainly 295 let size = unsafe { 296 (*head).size 297 }; 298 // SAFETY: head pointer should be not null certainly 299 let id_msg = unsafe { 300 (*head).id_msg 301 }; 302 if !(0..=MAX_PACKET_BUF_SIZE).contains(&size) { 303 error!(LOG_LABEL, "Packet header parsing error, and this error cannot be recovered. \ 304 The buffer will be reset. size:{}, unreadSize:{}", size, unread_size); 305 self.reset(); 306 break; 307 } 308 if size > data_size { 309 break; 310 } 311 let mut pkt: NetPacket = NetPacket { 312 msg_id: id_msg, 313 ..Default::default() 314 }; 315 unsafe { 316 if size > 0 && 317 !pkt.stream_buffer.write_char_usize(buf.add(HEAD_SIZE) as *const c_char, size) { 318 error!(LOG_LABEL, "Error writing data in the NetPacket. It will be retried next time. \ 319 messageid:{}, size:{}", id_msg as i32, size); 320 break; 321 } 322 } 323 if !self.seek_read_pos(pkt.get_packet_length()) { 324 error!(LOG_LABEL, "Set read position error, and this error cannot be recovered, and the buffer \ 325 will be reset. packetSize:{} unreadSize:{}", pkt.get_packet_length(), unread_size); 326 self.reset(); 327 break; 328 } 329 let c_net_packet: CNetPacket = CNetPacket { 330 msg_id: pkt.msg_id, 331 stream_buffer_ptr: Box::into_raw(Box::new(pkt.stream_buffer)) 332 }; 333 unsafe { 334 callback_fun(client, &c_net_packet as *const CNetPacket); 335 } 336 if self.is_empty() { 337 self.reset(); 338 break; 339 } 340 } 341 } r_count(&self) -> usize342 fn r_count(&self) -> usize { 343 self.r_count 344 } w_count(&self) -> usize345 fn w_count(&self) -> usize { 346 self.w_count 347 } w_pos(&self) -> usize348 fn w_pos(&self) -> usize { 349 self.w_pos 350 } r_pos(&self) -> usize351 fn r_pos(&self) -> usize { 352 self.r_pos 353 } sz_buff(&self) -> *const c_char354 fn sz_buff(&self) -> *const c_char { 355 &self.sz_buff[0] as *const c_char 356 } set_rw_error_status(&mut self, rw_error_status: ErrorStatus)357 fn set_rw_error_status(&mut self, rw_error_status: ErrorStatus) { 358 self.rw_error_status = rw_error_status 359 } set_r_pos(&mut self, r_pos: usize)360 fn set_r_pos(&mut self, r_pos: usize) { 361 self.r_pos = r_pos 362 } 363 } 364 365