• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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