mirror of
https://github.com/AkiChase/scrcpy-mask
synced 2025-02-23 07:22:17 +08:00
225 lines
7.2 KiB
Rust
225 lines
7.2 KiB
Rust
use std::sync::Arc;
|
|
|
|
use anyhow::Context;
|
|
use serde_json::json;
|
|
use tokio::{
|
|
io::AsyncReadExt,
|
|
net::{
|
|
tcp::{OwnedReadHalf, OwnedWriteHalf},
|
|
TcpStream,
|
|
},
|
|
};
|
|
|
|
use crate::{
|
|
control_msg::{self, ControlMsgType},
|
|
scrcpy_mask_cmd::{self, ScrcpyMaskCmdType},
|
|
};
|
|
|
|
pub async fn connect_socket(
|
|
address: String,
|
|
front_msg_receiver: tokio::sync::mpsc::Receiver<String>,
|
|
device_reply_sender: tokio::sync::mpsc::Sender<String>,
|
|
listen_handler: u32,
|
|
app: Arc<tauri::AppHandle>,
|
|
) -> anyhow::Result<()> {
|
|
|
|
let client = TcpStream::connect(address)
|
|
.await
|
|
.context("Socket connect failed")?;
|
|
|
|
println!("成功连接scrcpy-server:{:?}", client.local_addr());
|
|
|
|
let (read_half, write_half) = client.into_split();
|
|
|
|
// 开启线程读取设备发送的信息,并通过通道传递到与前端通信的线程,最后与前端通信的线程发送全局事件,告知前端设备发送的信息
|
|
tokio::spawn(async move {
|
|
read_socket(read_half, device_reply_sender).await;
|
|
});
|
|
|
|
// 开启线程接收通道消息,其中通道消息来自前端发送的事件
|
|
tokio::spawn(async move {
|
|
recv_front_msg(write_half, front_msg_receiver, listen_handler, app).await;
|
|
});
|
|
anyhow::Ok(())
|
|
}
|
|
|
|
// 从客户端读取
|
|
async fn read_socket(
|
|
mut reader: OwnedReadHalf,
|
|
device_reply_sender: tokio::sync::mpsc::Sender<String>,
|
|
) {
|
|
// read dummy byte
|
|
let mut buf: [u8; 1] = [0; 1];
|
|
if let Err(_e) = reader.read_exact(&mut buf).await {
|
|
eprintln!("failed to read dummy byte");
|
|
return;
|
|
}
|
|
|
|
// read metadata (device name)
|
|
let mut buf: [u8; 64] = [0; 64];
|
|
match reader.read(&mut buf).await {
|
|
Err(_e) => {
|
|
eprintln!("failed to read metadata");
|
|
return;
|
|
}
|
|
Ok(0) => {
|
|
eprintln!("failed to read metadata");
|
|
return;
|
|
}
|
|
Ok(n) => {
|
|
let mut end = n;
|
|
while buf[end - 1] == 0 {
|
|
end -= 1;
|
|
}
|
|
let device_name = std::str::from_utf8(&buf[..end]).unwrap();
|
|
let msg = json!({
|
|
"type": "MetaData",
|
|
"deviceName": device_name,
|
|
})
|
|
.to_string();
|
|
device_reply_sender.send(msg).await.unwrap();
|
|
}
|
|
};
|
|
|
|
loop {
|
|
match reader.read_u8().await {
|
|
Err(e) => {
|
|
eprintln!(
|
|
"Failed to read from scrcpy server, maybe it was closed. Error:{}",
|
|
e
|
|
);
|
|
println!("Drop TcpStream reader");
|
|
drop(reader);
|
|
return;
|
|
}
|
|
Ok(message_type) => {
|
|
let message_type = match DeviceMsgType::from_u8(message_type) {
|
|
Some(t) => t,
|
|
None => {
|
|
println!("Ignore unkonw message type: {}", message_type);
|
|
continue;
|
|
}
|
|
};
|
|
if let Err(e) =
|
|
handle_device_message(message_type, &mut reader, &device_reply_sender).await
|
|
{
|
|
eprintln!("Failed to handle device message: {}", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn handle_device_message(
|
|
message_type: DeviceMsgType,
|
|
reader: &mut OwnedReadHalf,
|
|
device_reply_sender: &tokio::sync::mpsc::Sender<String>,
|
|
) -> anyhow::Result<()> {
|
|
match message_type {
|
|
// 设备剪切板变动
|
|
DeviceMsgType::DeviceMsgTypeClipboard => {
|
|
let text_length = reader.read_u32().await?;
|
|
let mut buf: Vec<u8> = vec![0; text_length as usize];
|
|
reader.read_exact(&mut buf).await?;
|
|
let cb = String::from_utf8(buf)?;
|
|
let msg = json!({
|
|
"type": "ClipboardChanged",
|
|
"clipboard": cb
|
|
})
|
|
.to_string();
|
|
device_reply_sender.send(msg).await?;
|
|
}
|
|
// 设备剪切板设置成功的回复
|
|
DeviceMsgType::DeviceMsgTypeAckClipboard => {
|
|
let sequence = reader.read_u64().await?;
|
|
let msg = json!({
|
|
"type": "ClipboardSetAck",
|
|
"sequence": sequence
|
|
})
|
|
.to_string();
|
|
device_reply_sender.send(msg).await?;
|
|
}
|
|
// 虚拟设备输出,仅读取但不做进一步处理
|
|
DeviceMsgType::DeviceMsgTypeUhidOutput => {
|
|
let _id = reader.read_u16().await?;
|
|
let size = reader.read_u16().await?;
|
|
let mut buf: Vec<u8> = vec![0; size as usize];
|
|
reader.read_exact(&mut buf).await?;
|
|
}
|
|
};
|
|
anyhow::Ok(())
|
|
}
|
|
|
|
// 接收前端发送的消息,执行相关操作
|
|
async fn recv_front_msg(
|
|
mut write_half: OwnedWriteHalf,
|
|
mut front_msg_receiver: tokio::sync::mpsc::Receiver<String>,
|
|
listen_handler: u32,
|
|
app: Arc<tauri::AppHandle>,
|
|
) {
|
|
while let Some(msg) = front_msg_receiver.recv().await {
|
|
match serde_json::from_str::<serde_json::Value>(&msg) {
|
|
Err(_e) => {
|
|
println!("无法解析的Json数据: {}", msg);
|
|
}
|
|
Ok(payload) => {
|
|
if let Some(front_msg_type) = payload["msgType"].as_i64() {
|
|
// 发送原始控制信息
|
|
if front_msg_type >= 0 && front_msg_type <= 14 {
|
|
let ctrl_msg_type = ControlMsgType::from_i64(front_msg_type).unwrap();
|
|
control_msg::send_ctrl_msg(
|
|
ctrl_msg_type,
|
|
&payload["msgData"],
|
|
&mut write_half,
|
|
)
|
|
.await;
|
|
continue;
|
|
} else {
|
|
// 处理Scrcpy Mask命令
|
|
if let Some(cmd_type) = ScrcpyMaskCmdType::from_i64(front_msg_type) {
|
|
if let ScrcpyMaskCmdType::Shutdown = cmd_type {
|
|
drop(write_half);
|
|
println!("Drop TcpStream writer");
|
|
app.unlisten(listen_handler);
|
|
println!("front msg channel closed");
|
|
return;
|
|
}
|
|
|
|
scrcpy_mask_cmd::handle_sm_cmd(
|
|
cmd_type,
|
|
&payload["msgData"],
|
|
&mut write_half,
|
|
)
|
|
.await
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
eprintln!("fc-command非法");
|
|
eprintln!("{:?}", payload);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
println!("font msg channel closed");
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum DeviceMsgType {
|
|
DeviceMsgTypeClipboard,
|
|
DeviceMsgTypeAckClipboard,
|
|
DeviceMsgTypeUhidOutput,
|
|
}
|
|
|
|
impl DeviceMsgType {
|
|
fn from_u8(value: u8) -> Option<Self> {
|
|
match value {
|
|
0 => Some(Self::DeviceMsgTypeClipboard),
|
|
1 => Some(Self::DeviceMsgTypeAckClipboard),
|
|
2 => Some(Self::DeviceMsgTypeUhidOutput),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|