Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
fix(rome_cli): ensures the service only connects to compatible versio…
Browse files Browse the repository at this point in the history
…ns (#3642)

* fix(rome_cli): ensures the service only connects to compatible versions

* enumerate running rome servers in `rome rage`

* fix the build on unix
  • Loading branch information
leops authored Nov 10, 2022
1 parent 2e2e64f commit 90ec8a4
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 31 deletions.
74 changes: 54 additions & 20 deletions crates/rome_cli/src/commands/rage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{env, io, ops::Deref};
use tokio::runtime::Runtime;

use crate::commands::daemon::read_most_recent_log_file;
use crate::service::enumerate_pipes;
use crate::{service, CliSession, Termination, VERSION};

/// Handler for the `rage` command
Expand Down Expand Up @@ -85,38 +86,71 @@ struct RunningRomeServer;

impl Display for RunningRomeServer {
fn fmt(&self, f: &mut Formatter) -> io::Result<()> {
let runtime = Runtime::new()?;

match service::open_transport(runtime) {
Ok(None) => {
return markup!(
{Section("Server")}
{KeyValuePair("Status", markup!(<Dim>"stopped"</Dim>))}
)
.fmt(f);
let versions = match enumerate_pipes() {
Ok(iter) => iter,
Err(err) => {
(markup! {<Error>"\u{2716} Enumerating Rome instances failed:"</Error>}).fmt(f)?;
return writeln!(f, " {err}");
}
Ok(Some(transport)) => {
markup!("\n"<Emphasis>"Running Rome Server:"</Emphasis>" "{HorizontalLine::new(78)}"
};

for version in versions {
if version == rome_service::VERSION {
let runtime = Runtime::new()?;
match service::open_transport(runtime) {
Ok(None) => {
markup!(
{Section("Server")}
{KeyValuePair("Status", markup!(<Dim>"stopped"</Dim>))}
)
.fmt(f)?;
continue;
}
Ok(Some(transport)) => {
markup!("\n"<Emphasis>"Running Rome Server:"</Emphasis>" "{HorizontalLine::new(78)}"
"<Info>"\u{2139} The client isn't connected to any server but rage discovered this running Rome server."</Info>"
")
.fmt(f)?;

match client(transport) {
Ok(client) => WorkspaceRage(client.deref()).fmt(f)?,
match client(transport) {
Ok(client) => WorkspaceRage(client.deref()).fmt(f)?,
Err(err) => {
markup!(<Error>"\u{2716} Failed to connect: "</Error>).fmt(f)?;
writeln!(f, "{err}")?;
}
}
}
Err(err) => {
markup!(<Error>"\u{2716} Failed to connect: "</Error>).fmt(f)?;
markup!("\n"<Error>"\u{2716} Failed to connect: "</Error>).fmt(f)?;
writeln!(f, "{err}")?;
}
}

RomeServerLog.fmt(f)?;
} else {
markup!("\n"<Emphasis>"Incompatible Rome Server:"</Emphasis>" "{HorizontalLine::new(78)}"
"<Info>"\u{2139} Rage discovered this running server using an incompatible version of Rome."</Info>"
")
.fmt(f)?;

// Version 10.0.0 and below did not include a service version in the pipe name
let version = if version.is_empty() {
"<=10.0.0"
} else {
version.as_str()
};

markup!(
{Section("Server")}
{KeyValuePair("Version", markup!({version}))}
)
.fmt(f)?;
}
Err(err) => {
markup!("\n"<Error>"\u{2716} Failed to connect: "</Error>).fmt(f)?;
writeln!(f, "{err}")?;
}
};
}

RomeServerLog.fmt(f)
Ok(())
}
}

Expand Down
10 changes: 6 additions & 4 deletions crates/rome_cli/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,16 @@ use tokio::{
#[cfg(windows)]
mod windows;
#[cfg(windows)]
pub(crate) use self::windows::{ensure_daemon, open_socket, print_socket, run_daemon};
pub(crate) use self::windows::{
ensure_daemon, enumerate_pipes, open_socket, print_socket, run_daemon,
};

#[cfg(unix)]
mod unix;
#[cfg(unix)]
pub(crate) use self::unix::open_socket;
#[cfg(unix)]
pub(crate) use self::unix::{ensure_daemon, print_socket, run_daemon};
pub(crate) use self::unix::{
ensure_daemon, enumerate_pipes, open_socket, print_socket, run_daemon,
};

/// Tries to open a connection to a running daemon instance, returning a
/// [WorkspaceTransport] instance if the socket is currently active
Expand Down
19 changes: 18 additions & 1 deletion crates/rome_cli/src/service/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,24 @@ use tracing::Instrument;
/// Returns the filesystem path of the global socket used to communicate with
/// the server daemon
fn get_socket_name() -> PathBuf {
env::temp_dir().join("rome-socket")
env::temp_dir().join(format!("rome-socket-{}", rome_service::VERSION))
}

pub(crate) fn enumerate_pipes() -> io::Result<impl Iterator<Item = String>> {
fs::read_dir(env::temp_dir()).map(|iter| {
iter.filter_map(|entry| {
let entry = entry.ok()?.path();
let file_name = entry.file_name()?;
let file_name = file_name.to_str()?;

let rome_version = file_name.strip_prefix("rome-socket")?;
if rome_version.is_empty() {
Some(String::new())
} else {
Some(rome_version.strip_prefix('-')?.to_string())
}
})
})
}

/// Try to connect to the global socket and wait for the connection to become ready
Expand Down
33 changes: 27 additions & 6 deletions crates/rome_cli/src/service/windows.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
convert::Infallible,
env,
fs::read_dir,
io::{self, ErrorKind},
mem::swap,
os::windows::process::CommandExt,
Expand All @@ -19,16 +20,36 @@ use tokio::{
};
use tracing::Instrument;

/// Name of the global named pipe used to communicate with the server daemon
const PIPE_NAME: &str = r"\\.\pipe\rome-service";
/// Returns the name of the global named pipe used to communicate with the
/// server daemon
fn get_pipe_name() -> String {
format!(r"\\.\pipe\rome-service-{}", rome_service::VERSION)
}

pub(crate) fn enumerate_pipes() -> io::Result<impl Iterator<Item = String>> {
read_dir(r"\\.\pipe").map(|iter| {
iter.filter_map(|entry| {
let entry = entry.ok()?.path();
let file_name = entry.file_name()?;
let file_name = file_name.to_str()?;

let rome_version = file_name.strip_prefix("rome-service")?;
if rome_version.is_empty() {
Some(String::new())
} else {
Some(rome_version.strip_prefix('-')?.to_string())
}
})
})
}

/// Error code from the Win32 API
const ERROR_PIPE_BUSY: i32 = 231;

/// Try to connect to the global pipe and wait for the connection to become ready
async fn try_connect() -> io::Result<NamedPipeClient> {
loop {
match ClientOptions::new().open(PIPE_NAME) {
match ClientOptions::new().open(get_pipe_name()) {
Ok(client) => return Ok(client),
// If the connection failed with ERROR_PIPE_BUSY, wait a few
// milliseconds then retry the connection (we should be using
Expand Down Expand Up @@ -165,7 +186,7 @@ pub(crate) async fn ensure_daemon() -> io::Result<bool> {
/// print the global pipe name in the standard output
pub(crate) async fn print_socket() -> io::Result<()> {
ensure_daemon().await?;
println!("{PIPE_NAME}");
println!("{}", get_pipe_name());
Ok(())
}

Expand All @@ -174,11 +195,11 @@ pub(crate) async fn print_socket() -> io::Result<()> {
pub(crate) async fn run_daemon(factory: ServerFactory) -> io::Result<Infallible> {
let mut prev_server = ServerOptions::new()
.first_pipe_instance(true)
.create(PIPE_NAME)?;
.create(get_pipe_name())?;

loop {
prev_server.connect().await?;
let mut next_server = ServerOptions::new().create(PIPE_NAME)?;
let mut next_server = ServerOptions::new().create(get_pipe_name())?;
swap(&mut prev_server, &mut next_server);

let connection = factory.create();
Expand Down

0 comments on commit 90ec8a4

Please sign in to comment.