feature: support bridge protocol on emulator device

Signed-off-by: liupeng298@huawei.com <liupeng298@huawei.com>
This commit is contained in:
liupeng298@huawei.com 2024-04-09 10:54:04 +08:00
parent 2514e26045
commit 0f71dda6a5
12 changed files with 622 additions and 4 deletions

View File

@ -170,6 +170,7 @@ template("hdcd_source_set") {
if (product_name != "ohos-sdk") {
ohos_static_library("serialize_structs") {
sources = [
"hdc_rust/src/cffi/bridge.cpp",
"hdc_rust/src/cffi/cmd.cpp",
"hdc_rust/src/cffi/getparameter.cpp",
"hdc_rust/src/cffi/log.cpp",
@ -222,6 +223,9 @@ if (product_name != "ohos-sdk") {
"//third_party/rust/crates/log:lib",
"//third_party/rust/crates/rust-openssl/openssl:lib",
]
if (is_emulator && product_name != "ohos-sdk") {
features = [ "emulator" ]
}
external_deps = [
"hilog:hilog_rust",
"ylong_runtime:ylong_runtime",
@ -277,6 +281,9 @@ template("build_hdc") {
output_name = "hdcd_${image_name}"
install_enable = false
features = [ "daemon" ]
if (is_emulator) {
features += [ "emulator" ]
}
subsystem_name = "developtools"
part_name = "hdc"
}

View File

@ -15,6 +15,7 @@ import("//build/ohos.gni")
ohos_static_library("serialize_structs") {
sources = [
"src/cffi/bridge.cpp",
"src/cffi/cmd.cpp",
"src/cffi/getparameter.cpp",
"src/cffi/log.cpp",
@ -68,6 +69,10 @@ ohos_rust_shared_library("lib") {
crate_root = "src/lib.rs"
sources = [ "src/lib.rs" ]
if (is_emulator && product_name != "ohos-sdk") {
features = [ "emulator" ]
}
deps = [
":serialize_structs",
"//third_party/rust/crates/humantime:lib",
@ -109,6 +114,9 @@ ohos_rust_executable("hdcd") {
module_install_dir = "bin"
install_images = [ "system" ]
features = [ "daemon" ]
if (is_emulator) {
features += [ "emulator" ]
}
subsystem_name = "developtools"
part_name = "hdc"
}

View File

@ -0,0 +1,206 @@
/*
* Copyright (C) 2024 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.
*/
#include "bridge.h"
#include "log.h"
#include "sys_para.h"
#include "base.h"
#include <unistd.h>
#include <fcntl.h>
namespace Hdc {
static uint8_t *g_bridgeReadBuf = nullptr;
static constexpr char BRIDGE_FILE_PATH[20] = "/dev/express_bridge";
HdcBridge::HdcBridge()
{
string strBridgePort;
GetDevItem("persist.hdc.port", strBridgePort);
WRITE_LOG(LOG_INFO, "strBridgePort:%s", strBridgePort.c_str());
bridgeListenPort = atoi(strBridgePort.c_str());
if (bridgeListenPort <= 0) {
bridgeListenPort = 0;
}
WRITE_LOG(LOG_INFO, "bridgeListenPort:%d", bridgeListenPort);
}
HdcBridge::~HdcBridge()
{
}
int HdcBridge::StartListen()
{
bridgeFd = open(BRIDGE_FILE_PATH, O_RDWR);
WRITE_LOG(LOG_INFO, "StartListen bridgeFd:%d", bridgeFd);
if (bridgeFd <= 0) {
WRITE_LOG(LOG_FATAL, "SetBridgeListen open failed");
return -1;
}
int ret = ioctl(bridgeFd, IOC_BIND, static_cast<unsigned long>(bridgeListenPort));
WRITE_LOG(LOG_INFO, "StartListen ioctl ret:%d", ret);
if (ret < 0) {
WRITE_LOG(LOG_FATAL, "SetBridgeListen IOC_BIND failed");
return -1;
}
return bridgeFd;
}
int HdcBridge::HandleClient(int socketFd)
{
int newClientFd = open(BRIDGE_FILE_PATH, O_RDWR);
WRITE_LOG(LOG_INFO, "HandleClient newClientFd:%d", newClientFd);
if (newClientFd < 0) {
WRITE_LOG(LOG_FATAL, "Unable to open new bridge connection err %d", errno);
return -1;
}
errno = 0;
int ret = ioctl(newClientFd, IOC_CONNECT, static_cast<unsigned long>(socketFd));
if (ret < 0) {
WRITE_LOG(LOG_FATAL, "Unable to ioctl new bridge err %d", errno);
close(newClientFd);
return -1;
}
return newClientFd;
}
int HdcBridge::ReadPipeFd(int fd, char* buf, int size)
{
WRITE_LOG(LOG_INFO, "ReadPipeFd start");
return read(fd, buf, size);
}
PersistBuffer HdcBridge::ReadClient(int fd, int size)
{
if (g_bridgeReadBuf == nullptr) {
WRITE_LOG(LOG_DEBUG, "remalloc g_bridgeReadBuf");
g_bridgeReadBuf = new uint8_t[MAX_SIZE_IOBUF];
}
int readSize = read(fd, g_bridgeReadBuf, size);
return PersistBuffer{reinterpret_cast<char *>(g_bridgeReadBuf), static_cast<uint64_t>(readSize)};
}
int HdcBridge::WriteClient(int fd, SerializedBuffer buf)
{
uint8_t* ptr = reinterpret_cast<uint8_t *>(buf.ptr);
size_t size = static_cast<size_t>(buf.size);
int cnt = size;
constexpr int intrmax = 1000;
int intrcnt = 0;
while (cnt > 0) {
int rc = write(fd, ptr, cnt);
if (rc < 0) {
int err = errno;
if (err != EINTR && err != EAGAIN) {
WRITE_LOG(LOG_FATAL, "WriteClient fd:%d send rc:%d err:%d", fd, rc, err);
cnt = -1;
break;
}
if (++intrcnt > intrmax) {
WRITE_LOG(LOG_WARN, "WriteClient fd:%d send interrupt err:%d", fd, err);
intrcnt = 0;
}
continue;
}
ptr += rc;
cnt -= rc;
}
return cnt == 0 ? size : cnt;
}
void HdcBridge::Stop()
{
if (bridgeFd > 0) {
close(bridgeFd);
bridgeFd = -1;
}
if (g_bridgeReadBuf != nullptr) {
delete[] g_bridgeReadBuf;
g_bridgeReadBuf = nullptr;
}
}
extern "C" void* InitBridge()
{
HdcBridge* instance = new HdcBridge();
return instance;
}
extern "C" int StartListen(void* ptr)
{
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return -1;
}
return bridge->StartListen();
}
extern "C" int AcceptServerSocketFd(void* ptr, int pipeFd)
{
WRITE_LOG(LOG_INFO, "AcceptServerSocketFd start, pipeFd:%d", pipeFd);
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return -1;
}
char socketFdBuf[4] = { 0 };
int ret = bridge->ReadPipeFd(pipeFd, socketFdBuf, 4);
WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd buf size:%d", ret);
if (ret < 0) {
WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socket fd fail");
return -1;
}
int socketFd = *reinterpret_cast<int*>(socketFdBuf);
WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd:%d", socketFd);
return socketFd;
}
extern "C" int InitClientFd(void* ptr, int socketFd)
{
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return -1;
}
return bridge->HandleClient(socketFd);
}
extern "C" PersistBuffer ReadClient(void* ptr, int fd, int size)
{
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return PersistBuffer{reinterpret_cast<char *>(0), static_cast<uint64_t>(0)};
}
return bridge->ReadClient(fd, size);
}
extern "C" int WriteClient(void* ptr, int fd, SerializedBuffer buf)
{
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return -1;
}
return bridge->WriteClient(fd, buf);
}
extern "C" int Stop(void* ptr)
{
HdcBridge* bridge = (HdcBridge*)ptr;
if (bridge == nullptr) {
return -1;
}
bridge->Stop();
return 0;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 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.
*/
#ifndef HDC_RUST_BRIDGE_H
#define HDC_RUST_BRIDGE_H
#include "arpa/inet.h"
#include "netinet/in.h"
#include "sys/socket.h"
#include <linux/ioctl.h>
#include <sys/ioctl.h>
#include "ffi_utils.h"
namespace Hdc {
#define IOC_MAGIC 0xE6
#define IOC_BIND _IOW(IOC_MAGIC, 1, int)
#define IOC_CONNECT _IOW(IOC_MAGIC, 2, int)
struct PersistBuffer {
char* ptr;
uint64_t size;
};
class HdcBridge {
public:
HdcBridge();
~HdcBridge();
int StartListen();
int HandleClient(int socketFd);
int ReadPipeFd(int fd, char* buf, int size);
PersistBuffer ReadClient(int fd, int size);
int WriteClient(int fd, SerializedBuffer buf);
void Stop();
private:
int bridgeListenPort;
int bridgeFd;
};
}
#endif

View File

@ -34,6 +34,7 @@ use crate::transfer;
use crate::utils::hdc_log::*;
use std::io::Read;
use std::sync::Arc;
use std::time::Duration;
use ylong_runtime::io::AsyncReadExt;
use ylong_runtime::io::AsyncWriteExt;
use ylong_runtime::net::{SplitReadHalf, SplitWriteHalf, TcpListener, TcpStream};
@ -677,6 +678,10 @@ pub async fn setup_jdwp_point(session_id: u32, channel_id: u32) -> bool {
free_context(session_id, channel_id, 0, true).await;
break;
}
if size == 0 {
ylong_runtime::time::sleep(Duration::from_millis(200)).await;
continue;
}
send_to_task(
session_id,
channel_id,

View File

@ -49,6 +49,7 @@ pub enum ConnectType {
Tcp,
Uart,
Bt,
Bridge,
}
pub enum ErrCode {

View File

@ -182,6 +182,7 @@ pub fn get_host_pubkey_info(buf: &str) -> (String, String) {
}
}
#[allow(unused)]
pub async fn get_new_session_id(task_message: &TaskMessage) -> io::Result<u32> {
let mut recv = native_struct::SessionHandShake::default();
recv.parse(task_message.payload.clone())?;

View File

@ -35,24 +35,34 @@ use hdc::common::jdwp;
use hdc::config;
use hdc::config::TaskMessage;
use hdc::transfer;
#[cfg(not(feature = "emulator"))]
use hdc::transfer::uart::UartReader;
#[cfg(not(feature = "emulator"))]
use hdc::transfer::base::Reader;
#[cfg(not(feature = "emulator"))]
use hdc::transfer::uart_wrapper;
use hdc::utils;
use crate::shell::PtyMap;
#[cfg(feature = "emulator")]
use hdc::daemon_lib::bridge;
use log::LevelFilter;
use std::ffi::CString;
#[cfg(not(feature = "emulator"))]
use ylong_runtime::net::{TcpListener, TcpStream};
#[cfg(not(feature = "emulator"))]
use ylong_runtime::sync::mpsc;
#[cfg(not(feature = "emulator"))]
use std::ffi::c_int;
use crate::sys_para::{*};
use crate::auth::clear_auth_pub_key_file;
extern "C" {
#[cfg(not(feature = "emulator"))]
fn NeedDropRootPrivileges()-> c_int;
}
#[cfg(not(feature = "emulator"))]
fn need_drop_root_privileges() {
hdc::info!("need_drop_root_privileges");
unsafe {
@ -83,6 +93,76 @@ async fn jdwp_daemon_start(lock_value: Arc<Jdwp>) {
lock_value.init().await;
}
#[cfg(feature = "emulator")]
async fn bridge_daemon_start() -> io::Result<()> {
hdc::info!("bridge_daemon_start start...");
let ptr = bridge::init_bridge() as u64;
hdc::info!("bridge_daemon_start ptr:{}", ptr);
let pipe_read_fd = bridge::start_listen(ptr);
hdc::info!("bridge_daemon_start pipe_read_fd:{}", pipe_read_fd);
if pipe_read_fd < 0 {
hdc::error!("daemon bridge listen fail.");
return Err(std::io::Error::new(ErrorKind::Other, "daemon bridge listen fail."));
}
loop {
hdc::info!("bridge_daemon_start loop...");
let client_fd_for_hdc_server = bridge::accept_server_socket_fd(ptr, pipe_read_fd);
if client_fd_for_hdc_server < 0 {
hdc::error!("bridge_daemon_start accept client fd for hdc server fail...");
break;
}
let client_fd = bridge::init_client_fd(ptr, client_fd_for_hdc_server);
if client_fd < 0 {
hdc::error!("bridge_daemon_start init client fd fail...");
break;
}
ylong_runtime::spawn(bridge_handle_client(ptr, client_fd, client_fd_for_hdc_server));
}
bridge::stop(ptr);
Ok(())
}
#[cfg(feature = "emulator")]
async fn bridge_handle_client(ptr: u64, fd: i32, client_fd: i32) -> io::Result<()> {
hdc::info!("bridge_handle_client start...");
let rd = bridge::BridgeReader {ptr, fd};
let wr = bridge::BridgeWriter {ptr, fd};
let recv_msg = bridge::unpack_task_message(&rd).await?;
let (session_id, send_msg) = auth::handshake_init(recv_msg).await?;
let channel_id = send_msg.channel_id;
bridge::BridgeMap::start(session_id, wr).await;
transfer::put(session_id, send_msg).await;
if auth::AuthStatusMap::get(session_id).await == auth::AuthStatus::Ok {
transfer::put(
session_id,
TaskMessage {
channel_id,
command: config::HdcCommand::KernelChannelClose,
payload: vec![0],
},
)
.await;
}
loop {
let ret = handle_message(
transfer::tcp::unpack_task_message(&rd).await,
session_id,
)
.await;
if ret.is_err() {
unsafe {
libc::close(fd);
libc::close(client_fd);
}
break;
}
}
Ok(())
}
#[cfg(not(feature = "emulator"))]
async fn tcp_handle_client(stream: TcpStream) -> io::Result<()> {
let (mut rd, wr) = stream.into_split();
let recv_msg = transfer::tcp::unpack_task_message(&mut rd).await?;
@ -113,6 +193,7 @@ async fn tcp_handle_client(stream: TcpStream) -> io::Result<()> {
}
}
#[cfg(not(feature = "emulator"))]
async fn tcp_daemon_start(port: u16) -> io::Result<()> {
let saddr = format!("0.0.0.0:{}", port);
let listener = TcpListener::bind(saddr.clone()).await?;
@ -124,6 +205,7 @@ async fn tcp_daemon_start(port: u16) -> io::Result<()> {
}
}
#[cfg(not(feature = "emulator"))]
async fn uart_daemon_start() -> io::Result<()> {
loop {
let fd = transfer::uart::uart_init()?;
@ -132,6 +214,7 @@ async fn uart_daemon_start() -> io::Result<()> {
}
}
#[cfg(not(feature = "emulator"))]
async fn uart_handshake(
handshake_message: TaskMessage,
fd: i32,
@ -163,6 +246,7 @@ async fn uart_handshake(
Ok(session_id)
}
#[cfg(not(feature = "emulator"))]
async fn uart_handle_client(fd: i32) -> io::Result<()> {
let mut rd = transfer::uart::UartReader { fd, head: None };
let (packet_size, package_index) = rd.check_protocol_head()?;
@ -242,8 +326,9 @@ async fn uart_handle_client(fd: i32) -> io::Result<()> {
}
}
}
}
}
#[cfg(not(feature = "emulator"))]
async fn usb_daemon_start() -> io::Result<()> {
loop {
let ret = transfer::usb::usb_init();
@ -260,6 +345,7 @@ async fn usb_daemon_start() -> io::Result<()> {
}
}
#[cfg(not(feature = "emulator"))]
async fn usb_handle_client(_config_fd: i32, bulkin_fd: i32, bulkout_fd: i32) -> io::Result<()> {
let _rd = transfer::usb::UsbReader { fd: bulkin_fd };
let wr = transfer::usb::UsbWriter { fd: bulkout_fd };
@ -365,6 +451,7 @@ fn get_logger_lv() -> LevelFilter {
config::LOG_LEVEL_ORDER[lv]
}
#[cfg(not(feature = "emulator"))]
fn get_tcp_port() -> u16 {
let (ret, host_port) = get_dev_item(config::ENV_HOST_PORT, "_");
if !ret || host_port == "_" {
@ -408,32 +495,49 @@ fn main() {
.keep_alive_time(std::time::Duration::from_secs(10))
.build_global();
#[cfg(not(feature = "emulator"))]
need_drop_root_privileges();
clear_auth_pub_key_file();
ylong_runtime::block_on(async {
#[cfg(not(feature = "emulator"))]
let tcp_task = ylong_runtime::spawn(async {
if let Err(e) = tcp_daemon_start(get_tcp_port()).await {
println!("[Fail]tcp daemon failed: {}", e);
}
});
#[cfg(not(feature = "emulator"))]
let usb_task = ylong_runtime::spawn(async {
if let Err(e) = usb_daemon_start().await {
println!("[Fail]usb daemon failed: {}", e);
}
});
#[cfg(not(feature = "emulator"))]
let uart_task = ylong_runtime::spawn(async {
if let Err(e) = uart_daemon_start().await {
println!("[Fail]uart daemon failed: {}", e);
}
});
#[cfg(feature = "emulator")]
hdc::info!("daemon main emulator, start bridge daemon.");
#[cfg(feature = "emulator")]
let bridge_task = ylong_runtime::spawn(async {
if let Err(e) = bridge_daemon_start().await {
println!("[Fail]bridge daemon failed: {}", e);
}
});
let lock_value = Jdwp::get_instance();
let jdwp_server_task = ylong_runtime::spawn(async {
jdwp_daemon_start(lock_value).await;
});
#[cfg(not(feature = "emulator"))]
let _ = tcp_task.await;
#[cfg(not(feature = "emulator"))]
let _ = usb_task.await;
#[cfg(not(feature = "emulator"))]
let _ = uart_task.await;
#[cfg(feature = "emulator")]
let _ = bridge_task.await;
let _ = jdwp_server_task.await;
});
}

View File

@ -0,0 +1,17 @@
/*
* Copyright (C) 2024 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.
*/
//! daemon_lib
pub mod bridge;

View File

@ -0,0 +1,209 @@
/*
* Copyright (C) 2024 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.
*/
//! bridge
use crate::transfer::base;
#[allow(unused)]
use crate::config::*;
#[allow(unused)]
use crate::serializer;
use crate::utils;
#[allow(unused)]
use crate::utils::hdc_log::*;
#[allow(unused)]
use crate::serializer::serialize::Serialization;
use crate::serializer::serialize::SerializedBuffer;
#[allow(unused)]
use std::io::{self, Error, ErrorKind};
use crate::transfer::buffer::ConnectTypeMap;
use ylong_runtime::sync::{Mutex, RwLock};
use std::collections::HashMap;
use std::sync::Arc;
use crate::transfer::base::Writer;
#[repr(C)]
pub struct PersistBuffer {
pub ptr: *const libc::c_char,
pub size: libc::c_ulonglong,
}
#[allow(unused)]
pub fn buf_to_vec(buf: PersistBuffer) -> Vec<u8> {
let slice =
unsafe { std::slice::from_raw_parts(buf.ptr as *const libc::c_uchar, buf.size as usize) };
slice.to_vec()
}
#[allow(unused)]
extern "C" {
fn InitBridge() -> *mut libc::c_void;
fn StartListen(ptr: *mut libc::c_void) -> libc::c_int;
fn AcceptServerSocketFd(ptr: *mut libc::c_void, pipeFd: i32) -> libc::c_int;
fn InitClientFd(ptr: *mut libc::c_void, socketFd: i32) -> libc::c_int;
fn ReadClient(ptr: *mut libc::c_void, fd: i32, excepted_size: i32) -> PersistBuffer;
fn WriteClient(ptr: *mut libc::c_void, fd: i32, buf: SerializedBuffer) -> libc::c_int;
fn Stop(ptr: *mut libc::c_void) -> libc::c_int;
}
#[allow(unused)]
pub fn init_bridge() -> *mut libc::c_void {
unsafe {
InitBridge()
}
}
#[allow(unused)]
pub fn start_listen(ptr: u64) -> i32 {
unsafe {
StartListen(ptr as *mut libc::c_void)
}
}
#[allow(unused)]
pub fn accept_server_socket_fd(ptr: u64, pipe_fd: i32) -> i32 {
unsafe {
AcceptServerSocketFd(
ptr as *mut libc::c_void,
pipe_fd
)
}
}
#[allow(unused)]
pub fn init_client_fd(ptr: u64, socket_fd: i32) -> i32 {
unsafe {
InitClientFd(
ptr as *mut libc::c_void,
socket_fd
)
}
}
#[allow(unused)]
pub fn write_client(ptr: u64, fd: i32, buf: SerializedBuffer) -> i32 {
unsafe {
WriteClient(ptr as *mut libc::c_void, fd, buf)
}
}
#[allow(unused)]
pub fn read_client(ptr: u64, fd: i32, excepted_size: i32) -> PersistBuffer {
unsafe {
ReadClient(ptr as *mut libc::c_void, fd, excepted_size)
}
}
#[allow(unused)]
pub fn stop(ptr: u64) -> i32 {
unsafe {
Stop(ptr as *mut libc::c_void)
}
}
pub struct BridgeReader {
pub ptr: u64,
pub fd: i32,
}
pub struct BridgeWriter {
pub ptr: u64,
pub fd: i32,
}
impl base::Reader for BridgeReader {
fn read_frame(&self, _expected_size: usize) -> io::Result<Vec<u8>> {
let buf = read_client(self.ptr, self.fd, _expected_size as i32);
if buf.size == 0 {
crate::warn!("bridge read result <= 0");
return Err(utils::error_other("bridge read error".to_string()));
}
Ok(buf_to_vec(buf))
}
fn check_protocol_head(&mut self) -> io::Result<(u32, u32)> {
Ok((0, 0))
}
}
impl base::Writer for BridgeWriter {
fn write_all(&self, data: Vec<u8>) -> io::Result<()> {
let buf = SerializedBuffer {
ptr: data.as_ptr() as *const libc::c_char,
size: data.len() as u64,
};
if write_client(self.ptr, self.fd, buf) <= 0 {
Err(utils::error_other("usb write failed".to_string()))
} else {
Ok(())
}
}
}
type BridgeWriter_ = Arc<Mutex<BridgeWriter>>;
type BridgeMap_ = Arc<RwLock<HashMap<u32, BridgeWriter_>>>;
pub struct BridgeMap {}
impl BridgeMap {
fn get_instance() -> BridgeMap_ {
static mut BRIDGE_MAP: Option<BridgeMap_> = None;
unsafe {
BRIDGE_MAP
.get_or_insert_with(|| Arc::new(RwLock::new(HashMap::new())))
.clone()
}
}
pub async fn put(session_id: u32, data: TaskMessage) {
let send = serializer::concat_pack(data);
let instance = Self::get_instance();
let map = instance.read().await;
let arc_wr = map.get(&session_id).unwrap();
let wr = arc_wr.lock().await;
let _ = wr.write_all(send);
}
pub async fn send_channel_message(channel_id: u32, buf: Vec<u8>) -> io::Result<()> {
crate::trace!("send channel msg: {:#?}", buf.clone());
let send = [
u32::to_be_bytes(buf.len() as u32).as_slice(),
buf.as_slice(),
]
.concat();
let instance = Self::get_instance();
let map = instance.read().await;
if let Some(guard) = map.get(&channel_id) {
let wr = guard.lock().await;
let _ = wr.write_all(send);
return Ok(());
}
Err(Error::new(ErrorKind::NotFound, "channel not found"))
}
pub async fn start(id: u32, wr: BridgeWriter) {
let instance = Self::get_instance();
let mut map = instance.write().await;
let arc_wr = Arc::new(Mutex::new(wr));
map.insert(id, arc_wr);
ConnectTypeMap::put(id, ConnectType::Bridge).await;
}
pub async fn end(id: u32) {
let instance = Self::get_instance();
let mut map = instance.write().await;
if let Some(arc_wr) = map.remove(&id) {
let mut _wr = arc_wr.lock().await;
}
}
}

View File

@ -21,3 +21,5 @@ pub mod config;
pub mod serializer;
pub mod transfer;
pub mod utils;
#[cfg(feature = "emulator")]
pub mod daemon_lib;

View File

@ -19,6 +19,8 @@ use super::base::{self, Writer};
use super::uart::UartWriter;
use super::usb::{self, UsbReader, UsbWriter};
use super::{tcp, uart_wrapper};
#[cfg(feature = "emulator")]
use crate::daemon_lib::bridge::BridgeMap;
use crate::config::TaskMessage;
use crate::config::{self, ConnectType};
@ -36,7 +38,7 @@ use ylong_runtime::sync::{mpsc, Mutex, RwLock};
type ConnectTypeMap_ = Arc<RwLock<HashMap<u32, ConnectType>>>;
struct ConnectTypeMap {}
pub struct ConnectTypeMap {}
impl ConnectTypeMap {
fn get_instance() -> ConnectTypeMap_ {
static mut CONNECT_TYPE_MAP: Option<ConnectTypeMap_> = None;
@ -47,13 +49,13 @@ impl ConnectTypeMap {
}
}
async fn put(session_id: u32, conn_type: ConnectType) {
pub async fn put(session_id: u32, conn_type: ConnectType) {
let arc_map = Self::get_instance();
let mut map = arc_map.write().await;
map.insert(session_id, conn_type);
}
async fn get(session_id: u32) -> ConnectType {
pub async fn get(session_id: u32) -> ConnectType {
let arc_map = Self::get_instance();
let map = arc_map.read().await;
map.get(&session_id).unwrap().clone()
@ -208,6 +210,10 @@ pub async fn put(session_id: u32, data: TaskMessage) {
uart_wrapper::wrap_put(session_id, data, 0, 0).await;
}
ConnectType::Bt => {}
ConnectType::Bridge => {
#[cfg(feature = "emulator")]
BridgeMap::put(session_id, data).await;
}
}
}