portable-service: exchange ipc server/client

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-11-11 11:40:23 +08:00
parent e186eec5df
commit 9f73b89f21
4 changed files with 239 additions and 281 deletions

View File

@ -429,31 +429,31 @@ impl Connection {
_ = second_timer.tick() => { _ = second_timer.tick() => {
#[cfg(windows)] #[cfg(windows)]
{ {
use crate::portable_service::client::{PORTABLE_SERVICE_STATUS, PortableServiceStatus::*};
let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone();
if last_uac != uac {
last_uac = uac;
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == NotStarted {
let mut misc = Misc::new();
misc.set_uac(uac);
let mut msg = Message::new();
msg.set_misc(misc);
conn.inner.send(msg.into());
}
}
let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap().clone();
if last_foreground_window_elevated != foreground_window_elevated {
last_foreground_window_elevated = foreground_window_elevated;
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == NotStarted {
let mut misc = Misc::new();
misc.set_foreground_window_elevated(foreground_window_elevated);
let mut msg = Message::new();
msg.set_misc(misc);
conn.inner.send(msg.into());
}
}
if !is_installed { if !is_installed {
let show_elevation = PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == NotStarted; let portable_service_running = crate::portable_service::client::PORTABLE_SERVICE_RUNNING.lock().unwrap().clone();
let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone();
if last_uac != uac {
last_uac = uac;
if !portable_service_running {
let mut misc = Misc::new();
misc.set_uac(uac);
let mut msg = Message::new();
msg.set_misc(misc);
conn.inner.send(msg.into());
}
}
let foreground_window_elevated = crate::video_service::IS_FOREGROUND_WINDOW_ELEVATED.lock().unwrap().clone();
if last_foreground_window_elevated != foreground_window_elevated {
last_foreground_window_elevated = foreground_window_elevated;
if !portable_service_running {
let mut misc = Misc::new();
misc.set_foreground_window_elevated(foreground_window_elevated);
let mut msg = Message::new();
msg.set_misc(misc);
conn.inner.send(msg.into());
}
}
let show_elevation = !portable_service_running;
conn.send_to_cm(ipc::Data::DataPortableService(ipc::DataPortableService::CmShowElevation(show_elevation))); conn.send_to_cm(ipc::Data::DataPortableService(ipc::DataPortableService::CmShowElevation(show_elevation)));
} }

View File

@ -7,7 +7,6 @@ use hbb_common::{
log, log,
message_proto::{KeyEvent, MouseEvent}, message_proto::{KeyEvent, MouseEvent},
protobuf::Message, protobuf::Message,
sleep,
tokio::{self, sync::mpsc}, tokio::{self, sync::mpsc},
ResultType, ResultType,
}; };
@ -17,7 +16,7 @@ use std::{
mem::size_of, mem::size_of,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
time::Duration, time::{Duration, Instant},
}; };
use winapi::{ use winapi::{
shared::minwindef::{BOOL, FALSE, TRUE}, shared::minwindef::{BOOL, FALSE, TRUE},
@ -48,18 +47,6 @@ const ADDR_CAPTURE_FRAME: usize =
const IPC_PROFIX: &str = "_portable_service"; const IPC_PROFIX: &str = "_portable_service";
pub const SHMEM_NAME: &str = "_portable_service"; pub const SHMEM_NAME: &str = "_portable_service";
const MAX_NACK: usize = 3; const MAX_NACK: usize = 3;
const IPC_CONN_TIMEOUT: Duration = Duration::from_secs(3);
pub enum PortableServiceStatus {
NonStart,
Running,
}
impl Default for PortableServiceStatus {
fn default() -> Self {
Self::NonStart
}
}
pub struct SharedMemory { pub struct SharedMemory {
inner: Shmem, inner: Shmem,
@ -200,8 +187,6 @@ mod utils {
// functions called in seperate SYSTEM user process. // functions called in seperate SYSTEM user process.
pub mod server { pub mod server {
use hbb_common::tokio::time::Instant;
use super::*; use super::*;
lazy_static::lazy_static! { lazy_static::lazy_static! {
@ -220,7 +205,7 @@ pub mod server {
run_capture(shmem2); run_capture(shmem2);
})); }));
threads.push(std::thread::spawn(|| { threads.push(std::thread::spawn(|| {
run_ipc_server(); run_ipc_client();
})); }));
threads.push(std::thread::spawn(|| { threads.push(std::thread::spawn(|| {
run_exit_check(); run_exit_check();
@ -270,7 +255,7 @@ pub mod server {
if EXIT.lock().unwrap().clone() { if EXIT.lock().unwrap().clone() {
break; break;
} }
let start = std::time::Instant::now(); let start = Instant::now();
unsafe { unsafe {
let para_ptr = shmem.as_ptr().add(ADDR_CAPTURER_PARA); let para_ptr = shmem.as_ptr().add(ADDR_CAPTURER_PARA);
let para = para_ptr as *const CapturerPara; let para = para_ptr as *const CapturerPara;
@ -278,7 +263,6 @@ pub mod server {
let use_yuv = (*para).use_yuv; let use_yuv = (*para).use_yuv;
let timeout_ms = (*para).timeout_ms; let timeout_ms = (*para).timeout_ms;
if c.is_none() { if c.is_none() {
let use_yuv = true;
*crate::video_service::CURRENT_DISPLAY.lock().unwrap() = current_display; *crate::video_service::CURRENT_DISPLAY.lock().unwrap() = current_display;
let (_, _current, display) = get_current_display().unwrap(); let (_, _current, display) = get_current_display().unwrap();
match Capturer::new(display, use_yuv) { match Capturer::new(display, use_yuv) {
@ -348,114 +332,78 @@ pub mod server {
} }
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn run_ipc_server() { async fn run_ipc_client() {
use DataPortableService::*; use DataPortableService::*;
let postfix = IPC_PROFIX; let postfix = IPC_PROFIX;
let last_recv_time = Arc::new(Mutex::new(Instant::now()));
let mut interval = tokio::time::interval(Duration::from_secs(1));
match new_listener(postfix).await { match ipc::connect(1000, postfix).await {
Ok(mut incoming) => loop { Ok(mut stream) => {
tokio::select! { let mut timer = tokio::time::interval(Duration::from_secs(1));
Some(result) = incoming.next() => { let mut nack = 0;
match result { loop {
Ok(stream) => { tokio::select! {
log::info!("Got new connection"); res = stream.next() => {
let last_recv_time_cloned = last_recv_time.clone(); match res {
tokio::spawn(async move { Err(err) => {
let mut stream = Connection::new(stream); log::error!(
let postfix = postfix.to_owned(); "ipc{} connection closed: {}",
let mut timer = tokio::time::interval(Duration::from_secs(1)); postfix,
let mut nack = 0; err
let mut old_conn_count = 0; );
loop { break;
tokio::select! { }
res = stream.next() => { Ok(Some(Data::DataPortableService(data))) => match data {
if res.is_ok() { Ping => {
*last_recv_time_cloned.lock().unwrap() = Instant::now(); allow_err!(
} stream
match res { .send(&Data::DataPortableService(Pong))
Err(err) => { .await
log::error!( );
"ipc{} connection closed: {}", }
postfix, Pong => {
err nack = 0;
); }
*EXIT.lock().unwrap() = true; ConnCount(Some(n)) => {
break; if n == 0 {
} log::info!("Connnection count equals 0, exit");
Ok(Some(Data::DataPortableService(data))) => match data { stream.send(&Data::DataPortableService(WillClose)).await.ok();
Ping => { break;
allow_err!(
stream
.send(&Data::DataPortableService(Pong))
.await
);
}
Pong => {
nack = 0;
}
ConnCount(Some(n)) => {
if old_conn_count != 0 && n == 0 {
log::info!("Connection count decrease to 0, exit");
stream.send(&Data::DataPortableService(WillClose)).await.ok();
*EXIT.lock().unwrap() = true;
break;
}
old_conn_count = n;
}
Mouse(v) => {
if let Ok(evt) = MouseEvent::parse_from_bytes(&v) {
crate::input_service::handle_mouse_(&evt);
}
}
Key(v) => {
if let Ok(evt) = KeyEvent::parse_from_bytes(&v) {
crate::input_service::handle_key_(&evt);
}
}
_ => {}
},
_ => {}
}
}
_ = timer.tick() => {
nack+=1;
if nack > MAX_NACK {
log::info!("max ping nack, exit");
*EXIT.lock().unwrap() = true;
break;
}
stream.send(&Data::DataPortableService(Ping)).await.ok();
stream.send(&Data::DataPortableService(ConnCount(None))).await.ok();
}
} }
} }
}); Mouse(v) => {
} if let Ok(evt) = MouseEvent::parse_from_bytes(&v) {
Err(err) => { crate::input_service::handle_mouse_(&evt);
log::error!("Couldn't get portable client: {:?}", err); }
*EXIT.lock().unwrap() = true; }
Key(v) => {
if let Ok(evt) = KeyEvent::parse_from_bytes(&v) {
crate::input_service::handle_key_(&evt);
}
}
_ => {}
},
_ => {}
} }
} }
} _ = timer.tick() => {
_ = interval.tick() => { nack+=1;
if last_recv_time.lock().unwrap().elapsed() > IPC_CONN_TIMEOUT { if nack > MAX_NACK {
log::error!("receive data timeout"); log::info!("max ping nack, exit");
*EXIT.lock().unwrap() = true; break;
} }
if EXIT.lock().unwrap().clone() { stream.send(&Data::DataPortableService(Ping)).await.ok();
break; stream.send(&Data::DataPortableService(ConnCount(None))).await.ok();
} }
} }
} }
}, }
Err(err) => { Err(e) => {
log::error!("Failed to start cm ipc server: {}", err); log::error!("Failed to connect portable service ipc:{:?}", e);
*EXIT.lock().unwrap() = true;
} }
} }
*EXIT.lock().unwrap() = true;
} }
} }
@ -466,54 +414,46 @@ pub mod client {
use super::*; use super::*;
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref SHMEM: Arc<Mutex<Option<SharedMemory>>> = Default::default(); pub static ref PORTABLE_SERVICE_RUNNING: Arc<Mutex<bool>> = Default::default();
pub static ref PORTABLE_SERVICE_STATUS: Arc<Mutex<PortableServiceStatus>> = Default::default(); static ref SHMEM: Arc<Mutex<Option<SharedMemory>>> = Default::default();
static ref SENDER : Mutex<mpsc::UnboundedSender<ipc::Data>> = Mutex::new(client::start_ipc_client()); static ref SENDER : Mutex<mpsc::UnboundedSender<ipc::Data>> = Mutex::new(client::start_ipc_server());
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PortableServiceStatus {
NotStarted,
Starting,
Running,
}
impl Default for PortableServiceStatus {
fn default() -> Self {
Self::NotStarted
}
} }
pub(crate) fn start_portable_service() -> ResultType<()> { pub(crate) fn start_portable_service() -> ResultType<()> {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::NotStarted { if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if SHMEM.lock().unwrap().is_none() { bail!("already running");
let displays = scrap::Display::all()?;
if displays.is_empty() {
bail!("no display available!");
}
let mut max_pixel = 0;
let align = 64;
for d in displays {
let pixel = utils::align(d.width(), align) * utils::align(d.height(), align);
if max_pixel < pixel {
max_pixel = pixel;
}
}
let shmem_size = utils::align(ADDR_CAPTURE_FRAME + max_pixel * 4, align);
// os error 112, no enough space
*SHMEM.lock().unwrap() = Some(crate::portable_service::SharedMemory::create(
crate::portable_service::SHMEM_NAME,
shmem_size,
)?);
shutdown_hooks::add_shutdown_hook(drop_shmem);
}
if crate::common::run_me(vec!["--portable-service"]).is_err() {
*SHMEM.lock().unwrap() = None;
bail!("Failed to run portable service process");
}
*PORTABLE_SERVICE_STATUS.lock().unwrap() = PortableServiceStatus::Starting;
let _sender = SENDER.lock().unwrap();
} }
if SHMEM.lock().unwrap().is_none() {
let displays = scrap::Display::all()?;
if displays.is_empty() {
bail!("no display available!");
}
let mut max_pixel = 0;
let align = 64;
for d in displays {
let pixel = utils::align(d.width(), align) * utils::align(d.height(), align);
if max_pixel < pixel {
max_pixel = pixel;
}
}
let shmem_size = utils::align(ADDR_CAPTURE_FRAME + max_pixel * 4, align);
// os error 112, no enough space
*SHMEM.lock().unwrap() = Some(crate::portable_service::SharedMemory::create(
crate::portable_service::SHMEM_NAME,
shmem_size,
)?);
shutdown_hooks::add_shutdown_hook(drop_shmem);
}
let mut option = SHMEM.lock().unwrap();
let shmem = option.as_mut().unwrap();
unsafe {
libc::memset(shmem.as_ptr() as _, 0, shmem.len() as _);
}
if crate::common::run_me(vec!["--portable-service"]).is_err() {
*SHMEM.lock().unwrap() = None;
bail!("Failed to run portable service process");
}
let _sender = SENDER.lock().unwrap();
Ok(()) Ok(())
} }
@ -613,94 +553,98 @@ pub mod client {
} }
} }
pub(super) fn start_ipc_client() -> mpsc::UnboundedSender<Data> { pub(super) fn start_ipc_server() -> mpsc::UnboundedSender<Data> {
let (tx, rx) = mpsc::unbounded_channel::<Data>(); let (tx, rx) = mpsc::unbounded_channel::<Data>();
std::thread::spawn(move || start_ipc_client_async(rx)); std::thread::spawn(move || start_ipc_server_async(rx));
tx tx
} }
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn start_ipc_client_async(rx: mpsc::UnboundedReceiver<Data>) { async fn start_ipc_server_async(rx: mpsc::UnboundedReceiver<Data>) {
use DataPortableService::*; use DataPortableService::*;
let mut rx = rx; let rx = Arc::new(tokio::sync::Mutex::new(rx));
let mut connect_failed = 0; let postfix = IPC_PROFIX;
loop {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::NotStarted
{
sleep(1.).await;
continue;
}
if let Ok(mut c) = ipc::connect(1000, IPC_PROFIX).await {
let mut nack = 0;
let mut timer = tokio::time::interval(Duration::from_secs(1));
loop {
tokio::select! {
res = c.next() => {
match res {
Err(err) => {
log::error!("ipc connection closed: {}", err);
break;
}
Ok(Some(Data::DataPortableService(data))) => {
match data {
Ping => {
c.send(&Data::DataPortableService(Pong)).await.ok();
}
Pong => {
nack = 0;
*PORTABLE_SERVICE_STATUS.lock().unwrap() = PortableServiceStatus::Running;
},
ConnCount(None) => {
let cnt = crate::server::CONN_COUNT.lock().unwrap().clone();
c.send(&Data::DataPortableService(ConnCount(Some(cnt)))).await.ok();
},
WillClose => {
log::info!("portable service will close, set status to not started");
*PORTABLE_SERVICE_STATUS.lock().unwrap() = PortableServiceStatus::NotStarted;
break;
}
_=>{}
}
}
_ => {}
}
}
_ = timer.tick() => {
nack+=1;
if nack > MAX_NACK {
// In fact, this will not happen, ipc will be closed before max nack.
log::error!("max ipc nack, set status to not started");
*PORTABLE_SERVICE_STATUS.lock().unwrap() = PortableServiceStatus::NotStarted;
break;
}
c.send(&Data::DataPortableService(Ping)).await.ok();
}
Some(data) = rx.recv() => {
allow_err!(c.send(&data).await);
}
match new_listener(postfix).await {
Ok(mut incoming) => loop {
{
tokio::select! {
Some(result) = incoming.next() => {
match result {
Ok(stream) => {
log::info!("Got portable service ipc connection");
let rx_clone = rx.clone();
tokio::spawn(async move {
let mut stream = Connection::new(stream);
let postfix = postfix.to_owned();
let mut timer = tokio::time::interval(Duration::from_secs(1));
let mut nack = 0;
let mut rx = rx_clone.lock().await;
loop {
tokio::select! {
res = stream.next() => {
match res {
Err(err) => {
log::info!(
"ipc{} connection closed: {}",
postfix,
err
);
break;
}
Ok(Some(Data::DataPortableService(data))) => match data {
Ping => {
stream.send(&Data::DataPortableService(Pong)).await.ok();
}
Pong => {
nack = 0;
*PORTABLE_SERVICE_RUNNING.lock().unwrap() = true;
},
ConnCount(None) => {
let cnt = crate::server::CONN_COUNT.lock().unwrap().clone();
stream.send(&Data::DataPortableService(ConnCount(Some(cnt)))).await.ok();
},
WillClose => {
log::info!("portable service will close");
break;
}
_=>{}
}
_=>{}
}
}
_ = timer.tick() => {
nack+=1;
if nack > MAX_NACK {
// In fact, this will not happen, ipc will be closed before max nack.
log::error!("max ipc nack");
break;
}
stream.send(&Data::DataPortableService(Ping)).await.ok();
}
Some(data) = rx.recv() => {
allow_err!(stream.send(&data).await);
}
}
}
*PORTABLE_SERVICE_RUNNING.lock().unwrap() = false;
});
}
Err(err) => {
log::error!("Couldn't get portable client: {:?}", err);
}
}
}
} }
} }
} else { },
connect_failed += 1; Err(err) => {
if connect_failed > IPC_CONN_TIMEOUT.as_secs() { log::error!("Failed to start portable service ipc server: {}", err);
connect_failed = 0;
*PORTABLE_SERVICE_STATUS.lock().unwrap() = PortableServiceStatus::NotStarted;
log::info!(
"connect failed {} times, set status to not started",
connect_failed
);
}
log::info!(
"client ip connect failed, status:{:?}",
PORTABLE_SERVICE_STATUS.lock().unwrap().clone(),
);
} }
sleep(1.).await;
} }
} }
fn client_ipc_send(data: Data) -> ResultType<()> { fn ipc_send(data: Data) -> ResultType<()> {
let sender = SENDER.lock().unwrap(); let sender = SENDER.lock().unwrap();
sender sender
.send(data) .send(data)
@ -721,21 +665,25 @@ pub mod client {
fn handle_mouse_(evt: &MouseEvent) -> ResultType<()> { fn handle_mouse_(evt: &MouseEvent) -> ResultType<()> {
let mut v = vec![]; let mut v = vec![];
evt.write_to_vec(&mut v)?; evt.write_to_vec(&mut v)?;
client_ipc_send(Data::DataPortableService(DataPortableService::Mouse(v))) ipc_send(Data::DataPortableService(DataPortableService::Mouse(v)))
} }
fn handle_key_(evt: &KeyEvent) -> ResultType<()> { fn handle_key_(evt: &KeyEvent) -> ResultType<()> {
let mut v = vec![]; let mut v = vec![];
evt.write_to_vec(&mut v)?; evt.write_to_vec(&mut v)?;
client_ipc_send(Data::DataPortableService(DataPortableService::Key(v))) ipc_send(Data::DataPortableService(DataPortableService::Key(v)))
} }
pub fn create_capturer( pub fn create_capturer(
current_display: usize, current_display: usize,
display: scrap::Display, display: scrap::Display,
use_yuv: bool, use_yuv: bool,
portable_service_running: bool,
) -> ResultType<Box<dyn TraitCapturer>> { ) -> ResultType<Box<dyn TraitCapturer>> {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::Running { if portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
log::info!("portable service status mismatch");
}
if portable_service_running {
log::info!("Create shared memeory capturer"); log::info!("Create shared memeory capturer");
return Ok(Box::new(CapturerPortable::new(current_display, use_yuv))); return Ok(Box::new(CapturerPortable::new(current_display, use_yuv)));
} else { } else {
@ -747,7 +695,7 @@ pub mod client {
} }
pub fn get_cursor_info(pci: PCURSORINFO) -> BOOL { pub fn get_cursor_info(pci: PCURSORINFO) -> BOOL {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::Running { if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
get_cursor_info_(&mut SHMEM.lock().unwrap().as_mut().unwrap(), pci) get_cursor_info_(&mut SHMEM.lock().unwrap().as_mut().unwrap(), pci)
} else { } else {
unsafe { winuser::GetCursorInfo(pci) } unsafe { winuser::GetCursorInfo(pci) }
@ -755,7 +703,7 @@ pub mod client {
} }
pub fn handle_mouse(evt: &MouseEvent) { pub fn handle_mouse(evt: &MouseEvent) {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::Running { if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
handle_mouse_(evt).ok(); handle_mouse_(evt).ok();
} else { } else {
crate::input_service::handle_mouse_(evt); crate::input_service::handle_mouse_(evt);
@ -763,7 +711,7 @@ pub mod client {
} }
pub fn handle_key(evt: &KeyEvent) { pub fn handle_key(evt: &KeyEvent) {
if PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == PortableServiceStatus::Running { if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
handle_key_(evt).ok(); handle_key_(evt).ok();
} else { } else {
crate::input_service::handle_key_(evt); crate::input_service::handle_key_(evt);

View File

@ -20,7 +20,7 @@
use super::{video_qos::VideoQoS, *}; use super::{video_qos::VideoQoS, *};
#[cfg(windows)] #[cfg(windows)]
use crate::portable_service::client::{PortableServiceStatus, PORTABLE_SERVICE_STATUS}; use crate::portable_service::client::PORTABLE_SERVICE_RUNNING;
use hbb_common::tokio::sync::{ use hbb_common::tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex, Mutex as TokioMutex,
@ -191,6 +191,7 @@ fn create_capturer(
display: Display, display: Display,
use_yuv: bool, use_yuv: bool,
current: usize, current: usize,
_portable_service_running: bool,
) -> ResultType<Box<dyn TraitCapturer>> { ) -> ResultType<Box<dyn TraitCapturer>> {
#[cfg(not(windows))] #[cfg(not(windows))]
let c: Option<Box<dyn TraitCapturer>> = None; let c: Option<Box<dyn TraitCapturer>> = None;
@ -252,7 +253,12 @@ fn create_capturer(
None => { None => {
log::debug!("Create capturer dxgi|gdi"); log::debug!("Create capturer dxgi|gdi");
#[cfg(windows)] #[cfg(windows)]
return crate::portable_service::client::create_capturer(current, display, use_yuv); return crate::portable_service::client::create_capturer(
current,
display,
use_yuv,
_portable_service_running,
);
#[cfg(not(windows))] #[cfg(not(windows))]
return Ok(Box::new( return Ok(Box::new(
Capturer::new(display, use_yuv).with_context(|| "Failed to create capturer")?, Capturer::new(display, use_yuv).with_context(|| "Failed to create capturer")?,
@ -282,7 +288,7 @@ pub fn test_create_capturer(privacy_mode_id: i32, timeout_millis: u64) -> bool {
let test_begin = Instant::now(); let test_begin = Instant::now();
while test_begin.elapsed().as_millis() < timeout_millis as _ { while test_begin.elapsed().as_millis() < timeout_millis as _ {
if let Ok((_, current, display)) = get_current_display() { if let Ok((_, current, display)) = get_current_display() {
if let Ok(_) = create_capturer(privacy_mode_id, display, true, current) { if let Ok(_) = create_capturer(privacy_mode_id, display, true, current, false) {
return true; return true;
} }
} }
@ -331,7 +337,7 @@ impl DerefMut for CapturerInfo {
} }
} }
fn get_capturer(use_yuv: bool) -> ResultType<CapturerInfo> { fn get_capturer(use_yuv: bool, portable_service_running: bool) -> ResultType<CapturerInfo> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
{ {
if !scrap::is_x11() { if !scrap::is_x11() {
@ -373,7 +379,13 @@ fn get_capturer(use_yuv: bool) -> ResultType<CapturerInfo> {
} else { } else {
log::info!("In privacy mode, the peer side cannot watch the screen"); log::info!("In privacy mode, the peer side cannot watch the screen");
} }
let capturer = create_capturer(captuerer_privacy_mode_id, display, use_yuv, current)?; let capturer = create_capturer(
captuerer_privacy_mode_id,
display,
use_yuv,
current,
portable_service_running,
)?;
Ok(CapturerInfo { Ok(CapturerInfo {
origin, origin,
width, width,
@ -393,8 +405,12 @@ fn run(sp: GenericService) -> ResultType<()> {
// ensure_inited() is needed because release_resouce() may be called. // ensure_inited() is needed because release_resouce() may be called.
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
super::wayland::ensure_inited()?; super::wayland::ensure_inited()?;
#[cfg(windows)]
let last_portable_service_running = PORTABLE_SERVICE_RUNNING.lock().unwrap().clone();
#[cfg(not(windows))]
let last_portable_service_running = false;
let mut c = get_capturer(true)?; let mut c = get_capturer(true, last_portable_service_running)?;
let mut video_qos = VIDEO_QOS.lock().unwrap(); let mut video_qos = VIDEO_QOS.lock().unwrap();
video_qos.set_size(c.width as _, c.height as _); video_qos.set_size(c.width as _, c.height as _);
@ -472,11 +488,6 @@ fn run(sp: GenericService) -> ResultType<()> {
let recorder: Arc<Mutex<Option<Recorder>>> = Default::default(); let recorder: Arc<Mutex<Option<Recorder>>> = Default::default();
#[cfg(windows)] #[cfg(windows)]
start_uac_elevation_check(); start_uac_elevation_check();
#[cfg(windows)]
let portable_service_status = crate::portable_service::client::PORTABLE_SERVICE_STATUS
.lock()
.unwrap()
.clone();
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
let mut would_block_count = 0u32; let mut would_block_count = 0u32;
@ -508,15 +519,14 @@ fn run(sp: GenericService) -> ResultType<()> {
bail!("SWITCH"); bail!("SWITCH");
} }
#[cfg(windows)] #[cfg(windows)]
if portable_service_status != PORTABLE_SERVICE_STATUS.lock().unwrap().clone() { if last_portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
bail!("SWITCH"); bail!("SWITCH");
} }
check_privacy_mode_changed(&sp, c.privacy_mode_id)?; check_privacy_mode_changed(&sp, c.privacy_mode_id)?;
#[cfg(windows)] #[cfg(windows)]
{ {
if crate::platform::windows::desktop_changed() if crate::platform::windows::desktop_changed()
&& PORTABLE_SERVICE_STATUS.lock().unwrap().clone() && !PORTABLE_SERVICE_RUNNING.lock().unwrap().clone()
== PortableServiceStatus::NotStarted
{ {
bail!("Desktop changed"); bail!("Desktop changed");
} }

View File

@ -770,11 +770,11 @@ fn cm_inner_send(id: i32, data: Data) {
pub fn can_elevate() -> bool { pub fn can_elevate() -> bool {
#[cfg(windows)] #[cfg(windows)]
{ {
use crate::portable_service::client::{
PortableServiceStatus::NotStarted, PORTABLE_SERVICE_STATUS,
};
return !crate::platform::is_installed() return !crate::platform::is_installed()
&& PORTABLE_SERVICE_STATUS.lock().unwrap().clone() == NotStarted; && !crate::portable_service::client::PORTABLE_SERVICE_RUNNING
.lock()
.unwrap()
.clone();
} }
#[cfg(not(windows))] #[cfg(not(windows))]
return false; return false;