mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
parent
7c1b8f38a4
commit
eab8ba65bf
|
@ -93,6 +93,7 @@ async fn main() -> Result<(), std::convert::Infallible> {
|
|||
Some(args::TunnelSubcommand::Unregister) => tunnels::unregister(context).await,
|
||||
Some(args::TunnelSubcommand::Kill) => tunnels::kill(context).await,
|
||||
Some(args::TunnelSubcommand::Restart) => tunnels::restart(context).await,
|
||||
Some(args::TunnelSubcommand::Status) => tunnels::status(context).await,
|
||||
Some(args::TunnelSubcommand::Rename(rename_args)) => {
|
||||
tunnels::rename(context, rename_args).await
|
||||
}
|
||||
|
|
|
@ -630,6 +630,9 @@ pub enum TunnelSubcommand {
|
|||
/// Restarts any running tunnel on the system.
|
||||
Restart,
|
||||
|
||||
/// Gets whether there is a tunnel running on the current machineiou.
|
||||
Status,
|
||||
|
||||
/// Rename the name of this machine associated with port forwarding service.
|
||||
Rename(TunnelRenameArgs),
|
||||
|
||||
|
|
|
@ -203,17 +203,19 @@ pub async fn unregister(ctx: CommandContext) -> Result<i32, AnyError> {
|
|||
Ok(0)
|
||||
}
|
||||
|
||||
async fn do_single_rpc_call(
|
||||
ctx: CommandContext,
|
||||
async fn do_single_rpc_call<
|
||||
P: serde::Serialize,
|
||||
R: serde::de::DeserializeOwned + Send + 'static,
|
||||
>(
|
||||
ctx: &CommandContext,
|
||||
method: &'static str,
|
||||
params: impl serde::Serialize,
|
||||
) -> Result<i32, AnyError> {
|
||||
params: P,
|
||||
) -> Result<R, AnyError> {
|
||||
let client = match connect_as_client(&ctx.paths.tunnel_lockfile()).await {
|
||||
Ok(p) => p,
|
||||
Err(CodeError::SingletonLockfileOpenFailed(_))
|
||||
| Err(CodeError::SingletonLockedProcessExited(_)) => {
|
||||
error!(ctx.log, "No tunnel is running");
|
||||
return Ok(1);
|
||||
return Err(CodeError::NoRunningTunnel.into());
|
||||
}
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
|
@ -236,33 +238,42 @@ async fn do_single_rpc_call(
|
|||
.unwrap();
|
||||
});
|
||||
|
||||
let r = caller.call::<_, _, ()>(method, params).await.unwrap();
|
||||
let r = caller.call(method, params).await.unwrap();
|
||||
rpc.abort();
|
||||
|
||||
if let Err(r) = r {
|
||||
error!(ctx.log, "RPC call failed: {:?}", r);
|
||||
return Ok(1);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
r.map_err(|err| CodeError::TunnelRpcCallFailed(err).into())
|
||||
}
|
||||
|
||||
pub async fn restart(ctx: CommandContext) -> Result<i32, AnyError> {
|
||||
do_single_rpc_call(
|
||||
ctx,
|
||||
do_single_rpc_call::<_, ()>(
|
||||
&ctx,
|
||||
protocol::singleton::METHOD_RESTART,
|
||||
protocol::EmptyObject {},
|
||||
)
|
||||
.await
|
||||
.map(|_| 0)
|
||||
}
|
||||
|
||||
pub async fn kill(ctx: CommandContext) -> Result<i32, AnyError> {
|
||||
do_single_rpc_call(
|
||||
ctx,
|
||||
do_single_rpc_call::<_, ()>(
|
||||
&ctx,
|
||||
protocol::singleton::METHOD_SHUTDOWN,
|
||||
protocol::EmptyObject {},
|
||||
)
|
||||
.await
|
||||
.map(|_| 0)
|
||||
}
|
||||
|
||||
pub async fn status(ctx: CommandContext) -> Result<i32, AnyError> {
|
||||
let status: protocol::singleton::Status = do_single_rpc_call(
|
||||
&ctx,
|
||||
protocol::singleton::METHOD_STATUS,
|
||||
protocol::EmptyObject {},
|
||||
)
|
||||
.await?;
|
||||
|
||||
ctx.log.result(serde_json::to_string(&status).unwrap());
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Removes unused servers.
|
||||
|
|
|
@ -164,6 +164,7 @@ pub mod singleton {
|
|||
|
||||
pub const METHOD_RESTART: &str = "restart";
|
||||
pub const METHOD_SHUTDOWN: &str = "shutdown";
|
||||
pub const METHOD_STATUS: &str = "status";
|
||||
pub const METHOD_LOG: &str = "log";
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -179,4 +180,9 @@ pub mod singleton {
|
|||
pub prefix: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Status {
|
||||
pub ok: bool,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,13 @@ pub fn make_singleton_server(
|
|||
},
|
||||
);
|
||||
|
||||
rpc.register_sync(
|
||||
protocol::singleton::METHOD_STATUS,
|
||||
|_: protocol::EmptyObject, _| {
|
||||
Ok(protocol::singleton::Status { ok: true }) // mostly placeholder
|
||||
},
|
||||
);
|
||||
|
||||
rpc.register_sync(
|
||||
protocol::singleton::METHOD_SHUTDOWN,
|
||||
|_: protocol::EmptyObject, ctx| {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
use crate::constants::{
|
||||
use crate::{constants::{
|
||||
APPLICATION_NAME, CONTROL_PORT, DOCUMENTATION_URL, QUALITYLESS_PRODUCT_NAME,
|
||||
};
|
||||
}, rpc::ResponseError};
|
||||
use std::fmt::Display;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -479,16 +479,20 @@ macro_rules! makeAnyError {
|
|||
/// Note: other error should be migrated to this type gradually
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CodeError {
|
||||
#[error("could not connect to socket/pipe")]
|
||||
#[error("could not connect to socket/pipe: {0:?}")]
|
||||
AsyncPipeFailed(std::io::Error),
|
||||
#[error("could not listen on socket/pipe")]
|
||||
#[error("could not listen on socket/pipe: {0:?}")]
|
||||
AsyncPipeListenerFailed(std::io::Error),
|
||||
#[error("could not create singleton lock file")]
|
||||
#[error("could not create singleton lock file: {0:?}")]
|
||||
SingletonLockfileOpenFailed(std::io::Error),
|
||||
#[error("could not read singleton lock file")]
|
||||
#[error("could not read singleton lock file: {0:?}")]
|
||||
SingletonLockfileReadFailed(rmp_serde::decode::Error),
|
||||
#[error("the process holding the singleton lock file exited")]
|
||||
#[error("the process holding the singleton lock file (pid={0}) exited")]
|
||||
SingletonLockedProcessExited(u32),
|
||||
#[error("no tunnel process is currently running")]
|
||||
NoRunningTunnel,
|
||||
#[error("rpc call failed: {0:?}")]
|
||||
TunnelRpcCallFailed(ResponseError),
|
||||
}
|
||||
|
||||
makeAnyError!(
|
||||
|
|
Loading…
Reference in a new issue