ppc login works in mme main
This commit is contained in:
@@ -59,13 +59,13 @@ impl ConfigOptId {
|
||||
opt.fun = Some(fun);
|
||||
self.clone()
|
||||
}
|
||||
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(self, name: &str, fun: F) -> ConfigOptId {
|
||||
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(self, name: &str, signature: &str, fun: F) -> ConfigOptId {
|
||||
let mize = get_global_mize().unwrap();
|
||||
let mut cur_part = self.id.clone();
|
||||
let id = cur_part.join(name).unwrap();
|
||||
// in generate mode: record method metadata, skip normal registration
|
||||
if mize.is_generate_mode().unwrap_or(false) {
|
||||
mize.record_method(name, id.clone(), "method").ok();
|
||||
mize.record_method(name, id.clone(), "method", signature).ok();
|
||||
return self.clone();
|
||||
}
|
||||
let mut opts = mize.config_opts.lock().unwrap();
|
||||
@@ -118,13 +118,13 @@ pub fn opt(name: &str) -> crate::config::ConfigOptId {
|
||||
ConfigOptId { id }
|
||||
}
|
||||
|
||||
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, fun: F) -> ConfigOptId {
|
||||
pub fn method<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(name: &str, signature: &str, fun: F) -> ConfigOptId {
|
||||
let mize = get_global_mize().unwrap();
|
||||
let mut cur_part = mize.cur_eval_part.lock().unwrap().clone().unwrap();
|
||||
let id = cur_part.join(name).unwrap();
|
||||
// in generate mode: record method metadata, skip normal registration
|
||||
if mize.is_generate_mode().unwrap_or(false) {
|
||||
mize.record_method(name, id.clone(), "method").ok();
|
||||
mize.record_method(name, id.clone(), "method", signature).ok();
|
||||
return ConfigOptId { id };
|
||||
}
|
||||
let mut opts = mize.config_opts.lock().unwrap();
|
||||
@@ -146,7 +146,7 @@ pub fn effect<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(n
|
||||
let id = cur_part.join(name).unwrap();
|
||||
// in generate mode: record effect metadata, skip normal registration
|
||||
if mize.is_generate_mode().unwrap_or(false) {
|
||||
mize.record_method(name, id.clone(), "effect").ok();
|
||||
mize.record_method(name, id.clone(), "effect", "").ok();
|
||||
return ConfigOptId { id };
|
||||
}
|
||||
let mut opts = mize.config_opts.lock().unwrap();
|
||||
@@ -168,7 +168,7 @@ pub fn thread<F: Fn(ItemData) -> MizeResult<ItemData> + Send + Sync + 'static>(n
|
||||
let id = cur_part.join(name).unwrap();
|
||||
// in generate mode: record thread metadata, skip normal registration
|
||||
if mize.is_generate_mode().unwrap_or(false) {
|
||||
mize.record_method(name, id.clone(), "thread").ok();
|
||||
mize.record_method(name, id.clone(), "thread", "").ok();
|
||||
return ConfigOptId { id };
|
||||
}
|
||||
let mut opts = mize.config_opts.lock().unwrap();
|
||||
@@ -199,11 +199,15 @@ pub mod c_api {
|
||||
super::opt(&string)
|
||||
}
|
||||
}
|
||||
pub extern "C" fn method(name: *const c_char, c_fun: CFun) -> ConfigOptId {
|
||||
pub extern "C" fn method(name: *const c_char, signature: *const c_char, c_fun: CFun) -> ConfigOptId {
|
||||
unsafe {
|
||||
let c_str = CStr::from_ptr(name);
|
||||
let string = c_str.to_string_lossy();
|
||||
super::method(&string, move |args| {
|
||||
let name_str = CStr::from_ptr(name).to_string_lossy();
|
||||
let sig_str = if signature.is_null() {
|
||||
String::new()
|
||||
} else {
|
||||
CStr::from_ptr(signature).to_string_lossy().into_owned()
|
||||
};
|
||||
super::method(&name_str, &sig_str, move |args| {
|
||||
let raw_ptr = Box::into_raw(Box::new(args));
|
||||
let ret_ptr = c_fun(raw_ptr);
|
||||
let data = *Box::from_raw(ret_ptr);
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::fmt::Debug;
|
||||
use std::fmt::Display;
|
||||
use std::io;
|
||||
use std::string::FromUtf8Error;
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use crate::prelude::*;
|
||||
|
||||
//use crate::proto::MizeMessage;
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::{thread, vec};
|
||||
use tracing::{debug, info, trace};
|
||||
|
||||
use crate::set_global_mize;
|
||||
use crate::config::{ConfigOpt, ConfigOptId, MizeFun};
|
||||
@@ -24,6 +23,7 @@ use crate::memstore::MemStore;
|
||||
use crate::mize_err;
|
||||
use crate::proto::MizeMessage;
|
||||
use crate::error::IntoMizeResult;
|
||||
use crate::prelude::*;
|
||||
|
||||
use self::connection::{ConnListener, Connection};
|
||||
use self::updater::handle_operation;
|
||||
@@ -47,7 +47,7 @@ mod tests;
|
||||
|
||||
static MSG_CHANNEL_SIZE: usize = 200;
|
||||
|
||||
static BUILD_TIME_CONFIG: &str = include_str!(std::env!("MIZE_BUILD_CONFIG"));
|
||||
static BUILD_TIME_CONFIG: &str = std::env!("MIZE_BUILD_CONFIG");
|
||||
|
||||
/// The Instance type is the heart of the mize system
|
||||
#[derive(Clone)]
|
||||
@@ -121,6 +121,35 @@ pub struct MethodMetadata {
|
||||
pub name: String,
|
||||
pub id: MizeId,
|
||||
pub kind: String, // "method", "effect", "thread"
|
||||
/// Raw signature string, e.g. `"String -> ()"` or `"Command, Func -> ()"`.
|
||||
pub signature: String,
|
||||
/// Parsed argument type names (left of `->`).
|
||||
pub arg_types: Vec<String>,
|
||||
/// Parsed return type name (right of `->`). Empty means unspecified / ItemData.
|
||||
pub return_type: String,
|
||||
}
|
||||
|
||||
/// Parse a method signature like `"String -> ()"` or `"Command, Func -> ()"`.
|
||||
/// Returns `(arg_types, return_type)` where `return_type` is empty if no `->` was given.
|
||||
pub fn parse_method_signature(signature: &str) -> (Vec<String>, String) {
|
||||
let signature = signature.trim();
|
||||
if signature.is_empty() {
|
||||
return (Vec::new(), String::new());
|
||||
}
|
||||
let (args_part, ret_part) = match signature.split_once("->") {
|
||||
Some((a, r)) => (a.trim(), r.trim().to_string()),
|
||||
None => (signature, String::new()),
|
||||
};
|
||||
let arg_types = if args_part.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
args_part
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect()
|
||||
};
|
||||
(arg_types, ret_part)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -129,6 +158,10 @@ pub struct NativeMetadata {
|
||||
pub type_name: String,
|
||||
pub associated: Vec<String>,
|
||||
pub methods: Vec<String>,
|
||||
/// Signature strings parallel to `associated`.
|
||||
pub associated_sigs: Vec<String>,
|
||||
/// Signature strings parallel to `methods`.
|
||||
pub method_sigs: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct InstanceRef {
|
||||
@@ -146,8 +179,8 @@ impl PartRef {
|
||||
}
|
||||
|
||||
impl MizePart for PartRef {
|
||||
fn id(&self) -> MizeId {
|
||||
self.id.clone()
|
||||
fn id(&self) -> MizeResult<MizeId> {
|
||||
Ok(self.id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,11 +193,15 @@ pub struct InstanceAsync {
|
||||
}
|
||||
|
||||
pub trait MizePart {
|
||||
fn id(&self) -> MizeId;
|
||||
fn id(&self) -> MizeResult<MizeId>;
|
||||
}
|
||||
|
||||
impl Mize {
|
||||
pub fn empty() -> MizeResult<Mize> {
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build()?;
|
||||
let guard = runtime.enter();
|
||||
std::mem::forget(guard);
|
||||
|
||||
let id_pool = Arc::new(Mutex::new(VecStringPool::default()));
|
||||
let namespace_pool_raw = StringPool::default();
|
||||
let connections = Arc::new(Mutex::new(Vec::new()));
|
||||
@@ -206,9 +243,7 @@ impl Mize {
|
||||
part_metadata: Arc::new(Mutex::new(HashMap::new())),
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
runtime: Arc::new(Mutex::new(
|
||||
Runtime::new().mres_msg("Could not create async runtime")?,
|
||||
)),
|
||||
runtime: Arc::new(Mutex::new(runtime)),
|
||||
};
|
||||
|
||||
#[cfg(feature = "target-os")]
|
||||
@@ -244,7 +279,7 @@ impl Mize {
|
||||
console_log!("before loading build time config");
|
||||
|
||||
// load the config from build time
|
||||
let config = ItemData::from_toml(BUILD_TIME_CONFIG)?;
|
||||
let config = ItemData::from_json(BUILD_TIME_CONFIG.to_owned())?;
|
||||
instance.set_blocking("0", config);
|
||||
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
@@ -546,7 +581,7 @@ impl Mize {
|
||||
}
|
||||
|
||||
/// Record a method/effect/thread declaration while in generate mode.
|
||||
pub fn record_method(&self, name: &str, id: MizeId, kind: &str) -> MizeResult<()> {
|
||||
pub fn record_method(&self, name: &str, id: MizeId, kind: &str, signature: &str) -> MizeResult<()> {
|
||||
let cur_part = self.cur_eval_part.lock()?.clone()
|
||||
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
|
||||
let mut metadata_map = self.part_metadata.lock()?;
|
||||
@@ -554,10 +589,14 @@ impl Mize {
|
||||
part_name: cur_part.dot(),
|
||||
..Default::default()
|
||||
});
|
||||
let (arg_types, return_type) = parse_method_signature(signature);
|
||||
let m = MethodMetadata {
|
||||
name: name.to_string(),
|
||||
id,
|
||||
kind: kind.to_string(),
|
||||
signature: signature.to_string(),
|
||||
arg_types,
|
||||
return_type,
|
||||
};
|
||||
match kind {
|
||||
"effect" => metadata.effects.push(m),
|
||||
@@ -568,7 +607,15 @@ impl Mize {
|
||||
}
|
||||
|
||||
/// Record a native type inclusion while in generate mode.
|
||||
pub fn record_native(&self, name: &str, type_name: &str, associated: Vec<String>, methods: Vec<String>) -> MizeResult<()> {
|
||||
pub fn record_native(
|
||||
&self,
|
||||
name: &str,
|
||||
type_name: &str,
|
||||
associated: Vec<String>,
|
||||
methods: Vec<String>,
|
||||
associated_sigs: Vec<String>,
|
||||
method_sigs: Vec<String>,
|
||||
) -> MizeResult<()> {
|
||||
let cur_part = self.cur_eval_part.lock()?.clone()
|
||||
.ok_or_else(|| mize_err!("no cur_eval_part set"))?;
|
||||
let mut metadata_map = self.part_metadata.lock()?;
|
||||
@@ -581,6 +628,8 @@ impl Mize {
|
||||
type_name: type_name.to_string(),
|
||||
associated,
|
||||
methods,
|
||||
associated_sigs,
|
||||
method_sigs,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
@@ -805,12 +854,15 @@ impl Mize {
|
||||
) -> MizeResult<()> {
|
||||
let mut threads_inner = self.threads.lock()?;
|
||||
let mut next_thread_id = self.next_thread_id.lock()?;
|
||||
let tokio_handle = tokio::runtime::Handle::current();
|
||||
|
||||
let my_thread_id_no_mutex_guard = *next_thread_id;
|
||||
let _thread_mutex = self.threads.clone();
|
||||
let name_to_move = name.to_owned();
|
||||
let to_spawn = move || -> () {
|
||||
debug!("spawning thread: {}", name_to_move);
|
||||
let guard = tokio_handle.enter();
|
||||
std::mem::forget(guard);
|
||||
let _my_thread_id = my_thread_id_no_mutex_guard;
|
||||
|
||||
let res = func();
|
||||
@@ -883,8 +935,8 @@ impl Mize {
|
||||
let mut next_thread_id = self.next_thread_id.lock()?;
|
||||
|
||||
threads_inner.push((*next_thread_id, name.to_owned(), None));
|
||||
let runtime_inner = self.runtime.lock().unwrap();
|
||||
runtime_inner.spawn(func);
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
runtime.spawn(func);
|
||||
|
||||
*next_thread_id += 1;
|
||||
|
||||
@@ -893,9 +945,7 @@ impl Mize {
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub fn async_get_handle(&self) -> Handle {
|
||||
let runtime_inner = self.runtime.lock().unwrap();
|
||||
let handle = runtime_inner.handle().to_owned();
|
||||
handle
|
||||
tokio::runtime::Handle::current()
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
@@ -916,16 +966,13 @@ impl Mize {
|
||||
.expect("mutex lock failed in spawn_async_blocking");
|
||||
|
||||
threads_inner.push((*next_thread_id, name.to_owned(), None));
|
||||
let runtime_inner = self.runtime.lock().unwrap();
|
||||
let handle = runtime_inner.handle().to_owned();
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
*next_thread_id += 1;
|
||||
|
||||
drop(runtime_inner);
|
||||
drop(threads_inner);
|
||||
drop(next_thread_id);
|
||||
|
||||
handle.enter();
|
||||
let result = handle.block_on(func);
|
||||
let result = runtime.block_on(func);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -958,24 +1005,29 @@ impl Mize {
|
||||
|
||||
let mut opt = config_opts
|
||||
.get_mut(&id)
|
||||
.ok_or_else(|| mize_err!("Config opt for {name} not in config_opts"))?;
|
||||
.ok_or_else(|| mize_err!("Config opt for {id} not in config_opts"))?;
|
||||
|
||||
if let Some(val) = opt.val.clone() {
|
||||
return Ok(val);
|
||||
}
|
||||
|
||||
// in case it is not cached run the fun if it exists
|
||||
if let Some(fun) = &opt.fun {
|
||||
if opt.fun.is_some() {
|
||||
let fun = opt.fun.take().unwrap();
|
||||
drop(config_opts);
|
||||
let res = fun()?;
|
||||
let mut config_opts = self.config_opts.lock().unwrap();
|
||||
let mut opt = config_opts.get_mut(&id).unwrap();
|
||||
opt.fun = Some(fun);
|
||||
opt.val = Some(res.clone());
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
Err(mize_err!("ConfigOpt {name} has no fun and no cached value"))
|
||||
Err(mize_err!("ConfigOpt {id} has no fun and no cached value"))
|
||||
}
|
||||
|
||||
pub fn dyn_call(&mut self, part_id: MizeId, method: &str, args: ItemData) -> MizeResult<ItemData> {
|
||||
debug!("dyn call {}.{} with args: {}", part_id, method, args);
|
||||
debug!("dyn call {}/{} with args: {}", part_id, method, args);
|
||||
let mut fun_values = self.fun_values.lock()?;
|
||||
|
||||
let id = part_id.clone().join(method)?;
|
||||
@@ -985,7 +1037,9 @@ impl Mize {
|
||||
|
||||
let calling_part = self.clone().cur_eval_part()?;
|
||||
self.clone().set_cur_eval_part(Some(part_id));
|
||||
println!("before call");
|
||||
let res = fun(args);
|
||||
println!("after call");
|
||||
self.clone().set_cur_eval_part(calling_part);
|
||||
let mut fun_values = self.fun_values.lock()?;
|
||||
fun_values.insert(id, fun);
|
||||
|
||||
@@ -2,13 +2,13 @@ use core::fmt;
|
||||
use flume::Sender;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::error::MizeResult;
|
||||
use crate::id::MizeId;
|
||||
use crate::instance::connection::Connection;
|
||||
use crate::item::Item;
|
||||
use crate::proto::MizeMessage;
|
||||
use crate::prelude::*;
|
||||
|
||||
use super::Mize;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use flume::Receiver;
|
||||
use std::borrow::BorrowMut;
|
||||
use std::sync::Arc;
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use crate::error::{MizeError, MizeResult, MizeResultTrait};
|
||||
use crate::id::MizeId;
|
||||
use crate::mize_err;
|
||||
use crate::prelude::*;
|
||||
use crate::proto::{MessageCmd, MizeMessage};
|
||||
use crate::{instance::Mize, item::ItemData};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::{config, get_global_mize};
|
||||
use crate::config::{ConfigOpt, FromItemData, MizeFun};
|
||||
use ciborium::into_writer;
|
||||
use ciborium::from_reader;
|
||||
use colored::Colorize;
|
||||
use serde_json::from_reader;
|
||||
use serde::de::DeserializeOwned;
|
||||
use core::fmt;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -13,7 +14,8 @@ use std::sync::MutexGuard;
|
||||
use std::{boxed, io};
|
||||
use std::fmt::Display;
|
||||
use std::i128;
|
||||
use tracing::{debug, instrument, trace, warn};
|
||||
use crate::tracing::instrument;
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::error::{IntoMizeResult, MizeError, MizeErrorWhichImplementsError, MizeResult};
|
||||
use crate::id::MizeId;
|
||||
@@ -256,7 +258,12 @@ impl ItemData {
|
||||
let fun_num = self.get_path("_fun_num")?.value_u32()?;
|
||||
let fun_id = mize.clone().id_new_dots("mize.fun")?.join(format!("{fun_num}").as_str())?;
|
||||
let fun = fun_values.remove(&fun_id).ok_or(mize_err!("fun with id {fun_id} not in fun_values"))?;
|
||||
|
||||
drop(fun_values);
|
||||
let res = fun(args)?;
|
||||
let mut fun_values = mize.fun_values.lock()?;
|
||||
fun_values.insert(fun_id, fun);
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
@@ -406,6 +413,13 @@ impl ItemData {
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn deserialize<T: Serialize + DeserializeOwned>(&self) -> MizeResult<T> {
|
||||
let mut buffer = Vec::new();
|
||||
into_writer(&self, &mut buffer)?;
|
||||
let cbor_val: T = from_reader(buffer.as_slice())?;
|
||||
Ok(cbor_val)
|
||||
}
|
||||
|
||||
/// Get an immutable reference to the native value stored in this ItemData.
|
||||
///
|
||||
/// If the ItemData has a `_native` field (stored via `from_native()`), returns a guard
|
||||
@@ -467,6 +481,7 @@ impl ItemData {
|
||||
///
|
||||
/// Otherwise, constructs the value via `T::from_itemdata(self)`, stores it in the
|
||||
/// registry, and returns a guard to it.
|
||||
/// i hate rust. (as you can't have a generic FromItemData impl and then more specific ones.)
|
||||
pub fn native_from<T: FromItemData + Any + Send + Sync + 'static>(&self) -> MizeResult<NativeRefGuard<T>> {
|
||||
// Fast path: the registry already holds a T for this ItemData
|
||||
if let Some(id) = self.try_get_native_id() {
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::fmt::format;
|
||||
macro_rules! out {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!($($arg)*)) {
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("{}\n", format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
@@ -17,7 +17,7 @@ macro_rules! out {
|
||||
}
|
||||
|
||||
pub fn write_to_mize_stdout(args: std::fmt::Arguments) -> MizeResult<()> {
|
||||
println!("{}", args);
|
||||
print!("{}", args);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -84,8 +84,11 @@ pub mod prelude {
|
||||
pub use config::*;
|
||||
pub use api::*;
|
||||
pub use mize_macros::*;
|
||||
pub use crate::tracing::{trace, warn, debug, info, error};
|
||||
}
|
||||
pub use flume;
|
||||
use tokio::runtime::Builder;
|
||||
use tokio::runtime::Runtime;
|
||||
pub use tracing;
|
||||
|
||||
|
||||
@@ -108,13 +111,15 @@ pub use error::MizeError;
|
||||
pub use error::MizeResult;
|
||||
pub use instance::Mize;
|
||||
pub use instance::{
|
||||
MizePart, PartMetadata, OptMetadata, MethodMetadata, NativeMetadata,
|
||||
MizePart, PartMetadata, OptMetadata, MethodMetadata, NativeMetadata, parse_method_signature,
|
||||
};
|
||||
pub use mize_macros::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use std::sync::{Arc, Mutex, OnceLock};
|
||||
|
||||
use crate::platform::os;
|
||||
|
||||
/// Global Mize instance storage.
|
||||
/// This is set once when the Mize instance is created and can be accessed from anywhere.
|
||||
pub static GLOBAL_MIZE: OnceLock<Arc<Mutex<Mize>>> = OnceLock::new();
|
||||
@@ -144,9 +149,32 @@ pub fn set_global_mize(mize: Mize) -> MizeResult<()> {
|
||||
|
||||
/// C API function to set the global Mize instance from a dynamically loaded part.
|
||||
/// This is a hack to allow Rust parts loaded as .so files to access the global Mize instance.
|
||||
// i hate rust.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn mize_rust_hack_set_global(mize: Arc<Mutex<Mize>>) {
|
||||
pub extern "C" fn mize_rust_hack_set_global(mize: Arc<Mutex<Mize>>, dispatch_ptr: *const std::ffi::c_void) {
|
||||
// and also set the tokio runtime
|
||||
//let mize_locked = mize.lock().unwrap();
|
||||
//let rt = mize_locked.runtime.lock().unwrap();
|
||||
//rt.enter();
|
||||
//drop(rt);
|
||||
//drop(mize_locked);
|
||||
let rt = Builder::new_multi_thread().enable_all().build().unwrap();
|
||||
let guard = rt.enter();
|
||||
std::mem::forget(guard);
|
||||
|
||||
use crate::tracing::Dispatch;
|
||||
let _ = GLOBAL_MIZE.set(mize);
|
||||
|
||||
//and also init tracing
|
||||
unsafe {
|
||||
/// i hate rust.
|
||||
let dispatch = &*(dispatch_ptr as *const Dispatch);
|
||||
if let Err(e) = tracing::dispatcher::set_global_default(dispatch.clone()) {
|
||||
println!("failed to set tracing dispatcher: {e}");
|
||||
}
|
||||
tracing::callsite::rebuild_interest_cache();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Resolve an executable name to its full path in the nixpkgs store.
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::collections::binary_heap::Iter;
|
||||
use std::collections::HashMap;
|
||||
use std::iter::Map;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tracing::{instrument, trace};
|
||||
use crate::tracing::instrument;
|
||||
|
||||
use crate::error::{IntoMizeResult, MizeError, MizeResult};
|
||||
use crate::id::MizeId;
|
||||
@@ -13,6 +13,7 @@ use crate::instance::Mize;
|
||||
use crate::item::get_raw_from_cbor;
|
||||
use crate::item::{Item, ItemData};
|
||||
use crate::mize_err;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MemStore {
|
||||
|
||||
@@ -4,7 +4,6 @@ use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::id::MizeId;
|
||||
use crate::item::{Item, ItemData};
|
||||
@@ -15,6 +14,9 @@ use crate::item::get_raw_from_cbor;
|
||||
use crate::item::IntoItemData;
|
||||
use crate::memstore::MemStore;
|
||||
use crate::{instance::store::Store, mize_err};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
use tokio::net::UnixStream;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -72,6 +74,7 @@ impl FileStore {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
|
||||
match UnixStream::connect(PathBuf::from(store_path).join("sock")).await {
|
||||
Err(_) => Err(mize_err!("")),
|
||||
@@ -79,6 +82,21 @@ async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
async fn try_connect_to_sock(store_path: String) -> MizeResult<()> {
|
||||
use tokio::net::windows::named_pipe::{ClientOptions};
|
||||
let pipe_name = format!(
|
||||
"\\.\\pipe\\mize_{}",
|
||||
store_path.replace('\\', "_").replace('/', "_").replace(':', "_")
|
||||
);
|
||||
// ClientOptions::new().open() is synchronous, not async
|
||||
// So we just try to open and immediately close it
|
||||
match ClientOptions::new().open(&pipe_name) {
|
||||
Err(_) => Err(mize_err!("")),
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
impl Store for FileStore {
|
||||
fn new_id(&self) -> MizeResult<String> {
|
||||
let mut next_id: u64 =
|
||||
@@ -191,6 +209,7 @@ impl Store for FileStore {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
fn valid_pid_file(path: &Path) -> MizeResult<Option<u32>> {
|
||||
let pid_file_path = path.join("pid");
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing::Event;
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use tracing::{Dispatch, Event};
|
||||
use tracing::{field::Visit, Id, Subscriber};
|
||||
use tracing::{span_enabled, Instrument, Level};
|
||||
use tracing_core::Field;
|
||||
@@ -29,10 +28,65 @@ use crate::id::MizeId;
|
||||
use crate::item::ItemData;
|
||||
use crate::MizeError;
|
||||
use crate::MizeResult;
|
||||
use crate::prelude::*;
|
||||
|
||||
static DEFAULT_LOG_LEVEL: LevelFilter = LevelFilter::WARN;
|
||||
|
||||
pub fn init_logger(cli_matches: &ArgMatches) {
|
||||
|
||||
/*
|
||||
#[macro_export]
|
||||
macro_rules! trace {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::yellow("TRACE"), format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! debug {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::green("DEBUG"), format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! info {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::blue("INFO"), format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! warn {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::truecolor("WARN", 245, 164, 66), format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! error {
|
||||
($($arg:tt)*) => {
|
||||
// format_args! handles string interpolation safely at compile time
|
||||
if let Err(e) = $crate::write_to_mize_stdout(format_args!("[ {} ] {}\n", colored::Colorize::red("ERROR"), format_args!($($arg)*))) {
|
||||
// Choose your error handling behavior here (panic, print to stderr, or ignore)
|
||||
eprintln!("out! macro failed to write!!");
|
||||
}
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn init_logger(cli_matches: Option<&ArgMatches>) {
|
||||
trace!("init_logger called");
|
||||
// to save log messages, before the logger is setup
|
||||
let mut log_messages: Vec<(Level, String)> = Vec::new();
|
||||
@@ -96,67 +150,69 @@ pub fn init_logger(cli_matches: &ArgMatches) {
|
||||
log_messages.append(&mut val_mize_log.1);
|
||||
|
||||
// check -vvvvv flags
|
||||
let v_flag_count = cli_matches.get_count("verbose");
|
||||
if v_flag_count > 0 {
|
||||
let default_log_level_as_num = match DEFAULT_LOG_LEVEL {
|
||||
LevelFilter::OFF => 0,
|
||||
LevelFilter::ERROR => 1,
|
||||
LevelFilter::WARN => 2,
|
||||
LevelFilter::INFO => 3,
|
||||
LevelFilter::DEBUG => 4,
|
||||
LevelFilter::TRACE => 5,
|
||||
};
|
||||
let new_log_level_num = default_log_level_as_num + v_flag_count;
|
||||
log_level = match new_log_level_num {
|
||||
0 => LevelFilter::OFF,
|
||||
1 => LevelFilter::ERROR,
|
||||
2 => LevelFilter::WARN,
|
||||
3 => LevelFilter::INFO,
|
||||
4 => LevelFilter::DEBUG,
|
||||
5 => LevelFilter::TRACE,
|
||||
_ => {
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!(
|
||||
"the number of verbose (-v) flags passed ({}) exeeds the maximumg log_level",
|
||||
v_flag_count
|
||||
),
|
||||
));
|
||||
LevelFilter::TRACE
|
||||
}
|
||||
};
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!("set log level from the verbose flags to {}", log_level),
|
||||
));
|
||||
}
|
||||
if let Some(cli_matches) = cli_matches {
|
||||
let v_flag_count = cli_matches.get_count("verbose");
|
||||
if v_flag_count > 0 {
|
||||
let default_log_level_as_num = match DEFAULT_LOG_LEVEL {
|
||||
LevelFilter::OFF => 0,
|
||||
LevelFilter::ERROR => 1,
|
||||
LevelFilter::WARN => 2,
|
||||
LevelFilter::INFO => 3,
|
||||
LevelFilter::DEBUG => 4,
|
||||
LevelFilter::TRACE => 5,
|
||||
};
|
||||
let new_log_level_num = default_log_level_as_num + v_flag_count;
|
||||
log_level = match new_log_level_num {
|
||||
0 => LevelFilter::OFF,
|
||||
1 => LevelFilter::ERROR,
|
||||
2 => LevelFilter::WARN,
|
||||
3 => LevelFilter::INFO,
|
||||
4 => LevelFilter::DEBUG,
|
||||
5 => LevelFilter::TRACE,
|
||||
_ => {
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!(
|
||||
"the number of verbose (-v) flags passed ({}) exeeds the maximumg log_level",
|
||||
v_flag_count
|
||||
),
|
||||
));
|
||||
LevelFilter::TRACE
|
||||
}
|
||||
};
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!("set log level from the verbose flags to {}", log_level),
|
||||
));
|
||||
}
|
||||
|
||||
// check --log-level arg
|
||||
if let Some(log_level_arg_string) = cli_matches.get_one::<String>("log-level") {
|
||||
let log_level_from_arg = match log_level_arg_string.to_owned().to_lowercase().as_str() {
|
||||
"none" => LevelFilter::OFF,
|
||||
"trace" => LevelFilter::TRACE,
|
||||
"debug" => LevelFilter::DEBUG,
|
||||
"info" => LevelFilter::INFO,
|
||||
"warn" => LevelFilter::WARN,
|
||||
"error" => LevelFilter::ERROR,
|
||||
_ => {
|
||||
log_messages.push((Level::WARN, format!(
|
||||
"The argument to --log-level \"{}\" is not a valid log-level. loglevel stays at: {}"
|
||||
, log_level_arg_string
|
||||
, log_level
|
||||
)));
|
||||
log_level
|
||||
}
|
||||
};
|
||||
log_level = log_level_from_arg;
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!(
|
||||
"set log level from the --log-level arg to {}",
|
||||
log_level_from_arg
|
||||
),
|
||||
));
|
||||
// check --log-level arg
|
||||
if let Some(log_level_arg_string) = cli_matches.get_one::<String>("log-level") {
|
||||
let log_level_from_arg = match log_level_arg_string.to_owned().to_lowercase().as_str() {
|
||||
"none" => LevelFilter::OFF,
|
||||
"trace" => LevelFilter::TRACE,
|
||||
"debug" => LevelFilter::DEBUG,
|
||||
"info" => LevelFilter::INFO,
|
||||
"warn" => LevelFilter::WARN,
|
||||
"error" => LevelFilter::ERROR,
|
||||
_ => {
|
||||
log_messages.push((Level::WARN, format!(
|
||||
"The argument to --log-level \"{}\" is not a valid log-level. loglevel stays at: {}"
|
||||
, log_level_arg_string
|
||||
, log_level
|
||||
)));
|
||||
log_level
|
||||
}
|
||||
};
|
||||
log_level = log_level_from_arg;
|
||||
log_messages.push((
|
||||
Level::TRACE,
|
||||
format!(
|
||||
"set log level from the --log-level arg to {}",
|
||||
log_level_from_arg
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// actually set the log_level on the builder
|
||||
@@ -181,13 +237,18 @@ pub fn init_logger(cli_matches: &ArgMatches) {
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
builder
|
||||
let subscriber = builder
|
||||
//.with_env_filter(my_env_filter)
|
||||
.without_time()
|
||||
.event_format(MyFormatter)
|
||||
.fmt_fields(field_formatter)
|
||||
.with_max_level(log_level)
|
||||
.init();
|
||||
.finish();
|
||||
|
||||
let dispatch = Dispatch::new(subscriber);
|
||||
if let Err(e) = tracing::dispatcher::set_global_default(dispatch) {
|
||||
println!("faild to set_global_default(dispatch): {e}");
|
||||
}
|
||||
|
||||
// write out all log messages from log_messages
|
||||
for (level, msg) in log_messages {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use clap::ArgMatches;
|
||||
use colored::Colorize;
|
||||
use tracing::Dispatch;
|
||||
use core::fmt;
|
||||
use flate2::bufread::GzDecoder;
|
||||
use sha2::{Digest, Sha256};
|
||||
@@ -12,7 +13,6 @@ use std::path::PathBuf;
|
||||
use std::time::UNIX_EPOCH;
|
||||
use tar::Archive;
|
||||
use tracing::Event;
|
||||
use tracing::{debug, info, trace, warn};
|
||||
use tracing::field::Visit;
|
||||
use tracing::Level;
|
||||
use tracing_core::Field;
|
||||
@@ -25,12 +25,8 @@ use tracing_subscriber::registry::LookupSpan;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::GLOBAL_MIZE;
|
||||
use crate::config::ConfigOpt;
|
||||
use crate::error::{IntoMizeResult, MizeResult};
|
||||
use crate::instance::Mize;
|
||||
use crate::item::{data_from_string, IntoItemData, ItemData};
|
||||
use crate::mize_err;
|
||||
use crate::prelude::*;
|
||||
use crate::item::data_from_string;
|
||||
|
||||
use self::fsstore::FileStore;
|
||||
|
||||
@@ -40,8 +36,14 @@ pub mod logging;
|
||||
#[cfg(target_family = "unix")]
|
||||
mod unix_socket;
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
mod windows_socket;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
use crate::platform::os::unix_socket::UnixListener;
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
use crate::platform::os::windows_socket::WindowsListener as UnixListener;
|
||||
//mod web;
|
||||
|
||||
pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
|
||||
@@ -133,7 +135,10 @@ pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
{
|
||||
error!("CONNECTING... would connect, but that is not implemented on windows yet");
|
||||
info!("CONNECTING");
|
||||
use crate::platform::os::windows_socket;
|
||||
windows_socket::connect(mize, store_path.into())?;
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
// else open it ourselves
|
||||
@@ -149,7 +154,7 @@ pub fn os_instance_init(mize: &mut Mize) -> MizeResult<()> {
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
{
|
||||
warn!("would add a Listener on a local socket, but that is not yet implemented for windows");
|
||||
mize.add_conn_listener(UnixListener::new(path)?)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,31 +278,33 @@ pub fn fetch_part(mize: &mut Mize, part_name: &str) -> MizeResult<String> {
|
||||
|
||||
fn get_part_path(mize: &mut Mize, part_name: &str, _path: Option<String>) -> MizeResult<String> {
|
||||
|
||||
let part_symbol_name = part_name.replace(".", "_");
|
||||
|
||||
// check if $name.src is set
|
||||
if let Ok(itm) = mize.get_config(format!("{part_name}.src").as_str()) {
|
||||
let part_src = itm.value_string().map_err(|e| e.msg(format!("opt {part_name}.src was not a string")))?;
|
||||
// will only work for rust for now
|
||||
let part_path = format!("{part_src}/target/debug/libmize_part_{part_name}.so");
|
||||
let part_path = format!("{part_src}/target/debug/libmize_part_{part_symbol_name}.so");
|
||||
return Ok(part_path);
|
||||
}
|
||||
|
||||
// check if $name.out is set
|
||||
if let Ok(itm) = mize.get_config(format!("{part_name}.out").as_str()) {
|
||||
let part_out = itm.value_string().map_err(|e| e.msg(format!("opt {part_name}.out was not a string")))?;
|
||||
let part_path = format!("{part_out}/lib/libmize_part_{part_name}.so");
|
||||
let part_path = format!("{part_out}/lib/libmize_part_{part_symbol_name}.so");
|
||||
return Ok(part_path);
|
||||
}
|
||||
|
||||
// check if we find the part inside mize.src
|
||||
if let Ok(itm) = mize.get_config("mize.src") {
|
||||
let mize_src = itm.value_string().map_err(|e| e.msg("opt mize.src was not a string"))?;
|
||||
let part_path = format!("{mize_src}/target/debug/libmize_part_{part_name}.so");
|
||||
let part_path = format!("{mize_src}/target/debug/libmize_part_{part_symbol_name}.so");
|
||||
return Ok(part_path);
|
||||
}
|
||||
|
||||
// fetch the part from https://mize.works
|
||||
let out_path = fetch_part(mize, part_name)?;
|
||||
return Ok(format!("{out_path}/lib/libmize_part_{part_name}.so"));
|
||||
return Ok(format!("{out_path}/lib/libmize_part_{part_symbol_name}.so"));
|
||||
|
||||
//Err(mize_err!("part {part_name} not found"))
|
||||
}
|
||||
@@ -308,16 +315,33 @@ pub fn load_part(mize: &mut Mize, part_name: &str, path: Option<String>) -> Mize
|
||||
let lib = unsafe { libloading::Library::new(part_path)? };
|
||||
|
||||
unsafe {
|
||||
if let Ok(rust_hack_func) = lib.get::<libloading::Symbol<unsafe extern "C" fn(Arc<Mutex<Mize>>)>>("mize_rust_hack_set_global".as_bytes()) {
|
||||
rust_hack_func(GLOBAL_MIZE.get().unwrap().clone())
|
||||
if let Ok(rust_hack_func) = lib.get::<libloading::Symbol<unsafe extern "C" fn(Arc<Mutex<Mize>>, *const std::ffi::c_void)>>("mize_rust_hack_set_global".as_bytes()) {
|
||||
|
||||
tracing::dispatcher::get_default(|dispatch| {
|
||||
rust_hack_func(GLOBAL_MIZE.get().unwrap().clone(), dispatch as *const Dispatch as *const std::ffi::c_void);
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
let part_symbol_name = part_name.replace(".", "_");
|
||||
|
||||
let func: libloading::Symbol<
|
||||
unsafe extern "C" fn() -> MizeResult<()>,
|
||||
> = unsafe { lib.get(format!("part_{}", part_name).as_bytes())? };
|
||||
> = unsafe { lib.get(format!("part_{}", part_symbol_name).as_bytes())? };
|
||||
|
||||
mize.clone().set_cur_eval_part(Some(mize.clone().id_new_dots(part_name)?))?;
|
||||
let part_id = mize.clone().id_new_dots(part_name)?;
|
||||
{
|
||||
let mut opts = mize.config_opts.lock()?;
|
||||
opts.entry(part_id.clone()).or_insert_with(|| ConfigOpt {
|
||||
name: part_name.to_owned(),
|
||||
val: Some(ItemData::new()),
|
||||
fun: None,
|
||||
deps: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
mize.clone().set_cur_eval_part(Some(part_id))?;
|
||||
unsafe { func()? };
|
||||
mize.clone().set_cur_eval_part(None)?;
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ use std::path::{Path, PathBuf};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt, Interest};
|
||||
use tokio::net::unix::{OwnedReadHalf, OwnedWriteHalf};
|
||||
use tokio::net::{UnixListener as TokioUnixListener, UnixStream};
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use crate::error::{IntoMizeResult, MizeError, MizeResult};
|
||||
use crate::instance::connection::{ConnListener, Connection};
|
||||
use crate::instance::{self, Mize};
|
||||
use crate::proto::{self, MizeMessage};
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct UnixListener {
|
||||
sock_path: PathBuf,
|
||||
|
||||
224
core/src/platform/os/windows_socket.rs
Normal file
224
core/src/platform/os/windows_socket.rs
Normal file
@@ -0,0 +1,224 @@
|
||||
// This module is only compiled on Windows
|
||||
// It provides the same functionality as unix_socket.rs but using Windows named pipes
|
||||
|
||||
use ciborium::Value as CborValue;
|
||||
use flume::{unbounded, Receiver, Sender};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use crate::error::{IntoMizeResult, MizeError, MizeResult};
|
||||
use crate::instance::connection::{ConnListener, Connection};
|
||||
use crate::instance::{self, Mize};
|
||||
use crate::proto::{self, MizeMessage};
|
||||
|
||||
pub struct WindowsListener {
|
||||
pipe_name: String,
|
||||
}
|
||||
|
||||
impl WindowsListener {
|
||||
pub fn new(store_path: PathBuf) -> MizeResult<WindowsListener> {
|
||||
// On Windows, we use a named pipe with a specific format
|
||||
// The format is \.\pipe\<name> for local pipes
|
||||
// We'll use the store path hash or name to create a unique pipe name
|
||||
let pipe_name = format!(
|
||||
"\\.\\pipe\\mize_{}",
|
||||
store_path.to_string_lossy().replace('\\', "_").replace('/', "_").replace(':', "_")
|
||||
);
|
||||
Ok(WindowsListener { pipe_name })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect(instance: &mut Mize, store_path: PathBuf) -> MizeResult<()> {
|
||||
let conn_id = instance.spawn_async_blocking(
|
||||
"windows_connection",
|
||||
connect_async(instance.clone(), store_path),
|
||||
)?;
|
||||
|
||||
let ns_of_peer_str = instance
|
||||
.get(format!(
|
||||
"inst/con_by_id/{}/peer/self/config/namespace",
|
||||
conn_id
|
||||
))?
|
||||
.value_string()?;
|
||||
let ns_of_peer = instance.namespace_from_string(ns_of_peer_str)?;
|
||||
|
||||
info!(
|
||||
"connect_async ... ns_of_peer: {}",
|
||||
ns_of_peer.clone().as_string()
|
||||
);
|
||||
|
||||
instance.connection_set_namespace(conn_id, ns_of_peer.clone());
|
||||
instance.set_namespace(ns_of_peer);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn connect_async(mut instance: Mize, store_path: PathBuf) -> MizeResult<u64> {
|
||||
let pipe_name = format!(
|
||||
"\\.\\pipe\\mize_{}",
|
||||
store_path.to_string_lossy().replace('\\', "_").replace('/', "_").replace(':', "_")
|
||||
);
|
||||
|
||||
// Create the client synchronously
|
||||
let client = ClientOptions::new().open(&pipe_name)?;
|
||||
|
||||
// Wrap the client in an Arc<Mutex> so it can be shared between incoming and outgoing tasks
|
||||
let shared_client = Arc::new(Mutex::new(client));
|
||||
|
||||
let (send_tx, send_rx) = unbounded::<MizeMessage>();
|
||||
|
||||
let conn_id = instance.new_connection(send_tx)?;
|
||||
|
||||
let cloned_instance = instance.clone();
|
||||
let incoming_client = shared_client.clone();
|
||||
instance.spawn_background("incomming", move || {
|
||||
let result = windows_incomming(incoming_client, cloned_instance, conn_id);
|
||||
if let Err(err) = result {
|
||||
warn!("Connection closing because of EOF: {:?}", err);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let outgoing_cloned_instance = instance.clone();
|
||||
let outgoing_client = shared_client.clone();
|
||||
instance.spawn_background("outgoing", move || {
|
||||
let result = windows_outgoing(outgoing_client, send_rx, outgoing_cloned_instance, conn_id);
|
||||
if let Err(err) = result {
|
||||
warn!("Connection closing because of EOF: {:?}", err);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
Ok(conn_id)
|
||||
}
|
||||
|
||||
impl ConnListener for WindowsListener {
|
||||
fn listen(self, mut instance: Mize) -> MizeResult<()> {
|
||||
instance.spawn_async("windows listen async", windows_listen(self, instance.clone()));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
async fn windows_listen(listener: WindowsListener, mut instance: Mize) -> MizeResult<()> {
|
||||
// Create the first server instance
|
||||
let mut server = ServerOptions::new()
|
||||
.first_pipe_instance(true)
|
||||
.create(&listener.pipe_name)?;
|
||||
|
||||
loop {
|
||||
// Wait for a client to connect
|
||||
server.connect().await.mres_msg("Error while accepting Windows named pipe connection")?;
|
||||
info!("new connection");
|
||||
|
||||
let (send_tx, send_rx) = unbounded::<MizeMessage>();
|
||||
let conn_id = instance.new_connection(send_tx)?;
|
||||
|
||||
// Take ownership of the current server (which is now connected)
|
||||
let connected_server = server;
|
||||
|
||||
// Create a new server for the next connection
|
||||
server = ServerOptions::new().create(&listener.pipe_name)?;
|
||||
|
||||
// Wrap the connected server in an Arc<Mutex> so it can be shared
|
||||
let shared_server = Arc::new(Mutex::new(connected_server));
|
||||
|
||||
let cloned_instance = instance.clone();
|
||||
let incoming_server = shared_server.clone();
|
||||
instance.spawn_background("incomming", move || {
|
||||
let result = windows_incomming(incoming_server, cloned_instance, conn_id);
|
||||
if let Err(err) = result {
|
||||
warn!("Connection closing because of EOF: {:?}", err);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let outgoing_cloned_instance = instance.clone();
|
||||
let outgoing_server = shared_server.clone();
|
||||
instance.spawn_background("outgoing", move || {
|
||||
let result = windows_outgoing(outgoing_server, send_rx, outgoing_cloned_instance, conn_id);
|
||||
if let Err(err) = result {
|
||||
warn!("Connection closing because of EOF: {:?}", err);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn windows_outgoing<W>(shared_pipe: Arc<Mutex<W>>, send_rx: Receiver<MizeMessage>, mut instance: Mize, conn_id: u64) -> MizeResult<()>
|
||||
where
|
||||
W: AsyncWriteExt + Unpin,
|
||||
{
|
||||
for msg in send_rx {
|
||||
debug!("windows outgoing got msg: {}", msg);
|
||||
let adapter = MyCiboriumWriter {
|
||||
inner: &mut *shared_pipe.blocking_lock(),
|
||||
instance: &mut instance,
|
||||
};
|
||||
let value = msg.value();
|
||||
ciborium::into_writer(&value, adapter)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn windows_incomming<R>(shared_pipe: Arc<Mutex<R>>, mut instance: Mize, conn_id: u64) -> MizeResult<()>
|
||||
where
|
||||
R: AsyncReadExt + Unpin,
|
||||
{
|
||||
loop {
|
||||
let adapter = MyCiboriumReader {
|
||||
inner: &mut *shared_pipe.blocking_lock(),
|
||||
instance: &mut instance,
|
||||
};
|
||||
let value: CborValue = ciborium::from_reader(adapter)?;
|
||||
if let CborValue::Integer(_) = value {
|
||||
break;
|
||||
}
|
||||
let msg = MizeMessage::new(value, conn_id);
|
||||
debug!("windows incomming got msg: {}", msg);
|
||||
instance.got_msg(msg);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct MyCiboriumWriter<'a, W> {
|
||||
inner: &'a mut W,
|
||||
instance: &'a mut Mize,
|
||||
}
|
||||
|
||||
impl<'a, W> ciborium_io::Write for MyCiboriumWriter<'a, W>
|
||||
where
|
||||
W: AsyncWriteExt + Unpin,
|
||||
{
|
||||
type Error = MizeError;
|
||||
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
|
||||
let runtime = self.instance.runtime.lock()?;
|
||||
let _ = runtime.block_on(self.inner.write_all(data))?;
|
||||
Ok(())
|
||||
}
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
let handle = self.instance.async_get_handle();
|
||||
let _ = handle.block_on(self.inner.flush());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct MyCiboriumReader<'a, R> {
|
||||
inner: &'a mut R,
|
||||
instance: &'a mut Mize,
|
||||
}
|
||||
|
||||
impl<'a, R> ciborium_io::Read for MyCiboriumReader<'a, R>
|
||||
where
|
||||
R: AsyncReadExt + Unpin,
|
||||
{
|
||||
type Error = MizeError;
|
||||
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
|
||||
let handle = self.instance.async_get_handle();
|
||||
let _ = handle.block_on(self.inner.read_exact(data))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user