mirror of
https://github.com/rustdesk/qemu-display.git
synced 2025-07-01 15:25:29 +00:00
qemu-display: add simple win32-test
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
0728a62a58
commit
e75fbd1539
@ -28,3 +28,10 @@ async-lock = "2.3.0"
|
|||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
uds_windows = "1.0.1"
|
uds_windows = "1.0.1"
|
||||||
windows = { version = "0.39.0", features = ["Win32_Networking_WinSock", "Win32_Foundation", "Win32_System_IO", "Win32_System_Threading"] }
|
windows = { version = "0.39.0", features = ["Win32_Networking_WinSock", "Win32_Foundation", "Win32_System_IO", "Win32_System_Threading"] }
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dev-dependencies]
|
||||||
|
qapi = { version = "0.9.0", features = ["qmp"] }
|
||||||
|
serde = { version = "^1.0.27", features = ["derive"] }
|
||||||
|
base64 = "0.13"
|
||||||
|
async-std = { version = "1.12.0", features = ["attributes"] }
|
||||||
|
tracing-subscriber = { version = "0.3.11", features = ["env-filter" , "fmt"], default-features = false }
|
||||||
|
135
qemu-display/examples/win32-test.rs
Normal file
135
qemu-display/examples/win32-test.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#![allow(non_snake_case, non_camel_case_types)]
|
||||||
|
|
||||||
|
use std::env::args;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::os::windows::io::AsRawSocket;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use qapi::{qmp, Qmp};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uds_windows::UnixStream;
|
||||||
|
use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW};
|
||||||
|
|
||||||
|
use qemu_display::Display;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct get_win32_socket {
|
||||||
|
#[serde(rename = "info")]
|
||||||
|
pub info: ::std::string::String,
|
||||||
|
#[serde(rename = "fdname")]
|
||||||
|
pub fdname: ::std::string::String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl qmp::QmpCommand for get_win32_socket {}
|
||||||
|
impl qapi::Command for get_win32_socket {
|
||||||
|
const NAME: &'static str = "get-win32-socket";
|
||||||
|
const ALLOW_OOB: bool = false;
|
||||||
|
|
||||||
|
type Ok = qapi::Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wsa_last_err() -> std::io::Error {
|
||||||
|
use windows::Win32::Networking::WinSock::WSAGetLastError;
|
||||||
|
|
||||||
|
let err = unsafe { WSAGetLastError() };
|
||||||
|
std::io::Error::from_raw_os_error(err.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the process ID of the connected peer
|
||||||
|
fn unix_stream_get_peer_pid(stream: &UnixStream) -> Result<u32, std::io::Error> {
|
||||||
|
use windows::Win32::Networking::WinSock::{WSAIoctl, IOC_OUT, IOC_VENDOR, SOCKET_ERROR};
|
||||||
|
|
||||||
|
macro_rules! _WSAIOR {
|
||||||
|
($x:expr, $y:expr) => {
|
||||||
|
IOC_OUT | $x | $y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let socket = stream.as_raw_socket();
|
||||||
|
const SIO_AF_UNIX_GETPEERPID: u32 = _WSAIOR!(IOC_VENDOR, 256);
|
||||||
|
let mut ret = 0 as u32;
|
||||||
|
let mut bytes = 0;
|
||||||
|
|
||||||
|
let r = unsafe {
|
||||||
|
WSAIoctl(
|
||||||
|
SOCKET(socket as _),
|
||||||
|
SIO_AF_UNIX_GETPEERPID,
|
||||||
|
0 as *mut _,
|
||||||
|
0,
|
||||||
|
&mut ret as *mut _ as *mut _,
|
||||||
|
std::mem::size_of_val(&ret) as u32,
|
||||||
|
&mut bytes,
|
||||||
|
0 as *mut _,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if r == SOCKET_ERROR {
|
||||||
|
return Err(wsa_last_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn duplicate_socket(pid: u32, sock: SOCKET) -> Result<Vec<u8>, std::io::Error> {
|
||||||
|
let mut info = unsafe { std::mem::zeroed() };
|
||||||
|
if unsafe { WSADuplicateSocketW(sock, pid, &mut info) } != 0 {
|
||||||
|
return Err(wsa_last_err());
|
||||||
|
}
|
||||||
|
let info = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
&info as *const _ as *const u8,
|
||||||
|
std::mem::size_of::<WSAPROTOCOL_INFOW>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Ok(info.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let socket_addr = args().nth(1).expect("argument: QMP socket path");
|
||||||
|
let stream = UnixStream::connect(socket_addr).expect("failed to connect to socket");
|
||||||
|
let pid = unix_stream_get_peer_pid(&stream).expect("failed to get peer PID");
|
||||||
|
|
||||||
|
let mut qmp = Qmp::from_stream(&stream);
|
||||||
|
|
||||||
|
let info = qmp.handshake().expect("handshake failed");
|
||||||
|
println!("QMP info: {:#?}", info);
|
||||||
|
|
||||||
|
let (p0, p1) = UnixStream::pair().expect("failed to make a socketpair");
|
||||||
|
let info =
|
||||||
|
duplicate_socket(pid, SOCKET(p0.as_raw_socket() as _)).expect("Failed to pass socket");
|
||||||
|
let info = base64::encode(info);
|
||||||
|
qmp.execute(&get_win32_socket {
|
||||||
|
info,
|
||||||
|
fdname: "fdname".into(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
qmp.execute(&qmp::add_client {
|
||||||
|
skipauth: None,
|
||||||
|
tls: None,
|
||||||
|
protocol: "@dbus-display".into(),
|
||||||
|
fdname: "fdname".into(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let conn = zbus::ConnectionBuilder::unix_stream(p1)
|
||||||
|
.p2p()
|
||||||
|
.build()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let display = Display::new(&conn, Option::<String>::None).await.unwrap();
|
||||||
|
loop {
|
||||||
|
qmp.nop().unwrap();
|
||||||
|
for event in qmp.events() {
|
||||||
|
println!("Got event: {:#?}", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user