* Copyright (C) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#![allow(missing_docs)]
extern crate libc;
use crate::serializer::native_struct::{FileMode, TransferConfig, TransferPayload};
use crate::serializer::native_struct::{PayloadHead, PayloadProtect, SessionHandShake};
use crate::serializer::pack_struct::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::io::{self, Error, ErrorKind};
use super::native_struct::UartHead;
use super::native_struct::UsbHead;
#[repr(C)]
pub struct SerializedBuffer {
pub ptr: *const libc::c_char,
pub size: libc::c_ulonglong,
}
impl Drop for SerializedBuffer {
fn drop(&mut self) {
unsafe {
free(self.ptr.cast());
}
}
}
pub struct RawPayload {
pub bytes: Vec<u8>,
}
extern "C" {
fn free(ptr: *const libc::c_void);
fn SerializeSessionHandShake(value: *const SessionHandShakePack) -> SerializedBuffer;
fn SerializePayloadProtect(value: *const PayloadProtectPack) -> SerializedBuffer;
fn SerializeTransferConfig(value: *const TransferConfigPack) -> SerializedBuffer;
fn SerializeFileMode(value: *const FileModePack) -> SerializedBuffer;
fn SerializeTransferPayload(value: *const TransferPayloadPack) -> SerializedBuffer;
fn SerializePayloadHead(value: *const PayloadHeadPack) -> SerializedBuffer;
fn SerializeUsbHead(value: *const UsbHeadPack) -> SerializedBuffer;
fn SerializeUartHead(value: *const UartHeadPack) -> SerializedBuffer;
fn ParseSessionHandShake(
value: *mut SessionHandShakePack,
buf: SerializedBuffer,
) -> libc::c_uchar;
fn ParsePayloadProtect(value: *mut PayloadProtectPack, buf: SerializedBuffer) -> libc::c_uchar;
fn ParseTransferConfig(value: *mut TransferConfigPack, buf: SerializedBuffer) -> libc::c_uchar;
fn ParseFileMode(value: *mut FileModePack, buf: SerializedBuffer) -> libc::c_uchar;
fn ParseTransferPayload(
value: *mut TransferPayloadPack,
buf: SerializedBuffer,
) -> libc::c_uchar;
fn ParsePayloadHead(value: *mut PayloadHeadPack, buf: SerializedBuffer) -> libc::c_uchar;
fn ParseUsbHead(value: *mut UsbHeadPack, buf: SerializedBuffer) -> libc::c_uchar;
fn ParseUartHead(value: *mut UartHeadPack, buf: SerializedBuffer) -> libc::c_uchar;
}
pub trait Serialization {
fn serialize(&self) -> Vec<u8>;
fn parse(&mut self, _: Vec<u8>) -> io::Result<()> {
Ok(())
}
}
impl Serialization for RawPayload {
fn serialize(&self) -> Vec<u8> {
self.bytes.clone()
}
}
impl Serialization for SessionHandShake {
fn serialize(&self) -> Vec<u8> {
let banner = CString::new(self.banner.as_str()).unwrap();
let connect_key = CString::new(self.connect_key.as_str()).unwrap();
let buf = CString::new(self.buf.as_str()).unwrap();
let version = CString::new(self.version.as_str()).unwrap();
let pack = SessionHandShakePack {
banner: banner.as_ptr(),
auth_type: self.auth_type,
session_id: self.session_id,
connect_key: connect_key.as_ptr(),
buf: buf.as_ptr(),
version: version.as_ptr(),
};
let buf = unsafe { SerializeSessionHandShake(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = SessionHandShakePack {
banner: std::ptr::null(),
auth_type: 0,
session_id: 0,
connect_key: std::ptr::null(),
buf: std::ptr::null(),
version: std::ptr::null(),
};
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseSessionHandShake(&mut pack, buf) } == 0 {
return Err(Error::new(
ErrorKind::Other,
"cffi ParseSessionHandShake failed",
));
}
self.banner = ptr_to_string(pack.banner);
self.auth_type = pack.auth_type;
self.session_id = pack.session_id;
self.connect_key = ptr_to_string(pack.connect_key);
self.buf = ptr_to_string(pack.buf);
self.version = ptr_to_string(pack.version);
Ok(())
}
}
impl Serialization for PayloadProtect {
fn serialize(&self) -> Vec<u8> {
let pack = PayloadProtectPack {
channel_id: self.channel_id,
command_flag: self.command_flag,
check_sum: self.check_sum,
v_code: self.v_code,
};
let buf = unsafe { SerializePayloadProtect(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = PayloadProtectPack::default();
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParsePayloadProtect(&mut pack, buf) } == 0 {
return Err(Error::new(
ErrorKind::Other,
"cffi ParsePayloadProtect failed",
));
}
self.channel_id = pack.channel_id;
self.command_flag = pack.command_flag;
self.check_sum = pack.check_sum;
self.v_code = pack.v_code;
Ok(())
}
}
impl Serialization for TransferConfig {
fn serialize(&self) -> Vec<u8> {
let options = CString::new(self.options.as_str()).unwrap();
let path = CString::new(self.path.as_str()).unwrap();
let optional_name = CString::new(self.optional_name.as_str()).unwrap();
let function_name = CString::new(self.function_name.as_str()).unwrap();
let client_cwd = CString::new(self.client_cwd.as_str()).unwrap();
let reserve1 = CString::new(self.reserve1.as_str()).unwrap();
let reserve2 = CString::new(self.reserve2.as_str()).unwrap();
let pack = TransferConfigPack {
file_size: self.file_size,
atime: self.atime,
mtime: self.mtime,
options: options.as_ptr(),
path: path.as_ptr(),
optional_name: optional_name.as_ptr(),
update_if_new: self.update_if_new as u8,
compress_type: self.compress_type,
hold_timestamp: self.hold_timestamp as u8,
function_name: function_name.as_ptr(),
client_cwd: client_cwd.as_ptr(),
reserve1: reserve1.as_ptr(),
reserve2: reserve2.as_ptr(),
};
let buf = unsafe { SerializeTransferConfig(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = TransferConfigPack {
file_size: 0,
atime: 0,
mtime: 0,
options: std::ptr::null(),
path: std::ptr::null(),
optional_name: std::ptr::null(),
update_if_new: 0,
compress_type: 0,
hold_timestamp: 0,
function_name: std::ptr::null(),
client_cwd: std::ptr::null(),
reserve1: std::ptr::null(),
reserve2: std::ptr::null(),
};
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseTransferConfig(&mut pack, buf) } == 0 {
return Err(Error::new(
ErrorKind::Other,
"cffi ParseTransferConfig failed",
));
}
self.file_size = pack.file_size;
self.atime = pack.atime;
self.mtime = pack.mtime;
self.options = ptr_to_string(pack.options);
self.path = ptr_to_string(pack.path);
self.optional_name = ptr_to_string(pack.optional_name);
self.update_if_new = pack.update_if_new > 0;
self.compress_type = pack.compress_type;
self.hold_timestamp = pack.hold_timestamp > 0;
self.function_name = ptr_to_string(pack.function_name);
self.client_cwd = ptr_to_string(pack.client_cwd);
self.reserve1 = ptr_to_string(pack.reserve1);
self.reserve2 = ptr_to_string(pack.reserve2);
Ok(())
}
}
impl Serialization for FileMode {
fn serialize(&self) -> Vec<u8> {
let context = CString::new(self.context.as_str()).unwrap();
let full_name = CString::new(self.full_name.as_str()).unwrap();
let pack = FileModePack {
perm: self.perm,
u_id: self.u_id,
g_id: self.g_id,
context: context.as_ptr(),
full_name: full_name.as_ptr(),
};
let buf = unsafe { SerializeFileMode(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = FileModePack {
perm: 0,
u_id: 0,
g_id: 0,
context: std::ptr::null(),
full_name: std::ptr::null(),
};
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseFileMode(&mut pack, buf) } == 0 {
return Err(Error::new(ErrorKind::Other, "cffi ParseFileMode failed"));
}
self.perm = pack.perm;
self.u_id = pack.u_id;
self.g_id = pack.g_id;
self.context = ptr_to_string(pack.context);
self.full_name = ptr_to_string(pack.full_name);
Ok(())
}
}
impl Serialization for TransferPayload {
fn serialize(&self) -> Vec<u8> {
let pack = TransferPayloadPack {
index: self.index,
compress_type: self.compress_type,
compress_size: self.compress_size,
uncompress_size: self.uncompress_size,
};
let buf = unsafe { SerializeTransferPayload(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = TransferPayloadPack::default();
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseTransferPayload(&mut pack, buf) } == 0 {
return Err(Error::new(
ErrorKind::Other,
"cffi ParseTransferPayload failed",
));
}
self.index = pack.index;
self.compress_type = pack.compress_type;
self.compress_size = pack.compress_size;
self.uncompress_size = pack.uncompress_size;
Ok(())
}
}
impl Serialization for PayloadHead {
fn serialize(&self) -> Vec<u8> {
let pack = PayloadHeadPack {
flag: self.flag,
reserve: self.reserve,
protocol_ver: self.protocol_ver,
head_size: self.head_size,
data_size: self.data_size,
};
let buf = unsafe { SerializePayloadHead(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = PayloadHeadPack::default();
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParsePayloadHead(&mut pack, buf) == 0 } {
return Err(Error::new(ErrorKind::Other, "cffi ParsePayloadHead failed"));
}
self.flag = pack.flag;
self.reserve = pack.reserve;
self.protocol_ver = pack.protocol_ver;
self.head_size = pack.head_size;
self.data_size = pack.data_size;
Ok(())
}
}
impl Serialization for UsbHead {
fn serialize(&self) -> Vec<u8> {
let pack = UsbHeadPack {
flag: self.flag,
option: self.option,
session_id: self.session_id,
data_size: self.data_size,
};
let buf = unsafe { SerializeUsbHead(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = UsbHeadPack::default();
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseUsbHead(&mut pack, buf) == 0 } {
return Err(Error::new(ErrorKind::Other, "cffi ParseUsbHead failed"));
}
self.flag = pack.flag;
self.option = pack.option;
self.session_id = pack.session_id;
self.data_size = pack.data_size;
Ok(())
}
}
impl Serialization for UartHead {
fn serialize(&self) -> Vec<u8> {
let pack = UartHeadPack {
flag: self.flag,
option: self.option,
session_id: self.session_id,
data_size: self.data_size,
package_index: self.package_index,
data_checksum: self.data_checksum,
head_checksum: self.head_checksum,
};
let buf = unsafe { SerializeUartHead(&pack) };
buf_to_vec(buf)
}
fn parse(&mut self, input: Vec<u8>) -> io::Result<()> {
let mut pack = UartHeadPack::default();
let buf = SerializedBuffer {
ptr: input.as_ptr() as *const libc::c_char,
size: input.len() as u64,
};
if unsafe { ParseUartHead(&mut pack, buf) == 0 } {
return Err(Error::new(ErrorKind::Other, "cffi ParseUartHead failed"));
}
self.flag = pack.flag;
self.option = pack.option;
self.session_id = pack.session_id;
self.data_size = pack.data_size;
self.package_index = pack.package_index;
self.data_checksum = pack.data_checksum;
self.head_checksum = pack.head_checksum;
Ok(())
}
}
fn ptr_to_string(p: *const libc::c_char) -> String {
let c_str: &CStr = unsafe { CStr::from_ptr(p) };
c_str.to_str().unwrap().to_string()
}
pub fn buf_to_vec(buf: SerializedBuffer) -> Vec<u8> {
let slice =
unsafe { std::slice::from_raw_parts(buf.ptr as *const libc::c_uchar, buf.size as usize) };
slice.to_vec()
}