scrcpy-mask/src-tauri/src/socket.rs
2024-04-14 17:15:39 +08:00

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,
}
}
}