rename uqbar->nectar, update to nectar-wit and process_lib releases

This commit is contained in:
dr-frmr 2024-01-08 18:49:44 -03:00
parent 4c7ca4d35e
commit faf7676f8d
No known key found for this signature in database
45 changed files with 780 additions and 753 deletions

View File

@ -139,11 +139,14 @@ fn main() {
let wit_dir = pwd.join("wit"); let wit_dir = pwd.join("wit");
fs::create_dir_all(&wit_dir).unwrap(); fs::create_dir_all(&wit_dir).unwrap();
let wit_file = wit_dir.join("nectar.wit"); let wit_file = wit_dir.join("nectar.wit");
//if !wit_file.exists() { // TODO: cache in better way if !wit_file.exists() {
let mut wit_file = std::fs::File::create(&wit_file).unwrap(); // TODO: cache in better way
let nectar_wit_url = "https://raw.githubusercontent.com/uqbar-dao/uqwit/master/nectar.wit"; let mut wit_file = std::fs::File::create(&wit_file).unwrap();
let mut response = reqwest::blocking::get(nectar_wit_url).unwrap(); let nectar_wit_url =
io::copy(&mut response, &mut wit_file).unwrap(); "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 // Create target.wasm (compiled .wit) & world
run_command(Command::new("wasm-tools").args([ run_command(Command::new("wasm-tools").args([

View File

@ -14,11 +14,11 @@ version = "0.2.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"nectar_process_lib",
"rand", "rand",
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -222,6 +222,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -445,23 +462,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -15,7 +15,7 @@ rand = "0.8"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
sha2 = "0.10.8" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -1,6 +1,6 @@
use nectar_process_lib::kernel_types as kt; use nectar_process_lib::kernel_types as kt;
use nectar_process_lib::println;
use nectar_process_lib::*; use nectar_process_lib::*;
use nectar_process_lib::{call_init, println};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use sha2::Digest; use sha2::Digest;
@ -73,7 +73,7 @@ struct PackageListing {
/// on different nodes, take this form. Will add more to enum in the future /// on different nodes, take this form. Will add more to enum in the future
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum RemoteRequest { 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, /// remote node must return RemoteResponse::DownloadApproved,
/// at which point requester can expect a FTWorkerRequest::Receive /// at which point requester can expect a FTWorkerRequest::Receive
Download(PackageId), Download(PackageId),
@ -88,22 +88,22 @@ pub enum RemoteResponse {
/// Local requests take this form. /// Local requests take this form.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum LocalRequest { 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 /// if requested, will return a NewPackageResponse indicating success/failure
NewPackage { NewPackage {
package: PackageId, package: PackageId,
mirror: bool, // sets whether we will mirror this package 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 /// if requested, will return a DownloadResponse indicating success/failure
Download { Download {
package: PackageId, package: PackageId,
install_from: NodeId, 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 /// if requested, will return an InstallResponse indicating success/failure
Install(PackageId), 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, /// This will kill the processes in the **manifest** of the package,
/// but not the processes that were spawned by those processes! Take /// but not the processes that were spawned by those processes! Take
/// care to kill those processes yourself. This will also delete the drive /// 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 { Message::Request {
source, source,
expects_response, expects_response,
ipc, body,
.. ..
} => { } => {
match &serde_json::from_slice::<Req>(&ipc)? { match &serde_json::from_slice::<Req>(&body)? {
Req::LocalRequest(local_request) => { Req::LocalRequest(local_request) => {
if our.node != source.node { if our.node != source.node {
return Err(anyhow::anyhow!("local request from non-local node")); return Err(anyhow::anyhow!("local request from non-local node"));
} }
let resp = handle_local_request(&our, local_request, &mut state); let resp = handle_local_request(&our, local_request, &mut state);
if expects_response.is_some() { 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) => { Req::RemoteRequest(remote_request) => {
let resp = handle_remote_request(&our, &source, remote_request, &mut state); let resp = handle_remote_request(&our, &source, remote_request, &mut state);
if expects_response.is_some() { 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)) => { Req::FTWorkerResult(FTWorkerResult::ReceiveSuccess(name)) => {
// do with file what you'd like here // do with file what you'd like here
println!("app store: successfully received {:?}", name); println!("app store: successfully received {:?}", name);
// remove leading / and .zip from file name to get package ID // 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, Ok(package_id) => package_id,
Err(e) => { Err(e) => {
println!("app store: bad package filename: {}", name); 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 // only install the app if we actually requested it
if state.requested_packages.remove(&package_id) { 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() Request::new()
.target(our.clone()) .target(our.clone())
.inherit(true) .inherit(true)
.ipc(serde_json::to_vec(&Req::LocalRequest( .body(serde_json::to_vec(&Req::LocalRequest(
LocalRequest::NewPackage { LocalRequest::NewPackage {
package: package_id, package: package_id,
mirror: true, // can turn off auto-mirroring 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:?}"); println!("app store: got ft_worker result: {r:?}");
} }
Req::FTWorkerCommand(_) => { 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 { Resp::RemoteResponse(remote_response) => match remote_response {
RemoteResponse::DownloadApproved => { RemoteResponse::DownloadApproved => {
println!("app store: download approved"); println!("app store: download approved");
@ -306,11 +306,11 @@ fn handle_local_request(our: &Address, request: &LocalRequest, state: &mut State
match Request::new() match Request::new()
.target((install_from.as_str(), our.process.clone())) .target((install_from.as_str(), our.process.clone()))
.inherit(true) .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) .send_and_await_response(5)
{ {
Ok(Ok(Message::Response { ipc, .. })) => { Ok(Ok(Message::Response { body, .. })) => {
match serde_json::from_slice::<Resp>(&ipc) { match serde_json::from_slice::<Resp>(&body) {
Ok(Resp::RemoteResponse(RemoteResponse::DownloadApproved)) => { Ok(Resp::RemoteResponse(RemoteResponse::DownloadApproved)) => {
state.requested_packages.insert(package.clone()); state.requested_packages.insert(package.clone());
crate::set_state(&bincode::serialize(&state).unwrap()); crate::set_state(&bincode::serialize(&state).unwrap());
@ -339,15 +339,15 @@ fn handle_new_package(
mirror: bool, mirror: bool,
state: &mut State, state: &mut State,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let Some(mut payload) = get_payload() else { let Some(mut blob) = get_blob() else {
return Err(anyhow::anyhow!("no payload")); return Err(anyhow::anyhow!("no blob"));
}; };
let drive = format!("/{}/pkg", package); let drive = format!("/{}/pkg", package);
// create a new drive for this package in VFS // create a new drive for this package in VFS
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: drive.clone(), path: drive.clone(),
action: vfs::VfsAction::CreateDrive, action: vfs::VfsAction::CreateDrive,
})?) })?)
@ -355,21 +355,21 @@ fn handle_new_package(
// produce the version hash for this new package // produce the version hash for this new package
let mut hasher = sha2::Sha256::new(); let mut hasher = sha2::Sha256::new();
hasher.update(&payload.bytes); hasher.update(&blob.bytes);
let version_hash = format!("{:x}", hasher.finalize()); let version_hash = format!("{:x}", hasher.finalize());
// add zip bytes // add zip bytes
payload.mime = Some("application/zip".to_string()); blob.mime = Some("application/zip".to_string());
let response = Request::new() let response = Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: drive.clone(), path: drive.clone(),
action: vfs::VfsAction::AddZip, action: vfs::VfsAction::AddZip,
})?) })?)
.payload(payload.clone()) .blob(blob.clone())
.send_and_await_response(5)??; .send_and_await_response(5)??;
let vfs_ipc = serde_json::from_slice::<serde_json::Value>(response.ipc())?; let vfs_body = serde_json::from_slice::<serde_json::Value>(response.body())?;
if vfs_ipc == serde_json::json!({"Err": "NoCap"}) { if vfs_body == serde_json::json!({"Err": "NoCap"}) {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"cannot add NewPackage: do not have capability to access vfs" "cannot add NewPackage: do not have capability to access vfs"
)); ));
@ -381,11 +381,11 @@ fn handle_new_package(
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.inherit(true) .inherit(true)
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: zip_path, path: zip_path,
action: vfs::VfsAction::Write, action: vfs::VfsAction::Write,
})?) })?)
.payload(payload) .blob(blob)
.send_and_await_response(5)??; .send_and_await_response(5)??;
let metadata_path = format!("{}/metadata.json", drive.clone()); 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. // such that we can mirror this package to others.
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: metadata_path, path: metadata_path,
action: vfs::VfsAction::Read, action: vfs::VfsAction::Read,
})?) })?)
.send_and_await_response(5)??; .send_and_await_response(5)??;
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return Err(anyhow::anyhow!("no metadata found!")); 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 metadata = serde_json::from_str::<kt::PackageMetadata>(&metadata)?;
let listing_data = PackageListing { let listing_data = PackageListing {
@ -428,15 +428,15 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
let drive_path = format!("/{}/pkg", package); let drive_path = format!("/{}/pkg", package);
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .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), path: format!("{}/manifest.json", drive_path),
action: vfs::VfsAction::Read, action: vfs::VfsAction::Read,
})?) })?)
.send_and_await_response(5)??; .send_and_await_response(5)??;
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return Err(anyhow::anyhow!("no payload")); 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)?; let manifest = serde_json::from_str::<Vec<kt::PackageManifestEntry>>(&manifest)?;
// always grant read/write to their drive, which we created for them // always grant read/write to their drive, which we created for them
let Some(read_cap) = get_capability( 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(read_cap.clone()));
initial_capabilities.insert(kt::de_wit_capability(write_cap.clone())); initial_capabilities.insert(kt::de_wit_capability(write_cap.clone()));
let process_id = format!("{}:{}", entry.process_name, package); 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!")); return Err(anyhow::anyhow!("app store: invalid process id!"));
}; };
// kill process if it already exists // kill process if it already exists
Request::new() Request::new()
.target(("our", "kernel", "sys", "nectar")) .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(), parsed_new_process_id.clone(),
))?) ))?)
.send()?; .send()?;
let _bytes_response = Request::new() let _bytes_response = Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: wasm_path.clone(), path: wasm_path.clone(),
action: vfs::VfsAction::Read, action: vfs::VfsAction::Read,
})?) })?)
@ -504,7 +504,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
let mut capability = None; let mut capability = None;
match value { match value {
serde_json::Value::String(process_name) => { 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( capability = get_capability(
&Address { &Address {
node: our.node.clone(), node: our.node.clone(),
@ -516,8 +516,10 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
} }
serde_json::Value::Object(map) => { serde_json::Value::Object(map) => {
if let Some(process_name) = map.get("process") { if let Some(process_name) = map.get("process") {
if let Ok(parsed_process_id) = if let Ok(parsed_process_id) = process_name
ProcessId::from_str(&process_name.to_string()) .as_str()
.unwrap_or_default()
.parse::<ProcessId>()
{ {
if let Some(params) = map.get("params") { if let Some(params) = map.get("params") {
if params.to_string() == "\"root\"" { if params.to_string() == "\"root\"" {
@ -555,7 +557,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
} }
Request::new() Request::new()
.target(("our", "kernel", "sys", "nectar")) .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(), id: parsed_new_process_id.clone(),
wasm_bytes_handle: wasm_path, wasm_bytes_handle: wasm_path,
wit_version: None, wit_version: None,
@ -569,10 +571,10 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
for value in to_grant { for value in to_grant {
match value { match value {
serde_json::Value::String(process_name) => { 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() let _ = Request::new()
.target(("our", "kernel", "sys", "nectar")) .target(("our", "kernel", "sys", "nectar"))
.ipc( .body(
serde_json::to_vec(&kt::KernelCommand::GrantCapabilities { serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
target: parsed_process_id, target: parsed_process_id,
capabilities: vec![kt::Capability { capabilities: vec![kt::Capability {
@ -590,13 +592,15 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
} }
serde_json::Value::Object(map) => { serde_json::Value::Object(map) => {
if let Some(process_name) = map.get("process") { if let Some(process_name) = map.get("process") {
if let Ok(parsed_process_id) = if let Ok(parsed_process_id) = process_name
ProcessId::from_str(&process_name.to_string()) .as_str()
.unwrap_or_default()
.parse::<ProcessId>()
{ {
if let Some(params) = map.get("params") { if let Some(params) = map.get("params") {
let _ = Request::new() let _ = Request::new()
.target(("our", "kernel", "sys", "nectar")) .target(("our", "kernel", "sys", "nectar"))
.ipc( .body(
serde_json::to_vec( serde_json::to_vec(
&kt::KernelCommand::GrantCapabilities { &kt::KernelCommand::GrantCapabilities {
target: parsed_process_id, target: parsed_process_id,
@ -624,7 +628,7 @@ fn handle_install(our: &Address, package: &PackageId) -> anyhow::Result<()> {
} }
Request::new() Request::new()
.target(("our", "kernel", "sys", "nectar")) .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, parsed_new_process_id,
))?) ))?)
.send_and_await_response(5)??; .send_and_await_response(5)??;
@ -636,25 +640,25 @@ fn handle_uninstall(package: &PackageId) -> anyhow::Result<()> {
let drive_path = format!("/{}/pkg", package); let drive_path = format!("/{}/pkg", package);
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .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), path: format!("{}/manifest.json", drive_path),
action: vfs::VfsAction::Read, action: vfs::VfsAction::Read,
})?) })?)
.send_and_await_response(5)??; .send_and_await_response(5)??;
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return Err(anyhow::anyhow!("no payload")); 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)?; let manifest = serde_json::from_str::<Vec<kt::PackageManifestEntry>>(&manifest)?;
// reading from the package manifest, kill every process // reading from the package manifest, kill every process
for entry in &manifest { for entry in &manifest {
let process_id = format!("{}:{}", entry.process_name, package); 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; continue;
}; };
Request::new() Request::new()
.target(("our", "kernel", "sys", "nectar")) .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, parsed_new_process_id,
))?) ))?)
.send()?; .send()?;
@ -662,7 +666,7 @@ fn handle_uninstall(package: &PackageId) -> anyhow::Result<()> {
// then, delete the drive // then, delete the drive
Request::new() Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: drive_path, path: drive_path,
action: vfs::VfsAction::RemoveDirAll, action: vfs::VfsAction::RemoveDirAll,
})?) })?)
@ -684,11 +688,11 @@ fn handle_remote_request(
if !package_state.mirroring { if !package_state.mirroring {
return Resp::RemoteResponse(RemoteResponse::DownloadDenied); 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 file_path = format!("/{}/pkg/{}.zip", package, package);
let Ok(Ok(_)) = Request::new() let Ok(Ok(_)) = Request::new()
.target(("our", "vfs", "sys", "nectar")) .target(("our", "vfs", "sys", "nectar"))
.ipc( .body(
serde_json::to_vec(&vfs::VfsRequest { serde_json::to_vec(&vfs::VfsRequest {
path: file_path, path: file_path,
action: vfs::VfsAction::Read, action: vfs::VfsAction::Read,
@ -699,7 +703,7 @@ fn handle_remote_request(
else { else {
return Resp::RemoteResponse(RemoteResponse::DownloadDenied); 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); let file_name = format!("/{}.zip", package);
match spawn_transfer(&our, &file_name, None, 60, &source) { match spawn_transfer(&our, &file_name, None, 60, &source) {
Ok(()) => Resp::RemoteResponse(RemoteResponse::DownloadApproved), Ok(()) => Resp::RemoteResponse(RemoteResponse::DownloadApproved),

View File

@ -62,10 +62,10 @@ version = "0.2.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"nectar_process_lib",
"rand", "rand",
"serde", "serde",
"serde_json", "serde_json",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -173,6 +173,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -379,23 +396,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -16,7 +16,7 @@ bincode = "1.3.3"
rand = "0.8" rand = "0.8"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -13,7 +13,7 @@ pub struct FileTransferContext {
/// in order to prompt them to spawn a worker /// in order to prompt them to spawn a worker
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum FTWorkerCommand { pub enum FTWorkerCommand {
/// make sure to attach file itself as payload /// make sure to attach file itself as blob
Send { Send {
target: Address, target: Address,
file_name: String, file_name: String,
@ -32,7 +32,7 @@ pub enum FTWorkerCommand {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum FTWorkerResult { pub enum FTWorkerResult {
SendSuccess, SendSuccess,
/// string is name of file. bytes in payload /// string is name of file. bytes in blob
ReceiveSuccess(String), ReceiveSuccess(String),
Err(TransferError), Err(TransferError),
} }
@ -49,7 +49,7 @@ pub enum TransferError {
/// A helper function to spawn a worker and initialize a file transfer. /// A helper function to spawn a worker and initialize a file transfer.
/// The outcome will be sent as an [`FTWorkerResult`] to the caller process. /// 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)] #[allow(dead_code)]
pub fn spawn_transfer( pub fn spawn_transfer(
our: &Address, our: &Address,
@ -71,15 +71,15 @@ pub fn spawn_transfer(
return Err(anyhow::anyhow!("failed to spawn ft_worker!")); return Err(anyhow::anyhow!("failed to spawn ft_worker!"));
}; };
// tell the worker what to do // tell the worker what to do
let payload_or_inherit = match file_bytes { let blob_or_inherit = match file_bytes {
Some(bytes) => Some(Payload { mime: None, bytes }), Some(bytes) => Some(LazyLoadBlob { mime: None, bytes }),
None => None, None => None,
}; };
let mut req = Request::new() let mut req = Request::new()
.target((our.node.as_ref(), worker_process_id)) .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 .expects_response(timeout + 1) // don't call with 2^64 lol
.ipc( .body(
serde_json::to_vec(&FTWorkerCommand::Send { serde_json::to_vec(&FTWorkerCommand::Send {
target: to_addr.clone(), target: to_addr.clone(),
file_name: file_name.into(), file_name: file_name.into(),
@ -90,7 +90,7 @@ pub fn spawn_transfer(
.context( .context(
serde_json::to_vec(&FileTransferContext { serde_json::to_vec(&FileTransferContext {
file_name: file_name.into(), 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), Some(p) => Some(p.bytes.len() as u64),
None => None, // TODO None => None, // TODO
}, },
@ -99,8 +99,8 @@ pub fn spawn_transfer(
.unwrap(), .unwrap(),
); );
if let Some(payload) = payload_or_inherit { if let Some(blob) = blob_or_inherit {
req = req.payload(payload); req = req.blob(blob);
} }
req.send() 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 /// and let it do the rest. The outcome will be sent as an [`FTWorkerResult`] inside
/// a Response to the caller. /// a Response to the caller.
#[allow(dead_code)] #[allow(dead_code)]
pub fn spawn_receive_transfer(our: &Address, ipc: &[u8]) -> anyhow::Result<()> { pub fn spawn_receive_transfer(our: &Address, body: &[u8]) -> anyhow::Result<()> {
let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_slice(ipc) else { let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_slice(body) else {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"spawn_receive_transfer: got malformed request" "spawn_receive_transfer: got malformed request"
)); ));
@ -130,6 +130,6 @@ pub fn spawn_receive_transfer(our: &Address, ipc: &[u8]) -> anyhow::Result<()> {
Request::new() Request::new()
.target((our.node.as_ref(), worker_process_id)) .target((our.node.as_ref(), worker_process_id))
.inherit(true) .inherit(true)
.ipc(ipc) .body(body)
.send() .send()
} }

View File

@ -25,14 +25,14 @@ call_init!(init);
fn init(our: Address) { fn init(our: Address) {
let Ok(Message::Request { let Ok(Message::Request {
source: parent_process, source: parent_process,
ipc, body,
.. ..
}) = await_message() }) = await_message()
else { else {
panic!("ft_worker: got bad init message"); 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"); .expect("ft_worker: got unparseable init message");
let Some(result) = (match command { let Some(result) = (match command {
@ -52,7 +52,7 @@ fn init(our: Address) {
}; };
Response::new() Response::new()
.ipc(serde_json::to_vec(&result).unwrap()) .body(serde_json::to_vec(&result).unwrap())
.send() .send()
.unwrap(); .unwrap();
@ -61,11 +61,11 @@ fn init(our: Address) {
fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -> FTWorkerResult { fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -> FTWorkerResult {
let transfer_id: u64 = our.process().parse().unwrap(); let transfer_id: u64 = our.process().parse().unwrap();
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
println!("ft_worker: wasn't given payload!"); println!("ft_worker: wasn't given blob!");
return FTWorkerResult::Err(TransferError::SourceFailed); 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 file_size = file_bytes.len() as u64;
let mut offset: u64 = 0; let mut offset: u64 = 0;
let chunk_size: u64 = 1048576; // 1MB, can be changed 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 // send contents in chunks and wait for
// acknowledgement. // acknowledgement.
let Ok(Ok(response)) = Request::to(target.clone()) let Ok(Ok(response)) = Request::to(target.clone())
.ipc( .body(
serde_json::to_vec(&FTWorkerCommand::Receive { serde_json::to_vec(&FTWorkerCommand::Receive {
transfer_id, transfer_id,
file_name: file_name.to_string(), 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); return FTWorkerResult::Err(TransferError::TargetOffline);
}; };
let opp_worker = response.source(); 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); return FTWorkerResult::Err(TransferError::TargetRejected);
}; };
// send file in chunks // 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 { if file_size < chunk_size {
// this is the last chunk, so we should expect a Finished response // this is the last chunk, so we should expect a Finished response
let _ = Request::to(opp_worker.clone()) let _ = Request::to(opp_worker.clone())
.ipc(vec![]) .body(vec![])
.payload(Payload { .blob(LazyLoadBlob {
mime: None, mime: None,
bytes: file_bytes[offset as usize..offset as usize + file_size as usize] bytes: file_bytes[offset as usize..offset as usize + file_size as usize]
.to_vec(), .to_vec(),
@ -110,8 +110,8 @@ fn handle_send(our: &Address, target: &Address, file_name: &str, timeout: u64) -
break; break;
} }
let _ = Request::to(opp_worker.clone()) let _ = Request::to(opp_worker.clone())
.ipc(vec![]) .body(vec![])
.payload(Payload { .blob(LazyLoadBlob {
mime: None, mime: None,
bytes: file_bytes[offset as usize..offset as usize + chunk_size as usize].to_vec(), 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; offset += chunk_size;
} }
// now wait for Finished response // 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); 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 FTWorkerResult::Err(TransferError::TargetRejected);
}; };
// return success to parent // return success to parent
@ -138,7 +138,7 @@ fn handle_receive(
) -> Option<FTWorkerResult> { ) -> Option<FTWorkerResult> {
// send Ready response to counterparty // send Ready response to counterparty
Response::new() Response::new()
.ipc(serde_json::to_vec(&FTWorkerProtocol::Ready).unwrap()) .body(serde_json::to_vec(&FTWorkerProtocol::Ready).unwrap())
.send() .send()
.unwrap(); .unwrap();
// receive a file from a worker, then send it to parent // 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 { if start_time.elapsed().as_secs() > timeout {
return Some(FTWorkerResult::Err(TransferError::SourceFailed)); return Some(FTWorkerResult::Err(TransferError::SourceFailed));
} }
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return Some(FTWorkerResult::Err(TransferError::SourceFailed)); return Some(FTWorkerResult::Err(TransferError::SourceFailed));
}; };
chunks_received += 1; chunks_received += 1;
file_bytes.extend(payload.bytes); file_bytes.extend(blob.bytes);
if chunks_received == total_chunks { if chunks_received == total_chunks {
break; break;
} }
} }
// send Finished message to sender // send Finished message to sender
Response::new() Response::new()
.ipc(serde_json::to_vec(&FTWorkerProtocol::Finished).unwrap()) .body(serde_json::to_vec(&FTWorkerProtocol::Finished).unwrap())
.send() .send()
.unwrap(); .unwrap();
// send Success message to parent // send Success message to parent
Request::to(parent_process) Request::to(parent_process)
.ipc(serde_json::to_vec(&FTWorkerResult::ReceiveSuccess(file_name.to_string())).unwrap()) .body(serde_json::to_vec(&FTWorkerResult::ReceiveSuccess(file_name.to_string())).unwrap())
.payload(Payload { .blob(LazyLoadBlob {
mime: None, mime: None,
bytes: file_bytes, bytes: file_bytes,
}) })

View File

@ -69,10 +69,10 @@ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
"bincode", "bincode",
"nectar_process_lib",
"pleco", "pleco",
"serde", "serde",
"serde_json", "serde_json",
"uqbar_process_lib",
"url", "url",
"wit-bindgen", "wit-bindgen",
] ]
@ -283,6 +283,23 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55d0c9dc43dedfd2414deb74ade67687749ef88b1d3482024d4c81d901a7a83" 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]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.16.0" version = "1.16.0"
@ -654,23 +671,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -16,7 +16,7 @@ pleco = "0.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
url = "*" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -1,7 +1,7 @@
#![feature(let_chains)] #![feature(let_chains)]
use nectar_process_lib::{ use nectar_process_lib::{
await_message, call_init, get_payload, get_typed_state, http, println, set_state, Address, await_message, call_init, get_blob, get_typed_state, http, println, set_state, Address,
Message, NodeId, Payload, Request, Response, LazyLoadBlob, Message, NodeId, Request, Response,
}; };
use pleco::Board; use pleco::Board;
use serde::{Deserialize, Serialize}; 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 { for channel in open_channels {
Request::new() Request::new()
.target((&our.node, "http_server", "sys", "nectar")) .target((&our.node, "http_server", "sys", "nectar"))
.ipc(serde_json::to_vec( .body(serde_json::to_vec(
&http::HttpServerAction::WebSocketPush { &http::HttpServerAction::WebSocketPush {
channel_id: *channel, channel_id: *channel,
message_type: http::WsMessageType::Binary, message_type: http::WsMessageType::Binary,
}, },
)?) )?)
.payload(Payload { .blob(LazyLoadBlob {
mime: Some("application/json".to_string()), mime: Some("application/json".to_string()),
bytes: serde_json::json!({ bytes: serde_json::json!({
"kind": "game_update", "kind": "game_update",
@ -160,7 +160,7 @@ fn handle_request(our: &Address, message: &Message, state: &mut ChessState) -> a
if message.source().node != our.node { if message.source().node != our.node {
// Deserialize the request IPC to our format, and throw it away if it // Deserialize the request IPC to our format, and throw it away if it
// doesn't fit. // 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")); return Err(anyhow::anyhow!("invalid chess request"));
}; };
handle_chess_request(our, &message.source().node, state, &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 } else if message.source().node == our.node
&& message.source().process == "terminal:terminal:nectar" && 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")); return Err(anyhow::anyhow!("invalid chess request"));
}; };
handle_local_request(our, state, &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" && message.source().process == "http_server:sys:nectar"
{ {
// receive HTTP requests and websocket connection messages from our server // 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) => { http::HttpServerRequest::Http(ref incoming) => {
match handle_http_request(our, state, incoming) { match handle_http_request(our, state, incoming) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
@ -258,7 +258,7 @@ fn handle_chess_request(
// Send a response to tell them we've accepted the game. // Send a response to tell them we've accepted the game.
// Remember, the other player is waiting for this. // Remember, the other player is waiting for this.
Response::new() Response::new()
.ipc(serde_json::to_vec(&ChessResponse::NewGameAccepted)?) .body(serde_json::to_vec(&ChessResponse::NewGameAccepted)?)
.send() .send()
} }
ChessRequest::Move { ref move_str, .. } => { ChessRequest::Move { ref move_str, .. } => {
@ -267,7 +267,7 @@ fn handle_chess_request(
let Some(game) = state.games.get_mut(game_id) else { let Some(game) = state.games.get_mut(game_id) else {
// If we don't have a game with them, reject the move. // If we don't have a game with them, reject the move.
return Response::new() return Response::new()
.ipc(serde_json::to_vec(&ChessResponse::MoveRejected)?) .body(serde_json::to_vec(&ChessResponse::MoveRejected)?)
.send(); .send();
}; };
// Convert the saved board to one we can manipulate. // Convert the saved board to one we can manipulate.
@ -275,7 +275,7 @@ fn handle_chess_request(
if !board.apply_uci_move(move_str) { if !board.apply_uci_move(move_str) {
// Reject invalid moves! // Reject invalid moves!
return Response::new() return Response::new()
.ipc(serde_json::to_vec(&ChessResponse::MoveRejected)?) .body(serde_json::to_vec(&ChessResponse::MoveRejected)?)
.send(); .send();
} }
game.turns += 1; game.turns += 1;
@ -288,7 +288,7 @@ fn handle_chess_request(
save_chess_state(&state); save_chess_state(&state);
// Send a response to tell them we've accepted the move. // Send a response to tell them we've accepted the move.
Response::new() Response::new()
.ipc(serde_json::to_vec(&ChessResponse::MoveAccepted)?) .body(serde_json::to_vec(&ChessResponse::MoveAccepted)?)
.send() .send()
} }
ChessRequest::Resign(_) => { ChessRequest::Resign(_) => {
@ -329,9 +329,9 @@ fn handle_local_request(
// Send the other player a NewGame request // Send the other player a NewGame request
// The request is exactly the same as what we got from terminal. // The request is exactly the same as what we got from terminal.
// We'll give them 5 seconds to respond... // 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())) .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)? .send_and_await_response(5)?
else { else {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
@ -339,7 +339,7 @@ fn handle_local_request(
)); ));
}; };
// If they accept, create a new game -- otherwise, error out. // 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!")); return Err(anyhow::anyhow!("other player rejected new game request!"));
} }
// New game with default board. // 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. // 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. // The request is exactly the same as what we got from terminal.
// We'll give them 5 seconds to respond... // 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())) .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)? .send_and_await_response(5)?
else { else {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"other player did not respond properly to our move" "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")); return Err(anyhow::anyhow!("other player rejected our move"));
} }
game.turns += 1; game.turns += 1;
@ -403,7 +403,7 @@ fn handle_local_request(
// send the other player an end game request -- no response expected // send the other player an end game request -- no response expected
Request::new() Request::new()
.target((with_who.as_ref(), our.process.clone())) .target((with_who.as_ref(), our.process.clone()))
.ipc(serde_json::to_vec(&action)?) .body(serde_json::to_vec(&action)?)
.send()?; .send()?;
game.ended = true; game.ended = true;
save_chess_state(&state); save_chess_state(&state);
@ -437,11 +437,11 @@ fn handle_http_request(
), ),
// on POST: create a new game // on POST: create a new game
"POST" => { "POST" => {
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]); return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
}; };
let payload_json = serde_json::from_slice::<serde_json::Value>(&payload.bytes)?; let blob_json = serde_json::from_slice::<serde_json::Value>(&blob.bytes)?;
let Some(game_id) = payload_json["id"].as_str() else { let Some(game_id) = blob_json["id"].as_str() else {
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]); return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
}; };
if let Some(game) = state.games.get(game_id) 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![]); return http::send_response(http::StatusCode::CONFLICT, None, vec![]);
}; };
let player_white = payload_json["white"] let player_white = blob_json["white"]
.as_str() .as_str()
.unwrap_or(our.node.as_str()) .unwrap_or(our.node.as_str())
.to_string(); .to_string();
let player_black = payload_json["black"] let player_black = blob_json["black"].as_str().unwrap_or(game_id).to_string();
.as_str()
.unwrap_or(game_id)
.to_string();
// send the other player a new game request // send the other player a new game request
let Ok(msg) = Request::new() let Ok(msg) = Request::new()
.target((game_id, our.process.clone())) .target((game_id, our.process.clone()))
.ipc(serde_json::to_vec(&ChessRequest::NewGame { .body(serde_json::to_vec(&ChessRequest::NewGame {
white: player_white.clone(), white: player_white.clone(),
black: player_black.clone(), black: player_black.clone(),
})?) })?)
@ -474,7 +471,8 @@ fn handle_http_request(
}; };
// if they accept, create a new game // if they accept, create a new game
// otherwise, should surface error to FE... // 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")); return Err(anyhow::anyhow!("other player rejected new game request"));
} }
@ -501,11 +499,11 @@ fn handle_http_request(
} }
// on PUT: make a move // on PUT: make a move
"PUT" => { "PUT" => {
let Some(payload) = get_payload() else { let Some(blob) = get_blob() else {
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]); return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
}; };
let payload_json = serde_json::from_slice::<serde_json::Value>(&payload.bytes)?; let blob_json = serde_json::from_slice::<serde_json::Value>(&blob.bytes)?;
let Some(game_id) = payload_json["id"].as_str() else { let Some(game_id) = blob_json["id"].as_str() else {
return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]); return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
}; };
let Some(game) = state.games.get_mut(game_id) else { let Some(game) = state.games.get_mut(game_id) else {
@ -518,7 +516,7 @@ fn handle_http_request(
} else if game.ended { } else if game.ended {
return http::send_response(http::StatusCode::CONFLICT, None, vec![]); 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![]); return http::send_response(http::StatusCode::BAD_REQUEST, None, vec![]);
}; };
let mut board = Board::from_fen(&game.board).unwrap(); let mut board = Board::from_fen(&game.board).unwrap();
@ -531,7 +529,7 @@ fn handle_http_request(
// if so, update the records // if so, update the records
let Ok(msg) = Request::new() let Ok(msg) = Request::new()
.target((game_id, our.process.clone())) .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(), game_id: game_id.to_string(),
move_str: move_str.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" "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")); return Err(anyhow::anyhow!("other player rejected our move"));
} }
// update the game // update the game
@ -574,7 +572,7 @@ fn handle_http_request(
// send the other player an end game request // send the other player an end game request
Request::new() Request::new()
.target((game_id.as_str(), our.process.clone())) .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()?; .send()?;
game.ended = true; game.ended = true;
let body = serde_json::to_vec(&game)?; let body = serde_json::to_vec(&game)?;

View File

@ -88,9 +88,9 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"nectar_process_lib",
"serde", "serde",
"serde_json", "serde_json",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -172,6 +172,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -378,23 +395,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -15,7 +15,7 @@ anyhow = "1.0"
bincode = "1.3.3" bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -1,7 +1,6 @@
#![feature(let_chains)] #![feature(let_chains)]
use nectar_process_lib::{ use nectar_process_lib::{
await_message, http::bind_http_static_path, http::HttpServerError, println, Address, Message, await_message, http::bind_http_static_path, http::HttpServerError, println, Address, Message,
ProcessId,
}; };
wit_bindgen::generate!({ wit_bindgen::generate!({
@ -18,7 +17,7 @@ const HOME_PAGE: &str = include_str!("home.html");
impl Guest for Component { impl Guest for Component {
fn init(our: String) { fn init(our: String) {
let our = Address::from_str(&our).unwrap(); let our: Address = our.parse().unwrap();
match main(our) { match main(our) {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
@ -65,10 +64,10 @@ fn main(our: Address) -> anyhow::Result<()> {
println!("homepage: got network error??"); println!("homepage: got network error??");
continue; continue;
}; };
if let Message::Response { source, ipc, .. } = message if let Message::Response { source, body, .. } = message
&& source.process == "http_server:sys:nectar" && 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(Ok(())) => continue,
Ok(Err(e)) => println!("homepage: got error from http_server: {e}"), Ok(Err(e)) => println!("homepage: got error from http_server: {e}"),
Err(_e) => println!("homepage: got malformed message from http_server!"), Err(_e) => println!("homepage: got malformed message from http_server!"),

View File

@ -1103,6 +1103,24 @@ dependencies = [
"unicase", "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]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.4" version = "0.4.4"
@ -1360,10 +1378,10 @@ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"hex", "hex",
"nectar_process_lib",
"rmp-serde", "rmp-serde",
"serde", "serde",
"serde_json", "serde_json",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -2089,24 +2107,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -20,7 +20,7 @@ hex = "0.4.3"
rmp-serde = "1.1.2" rmp-serde = "1.1.2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -1,10 +1,9 @@
use alloy_primitives::B256;
use alloy_rpc_types::Log; use alloy_rpc_types::Log;
use alloy_sol_types::{sol, SolEvent}; use alloy_sol_types::{sol, SolEvent};
use nectar_process_lib::eth::{EthAddress, SubscribeLogsRequest}; use nectar_process_lib::eth::{EthAddress, SubscribeLogsRequest};
use nectar_process_lib::{ use nectar_process_lib::{
await_message, get_typed_state, http, print_to_terminal, println, set_state, Address, Message, await_message, get_typed_state, http, print_to_terminal, println, set_state, Address,
Payload, Request, Response, LazyLoadBlob, Message, Request, Response,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::hash_map::{Entry, HashMap}; use std::collections::hash_map::{Entry, HashMap};
@ -84,7 +83,7 @@ sol! {
struct Component; struct Component;
impl Guest for Component { impl Guest for Component {
fn init(our: String) { fn init(our: String) {
let our = Address::from_str(&our).unwrap(); let our: Address = our.parse().unwrap();
let mut state: State = State { let mut state: State = State {
names: HashMap::new(), names: HashMap::new(),
@ -113,7 +112,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
// shove all state into net::net // shove all state into net::net
Request::new() Request::new()
.target((&our.node, "net", "sys", "nectar")) .target((&our.node, "net", "sys", "nectar"))
.try_ipc(NetActions::QnsBatchUpdate( .try_body(NetActions::QnsBatchUpdate(
state.nodes.values().cloned().collect::<Vec<_>>(), state.nodes.values().cloned().collect::<Vec<_>>(),
))? ))?
.send()?; .send()?;
@ -139,26 +138,26 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
println!("qns_indexer: got network error"); println!("qns_indexer: got network error");
continue; continue;
}; };
let Message::Request { source, ipc, .. } = message else { let Message::Request { source, body, .. } = message else {
// TODO we should store the subscription ID for eth // TODO we should store the subscription ID for eth
// incase we want to cancel/reset it // incase we want to cancel/reset it
continue; continue;
}; };
if source.process == "http_server:sys:nectar" { if source.process == "http_server:sys:nectar" {
if let Ok(ipc_json) = serde_json::from_slice::<serde_json::Value>(&ipc) { if let Ok(body_json) = serde_json::from_slice::<serde_json::Value>(&body) {
if ipc_json["path"].as_str().unwrap_or_default() == "/node/:name" { if body_json["path"].as_str().unwrap_or_default() == "/node/:name" {
if let Some(name) = ipc_json["url_params"]["name"].as_str() { if let Some(name) = body_json["url_params"]["name"].as_str() {
if let Some(node) = state.nodes.get(name) { if let Some(node) = state.nodes.get(name) {
Response::new() Response::new()
.ipc(serde_json::to_vec(&http::HttpResponse { .body(serde_json::to_vec(&http::HttpResponse {
status: 200, status: 200,
headers: HashMap::from([( headers: HashMap::from([(
"Content-Type".to_string(), "Content-Type".to_string(),
"application/json".to_string(), "application/json".to_string(),
)]), )]),
})?) })?)
.payload(Payload { .blob(LazyLoadBlob {
mime: Some("application/json".to_string()), mime: Some("application/json".to_string()),
bytes: serde_json::to_string(&node)?.as_bytes().to_vec(), 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() Response::new()
.ipc(serde_json::to_vec(&http::HttpResponse { .body(serde_json::to_vec(&http::HttpResponse {
status: 404, status: 404,
headers: HashMap::from([( headers: HashMap::from([(
"Content-Type".to_string(), "Content-Type".to_string(),
@ -180,7 +179,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
continue; 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"); println!("qns_indexer: got invalid message");
continue; continue;
}; };
@ -196,7 +195,7 @@ fn main(our: Address, mut state: State) -> anyhow::Result<()> {
Entry::Vacant(v) => v.insert(get_name(&e)), Entry::Vacant(v) => v.insert(get_name(&e)),
}; };
let mut node = state let node = state
.nodes .nodes
.entry(name.to_string()) .entry(name.to_string())
.or_insert_with(|| QnsUpdate::new(name, &node_id.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)); print_to_terminal(1, &format!("qns_indexer: sending ID to net: {:?}", node));
Request::new() Request::new()
.target((&our.node, "net", "sys", "nectar")) .target((&our.node, "net", "sys", "nectar"))
.try_ipc(NetActions::QnsUpdate(node.clone()))? .try_body(NetActions::QnsUpdate(node.clone()))?
.send()?; .send()?;
} }
} }

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -295,9 +312,9 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"nectar_process_lib",
"serde", "serde",
"serde_json", "serde_json",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -378,23 +395,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -15,7 +15,7 @@ anyhow = "1.0"
bincode = "1.3.3" bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" 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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -36,7 +36,7 @@ fn parse_command(state: &mut TerminalState, line: &str) -> anyhow::Result<()> {
}; };
Request::new() Request::new()
.target((node_id, "net", "sys", "nectar")) .target((node_id, "net", "sys", "nectar"))
.ipc(message) .body(message)
.expects_response(5) .expects_response(5)
.send()?; .send()?;
Ok(()) Ok(())
@ -48,7 +48,7 @@ fn parse_command(state: &mut TerminalState, line: &str) -> anyhow::Result<()> {
println!("current target cleared"); println!("current target cleared");
return Ok(()); return Ok(());
} }
let Ok(target) = Address::from_str(tail) else { let Ok(target) = tail.parse::<Address>() else {
return Err(anyhow!("invalid address: \"{tail}\"")); return Err(anyhow!("invalid address: \"{tail}\""));
}; };
println!("current target set to {target}"); 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 // otherwise use the current_target
"/m" | "/message" => { "/m" | "/message" => {
if let Some(target) = &state.current_target { if let Some(target) = &state.current_target {
Request::new().target(target.clone()).ipc(tail).send() Request::new().target(target.clone()).body(tail).send()
} else { } else {
let (target, ipc) = match tail.split_once(" ") { let (target, body) = match tail.split_once(" ") {
Some((a, p)) => (a, p), Some((a, p)) => (a, p),
None => return Err(anyhow!("invalid command: \"{line}\"")), 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}\"")); 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}\"")), _ => return Err(anyhow!("invalid command: \"{line}\"")),
@ -80,7 +80,7 @@ struct Component;
impl Guest for Component { impl Guest for Component {
fn init(our: String) { fn init(our: String) {
let mut state = TerminalState { let mut state = TerminalState {
our: Address::from_str(&our).unwrap(), our: our.parse::<Address>().unwrap(),
current_target: None, current_target: None,
}; };
loop { loop {
@ -92,20 +92,21 @@ impl Guest for Component {
} }
}; };
match message { 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 { if state.our.node != source.node || state.our.process != source.process {
continue; 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, Ok(()) => continue,
Err(e) => println!("terminal: {e}"), Err(e) => println!("terminal: {e}"),
} }
} }
wit::Message::Response((wit::Response { ipc, .. }, _)) => { wit::Message::Response((wit::Response { body, .. }, _)) => {
if let Ok(txt) = std::str::from_utf8(&ipc) { if let Ok(txt) = std::str::from_utf8(&body) {
println!("response from {source}: {txt}"); println!("response from {source}: {txt}");
} else { } else {
println!("response from {source}: {ipc:?}"); println!("response from {source}: {body:?}");
} }
} }
} }

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -295,10 +312,10 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"nectar_process_lib",
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -379,23 +396,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -16,7 +16,7 @@ bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
thiserror = "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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -21,7 +21,7 @@ wit_bindgen::generate!({
fn make_vfs_address(our: &wit::Address) -> anyhow::Result<Address> { fn make_vfs_address(our: &wit::Address) -> anyhow::Result<Address> {
Ok(wit::Address { Ok(wit::Address {
node: our.node.clone(), 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(_) => { wit::Message::Response(_) => {
return Err(tt::TesterError::UnexpectedResponse.into()); return Err(tt::TesterError::UnexpectedResponse.into());
} }
wit::Message::Request(wit::Request { ref ipc, .. }) => { wit::Message::Request(wit::Request { ref body, .. }) => {
match serde_json::from_slice(ipc)? { match serde_json::from_slice(body)? {
tt::TesterRequest::Run { test_timeout, .. } => { tt::TesterRequest::Run { test_timeout, .. } => {
wit::print_to_terminal(0, "test_runner: got Run"); wit::print_to_terminal(0, "test_runner: got Run");
let response = Request::new() let response = Request::new()
.target(make_vfs_address(&our)?) .target(make_vfs_address(&our)?)
.ipc(serde_json::to_vec(&vfs::VfsRequest { .body(serde_json::to_vec(&vfs::VfsRequest {
path: "/tester:nectar/tests".into(), path: "/tester:nectar/tests".into(),
action: vfs::VfsAction::ReadDir, action: vfs::VfsAction::ReadDir,
})?) })?)
.send_and_await_response(test_timeout)? .send_and_await_response(test_timeout)?
.unwrap(); .unwrap();
let Message::Response { ipc: vfs_ipc, .. } = response else { let Message::Response { body: vfs_body, .. } = response else {
panic!("") panic!("")
}; };
let vfs::VfsResponse::ReadDir(children) = serde_json::from_slice(&vfs_ipc)? let vfs::VfsResponse::ReadDir(children) = serde_json::from_slice(&vfs_body)?
else { else {
wit::print_to_terminal( wit::print_to_terminal(
0, 0,
&format!( &format!(
"{:?}", "{:?}",
serde_json::from_slice::<serde_json::Value>(&vfs_ipc)?, serde_json::from_slice::<serde_json::Value>(&vfs_body)?,
), ),
); );
panic!("") panic!("")
@ -91,14 +91,14 @@ fn handle_message(our: &Address) -> anyhow::Result<()> {
node: our.node.clone(), node: our.node.clone(),
process: child_process_id, process: child_process_id,
}) })
.ipc(ipc.clone()) .body(body.clone())
.send_and_await_response(test_timeout)? .send_and_await_response(test_timeout)?
.unwrap(); .unwrap();
let Message::Response { ipc, .. } = response else { let Message::Response { body, .. } = response else {
panic!("") panic!("")
}; };
match serde_json::from_slice(&ipc)? { match serde_json::from_slice(&body)? {
tt::TesterResponse::Pass => {} tt::TesterResponse::Pass => {}
tt::TesterResponse::GetFullMessage(_) => {} tt::TesterResponse::GetFullMessage(_) => {}
tt::TesterResponse::Fail { 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)); wit::print_to_terminal(0, &format!("test_runner: done running {:?}", children));
Response::new() Response::new()
.ipc(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap()) .body(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
.send() .send()
.unwrap(); .unwrap();
} }
@ -133,7 +133,7 @@ impl Guest for Component {
fn init(our: String) { fn init(our: String) {
wit::print_to_terminal(0, "test_runner: begin"); wit::print_to_terminal(0, "test_runner: begin");
let our = Address::from_str(&our).unwrap(); let our: Address = our.parse().unwrap();
loop { loop {
match handle_message(&our) { match handle_message(&our) {

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase", "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]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -296,10 +313,10 @@ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
"indexmap", "indexmap",
"nectar_process_lib",
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
"uqbar_process_lib",
"wit-bindgen", "wit-bindgen",
] ]
@ -380,23 +397,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 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]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.0"

View File

@ -17,7 +17,7 @@ indexmap = "2.1"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
thiserror = "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" } wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib] [lib]

View File

@ -22,7 +22,7 @@ type Messages = IndexMap<kt::Message, tt::KernelMessage>;
fn make_vfs_address(our: &Address) -> anyhow::Result<Address> { fn make_vfs_address(our: &Address) -> anyhow::Result<Address> {
Ok(Address { Ok(Address {
node: our.node.clone(), 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 { match message {
Message::Response { source, ipc, .. } => { Message::Response { source, body, .. } => {
match serde_json::from_slice(&ipc)? { match serde_json::from_slice(&body)? {
tt::TesterResponse::Pass | tt::TesterResponse::Fail { .. } => { tt::TesterResponse::Pass | tt::TesterResponse::Fail { .. } => {
if (source.process.package_name != "tester") if (source.process.package_name != "tester")
| (source.process.publisher_node != "nectar") | (source.process.publisher_node != "nectar")
{ {
return Err(tt::TesterError::UnexpectedResponse.into()); return Err(tt::TesterError::UnexpectedResponse.into());
} }
Response::new().ipc(ipc).send().unwrap(); Response::new().body(body).send().unwrap();
} }
tt::TesterResponse::GetFullMessage(_) => { tt::TesterResponse::GetFullMessage(_) => {
unimplemented!() unimplemented!()
@ -52,8 +52,8 @@ fn handle_message(
} }
Ok(()) Ok(())
} }
Message::Request { source, ipc, .. } => { Message::Request { source, body, .. } => {
match serde_json::from_slice(&ipc)? { match serde_json::from_slice(&body)? {
tt::TesterRequest::Run { tt::TesterRequest::Run {
input_node_names, input_node_names,
test_timeout, test_timeout,
@ -65,7 +65,7 @@ fn handle_message(
if our.node != node_names[0] { if our.node != node_names[0] {
Response::new() Response::new()
.ipc(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap()) .body(serde_json::to_vec(&tt::TesterResponse::Pass).unwrap())
.send() .send()
.unwrap(); .unwrap();
} else { } else {
@ -76,7 +76,7 @@ fn handle_message(
child, child,
OnExit::None, // TODO: notify us OnExit::None, // TODO: notify us
our_capabilities(), our_capabilities(),
vec![ProcessId::from_str("vfs:sys:nectar").unwrap()], vec!["vfs:sys:nectar".parse::<ProcessId>().unwrap()],
false, // not public false, // not public
) { ) {
Ok(child_process_id) => child_process_id, Ok(child_process_id) => child_process_id,
@ -90,7 +90,7 @@ fn handle_message(
node: our.node.clone(), node: our.node.clone(),
process: child_process_id, process: child_process_id,
}) })
.ipc(ipc) .body(body)
.expects_response(test_timeout) .expects_response(test_timeout)
.send()?; .send()?;
} }
@ -112,7 +112,7 @@ fn init(our: Address) {
let mut node_names: Vec<String> = Vec::new(); let mut node_names: Vec<String> = Vec::new();
let _ = Request::new() let _ = Request::new()
.target(make_vfs_address(&our).unwrap()) .target(make_vfs_address(&our).unwrap())
.ipc( .body(
serde_json::to_vec(&vfs::VfsRequest { serde_json::to_vec(&vfs::VfsRequest {
path: "/tester:nectar/tests".into(), path: "/tester:nectar/tests".into(),
action: vfs::VfsAction::CreateDrive, action: vfs::VfsAction::CreateDrive,
@ -124,7 +124,7 @@ fn init(our: Address) {
.unwrap(); .unwrap();
let _ = Request::new() let _ = Request::new()
.target(("our", "kernel", "sys", "nectar")) .target(("our", "kernel", "sys", "nectar"))
.ipc( .body(
serde_json::to_vec(&kt::KernelCommand::GrantCapabilities { serde_json::to_vec(&kt::KernelCommand::GrantCapabilities {
target: ProcessId::new(Some("http_server"), "sys", "nectar"), target: ProcessId::new(Some("http_server"), "sys", "nectar"),
capabilities: vec![kt::Capability { capabilities: vec![kt::Capability {
@ -148,7 +148,7 @@ fn init(our: Address) {
// -> must give drive cap to rpc // -> must give drive cap to rpc
let _ = Request::new() let _ = Request::new()
.target(make_vfs_address(&our).unwrap()) .target(make_vfs_address(&our).unwrap())
.ipc( .body(
serde_json::to_vec(&vfs::VfsRequest { serde_json::to_vec(&vfs::VfsRequest {
path: "/tester:nectar/tests".into(), path: "/tester:nectar/tests".into(),
action: vfs::VfsAction::CreateDrive, action: vfs::VfsAction::CreateDrive,

View File

@ -14,7 +14,7 @@ pub struct KernelMessage {
pub target: Address, pub target: Address,
pub rsvp: Rsvp, pub rsvp: Rsvp,
pub message: kt::Message, pub message: kt::Message,
pub payload: Option<kt::Payload>, pub lazy_load_blob: Option<kt::LazyLoadBlob>,
pub signed_capabilities: HashMap<kt::Capability, Vec<u8>>, pub signed_capabilities: HashMap<kt::Capability, Vec<u8>>,
} }
@ -62,7 +62,7 @@ pub enum TesterError {
macro_rules! fail { macro_rules! fail {
($test:expr) => { ($test:expr) => {
Response::new() Response::new()
.ipc( .body(
serde_json::to_vec(&tt::TesterResponse::Fail { serde_json::to_vec(&tt::TesterResponse::Fail {
test: $test.into(), test: $test.into(),
file: file!().into(), file: file!().into(),
@ -77,7 +77,7 @@ macro_rules! fail {
}; };
($test:expr, $file:expr, $line:expr, $column:expr) => { ($test:expr, $file:expr, $line:expr, $column:expr) => {
Response::new() Response::new()
.ipc( .body(
serde_json::to_vec(&tt::TesterResponse::Fail { serde_json::to_vec(&tt::TesterResponse::Fail {
test: $test.into(), test: $test.into(),
file: $file.into(), file: $file.into(),

View File

@ -75,9 +75,9 @@ async fn handle_request(
connections: &Arc<Mutex<RpcConnections>>, connections: &Arc<Mutex<RpcConnections>>,
send_to_loop: &MessageSender, send_to_loop: &MessageSender,
) -> Result<()> { ) -> 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; 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; return handle_eth_request(action, our, km, connections, send_to_loop).await;
} else { } else {
return Err(anyhow::anyhow!("malformed request")); return Err(anyhow::anyhow!("malformed request"));
@ -95,7 +95,7 @@ async fn handle_http_server_request(
} = action } = action
{ {
if message_type == WsMessageType::Text { 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 text = std::str::from_utf8(&bytes).unwrap();
let mut json: serde_json::Value = serde_json::from_str(text)?; let mut json: serde_json::Value = serde_json::from_str(text)?;
let mut id = json["id"].as_u64().unwrap(); let mut id = json["id"].as_u64().unwrap();
@ -211,7 +211,7 @@ async fn spawn_provider_read_stream(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: json!({ body: json!({
"EventSubscription": serde_json::to_value(event.clone()).unwrap() "EventSubscription": serde_json::to_value(event.clone()).unwrap()
}) })
.to_string() .to_string()
@ -219,7 +219,7 @@ async fn spawn_provider_read_stream(
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await .await
.unwrap(); .unwrap();
@ -241,7 +241,7 @@ async fn bind_websockets(our: &str, send_to_loop: &MessageSender) {
rsvp: None, rsvp: None,
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&HttpServerAction::WebSocketBind { body: serde_json::to_vec(&HttpServerAction::WebSocketBind {
path: "/".to_string(), path: "/".to_string(),
authenticated: false, authenticated: false,
encrypted: false, encrypted: false,
@ -251,7 +251,7 @@ async fn bind_websockets(our: &str, send_to_loop: &MessageSender) {
expects_response: None, expects_response: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
} }
@ -316,7 +316,7 @@ async fn handle_external_websocket_passthrough(
rsvp: None, rsvp: None,
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&HttpServerAction::WebSocketPush { body: serde_json::to_vec(&HttpServerAction::WebSocketPush {
channel_id, channel_id,
message_type: WsMessageType::Text, message_type: WsMessageType::Text,
}) })
@ -325,7 +325,7 @@ async fn handle_external_websocket_passthrough(
expects_response: None, expects_response: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(Payload { lazy_load_blob: Some(LazyLoadBlob {
bytes: json.to_string().as_bytes().to_vec(), bytes: json.to_string().as_bytes().to_vec(),
mime: None, mime: None,
}), }),

View File

@ -43,15 +43,15 @@ pub async fn http_client(
message: message:
Message::Request(Request { Message::Request(Request {
expects_response, expects_response,
ipc, body,
.. ..
}), }),
payload, lazy_load_blob: blob,
.. ..
}) = recv_in_client.recv().await }) = recv_in_client.recv().await
{ {
// First check if a WebSocketClientAction, otherwise assume it's an OutgoingHttpRequest // 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 ws_streams_clone = Arc::clone(&ws_streams);
let _ = handle_websocket_action( let _ = handle_websocket_action(
@ -60,7 +60,7 @@ pub async fn http_client(
rsvp.unwrap_or(source), rsvp.unwrap_or(source),
expects_response, expects_response,
ws_action, ws_action,
payload, blob,
ws_streams_clone, ws_streams_clone,
send_to_loop.clone(), send_to_loop.clone(),
print_tx.clone(), print_tx.clone(),
@ -72,8 +72,8 @@ pub async fn http_client(
id, id,
rsvp.unwrap_or(source), rsvp.unwrap_or(source),
expects_response, expects_response,
ipc, body,
payload, blob,
client.clone(), client.clone(),
send_to_loop.clone(), send_to_loop.clone(),
print_tx.clone(), print_tx.clone(),
@ -89,7 +89,7 @@ async fn handle_websocket_action(
target: Address, target: Address,
expects_response: Option<u64>, expects_response: Option<u64>,
ws_action: WebSocketClientAction, ws_action: WebSocketClientAction,
payload: Option<Payload>, blob: Option<LazyLoadBlob>,
ws_streams: WebSocketStreams, ws_streams: WebSocketStreams,
send_to_loop: MessageSender, send_to_loop: MessageSender,
print_tx: PrintSender, print_tx: PrintSender,
@ -118,14 +118,7 @@ async fn handle_websocket_action(
channel_id, channel_id,
message_type, message_type,
} => ( } => (
send_ws_push( send_ws_push(target.clone(), channel_id, message_type, blob, ws_streams).await,
target.clone(),
channel_id,
message_type,
payload,
ws_streams,
)
.await,
channel_id, channel_id,
), ),
WebSocketClientAction::Close { channel_id } => ( WebSocketClientAction::Close { channel_id } => (
@ -214,7 +207,7 @@ async fn connect_websocket(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec::<WebSocketClientAction>( body: serde_json::to_vec::<WebSocketClientAction>(
&WebSocketClientAction::Response { &WebSocketClientAction::Response {
channel_id, channel_id,
result: Ok(()), result: Ok(()),
@ -226,7 +219,7 @@ async fn connect_websocket(
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
@ -260,7 +253,7 @@ async fn listen_to_stream(
// Handle different types of messages here // Handle different types of messages here
match msg { match msg {
TungsteniteMessage::Text(text) => { 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( handle_ws_message(
our.clone(), our.clone(),
id, id,
@ -269,7 +262,7 @@ async fn listen_to_stream(
channel_id, channel_id,
message_type: WsMessageType::Text, message_type: WsMessageType::Text,
}, },
Some(Payload { Some(LazyLoadBlob {
mime: Some("text/plain".into()), mime: Some("text/plain".into()),
bytes: text.into_bytes(), bytes: text.into_bytes(),
}), }),
@ -278,7 +271,7 @@ async fn listen_to_stream(
.await; .await;
} }
TungsteniteMessage::Binary(bytes) => { 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( handle_ws_message(
our.clone(), our.clone(),
id, id,
@ -287,7 +280,7 @@ async fn listen_to_stream(
channel_id, channel_id,
message_type: WsMessageType::Binary, message_type: WsMessageType::Binary,
}, },
Some(Payload { Some(LazyLoadBlob {
mime: Some("application/octet-stream".into()), mime: Some("application/octet-stream".into()),
bytes, bytes,
}), }),
@ -347,7 +340,7 @@ async fn handle_http_request(
target: Address, target: Address,
expects_response: Option<u64>, expects_response: Option<u64>,
json: Vec<u8>, json: Vec<u8>,
body: Option<Payload>, body: Option<LazyLoadBlob>,
client: reqwest::Client, client: reqwest::Client,
send_to_loop: MessageSender, send_to_loop: MessageSender,
print_tx: PrintSender, print_tx: PrintSender,
@ -414,8 +407,8 @@ async fn handle_http_request(
} }
} }
if let Some(payload) = body { if let Some(blob) = body {
request_builder = request_builder.body(payload.bytes); request_builder = request_builder.body(blob.bytes);
} }
let Ok(request) = request_builder let Ok(request) = request_builder
@ -456,7 +449,7 @@ async fn handle_http_request(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Ok( body: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Ok(
HttpResponse { HttpResponse {
status: response.status().as_u16(), status: response.status().as_u16(),
headers: serialize_headers(response.headers()), headers: serialize_headers(response.headers()),
@ -468,7 +461,7 @@ async fn handle_http_request(
}, },
None, None,
)), )),
payload: Some(Payload { lazy_load_blob: Some(LazyLoadBlob {
mime: None, mime: None,
bytes: response.bytes().await.unwrap_or_default().to_vec(), bytes: response.bytes().await.unwrap_or_default().to_vec(),
}), }),
@ -556,7 +549,7 @@ async fn http_error_message(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Err( body: serde_json::to_vec::<Result<HttpResponse, HttpClientError>>(&Err(
error, error,
)) ))
.unwrap(), .unwrap(),
@ -565,7 +558,7 @@ async fn http_error_message(
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
} }
@ -593,7 +586,7 @@ async fn websocket_error_message(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec::<WebSocketClientAction>( body: serde_json::to_vec::<WebSocketClientAction>(
&WebSocketClientAction::Response { &WebSocketClientAction::Response {
channel_id, channel_id,
result: Err(error), result: Err(error),
@ -605,7 +598,7 @@ async fn websocket_error_message(
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
} }
@ -615,7 +608,7 @@ async fn send_ws_push(
target: Address, target: Address,
channel_id: u32, channel_id: u32,
message_type: WsMessageType, message_type: WsMessageType,
payload: Option<Payload>, blob: Option<LazyLoadBlob>,
ws_streams: WebSocketStreams, ws_streams: WebSocketStreams,
) -> Result<(), WebSocketClientError> { ) -> Result<(), WebSocketClientError> {
let Some(mut ws_stream) = ws_streams.get_mut(&(target.process.clone(), channel_id)) else { 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 { let result = match message_type {
WsMessageType::Text => { WsMessageType::Text => {
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(WebSocketClientError::BadRequest { 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 { 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 ws_stream.send(TungsteniteMessage::Text(text)).await
} }
WsMessageType::Binary => { WsMessageType::Binary => {
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(WebSocketClientError::BadRequest { return Err(WebSocketClientError::BadRequest {
req: "no payload".into(), req: "no blob".into(),
}); });
}; };
ws_stream ws_stream.send(TungsteniteMessage::Binary(blob.bytes)).await
.send(TungsteniteMessage::Binary(payload.bytes))
.await
} }
WsMessageType::Ping => ws_stream.send(TungsteniteMessage::Ping(vec![])).await, WsMessageType::Ping => ws_stream.send(TungsteniteMessage::Ping(vec![])).await,
WsMessageType::Pong => ws_stream.send(TungsteniteMessage::Pong(vec![])).await, WsMessageType::Pong => ws_stream.send(TungsteniteMessage::Pong(vec![])).await,
@ -683,7 +674,7 @@ async fn handle_ws_message(
id: u64, id: u64,
target: Address, target: Address,
action: WebSocketClientAction, action: WebSocketClientAction,
payload: Option<Payload>, blob: Option<LazyLoadBlob>,
send_to_loop: MessageSender, send_to_loop: MessageSender,
) { ) {
let _ = send_to_loop let _ = send_to_loop
@ -697,12 +688,12 @@ async fn handle_ws_message(
rsvp: None, rsvp: None,
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
ipc: serde_json::to_vec::<WebSocketClientAction>(&action).unwrap(), body: serde_json::to_vec::<WebSocketClientAction>(&action).unwrap(),
expects_response: None, expects_response: None,
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload, lazy_load_blob: blob,
}) })
.await; .await;
} }

View File

@ -43,7 +43,7 @@ struct BoundPath {
pub secure_subdomain: Option<String>, pub secure_subdomain: Option<String>,
pub authenticated: bool, pub authenticated: bool,
pub local_only: 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 { struct BoundWsPath {
@ -86,7 +86,7 @@ pub async fn http_server(
// add RPC path // add RPC path
let mut bindings_map: Router<BoundPath> = Router::new(); let mut bindings_map: Router<BoundPath> = Router::new();
let rpc_bound_path = BoundPath { 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? secure_subdomain: None, // TODO maybe RPC should have subdomain?
authenticated: false, authenticated: false,
local_only: true, local_only: true,
@ -482,7 +482,7 @@ async fn http_handler(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: Some(HTTP_SELF_IMPOSED_TIMEOUT), 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()), source_socket_addr: socket_addr.map(|addr| addr.to_string()),
method: method.to_string(), method: method.to_string(),
raw_path: format!( raw_path: format!(
@ -498,7 +498,7 @@ async fn http_handler(
metadata: Some("http".into()), metadata: Some("http".into()),
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(Payload { lazy_load_blob: Some(LazyLoadBlob {
mime: None, mime: None,
bytes: body.to_vec(), bytes: body.to_vec(),
}), }),
@ -572,7 +572,7 @@ async fn handle_rpc_message(
return Err(StatusCode::BAD_REQUEST); 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); return Err(StatusCode::BAD_REQUEST);
}; };
@ -583,10 +583,10 @@ async fn handle_rpc_message(
}) })
.await; .await;
let payload: Option<Payload> = match rpc_message.data { let blob: Option<LazyLoadBlob> = match rpc_message.data {
None => None, None => None,
Some(b64_bytes) => match base64::decode(b64_bytes) { Some(b64_bytes) => match base64::decode(b64_bytes) {
Ok(bytes) => Some(Payload { Ok(bytes) => Some(LazyLoadBlob {
mime: rpc_message.mime, mime: rpc_message.mime,
bytes, bytes,
}), }),
@ -611,14 +611,14 @@ async fn handle_rpc_message(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: Some(15), // NB: no effect on runtime expects_response: Some(15), // NB: no effect on runtime
ipc: match rpc_message.ipc { body: match rpc_message.body {
Some(ipc_string) => ipc_string.into_bytes(), Some(body_string) => body_string.into_bytes(),
None => Vec::new(), None => Vec::new(),
}, },
metadata: rpc_message.metadata, metadata: rpc_message.metadata,
capabilities: vec![], capabilities: vec![],
}), }),
payload, lazy_load_blob: blob,
}) })
} }
@ -660,12 +660,12 @@ async fn maintain_websocket(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&HttpServerRequest::WebSocketOpen { path, channel_id }) body: serde_json::to_vec(&HttpServerRequest::WebSocketOpen { path, channel_id })
.unwrap(), .unwrap(),
metadata: Some("ws".into()), metadata: Some("ws".into()),
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
@ -701,14 +701,14 @@ async fn maintain_websocket(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&HttpServerRequest::WebSocketPush { body: serde_json::to_vec(&HttpServerRequest::WebSocketPush {
channel_id, channel_id,
message_type: ws_msg_type, message_type: ws_msg_type,
}).unwrap(), }).unwrap(),
metadata: Some("ws".into()), metadata: Some("ws".into()),
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(Payload { lazy_load_blob: Some(LazyLoadBlob {
mime: None, mime: None,
bytes: msg.into_bytes(), bytes: msg.into_bytes(),
}), }),
@ -763,15 +763,15 @@ async fn websocket_close(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, 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()), metadata: Some("ws".into()),
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(Payload { lazy_load_blob: Some(LazyLoadBlob {
mime: None, mime: None,
bytes: serde_json::to_vec(&RpcResponseBody { bytes: serde_json::to_vec(&RpcResponseBody {
ipc: Vec::new(), body: Vec::new(),
payload: None, lazy_load_blob: None,
}) })
.unwrap(), .unwrap(),
}), }),
@ -796,9 +796,9 @@ async fn handle_app_message(
let Some((_id, (path, sender))) = http_response_senders.remove(&km.id) else { let Some((_id, (path, sender))) = http_response_senders.remove(&km.id) else {
return; 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" { 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, mime: p.mime,
bytes: base64::encode(p.bytes).into_bytes(), bytes: base64::encode(p.bytes).into_bytes(),
}); });
@ -812,13 +812,13 @@ async fn handle_app_message(
headers: default_headers, headers: default_headers,
}, },
serde_json::to_vec(&RpcResponseBody { serde_json::to_vec(&RpcResponseBody {
ipc: response.ipc, body: response.body,
payload, lazy_load_blob: blob,
}) })
.unwrap(), .unwrap(),
)); ));
} else { } 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. // the receiver will automatically trigger a 503 when sender is dropped.
return; return;
}; };
@ -827,25 +827,25 @@ async fn handle_app_message(
status: response.status, status: response.status,
headers: response.headers, headers: response.headers,
}, },
match km.payload { match km.lazy_load_blob {
None => vec![], None => vec![],
Some(p) => p.bytes, Some(p) => p.bytes,
}, },
)); ));
} }
} }
Message::Request(Request { ref ipc, .. }) => { Message::Request(Request { ref body, .. }) => {
let Ok(message) = serde_json::from_slice::<HttpServerAction>(ipc) else { let Ok(message) = serde_json::from_slice::<HttpServerAction>(body) else {
println!( println!(
"http_server: got malformed request from {}: {:?}\r", "http_server: got malformed request from {}: {:?}\r",
km.source, ipc km.source, body
); );
send_action_response( send_action_response(
km.id, km.id,
km.source, km.source,
&send_to_loop, &send_to_loop,
Err(HttpServerError::BadRequest { Err(HttpServerError::BadRequest {
req: String::from_utf8_lossy(ipc).to_string(), req: String::from_utf8_lossy(body).to_string(),
}), }),
) )
.await; .await;
@ -888,12 +888,12 @@ async fn handle_app_message(
}, },
); );
} else { } else {
let Some(payload) = km.payload else { let Some(blob) = km.lazy_load_blob else {
send_action_response( send_action_response(
km.id, km.id,
km.source, km.source,
&send_to_loop, &send_to_loop,
Err(HttpServerError::NoPayload), Err(HttpServerError::NoBlob),
) )
.await; .await;
return; return;
@ -906,7 +906,7 @@ async fn handle_app_message(
secure_subdomain: None, secure_subdomain: None,
authenticated, authenticated,
local_only, local_only,
static_content: Some(payload), static_content: Some(blob),
}, },
); );
} }
@ -934,12 +934,12 @@ async fn handle_app_message(
}, },
); );
} else { } else {
let Some(payload) = km.payload else { let Some(blob) = km.lazy_load_blob else {
send_action_response( send_action_response(
km.id, km.id,
km.source, km.source,
&send_to_loop, &send_to_loop,
Err(HttpServerError::NoPayload), Err(HttpServerError::NoBlob),
) )
.await; .await;
return; return;
@ -952,7 +952,7 @@ async fn handle_app_message(
secure_subdomain: Some(subdomain), secure_subdomain: Some(subdomain),
authenticated: true, authenticated: true,
local_only: false, local_only: false,
static_content: Some(payload), static_content: Some(blob),
}, },
); );
} }
@ -1020,23 +1020,23 @@ async fn handle_app_message(
channel_id, channel_id,
message_type, message_type,
} => { } => {
let Some(payload) = km.payload else { let Some(blob) = km.lazy_load_blob else {
send_action_response( send_action_response(
km.id, km.id,
km.source, km.source,
&send_to_loop, &send_to_loop,
Err(HttpServerError::NoPayload), Err(HttpServerError::NoBlob),
) )
.await; .await;
return; return;
}; };
let ws_message = match message_type { let ws_message = match message_type {
WsMessageType::Text => warp::ws::Message::text( 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 => { WsMessageType::Ping | WsMessageType::Pong => {
if payload.bytes.len() > 125 { if blob.bytes.len() > 125 {
send_action_response( send_action_response(
km.id, km.id,
km.source, km.source,
@ -1050,9 +1050,9 @@ async fn handle_app_message(
return; return;
} }
if message_type == WsMessageType::Ping { if message_type == WsMessageType::Ping {
warp::ws::Message::ping(payload.bytes) warp::ws::Message::ping(blob.bytes)
} else { } else {
warp::ws::Message::pong(payload.bytes) warp::ws::Message::pong(blob.bytes)
} }
} }
WsMessageType::Close => { WsMessageType::Close => {
@ -1147,13 +1147,13 @@ pub async fn send_action_response(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&result).unwrap(), body: serde_json::to_vec(&result).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
} }

View File

@ -1,4 +1,4 @@
use crate::types::Payload; use crate::types::LazyLoadBlob;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use thiserror::Error; use thiserror::Error;
@ -17,7 +17,7 @@ pub enum HttpServerRequest {
}, },
/// Processes can both SEND and RECEIVE this kind of request /// Processes can both SEND and RECEIVE this kind of request
/// (send as [`type@HttpServerAction::WebSocketPush`]). /// (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 { WebSocketPush {
channel_id: u32, channel_id: u32,
message_type: WsMessageType, message_type: WsMessageType,
@ -34,7 +34,7 @@ pub struct IncomingHttpRequest {
pub raw_path: String, pub raw_path: String,
pub headers: HashMap<String, String>, pub headers: HashMap<String, String>,
pub query_params: 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. /// 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 version: Option<String>, // must parse to http::Version
pub url: String, // must parse to url::Url pub url: String, // must parse to url::Url
pub headers: HashMap<String, String>, 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 // TIMEOUT is stored in the message expect_response
} }
@ -55,7 +55,7 @@ pub struct OutgoingHttpRequest {
pub struct HttpResponse { pub struct HttpResponse {
pub status: u16, pub status: u16,
pub headers: HashMap<String, String>, 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. /// WebSocket Client Request type that can be shared over WASM boundary to apps.
@ -82,8 +82,8 @@ pub enum WebSocketClientAction {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct RpcResponseBody { pub struct RpcResponseBody {
pub ipc: Vec<u8>, pub body: Vec<u8>,
pub payload: Option<Payload>, pub lazy_load_blob: Option<LazyLoadBlob>,
} }
#[derive(Error, Debug, Serialize, Deserialize)] #[derive(Error, Debug, Serialize, Deserialize)]
@ -122,7 +122,7 @@ pub enum WebSocketClientError {
/// with the shape Result<(), HttpServerActionError> serialized to JSON. /// with the shape Result<(), HttpServerActionError> serialized to JSON.
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum HttpServerAction { 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. /// be the static file to serve at this path.
Bind { Bind {
path: String, path: String,
@ -131,11 +131,11 @@ pub enum HttpServerAction {
authenticated: bool, authenticated: bool,
/// Set whether requests can be fielded from anywhere, or only the loopback address. /// Set whether requests can be fielded from anywhere, or only the loopback address.
local_only: bool, local_only: bool,
/// Set whether to bind the payload statically to this path. That is, take the /// Set whether to bind the lazy_load_blob statically to this path. That is, take the
/// payload bytes and serve them as the response to any request to this path. /// lazy_load_blob bytes and serve them as the response to any request to this path.
cache: bool, 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. /// be the static file to serve at this path.
/// ///
/// SecureBind is the same as Bind, except that it forces requests to be made from /// 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. /// will require the user to be logged in separately to the general domain authentication.
SecureBind { SecureBind {
path: String, path: String,
/// Set whether to bind the payload statically to this path. That is, take the /// Set whether to bind the lazy_load_blob statically to this path. That is, take the
/// payload bytes and serve them as the response to any request to this path. /// lazy_load_blob bytes and serve them as the response to any request to this path.
cache: bool, cache: bool,
}, },
/// Bind a path to receive incoming WebSocket connections. /// 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* /// If a process does not want this websocket open, they should issue a *request*
/// containing a [`type@HttpServerAction::WebSocketClose`] message and this channel ID. /// containing a [`type@HttpServerAction::WebSocketClose`] message and this channel ID.
WebSocketOpen { path: String, channel_id: u32 }, 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 { WebSocketPush {
channel_id: u32, channel_id: u32,
message_type: WsMessageType, message_type: WsMessageType,
@ -176,9 +176,9 @@ pub enum HttpServerAction {
} }
/// The possible message types for WebSocketPush. Ping and Pong are limited to 125 bytes /// 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 /// 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)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum WsMessageType { pub enum WsMessageType {
Text, Text,
@ -196,8 +196,8 @@ pub enum HttpServerError {
req req
)] )]
BadRequest { req: String }, BadRequest { req: String },
#[error("http_server: action expected payload")] #[error("http_server: action expected blob")]
NoPayload, NoBlob,
#[error("http_server: path binding error: {:?}", error)] #[error("http_server: path binding error: {:?}", error)]
PathBindError { error: String }, PathBindError { error: String },
#[error("http_server: WebSocket error: {:?}", error)] #[error("http_server: WebSocket error: {:?}", error)]

View File

@ -13,7 +13,7 @@ pub struct RpcMessage {
pub process: String, pub process: String,
pub inherit: Option<bool>, pub inherit: Option<bool>,
pub expects_response: Option<u64>, pub expects_response: Option<u64>,
pub ipc: Option<String>, pub body: Option<String>,
pub metadata: Option<String>, pub metadata: Option<String>,
pub context: Option<String>, pub context: Option<String>,
pub mime: Option<String>, pub mime: Option<String>,

View File

@ -65,12 +65,12 @@ async fn persist_state(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: true, inherit: true,
expects_response: None, 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(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(t::Payload { mime: None, bytes }), lazy_load_blob: Some(t::LazyLoadBlob { mime: None, bytes }),
}) })
.await?; .await?;
Ok(()) Ok(())
@ -92,7 +92,7 @@ async fn handle_kernel_request(
let t::Message::Request(request) = km.message else { let t::Message::Request(request) = km.message else {
return; 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) => { Err(e) => {
let _ = send_to_terminal let _ = send_to_terminal
.send(t::Printout { .send(t::Printout {
@ -125,11 +125,11 @@ async fn handle_kernel_request(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: b"run".to_vec(), body: b"run".to_vec(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
})) }))
.await; .await;
} }
@ -150,7 +150,7 @@ async fn handle_kernel_request(
initial_capabilities, initial_capabilities,
public, public,
} => { } => {
let Some(payload) = km.payload else { let Some(blob) = km.lazy_load_blob else {
let _ = send_to_terminal let _ = send_to_terminal
.send(t::Printout { .send(t::Printout {
verbosity: 0, verbosity: 0,
@ -170,14 +170,16 @@ async fn handle_kernel_request(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&t::KernelResponse::InitializeProcessError) body: serde_json::to_vec(
.unwrap(), &t::KernelResponse::InitializeProcessError,
)
.unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -247,7 +249,7 @@ async fn handle_kernel_request(
our_name.clone(), our_name.clone(),
keypair.clone(), keypair.clone(),
km.id, km.id,
payload.bytes, blob.bytes,
send_to_loop.clone(), send_to_loop.clone(),
send_to_terminal, send_to_terminal,
senders, senders,
@ -288,7 +290,7 @@ async fn handle_kernel_request(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec( body: serde_json::to_vec(
&t::KernelResponse::InitializeProcessError, &t::KernelResponse::InitializeProcessError,
) )
.unwrap(), .unwrap(),
@ -297,7 +299,7 @@ async fn handle_kernel_request(
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -353,11 +355,11 @@ async fn handle_kernel_request(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: b"run".to_vec(), body: b"run".to_vec(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
})) }))
.await .await
{ {
@ -373,14 +375,14 @@ async fn handle_kernel_request(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&t::KernelResponse::StartedProcess) body: serde_json::to_vec(&t::KernelResponse::StartedProcess)
.unwrap(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -405,14 +407,14 @@ async fn handle_kernel_request(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&t::KernelResponse::RunProcessError) body: serde_json::to_vec(&t::KernelResponse::RunProcessError)
.unwrap(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -459,14 +461,14 @@ async fn handle_kernel_request(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&t::KernelResponse::KilledProcess(process_id)) body: serde_json::to_vec(&t::KernelResponse::KilledProcess(process_id))
.unwrap(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -521,7 +523,7 @@ async fn start_process(
our_name: String, our_name: String,
keypair: Arc<signature::Ed25519KeyPair>, keypair: Arc<signature::Ed25519KeyPair>,
km_id: u64, km_id: u64,
km_payload_bytes: Vec<u8>, km_blob_bytes: Vec<u8>,
send_to_loop: t::MessageSender, send_to_loop: t::MessageSender,
send_to_terminal: t::PrintSender, send_to_terminal: t::PrintSender,
senders: &mut Senders, senders: &mut Senders,
@ -569,7 +571,7 @@ async fn start_process(
send_to_terminal.clone(), send_to_terminal.clone(),
recv_in_process, recv_in_process,
send_to_process, send_to_process,
km_payload_bytes, km_blob_bytes,
caps_oracle, caps_oracle,
engine.clone(), engine.clone(),
)), )),
@ -592,13 +594,13 @@ async fn start_process(
message: t::Message::Response(( message: t::Message::Response((
t::Response { t::Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&t::KernelResponse::InitializedProcess)?, body: serde_json::to_vec(&t::KernelResponse::InitializedProcess)?,
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await?; .await?;
Ok(()) Ok(())
@ -691,7 +693,7 @@ pub async fn kernel(
if let t::OnExit::Requests(requests) = &persisted.on_exit { if let t::OnExit::Requests(requests) = &persisted.on_exit {
// if a persisted process had on-death-requests, we should perform them now // 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 // 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 // the process that made the request is dead, so never expects response
let mut request = request.to_owned(); let mut request = request.to_owned();
request.expects_response = None; request.expects_response = None;
@ -710,7 +712,7 @@ pub async fn kernel(
target: address.clone(), target: address.clone(),
rsvp: None, rsvp: None,
message: t::Message::Request(request), message: t::Message::Request(request),
payload: payload.clone(), lazy_load_blob: blob.clone(),
}) })
.await .await
.expect("fatal: kernel event loop died"); .expect("fatal: kernel event loop died");
@ -767,11 +769,11 @@ pub async fn kernel(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: true, inherit: true,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&t::KernelCommand::Booted).unwrap(), body: serde_json::to_vec(&t::KernelCommand::Booted).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("fatal: kernel event loop died"); .expect("fatal: kernel event loop died");

View File

@ -26,7 +26,7 @@ pub struct ProcessState {
pub send_to_loop: t::MessageSender, pub send_to_loop: t::MessageSender,
pub send_to_terminal: t::PrintSender, pub send_to_terminal: t::PrintSender,
pub prompting_message: Option<t::KernelMessage>, 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 contexts: HashMap<u64, (t::ProcessContext, JoinHandle<()>)>,
pub message_queue: VecDeque<Result<t::KernelMessage, t::WrappedSendError>>, pub message_queue: VecDeque<Result<t::KernelMessage, t::WrappedSendError>>,
pub caps_oracle: t::CapMessageSender, pub caps_oracle: t::CapMessageSender,
@ -58,7 +58,7 @@ pub async fn send_and_await_response(
source: Option<t::Address>, source: Option<t::Address>,
target: wit::Address, target: wit::Address,
request: wit::Request, request: wit::Request,
payload: Option<wit::Payload>, blob: Option<wit::LazyLoadBlob>,
) -> Result<Result<(wit::Address, wit::Message), wit::SendError>> { ) -> Result<Result<(wit::Address, wit::Message), wit::SendError>> {
if request.expects_response.is_none() { if request.expects_response.is_none() {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
@ -68,7 +68,7 @@ pub async fn send_and_await_response(
} }
let id = process let id = process
.process .process
.send_request(source, target, request, None, payload) .send_request(source, target, request, None, blob)
.await; .await;
match id { match id {
Ok(id) => match process.process.get_specific_message_for_process(id).await { Ok(id) => match process.process.get_specific_message_for_process(id).await {
@ -108,7 +108,7 @@ impl ProcessState {
target: wit::Address, target: wit::Address,
request: wit::Request, request: wit::Request,
new_context: Option<wit::Context>, new_context: Option<wit::Context>,
payload: Option<wit::Payload>, blob: Option<wit::LazyLoadBlob>,
) -> Result<u64> { ) -> Result<u64> {
let source = match &fake_source { let source = match &fake_source {
Some(_) => fake_source.unwrap(), Some(_) => fake_source.unwrap(),
@ -130,13 +130,13 @@ impl ProcessState {
} }
}; };
let payload = match payload { let blob = match blob {
Some(p) => Some(t::Payload { Some(p) => Some(t::LazyLoadBlob {
mime: p.mime, mime: p.mime,
bytes: p.bytes, bytes: p.bytes,
}), }),
None => match request.inherit { None => match request.inherit {
true => self.last_payload.clone(), true => self.last_blob.clone(),
false => None, false => None,
}, },
}; };
@ -186,7 +186,7 @@ impl ProcessState {
(_, None, None) => None, (_, None, None) => None,
}, },
message: t::Message::Request(inner_request), message: t::Message::Request(inner_request),
payload: payload.clone(), lazy_load_blob: blob.clone(),
}; };
// modify the process' context map as needed. // modify the process' context map as needed.
@ -205,7 +205,7 @@ impl ProcessState {
kind: t::SendErrorKind::Timeout, kind: t::SendErrorKind::Timeout,
target: t::Address::de_wit(target), target: t::Address::de_wit(target),
message: t::Message::Request(t::de_wit_request(request.clone())), message: t::Message::Request(t::de_wit_request(request.clone())),
payload, lazy_load_blob: blob,
}, },
})) }))
.await; .await;
@ -235,7 +235,11 @@ impl ProcessState {
} }
/// takes Response generated by a process and sends it to the main event loop. /// 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 { let (id, target) = match self.make_response_id_target().await {
Some(r) => r, Some(r) => r,
None => { None => {
@ -250,9 +254,9 @@ impl ProcessState {
} }
}; };
let payload = match response.inherit { let blob = match response.inherit {
true => self.last_payload.clone(), true => self.last_blob.clone(),
false => t::de_wit_payload(payload), false => t::de_wit_blob(blob),
}; };
let mut inner_response = t::de_wit_response(response.clone()); 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. // the context will be set by the process receiving this Response.
None, None,
)), )),
payload, lazy_load_blob: blob,
}) })
.await .await
.expect("fatal: kernel couldn't send response"); .expect("fatal: kernel couldn't send response");
@ -331,14 +335,14 @@ impl ProcessState {
let (context, km) = match res { let (context, km) = match res {
Ok(km) => match &km.message { Ok(km) => match &km.message {
t::Message::Request(_) => { t::Message::Request(_) => {
self.last_payload = km.payload.clone(); self.last_blob = km.lazy_load_blob.clone();
self.prompting_message = Some(km.clone()); self.prompting_message = Some(km.clone());
(None, km) (None, km)
} }
t::Message::Response(_) => { t::Message::Response(_) => {
if let Some((context, timeout_handle)) = self.contexts.remove(&km.id) { if let Some((context, timeout_handle)) = self.contexts.remove(&km.id) {
timeout_handle.abort(); timeout_handle.abort();
self.last_payload = km.payload.clone(); self.last_blob = km.lazy_load_blob.clone();
self.prompting_message = match context.prompting_message { self.prompting_message = match context.prompting_message {
None => Some(km.clone()), None => Some(km.clone()),
Some(prompting_message) => Some(prompting_message), Some(prompting_message) => Some(prompting_message),
@ -458,7 +462,7 @@ pub async fn make_process_loop(
== t::Message::Request(t::Request { == t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: b"run".to_vec(), body: b"run".to_vec(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
})) }))
@ -499,7 +503,7 @@ pub async fn make_process_loop(
send_to_loop: send_to_loop.clone(), send_to_loop: send_to_loop.clone(),
send_to_terminal: send_to_terminal.clone(), send_to_terminal: send_to_terminal.clone(),
prompting_message: None, prompting_message: None,
last_payload: None, last_blob: None,
contexts: HashMap::new(), contexts: HashMap::new(),
message_queue: VecDeque::new(), message_queue: VecDeque::new(),
caps_oracle: caps_oracle.clone(), caps_oracle: caps_oracle.clone(),
@ -576,14 +580,14 @@ pub async fn make_process_loop(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&t::KernelCommand::KillProcess( body: serde_json::to_vec(&t::KernelCommand::KillProcess(
metadata.our.process.clone(), metadata.our.process.clone(),
)) ))
.unwrap(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -616,14 +620,14 @@ pub async fn make_process_loop(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&t::KernelCommand::KillProcess( body: serde_json::to_vec(&t::KernelCommand::KillProcess(
metadata.our.process.clone(), metadata.our.process.clone(),
)) ))
.unwrap(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
@ -642,7 +646,7 @@ pub async fn make_process_loop(
message: t::Message::Request(t::Request { message: t::Message::Request(t::Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&t::KernelCommand::InitializeProcess { body: serde_json::to_vec(&t::KernelCommand::InitializeProcess {
id: metadata.our.process.clone(), id: metadata.our.process.clone(),
wasm_bytes_handle: metadata.wasm_bytes_handle, wasm_bytes_handle: metadata.wasm_bytes_handle,
wit_version: Some(metadata.wit_version), wit_version: Some(metadata.wit_version),
@ -654,7 +658,7 @@ pub async fn make_process_loop(
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: Some(t::Payload { lazy_load_blob: Some(t::LazyLoadBlob {
mime: None, mime: None,
bytes: wasm_bytes, bytes: wasm_bytes,
}), }),
@ -665,7 +669,7 @@ pub async fn make_process_loop(
// if requests, fire them // if requests, fire them
// even in death, a process can only message processes it has capabilities for // even in death, a process can only message processes it has capabilities for
t::OnExit::Requests(requests) => { t::OnExit::Requests(requests) => {
for (address, mut request, payload) in requests { for (address, mut request, blob) in requests {
request.expects_response = None; request.expects_response = None;
let (tx, rx) = tokio::sync::oneshot::channel(); let (tx, rx) = tokio::sync::oneshot::channel();
let _ = caps_oracle let _ = caps_oracle
@ -686,7 +690,7 @@ pub async fn make_process_loop(
target: address, target: address,
rsvp: None, rsvp: None,
message: t::Message::Request(request), message: t::Message::Request(request),
payload, lazy_load_blob: blob,
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");

View File

@ -33,11 +33,6 @@ impl StandardHost for process::ProcessWasi {
.map_err(|e| anyhow::anyhow!("fatal: couldn't send to terminal: {e:?}")) .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: // process management:
// //
@ -56,7 +51,7 @@ impl StandardHost for process::ProcessWasi {
/// create a message from the *kernel* to the filesystem, /// create a message from the *kernel* to the filesystem,
/// asking it to fetch the current state saved under this process /// asking it to fetch the current state saved under this process
async fn get_state(&mut self) -> Result<Option<Vec<u8>>> { 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( let res = match process::send_and_await_response(
self, self,
Some(t::Address { Some(t::Address {
@ -70,7 +65,7 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), 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(), self.process.metadata.our.process.clone(),
)) ))
.unwrap(), .unwrap(),
@ -83,14 +78,14 @@ impl StandardHost for process::ProcessWasi {
{ {
Ok(Ok(_resp)) => { Ok(Ok(_resp)) => {
// basically assuming filesystem responding properly here // basically assuming filesystem responding properly here
match &self.process.last_payload { match &self.process.last_blob {
None => Ok(None), None => Ok(None),
Some(payload) => Ok(Some(payload.bytes.clone())), Some(blob) => Ok(Some(blob.bytes.clone())),
} }
} }
_ => Ok(None), _ => Ok(None),
}; };
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return res; return res;
} }
@ -98,7 +93,7 @@ impl StandardHost for process::ProcessWasi {
/// asking it to replace the current state saved under /// asking it to replace the current state saved under
/// this process with these bytes /// this process with these bytes
async fn set_state(&mut self, bytes: Vec<u8>) -> Result<()> { 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( let res = match process::send_and_await_response(
self, self,
Some(t::Address { Some(t::Address {
@ -112,14 +107,14 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), 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(), self.process.metadata.our.process.clone(),
)) ))
.unwrap(), .unwrap(),
metadata: Some(self.process.metadata.our.process.to_string()), metadata: Some(self.process.metadata.our.process.to_string()),
capabilities: vec![], capabilities: vec![],
}, },
Some(wit::Payload { mime: None, bytes }), Some(wit::LazyLoadBlob { mime: None, bytes }),
) )
.await .await
{ {
@ -131,7 +126,7 @@ impl StandardHost for process::ProcessWasi {
"filesystem did not respond properly to SetState!!" "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; print_debug(&self.process, "persisted state").await;
return res; return res;
} }
@ -139,7 +134,7 @@ impl StandardHost for process::ProcessWasi {
/// create a message from the *kernel* to the filesystem, /// create a message from the *kernel* to the filesystem,
/// asking it to delete the current state saved under this process /// asking it to delete the current state saved under this process
async fn clear_state(&mut self) -> Result<()> { 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( let res = match process::send_and_await_response(
self, self,
Some(t::Address { Some(t::Address {
@ -153,7 +148,7 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), 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(), self.process.metadata.our.process.clone(),
)) ))
.unwrap(), .unwrap(),
@ -172,7 +167,7 @@ impl StandardHost for process::ProcessWasi {
"filesystem did not respond properly to ClearState!!" "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; print_debug(&self.process, "cleared persisted state").await;
return res; return res;
} }
@ -189,8 +184,8 @@ impl StandardHost for process::ProcessWasi {
grant_capabilities: Vec<wit::ProcessId>, grant_capabilities: Vec<wit::ProcessId>,
public: bool, public: bool,
) -> Result<Result<wit::ProcessId, wit::SpawnError>> { ) -> Result<Result<wit::ProcessId, wit::SpawnError>> {
// save existing payload to restore later // save existing blob to restore later
let old_last_payload = self.process.last_payload.clone(); let old_last_blob = self.process.last_blob.clone();
let vfs_address = wit::Address { let vfs_address = wit::Address {
node: self.process.metadata.our.node.clone(), node: self.process.metadata.our.node.clone(),
process: VFS_PROCESS_ID.en_wit(), process: VFS_PROCESS_ID.en_wit(),
@ -202,7 +197,7 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), expects_response: Some(5),
ipc: serde_json::to_vec(&t::VfsRequest { body: serde_json::to_vec(&t::VfsRequest {
path: wasm_path.clone(), path: wasm_path.clone(),
action: t::VfsAction::Read, action: t::VfsAction::Read,
}) })
@ -215,23 +210,23 @@ impl StandardHost for process::ProcessWasi {
.await .await
else { else {
println!("spawn: GetHash fail"); println!("spawn: GetHash fail");
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NoFileAtPath)); return Ok(Err(wit::SpawnError::NoFileAtPath));
}; };
let wit::Message::Response((wit::Response { ipc, .. }, _)) = hash_response else { let wit::Message::Response((wit::Response { body, .. }, _)) = hash_response else {
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NoFileAtPath)); return Ok(Err(wit::SpawnError::NoFileAtPath));
}; };
let t::VfsResponse::Read = serde_json::from_slice(&ipc).unwrap() else { let t::VfsResponse::Read = serde_json::from_slice(&body).unwrap() else {
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NoFileAtPath)); return Ok(Err(wit::SpawnError::NoFileAtPath));
}; };
let Some(t::Payload { mime: _, ref bytes }) = self.process.last_payload else { let Some(t::LazyLoadBlob { mime: _, ref bytes }) = self.process.last_blob else {
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NoFileAtPath)); return Ok(Err(wit::SpawnError::NoFileAtPath));
}; };
@ -258,7 +253,7 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), // TODO evaluate 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(), id: new_process_id.clone(),
wasm_bytes_handle: wasm_path, wasm_bytes_handle: wasm_path,
wit_version: Some(self.process.metadata.wit_version), wit_version: Some(self.process.metadata.wit_version),
@ -276,15 +271,15 @@ impl StandardHost for process::ProcessWasi {
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
Some(wit::Payload { Some(wit::LazyLoadBlob {
mime: None, mime: None,
bytes: bytes.to_vec(), bytes: bytes.to_vec(),
}), }),
) )
.await .await
else { else {
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NameTaken)); return Ok(Err(wit::SpawnError::NameTaken));
}; };
// insert messaging capabilities into requested processes // insert messaging capabilities into requested processes
@ -321,7 +316,7 @@ impl StandardHost for process::ProcessWasi {
wit::Request { wit::Request {
inherit: false, inherit: false,
expects_response: Some(5), // TODO evaluate 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(), .unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
@ -330,16 +325,16 @@ impl StandardHost for process::ProcessWasi {
) )
.await .await
else { else {
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
return Ok(Err(wit::SpawnError::NameTaken)); return Ok(Err(wit::SpawnError::NameTaken));
}; };
// reset payload to what it was // reset blob to what it was
self.process.last_payload = old_last_payload; self.process.last_blob = old_last_blob;
let wit::Message::Response((wit::Response { ipc, .. }, _)) = response else { let wit::Message::Response((wit::Response { body, .. }, _)) = response else {
return Ok(Err(wit::SpawnError::NoFileAtPath)); 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)); return Ok(Err(wit::SpawnError::NoFileAtPath));
}; };
// child processes are always able to Message parent // 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) Ok(self.process.get_next_message_for_process().await)
} }
/// from a process: grab the payload part of the current prompting message. /// from a process: grab the blob part of the current prompting message.
/// if the prompting message did not have a payload, will return None. /// if the prompting message did not have a blob, will return None.
/// will also return None if there is no prompting message. /// will also return None if there is no prompting message.
async fn get_payload(&mut self) -> Result<Option<wit::Payload>> { async fn get_blob(&mut self) -> Result<Option<wit::LazyLoadBlob>> {
Ok(t::en_wit_payload(self.process.last_payload.clone())) Ok(t::en_wit_blob(self.process.last_blob.clone()))
} }
async fn send_request( async fn send_request(
@ -445,11 +440,11 @@ impl StandardHost for process::ProcessWasi {
target: wit::Address, target: wit::Address,
request: wit::Request, request: wit::Request,
context: Option<wit::Context>, context: Option<wit::Context>,
payload: Option<wit::Payload>, blob: Option<wit::LazyLoadBlob>,
) -> Result<()> { ) -> Result<()> {
let id = self let id = self
.process .process
.send_request(None, target, request, context, payload) .send_request(None, target, request, context, blob)
.await; .await;
match id { match id {
Ok(_id) => Ok(()), Ok(_id) => Ok(()),
@ -463,7 +458,7 @@ impl StandardHost for process::ProcessWasi {
wit::Address, wit::Address,
wit::Request, wit::Request,
Option<wit::Context>, Option<wit::Context>,
Option<wit::Payload>, Option<wit::LazyLoadBlob>,
)>, )>,
) -> Result<()> { ) -> Result<()> {
for request in requests { for request in requests {
@ -482,9 +477,9 @@ impl StandardHost for process::ProcessWasi {
async fn send_response( async fn send_response(
&mut self, &mut self,
response: wit::Response, response: wit::Response,
payload: Option<wit::Payload>, blob: Option<wit::LazyLoadBlob>,
) -> Result<()> { ) -> Result<()> {
self.process.send_response(response, payload).await; self.process.send_response(response, blob).await;
Ok(()) Ok(())
} }
@ -492,8 +487,8 @@ impl StandardHost for process::ProcessWasi {
&mut self, &mut self,
target: wit::Address, target: wit::Address,
request: wit::Request, request: wit::Request,
payload: Option<wit::Payload>, blob: Option<wit::LazyLoadBlob>,
) -> Result<Result<(wit::Address, wit::Message), wit::SendError>> { ) -> 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
} }
} }

View File

@ -101,11 +101,11 @@ async fn handle_request(
id, id,
source, source,
message, message,
payload, lazy_load_blob: blob,
.. ..
} = km.clone(); } = km.clone();
let Message::Request(Request { let Message::Request(Request {
ipc, body,
expects_response, expects_response,
metadata, 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, Ok(r) => r,
Err(e) => { Err(e) => {
println!("kv: got invalid Request: {}", e); println!("kv: got invalid Request: {}", e);
@ -136,7 +136,7 @@ async fn handle_request(
) )
.await?; .await?;
let (ipc, bytes) = match &request.action { let (body, bytes) = match &request.action {
KvAction::Open => { KvAction::Open => {
// handled in check_caps. // handled in check_caps.
(serde_json::to_vec(&KvResponse::Ok).unwrap(), None) (serde_json::to_vec(&KvResponse::Ok).unwrap(), None)
@ -184,15 +184,15 @@ async fn handle_request(
} }
Some(db) => db, Some(db) => db,
}; };
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(KvError::InputError { return Err(KvError::InputError {
error: "no payload".into(), error: "no blob".into(),
}); });
}; };
match tx_id { match tx_id {
None => { None => {
db.put(key, payload.bytes)?; db.put(key, blob.bytes)?;
} }
Some(tx_id) => { Some(tx_id) => {
let mut tx = match txs.get_mut(&tx_id) { let mut tx = match txs.get_mut(&tx_id) {
@ -201,7 +201,7 @@ async fn handle_request(
} }
Some(tx) => tx, 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(); let tx = db.transaction();
for (action, payload) in txs { for (action, blob) in txs {
match action { match action {
KvAction::Set { key, .. } => { KvAction::Set { key, .. } => {
if let Some(payload) = payload { if let Some(blob) = blob {
tx.put(&key, &payload)?; tx.put(&key, &blob)?;
} }
} }
KvAction::Delete { key, .. } => { KvAction::Delete { key, .. } => {
@ -297,13 +297,13 @@ async fn handle_request(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc, body,
metadata, metadata,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: bytes.map(|bytes| Payload { lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
mime: Some("application/octet-stream".into()), mime: Some("application/octet-stream".into()),
bytes, bytes,
}), }),
@ -316,7 +316,7 @@ async fn handle_request(
verbosity: 2, verbosity: 2,
content: format!( content: format!(
"kv: not sending response: {:?}", "kv: not sending response: {:?}",
serde_json::from_slice::<KvResponse>(&ipc) serde_json::from_slice::<KvResponse>(&body)
), ),
}) })
.await .await
@ -497,13 +497,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: KvError) -> K
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&KvResponse::Err { error: error }).unwrap(), body: serde_json::to_vec(&KvResponse::Err { error: error }).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
} }
} }

View File

@ -507,11 +507,11 @@ async fn main() {
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(), body: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
}) })
.await; .await;

View File

@ -855,12 +855,12 @@ async fn handle_local_message(
print_tx: &PrintSender, print_tx: &PrintSender,
) -> Result<()> { ) -> Result<()> {
print_debug(print_tx, "net: handling local message").await; print_debug(print_tx, "net: handling local message").await;
let ipc = match km.message { let body = match km.message {
Message::Request(ref request) => &request.ipc, Message::Request(ref request) => &request.body,
Message::Response((response, _context)) => { Message::Response((response, _context)) => {
// these are received as a router, when we send ConnectionRequests // these are received as a router, when we send ConnectionRequests
// to a node we do routing for. // 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(_)) => { Ok(NetResponses::Accepted(_)) => {
// TODO anything here? // TODO anything here?
} }
@ -880,7 +880,7 @@ async fn handle_local_message(
}; };
if km.source.node != our.name { 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 { match act {
NetActions::QnsBatchUpdate(_) | NetActions::QnsUpdate(_) => { NetActions::QnsBatchUpdate(_) | NetActions::QnsUpdate(_) => {
// for now, we don't get these from remote. // for now, we don't get these from remote.
@ -922,14 +922,14 @@ async fn handle_local_message(
id: km.id, id: km.id,
source: Address { source: Address {
node: our.name.clone(), 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), target: km.rsvp.unwrap_or(km.source),
rsvp: None, rsvp: None,
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: rmp_serde::to_vec( body: rmp_serde::to_vec(
&res.unwrap_or(NetResponses::Rejected(from)), &res.unwrap_or(NetResponses::Rejected(from)),
)?, )?,
metadata: None, metadata: None,
@ -937,7 +937,7 @@ async fn handle_local_message(
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await?; .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 // 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 // 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(()) Ok(())
} else { } else {
// available commands: "peers", "pki", "names", "diagnostics" // available commands: "peers", "pki", "names", "diagnostics"
// first parse as raw string, then deserialize to NetActions object // first parse as raw string, then deserialize to NetActions object
let mut printout = String::new(); let mut printout = String::new();
match std::str::from_utf8(ipc) { match std::str::from_utf8(body) {
Ok("peers") => { Ok("peers") => {
printout.push_str(&format!( 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(_)) => { Ok(NetActions::ConnectionRequest(_)) => {
// we shouldn't receive these from ourselves. // 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(()); return Ok(());
} }
} }

View File

@ -215,21 +215,21 @@ pub async fn create_passthrough(
id: rand::random(), id: rand::random(),
source: Address { source: Address {
node: our.name.clone(), node: our.name.clone(),
process: ProcessId::from_str("net:sys:nectar").unwrap(), process: ProcessId::new(Some("net"), "sys", "nectar"),
}, },
target: Address { target: Address {
node: to_name.clone(), node: to_name.clone(),
process: ProcessId::from_str("net:sys:nectar").unwrap(), process: ProcessId::new(Some("net"), "sys", "nectar"),
}, },
rsvp: None, rsvp: None,
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: Some(5), 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, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
})?; })?;
return Ok(( return Ok((
@ -449,7 +449,7 @@ pub async fn error_offline(km: KernelMessage, network_error_tx: &NetworkErrorSen
kind: SendErrorKind::Offline, kind: SendErrorKind::Offline,
target: km.target, target: km.target,
message: km.message, message: km.message,
payload: km.payload, lazy_load_blob: km.lazy_load_blob,
}, },
}) })
.await?; .await?;
@ -466,7 +466,7 @@ fn strip_0x(s: &str) -> String {
pub async fn parse_hello_message( pub async fn parse_hello_message(
our: &Identity, our: &Identity,
km: &KernelMessage, km: &KernelMessage,
ipc: &[u8], body: &[u8],
kernel_message_tx: &MessageSender, kernel_message_tx: &MessageSender,
print_tx: &PrintSender, print_tx: &PrintSender,
) -> Result<()> { ) -> Result<()> {
@ -476,7 +476,7 @@ pub async fn parse_hello_message(
content: format!( content: format!(
"\x1b[3;32m{}: {}\x1b[0m", "\x1b[3;32m{}: {}\x1b[0m",
km.source.node, km.source.node,
std::str::from_utf8(ipc).unwrap_or("!!message parse error!!") std::str::from_utf8(body).unwrap_or("!!message parse error!!")
), ),
}) })
.await?; .await?;
@ -485,20 +485,20 @@ pub async fn parse_hello_message(
id: km.id, id: km.id,
source: Address { source: Address {
node: our.name.clone(), 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(), target: km.rsvp.as_ref().unwrap_or(&km.source).clone(),
rsvp: None, rsvp: None,
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: "delivered".as_bytes().to_vec(), body: "delivered".as_bytes().to_vec(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await?; .await?;
Ok(()) Ok(())

View File

@ -121,11 +121,11 @@ async fn handle_request(
id, id,
source, source,
message, message,
payload, lazy_load_blob: blob,
.. ..
} = km.clone(); } = km.clone();
let Message::Request(Request { let Message::Request(Request {
ipc, body,
expects_response, expects_response,
metadata, 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, Ok(r) => r,
Err(e) => { Err(e) => {
println!("sqlite: got invalid Request: {}", e); println!("sqlite: got invalid Request: {}", e);
@ -156,7 +156,7 @@ async fn handle_request(
) )
.await?; .await?;
let (ipc, bytes) = match request.action { let (body, bytes) = match request.action {
SqliteAction::Open => { SqliteAction::Open => {
// handled in check_caps // handled in check_caps
(serde_json::to_vec(&SqliteResponse::Ok).unwrap(), None) (serde_json::to_vec(&SqliteResponse::Ok).unwrap(), None)
@ -182,7 +182,7 @@ async fn handle_request(
return Err(SqliteError::NotAReadKeyword.into()); return Err(SqliteError::NotAReadKeyword.into());
} }
let parameters = get_json_params(payload)?; let parameters = get_json_params(blob)?;
let mut statement = db.prepare(&query)?; let mut statement = db.prepare(&query)?;
let column_names: Vec<String> = statement let column_names: Vec<String> = statement
@ -238,7 +238,7 @@ async fn handle_request(
return Err(SqliteError::NotAWriteKeyword.into()); return Err(SqliteError::NotAWriteKeyword.into());
} }
let parameters = get_json_params(payload)?; let parameters = get_json_params(blob)?;
match tx_id { match tx_id {
Some(tx_id) => { Some(tx_id) => {
@ -319,13 +319,13 @@ async fn handle_request(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc, body,
metadata, metadata,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: bytes.map(|bytes| Payload { lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
mime: Some("application/octet-stream".into()), mime: Some("application/octet-stream".into()),
bytes, bytes,
}), }),
@ -338,7 +338,7 @@ async fn handle_request(
verbosity: 2, verbosity: 2,
content: format!( content: format!(
"sqlite: not sending response: {:?}", "sqlite: not sending response: {:?}",
serde_json::from_slice::<SqliteResponse>(&ipc) serde_json::from_slice::<SqliteResponse>(&body)
), ),
}) })
.await .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> { fn get_json_params(blob: Option<LazyLoadBlob>) -> Result<Vec<SqlValue>, SqliteError> {
match payload { match blob {
None => Ok(vec![]), 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 Ok(serde_json::Value::Array(vec)) => vec
.iter() .iter()
.map(|value| json_to_sqlite(value)) .map(|value| json_to_sqlite(value))
@ -567,13 +567,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: SqliteError)
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&SqliteResponse::Err { error: error }).unwrap(), body: serde_json::to_vec(&SqliteResponse::Err { error: error }).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
} }
} }
impl ToSql for SqlValue { impl ToSql for SqlValue {

View File

@ -141,12 +141,12 @@ async fn handle_request(
source, source,
rsvp, rsvp,
message, message,
payload, lazy_load_blob: blob,
.. ..
} = kernel_message; } = kernel_message;
let Message::Request(Request { let Message::Request(Request {
expects_response, expects_response,
ipc, body,
metadata, // for kernel metadata, // for kernel
.. ..
}) = message }) = 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, Ok(r) => r,
Err(e) => { Err(e) => {
return Err(StateError::BadJson { 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) => { StateAction::SetState(process_id) => {
let key = process_to_vec(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 { return Err(StateError::BadBytes {
action: "SetState".into(), action: "SetState".into(),
}); });
}; };
db.put(key, &payload.bytes) db.put(key, &blob.bytes)
.map_err(|e| StateError::RocksDBError { .map_err(|e| StateError::RocksDBError {
action: "SetState".into(), action: "SetState".into(),
error: e.to_string(), error: e.to_string(),
@ -259,13 +259,13 @@ async fn handle_request(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc, body,
metadata, metadata,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: bytes.map(|bytes| Payload { lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
mime: Some("application/octet-stream".into()), mime: Some("application/octet-stream".into()),
bytes, bytes,
}), }),
@ -299,7 +299,7 @@ async fn bootstrap(
let k_cap = Capability { let k_cap = Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str("kernel:sys:nectar").unwrap(), process: ProcessId::new(Some("kernel"), "sys", "nectar"),
}, },
params: "\"messaging\"".into(), params: "\"messaging\"".into(),
}; };
@ -308,7 +308,7 @@ async fn bootstrap(
let n_cap = Capability { let n_cap = Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str("net:sys:nectar").unwrap(), process: ProcessId::new(Some("net"), "sys", "nectar"),
}, },
params: "\"messaging\"".into(), params: "\"messaging\"".into(),
}; };
@ -336,7 +336,7 @@ async fn bootstrap(
// finally, save runtime modules in state map as well, somewhat fakely // finally, save runtime modules in state map as well, somewhat fakely
// special cases for kernel and net // special cases for kernel and net
process_map process_map
.entry(ProcessId::from_str("kernel:sys:nectar").unwrap()) .entry(ProcessId::new(Some("kernel"), "sys", "nectar"))
.or_insert(PersistedProcess { .or_insert(PersistedProcess {
wasm_bytes_handle: "".into(), wasm_bytes_handle: "".into(),
wit_version: None, wit_version: None,
@ -345,7 +345,7 @@ async fn bootstrap(
public: false, public: false,
}); });
process_map process_map
.entry(ProcessId::from_str("net:sys:nectar").unwrap()) .entry(ProcessId::new(Some("net"), "sys", "nectar"))
.or_insert(PersistedProcess { .or_insert(PersistedProcess {
wasm_bytes_handle: "".into(), wasm_bytes_handle: "".into(),
wit_version: None, wit_version: None,
@ -505,7 +505,7 @@ async fn bootstrap(
serde_json::Value::String(process_name) => Capability { serde_json::Value::String(process_name) => Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str(process_name).unwrap(), process: process_name.parse().unwrap(),
}, },
params: "\"messaging\"".into(), params: "\"messaging\"".into(),
}, },
@ -515,10 +515,11 @@ async fn bootstrap(
Capability { Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str( process: process_name
process_name.as_str().unwrap(), .as_str()
) .unwrap()
.unwrap(), .parse()
.unwrap(),
}, },
params: params.to_string(), params: params.to_string(),
} }
@ -660,12 +661,12 @@ async fn bootstrap(
for value in to_grant { for value in to_grant {
match value { match value {
serde_json::Value::String(process_name) => { 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) { if let Some(process) = process_map.get_mut(&parsed_process_id) {
let cap = Capability { let cap = Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str(&our_process_id).unwrap(), process: our_process_id.parse().unwrap(),
}, },
params: "\"messaging\"".into(), params: "\"messaging\"".into(),
}; };
@ -678,7 +679,7 @@ async fn bootstrap(
serde_json::Value::Object(map) => { serde_json::Value::Object(map) => {
if let Some(process_name) = map.get("process") { if let Some(process_name) = map.get("process") {
if let Ok(parsed_process_id) = 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(params) = map.get("params") {
if let Some(process) = if let Some(process) =
@ -687,8 +688,7 @@ async fn bootstrap(
let cap = Capability { let cap = Capability {
issuer: Address { issuer: Address {
node: our_name.to_string(), node: our_name.to_string(),
process: ProcessId::from_str(&our_process_id) process: our_process_id.parse().unwrap(),
.unwrap(),
}, },
params: params.to_string(), params: params.to_string(),
}; };
@ -759,13 +759,13 @@ fn make_error_message(our_name: String, km: &KernelMessage, error: StateError) -
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&StateResponse::Err(error)).unwrap(), body: serde_json::to_vec(&StateResponse::Err(error)).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
} }
} }

View File

@ -602,11 +602,11 @@ pub async fn terminal(
message: Message::Request(Request { message: Message::Request(Request {
inherit: false, inherit: false,
expects_response: None, expects_response: None,
ipc: command.into_bytes(), body: command.into_bytes(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}), }),
payload: None, lazy_load_blob: None,
} }
).await.expect("terminal: couldn't execute command!"); ).await.expect("terminal: couldn't execute command!");
}, },

View File

@ -39,7 +39,7 @@ pub async fn timer_service(
// we only handle Requests which contain a little-endian u64 as IPC, // we only handle Requests which contain a little-endian u64 as IPC,
// except for a special "debug" message, which prints the current state // except for a special "debug" message, which prints the current state
let Message::Request(req) = km.message else { continue }; 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 { let _ = print_tx.send(Printout {
verbosity: 0, verbosity: 0,
content: format!("timer service active timers ({}):", timer_map.timers.len()), content: format!("timer service active timers ({}):", timer_map.timers.len()),
@ -52,7 +52,7 @@ pub async fn timer_service(
} }
continue 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); let timer_millis = u64::from_le_bytes(bytes);
// if the timer is set to pop in 0 millis, we immediately respond // if the timer is set to pop in 0 millis, we immediately respond
// otherwise, store in our persisted map, and spawn a task that // 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(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: vec![], body: vec![],
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
}) })
.await; .await;
} }

View File

@ -54,7 +54,7 @@ impl<'a> Deserialize<'a> for ProcessId {
D: serde::de::Deserializer<'a>, D: serde::de::Deserializer<'a>,
{ {
let s = String::deserialize(deserializer)?; 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(), 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 // split string on colons into 2 segments
let mut segments = input.split(':'); let mut segments = input.split(':');
let package_name = segments let package_name = segments
@ -92,12 +109,6 @@ impl PackageId {
publisher_node, publisher_node,
}) })
} }
pub fn _package(&self) -> &str {
&self.package_name
}
pub fn _publisher(&self) -> &str {
&self.publisher_node
}
} }
impl std::fmt::Display for PackageId { impl std::fmt::Display for PackageId {
@ -119,30 +130,6 @@ impl ProcessId {
publisher_node: publisher_node.into(), 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 { pub fn process(&self) -> &str {
&self.process_name &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 { impl From<(&str, &str, &str)> for ProcessId {
fn from(input: (&str, &str, &str)) -> Self { fn from(input: (&str, &str, &str)) -> Self {
ProcessId::new(Some(input.0), input.1, input.2) ProcessId::new(Some(input.0), input.1, input.2)
@ -248,7 +269,33 @@ impl Address {
process: process.into(), 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, // split string on colons into 4 segments,
// first one with @, next 3 with : // first one with @, next 3 with :
let mut name_rest = input.split('@'); 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 { impl Serialize for Address {
@ -317,7 +348,7 @@ impl<'a> Deserialize<'a> for Address {
D: serde::de::Deserializer<'a>, D: serde::de::Deserializer<'a>,
{ {
let s = String::deserialize(deserializer)?; 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)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Payload { pub struct LazyLoadBlob {
pub mime: Option<String>, // MIME type pub mime: Option<String>, // MIME type
pub bytes: Vec<u8>, pub bytes: Vec<u8>,
} }
@ -384,7 +415,7 @@ pub struct Payload {
pub struct Request { pub struct Request {
pub inherit: bool, pub inherit: bool,
pub expects_response: Option<u64>, // number of seconds until timeout 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 metadata: Option<String>, // JSON-string
pub capabilities: Vec<(Capability, Vec<u8>)>, pub capabilities: Vec<(Capability, Vec<u8>)>,
} }
@ -392,7 +423,7 @@ pub struct Request {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Response { pub struct Response {
pub inherit: bool, pub inherit: bool,
pub ipc: Vec<u8>, pub body: Vec<u8>,
pub metadata: Option<String>, // JSON-string pub metadata: Option<String>, // JSON-string
pub capabilities: Vec<(Capability, Vec<u8>)>, pub capabilities: Vec<(Capability, Vec<u8>)>,
} }
@ -424,7 +455,7 @@ pub struct SendError {
pub kind: SendErrorKind, pub kind: SendErrorKind,
pub target: Address, pub target: Address,
pub message: Message, pub message: Message,
pub payload: Option<Payload>, pub lazy_load_blob: Option<LazyLoadBlob>,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -437,7 +468,7 @@ pub enum SendErrorKind {
pub enum OnExit { pub enum OnExit {
None, None,
Restart, Restart,
Requests(Vec<(Address, Request, Option<Payload>)>), Requests(Vec<(Address, Request, Option<LazyLoadBlob>)>),
} }
impl OnExit { impl OnExit {
@ -455,11 +486,11 @@ impl OnExit {
OnExit::Restart => wit::OnExit::Restart, OnExit::Restart => wit::OnExit::Restart,
OnExit::Requests(reqs) => wit::OnExit::Requests( OnExit::Requests(reqs) => wit::OnExit::Requests(
reqs.iter() reqs.iter()
.map(|(address, request, payload)| { .map(|(address, request, blob)| {
( (
address.en_wit(), address.en_wit(),
en_wit_request(request.clone()), en_wit_request(request.clone()),
en_wit_payload(payload.clone()), en_wit_blob(blob.clone()),
) )
}) })
.collect(), .collect(),
@ -473,11 +504,11 @@ impl OnExit {
wit::OnExit::Restart => OnExit::Restart, wit::OnExit::Restart => OnExit::Restart,
wit::OnExit::Requests(reqs) => OnExit::Requests( wit::OnExit::Requests(reqs) => OnExit::Requests(
reqs.into_iter() reqs.into_iter()
.map(|(address, request, payload)| { .map(|(address, request, blob)| {
( (
Address::de_wit(address), Address::de_wit(address),
de_wit_request(request), de_wit_request(request),
de_wit_payload(payload), de_wit_blob(blob),
) )
}) })
.collect(), .collect(),
@ -491,12 +522,12 @@ impl std::fmt::Display for Message {
match self { match self {
Message::Request(request) => write!( Message::Request(request) => write!(
f, 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.inherit,
request.expects_response, 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), Ok(json) => format!("{}", json),
Err(_) => format!("{:?}", request.ipc), Err(_) => format!("{:?}", request.body),
}, },
&request.metadata.as_ref().unwrap_or(&"None".into()), &request.metadata.as_ref().unwrap_or(&"None".into()),
{ {
@ -514,11 +545,11 @@ impl std::fmt::Display for Message {
), ),
Message::Response((response, context)) => write!( Message::Response((response, context)) => write!(
f, 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, 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), Ok(json) => format!("{}", json),
Err(_) => format!("{:?}", response.ipc), Err(_) => format!("{:?}", response.body),
}, },
&response.metadata.as_ref().unwrap_or(&"None".into()), &response.metadata.as_ref().unwrap_or(&"None".into()),
if context.is_none() { if context.is_none() {
@ -554,7 +585,7 @@ pub fn de_wit_request(wit: wit::Request) -> Request {
Request { Request {
inherit: wit.inherit, inherit: wit.inherit,
expects_response: wit.expects_response, expects_response: wit.expects_response,
ipc: wit.ipc, body: wit.body,
metadata: wit.metadata, metadata: wit.metadata,
capabilities: wit capabilities: wit
.capabilities .capabilities
@ -568,7 +599,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
wit::Request { wit::Request {
inherit: request.inherit, inherit: request.inherit,
expects_response: request.expects_response, expects_response: request.expects_response,
ipc: request.ipc, body: request.body,
metadata: request.metadata, metadata: request.metadata,
capabilities: request capabilities: request
.capabilities .capabilities
@ -581,7 +612,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
pub fn de_wit_response(wit: wit::Response) -> Response { pub fn de_wit_response(wit: wit::Response) -> Response {
Response { Response {
inherit: wit.inherit, inherit: wit.inherit,
ipc: wit.ipc, body: wit.body,
metadata: wit.metadata, metadata: wit.metadata,
capabilities: wit capabilities: wit
.capabilities .capabilities
@ -594,7 +625,7 @@ pub fn de_wit_response(wit: wit::Response) -> Response {
pub fn en_wit_response(response: Response) -> wit::Response { pub fn en_wit_response(response: Response) -> wit::Response {
wit::Response { wit::Response {
inherit: response.inherit, inherit: response.inherit,
ipc: response.ipc, body: response.body,
metadata: response.metadata, metadata: response.metadata,
capabilities: response capabilities: response
.capabilities .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 { match wit {
None => None, None => None,
Some(wit) => Some(Payload { Some(wit) => Some(LazyLoadBlob {
mime: wit.mime, mime: wit.mime,
bytes: wit.bytes, 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 { match load {
None => None, None => None,
Some(load) => Some(wit::Payload { Some(load) => Some(wit::LazyLoadBlob {
mime: load.mime, mime: load.mime,
bytes: load.bytes, bytes: load.bytes,
}), }),
@ -661,7 +692,7 @@ pub fn en_wit_send_error(error: SendError) -> wit::SendError {
wit::SendError { wit::SendError {
kind: en_wit_send_error_kind(error.kind), kind: en_wit_send_error_kind(error.kind),
message: en_wit_message(error.message), 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 target: Address,
pub rsvp: Rsvp, pub rsvp: Rsvp,
pub message: Message, pub message: Message,
pub payload: Option<Payload>, pub lazy_load_blob: Option<LazyLoadBlob>,
} }
impl std::fmt::Display for KernelMessage { impl std::fmt::Display for KernelMessage {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( write!(
f, 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.id,
self.source, self.source,
self.target, self.target,
@ -814,7 +845,7 @@ impl std::fmt::Display for KernelMessage {
None => "None".to_string() None => "None".to_string()
}, },
self.message, self.message,
self.payload.is_some(), self.lazy_load_blob.is_some(),
) )
} }
} }
@ -1002,11 +1033,11 @@ pub enum StateError {
RocksDBError { action: String, error: String }, RocksDBError { action: String, error: String },
#[error("kernel_state: startup error")] #[error("kernel_state: startup error")]
StartupError { action: String }, StartupError { action: String },
#[error("kernel_state: bytes payload required for {action}")] #[error("kernel_state: bytes blob required for {action}")]
BadBytes { action: String }, BadBytes { action: String },
#[error("kernel_state: bad request error: {error}")] #[error("kernel_state: bad request error: {error}")]
BadRequest { error: String }, BadRequest { error: String },
#[error("kernel_state: Bad JSON payload: {error}")] #[error("kernel_state: Bad JSON blob: {error}")]
BadJson { error: String }, BadJson { error: String },
#[error("kernel_state: state not found for ProcessId {process_id}")] #[error("kernel_state: state not found for ProcessId {process_id}")]
NotFound { process_id: ProcessId }, NotFound { process_id: ProcessId },
@ -1109,7 +1140,7 @@ pub enum VfsResponse {
pub enum VfsError { pub enum VfsError {
#[error("vfs: No capability for action {action} at path {path}")] #[error("vfs: No capability for action {action} at path {path}")]
NoCap { action: String, path: String }, 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 }, BadBytes { action: String, path: String },
#[error("vfs: bad request error: {error}")] #[error("vfs: bad request error: {error}")]
BadRequest { error: String }, BadRequest { error: String },
@ -1119,7 +1150,7 @@ pub enum VfsError {
IOError { error: String, path: String }, IOError { error: String, path: String },
#[error("vfs: kernel capability channel error: {error}")] #[error("vfs: kernel capability channel error: {error}")]
CapChannelFail { error: String }, CapChannelFail { error: String },
#[error("vfs: Bad JSON payload: {error}")] #[error("vfs: Bad JSON blob: {error}")]
BadJson { error: String }, BadJson { error: String },
#[error("vfs: File not found at path {path}")] #[error("vfs: File not found at path {path}")]
NotFound { path: String }, NotFound { path: String },

View File

@ -97,11 +97,11 @@ async fn handle_request(
id, id,
source, source,
message, message,
payload, lazy_load_blob: blob,
.. ..
} = km.clone(); } = km.clone();
let Message::Request(Request { let Message::Request(Request {
ipc, body,
expects_response, expects_response,
metadata, 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, Ok(r) => r,
Err(e) => { Err(e) => {
println!("vfs: got invalid Request: {}", e); println!("vfs: got invalid Request: {}", e);
@ -142,7 +142,7 @@ async fn handle_request(
} }
// real safe path that the vfs will use // real safe path that the vfs will use
let path = PathBuf::from(format!("{}{}/{}", vfs_path, drive, rest)); let path = PathBuf::from(format!("{}{}/{}", vfs_path, drive, rest));
let (ipc, bytes) = match request.action { let (body, bytes) = match request.action {
VfsAction::CreateDrive => { VfsAction::CreateDrive => {
// handled in check_caps. // handled in check_caps.
(serde_json::to_vec(&VfsResponse::Ok).unwrap(), None) (serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
@ -177,38 +177,38 @@ async fn handle_request(
} }
VfsAction::WriteAt => { VfsAction::WriteAt => {
// doesn't create a file, writes at exact cursor. // doesn't create a file, writes at exact cursor.
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(VfsError::BadRequest { 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 file = open_file(open_files.clone(), path, false, false).await?;
let mut file = file.lock().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) (serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
} }
VfsAction::Write => { VfsAction::Write => {
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(VfsError::BadRequest { return Err(VfsError::BadRequest {
error: "payload needs to exist for Write".into(), error: "blob needs to exist for Write".into(),
}); });
}; };
open_files.remove(&path); open_files.remove(&path);
let file = open_file(open_files.clone(), path, true, true).await?; let file = open_file(open_files.clone(), path, true, true).await?;
let mut file = file.lock().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) (serde_json::to_vec(&VfsResponse::Ok).unwrap(), None)
} }
VfsAction::Append => { VfsAction::Append => {
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(VfsError::BadRequest { 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 file = open_file(open_files.clone(), path, false, false).await?;
let mut file = file.lock().await; let mut file = file.lock().await;
file.seek(SeekFrom::End(0)).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) (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) (serde_json::to_vec(&VfsResponse::Hash(hash)).unwrap(), None)
} }
VfsAction::AddZip => { VfsAction::AddZip => {
let Some(payload) = payload else { let Some(blob) = blob else {
return Err(VfsError::BadRequest { 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 { 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 { if "application/zip" != mime {
return Err(VfsError::BadRequest { 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) { let mut zip = match zip::ZipArchive::new(file) {
Ok(f) => f, Ok(f) => f,
Err(e) => { Err(e) => {
@ -442,13 +442,13 @@ async fn handle_request(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc, body,
metadata, metadata,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: bytes.map(|bytes| Payload { lazy_load_blob: bytes.map(|bytes| LazyLoadBlob {
mime: Some("application/octet-stream".into()), mime: Some("application/octet-stream".into()),
bytes, bytes,
}), }),
@ -462,7 +462,7 @@ async fn handle_request(
verbosity: 2, verbosity: 2,
content: format!( content: format!(
"vfs: not sending response: {:?}", "vfs: not sending response: {:?}",
serde_json::from_slice::<VfsResponse>(&ipc) serde_json::from_slice::<VfsResponse>(&body)
), ),
}) })
.await .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, Ok(id) => id,
Err(e) => { Err(e) => {
return Err(VfsError::ParseError { return Err(VfsError::ParseError {
@ -809,13 +809,13 @@ fn make_error_message(
message: Message::Response(( message: Message::Response((
Response { Response {
inherit: false, inherit: false,
ipc: serde_json::to_vec(&VfsResponse::Err(error)).unwrap(), body: serde_json::to_vec(&VfsResponse::Err(error)).unwrap(),
metadata: None, metadata: None,
capabilities: vec![], capabilities: vec![],
}, },
None, None,
)), )),
payload: None, lazy_load_blob: None,
} }
} }