Skip to content

Commit

Permalink
cli: add --no-sleep flag, implementation for macos (#171885)
Browse files Browse the repository at this point in the history
  • Loading branch information
connor4312 committed Jan 20, 2023
1 parent 00e8fde commit 4cf496e
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 12 deletions.
1 change: 1 addition & 0 deletions cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ log = "0.4"
const_format = "0.2"
sha2 = "0.10"
base64 = "0.13"
core-foundation = "0.9.3"

[build-dependencies]
serde = { version = "1.0" }
Expand Down
4 changes: 4 additions & 0 deletions cli/src/commands/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,10 @@ pub struct TunnelServeArgs {
#[clap(long)]
pub random_name: bool,

/// Prevents the machine going to sleep while this command runs.
#[clap(long)]
pub no_sleep: bool,

/// Sets the machine name for port forwarding service
#[clap(long)]
pub name: Option<String>,
Expand Down
36 changes: 24 additions & 12 deletions cli/src/commands/tunnels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use super::{
CommandContext,
};

use crate::tunnels::dev_tunnels::ActiveTunnel;
use crate::tunnels::shutdown_signal::ShutdownSignal;
use crate::tunnels::{dev_tunnels::ActiveTunnel, SleepInhibitor};
use crate::{
auth::Auth,
log::{self, Logger},
Expand Down Expand Up @@ -213,10 +213,22 @@ pub async fn serve(ctx: CommandContext, gateway_args: TunnelServeArgs) -> Result
log, paths, args, ..
} = ctx;

let no_sleep = match gateway_args.no_sleep.then(SleepInhibitor::new) {
Some(Ok(i)) => Some(i),
Some(Err(e)) => {
warning!(log, "Could not inhibit sleep: {}", e);
None
}
None => None,
};

legal::require_consent(&paths, gateway_args.accept_server_license_terms)?;

let csa = (&args).into();
serve_with_csa(paths, log, gateway_args, csa, None).await
let result = serve_with_csa(paths, log, gateway_args, csa, None).await;
drop(no_sleep);

result
}

fn get_connection_token(tunnel: &ActiveTunnel) -> String {
Expand Down Expand Up @@ -253,16 +265,16 @@ async fn serve_with_csa(
let shutdown_tx = if let Some(tx) = shutdown_rx {
tx
} else if let Some(pid) = gateway_args
.parent_process_id
.and_then(|p| Pid::from_str(&p).ok())
{
ShutdownSignal::create_rx(&[
ShutdownSignal::CtrlC,
ShutdownSignal::ParentProcessKilled(pid),
])
} else {
ShutdownSignal::create_rx(&[ShutdownSignal::CtrlC])
};
.parent_process_id
.and_then(|p| Pid::from_str(&p).ok())
{
ShutdownSignal::create_rx(&[
ShutdownSignal::CtrlC,
ShutdownSignal::ParentProcessKilled(pid),
])
} else {
ShutdownSignal::create_rx(&[ShutdownSignal::CtrlC])
};

let mut r = crate::tunnels::serve(&log, tunnel, &paths, &csa, platform, shutdown_tx).await?;
r.tunnel.close().await.ok();
Expand Down
4 changes: 4 additions & 0 deletions cli/src/tunnels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub mod shutdown_signal;

mod control_server;
mod name_generator;
mod nosleep;
#[cfg(target_os = "macos")]
mod nosleep_macos;
mod port_forwarder;
mod protocol;
#[cfg_attr(unix, path = "tunnels/server_bridge_unix.rs")]
Expand All @@ -28,6 +31,7 @@ mod socket_signal;
mod wsl_server;

pub use control_server::serve;
pub use nosleep::SleepInhibitor;
pub use service::{
create_service_manager, ServiceContainer, ServiceManager, SERVICE_LOG_FILE_NAME,
};
Expand Down
30 changes: 30 additions & 0 deletions cli/src/tunnels/nosleep.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

#[cfg(target_os = "windows")]
pub type SleepInhibitor = NoOpSleepInhibitor;

#[cfg(target_os = "linux")]
pub type SleepInhibitor = NoOpSleepInhibitor;

#[cfg(target_os = "macos")]
pub type SleepInhibitor = super::nosleep_macos::SleepInhibitor;

/// Stub no-sleep implementation for unsupported platforms.
#[allow(dead_code)]
pub struct NoOpSleepInhibitor();

#[allow(dead_code)]
impl NoOpSleepInhibitor {
pub fn new() -> std::io::Result<Self> {
Ok(NoOpSleepInhibitor())
}
}

impl Drop for NoOpSleepInhibitor {
fn drop(&mut self) {
// no-op
}
}
59 changes: 59 additions & 0 deletions cli/src/tunnels/nosleep_macos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

use std::io;

use const_format::concatcp;
use core_foundation::base::TCFType;
use core_foundation::string::{CFString, CFStringRef};
use libc::c_int;

use crate::constants::APPLICATION_NAME;

extern "C" {
pub fn IOPMAssertionCreateWithName(
assertion_type: CFStringRef,
assertion_level: u32,
assertion_name: CFStringRef,
assertion_id: &mut u32,
) -> c_int;

pub fn IOPMAssertionRelease(assertion_id: u32) -> c_int;
}

pub struct SleepInhibitor {
assertion_id: u32,
}

impl SleepInhibitor {
pub fn new() -> io::Result<Self> {
let mut assertion_id = 0;
let assertion_type = CFString::from_static_string("PreventSystemSleep");
let assertion_name =
CFString::from_static_string(concatcp!(APPLICATION_NAME, " running tunnel"));
let result = unsafe {
IOPMAssertionCreateWithName(
assertion_type.as_concrete_TypeRef(),
255,
assertion_name.as_concrete_TypeRef(),
&mut assertion_id,
)
};

if result != 0 {
return Err(io::Error::last_os_error());
}

Ok(Self { assertion_id })
}
}

impl Drop for SleepInhibitor {
fn drop(&mut self) {
unsafe {
IOPMAssertionRelease(self.assertion_id);
}
}
}

0 comments on commit 4cf496e

Please sign in to comment.