ipc works

This commit is contained in:
John Smith 2023-12-14 21:28:02 -05:00 committed by Christien Rioux
parent 37979277b5
commit caa2746110
6 changed files with 100 additions and 82 deletions

View file

@ -31,7 +31,7 @@ struct CmdlineArgs {
/// IPC socket to connect to /// IPC socket to connect to
#[arg(long, short = 'p')] #[arg(long, short = 'p')]
ipc_path: Option<PathBuf>, ipc_path: Option<PathBuf>,
/// IPC socket to connect to /// Subnode index to use when connecting
#[arg(long, short = 'i', default_value = "0")] #[arg(long, short = 'i', default_value = "0")]
subnode_index: usize, subnode_index: usize,
/// Address to connect to /// Address to connect to

View file

@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
pub fn load_default_config() -> Result<config::Config, config::ConfigError> { pub fn load_default_config() -> Result<config::Config, config::ConfigError> {
let default_config = r#"--- let default_config = r#"---
enable_ipc: true enable_ipc: true
local_socket_path: '%LOCAL_SOCKET_DIRECTORY%' ipc_path: '%IPC_DIRECTORY%'
enable_network: true enable_network: true
address: "localhost:5959" address: "localhost:5959"
autoconnect: true autoconnect: true
@ -49,8 +49,8 @@ interface:
error : "light red" error : "light red"
"# "#
.replace( .replace(
"%LOCAL_SOCKET_DIRECTORY%", "%IPC_DIRECTORY%",
&Settings::get_default_local_socket_path().to_string_lossy(), &Settings::get_default_ipc_directory().to_string_lossy(),
) )
.replace( .replace(
"%LOGGING_FILE_DIRECTORY%", "%LOGGING_FILE_DIRECTORY%",
@ -248,8 +248,8 @@ impl Settings {
ts_path ts_path
} }
pub fn get_default_local_socket_path() -> PathBuf { pub fn get_default_ipc_directory() -> PathBuf {
Self::get_server_default_directory("local_sockets") Self::get_server_default_directory("ipc")
} }
pub fn get_default_config_path() -> PathBuf { pub fn get_default_config_path() -> PathBuf {

View file

@ -27,18 +27,24 @@ use thiserror::Error;
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
/// ///
struct Dirty<T> { struct Dirty<T>
where
T: PartialEq,
{
value: T, value: T,
dirty: bool, dirty: bool,
} }
impl<T> Dirty<T> { impl<T> Dirty<T>
where
T: PartialEq,
{
pub fn new(value: T) -> Self { pub fn new(value: T) -> Self {
Self { value, dirty: true } Self { value, dirty: true }
} }
pub fn set(&mut self, value: T) { pub fn set(&mut self, value: T) {
self.dirty = self.value != value;
self.value = value; self.value = value;
self.dirty = true;
} }
pub fn get(&self) -> &T { pub fn get(&self) -> &T {
&self.value &self.value
@ -266,6 +272,9 @@ impl UI {
fn ipc_path_radio(s: &mut Cursive) -> ViewRef<RadioButton<u32>> { fn ipc_path_radio(s: &mut Cursive) -> ViewRef<RadioButton<u32>> {
s.find_name("ipc-path-radio").unwrap() s.find_name("ipc-path-radio").unwrap()
} }
fn connecting_text(s: &mut Cursive) -> ViewRef<TextView> {
s.find_name("connecting-text").unwrap()
}
fn network_address(s: &mut Cursive) -> ViewRef<EditView> { fn network_address(s: &mut Cursive) -> ViewRef<EditView> {
s.find_name("network-address").unwrap() s.find_name("network-address").unwrap()
} }
@ -618,7 +627,7 @@ impl UI {
EventResult::Ignored EventResult::Ignored
} }
fn show_connection_dialog(s: &mut Cursive, state: ConnectionState) -> bool { fn draw_connection_dialog(s: &mut Cursive, state: ConnectionState) -> bool {
let is_ipc = Self::command_processor(s).get_ipc_path().is_some(); let is_ipc = Self::command_processor(s).get_ipc_path().is_some();
let mut inner = Self::inner_mut(s); let mut inner = Self::inner_mut(s);
@ -634,7 +643,7 @@ impl UI {
let mut show: bool = false; let mut show: bool = false;
let mut hide: bool = false; let mut hide: bool = false;
let mut reset: bool = false; let mut connecting: bool = false;
match state { match state {
ConnectionState::Disconnected => { ConnectionState::Disconnected => {
if inner.connection_dialog_state.is_none() if inner.connection_dialog_state.is_none()
@ -651,7 +660,8 @@ impl UI {
.unwrap() .unwrap()
.is_retrying() .is_retrying()
{ {
reset = true; hide = true;
show = true
} }
} }
ConnectionState::ConnectedTCP(_, _) | ConnectionState::ConnectedIPC(_, _) => { ConnectionState::ConnectedTCP(_, _) | ConnectionState::ConnectedIPC(_, _) => {
@ -680,8 +690,10 @@ impl UI {
.unwrap() .unwrap()
.is_disconnected() .is_disconnected()
{ {
reset = true; hide = true;
show = true;
} }
connecting = true;
} }
} }
inner.connection_dialog_state = Some(state); inner.connection_dialog_state = Some(state);
@ -689,7 +701,6 @@ impl UI {
if hide { if hide {
s.pop_layer(); s.pop_layer();
s.pop_layer(); s.pop_layer();
return true;
} }
if show { if show {
s.add_fullscreen_layer(Layer::with_color( s.add_fullscreen_layer(Layer::with_color(
@ -698,56 +709,68 @@ impl UI {
)); ));
s.add_layer( s.add_layer(
Dialog::around( Dialog::around(if connecting {
LinearLayout::vertical().child( LinearLayout::vertical()
LinearLayout::horizontal() .child(TextView::new(" "))
.child( .child(
if is_ipc { TextView::new(if is_ipc {
connection_type_group.button(0, "IPC Path").selected() "Connecting to IPC:"
} else { } else {
connection_type_group.button(0, "IPC Path") "Connecting to TCP:"
} })
.with_name("ipc-path-radio"), .min_width(40),
) )
.child( .child(TextView::new("").with_name("connecting-text"))
EditView::new() } else {
.with_enabled(is_ipc) LinearLayout::vertical()
.on_submit(|s, _| Self::submit_ipc_path(s)) .child(TextView::new(" "))
.with_name("ipc-path") .child(
.fixed_height(1) if is_ipc {
.min_width(40), connection_type_group.button(0, "IPC Path").selected()
) } else {
.child( connection_type_group.button(0, "IPC Path")
if is_ipc { }
connection_type_group.button(1, "Network Address") .with_name("ipc-path-radio"),
} else { )
connection_type_group .child(
.button(1, "Network Address") EditView::new()
.selected() .with_enabled(is_ipc)
} .on_submit(|s, _| Self::submit_ipc_path(s))
.with_name("network-address-radio"), .with_name("ipc-path")
) .fixed_height(1)
.child( .min_width(40),
EditView::new() )
.with_enabled(!is_ipc) .child(TextView::new(" "))
.on_submit(|s, _| Self::submit_network_address(s)) .child(
.with_name("network-address") if is_ipc {
.fixed_height(1) connection_type_group.button(1, "Network Address")
.min_width(40), } else {
), connection_type_group
), .button(1, "Network Address")
) .selected()
.title("Connect to server") }
.with_name("network-address-radio"),
)
.child(
EditView::new()
.with_enabled(!is_ipc)
.on_submit(|s, _| Self::submit_network_address(s))
.with_name("network-address")
.fixed_height(1)
.min_width(40),
)
.child(TextView::new(" "))
})
.title(if connecting {
"Connecting to server..."
} else {
"Connect to server"
})
.with_name("connection-dialog"), .with_name("connection-dialog"),
); );
return true; return true;
} }
if reset {
let mut dlg = Self::connection_dialog(s);
dlg.clear_buttons();
return true;
}
false false
} }
@ -755,7 +778,7 @@ impl UI {
fn refresh_connection_dialog(s: &mut Cursive) { fn refresh_connection_dialog(s: &mut Cursive) {
let new_state = Self::inner(s).ui_state.connection_state.get().clone(); let new_state = Self::inner(s).ui_state.connection_state.get().clone();
if !Self::show_connection_dialog(s, new_state.clone()) { if !Self::draw_connection_dialog(s, new_state.clone()) {
return; return;
} }
@ -786,15 +809,8 @@ impl UI {
} }
ConnectionState::ConnectedTCP(_, _) | ConnectionState::ConnectedIPC(_, _) => {} ConnectionState::ConnectedTCP(_, _) | ConnectionState::ConnectedIPC(_, _) => {}
ConnectionState::RetryingTCP(addr, _) => { ConnectionState::RetryingTCP(addr, _) => {
Self::ipc_path_radio(s).set_enabled(false); let mut text = Self::connecting_text(s);
Self::network_address_radio(s).set_enabled(false); text.set_content(addr.to_string());
//
let mut edit = Self::network_address(s);
edit.set_content(addr.to_string());
edit.set_enabled(false);
Self::ipc_path(s).set_enabled(false);
let mut dlg = Self::connection_dialog(s); let mut dlg = Self::connection_dialog(s);
dlg.add_button("Cancel", |s| { dlg.add_button("Cancel", |s| {
@ -802,15 +818,8 @@ impl UI {
}); });
} }
ConnectionState::RetryingIPC(ipc_path, _) => { ConnectionState::RetryingIPC(ipc_path, _) => {
Self::ipc_path_radio(s).set_enabled(false); let mut text = Self::connecting_text(s);
Self::network_address_radio(s).set_enabled(false); text.set_content(ipc_path.to_string_lossy().to_string());
//
let mut edit = Self::ipc_path(s);
edit.set_content(ipc_path.to_string_lossy().to_string());
edit.set_enabled(false);
Self::network_address(s).set_enabled(false);
let mut dlg = Self::connection_dialog(s); let mut dlg = Self::connection_dialog(s);
dlg.add_button("Cancel", |s| { dlg.add_button("Cancel", |s| {

View file

@ -110,6 +110,12 @@ impl ClientApi {
} }
async fn handle_ipc_incoming(self, ipc_path: PathBuf) -> std::io::Result<()> { async fn handle_ipc_incoming(self, ipc_path: PathBuf) -> std::io::Result<()> {
if ipc_path.exists() {
if let Err(e) = std::fs::remove_file(&ipc_path) {
error!("Binding failed because IPC path is in use: {}\nAnother copy of this application may be using the same IPC path.", e);
return Err(e);
}
}
let listener = IpcListener::bind(ipc_path.clone()).await?; let listener = IpcListener::bind(ipc_path.clone()).await?;
debug!("IPC Client API listening on: {:?}", ipc_path); debug!("IPC Client API listening on: {:?}", ipc_path);
@ -137,6 +143,12 @@ impl ClientApi {
// Wait for all connections to terminate // Wait for all connections to terminate
awg.wait().await; awg.wait().await;
// Clean up IPC path
if let Err(e) = std::fs::remove_file(&ipc_path) {
warn!("Unable to remove IPC socket: {}", e);
return Err(e);
}
Ok(()) Ok(())
} }

View file

@ -180,9 +180,6 @@ fn main() -> EyreResult<()> {
settingsrw.daemon.enabled = false; settingsrw.daemon.enabled = false;
} }
if let Some(subnode_index) = args.subnode_index { if let Some(subnode_index) = args.subnode_index {
if subnode_index == 0 {
bail!("value of subnode_index should be between 1 and 65535");
}
settingsrw.testing.subnode_index = subnode_index; settingsrw.testing.subnode_index = subnode_index;
}; };

View file

@ -18,7 +18,7 @@ pub fn load_default_config() -> EyreResult<config::Config> {
daemon: daemon:
enabled: false enabled: false
client_api: client_api:
ipc_enabled: false ipc_enabled: true
ipc_directory: '%IPC_DIRECTORY%' ipc_directory: '%IPC_DIRECTORY%'
network_enabled: false network_enabled: false
listen_address: 'localhost:5959' listen_address: 'localhost:5959'