mirror of
https://gitee.com/openharmony/developtools_hdc
synced 2024-12-03 12:53:29 +00:00
feature: support bridge protocol on emulator device
Signed-off-by: liupeng298@huawei.com <liupeng298@huawei.com>
This commit is contained in:
parent
2514e26045
commit
0f71dda6a5
7
BUILD.gn
7
BUILD.gn
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
206
hdc_rust/src/cffi/bridge.cpp
Normal file
206
hdc_rust/src/cffi/bridge.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
52
hdc_rust/src/cffi/bridge.h
Normal file
52
hdc_rust/src/cffi/bridge.h
Normal 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
|
@ -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,
|
||||
|
@ -49,6 +49,7 @@ pub enum ConnectType {
|
||||
Tcp,
|
||||
Uart,
|
||||
Bt,
|
||||
Bridge,
|
||||
}
|
||||
|
||||
pub enum ErrCode {
|
||||
|
@ -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())?;
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
17
hdc_rust/src/daemon_lib.rs
Normal file
17
hdc_rust/src/daemon_lib.rs
Normal 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;
|
209
hdc_rust/src/daemon_lib/bridge.rs
Normal file
209
hdc_rust/src/daemon_lib/bridge.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,3 +21,5 @@ pub mod config;
|
||||
pub mod serializer;
|
||||
pub mod transfer;
|
||||
pub mod utils;
|
||||
#[cfg(feature = "emulator")]
|
||||
pub mod daemon_lib;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user