mirror of
https://github.com/uqbar-dao/nectar.git
synced 2025-01-02 05:28:22 +03:00
rename uqbar->nectar, update to nectar-wit and process_lib releases
This commit is contained in:
parent
4c7ca4d35e
commit
faf7676f8d
13
build.rs
13
build.rs
@ -139,11 +139,14 @@ fn main() {
|
||||
let wit_dir = pwd.join("wit");
|
||||
fs::create_dir_all(&wit_dir).unwrap();
|
||||
let wit_file = wit_dir.join("nectar.wit");
|
||||
//if !wit_file.exists() { // TODO: cache in better way
|
||||
let mut wit_file = std::fs::File::create(&wit_file).unwrap();
|
||||
let nectar_wit_url = "https://raw.githubusercontent.com/uqbar-dao/uqwit/master/nectar.wit";
|
||||
let mut response = reqwest::blocking::get(nectar_wit_url).unwrap();
|
||||
io::copy(&mut response, &mut wit_file).unwrap();
|
||||
if !wit_file.exists() {
|
||||
// TODO: cache in better way
|
||||
let mut wit_file = std::fs::File::create(&wit_file).unwrap();
|
||||
let nectar_wit_url =
|
||||
"https://raw.githubusercontent.com/uqbar-dao/nectar-wit/master/nectar.wit";
|
||||
let mut response = reqwest::blocking::get(nectar_wit_url).unwrap();
|
||||
io::copy(&mut response, &mut wit_file).unwrap();
|
||||
}
|
||||
|
||||
// Create target.wasm (compiled .wit) & world
|
||||
run_command(Command::new("wasm-tools").args([
|
||||
|
36
modules/app_store/app_store/Cargo.lock
generated
36
modules/app_store/app_store/Cargo.lock
generated
@ -14,11 +14,11 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -222,6 +222,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -445,23 +462,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -15,7 +15,7 @@ rand = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
sha2 = "0.10.8"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use nectar_process_lib::kernel_types as kt;
|
||||
use nectar_process_lib::println;
|
||||
use nectar_process_lib::*;
|
||||
use nectar_process_lib::{call_init, println};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use sha2::Digest;
|
||||
@ -73,7 +73,7 @@ struct PackageListing {
|
||||
/// on different nodes, take this form. Will add more to enum in the future
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum RemoteRequest {
|
||||
/// no payload; request a package from a node
|
||||
/// no blob; request a package from a node
|
||||
/// remote node must return RemoteResponse::DownloadApproved,
|
||||
/// at which point requester can expect a FTWorkerRequest::Receive
|
||||
Download(PackageId),
|
||||
@ -88,22 +88,22 @@ pub enum RemoteResponse {
|
||||
/// Local requests take this form.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum LocalRequest {
|
||||
/// expects a zipped package as payload: create a new package from it
|
||||
/// expects a zipped package as blob: create a new package from it
|
||||
/// if requested, will return a NewPackageResponse indicating success/failure
|
||||
NewPackage {
|
||||
package: PackageId,
|
||||
mirror: bool, // sets whether we will mirror this package
|
||||
},
|
||||
/// no payload; try to download a package from a specified node
|
||||
/// no blob; try to download a package from a specified node
|
||||
/// if requested, will return a DownloadResponse indicating success/failure
|
||||
Download {
|
||||
package: PackageId,
|
||||
install_from: NodeId,
|
||||
},
|
||||
/// no payload; select a downloaded package and install it
|
||||
/// no blob; select a downloaded package and install it
|
||||
/// if requested, will return an InstallResponse indicating success/failure
|
||||
Install(PackageId),
|
||||
/// Takes no payload; Select an installed package and uninstall it.
|
||||
/// Takes no blob; Select an installed package and uninstall it.
|
||||
/// This will kill the processes in the **manifest** of the package,
|
||||
/// but not the processes that were spawned by those processes! Take
|
||||
/// care to kill those processes yourself. This will also delete the drive
|
||||
@ -205,30 +205,30 @@ fn handle_message(our: &Address, mut state: &mut State, message: &Message) -> an
|
||||
Message::Request {
|
||||
source,
|
||||
expects_response,
|
||||
ipc,
|
||||
body,
|
||||
..
|
||||
} => {
|
||||
match &serde_json::from_slice::<Req>(&ipc)? {
|
||||
match &serde_json::from_slice::<Req>(&body)? {
|
||||
Req::LocalRequest(local_request) => {
|
||||
if our.node != source.node {
|
||||
return Err(anyhow::anyhow!("local request from non-local node"));
|
||||
}
|
||||
let resp = handle_local_request(&our, local_request, &mut state);
|
||||
if expects_response.is_some() {
|
||||
Response::new().ipc(serde_json::to_vec(&resp)?).send()?;
|
||||
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
||||
}
|
||||
}
|
||||
Req::RemoteRequest(remote_request) => {
|
||||
let resp = handle_remote_request(&our, &source, remote_request, &mut state);
|
||||
if expects_response.is_some() {
|
||||
Response::new().ipc(serde_json::to_vec(&resp)?).send()?;
|
||||
Response::new().body(serde_json::to_vec(&resp)?).send()?;
|
||||
}
|
||||
}
|
||||
Req::FTWorkerResult(FTWorkerResult::ReceiveSuccess(name)) => {
|
||||
// do with file what you'd like here
|
||||
println!("app store: successfully received {:?}", name);
|
||||
// remove leading / and .zip from file name to get package ID
|
||||
let package_id = match PackageId::from_str(name[1..].trim_end_matches(".zip")) {
|
||||
let package_id = match name[1..].trim_end_matches(".zip").parse::<PackageId>() {
|
||||
Ok(package_id) => package_id,
|
||||
Err(e) => {
|
||||
println!("app store: bad package filename: {}", name);
|
||||
@ -237,11 +237,11 @@ fn handle_message(our: &Address, mut state: &mut State, message: &Message) -> an
|
||||
};
|
||||
// only install the app if we actually requested it
|
||||
if state.requested_packages.remove(&package_id) {
|
||||
// auto-take zip from payload and request ourself with New
|
||||
// auto-take zip from blob and request ourself with New
|
||||
Request::new()
|
||||
.target(our.clone())
|
||||
.inherit(true)
|
||||
.ipc(serde_json::to_vec(&Req::LocalRequest(
|
||||
.body(serde_json::to_vec(&Req::LocalRequest(
|
||||
LocalRequest::NewPackage {
|
||||
package: package_id,
|
||||
mirror: true, // can turn off auto-mirroring
|
||||
@ -255,11 +255,11 @@ fn handle_message(our: &Address, mut state: &mut State, message: &Message) -> an
|
||||
println!("app store: got ft_worker result: {r:?}");
|
||||
}
|
||||
Req::FTWorkerCommand(_) => {
|
||||
spawn_receive_transfer(&our, &ipc)?;
|
||||
spawn_receive_transfer(&our, &body)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Response { ipc, context, .. } => match &serde_json::from_slice::<Resp>(&ipc)? {
|
||||
Message::Response { body, context, .. } => match &serde_json::from_slice::<Resp>(&body)? {
|
||||
Resp::RemoteResponse(remote_response) => match remote_response {
|
||||
RemoteResponse::DownloadApproved => {
|
||||
println!("app store: download approved");
|
||||
@ -306,11 +306,11 @@ fn handle_local_request(our: &Address, request: &LocalRequest, state: &mut State
|
||||
match Request::new()
|
||||
.target((install_from.as_str(), our.process.clone()))
|
||||
.inherit(true)
|
||||
.ipc(serde_json::to_vec(&RemoteRequest::Download(package.clone())).unwrap())
|
||||
.body(serde_json::to_vec(&RemoteRequest::Download(package.clone())).unwrap())
|
||||
.send_and_await_response(5)
|
||||
{
|
||||
Ok(Ok(Message::Response { ipc, .. })) => {
|
||||
match serde_json::from_slice::<Resp>(&ipc) {
|
||||
Ok(Ok(Message::Response { body, .. })) => {
|
||||
match serde_json::from_slice::<Resp>(&body) {
|
||||
Ok(Resp::RemoteResponse(RemoteResponse::DownloadApproved)) => {
|
||||
state.requested_packages.insert(package.clone());
|
||||
crate::set_state(&bincode::serialize(&state).unwrap());
|
||||
@ -339,15 +339,15 @@ fn handle_new_package(
|
||||
mirror: bool,
|
||||
state: &mut State,
|
||||
) -> anyhow::Result<()> {
|
||||
let Some(mut payload) = get_payload() else {
|
||||
return Err(anyhow::anyhow!("no payload"));
|
||||
let Some(mut blob) = get_blob() else {
|
||||
return Err(anyhow::anyhow!("no blob"));
|
||||
};
|
||||
let drive = format!("/{}/pkg", package);
|
||||
|
||||
// create a new drive for this package in VFS
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: drive.clone(),
|
||||
action: vfs::VfsAction::CreateDrive,
|
||||
})?)
|
||||
@ -355,21 +355,21 @@ fn handle_new_package(
|
||||
|
||||
// produce the version hash for this new package
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(&payload.bytes);
|
||||
hasher.update(&blob.bytes);
|
||||
let version_hash = format!("{:x}", hasher.finalize());
|
||||
|
||||
// add zip bytes
|
||||
payload.mime = Some("application/zip".to_string());
|
||||
blob.mime = Some("application/zip".to_string());
|
||||
let response = Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: drive.clone(),
|
||||
action: vfs::VfsAction::AddZip,
|
||||
})?)
|
||||
.payload(payload.clone())
|
||||
.blob(blob.clone())
|
||||
.send_and_await_response(5)??;
|
||||
let vfs_ipc = serde_json::from_slice::<serde_json::Value>(response.ipc())?;
|
||||
if vfs_ipc == serde_json::json!({"Err": "NoCap"}) {
|
||||
let vfs_body = serde_json::from_slice::<serde_json::Value>(response.body())?;
|
||||
if vfs_body == serde_json::json!({"Err": "NoCap"}) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"cannot add NewPackage: do not have capability to access vfs"
|
||||
));
|
||||
@ -381,11 +381,11 @@ fn handle_new_package(
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.inherit(true)
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: zip_path,
|
||||
action: vfs::VfsAction::Write,
|
||||
})?)
|
||||
.payload(payload)
|
||||
.blob(blob)
|
||||
.send_and_await_response(5)??;
|
||||
let metadata_path = format!("{}/metadata.json", drive.clone());
|
||||
|
||||
@ -393,16 +393,16 @@ fn handle_new_package(
|
||||
// such that we can mirror this package to others.
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: metadata_path,
|
||||
action: vfs::VfsAction::Read,
|
||||
})?)
|
||||
.send_and_await_response(5)??;
|
||||
let Some(payload) = get_payload() else {
|
||||
let Some(blob) = get_blob() else {
|
||||
return Err(anyhow::anyhow!("no metadata found!"));
|
||||
};
|
||||
|
||||
let metadata = String::from_utf8(payload.bytes)?;
|
||||
let metadata = String::from_utf8(blob.bytes)?;
|
||||
let metadata = serde_json::from_str::<kt::PackageMetadata>(&metadata)?;
|
||||
|
||||
let listing_data = PackageListing {
|
||||
@ -428,15 +428,15 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
let drive_path = format!("/{}/pkg", package);
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: format!("{}/manifest.json", drive_path),
|
||||
action: vfs::VfsAction::Read,
|
||||
})?)
|
||||
.send_and_await_response(5)??;
|
||||
let Some(payload) = get_payload() else {
|
||||
return Err(anyhow::anyhow!("no payload"));
|
||||
let Some(blob) = get_blob() else {
|
||||
return Err(anyhow::anyhow!("no blob"));
|
||||
};
|
||||
let manifest = String::from_utf8(payload.bytes)?;
|
||||
let manifest = String::from_utf8(blob.bytes)?;
|
||||
let manifest = serde_json::from_str::<Vec<kt::PackageManifestEntry>>(&manifest)?;
|
||||
// always grant read/write to their drive, which we created for them
|
||||
let Some(read_cap) = get_capability(
|
||||
@ -481,20 +481,20 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
initial_capabilities.insert(kt::de_wit_capability(read_cap.clone()));
|
||||
initial_capabilities.insert(kt::de_wit_capability(write_cap.clone()));
|
||||
let process_id = format!("{}:{}", entry.process_name, package);
|
||||
let Ok(parsed_new_process_id) = ProcessId::from_str(&process_id) else {
|
||||
let Ok(parsed_new_process_id) = process_id.parse::<ProcessId>() else {
|
||||
return Err(anyhow::anyhow!("app store: invalid process id!"));
|
||||
};
|
||||
// kill process if it already exists
|
||||
Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&kt::KernelCommand::KillProcess(
|
||||
.body(serde_json::to_vec(&kt::KernelCommand::KillProcess(
|
||||
parsed_new_process_id.clone(),
|
||||
))?)
|
||||
.send()?;
|
||||
|
||||
let _bytes_response = Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: wasm_path.clone(),
|
||||
action: vfs::VfsAction::Read,
|
||||
})?)
|
||||
@ -504,7 +504,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
let mut capability = None;
|
||||
match value {
|
||||
serde_json::Value::String(process_name) => {
|
||||
if let Ok(parsed_process_id) = ProcessId::from_str(&process_name) {
|
||||
if let Ok(parsed_process_id) = process_name.parse::<ProcessId>() {
|
||||
capability = get_capability(
|
||||
&Address {
|
||||
node: our.node.clone(),
|
||||
@ -516,8 +516,10 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
}
|
||||
serde_json::Value::Object(map) => {
|
||||
if let Some(process_name) = map.get("process") {
|
||||
if let Ok(parsed_process_id) =
|
||||
ProcessId::from_str(&process_name.to_string())
|
||||
if let Ok(parsed_process_id) = process_name
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.parse::<ProcessId>()
|
||||
{
|
||||
if let Some(params) = map.get("params") {
|
||||
if params.to_string() == "\"root\"" {
|
||||
@ -555,7 +557,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
}
|
||||
Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
|
||||
.body(serde_json::to_vec(&kt::KernelCommand::InitializeProcess {
|
||||
id: parsed_new_process_id.clone(),
|
||||
wasm_bytes_handle: wasm_path,
|
||||
wit_version: None,
|
||||
@ -569,10 +571,10 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
for value in to_grant {
|
||||
match value {
|
||||
serde_json::Value::String(process_name) => {
|
||||
if let Ok(parsed_process_id) = ProcessId::from_str(&process_name) {
|
||||
if let Ok(parsed_process_id) = process_name.parse::<ProcessId>() {
|
||||
let _ = Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
|
||||
target: parsed_process_id,
|
||||
capabilities: vec![kt::Capability {
|
||||
@ -590,13 +592,15 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
}
|
||||
serde_json::Value::Object(map) => {
|
||||
if let Some(process_name) = map.get("process") {
|
||||
if let Ok(parsed_process_id) =
|
||||
ProcessId::from_str(&process_name.to_string())
|
||||
if let Ok(parsed_process_id) = process_name
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.parse::<ProcessId>()
|
||||
{
|
||||
if let Some(params) = map.get("params") {
|
||||
let _ = Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(
|
||||
&kt::KernelCommand::GrantCapabilities {
|
||||
target: parsed_process_id,
|
||||
@ -624,7 +628,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
|
||||
}
|
||||
Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&kt::KernelCommand::RunProcess(
|
||||
.body(serde_json::to_vec(&kt::KernelCommand::RunProcess(
|
||||
parsed_new_process_id,
|
||||
))?)
|
||||
.send_and_await_response(5)??;
|
||||
@ -636,25 +640,25 @@ fn handle_uninstall(package: &PackageId) -> anyhow::Result<()> {
|
||||
let drive_path = format!("/{}/pkg", package);
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: format!("{}/manifest.json", drive_path),
|
||||
action: vfs::VfsAction::Read,
|
||||
})?)
|
||||
.send_and_await_response(5)??;
|
||||
let Some(payload) = get_payload() else {
|
||||
return Err(anyhow::anyhow!("no payload"));
|
||||
let Some(blob) = get_blob() else {
|
||||
return Err(anyhow::anyhow!("no blob"));
|
||||
};
|
||||
let manifest = String::from_utf8(payload.bytes)?;
|
||||
let manifest = String::from_utf8(blob.bytes)?;
|
||||
let manifest = serde_json::from_str::<Vec<kt::PackageManifestEntry>>(&manifest)?;
|
||||
// reading from the package manifest, kill every process
|
||||
for entry in &manifest {
|
||||
let process_id = format!("{}:{}", entry.process_name, package);
|
||||
let Ok(parsed_new_process_id) = ProcessId::from_str(&process_id) else {
|
||||
let Ok(parsed_new_process_id) = process_id.parse::<ProcessId>() else {
|
||||
continue;
|
||||
};
|
||||
Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&kt::KernelCommand::KillProcess(
|
||||
.body(serde_json::to_vec(&kt::KernelCommand::KillProcess(
|
||||
parsed_new_process_id,
|
||||
))?)
|
||||
.send()?;
|
||||
@ -662,7 +666,7 @@ fn handle_uninstall(package: &PackageId) -> anyhow::Result<()> {
|
||||
// then, delete the drive
|
||||
Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: drive_path,
|
||||
action: vfs::VfsAction::RemoveDirAll,
|
||||
})?)
|
||||
@ -684,11 +688,11 @@ fn handle_remote_request(
|
||||
if !package_state.mirroring {
|
||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied);
|
||||
}
|
||||
// get the .zip from VFS and attach as payload to response
|
||||
// get the .zip from VFS and attach as blob to response
|
||||
let file_path = format!("/{}/pkg/{}.zip", package, package);
|
||||
let Ok(Ok(_)) = Request::new()
|
||||
.target(("our", "vfs", "sys", "nectar"))
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: file_path,
|
||||
action: vfs::VfsAction::Read,
|
||||
@ -699,7 +703,7 @@ fn handle_remote_request(
|
||||
else {
|
||||
return Resp::RemoteResponse(RemoteResponse::DownloadDenied);
|
||||
};
|
||||
// transfer will *inherit* the payload bytes we receive from VFS
|
||||
// transfer will *inherit* the blob bytes we receive from VFS
|
||||
let file_name = format!("/{}.zip", package);
|
||||
match spawn_transfer(&our, &file_name, None, 60, &source) {
|
||||
Ok(()) => Resp::RemoteResponse(RemoteResponse::DownloadApproved),
|
||||
|
36
modules/app_store/ft_worker/Cargo.lock
generated
36
modules/app_store/ft_worker/Cargo.lock
generated
@ -62,10 +62,10 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -173,6 +173,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -379,23 +396,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -16,7 +16,7 @@ bincode = "1.3.3"
|
||||
rand = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -13,7 +13,7 @@ pub struct FileTransferContext {
|
||||
/// in order to prompt them to spawn a worker
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum FTWorkerCommand {
|
||||
/// make sure to attach file itself as payload
|
||||
/// make sure to attach file itself as blob
|
||||
Send {
|
||||
target: Address,
|
||||
file_name: String,
|
||||
@ -32,7 +32,7 @@ pub enum FTWorkerCommand {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum FTWorkerResult {
|
||||
SendSuccess,
|
||||
/// string is name of file. bytes in payload
|
||||
/// string is name of file. bytes in blob
|
||||
ReceiveSuccess(String),
|
||||
Err(TransferError),
|
||||
}
|
||||
@ -49,7 +49,7 @@ pub enum TransferError {
|
||||
/// A helper function to spawn a worker and initialize a file transfer.
|
||||
/// The outcome will be sent as an [`FTWorkerResult`] to the caller process.
|
||||
///
|
||||
/// if `file_bytes` is None, expects to inherit payload!
|
||||
/// if `file_bytes` is None, expects to inherit blob!
|
||||
#[allow(dead_code)]
|
||||
pub fn spawn_transfer(
|
||||
our: &Address,
|
||||
@ -71,15 +71,15 @@ pub fn spawn_transfer(
|
||||
return Err(anyhow::anyhow!("failed to spawn ft_worker!"));
|
||||
};
|
||||
// tell the worker what to do
|
||||
let payload_or_inherit = match file_bytes {
|
||||
Some(bytes) => Some(Payload { mime: None, bytes }),
|
||||
let blob_or_inherit = match file_bytes {
|
||||
Some(bytes) => Some(LazyLoadBlob { mime: None, bytes }),
|
||||
None => None,
|
||||
};
|
||||
let mut req = Request::new()
|
||||
.target((our.node.as_ref(), worker_process_id))
|
||||
.inherit(!payload_or_inherit.is_some())
|
||||
.inherit(!blob_or_inherit.is_some())
|
||||
.expects_response(timeout + 1) // don't call with 2^64 lol
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&FTWorkerCommand::Send {
|
||||
target: to_addr.clone(),
|
||||
file_name: file_name.into(),
|
||||
@ -90,7 +90,7 @@ pub fn spawn_transfer(
|
||||
.context(
|
||||
serde_json::to_vec(&FileTransferContext {
|
||||
file_name: file_name.into(),
|
||||
file_size: match &payload_or_inherit {
|
||||
file_size: match &blob_or_inherit {
|
||||
Some(p) => Some(p.bytes.len() as u64),
|
||||
None => None, // TODO
|
||||
},
|
||||
@ -99,8 +99,8 @@ pub fn spawn_transfer(
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
if let Some(payload) = payload_or_inherit {
|
||||
req = req.payload(payload);
|
||||
if let Some(blob) = blob_or_inherit {
|
||||
req = req.blob(blob);
|
||||
}
|
||||
req.send()
|
||||
}
|
||||
@ -110,8 +110,8 @@ pub fn spawn_transfer(
|
||||
/// and let it do the rest. The outcome will be sent as an [`FTWorkerResult`] inside
|
||||
/// a Response to the caller.
|
||||
#[allow(dead_code)]
|
||||
pub fn spawn_receive_transfer(our: &Address, ipc: &[u8]) -> anyhow::Result<()> {
|
||||
let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_slice(ipc) else {
|
||||
pub fn spawn_receive_transfer(our: &Address, body: &[u8]) -> anyhow::Result<()> {
|
||||
let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_slice(body) else {
|
||||
return Err(anyhow::anyhow!(
|
||||
"spawn_receive_transfer: got malformed request"
|
||||
));
|
||||
@ -130,6 +130,6 @@ pub fn spawn_receive_transfer(our: &Address, ipc: &[u8]) -> anyhow::Result<()> {
|
||||
Request::new()
|
||||
.target((our.node.as_ref(), worker_process_id))
|
||||
.inherit(true)
|
||||
.ipc(ipc)
|
||||
.body(body)
|
||||
.send()
|
||||
}
|
||||
|
@ -25,14 +25,14 @@ call_init!(init);
|
||||
fn init(our: Address) {
|
||||
let Ok(Message::Request {
|
||||
source: parent_process,
|
||||
ipc,
|
||||
body,
|
||||
..
|
||||
}) = await_message()
|
||||
else {
|
||||
panic!("ft_worker: got bad init message");
|
||||
};
|
||||
|
||||
let command = serde_json::from_slice::<FTWorkerCommand>(&ipc)
|
||||
let command = serde_json::from_slice::<FTWorkerCommand>(&body)
|
||||
.expect("ft_worker: got unparseable init message");
|
||||
|
||||
let Some(result) = (match command {
|
||||
@ -52,7 +52,7 @@ fn init(our: Address) {
|
||||
};
|
||||
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&result).unwrap())
|
||||
.body(serde_json::to_vec(&result).unwrap())
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
@ -61,11 +61,11 @@ fn init(our: Address) {
|
||||
|
||||
fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -> FTWorkerResult {
|
||||
let transfer_id: u64 = our.process().parse().unwrap();
|
||||
let Some(payload) = get_payload() else {
|
||||
println!("ft_worker: wasn't given payload!");
|
||||
let Some(blob) = get_blob() else {
|
||||
println!("ft_worker: wasn't given blob!");
|
||||
return FTWorkerResult::Err(TransferError::SourceFailed);
|
||||
};
|
||||
let file_bytes = payload.bytes;
|
||||
let file_bytes = blob.bytes;
|
||||
let mut file_size = file_bytes.len() as u64;
|
||||
let mut offset: u64 = 0;
|
||||
let chunk_size: u64 = 1048576; // 1MB, can be changed
|
||||
@ -76,7 +76,7 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
|
||||
// send contents in chunks and wait for
|
||||
// acknowledgement.
|
||||
let Ok(Ok(response)) = Request::to(target.clone())
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&FTWorkerCommand::Receive {
|
||||
transfer_id,
|
||||
file_name: file_name.to_string(),
|
||||
@ -91,7 +91,7 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
|
||||
return FTWorkerResult::Err(TransferError::TargetOffline);
|
||||
};
|
||||
let opp_worker = response.source();
|
||||
let Ok(FTWorkerProtocol::Ready) = serde_json::from_slice(&response.ipc()) else {
|
||||
let Ok(FTWorkerProtocol::Ready) = serde_json::from_slice(&response.body()) else {
|
||||
return FTWorkerResult::Err(TransferError::TargetRejected);
|
||||
};
|
||||
// send file in chunks
|
||||
@ -99,8 +99,8 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
|
||||
if file_size < chunk_size {
|
||||
// this is the last chunk, so we should expect a Finished response
|
||||
let _ = Request::to(opp_worker.clone())
|
||||
.ipc(vec![])
|
||||
.payload(Payload {
|
||||
.body(vec![])
|
||||
.blob(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: file_bytes[offset as usize..offset as usize + file_size as usize]
|
||||
.to_vec(),
|
||||
@ -110,8 +110,8 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
|
||||
break;
|
||||
}
|
||||
let _ = Request::to(opp_worker.clone())
|
||||
.ipc(vec![])
|
||||
.payload(Payload {
|
||||
.body(vec![])
|
||||
.blob(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: file_bytes[offset as usize..offset as usize + chunk_size as usize].to_vec(),
|
||||
})
|
||||
@ -120,10 +120,10 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
|
||||
offset += chunk_size;
|
||||
}
|
||||
// now wait for Finished response
|
||||
let Ok(Message::Response { ipc, .. }) = await_message() else {
|
||||
let Ok(Message::Response { body, .. }) = await_message() else {
|
||||
return FTWorkerResult::Err(TransferError::TargetRejected);
|
||||
};
|
||||
let Ok(FTWorkerProtocol::Finished) = serde_json::from_slice(&ipc) else {
|
||||
let Ok(FTWorkerProtocol::Finished) = serde_json::from_slice(&body) else {
|
||||
return FTWorkerResult::Err(TransferError::TargetRejected);
|
||||
};
|
||||
// return success to parent
|
||||
@ -138,7 +138,7 @@ fn handle_receive(
|
||||
) -> Option<FTWorkerResult> {
|
||||
// send Ready response to counterparty
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&FTWorkerProtocol::Ready).unwrap())
|
||||
.body(serde_json::to_vec(&FTWorkerProtocol::Ready).unwrap())
|
||||
.send()
|
||||
.unwrap();
|
||||
// receive a file from a worker, then send it to parent
|
||||
@ -154,24 +154,24 @@ fn handle_receive(
|
||||
if start_time.elapsed().as_secs() > timeout {
|
||||
return Some(FTWorkerResult::Err(TransferError::SourceFailed));
|
||||
}
|
||||
let Some(payload) = get_payload() else {
|
||||
let Some(blob) = get_blob() else {
|
||||
return Some(FTWorkerResult::Err(TransferError::SourceFailed));
|
||||
};
|
||||
chunks_received += 1;
|
||||
file_bytes.extend(payload.bytes);
|
||||
file_bytes.extend(blob.bytes);
|
||||
if chunks_received == total_chunks {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// send Finished message to sender
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&FTWorkerProtocol::Finished).unwrap())
|
||||
.body(serde_json::to_vec(&FTWorkerProtocol::Finished).unwrap())
|
||||
.send()
|
||||
.unwrap();
|
||||
// send Success message to parent
|
||||
Request::to(parent_process)
|
||||
.ipc(serde_json::to_vec(&FTWorkerResult::ReceiveSuccess(file_name.to_string())).unwrap())
|
||||
.payload(Payload {
|
||||
.body(serde_json::to_vec(&FTWorkerResult::ReceiveSuccess(file_name.to_string())).unwrap())
|
||||
.blob(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: file_bytes,
|
||||
})
|
||||
|
36
modules/chess/chess/Cargo.lock
generated
36
modules/chess/chess/Cargo.lock
generated
@ -69,10 +69,10 @@ dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"pleco",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uqbar_process_lib",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
@ -283,6 +283,23 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c55d0c9dc43dedfd2414deb74ade67687749ef88b1d3482024d4c81d901a7a83"
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
@ -654,23 +671,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -16,7 +16,7 @@ pleco = "0.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
url = "*"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![feature(let_chains)]
|
||||
use nectar_process_lib::{
|
||||
await_message, call_init, get_payload, get_typed_state, http, println, set_state, Address,
|
||||
Message, NodeId, Payload, Request, Response,
|
||||
await_message, call_init, get_blob, get_typed_state, http, println, set_state, Address,
|
||||
LazyLoadBlob, Message, NodeId, Request, Response,
|
||||
};
|
||||
use pleco::Board;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -74,13 +74,13 @@ fn send_ws_update(our: &Address, game: &Game, open_channels: &HashSet<u32>) -> a
|
||||
for channel in open_channels {
|
||||
Request::new()
|
||||
.target((&our.node, "http_server", "sys", "nectar"))
|
||||
.ipc(serde_json::to_vec(
|
||||
.body(serde_json::to_vec(
|
||||
&http::HttpServerAction::WebSocketPush {
|
||||
channel_id: *channel,
|
||||
message_type: http::WsMessageType::Binary,
|
||||
},
|
||||
)?)
|
||||
.payload(Payload {
|
||||
.blob(LazyLoadBlob {
|
||||
mime: Some("application/json".to_string()),
|
||||
bytes: serde_json::json!({
|
||||
"kind": "game_update",
|
||||
@ -160,7 +160,7 @@ fn handle_request(our: &Address, message: &Message, state: &mut ChessState) -> a
|
||||
if message.source().node != our.node {
|
||||
// Deserialize the request IPC to our format, and throw it away if it
|
||||
// doesn't fit.
|
||||
let Ok(chess_request) = serde_json::from_slice::<ChessRequest>(message.ipc()) else {
|
||||
let Ok(chess_request) = serde_json::from_slice::<ChessRequest>(message.body()) else {
|
||||
return Err(anyhow::anyhow!("invalid chess request"));
|
||||
};
|
||||
handle_chess_request(our, &message.source().node, state, &chess_request)
|
||||
@ -170,7 +170,7 @@ fn handle_request(our: &Address, message: &Message, state: &mut ChessState) -> a
|
||||
} else if message.source().node == our.node
|
||||
&& message.source().process == "terminal:terminal:nectar"
|
||||
{
|
||||
let Ok(chess_request) = serde_json::from_slice::<ChessRequest>(message.ipc()) else {
|
||||
let Ok(chess_request) = serde_json::from_slice::<ChessRequest>(message.body()) else {
|
||||
return Err(anyhow::anyhow!("invalid chess request"));
|
||||
};
|
||||
handle_local_request(our, state, &chess_request)
|
||||
@ -178,7 +178,7 @@ fn handle_request(our: &Address, message: &Message, state: &mut ChessState) -> a
|
||||
&& message.source().process == "http_server:sys:nectar"
|
||||
{
|
||||
// receive HTTP requests and websocket connection messages from our server
|
||||
match serde_json::from_slice::<http::HttpServerRequest>(message.ipc())? {
|
||||
match serde_json::from_slice::<http::HttpServerRequest>(message.body())? {
|
||||
http::HttpServerRequest::Http(ref incoming) => {
|
||||
match handle_http_request(our, state, incoming) {
|
||||
Ok(()) => Ok(()),
|
||||
@ -258,7 +258,7 @@ fn handle_chess_request(
|
||||
// Send a response to tell them we've accepted the game.
|
||||
// Remember, the other player is waiting for this.
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&ChessResponse::NewGameAccepted)?)
|
||||
.body(serde_json::to_vec(&ChessResponse::NewGameAccepted)?)
|
||||
.send()
|
||||
}
|
||||
ChessRequest::Move { ref move_str, .. } => {
|
||||
@ -267,7 +267,7 @@ fn handle_chess_request(
|
||||
let Some(game) = state.games.get_mut(game_id) else {
|
||||
// If we don't have a game with them, reject the move.
|
||||
return Response::new()
|
||||
.ipc(serde_json::to_vec(&ChessResponse::MoveRejected)?)
|
||||
.body(serde_json::to_vec(&ChessResponse::MoveRejected)?)
|
||||
.send();
|
||||
};
|
||||
// Convert the saved board to one we can manipulate.
|
||||
@ -275,7 +275,7 @@ fn handle_chess_request(
|
||||
if !board.apply_uci_move(move_str) {
|
||||
// Reject invalid moves!
|
||||
return Response::new()
|
||||
.ipc(serde_json::to_vec(&ChessResponse::MoveRejected)?)
|
||||
.body(serde_json::to_vec(&ChessResponse::MoveRejected)?)
|
||||
.send();
|
||||
}
|
||||
game.turns += 1;
|
||||
@ -288,7 +288,7 @@ fn handle_chess_request(
|
||||
save_chess_state(&state);
|
||||
// Send a response to tell them we've accepted the move.
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&ChessResponse::MoveAccepted)?)
|
||||
.body(serde_json::to_vec(&ChessResponse::MoveAccepted)?)
|
||||
.send()
|
||||
}
|
||||
ChessRequest::Resign(_) => {
|
||||
@ -329,9 +329,9 @@ fn handle_local_request(
|
||||
// Send the other player a NewGame request
|
||||
// The request is exactly the same as what we got from terminal.
|
||||
// We'll give them 5 seconds to respond...
|
||||
let Ok(Message::Response { ref ipc, .. }) = Request::new()
|
||||
let Ok(Message::Response { ref body, .. }) = Request::new()
|
||||
.target((game_id.as_ref(), our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&action)?)
|
||||
.body(serde_json::to_vec(&action)?)
|
||||
.send_and_await_response(5)?
|
||||
else {
|
||||
return Err(anyhow::anyhow!(
|
||||
@ -339,7 +339,7 @@ fn handle_local_request(
|
||||
));
|
||||
};
|
||||
// If they accept, create a new game -- otherwise, error out.
|
||||
if serde_json::from_slice::<ChessResponse>(ipc)? != ChessResponse::NewGameAccepted {
|
||||
if serde_json::from_slice::<ChessResponse>(body)? != ChessResponse::NewGameAccepted {
|
||||
return Err(anyhow::anyhow!("other player rejected new game request!"));
|
||||
}
|
||||
// New game with default board.
|
||||
@ -375,16 +375,16 @@ fn handle_local_request(
|
||||
// Send the move to the other player, then check if the game is over.
|
||||
// The request is exactly the same as what we got from terminal.
|
||||
// We'll give them 5 seconds to respond...
|
||||
let Ok(Message::Response { ref ipc, .. }) = Request::new()
|
||||
let Ok(Message::Response { ref body, .. }) = Request::new()
|
||||
.target((game_id.as_ref(), our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&action)?)
|
||||
.body(serde_json::to_vec(&action)?)
|
||||
.send_and_await_response(5)?
|
||||
else {
|
||||
return Err(anyhow::anyhow!(
|
||||
"other player did not respond properly to our move"
|
||||
));
|
||||
};
|
||||
if serde_json::from_slice::<ChessResponse>(ipc)? != ChessResponse::MoveAccepted {
|
||||
if serde_json::from_slice::<ChessResponse>(body)? != ChessResponse::MoveAccepted {
|
||||
return Err(anyhow::anyhow!("other player rejected our move"));
|
||||
}
|
||||
game.turns += 1;
|
||||
@ -403,7 +403,7 @@ fn handle_local_request(
|
||||
// send the other player an end game request -- no response expected
|
||||
Request::new()
|
||||
.target((with_who.as_ref(), our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&action)?)
|
||||
.body(serde_json::to_vec(&action)?)
|
||||
.send()?;
|
||||
game.ended = true;
|
||||
save_chess_state(&state);
|
||||
@ -437,11 +437,11 @@ fn handle_http_request(
|
||||
),
|
||||
// on POST: create a new game
|
||||
"POST" => {
|
||||
let Some(payload) = get_payload() else {
|
||||
let Some(blob) = get_blob() else {
|
||||
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
|
||||
};
|
||||
let payload_json = serde_json::from_slice::<serde_json::Value>(&payload.bytes)?;
|
||||
let Some(game_id) = payload_json["id"].as_str() else {
|
||||
let blob_json = serde_json::from_slice::<serde_json::Value>(&blob.bytes)?;
|
||||
let Some(game_id) = blob_json["id"].as_str() else {
|
||||
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
|
||||
};
|
||||
if let Some(game) = state.games.get(game_id)
|
||||
@ -450,19 +450,16 @@ fn handle_http_request(
|
||||
return http::send_response(http::StatusCode::CONFLICT, None, vec![]);
|
||||
};
|
||||
|
||||
let player_white = payload_json["white"]
|
||||
let player_white = blob_json["white"]
|
||||
.as_str()
|
||||
.unwrap_or(our.node.as_str())
|
||||
.to_string();
|
||||
let player_black = payload_json["black"]
|
||||
.as_str()
|
||||
.unwrap_or(game_id)
|
||||
.to_string();
|
||||
let player_black = blob_json["black"].as_str().unwrap_or(game_id).to_string();
|
||||
|
||||
// send the other player a new game request
|
||||
let Ok(msg) = Request::new()
|
||||
.target((game_id, our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&ChessRequest::NewGame {
|
||||
.body(serde_json::to_vec(&ChessRequest::NewGame {
|
||||
white: player_white.clone(),
|
||||
black: player_black.clone(),
|
||||
})?)
|
||||
@ -474,7 +471,8 @@ fn handle_http_request(
|
||||
};
|
||||
// if they accept, create a new game
|
||||
// otherwise, should surface error to FE...
|
||||
if serde_json::from_slice::<ChessResponse>(msg.ipc())? != ChessResponse::NewGameAccepted
|
||||
if serde_json::from_slice::<ChessResponse>(msg.body())?
|
||||
!= ChessResponse::NewGameAccepted
|
||||
{
|
||||
return Err(anyhow::anyhow!("other player rejected new game request"));
|
||||
}
|
||||
@ -501,11 +499,11 @@ fn handle_http_request(
|
||||
}
|
||||
// on PUT: make a move
|
||||
"PUT" => {
|
||||
let Some(payload) = get_payload() else {
|
||||
let Some(blob) = get_blob() else {
|
||||
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
|
||||
};
|
||||
let payload_json = serde_json::from_slice::<serde_json::Value>(&payload.bytes)?;
|
||||
let Some(game_id) = payload_json["id"].as_str() else {
|
||||
let blob_json = serde_json::from_slice::<serde_json::Value>(&blob.bytes)?;
|
||||
let Some(game_id) = blob_json["id"].as_str() else {
|
||||
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
|
||||
};
|
||||
let Some(game) = state.games.get_mut(game_id) else {
|
||||
@ -518,7 +516,7 @@ fn handle_http_request(
|
||||
} else if game.ended {
|
||||
return http::send_response(http::StatusCode::CONFLICT, None, vec![]);
|
||||
}
|
||||
let Some(move_str) = payload_json["move"].as_str() else {
|
||||
let Some(move_str) = blob_json["move"].as_str() else {
|
||||
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
|
||||
};
|
||||
let mut board = Board::from_fen(&game.board).unwrap();
|
||||
@ -531,7 +529,7 @@ fn handle_http_request(
|
||||
// if so, update the records
|
||||
let Ok(msg) = Request::new()
|
||||
.target((game_id, our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&ChessRequest::Move {
|
||||
.body(serde_json::to_vec(&ChessRequest::Move {
|
||||
game_id: game_id.to_string(),
|
||||
move_str: move_str.to_string(),
|
||||
})?)
|
||||
@ -541,7 +539,7 @@ fn handle_http_request(
|
||||
"other player did not respond properly to our move"
|
||||
));
|
||||
};
|
||||
if serde_json::from_slice::<ChessResponse>(msg.ipc())? != ChessResponse::MoveAccepted {
|
||||
if serde_json::from_slice::<ChessResponse>(msg.body())? != ChessResponse::MoveAccepted {
|
||||
return Err(anyhow::anyhow!("other player rejected our move"));
|
||||
}
|
||||
// update the game
|
||||
@ -574,7 +572,7 @@ fn handle_http_request(
|
||||
// send the other player an end game request
|
||||
Request::new()
|
||||
.target((game_id.as_str(), our.process.clone()))
|
||||
.ipc(serde_json::to_vec(&ChessRequest::Resign(our.node.clone()))?)
|
||||
.body(serde_json::to_vec(&ChessRequest::Resign(our.node.clone()))?)
|
||||
.send()?;
|
||||
game.ended = true;
|
||||
let body = serde_json::to_vec(&game)?;
|
||||
|
36
modules/homepage/homepage/Cargo.lock
generated
36
modules/homepage/homepage/Cargo.lock
generated
@ -88,9 +88,9 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -172,6 +172,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#235f4aae4d8078e86d3114753ed79ccedb947ebe"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -378,23 +395,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -15,7 +15,7 @@ anyhow = "1.0"
|
||||
bincode = "1.3.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![feature(let_chains)]
|
||||
use nectar_process_lib::{
|
||||
await_message, http::bind_http_static_path, http::HttpServerError, println, Address, Message,
|
||||
ProcessId,
|
||||
};
|
||||
|
||||
wit_bindgen::generate!({
|
||||
@ -18,7 +17,7 @@ const HOME_PAGE: &str = include_str!("home.html");
|
||||
|
||||
impl Guest for Component {
|
||||
fn init(our: String) {
|
||||
let our = Address::from_str(&our).unwrap();
|
||||
let our: Address = our.parse().unwrap();
|
||||
match main(our) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
@ -65,10 +64,10 @@ fn main(our: Address) -> anyhow::Result<()> {
|
||||
println!("homepage: got network error??");
|
||||
continue;
|
||||
};
|
||||
if let Message::Response { source, ipc, .. } = message
|
||||
if let Message::Response { source, body, .. } = message
|
||||
&& source.process == "http_server:sys:nectar"
|
||||
{
|
||||
match serde_json::from_slice::<Result<(), HttpServerError>>(&ipc) {
|
||||
match serde_json::from_slice::<Result<(), HttpServerError>>(&body) {
|
||||
Ok(Ok(())) => continue,
|
||||
Ok(Err(e)) => println!("homepage: got error from http_server: {e}"),
|
||||
Err(_e) => println!("homepage: got malformed message from http_server!"),
|
||||
|
38
modules/qns_indexer/qns_indexer/Cargo.lock
generated
38
modules/qns_indexer/qns_indexer/Cargo.lock
generated
@ -1103,6 +1103,24 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#235f4aae4d8078e86d3114753ed79ccedb947ebe"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"ethers-core",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
@ -1360,10 +1378,10 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"hex",
|
||||
"nectar_process_lib",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -2089,24 +2107,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=6228e0f#6228e0fe59c651fed5d3c977e4623e7d404c3c10"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"ethers-core",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -20,7 +20,7 @@ hex = "0.4.3"
|
||||
rmp-serde = "1.1.2"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6228e0f", features = ["eth"] }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha", features = ["eth"] }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -1,10 +1,9 @@
|
||||
use alloy_primitives::B256;
|
||||
use alloy_rpc_types::Log;
|
||||
use alloy_sol_types::{sol, SolEvent};
|
||||
use nectar_process_lib::eth::{EthAddress, SubscribeLogsRequest};
|
||||
use nectar_process_lib::{
|
||||
await_message, get_typed_state, http, print_to_terminal, println, set_state, Address, Message,
|
||||
Payload, Request, Response,
|
||||
await_message, get_typed_state, http, print_to_terminal, println, set_state, Address,
|
||||
LazyLoadBlob, Message, Request, Response,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::hash_map::{Entry, HashMap};
|
||||
@ -84,7 +83,7 @@ sol! {
|
||||
struct Component;
|
||||
impl Guest for Component {
|
||||
fn init(our: String) {
|
||||
let our = Address::from_str(&our).unwrap();
|
||||
let our: Address = our.parse().unwrap();
|
||||
|
||||
let mut state: State = State {
|
||||
names: HashMap::new(),
|
||||
@ -113,7 +112,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
// shove all state into net::net
|
||||
Request::new()
|
||||
.target((&our.node, "net", "sys", "nectar"))
|
||||
.try_ipc(NetActions::QnsBatchUpdate(
|
||||
.try_body(NetActions::QnsBatchUpdate(
|
||||
state.nodes.values().cloned().collect::<Vec<_>>(),
|
||||
))?
|
||||
.send()?;
|
||||
@ -139,26 +138,26 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
println!("qns_indexer: got network error");
|
||||
continue;
|
||||
};
|
||||
let Message::Request { source, ipc, .. } = message else {
|
||||
let Message::Request { source, body, .. } = message else {
|
||||
// TODO we should store the subscription ID for eth
|
||||
// incase we want to cancel/reset it
|
||||
continue;
|
||||
};
|
||||
|
||||
if source.process == "http_server:sys:nectar" {
|
||||
if let Ok(ipc_json) = serde_json::from_slice::<serde_json::Value>(&ipc) {
|
||||
if ipc_json["path"].as_str().unwrap_or_default() == "/node/:name" {
|
||||
if let Some(name) = ipc_json["url_params"]["name"].as_str() {
|
||||
if let Ok(body_json) = serde_json::from_slice::<serde_json::Value>(&body) {
|
||||
if body_json["path"].as_str().unwrap_or_default() == "/node/:name" {
|
||||
if let Some(name) = body_json["url_params"]["name"].as_str() {
|
||||
if let Some(node) = state.nodes.get(name) {
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&http::HttpResponse {
|
||||
.body(serde_json::to_vec(&http::HttpResponse {
|
||||
status: 200,
|
||||
headers: HashMap::from([(
|
||||
"Content-Type".to_string(),
|
||||
"application/json".to_string(),
|
||||
)]),
|
||||
})?)
|
||||
.payload(Payload {
|
||||
.blob(LazyLoadBlob {
|
||||
mime: Some("application/json".to_string()),
|
||||
bytes: serde_json::to_string(&node)?.as_bytes().to_vec(),
|
||||
})
|
||||
@ -169,7 +168,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&http::HttpResponse {
|
||||
.body(serde_json::to_vec(&http::HttpResponse {
|
||||
status: 404,
|
||||
headers: HashMap::from([(
|
||||
"Content-Type".to_string(),
|
||||
@ -180,7 +179,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Ok(msg) = serde_json::from_slice::<IndexerActions>(&ipc) else {
|
||||
let Ok(msg) = serde_json::from_slice::<IndexerActions>(&body) else {
|
||||
println!("qns_indexer: got invalid message");
|
||||
continue;
|
||||
};
|
||||
@ -196,7 +195,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
Entry::Vacant(v) => v.insert(get_name(&e)),
|
||||
};
|
||||
|
||||
let mut node = state
|
||||
let node = state
|
||||
.nodes
|
||||
.entry(name.to_string())
|
||||
.or_insert_with(|| QnsUpdate::new(name, &node_id.to_string()));
|
||||
@ -240,7 +239,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||
print_to_terminal(1, &format!("qns_indexer: sending ID to net: {:?}", node));
|
||||
Request::new()
|
||||
.target((&our.node, "net", "sys", "nectar"))
|
||||
.try_ipc(NetActions::QnsUpdate(node.clone()))?
|
||||
.try_body(NetActions::QnsUpdate(node.clone()))?
|
||||
.send()?;
|
||||
}
|
||||
}
|
||||
|
36
modules/terminal/terminal/Cargo.lock
generated
36
modules/terminal/terminal/Cargo.lock
generated
@ -160,6 +160,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -295,9 +312,9 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -378,23 +395,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -15,7 +15,7 @@ anyhow = "1.0"
|
||||
bincode = "1.3.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -36,7 +36,7 @@ fn parse_command(state: &mut TerminalState, line: &str) -> anyhow::Result<()> {
|
||||
};
|
||||
Request::new()
|
||||
.target((node_id, "net", "sys", "nectar"))
|
||||
.ipc(message)
|
||||
.body(message)
|
||||
.expects_response(5)
|
||||
.send()?;
|
||||
Ok(())
|
||||
@ -48,7 +48,7 @@ fn parse_command(state: &mut TerminalState, line: &str) -> anyhow::Result<()> {
|
||||
println!("current target cleared");
|
||||
return Ok(());
|
||||
}
|
||||
let Ok(target) = Address::from_str(tail) else {
|
||||
let Ok(target) = tail.parse::<Address>() else {
|
||||
return Err(anyhow!("invalid address: \"{tail}\""));
|
||||
};
|
||||
println!("current target set to {target}");
|
||||
@ -60,16 +60,16 @@ fn parse_command(state: &mut TerminalState, line: &str) -> anyhow::Result<()> {
|
||||
// otherwise use the current_target
|
||||
"/m" | "/message" => {
|
||||
if let Some(target) = &state.current_target {
|
||||
Request::new().target(target.clone()).ipc(tail).send()
|
||||
Request::new().target(target.clone()).body(tail).send()
|
||||
} else {
|
||||
let (target, ipc) = match tail.split_once(" ") {
|
||||
let (target, body) = match tail.split_once(" ") {
|
||||
Some((a, p)) => (a, p),
|
||||
None => return Err(anyhow!("invalid command: \"{line}\"")),
|
||||
};
|
||||
let Ok(target) = Address::from_str(target) else {
|
||||
let Ok(target) = target.parse::<Address>() else {
|
||||
return Err(anyhow!("invalid address: \"{target}\""));
|
||||
};
|
||||
Request::new().target(target).ipc(ipc).send()
|
||||
Request::new().target(target).body(body).send()
|
||||
}
|
||||
}
|
||||
_ => return Err(anyhow!("invalid command: \"{line}\"")),
|
||||
@ -80,7 +80,7 @@ struct Component;
|
||||
impl Guest for Component {
|
||||
fn init(our: String) {
|
||||
let mut state = TerminalState {
|
||||
our: Address::from_str(&our).unwrap(),
|
||||
our: our.parse::<Address>().unwrap(),
|
||||
current_target: None,
|
||||
};
|
||||
loop {
|
||||
@ -92,20 +92,21 @@ impl Guest for Component {
|
||||
}
|
||||
};
|
||||
match message {
|
||||
wit::Message::Request(wit::Request { ipc, .. }) => {
|
||||
wit::Message::Request(wit::Request { body, .. }) => {
|
||||
if state.our.node != source.node || state.our.process != source.process {
|
||||
continue;
|
||||
}
|
||||
match parse_command(&mut state, std::str::from_utf8(&ipc).unwrap_or_default()) {
|
||||
match parse_command(&mut state, std::str::from_utf8(&body).unwrap_or_default())
|
||||
{
|
||||
Ok(()) => continue,
|
||||
Err(e) => println!("terminal: {e}"),
|
||||
}
|
||||
}
|
||||
wit::Message::Response((wit::Response { ipc, .. }, _)) => {
|
||||
if let Ok(txt) = std::str::from_utf8(&ipc) {
|
||||
wit::Message::Response((wit::Response { body, .. }, _)) => {
|
||||
if let Ok(txt) = std::str::from_utf8(&body) {
|
||||
println!("response from {source}: {txt}");
|
||||
} else {
|
||||
println!("response from {source}: {ipc:?}");
|
||||
println!("response from {source}: {body:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
modules/tester/test_runner/Cargo.lock
generated
36
modules/tester/test_runner/Cargo.lock
generated
@ -160,6 +160,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -295,10 +312,10 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"nectar_process_lib",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -379,23 +396,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -16,7 +16,7 @@ bincode = "1.3.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -21,7 +21,7 @@ wit_bindgen::generate!({
|
||||
fn make_vfs_address(our: &wit::Address) -> anyhow::Result<Address> {
|
||||
Ok(wit::Address {
|
||||
node: our.node.clone(),
|
||||
process: ProcessId::from_str("vfs:sys:nectar")?,
|
||||
process: "vfs:sys:nectar".parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -36,30 +36,30 @@ fn handle_message(our: &Address) -> anyhow::Result<()> {
|
||||
wit::Message::Response(_) => {
|
||||
return Err(tt::TesterError::UnexpectedResponse.into());
|
||||
}
|
||||
wit::Message::Request(wit::Request { ref ipc, .. }) => {
|
||||
match serde_json::from_slice(ipc)? {
|
||||
wit::Message::Request(wit::Request { ref body, .. }) => {
|
||||
match serde_json::from_slice(body)? {
|
||||
tt::TesterRequest::Run { test_timeout, .. } => {
|
||||
wit::print_to_terminal(0, "test_runner: got Run");
|
||||
|
||||
let response = Request::new()
|
||||
.target(make_vfs_address(&our)?)
|
||||
.ipc(serde_json::to_vec(&vfs::VfsRequest {
|
||||
.body(serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: "/tester:nectar/tests".into(),
|
||||
action: vfs::VfsAction::ReadDir,
|
||||
})?)
|
||||
.send_and_await_response(test_timeout)?
|
||||
.unwrap();
|
||||
|
||||
let Message::Response { ipc: vfs_ipc, .. } = response else {
|
||||
let Message::Response { body: vfs_body, .. } = response else {
|
||||
panic!("")
|
||||
};
|
||||
let vfs::VfsResponse::ReadDir(children) = serde_json::from_slice(&vfs_ipc)?
|
||||
let vfs::VfsResponse::ReadDir(children) = serde_json::from_slice(&vfs_body)?
|
||||
else {
|
||||
wit::print_to_terminal(
|
||||
0,
|
||||
&format!(
|
||||
"{:?}",
|
||||
serde_json::from_slice::<serde_json::Value>(&vfs_ipc)?,
|
||||
serde_json::from_slice::<serde_json::Value>(&vfs_body)?,
|
||||
),
|
||||
);
|
||||
panic!("")
|
||||
@ -91,14 +91,14 @@ fn handle_message(our: &Address) -> anyhow::Result<()> {
|
||||
node: our.node.clone(),
|
||||
process: child_process_id,
|
||||
})
|
||||
.ipc(ipc.clone())
|
||||
.body(body.clone())
|
||||
.send_and_await_response(test_timeout)?
|
||||
.unwrap();
|
||||
|
||||
let Message::Response { ipc, .. } = response else {
|
||||
let Message::Response { body, .. } = response else {
|
||||
panic!("")
|
||||
};
|
||||
match serde_json::from_slice(&ipc)? {
|
||||
match serde_json::from_slice(&body)? {
|
||||
tt::TesterResponse::Pass => {}
|
||||
tt::TesterResponse::GetFullMessage(_) => {}
|
||||
tt::TesterResponse::Fail {
|
||||
@ -115,7 +115,7 @@ fn handle_message(our: &Address) -> anyhow::Result<()> {
|
||||
wit::print_to_terminal(0, &format!("test_runner: done running {:?}", children));
|
||||
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
|
||||
.body(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
|
||||
.send()
|
||||
.unwrap();
|
||||
}
|
||||
@ -133,7 +133,7 @@ impl Guest for Component {
|
||||
fn init(our: String) {
|
||||
wit::print_to_terminal(0, "test_runner: begin");
|
||||
|
||||
let our = Address::from_str(&our).unwrap();
|
||||
let our: Address = our.parse().unwrap();
|
||||
|
||||
loop {
|
||||
match handle_message(&our) {
|
||||
|
36
modules/tester/tester/Cargo.lock
generated
36
modules/tester/tester/Cargo.lock
generated
@ -160,6 +160,23 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nectar_process_lib"
|
||||
version = "0.5.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@ -296,10 +313,10 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"indexmap",
|
||||
"nectar_process_lib",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"uqbar_process_lib",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
@ -380,23 +397,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "uqbar_process_lib"
|
||||
version = "0.4.0"
|
||||
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"http",
|
||||
"mime_guess",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
|
@ -17,7 +17,7 @@ indexmap = "2.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
|
||||
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
|
||||
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
|
||||
|
||||
[lib]
|
||||
|
@ -22,7 +22,7 @@ type Messages = IndexMap<kt::Message, tt::KernelMessage>;
|
||||
fn make_vfs_address(our: &Address) -> anyhow::Result<Address> {
|
||||
Ok(Address {
|
||||
node: our.node.clone(),
|
||||
process: ProcessId::from_str("vfs:sys:nectar")?,
|
||||
process: "vfs:sys:nectar".parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -36,15 +36,15 @@ fn handle_message(
|
||||
};
|
||||
|
||||
match message {
|
||||
Message::Response { source, ipc, .. } => {
|
||||
match serde_json::from_slice(&ipc)? {
|
||||
Message::Response { source, body, .. } => {
|
||||
match serde_json::from_slice(&body)? {
|
||||
tt::TesterResponse::Pass | tt::TesterResponse::Fail { .. } => {
|
||||
if (source.process.package_name != "tester")
|
||||
| (source.process.publisher_node != "nectar")
|
||||
{
|
||||
return Err(tt::TesterError::UnexpectedResponse.into());
|
||||
}
|
||||
Response::new().ipc(ipc).send().unwrap();
|
||||
Response::new().body(body).send().unwrap();
|
||||
}
|
||||
tt::TesterResponse::GetFullMessage(_) => {
|
||||
unimplemented!()
|
||||
@ -52,8 +52,8 @@ fn handle_message(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Message::Request { source, ipc, .. } => {
|
||||
match serde_json::from_slice(&ipc)? {
|
||||
Message::Request { source, body, .. } => {
|
||||
match serde_json::from_slice(&body)? {
|
||||
tt::TesterRequest::Run {
|
||||
input_node_names,
|
||||
test_timeout,
|
||||
@ -65,7 +65,7 @@ fn handle_message(
|
||||
|
||||
if our.node != node_names[0] {
|
||||
Response::new()
|
||||
.ipc(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
|
||||
.body(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
|
||||
.send()
|
||||
.unwrap();
|
||||
} else {
|
||||
@ -76,7 +76,7 @@ fn handle_message(
|
||||
child,
|
||||
OnExit::None, // TODO: notify us
|
||||
our_capabilities(),
|
||||
vec![ProcessId::from_str("vfs:sys:nectar").unwrap()],
|
||||
vec!["vfs:sys:nectar".parse::<ProcessId>().unwrap()],
|
||||
false, // not public
|
||||
) {
|
||||
Ok(child_process_id) => child_process_id,
|
||||
@ -90,7 +90,7 @@ fn handle_message(
|
||||
node: our.node.clone(),
|
||||
process: child_process_id,
|
||||
})
|
||||
.ipc(ipc)
|
||||
.body(body)
|
||||
.expects_response(test_timeout)
|
||||
.send()?;
|
||||
}
|
||||
@ -112,7 +112,7 @@ fn init(our: Address) {
|
||||
let mut node_names: Vec<String> = Vec::new();
|
||||
let _ = Request::new()
|
||||
.target(make_vfs_address(&our).unwrap())
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: "/tester:nectar/tests".into(),
|
||||
action: vfs::VfsAction::CreateDrive,
|
||||
@ -124,7 +124,7 @@ fn init(our: Address) {
|
||||
.unwrap();
|
||||
let _ = Request::new()
|
||||
.target(("our", "kernel", "sys", "nectar"))
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
|
||||
target: ProcessId::new(Some("http_server"), "sys", "nectar"),
|
||||
capabilities: vec![kt::Capability {
|
||||
@ -148,7 +148,7 @@ fn init(our: Address) {
|
||||
// -> must give drive cap to rpc
|
||||
let _ = Request::new()
|
||||
.target(make_vfs_address(&our).unwrap())
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&vfs::VfsRequest {
|
||||
path: "/tester:nectar/tests".into(),
|
||||
action: vfs::VfsAction::CreateDrive,
|
||||
|
@ -14,7 +14,7 @@ pub struct KernelMessage {
|
||||
pub target: Address,
|
||||
pub rsvp: Rsvp,
|
||||
pub message: kt::Message,
|
||||
pub payload: Option<kt::Payload>,
|
||||
pub lazy_load_blob: Option<kt::LazyLoadBlob>,
|
||||
pub signed_capabilities: HashMap<kt::Capability, Vec<u8>>,
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ pub enum TesterError {
|
||||
macro_rules! fail {
|
||||
($test:expr) => {
|
||||
Response::new()
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&tt::TesterResponse::Fail {
|
||||
test: $test.into(),
|
||||
file: file!().into(),
|
||||
@ -77,7 +77,7 @@ macro_rules! fail {
|
||||
};
|
||||
($test:expr, $file:expr, $line:expr, $column:expr) => {
|
||||
Response::new()
|
||||
.ipc(
|
||||
.body(
|
||||
serde_json::to_vec(&tt::TesterResponse::Fail {
|
||||
test: $test.into(),
|
||||
file: $file.into(),
|
||||
|
@ -75,9 +75,9 @@ async fn handle_request(
|
||||
connections: &Arc<Mutex<RpcConnections>>,
|
||||
send_to_loop: &MessageSender,
|
||||
) -> Result<()> {
|
||||
if let Ok(action) = serde_json::from_slice::<HttpServerRequest>(&req.ipc) {
|
||||
if let Ok(action) = serde_json::from_slice::<HttpServerRequest>(&req.body) {
|
||||
return handle_http_server_request(action, km, connections).await;
|
||||
} else if let Ok(action) = serde_json::from_slice::<EthRequest>(&req.ipc) {
|
||||
} else if let Ok(action) = serde_json::from_slice::<EthRequest>(&req.body) {
|
||||
return handle_eth_request(action, our, km, connections, send_to_loop).await;
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("malformed request"));
|
||||
@ -95,7 +95,7 @@ async fn handle_http_server_request(
|
||||
} = action
|
||||
{
|
||||
if message_type == WsMessageType::Text {
|
||||
let bytes = &km.payload.as_ref().unwrap().bytes;
|
||||
let bytes = &km.lazy_load_blob.as_ref().unwrap().bytes;
|
||||
let text = std::str::from_utf8(&bytes).unwrap();
|
||||
let mut json: serde_json::Value = serde_json::from_str(text)?;
|
||||
let mut id = json["id"].as_u64().unwrap();
|
||||
@ -211,7 +211,7 @@ async fn spawn_provider_read_stream(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: json!({
|
||||
body: json!({
|
||||
"EventSubscription": serde_json::to_value(event.clone()).unwrap()
|
||||
})
|
||||
.to_string()
|
||||
@ -219,7 +219,7 @@ async fn spawn_provider_read_stream(
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
@ -241,7 +241,7 @@ async fn bind_websockets(our: &str, send_to_loop: &MessageSender) {
|
||||
rsvp: None,
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&HttpServerAction::WebSocketBind {
|
||||
body: serde_json::to_vec(&HttpServerAction::WebSocketBind {
|
||||
path: "/".to_string(),
|
||||
authenticated: false,
|
||||
encrypted: false,
|
||||
@ -251,7 +251,7 @@ async fn bind_websockets(our: &str, send_to_loop: &MessageSender) {
|
||||
expects_response: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@ -316,7 +316,7 @@ async fn handle_external_websocket_passthrough(
|
||||
rsvp: None,
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&HttpServerAction::WebSocketPush {
|
||||
body: serde_json::to_vec(&HttpServerAction::WebSocketPush {
|
||||
channel_id,
|
||||
message_type: WsMessageType::Text,
|
||||
})
|
||||
@ -325,7 +325,7 @@ async fn handle_external_websocket_passthrough(
|
||||
expects_response: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(Payload {
|
||||
lazy_load_blob: Some(LazyLoadBlob {
|
||||
bytes: json.to_string().as_bytes().to_vec(),
|
||||
mime: None,
|
||||
}),
|
||||
|
@ -43,15 +43,15 @@ pub async fn http_client(
|
||||
message:
|
||||
Message::Request(Request {
|
||||
expects_response,
|
||||
ipc,
|
||||
body,
|
||||
..
|
||||
}),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
..
|
||||
}) = recv_in_client.recv().await
|
||||
{
|
||||
// First check if a WebSocketClientAction, otherwise assume it's an OutgoingHttpRequest
|
||||
if let Ok(ws_action) = serde_json::from_slice::<WebSocketClientAction>(&ipc) {
|
||||
if let Ok(ws_action) = serde_json::from_slice::<WebSocketClientAction>(&body) {
|
||||
let ws_streams_clone = Arc::clone(&ws_streams);
|
||||
|
||||
let _ = handle_websocket_action(
|
||||
@ -60,7 +60,7 @@ pub async fn http_client(
|
||||
rsvp.unwrap_or(source),
|
||||
expects_response,
|
||||
ws_action,
|
||||
payload,
|
||||
blob,
|
||||
ws_streams_clone,
|
||||
send_to_loop.clone(),
|
||||
print_tx.clone(),
|
||||
@ -72,8 +72,8 @@ pub async fn http_client(
|
||||
id,
|
||||
rsvp.unwrap_or(source),
|
||||
expects_response,
|
||||
ipc,
|
||||
payload,
|
||||
body,
|
||||
blob,
|
||||
client.clone(),
|
||||
send_to_loop.clone(),
|
||||
print_tx.clone(),
|
||||
@ -89,7 +89,7 @@ async fn handle_websocket_action(
|
||||
target: Address,
|
||||
expects_response: Option<u64>,
|
||||
ws_action: WebSocketClientAction,
|
||||
payload: Option<Payload>,
|
||||
blob: Option<LazyLoadBlob>,
|
||||
ws_streams: WebSocketStreams,
|
||||
send_to_loop: MessageSender,
|
||||
print_tx: PrintSender,
|
||||
@ -118,14 +118,7 @@ async fn handle_websocket_action(
|
||||
channel_id,
|
||||
message_type,
|
||||
} => (
|
||||
send_ws_push(
|
||||
target.clone(),
|
||||
channel_id,
|
||||
message_type,
|
||||
payload,
|
||||
ws_streams,
|
||||
)
|
||||
.await,
|
||||
send_ws_push(target.clone(), channel_id, message_type, blob, ws_streams).await,
|
||||
channel_id,
|
||||
),
|
||||
WebSocketClientAction::Close { channel_id } => (
|
||||
@ -214,7 +207,7 @@ async fn connect_websocket(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec::<WebSocketClientAction>(
|
||||
body: serde_json::to_vec::<WebSocketClientAction>(
|
||||
&WebSocketClientAction::Response {
|
||||
channel_id,
|
||||
result: Ok(()),
|
||||
@ -226,7 +219,7 @@ async fn connect_websocket(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
|
||||
@ -260,7 +253,7 @@ async fn listen_to_stream(
|
||||
// Handle different types of messages here
|
||||
match msg {
|
||||
TungsteniteMessage::Text(text) => {
|
||||
// send a Request to the target with the text as payload
|
||||
// send a Request to the target with the text as blob
|
||||
handle_ws_message(
|
||||
our.clone(),
|
||||
id,
|
||||
@ -269,7 +262,7 @@ async fn listen_to_stream(
|
||||
channel_id,
|
||||
message_type: WsMessageType::Text,
|
||||
},
|
||||
Some(Payload {
|
||||
Some(LazyLoadBlob {
|
||||
mime: Some("text/plain".into()),
|
||||
bytes: text.into_bytes(),
|
||||
}),
|
||||
@ -278,7 +271,7 @@ async fn listen_to_stream(
|
||||
.await;
|
||||
}
|
||||
TungsteniteMessage::Binary(bytes) => {
|
||||
// send a Request to the target with the binary as payload
|
||||
// send a Request to the target with the binary as blob
|
||||
handle_ws_message(
|
||||
our.clone(),
|
||||
id,
|
||||
@ -287,7 +280,7 @@ async fn listen_to_stream(
|
||||
channel_id,
|
||||
message_type: WsMessageType::Binary,
|
||||
},
|
||||
Some(Payload {
|
||||
Some(LazyLoadBlob {
|
||||
mime: Some("application/octet-stream".into()),
|
||||
bytes,
|
||||
}),
|
||||
@ -347,7 +340,7 @@ async fn handle_http_request(
|
||||
target: Address,
|
||||
expects_response: Option<u64>,
|
||||
json: Vec<u8>,
|
||||
body: Option<Payload>,
|
||||
body: Option<LazyLoadBlob>,
|
||||
client: reqwest::Client,
|
||||
send_to_loop: MessageSender,
|
||||
print_tx: PrintSender,
|
||||
@ -414,8 +407,8 @@ async fn handle_http_request(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(payload) = body {
|
||||
request_builder = request_builder.body(payload.bytes);
|
||||
if let Some(blob) = body {
|
||||
request_builder = request_builder.body(blob.bytes);
|
||||
}
|
||||
|
||||
let Ok(request) = request_builder
|
||||
@ -456,7 +449,7 @@ async fn handle_http_request(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Ok(
|
||||
body: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Ok(
|
||||
HttpResponse {
|
||||
status: response.status().as_u16(),
|
||||
headers: serialize_headers(response.headers()),
|
||||
@ -468,7 +461,7 @@ async fn handle_http_request(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: Some(Payload {
|
||||
lazy_load_blob: Some(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: response.bytes().await.unwrap_or_default().to_vec(),
|
||||
}),
|
||||
@ -556,7 +549,7 @@ async fn http_error_message(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Err(
|
||||
body: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Err(
|
||||
error,
|
||||
))
|
||||
.unwrap(),
|
||||
@ -565,7 +558,7 @@ async fn http_error_message(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@ -593,7 +586,7 @@ async fn websocket_error_message(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec::<WebSocketClientAction>(
|
||||
body: serde_json::to_vec::<WebSocketClientAction>(
|
||||
&WebSocketClientAction::Response {
|
||||
channel_id,
|
||||
result: Err(error),
|
||||
@ -605,7 +598,7 @@ async fn websocket_error_message(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
@ -615,7 +608,7 @@ async fn send_ws_push(
|
||||
target: Address,
|
||||
channel_id: u32,
|
||||
message_type: WsMessageType,
|
||||
payload: Option<Payload>,
|
||||
blob: Option<LazyLoadBlob>,
|
||||
ws_streams: WebSocketStreams,
|
||||
) -> Result<(), WebSocketClientError> {
|
||||
let Some(mut ws_stream) = ws_streams.get_mut(&(target.process.clone(), channel_id)) else {
|
||||
@ -626,30 +619,28 @@ async fn send_ws_push(
|
||||
|
||||
let result = match message_type {
|
||||
WsMessageType::Text => {
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(WebSocketClientError::BadRequest {
|
||||
req: "no payload".into(),
|
||||
req: "no blob".into(),
|
||||
});
|
||||
};
|
||||
|
||||
let Ok(text) = String::from_utf8(payload.bytes) else {
|
||||
let Ok(text) = String::from_utf8(blob.bytes) else {
|
||||
return Err(WebSocketClientError::BadRequest {
|
||||
req: "failed to convert payload to string".into(),
|
||||
req: "failed to convert blob to string".into(),
|
||||
});
|
||||
};
|
||||
|
||||
ws_stream.send(TungsteniteMessage::Text(text)).await
|
||||
}
|
||||
WsMessageType::Binary => {
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(WebSocketClientError::BadRequest {
|
||||
req: "no payload".into(),
|
||||
req: "no blob".into(),
|
||||
});
|
||||
};
|
||||
|
||||
ws_stream
|
||||
.send(TungsteniteMessage::Binary(payload.bytes))
|
||||
.await
|
||||
ws_stream.send(TungsteniteMessage::Binary(blob.bytes)).await
|
||||
}
|
||||
WsMessageType::Ping => ws_stream.send(TungsteniteMessage::Ping(vec![])).await,
|
||||
WsMessageType::Pong => ws_stream.send(TungsteniteMessage::Pong(vec![])).await,
|
||||
@ -683,7 +674,7 @@ async fn handle_ws_message(
|
||||
id: u64,
|
||||
target: Address,
|
||||
action: WebSocketClientAction,
|
||||
payload: Option<Payload>,
|
||||
blob: Option<LazyLoadBlob>,
|
||||
send_to_loop: MessageSender,
|
||||
) {
|
||||
let _ = send_to_loop
|
||||
@ -697,12 +688,12 @@ async fn handle_ws_message(
|
||||
rsvp: None,
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec::<WebSocketClientAction>(&action).unwrap(),
|
||||
body: serde_json::to_vec::<WebSocketClientAction>(&action).unwrap(),
|
||||
expects_response: None,
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ struct BoundPath {
|
||||
pub secure_subdomain: Option<String>,
|
||||
pub authenticated: bool,
|
||||
pub local_only: bool,
|
||||
pub static_content: Option<Payload>, // TODO store in filesystem and cache
|
||||
pub static_content: Option<LazyLoadBlob>, // TODO store in filesystem and cache
|
||||
}
|
||||
|
||||
struct BoundWsPath {
|
||||
@ -86,7 +86,7 @@ pub async fn http_server(
|
||||
// add RPC path
|
||||
let mut bindings_map: Router<BoundPath> = Router::new();
|
||||
let rpc_bound_path = BoundPath {
|
||||
app: ProcessId::from_str("rpc:sys:nectar").unwrap(),
|
||||
app: ProcessId::new(Some("rpc"), "sys", "nectar"),
|
||||
secure_subdomain: None, // TODO maybe RPC should have subdomain?
|
||||
authenticated: false,
|
||||
local_only: true,
|
||||
@ -482,7 +482,7 @@ async fn http_handler(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: Some(HTTP_SELF_IMPOSED_TIMEOUT),
|
||||
ipc: serde_json::to_vec(&HttpServerRequest::Http(IncomingHttpRequest {
|
||||
body: serde_json::to_vec(&HttpServerRequest::Http(IncomingHttpRequest {
|
||||
source_socket_addr: socket_addr.map(|addr| addr.to_string()),
|
||||
method: method.to_string(),
|
||||
raw_path: format!(
|
||||
@ -498,7 +498,7 @@ async fn http_handler(
|
||||
metadata: Some("http".into()),
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(Payload {
|
||||
lazy_load_blob: Some(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: body.to_vec(),
|
||||
}),
|
||||
@ -572,7 +572,7 @@ async fn handle_rpc_message(
|
||||
return Err(StatusCode::BAD_REQUEST);
|
||||
};
|
||||
|
||||
let Ok(target_process) = ProcessId::from_str(&rpc_message.process) else {
|
||||
let Ok(target_process) = rpc_message.process.parse::<ProcessId>() else {
|
||||
return Err(StatusCode::BAD_REQUEST);
|
||||
};
|
||||
|
||||
@ -583,10 +583,10 @@ async fn handle_rpc_message(
|
||||
})
|
||||
.await;
|
||||
|
||||
let payload: Option<Payload> = match rpc_message.data {
|
||||
let blob: Option<LazyLoadBlob> = match rpc_message.data {
|
||||
None => None,
|
||||
Some(b64_bytes) => match base64::decode(b64_bytes) {
|
||||
Ok(bytes) => Some(Payload {
|
||||
Ok(bytes) => Some(LazyLoadBlob {
|
||||
mime: rpc_message.mime,
|
||||
bytes,
|
||||
}),
|
||||
@ -611,14 +611,14 @@ async fn handle_rpc_message(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: Some(15), // NB: no effect on runtime
|
||||
ipc: match rpc_message.ipc {
|
||||
Some(ipc_string) => ipc_string.into_bytes(),
|
||||
body: match rpc_message.body {
|
||||
Some(body_string) => body_string.into_bytes(),
|
||||
None => Vec::new(),
|
||||
},
|
||||
metadata: rpc_message.metadata,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
})
|
||||
}
|
||||
|
||||
@ -660,12 +660,12 @@ async fn maintain_websocket(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&HttpServerRequest::WebSocketOpen { path, channel_id })
|
||||
body: serde_json::to_vec(&HttpServerRequest::WebSocketOpen { path, channel_id })
|
||||
.unwrap(),
|
||||
metadata: Some("ws".into()),
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
|
||||
@ -701,14 +701,14 @@ async fn maintain_websocket(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&HttpServerRequest::WebSocketPush {
|
||||
body: serde_json::to_vec(&HttpServerRequest::WebSocketPush {
|
||||
channel_id,
|
||||
message_type: ws_msg_type,
|
||||
}).unwrap(),
|
||||
metadata: Some("ws".into()),
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(Payload {
|
||||
lazy_load_blob: Some(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: msg.into_bytes(),
|
||||
}),
|
||||
@ -763,15 +763,15 @@ async fn websocket_close(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&HttpServerRequest::WebSocketClose(channel_id)).unwrap(),
|
||||
body: serde_json::to_vec(&HttpServerRequest::WebSocketClose(channel_id)).unwrap(),
|
||||
metadata: Some("ws".into()),
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(Payload {
|
||||
lazy_load_blob: Some(LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: serde_json::to_vec(&RpcResponseBody {
|
||||
ipc: Vec::new(),
|
||||
payload: None,
|
||||
body: Vec::new(),
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.unwrap(),
|
||||
}),
|
||||
@ -796,9 +796,9 @@ async fn handle_app_message(
|
||||
let Some((_id, (path, sender))) = http_response_senders.remove(&km.id) else {
|
||||
return;
|
||||
};
|
||||
// if path is /rpc/message, return accordingly with base64 encoded payload
|
||||
// if path is /rpc/message, return accordingly with base64 encoded blob
|
||||
if path == "/rpc:sys:nectar/message" {
|
||||
let payload = km.payload.map(|p| Payload {
|
||||
let blob = km.lazy_load_blob.map(|p| LazyLoadBlob {
|
||||
mime: p.mime,
|
||||
bytes: base64::encode(p.bytes).into_bytes(),
|
||||
});
|
||||
@ -812,13 +812,13 @@ async fn handle_app_message(
|
||||
headers: default_headers,
|
||||
},
|
||||
serde_json::to_vec(&RpcResponseBody {
|
||||
ipc: response.ipc,
|
||||
payload,
|
||||
body: response.body,
|
||||
lazy_load_blob: blob,
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
} else {
|
||||
let Ok(response) = serde_json::from_slice::<HttpResponse>(&response.ipc) else {
|
||||
let Ok(response) = serde_json::from_slice::<HttpResponse>(&response.body) else {
|
||||
// the receiver will automatically trigger a 503 when sender is dropped.
|
||||
return;
|
||||
};
|
||||
@ -827,25 +827,25 @@ async fn handle_app_message(
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
},
|
||||
match km.payload {
|
||||
match km.lazy_load_blob {
|
||||
None => vec![],
|
||||
Some(p) => p.bytes,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
Message::Request(Request { ref ipc, .. }) => {
|
||||
let Ok(message) = serde_json::from_slice::<HttpServerAction>(ipc) else {
|
||||
Message::Request(Request { ref body, .. }) => {
|
||||
let Ok(message) = serde_json::from_slice::<HttpServerAction>(body) else {
|
||||
println!(
|
||||
"http_server: got malformed request from {}: {:?}\r",
|
||||
km.source, ipc
|
||||
km.source, body
|
||||
);
|
||||
send_action_response(
|
||||
km.id,
|
||||
km.source,
|
||||
&send_to_loop,
|
||||
Err(HttpServerError::BadRequest {
|
||||
req: String::from_utf8_lossy(ipc).to_string(),
|
||||
req: String::from_utf8_lossy(body).to_string(),
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
@ -888,12 +888,12 @@ async fn handle_app_message(
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let Some(payload) = km.payload else {
|
||||
let Some(blob) = km.lazy_load_blob else {
|
||||
send_action_response(
|
||||
km.id,
|
||||
km.source,
|
||||
&send_to_loop,
|
||||
Err(HttpServerError::NoPayload),
|
||||
Err(HttpServerError::NoBlob),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
@ -906,7 +906,7 @@ async fn handle_app_message(
|
||||
secure_subdomain: None,
|
||||
authenticated,
|
||||
local_only,
|
||||
static_content: Some(payload),
|
||||
static_content: Some(blob),
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -934,12 +934,12 @@ async fn handle_app_message(
|
||||
},
|
||||
);
|
||||
} else {
|
||||
let Some(payload) = km.payload else {
|
||||
let Some(blob) = km.lazy_load_blob else {
|
||||
send_action_response(
|
||||
km.id,
|
||||
km.source,
|
||||
&send_to_loop,
|
||||
Err(HttpServerError::NoPayload),
|
||||
Err(HttpServerError::NoBlob),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
@ -952,7 +952,7 @@ async fn handle_app_message(
|
||||
secure_subdomain: Some(subdomain),
|
||||
authenticated: true,
|
||||
local_only: false,
|
||||
static_content: Some(payload),
|
||||
static_content: Some(blob),
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -1020,23 +1020,23 @@ async fn handle_app_message(
|
||||
channel_id,
|
||||
message_type,
|
||||
} => {
|
||||
let Some(payload) = km.payload else {
|
||||
let Some(blob) = km.lazy_load_blob else {
|
||||
send_action_response(
|
||||
km.id,
|
||||
km.source,
|
||||
&send_to_loop,
|
||||
Err(HttpServerError::NoPayload),
|
||||
Err(HttpServerError::NoBlob),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
};
|
||||
let ws_message = match message_type {
|
||||
WsMessageType::Text => warp::ws::Message::text(
|
||||
String::from_utf8_lossy(&payload.bytes).to_string(),
|
||||
String::from_utf8_lossy(&blob.bytes).to_string(),
|
||||
),
|
||||
WsMessageType::Binary => warp::ws::Message::binary(payload.bytes),
|
||||
WsMessageType::Binary => warp::ws::Message::binary(blob.bytes),
|
||||
WsMessageType::Ping | WsMessageType::Pong => {
|
||||
if payload.bytes.len() > 125 {
|
||||
if blob.bytes.len() > 125 {
|
||||
send_action_response(
|
||||
km.id,
|
||||
km.source,
|
||||
@ -1050,9 +1050,9 @@ async fn handle_app_message(
|
||||
return;
|
||||
}
|
||||
if message_type == WsMessageType::Ping {
|
||||
warp::ws::Message::ping(payload.bytes)
|
||||
warp::ws::Message::ping(blob.bytes)
|
||||
} else {
|
||||
warp::ws::Message::pong(payload.bytes)
|
||||
warp::ws::Message::pong(blob.bytes)
|
||||
}
|
||||
}
|
||||
WsMessageType::Close => {
|
||||
@ -1147,13 +1147,13 @@ pub async fn send_action_response(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&result).unwrap(),
|
||||
body: serde_json::to_vec(&result).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::types::Payload;
|
||||
use crate::types::LazyLoadBlob;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
@ -17,7 +17,7 @@ pub enum HttpServerRequest {
|
||||
},
|
||||
/// Processes can both SEND and RECEIVE this kind of request
|
||||
/// (send as [`type@HttpServerAction::WebSocketPush`]).
|
||||
/// When received, will contain the message bytes as payload.
|
||||
/// When received, will contain the message bytes as lazy_load_blob.
|
||||
WebSocketPush {
|
||||
channel_id: u32,
|
||||
message_type: WsMessageType,
|
||||
@ -34,7 +34,7 @@ pub struct IncomingHttpRequest {
|
||||
pub raw_path: String,
|
||||
pub headers: HashMap<String, String>,
|
||||
pub query_params: HashMap<String, String>,
|
||||
// BODY is stored in the payload, as bytes
|
||||
// BODY is stored in the lazy_load_blob, as bytes
|
||||
}
|
||||
|
||||
/// HTTP Request type that can be shared over WASM boundary to apps.
|
||||
@ -45,7 +45,7 @@ pub struct OutgoingHttpRequest {
|
||||
pub version: Option<String>, // must parse to http::Version
|
||||
pub url: String, // must parse to url::Url
|
||||
pub headers: HashMap<String, String>,
|
||||
// BODY is stored in the payload, as bytes
|
||||
// BODY is stored in the lazy_load_blob, as bytes
|
||||
// TIMEOUT is stored in the message expect_response
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ pub struct OutgoingHttpRequest {
|
||||
pub struct HttpResponse {
|
||||
pub status: u16,
|
||||
pub headers: HashMap<String, String>,
|
||||
// BODY is stored in the payload, as bytes
|
||||
// BODY is stored in the lazy_load_blob, as bytes
|
||||
}
|
||||
|
||||
/// WebSocket Client Request type that can be shared over WASM boundary to apps.
|
||||
@ -82,8 +82,8 @@ pub enum WebSocketClientAction {
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RpcResponseBody {
|
||||
pub ipc: Vec<u8>,
|
||||
pub payload: Option<Payload>,
|
||||
pub body: Vec<u8>,
|
||||
pub lazy_load_blob: Option<LazyLoadBlob>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Serialize, Deserialize)]
|
||||
@ -122,7 +122,7 @@ pub enum WebSocketClientError {
|
||||
/// with the shape Result<(), HttpServerActionError> serialized to JSON.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum HttpServerAction {
|
||||
/// Bind expects a payload if and only if `cache` is TRUE. The payload should
|
||||
/// Bind expects a lazy_load_blob if and only if `cache` is TRUE. The lazy_load_blob should
|
||||
/// be the static file to serve at this path.
|
||||
Bind {
|
||||
path: String,
|
||||
@ -131,11 +131,11 @@ pub enum HttpServerAction {
|
||||
authenticated: bool,
|
||||
/// Set whether requests can be fielded from anywhere, or only the loopback address.
|
||||
local_only: bool,
|
||||
/// Set whether to bind the payload statically to this path. That is, take the
|
||||
/// payload bytes and serve them as the response to any request to this path.
|
||||
/// Set whether to bind the lazy_load_blob statically to this path. That is, take the
|
||||
/// lazy_load_blob bytes and serve them as the response to any request to this path.
|
||||
cache: bool,
|
||||
},
|
||||
/// SecureBind expects a payload if and only if `cache` is TRUE. The payload should
|
||||
/// SecureBind expects a lazy_load_blob if and only if `cache` is TRUE. The lazy_load_blob should
|
||||
/// be the static file to serve at this path.
|
||||
///
|
||||
/// SecureBind is the same as Bind, except that it forces requests to be made from
|
||||
@ -146,8 +146,8 @@ pub enum HttpServerAction {
|
||||
/// will require the user to be logged in separately to the general domain authentication.
|
||||
SecureBind {
|
||||
path: String,
|
||||
/// Set whether to bind the payload statically to this path. That is, take the
|
||||
/// payload bytes and serve them as the response to any request to this path.
|
||||
/// Set whether to bind the lazy_load_blob statically to this path. That is, take the
|
||||
/// lazy_load_blob bytes and serve them as the response to any request to this path.
|
||||
cache: bool,
|
||||
},
|
||||
/// Bind a path to receive incoming WebSocket connections.
|
||||
@ -166,7 +166,7 @@ pub enum HttpServerAction {
|
||||
/// If a process does not want this websocket open, they should issue a *request*
|
||||
/// containing a [`type@HttpServerAction::WebSocketClose`] message and this channel ID.
|
||||
WebSocketOpen { path: String, channel_id: u32 },
|
||||
/// When sent, expects a payload containing the WebSocket message bytes to send.
|
||||
/// When sent, expects a lazy_load_blob containing the WebSocket message bytes to send.
|
||||
WebSocketPush {
|
||||
channel_id: u32,
|
||||
message_type: WsMessageType,
|
||||
@ -176,9 +176,9 @@ pub enum HttpServerAction {
|
||||
}
|
||||
|
||||
/// The possible message types for WebSocketPush. Ping and Pong are limited to 125 bytes
|
||||
/// by the WebSockets protocol. Text will be sent as a Text frame, with the payload bytes
|
||||
/// by the WebSockets protocol. Text will be sent as a Text frame, with the lazy_load_blob bytes
|
||||
/// being the UTF-8 encoding of the string. Binary will be sent as a Binary frame containing
|
||||
/// the unmodified payload bytes.
|
||||
/// the unmodified lazy_load_blob bytes.
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum WsMessageType {
|
||||
Text,
|
||||
@ -196,8 +196,8 @@ pub enum HttpServerError {
|
||||
req
|
||||
)]
|
||||
BadRequest { req: String },
|
||||
#[error("http_server: action expected payload")]
|
||||
NoPayload,
|
||||
#[error("http_server: action expected blob")]
|
||||
NoBlob,
|
||||
#[error("http_server: path binding error: {:?}", error)]
|
||||
PathBindError { error: String },
|
||||
#[error("http_server: WebSocket error: {:?}", error)]
|
||||
|
@ -13,7 +13,7 @@ pub struct RpcMessage {
|
||||
pub process: String,
|
||||
pub inherit: Option<bool>,
|
||||
pub expects_response: Option<u64>,
|
||||
pub ipc: Option<String>,
|
||||
pub body: Option<String>,
|
||||
pub metadata: Option<String>,
|
||||
pub context: Option<String>,
|
||||
pub mime: Option<String>,
|
||||
|
@ -65,12 +65,12 @@ async fn persist_state(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: true,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&t::StateAction::SetState(KERNEL_PROCESS_ID.clone()))
|
||||
body: serde_json::to_vec(&t::StateAction::SetState(KERNEL_PROCESS_ID.clone()))
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(t::Payload { mime: None, bytes }),
|
||||
lazy_load_blob: Some(t::LazyLoadBlob { mime: None, bytes }),
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
@ -92,7 +92,7 @@ async fn handle_kernel_request(
|
||||
let t::Message::Request(request) = km.message else {
|
||||
return;
|
||||
};
|
||||
let command: t::KernelCommand = match serde_json::from_slice(&request.ipc) {
|
||||
let command: t::KernelCommand = match serde_json::from_slice(&request.body) {
|
||||
Err(e) => {
|
||||
let _ = send_to_terminal
|
||||
.send(t::Printout {
|
||||
@ -125,11 +125,11 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: b"run".to_vec(),
|
||||
body: b"run".to_vec(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}))
|
||||
.await;
|
||||
}
|
||||
@ -150,7 +150,7 @@ async fn handle_kernel_request(
|
||||
initial_capabilities,
|
||||
public,
|
||||
} => {
|
||||
let Some(payload) = km.payload else {
|
||||
let Some(blob) = km.lazy_load_blob else {
|
||||
let _ = send_to_terminal
|
||||
.send(t::Printout {
|
||||
verbosity: 0,
|
||||
@ -170,14 +170,16 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&t::KernelResponse::InitializeProcessError)
|
||||
.unwrap(),
|
||||
body: serde_json::to_vec(
|
||||
&t::KernelResponse::InitializeProcessError,
|
||||
)
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -247,7 +249,7 @@ async fn handle_kernel_request(
|
||||
our_name.clone(),
|
||||
keypair.clone(),
|
||||
km.id,
|
||||
payload.bytes,
|
||||
blob.bytes,
|
||||
send_to_loop.clone(),
|
||||
send_to_terminal,
|
||||
senders,
|
||||
@ -288,7 +290,7 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(
|
||||
body: serde_json::to_vec(
|
||||
&t::KernelResponse::InitializeProcessError,
|
||||
)
|
||||
.unwrap(),
|
||||
@ -297,7 +299,7 @@ async fn handle_kernel_request(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -353,11 +355,11 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: b"run".to_vec(),
|
||||
body: b"run".to_vec(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}))
|
||||
.await
|
||||
{
|
||||
@ -373,14 +375,14 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&t::KernelResponse::StartedProcess)
|
||||
body: serde_json::to_vec(&t::KernelResponse::StartedProcess)
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -405,14 +407,14 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&t::KernelResponse::RunProcessError)
|
||||
body: serde_json::to_vec(&t::KernelResponse::RunProcessError)
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -459,14 +461,14 @@ async fn handle_kernel_request(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&t::KernelResponse::KilledProcess(process_id))
|
||||
body: serde_json::to_vec(&t::KernelResponse::KilledProcess(process_id))
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -521,7 +523,7 @@ async fn start_process(
|
||||
our_name: String,
|
||||
keypair: Arc<signature::Ed25519KeyPair>,
|
||||
km_id: u64,
|
||||
km_payload_bytes: Vec<u8>,
|
||||
km_blob_bytes: Vec<u8>,
|
||||
send_to_loop: t::MessageSender,
|
||||
send_to_terminal: t::PrintSender,
|
||||
senders: &mut Senders,
|
||||
@ -569,7 +571,7 @@ async fn start_process(
|
||||
send_to_terminal.clone(),
|
||||
recv_in_process,
|
||||
send_to_process,
|
||||
km_payload_bytes,
|
||||
km_blob_bytes,
|
||||
caps_oracle,
|
||||
engine.clone(),
|
||||
)),
|
||||
@ -592,13 +594,13 @@ async fn start_process(
|
||||
message: t::Message::Response((
|
||||
t::Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&t::KernelResponse::InitializedProcess)?,
|
||||
body: serde_json::to_vec(&t::KernelResponse::InitializedProcess)?,
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
@ -691,7 +693,7 @@ pub async fn kernel(
|
||||
if let t::OnExit::Requests(requests) = &persisted.on_exit {
|
||||
// if a persisted process had on-death-requests, we should perform them now
|
||||
// even in death, a process can only message processes it has capabilities for
|
||||
for (address, request, payload) in requests {
|
||||
for (address, request, blob) in requests {
|
||||
// the process that made the request is dead, so never expects response
|
||||
let mut request = request.to_owned();
|
||||
request.expects_response = None;
|
||||
@ -710,7 +712,7 @@ pub async fn kernel(
|
||||
target: address.clone(),
|
||||
rsvp: None,
|
||||
message: t::Message::Request(request),
|
||||
payload: payload.clone(),
|
||||
lazy_load_blob: blob.clone(),
|
||||
})
|
||||
.await
|
||||
.expect("fatal: kernel event loop died");
|
||||
@ -767,11 +769,11 @@ pub async fn kernel(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: true,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::Booted).unwrap(),
|
||||
body: serde_json::to_vec(&t::KernelCommand::Booted).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("fatal: kernel event loop died");
|
||||
|
@ -26,7 +26,7 @@ pub struct ProcessState {
|
||||
pub send_to_loop: t::MessageSender,
|
||||
pub send_to_terminal: t::PrintSender,
|
||||
pub prompting_message: Option<t::KernelMessage>,
|
||||
pub last_payload: Option<t::Payload>,
|
||||
pub last_blob: Option<t::LazyLoadBlob>,
|
||||
pub contexts: HashMap<u64, (t::ProcessContext, JoinHandle<()>)>,
|
||||
pub message_queue: VecDeque<Result<t::KernelMessage, t::WrappedSendError>>,
|
||||
pub caps_oracle: t::CapMessageSender,
|
||||
@ -58,7 +58,7 @@ pub async fn send_and_await_response(
|
||||
source: Option<t::Address>,
|
||||
target: wit::Address,
|
||||
request: wit::Request,
|
||||
payload: Option<wit::Payload>,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) -> Result<Result<(wit::Address, wit::Message), wit::SendError>> {
|
||||
if request.expects_response.is_none() {
|
||||
return Err(anyhow::anyhow!(
|
||||
@ -68,7 +68,7 @@ pub async fn send_and_await_response(
|
||||
}
|
||||
let id = process
|
||||
.process
|
||||
.send_request(source, target, request, None, payload)
|
||||
.send_request(source, target, request, None, blob)
|
||||
.await;
|
||||
match id {
|
||||
Ok(id) => match process.process.get_specific_message_for_process(id).await {
|
||||
@ -108,7 +108,7 @@ impl ProcessState {
|
||||
target: wit::Address,
|
||||
request: wit::Request,
|
||||
new_context: Option<wit::Context>,
|
||||
payload: Option<wit::Payload>,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) -> Result<u64> {
|
||||
let source = match &fake_source {
|
||||
Some(_) => fake_source.unwrap(),
|
||||
@ -130,13 +130,13 @@ impl ProcessState {
|
||||
}
|
||||
};
|
||||
|
||||
let payload = match payload {
|
||||
Some(p) => Some(t::Payload {
|
||||
let blob = match blob {
|
||||
Some(p) => Some(t::LazyLoadBlob {
|
||||
mime: p.mime,
|
||||
bytes: p.bytes,
|
||||
}),
|
||||
None => match request.inherit {
|
||||
true => self.last_payload.clone(),
|
||||
true => self.last_blob.clone(),
|
||||
false => None,
|
||||
},
|
||||
};
|
||||
@ -186,7 +186,7 @@ impl ProcessState {
|
||||
(_, None, None) => None,
|
||||
},
|
||||
message: t::Message::Request(inner_request),
|
||||
payload: payload.clone(),
|
||||
lazy_load_blob: blob.clone(),
|
||||
};
|
||||
|
||||
// modify the process' context map as needed.
|
||||
@ -205,7 +205,7 @@ impl ProcessState {
|
||||
kind: t::SendErrorKind::Timeout,
|
||||
target: t::Address::de_wit(target),
|
||||
message: t::Message::Request(t::de_wit_request(request.clone())),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
},
|
||||
}))
|
||||
.await;
|
||||
@ -235,7 +235,11 @@ impl ProcessState {
|
||||
}
|
||||
|
||||
/// takes Response generated by a process and sends it to the main event loop.
|
||||
pub async fn send_response(&mut self, response: wit::Response, payload: Option<wit::Payload>) {
|
||||
pub async fn send_response(
|
||||
&mut self,
|
||||
response: wit::Response,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) {
|
||||
let (id, target) = match self.make_response_id_target().await {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
@ -250,9 +254,9 @@ impl ProcessState {
|
||||
}
|
||||
};
|
||||
|
||||
let payload = match response.inherit {
|
||||
true => self.last_payload.clone(),
|
||||
false => t::de_wit_payload(payload),
|
||||
let blob = match response.inherit {
|
||||
true => self.last_blob.clone(),
|
||||
false => t::de_wit_blob(blob),
|
||||
};
|
||||
|
||||
let mut inner_response = t::de_wit_response(response.clone());
|
||||
@ -285,7 +289,7 @@ impl ProcessState {
|
||||
// the context will be set by the process receiving this Response.
|
||||
None,
|
||||
)),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
})
|
||||
.await
|
||||
.expect("fatal: kernel couldn't send response");
|
||||
@ -331,14 +335,14 @@ impl ProcessState {
|
||||
let (context, km) = match res {
|
||||
Ok(km) => match &km.message {
|
||||
t::Message::Request(_) => {
|
||||
self.last_payload = km.payload.clone();
|
||||
self.last_blob = km.lazy_load_blob.clone();
|
||||
self.prompting_message = Some(km.clone());
|
||||
(None, km)
|
||||
}
|
||||
t::Message::Response(_) => {
|
||||
if let Some((context, timeout_handle)) = self.contexts.remove(&km.id) {
|
||||
timeout_handle.abort();
|
||||
self.last_payload = km.payload.clone();
|
||||
self.last_blob = km.lazy_load_blob.clone();
|
||||
self.prompting_message = match context.prompting_message {
|
||||
None => Some(km.clone()),
|
||||
Some(prompting_message) => Some(prompting_message),
|
||||
@ -458,7 +462,7 @@ pub async fn make_process_loop(
|
||||
== t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: b"run".to_vec(),
|
||||
body: b"run".to_vec(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}))
|
||||
@ -499,7 +503,7 @@ pub async fn make_process_loop(
|
||||
send_to_loop: send_to_loop.clone(),
|
||||
send_to_terminal: send_to_terminal.clone(),
|
||||
prompting_message: None,
|
||||
last_payload: None,
|
||||
last_blob: None,
|
||||
contexts: HashMap::new(),
|
||||
message_queue: VecDeque::new(),
|
||||
caps_oracle: caps_oracle.clone(),
|
||||
@ -576,14 +580,14 @@ pub async fn make_process_loop(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::KillProcess(
|
||||
body: serde_json::to_vec(&t::KernelCommand::KillProcess(
|
||||
metadata.our.process.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -616,14 +620,14 @@ pub async fn make_process_loop(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::KillProcess(
|
||||
body: serde_json::to_vec(&t::KernelCommand::KillProcess(
|
||||
metadata.our.process.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
@ -642,7 +646,7 @@ pub async fn make_process_loop(
|
||||
message: t::Message::Request(t::Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::InitializeProcess {
|
||||
body: serde_json::to_vec(&t::KernelCommand::InitializeProcess {
|
||||
id: metadata.our.process.clone(),
|
||||
wasm_bytes_handle: metadata.wasm_bytes_handle,
|
||||
wit_version: Some(metadata.wit_version),
|
||||
@ -654,7 +658,7 @@ pub async fn make_process_loop(
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: Some(t::Payload {
|
||||
lazy_load_blob: Some(t::LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: wasm_bytes,
|
||||
}),
|
||||
@ -665,7 +669,7 @@ pub async fn make_process_loop(
|
||||
// if requests, fire them
|
||||
// even in death, a process can only message processes it has capabilities for
|
||||
t::OnExit::Requests(requests) => {
|
||||
for (address, mut request, payload) in requests {
|
||||
for (address, mut request, blob) in requests {
|
||||
request.expects_response = None;
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
let _ = caps_oracle
|
||||
@ -686,7 +690,7 @@ pub async fn make_process_loop(
|
||||
target: address,
|
||||
rsvp: None,
|
||||
message: t::Message::Request(request),
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
})
|
||||
.await
|
||||
.expect("event loop: fatal: sender died");
|
||||
|
@ -33,11 +33,6 @@ impl StandardHost for process::ProcessWasi {
|
||||
.map_err(|e| anyhow::anyhow!("fatal: couldn't send to terminal: {e:?}"))
|
||||
}
|
||||
|
||||
async fn get_eth_block(&mut self) -> Result<u64> {
|
||||
// TODO connect to eth RPC
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
//
|
||||
// process management:
|
||||
//
|
||||
@ -56,7 +51,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
/// create a message from the *kernel* to the filesystem,
|
||||
/// asking it to fetch the current state saved under this process
|
||||
async fn get_state(&mut self) -> Result<Option<Vec<u8>>> {
|
||||
let old_last_payload = self.process.last_payload.clone();
|
||||
let old_last_blob = self.process.last_blob.clone();
|
||||
let res = match process::send_and_await_response(
|
||||
self,
|
||||
Some(t::Address {
|
||||
@ -70,7 +65,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5),
|
||||
ipc: serde_json::to_vec(&t::StateAction::GetState(
|
||||
body: serde_json::to_vec(&t::StateAction::GetState(
|
||||
self.process.metadata.our.process.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
@ -83,14 +78,14 @@ impl StandardHost for process::ProcessWasi {
|
||||
{
|
||||
Ok(Ok(_resp)) => {
|
||||
// basically assuming filesystem responding properly here
|
||||
match &self.process.last_payload {
|
||||
match &self.process.last_blob {
|
||||
None => Ok(None),
|
||||
Some(payload) => Ok(Some(payload.bytes.clone())),
|
||||
Some(blob) => Ok(Some(blob.bytes.clone())),
|
||||
}
|
||||
}
|
||||
_ => Ok(None),
|
||||
};
|
||||
self.process.last_payload = old_last_payload;
|
||||
self.process.last_blob = old_last_blob;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -98,7 +93,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
/// asking it to replace the current state saved under
|
||||
/// this process with these bytes
|
||||
async fn set_state(&mut self, bytes: Vec<u8>) -> Result<()> {
|
||||
let old_last_payload = self.process.last_payload.clone();
|
||||
let old_last_blob = self.process.last_blob.clone();
|
||||
let res = match process::send_and_await_response(
|
||||
self,
|
||||
Some(t::Address {
|
||||
@ -112,14 +107,14 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5),
|
||||
ipc: serde_json::to_vec(&t::StateAction::SetState(
|
||||
body: serde_json::to_vec(&t::StateAction::SetState(
|
||||
self.process.metadata.our.process.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
metadata: Some(self.process.metadata.our.process.to_string()),
|
||||
capabilities: vec![],
|
||||
},
|
||||
Some(wit::Payload { mime: None, bytes }),
|
||||
Some(wit::LazyLoadBlob { mime: None, bytes }),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@ -131,7 +126,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
"filesystem did not respond properly to SetState!!"
|
||||
)),
|
||||
};
|
||||
self.process.last_payload = old_last_payload;
|
||||
self.process.last_blob = old_last_blob;
|
||||
print_debug(&self.process, "persisted state").await;
|
||||
return res;
|
||||
}
|
||||
@ -139,7 +134,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
/// create a message from the *kernel* to the filesystem,
|
||||
/// asking it to delete the current state saved under this process
|
||||
async fn clear_state(&mut self) -> Result<()> {
|
||||
let old_last_payload = self.process.last_payload.clone();
|
||||
let old_last_blob = self.process.last_blob.clone();
|
||||
let res = match process::send_and_await_response(
|
||||
self,
|
||||
Some(t::Address {
|
||||
@ -153,7 +148,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5),
|
||||
ipc: serde_json::to_vec(&t::StateAction::DeleteState(
|
||||
body: serde_json::to_vec(&t::StateAction::DeleteState(
|
||||
self.process.metadata.our.process.clone(),
|
||||
))
|
||||
.unwrap(),
|
||||
@ -172,7 +167,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
"filesystem did not respond properly to ClearState!!"
|
||||
)),
|
||||
};
|
||||
self.process.last_payload = old_last_payload;
|
||||
self.process.last_blob = old_last_blob;
|
||||
print_debug(&self.process, "cleared persisted state").await;
|
||||
return res;
|
||||
}
|
||||
@ -189,8 +184,8 @@ impl StandardHost for process::ProcessWasi {
|
||||
grant_capabilities: Vec<wit::ProcessId>,
|
||||
public: bool,
|
||||
) -> Result<Result<wit::ProcessId, wit::SpawnError>> {
|
||||
// save existing payload to restore later
|
||||
let old_last_payload = self.process.last_payload.clone();
|
||||
// save existing blob to restore later
|
||||
let old_last_blob = self.process.last_blob.clone();
|
||||
let vfs_address = wit::Address {
|
||||
node: self.process.metadata.our.node.clone(),
|
||||
process: VFS_PROCESS_ID.en_wit(),
|
||||
@ -202,7 +197,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5),
|
||||
ipc: serde_json::to_vec(&t::VfsRequest {
|
||||
body: serde_json::to_vec(&t::VfsRequest {
|
||||
path: wasm_path.clone(),
|
||||
action: t::VfsAction::Read,
|
||||
})
|
||||
@ -215,23 +210,23 @@ impl StandardHost for process::ProcessWasi {
|
||||
.await
|
||||
else {
|
||||
println!("spawn: GetHash fail");
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
let wit::Message::Response((wit::Response { ipc, .. }, _)) = hash_response else {
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
let wit::Message::Response((wit::Response { body, .. }, _)) = hash_response else {
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
let t::VfsResponse::Read = serde_json::from_slice(&ipc).unwrap() else {
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
let t::VfsResponse::Read = serde_json::from_slice(&body).unwrap() else {
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
let Some(t::Payload { mime: _, ref bytes }) = self.process.last_payload else {
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
let Some(t::LazyLoadBlob { mime: _, ref bytes }) = self.process.last_blob else {
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
|
||||
@ -258,7 +253,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5), // TODO evaluate
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::InitializeProcess {
|
||||
body: serde_json::to_vec(&t::KernelCommand::InitializeProcess {
|
||||
id: new_process_id.clone(),
|
||||
wasm_bytes_handle: wasm_path,
|
||||
wit_version: Some(self.process.metadata.wit_version),
|
||||
@ -276,15 +271,15 @@ impl StandardHost for process::ProcessWasi {
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
Some(wit::Payload {
|
||||
Some(wit::LazyLoadBlob {
|
||||
mime: None,
|
||||
bytes: bytes.to_vec(),
|
||||
}),
|
||||
)
|
||||
.await
|
||||
else {
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NameTaken));
|
||||
};
|
||||
// insert messaging capabilities into requested processes
|
||||
@ -321,7 +316,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5), // TODO evaluate
|
||||
ipc: serde_json::to_vec(&t::KernelCommand::RunProcess(new_process_id.clone()))
|
||||
body: serde_json::to_vec(&t::KernelCommand::RunProcess(new_process_id.clone()))
|
||||
.unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
@ -330,16 +325,16 @@ impl StandardHost for process::ProcessWasi {
|
||||
)
|
||||
.await
|
||||
else {
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
return Ok(Err(wit::SpawnError::NameTaken));
|
||||
};
|
||||
// reset payload to what it was
|
||||
self.process.last_payload = old_last_payload;
|
||||
let wit::Message::Response((wit::Response { ipc, .. }, _)) = response else {
|
||||
// reset blob to what it was
|
||||
self.process.last_blob = old_last_blob;
|
||||
let wit::Message::Response((wit::Response { body, .. }, _)) = response else {
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
let t::KernelResponse::StartedProcess = serde_json::from_slice(&ipc).unwrap() else {
|
||||
let t::KernelResponse::StartedProcess = serde_json::from_slice(&body).unwrap() else {
|
||||
return Ok(Err(wit::SpawnError::NoFileAtPath));
|
||||
};
|
||||
// child processes are always able to Message parent
|
||||
@ -433,11 +428,11 @@ impl StandardHost for process::ProcessWasi {
|
||||
Ok(self.process.get_next_message_for_process().await)
|
||||
}
|
||||
|
||||
/// from a process: grab the payload part of the current prompting message.
|
||||
/// if the prompting message did not have a payload, will return None.
|
||||
/// from a process: grab the blob part of the current prompting message.
|
||||
/// if the prompting message did not have a blob, will return None.
|
||||
/// will also return None if there is no prompting message.
|
||||
async fn get_payload(&mut self) -> Result<Option<wit::Payload>> {
|
||||
Ok(t::en_wit_payload(self.process.last_payload.clone()))
|
||||
async fn get_blob(&mut self) -> Result<Option<wit::LazyLoadBlob>> {
|
||||
Ok(t::en_wit_blob(self.process.last_blob.clone()))
|
||||
}
|
||||
|
||||
async fn send_request(
|
||||
@ -445,11 +440,11 @@ impl StandardHost for process::ProcessWasi {
|
||||
target: wit::Address,
|
||||
request: wit::Request,
|
||||
context: Option<wit::Context>,
|
||||
payload: Option<wit::Payload>,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) -> Result<()> {
|
||||
let id = self
|
||||
.process
|
||||
.send_request(None, target, request, context, payload)
|
||||
.send_request(None, target, request, context, blob)
|
||||
.await;
|
||||
match id {
|
||||
Ok(_id) => Ok(()),
|
||||
@ -463,7 +458,7 @@ impl StandardHost for process::ProcessWasi {
|
||||
wit::Address,
|
||||
wit::Request,
|
||||
Option<wit::Context>,
|
||||
Option<wit::Payload>,
|
||||
Option<wit::LazyLoadBlob>,
|
||||
)>,
|
||||
) -> Result<()> {
|
||||
for request in requests {
|
||||
@ -482,9 +477,9 @@ impl StandardHost for process::ProcessWasi {
|
||||
async fn send_response(
|
||||
&mut self,
|
||||
response: wit::Response,
|
||||
payload: Option<wit::Payload>,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) -> Result<()> {
|
||||
self.process.send_response(response, payload).await;
|
||||
self.process.send_response(response, blob).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -492,8 +487,8 @@ impl StandardHost for process::ProcessWasi {
|
||||
&mut self,
|
||||
target: wit::Address,
|
||||
request: wit::Request,
|
||||
payload: Option<wit::Payload>,
|
||||
blob: Option<wit::LazyLoadBlob>,
|
||||
) -> Result<Result<(wit::Address, wit::Message), wit::SendError>> {
|
||||
process::send_and_await_response(self, None, target, request, payload).await
|
||||
process::send_and_await_response(self, None, target, request, blob).await
|
||||
}
|
||||
}
|
||||
|
32
src/kv.rs
32
src/kv.rs
@ -101,11 +101,11 @@ async fn handle_request(
|
||||
id,
|
||||
source,
|
||||
message,
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
..
|
||||
} = km.clone();
|
||||
let Message::Request(Request {
|
||||
ipc,
|
||||
body,
|
||||
expects_response,
|
||||
metadata,
|
||||
..
|
||||
@ -116,7 +116,7 @@ async fn handle_request(
|
||||
});
|
||||
};
|
||||
|
||||
let request: KvRequest = match serde_json::from_slice(&ipc) {
|
||||
let request: KvRequest = match serde_json::from_slice(&body) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
println!("kv: got invalid Request: {}", e);
|
||||
@ -136,7 +136,7 @@ async fn handle_request(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (ipc, bytes) = match &request.action {
|
||||
let (body, bytes) = match &request.action {
|
||||
KvAction::Open => {
|
||||
// handled in check_caps.
|
||||
(serde_json::to_vec(&KvResponse::Ok).unwrap(), None)
|
||||
@ -184,15 +184,15 @@ async fn handle_request(
|
||||
}
|
||||
Some(db) => db,
|
||||
};
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(KvError::InputError {
|
||||
error: "no payload".into(),
|
||||
error: "no blob".into(),
|
||||
});
|
||||
};
|
||||
|
||||
match tx_id {
|
||||
None => {
|
||||
db.put(key, payload.bytes)?;
|
||||
db.put(key, blob.bytes)?;
|
||||
}
|
||||
Some(tx_id) => {
|
||||
let mut tx = match txs.get_mut(&tx_id) {
|
||||
@ -201,7 +201,7 @@ async fn handle_request(
|
||||
}
|
||||
Some(tx) => tx,
|
||||
};
|
||||
tx.push((request.action.clone(), Some(payload.bytes)));
|
||||
tx.push((request.action.clone(), Some(blob.bytes)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,11 +246,11 @@ async fn handle_request(
|
||||
};
|
||||
let tx = db.transaction();
|
||||
|
||||
for (action, payload) in txs {
|
||||
for (action, blob) in txs {
|
||||
match action {
|
||||
KvAction::Set { key, .. } => {
|
||||
if let Some(payload) = payload {
|
||||
tx.put(&key, &payload)?;
|
||||
if let Some(blob) = blob {
|
||||
tx.put(&key, &blob)?;
|
||||
}
|
||||
}
|
||||
KvAction::Delete { key, .. } => {
|
||||
@ -297,13 +297,13 @@ async fn handle_request(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc,
|
||||
body,
|
||||
metadata,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: bytes.map(|bytes| Payload {
|
||||
lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
|
||||
mime: Some("application/octet-stream".into()),
|
||||
bytes,
|
||||
}),
|
||||
@ -316,7 +316,7 @@ async fn handle_request(
|
||||
verbosity: 2,
|
||||
content: format!(
|
||||
"kv: not sending response: {:?}",
|
||||
serde_json::from_slice::<KvResponse>(&ipc)
|
||||
serde_json::from_slice::<KvResponse>(&body)
|
||||
),
|
||||
})
|
||||
.await
|
||||
@ -497,13 +497,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: KvError) -> K
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&KvResponse::Err { error: error }).unwrap(),
|
||||
body: serde_json::to_vec(&KvResponse::Err { error: error }).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,11 +507,11 @@ async fn main() {
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(),
|
||||
body: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
|
||||
|
@ -855,12 +855,12 @@ async fn handle_local_message(
|
||||
print_tx: &PrintSender,
|
||||
) -> Result<()> {
|
||||
print_debug(print_tx, "net: handling local message").await;
|
||||
let ipc = match km.message {
|
||||
Message::Request(ref request) => &request.ipc,
|
||||
let body = match km.message {
|
||||
Message::Request(ref request) => &request.body,
|
||||
Message::Response((response, _context)) => {
|
||||
// these are received as a router, when we send ConnectionRequests
|
||||
// to a node we do routing for.
|
||||
match rmp_serde::from_slice::<NetResponses>(&response.ipc) {
|
||||
match rmp_serde::from_slice::<NetResponses>(&response.body) {
|
||||
Ok(NetResponses::Accepted(_)) => {
|
||||
// TODO anything here?
|
||||
}
|
||||
@ -880,7 +880,7 @@ async fn handle_local_message(
|
||||
};
|
||||
|
||||
if km.source.node != our.name {
|
||||
if let Ok(act) = rmp_serde::from_slice::<NetActions>(ipc) {
|
||||
if let Ok(act) = rmp_serde::from_slice::<NetActions>(body) {
|
||||
match act {
|
||||
NetActions::QnsBatchUpdate(_) | NetActions::QnsUpdate(_) => {
|
||||
// for now, we don't get these from remote.
|
||||
@ -922,14 +922,14 @@ async fn handle_local_message(
|
||||
id: km.id,
|
||||
source: Address {
|
||||
node: our.name.clone(),
|
||||
process: ProcessId::from_str("net:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("net"), "sys", "nectar"),
|
||||
},
|
||||
target: km.rsvp.unwrap_or(km.source),
|
||||
rsvp: None,
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: rmp_serde::to_vec(
|
||||
body: rmp_serde::to_vec(
|
||||
&res.unwrap_or(NetResponses::Rejected(from)),
|
||||
)?,
|
||||
metadata: None,
|
||||
@ -937,7 +937,7 @@ async fn handle_local_message(
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
@ -946,13 +946,13 @@ async fn handle_local_message(
|
||||
};
|
||||
// if we can't parse this to a netaction, treat it as a hello and print it
|
||||
// respond to a text message with a simple "delivered" response
|
||||
parse_hello_message(our, &km, ipc, kernel_message_tx, print_tx).await?;
|
||||
parse_hello_message(our, &km, body, kernel_message_tx, print_tx).await?;
|
||||
Ok(())
|
||||
} else {
|
||||
// available commands: "peers", "pki", "names", "diagnostics"
|
||||
// first parse as raw string, then deserialize to NetActions object
|
||||
let mut printout = String::new();
|
||||
match std::str::from_utf8(ipc) {
|
||||
match std::str::from_utf8(body) {
|
||||
Ok("peers") => {
|
||||
printout.push_str(&format!(
|
||||
"{:#?}",
|
||||
@ -992,7 +992,7 @@ async fn handle_local_message(
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match rmp_serde::from_slice::<NetActions>(ipc) {
|
||||
match rmp_serde::from_slice::<NetActions>(body) {
|
||||
Ok(NetActions::ConnectionRequest(_)) => {
|
||||
// we shouldn't receive these from ourselves.
|
||||
}
|
||||
@ -1036,7 +1036,7 @@ async fn handle_local_message(
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
parse_hello_message(our, &km, ipc, kernel_message_tx, print_tx).await?;
|
||||
parse_hello_message(our, &km, body, kernel_message_tx, print_tx).await?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -215,21 +215,21 @@ pub async fn create_passthrough(
|
||||
id: rand::random(),
|
||||
source: Address {
|
||||
node: our.name.clone(),
|
||||
process: ProcessId::from_str("net:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("net"), "sys", "nectar"),
|
||||
},
|
||||
target: Address {
|
||||
node: to_name.clone(),
|
||||
process: ProcessId::from_str("net:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("net"), "sys", "nectar"),
|
||||
},
|
||||
rsvp: None,
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: Some(5),
|
||||
ipc: rmp_serde::to_vec(&NetActions::ConnectionRequest(from_id.name.clone()))?,
|
||||
body: rmp_serde::to_vec(&NetActions::ConnectionRequest(from_id.name.clone()))?,
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})?;
|
||||
|
||||
return Ok((
|
||||
@ -449,7 +449,7 @@ pub async fn error_offline(km: KernelMessage, network_error_tx: &NetworkErrorSen
|
||||
kind: SendErrorKind::Offline,
|
||||
target: km.target,
|
||||
message: km.message,
|
||||
payload: km.payload,
|
||||
lazy_load_blob: km.lazy_load_blob,
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
@ -466,7 +466,7 @@ fn strip_0x(s: &str) -> String {
|
||||
pub async fn parse_hello_message(
|
||||
our: &Identity,
|
||||
km: &KernelMessage,
|
||||
ipc: &[u8],
|
||||
body: &[u8],
|
||||
kernel_message_tx: &MessageSender,
|
||||
print_tx: &PrintSender,
|
||||
) -> Result<()> {
|
||||
@ -476,7 +476,7 @@ pub async fn parse_hello_message(
|
||||
content: format!(
|
||||
"\x1b[3;32m{}: {}\x1b[0m",
|
||||
km.source.node,
|
||||
std::str::from_utf8(ipc).unwrap_or("!!message parse error!!")
|
||||
std::str::from_utf8(body).unwrap_or("!!message parse error!!")
|
||||
),
|
||||
})
|
||||
.await?;
|
||||
@ -485,20 +485,20 @@ pub async fn parse_hello_message(
|
||||
id: km.id,
|
||||
source: Address {
|
||||
node: our.name.clone(),
|
||||
process: ProcessId::from_str("net:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("net"), "sys", "nectar"),
|
||||
},
|
||||
target: km.rsvp.as_ref().unwrap_or(&km.source).clone(),
|
||||
rsvp: None,
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: "delivered".as_bytes().to_vec(),
|
||||
body: "delivered".as_bytes().to_vec(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
|
@ -121,11 +121,11 @@ async fn handle_request(
|
||||
id,
|
||||
source,
|
||||
message,
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
..
|
||||
} = km.clone();
|
||||
let Message::Request(Request {
|
||||
ipc,
|
||||
body,
|
||||
expects_response,
|
||||
metadata,
|
||||
..
|
||||
@ -136,7 +136,7 @@ async fn handle_request(
|
||||
});
|
||||
};
|
||||
|
||||
let request: SqliteRequest = match serde_json::from_slice(&ipc) {
|
||||
let request: SqliteRequest = match serde_json::from_slice(&body) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
println!("sqlite: got invalid Request: {}", e);
|
||||
@ -156,7 +156,7 @@ async fn handle_request(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (ipc, bytes) = match request.action {
|
||||
let (body, bytes) = match request.action {
|
||||
SqliteAction::Open => {
|
||||
// handled in check_caps
|
||||
(serde_json::to_vec(&SqliteResponse::Ok).unwrap(), None)
|
||||
@ -182,7 +182,7 @@ async fn handle_request(
|
||||
return Err(SqliteError::NotAReadKeyword.into());
|
||||
}
|
||||
|
||||
let parameters = get_json_params(payload)?;
|
||||
let parameters = get_json_params(blob)?;
|
||||
|
||||
let mut statement = db.prepare(&query)?;
|
||||
let column_names: Vec<String> = statement
|
||||
@ -238,7 +238,7 @@ async fn handle_request(
|
||||
return Err(SqliteError::NotAWriteKeyword.into());
|
||||
}
|
||||
|
||||
let parameters = get_json_params(payload)?;
|
||||
let parameters = get_json_params(blob)?;
|
||||
|
||||
match tx_id {
|
||||
Some(tx_id) => {
|
||||
@ -319,13 +319,13 @@ async fn handle_request(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc,
|
||||
body,
|
||||
metadata,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: bytes.map(|bytes| Payload {
|
||||
lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
|
||||
mime: Some("application/octet-stream".into()),
|
||||
bytes,
|
||||
}),
|
||||
@ -338,7 +338,7 @@ async fn handle_request(
|
||||
verbosity: 2,
|
||||
content: format!(
|
||||
"sqlite: not sending response: {:?}",
|
||||
serde_json::from_slice::<SqliteResponse>(&ipc)
|
||||
serde_json::from_slice::<SqliteResponse>(&body)
|
||||
),
|
||||
})
|
||||
.await
|
||||
@ -539,10 +539,10 @@ fn json_to_sqlite(value: &serde_json::Value) -> Result<SqlValue, SqliteError> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_json_params(payload: Option<Payload>) -> Result<Vec<SqlValue>, SqliteError> {
|
||||
match payload {
|
||||
fn get_json_params(blob: Option<LazyLoadBlob>) -> Result<Vec<SqlValue>, SqliteError> {
|
||||
match blob {
|
||||
None => Ok(vec![]),
|
||||
Some(payload) => match serde_json::from_slice::<serde_json::Value>(&payload.bytes) {
|
||||
Some(blob) => match serde_json::from_slice::<serde_json::Value>(&blob.bytes) {
|
||||
Ok(serde_json::Value::Array(vec)) => vec
|
||||
.iter()
|
||||
.map(|value| json_to_sqlite(value))
|
||||
@ -567,13 +567,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: SqliteError)
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&SqliteResponse::Err { error: error }).unwrap(),
|
||||
body: serde_json::to_vec(&SqliteResponse::Err { error: error }).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}
|
||||
}
|
||||
impl ToSql for SqlValue {
|
||||
|
48
src/state.rs
48
src/state.rs
@ -141,12 +141,12 @@ async fn handle_request(
|
||||
source,
|
||||
rsvp,
|
||||
message,
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
..
|
||||
} = kernel_message;
|
||||
let Message::Request(Request {
|
||||
expects_response,
|
||||
ipc,
|
||||
body,
|
||||
metadata, // for kernel
|
||||
..
|
||||
}) = message
|
||||
@ -156,7 +156,7 @@ async fn handle_request(
|
||||
});
|
||||
};
|
||||
|
||||
let action: StateAction = match serde_json::from_slice(&ipc) {
|
||||
let action: StateAction = match serde_json::from_slice(&body) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
return Err(StateError::BadJson {
|
||||
@ -165,17 +165,17 @@ async fn handle_request(
|
||||
}
|
||||
};
|
||||
|
||||
let (ipc, bytes) = match action {
|
||||
let (body, bytes) = match action {
|
||||
StateAction::SetState(process_id) => {
|
||||
let key = process_to_vec(process_id);
|
||||
|
||||
let Some(ref payload) = payload else {
|
||||
let Some(ref blob) = blob else {
|
||||
return Err(StateError::BadBytes {
|
||||
action: "SetState".into(),
|
||||
});
|
||||
};
|
||||
|
||||
db.put(key, &payload.bytes)
|
||||
db.put(key, &blob.bytes)
|
||||
.map_err(|e| StateError::RocksDBError {
|
||||
action: "SetState".into(),
|
||||
error: e.to_string(),
|
||||
@ -259,13 +259,13 @@ async fn handle_request(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc,
|
||||
body,
|
||||
metadata,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: bytes.map(|bytes| Payload {
|
||||
lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
|
||||
mime: Some("application/octet-stream".into()),
|
||||
bytes,
|
||||
}),
|
||||
@ -299,7 +299,7 @@ async fn bootstrap(
|
||||
let k_cap = Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str("kernel:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("kernel"), "sys", "nectar"),
|
||||
},
|
||||
params: "\"messaging\"".into(),
|
||||
};
|
||||
@ -308,7 +308,7 @@ async fn bootstrap(
|
||||
let n_cap = Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str("net:sys:nectar").unwrap(),
|
||||
process: ProcessId::new(Some("net"), "sys", "nectar"),
|
||||
},
|
||||
params: "\"messaging\"".into(),
|
||||
};
|
||||
@ -336,7 +336,7 @@ async fn bootstrap(
|
||||
// finally, save runtime modules in state map as well, somewhat fakely
|
||||
// special cases for kernel and net
|
||||
process_map
|
||||
.entry(ProcessId::from_str("kernel:sys:nectar").unwrap())
|
||||
.entry(ProcessId::new(Some("kernel"), "sys", "nectar"))
|
||||
.or_insert(PersistedProcess {
|
||||
wasm_bytes_handle: "".into(),
|
||||
wit_version: None,
|
||||
@ -345,7 +345,7 @@ async fn bootstrap(
|
||||
public: false,
|
||||
});
|
||||
process_map
|
||||
.entry(ProcessId::from_str("net:sys:nectar").unwrap())
|
||||
.entry(ProcessId::new(Some("net"), "sys", "nectar"))
|
||||
.or_insert(PersistedProcess {
|
||||
wasm_bytes_handle: "".into(),
|
||||
wit_version: None,
|
||||
@ -505,7 +505,7 @@ async fn bootstrap(
|
||||
serde_json::Value::String(process_name) => Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str(process_name).unwrap(),
|
||||
process: process_name.parse().unwrap(),
|
||||
},
|
||||
params: "\"messaging\"".into(),
|
||||
},
|
||||
@ -515,10 +515,11 @@ async fn bootstrap(
|
||||
Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str(
|
||||
process_name.as_str().unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
process: process_name
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
},
|
||||
params: params.to_string(),
|
||||
}
|
||||
@ -660,12 +661,12 @@ async fn bootstrap(
|
||||
for value in to_grant {
|
||||
match value {
|
||||
serde_json::Value::String(process_name) => {
|
||||
if let Ok(parsed_process_id) = ProcessId::from_str(process_name) {
|
||||
if let Ok(parsed_process_id) = process_name.parse::<ProcessId>() {
|
||||
if let Some(process) = process_map.get_mut(&parsed_process_id) {
|
||||
let cap = Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str(&our_process_id).unwrap(),
|
||||
process: our_process_id.parse().unwrap(),
|
||||
},
|
||||
params: "\"messaging\"".into(),
|
||||
};
|
||||
@ -678,7 +679,7 @@ async fn bootstrap(
|
||||
serde_json::Value::Object(map) => {
|
||||
if let Some(process_name) = map.get("process") {
|
||||
if let Ok(parsed_process_id) =
|
||||
ProcessId::from_str(&process_name.as_str().unwrap())
|
||||
process_name.as_str().unwrap().parse::<ProcessId>()
|
||||
{
|
||||
if let Some(params) = map.get("params") {
|
||||
if let Some(process) =
|
||||
@ -687,8 +688,7 @@ async fn bootstrap(
|
||||
let cap = Capability {
|
||||
issuer: Address {
|
||||
node: our_name.to_string(),
|
||||
process: ProcessId::from_str(&our_process_id)
|
||||
.unwrap(),
|
||||
process: our_process_id.parse().unwrap(),
|
||||
},
|
||||
params: params.to_string(),
|
||||
};
|
||||
@ -759,13 +759,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: StateError) -
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&StateResponse::Err(error)).unwrap(),
|
||||
body: serde_json::to_vec(&StateResponse::Err(error)).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,11 +602,11 @@ pub async fn terminal(
|
||||
message: Message::Request(Request {
|
||||
inherit: false,
|
||||
expects_response: None,
|
||||
ipc: command.into_bytes(),
|
||||
body: command.into_bytes(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
}),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}
|
||||
).await.expect("terminal: couldn't execute command!");
|
||||
},
|
||||
|
@ -39,7 +39,7 @@ pub async fn timer_service(
|
||||
// we only handle Requests which contain a little-endian u64 as IPC,
|
||||
// except for a special "debug" message, which prints the current state
|
||||
let Message::Request(req) = km.message else { continue };
|
||||
if req.ipc == "debug".as_bytes() {
|
||||
if req.body == "debug".as_bytes() {
|
||||
let _ = print_tx.send(Printout {
|
||||
verbosity: 0,
|
||||
content: format!("timer service active timers ({}):", timer_map.timers.len()),
|
||||
@ -52,7 +52,7 @@ pub async fn timer_service(
|
||||
}
|
||||
continue
|
||||
}
|
||||
let Ok(bytes): Result<[u8; 8], _> = req.ipc.try_into() else { continue };
|
||||
let Ok(bytes): Result<[u8; 8], _> = req.body.try_into() else { continue };
|
||||
let timer_millis = u64::from_le_bytes(bytes);
|
||||
// if the timer is set to pop in 0 millis, we immediately respond
|
||||
// otherwise, store in our persisted map, and spawn a task that
|
||||
@ -125,13 +125,13 @@ async fn send_response(our_node: &str, id: u64, target: Address, send_to_loop: &
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: vec![],
|
||||
body: vec![],
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
193
src/types.rs
193
src/types.rs
@ -54,7 +54,7 @@ impl<'a> Deserialize<'a> for ProcessId {
|
||||
D: serde::de::Deserializer<'a>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
ProcessId::from_str(&s).map_err(serde::de::Error::custom)
|
||||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,24 @@ impl PackageId {
|
||||
publisher_node: publisher_node.into(),
|
||||
}
|
||||
}
|
||||
pub fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
|
||||
pub fn _package(&self) -> &str {
|
||||
&self.package_name
|
||||
}
|
||||
pub fn _publisher(&self) -> &str {
|
||||
&self.publisher_node
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for PackageId {
|
||||
type Err = ProcessIdParseError;
|
||||
/// Attempt to parse a `PackageId` from a string. The string must
|
||||
/// contain exactly two segments, where segments are strings separated
|
||||
/// by a colon `:`. The segments cannot themselves contain colons.
|
||||
/// Please note that while any string without colons will parse successfully
|
||||
/// to create a `PackageId`, not all strings without colons are actually
|
||||
/// valid usernames, which the `publisher_node` field of a `PackageId` will
|
||||
/// always in practice be.
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
// split string on colons into 2 segments
|
||||
let mut segments = input.split(':');
|
||||
let package_name = segments
|
||||
@ -92,12 +109,6 @@ impl PackageId {
|
||||
publisher_node,
|
||||
})
|
||||
}
|
||||
pub fn _package(&self) -> &str {
|
||||
&self.package_name
|
||||
}
|
||||
pub fn _publisher(&self) -> &str {
|
||||
&self.publisher_node
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageId {
|
||||
@ -119,30 +130,6 @@ impl ProcessId {
|
||||
publisher_node: publisher_node.into(),
|
||||
}
|
||||
}
|
||||
pub fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
|
||||
// split string on colons into 3 segments
|
||||
let mut segments = input.split(':');
|
||||
let process_name = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
let package_name = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
let publisher_node = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
if segments.next().is_some() {
|
||||
return Err(ProcessIdParseError::TooManyColons);
|
||||
}
|
||||
Ok(ProcessId {
|
||||
process_name,
|
||||
package_name,
|
||||
publisher_node,
|
||||
})
|
||||
}
|
||||
pub fn process(&self) -> &str {
|
||||
&self.process_name
|
||||
}
|
||||
@ -168,6 +155,40 @@ impl ProcessId {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for ProcessId {
|
||||
type Err = ProcessIdParseError;
|
||||
/// Attempts to parse a `ProcessId` from a string. To succeed, the string must contain
|
||||
/// exactly 3 segments, separated by colons `:`. The segments must not contain colons.
|
||||
/// Please note that while any string without colons will parse successfully
|
||||
/// to create a `ProcessId`, not all strings without colons are actually
|
||||
/// valid usernames, which the `publisher_node` field of a `ProcessId` will
|
||||
/// always in practice be.
|
||||
fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
|
||||
// split string on colons into 3 segments
|
||||
let mut segments = input.split(':');
|
||||
let process_name = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
let package_name = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
let publisher_node = segments
|
||||
.next()
|
||||
.ok_or(ProcessIdParseError::MissingField)?
|
||||
.to_string();
|
||||
if segments.next().is_some() {
|
||||
return Err(ProcessIdParseError::TooManyColons);
|
||||
}
|
||||
Ok(ProcessId {
|
||||
process_name,
|
||||
package_name,
|
||||
publisher_node,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(&str, &str, &str)> for ProcessId {
|
||||
fn from(input: (&str, &str, &str)) -> Self {
|
||||
ProcessId::new(Some(input.0), input.1, input.2)
|
||||
@ -248,7 +269,33 @@ impl Address {
|
||||
process: process.into(),
|
||||
}
|
||||
}
|
||||
pub fn from_str(input: &str) -> Result<Self, AddressParseError> {
|
||||
pub fn en_wit(&self) -> wit::Address {
|
||||
wit::Address {
|
||||
node: self.node.clone(),
|
||||
process: self.process.en_wit(),
|
||||
}
|
||||
}
|
||||
pub fn de_wit(wit: wit::Address) -> Address {
|
||||
Address {
|
||||
node: wit.node,
|
||||
process: ProcessId {
|
||||
process_name: wit.process.process_name,
|
||||
package_name: wit.process.package_name,
|
||||
publisher_node: wit.process.publisher_node,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Address {
|
||||
type Err = AddressParseError;
|
||||
/// Attempt to parse an `Address` from a string. The formatting structure for
|
||||
/// an Address is `node@process_name:package_name:publisher_node`.
|
||||
///
|
||||
/// TODO: clarify if `@` can be present in process name / package name / publisher name
|
||||
///
|
||||
/// TODO: ensure `:` cannot sneak into first segment
|
||||
fn from_str(input: &str) -> Result<Self, AddressParseError> {
|
||||
// split string on colons into 4 segments,
|
||||
// first one with @, next 3 with :
|
||||
let mut name_rest = input.split('@');
|
||||
@ -284,22 +331,6 @@ impl Address {
|
||||
},
|
||||
})
|
||||
}
|
||||
pub fn en_wit(&self) -> wit::Address {
|
||||
wit::Address {
|
||||
node: self.node.clone(),
|
||||
process: self.process.en_wit(),
|
||||
}
|
||||
}
|
||||
pub fn de_wit(wit: wit::Address) -> Address {
|
||||
Address {
|
||||
node: wit.node,
|
||||
process: ProcessId {
|
||||
process_name: wit.process.process_name,
|
||||
package_name: wit.process.package_name,
|
||||
publisher_node: wit.process.publisher_node,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Address {
|
||||
@ -317,7 +348,7 @@ impl<'a> Deserialize<'a> for Address {
|
||||
D: serde::de::Deserializer<'a>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Address::from_str(&s).map_err(serde::de::Error::custom)
|
||||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +406,7 @@ impl std::error::Error for AddressParseError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Payload {
|
||||
pub struct LazyLoadBlob {
|
||||
pub mime: Option<String>, // MIME type
|
||||
pub bytes: Vec<u8>,
|
||||
}
|
||||
@ -384,7 +415,7 @@ pub struct Payload {
|
||||
pub struct Request {
|
||||
pub inherit: bool,
|
||||
pub expects_response: Option<u64>, // number of seconds until timeout
|
||||
pub ipc: Vec<u8>,
|
||||
pub body: Vec<u8>,
|
||||
pub metadata: Option<String>, // JSON-string
|
||||
pub capabilities: Vec<(Capability, Vec<u8>)>,
|
||||
}
|
||||
@ -392,7 +423,7 @@ pub struct Request {
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Response {
|
||||
pub inherit: bool,
|
||||
pub ipc: Vec<u8>,
|
||||
pub body: Vec<u8>,
|
||||
pub metadata: Option<String>, // JSON-string
|
||||
pub capabilities: Vec<(Capability, Vec<u8>)>,
|
||||
}
|
||||
@ -424,7 +455,7 @@ pub struct SendError {
|
||||
pub kind: SendErrorKind,
|
||||
pub target: Address,
|
||||
pub message: Message,
|
||||
pub payload: Option<Payload>,
|
||||
pub lazy_load_blob: Option<LazyLoadBlob>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -437,7 +468,7 @@ pub enum SendErrorKind {
|
||||
pub enum OnExit {
|
||||
None,
|
||||
Restart,
|
||||
Requests(Vec<(Address, Request, Option<Payload>)>),
|
||||
Requests(Vec<(Address, Request, Option<LazyLoadBlob>)>),
|
||||
}
|
||||
|
||||
impl OnExit {
|
||||
@ -455,11 +486,11 @@ impl OnExit {
|
||||
OnExit::Restart => wit::OnExit::Restart,
|
||||
OnExit::Requests(reqs) => wit::OnExit::Requests(
|
||||
reqs.iter()
|
||||
.map(|(address, request, payload)| {
|
||||
.map(|(address, request, blob)| {
|
||||
(
|
||||
address.en_wit(),
|
||||
en_wit_request(request.clone()),
|
||||
en_wit_payload(payload.clone()),
|
||||
en_wit_blob(blob.clone()),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
@ -473,11 +504,11 @@ impl OnExit {
|
||||
wit::OnExit::Restart => OnExit::Restart,
|
||||
wit::OnExit::Requests(reqs) => OnExit::Requests(
|
||||
reqs.into_iter()
|
||||
.map(|(address, request, payload)| {
|
||||
.map(|(address, request, blob)| {
|
||||
(
|
||||
Address::de_wit(address),
|
||||
de_wit_request(request),
|
||||
de_wit_payload(payload),
|
||||
de_wit_blob(blob),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
@ -491,12 +522,12 @@ impl std::fmt::Display for Message {
|
||||
match self {
|
||||
Message::Request(request) => write!(
|
||||
f,
|
||||
"Request(\n inherit: {},\n expects_response: {:?},\n ipc: {},\n metadata: {}\n capabilities: {}\n )",
|
||||
"Request(\n inherit: {},\n expects_response: {:?},\n body: {},\n metadata: {}\n capabilities: {}\n )",
|
||||
request.inherit,
|
||||
request.expects_response,
|
||||
match serde_json::from_slice::<serde_json::Value>(&request.ipc) {
|
||||
match serde_json::from_slice::<serde_json::Value>(&request.body) {
|
||||
Ok(json) => format!("{}", json),
|
||||
Err(_) => format!("{:?}", request.ipc),
|
||||
Err(_) => format!("{:?}", request.body),
|
||||
},
|
||||
&request.metadata.as_ref().unwrap_or(&"None".into()),
|
||||
{
|
||||
@ -514,11 +545,11 @@ impl std::fmt::Display for Message {
|
||||
),
|
||||
Message::Response((response, context)) => write!(
|
||||
f,
|
||||
"Response(\n inherit: {},\n ipc: {},\n metadata: {},\n context: {},\n capabilities: {}\n )",
|
||||
"Response(\n inherit: {},\n body: {},\n metadata: {},\n context: {},\n capabilities: {}\n )",
|
||||
response.inherit,
|
||||
match serde_json::from_slice::<serde_json::Value>(&response.ipc) {
|
||||
match serde_json::from_slice::<serde_json::Value>(&response.body) {
|
||||
Ok(json) => format!("{}", json),
|
||||
Err(_) => format!("{:?}", response.ipc),
|
||||
Err(_) => format!("{:?}", response.body),
|
||||
},
|
||||
&response.metadata.as_ref().unwrap_or(&"None".into()),
|
||||
if context.is_none() {
|
||||
@ -554,7 +585,7 @@ pub fn de_wit_request(wit: wit::Request) -> Request {
|
||||
Request {
|
||||
inherit: wit.inherit,
|
||||
expects_response: wit.expects_response,
|
||||
ipc: wit.ipc,
|
||||
body: wit.body,
|
||||
metadata: wit.metadata,
|
||||
capabilities: wit
|
||||
.capabilities
|
||||
@ -568,7 +599,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
|
||||
wit::Request {
|
||||
inherit: request.inherit,
|
||||
expects_response: request.expects_response,
|
||||
ipc: request.ipc,
|
||||
body: request.body,
|
||||
metadata: request.metadata,
|
||||
capabilities: request
|
||||
.capabilities
|
||||
@ -581,7 +612,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
|
||||
pub fn de_wit_response(wit: wit::Response) -> Response {
|
||||
Response {
|
||||
inherit: wit.inherit,
|
||||
ipc: wit.ipc,
|
||||
body: wit.body,
|
||||
metadata: wit.metadata,
|
||||
capabilities: wit
|
||||
.capabilities
|
||||
@ -594,7 +625,7 @@ pub fn de_wit_response(wit: wit::Response) -> Response {
|
||||
pub fn en_wit_response(response: Response) -> wit::Response {
|
||||
wit::Response {
|
||||
inherit: response.inherit,
|
||||
ipc: response.ipc,
|
||||
body: response.body,
|
||||
metadata: response.metadata,
|
||||
capabilities: response
|
||||
.capabilities
|
||||
@ -604,20 +635,20 @@ pub fn en_wit_response(response: Response) -> wit::Response {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn de_wit_payload(wit: Option<wit::Payload>) -> Option<Payload> {
|
||||
pub fn de_wit_blob(wit: Option<wit::LazyLoadBlob>) -> Option<LazyLoadBlob> {
|
||||
match wit {
|
||||
None => None,
|
||||
Some(wit) => Some(Payload {
|
||||
Some(wit) => Some(LazyLoadBlob {
|
||||
mime: wit.mime,
|
||||
bytes: wit.bytes,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn en_wit_payload(load: Option<Payload>) -> Option<wit::Payload> {
|
||||
pub fn en_wit_blob(load: Option<LazyLoadBlob>) -> Option<wit::LazyLoadBlob> {
|
||||
match load {
|
||||
None => None,
|
||||
Some(load) => Some(wit::Payload {
|
||||
Some(load) => Some(wit::LazyLoadBlob {
|
||||
mime: load.mime,
|
||||
bytes: load.bytes,
|
||||
}),
|
||||
@ -661,7 +692,7 @@ pub fn en_wit_send_error(error: SendError) -> wit::SendError {
|
||||
wit::SendError {
|
||||
kind: en_wit_send_error_kind(error.kind),
|
||||
message: en_wit_message(error.message),
|
||||
payload: en_wit_payload(error.payload),
|
||||
lazy_load_blob: en_wit_blob(error.lazy_load_blob),
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,14 +829,14 @@ pub struct KernelMessage {
|
||||
pub target: Address,
|
||||
pub rsvp: Rsvp,
|
||||
pub message: Message,
|
||||
pub payload: Option<Payload>,
|
||||
pub lazy_load_blob: Option<LazyLoadBlob>,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for KernelMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{{\n id: {},\n source: {},\n target: {},\n rsvp: {},\n message: {},\n payload: {},\n}}",
|
||||
"{{\n id: {},\n source: {},\n target: {},\n rsvp: {},\n message: {},\n blob: {},\n}}",
|
||||
self.id,
|
||||
self.source,
|
||||
self.target,
|
||||
@ -814,7 +845,7 @@ impl std::fmt::Display for KernelMessage {
|
||||
None => "None".to_string()
|
||||
},
|
||||
self.message,
|
||||
self.payload.is_some(),
|
||||
self.lazy_load_blob.is_some(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1002,11 +1033,11 @@ pub enum StateError {
|
||||
RocksDBError { action: String, error: String },
|
||||
#[error("kernel_state: startup error")]
|
||||
StartupError { action: String },
|
||||
#[error("kernel_state: bytes payload required for {action}")]
|
||||
#[error("kernel_state: bytes blob required for {action}")]
|
||||
BadBytes { action: String },
|
||||
#[error("kernel_state: bad request error: {error}")]
|
||||
BadRequest { error: String },
|
||||
#[error("kernel_state: Bad JSON payload: {error}")]
|
||||
#[error("kernel_state: Bad JSON blob: {error}")]
|
||||
BadJson { error: String },
|
||||
#[error("kernel_state: state not found for ProcessId {process_id}")]
|
||||
NotFound { process_id: ProcessId },
|
||||
@ -1109,7 +1140,7 @@ pub enum VfsResponse {
|
||||
pub enum VfsError {
|
||||
#[error("vfs: No capability for action {action} at path {path}")]
|
||||
NoCap { action: String, path: String },
|
||||
#[error("vfs: Bytes payload required for {action} at path {path}")]
|
||||
#[error("vfs: Bytes blob required for {action} at path {path}")]
|
||||
BadBytes { action: String, path: String },
|
||||
#[error("vfs: bad request error: {error}")]
|
||||
BadRequest { error: String },
|
||||
@ -1119,7 +1150,7 @@ pub enum VfsError {
|
||||
IOError { error: String, path: String },
|
||||
#[error("vfs: kernel capability channel error: {error}")]
|
||||
CapChannelFail { error: String },
|
||||
#[error("vfs: Bad JSON payload: {error}")]
|
||||
#[error("vfs: Bad JSON blob: {error}")]
|
||||
BadJson { error: String },
|
||||
#[error("vfs: File not found at path {path}")]
|
||||
NotFound { path: String },
|
||||
|
50
src/vfs.rs
50
src/vfs.rs
@ -97,11 +97,11 @@ async fn handle_request(
|
||||
id,
|
||||
source,
|
||||
message,
|
||||
payload,
|
||||
lazy_load_blob: blob,
|
||||
..
|
||||
} = km.clone();
|
||||
let Message::Request(Request {
|
||||
ipc,
|
||||
body,
|
||||
expects_response,
|
||||
metadata,
|
||||
..
|
||||
@ -112,7 +112,7 @@ async fn handle_request(
|
||||
});
|
||||
};
|
||||
|
||||
let request: VfsRequest = match serde_json::from_slice(&ipc) {
|
||||
let request: VfsRequest = match serde_json::from_slice(&body) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
println!("vfs: got invalid Request: {}", e);
|
||||
@ -142,7 +142,7 @@ async fn handle_request(
|
||||
}
|
||||
// real safe path that the vfs will use
|
||||
let path = PathBuf::from(format!("{}{}/{}", vfs_path, drive, rest));
|
||||
let (ipc, bytes) = match request.action {
|
||||
let (body, bytes) = match request.action {
|
||||
VfsAction::CreateDrive => {
|
||||
// handled in check_caps.
|
||||
(serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
|
||||
@ -177,38 +177,38 @@ async fn handle_request(
|
||||
}
|
||||
VfsAction::WriteAt => {
|
||||
// doesn't create a file, writes at exact cursor.
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload needs to exist for WriteAll".into(),
|
||||
error: "blob needs to exist for WriteAll".into(),
|
||||
});
|
||||
};
|
||||
let file = open_file(open_files.clone(), path, false, false).await?;
|
||||
let mut file = file.lock().await;
|
||||
file.write_all(&payload.bytes).await?;
|
||||
file.write_all(&blob.bytes).await?;
|
||||
(serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
|
||||
}
|
||||
VfsAction::Write => {
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload needs to exist for Write".into(),
|
||||
error: "blob needs to exist for Write".into(),
|
||||
});
|
||||
};
|
||||
open_files.remove(&path);
|
||||
let file = open_file(open_files.clone(), path, true, true).await?;
|
||||
let mut file = file.lock().await;
|
||||
file.write_all(&payload.bytes).await?;
|
||||
file.write_all(&blob.bytes).await?;
|
||||
(serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
|
||||
}
|
||||
VfsAction::Append => {
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload needs to exist for Append".into(),
|
||||
error: "blob needs to exist for Append".into(),
|
||||
});
|
||||
};
|
||||
let file = open_file(open_files.clone(), path, false, false).await?;
|
||||
let mut file = file.lock().await;
|
||||
file.seek(SeekFrom::End(0)).await?;
|
||||
file.write_all(&payload.bytes).await?;
|
||||
file.write_all(&blob.bytes).await?;
|
||||
|
||||
(serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
|
||||
}
|
||||
@ -360,22 +360,22 @@ async fn handle_request(
|
||||
(serde_json::to_vec(&VfsResponse::Hash(hash)).unwrap(), None)
|
||||
}
|
||||
VfsAction::AddZip => {
|
||||
let Some(payload) = payload else {
|
||||
let Some(blob) = blob else {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload needs to exist for AddZip".into(),
|
||||
error: "blob needs to exist for AddZip".into(),
|
||||
});
|
||||
};
|
||||
let Some(mime) = payload.mime else {
|
||||
let Some(mime) = blob.mime else {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload mime type needs to exist for AddZip".into(),
|
||||
error: "blob mime type needs to exist for AddZip".into(),
|
||||
});
|
||||
};
|
||||
if "application/zip" != mime {
|
||||
return Err(VfsError::BadRequest {
|
||||
error: "payload mime type needs to be application/zip for AddZip".into(),
|
||||
error: "blob mime type needs to be application/zip for AddZip".into(),
|
||||
});
|
||||
}
|
||||
let file = std::io::Cursor::new(&payload.bytes);
|
||||
let file = std::io::Cursor::new(&blob.bytes);
|
||||
let mut zip = match zip::ZipArchive::new(file) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
@ -442,13 +442,13 @@ async fn handle_request(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc,
|
||||
body,
|
||||
metadata,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: bytes.map(|bytes| Payload {
|
||||
lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
|
||||
mime: Some("application/octet-stream".into()),
|
||||
bytes,
|
||||
}),
|
||||
@ -462,7 +462,7 @@ async fn handle_request(
|
||||
verbosity: 2,
|
||||
content: format!(
|
||||
"vfs: not sending response: {:?}",
|
||||
serde_json::from_slice::<VfsResponse>(&ipc)
|
||||
serde_json::from_slice::<VfsResponse>(&body)
|
||||
),
|
||||
})
|
||||
.await
|
||||
@ -485,7 +485,7 @@ async fn parse_package_and_drive(path: &str) -> Result<(PackageId, String, Strin
|
||||
});
|
||||
}
|
||||
|
||||
let package_id = match PackageId::from_str(parts[0]) {
|
||||
let package_id = match parts[0].parse::<PackageId>() {
|
||||
Ok(id) => id,
|
||||
Err(e) => {
|
||||
return Err(VfsError::ParseError {
|
||||
@ -809,13 +809,13 @@ fn make_error_message(
|
||||
message: Message::Response((
|
||||
Response {
|
||||
inherit: false,
|
||||
ipc: serde_json::to_vec(&VfsResponse::Err(error)).unwrap(),
|
||||
body: serde_json::to_vec(&VfsResponse::Err(error)).unwrap(),
|
||||
metadata: None,
|
||||
capabilities: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
payload: None,
|
||||
lazy_load_blob: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user