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

View File

@ -14,11 +14,11 @@ version = "0.2.0"
dependencies = [
"anyhow",
"bincode",
"nectar_process_lib",
"rand",
"serde",
"serde_json",
"sha2",
"uqbar_process_lib",
"wit-bindgen",
]
@ -222,6 +222,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -445,23 +462,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -15,7 +15,7 @@ rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sha2 = "0.10.8"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -62,10 +62,10 @@ version = "0.2.0"
dependencies = [
"anyhow",
"bincode",
"nectar_process_lib",
"rand",
"serde",
"serde_json",
"uqbar_process_lib",
"wit-bindgen",
]
@ -173,6 +173,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -379,23 +396,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -16,7 +16,7 @@ bincode = "1.3.3"
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

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

View File

@ -69,10 +69,10 @@ dependencies = [
"anyhow",
"base64",
"bincode",
"nectar_process_lib",
"pleco",
"serde",
"serde_json",
"uqbar_process_lib",
"url",
"wit-bindgen",
]
@ -283,6 +283,23 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55d0c9dc43dedfd2414deb74ade67687749ef88b1d3482024d4c81d901a7a83"
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
@ -654,23 +671,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -16,7 +16,7 @@ pleco = "0.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
url = "*"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -88,9 +88,9 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"nectar_process_lib",
"serde",
"serde_json",
"uqbar_process_lib",
"wit-bindgen",
]
@ -172,6 +172,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#235f4aae4d8078e86d3114753ed79ccedb947ebe"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -378,23 +395,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -15,7 +15,7 @@ anyhow = "1.0"
bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -1103,6 +1103,24 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#235f4aae4d8078e86d3114753ed79ccedb947ebe"
dependencies = [
"anyhow",
"bincode",
"ethers-core",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
@ -1360,10 +1378,10 @@ dependencies = [
"anyhow",
"bincode",
"hex",
"nectar_process_lib",
"rmp-serde",
"serde",
"serde_json",
"uqbar_process_lib",
"wit-bindgen",
]
@ -2089,24 +2107,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=6228e0f#6228e0fe59c651fed5d3c977e4623e7d404c3c10"
dependencies = [
"anyhow",
"bincode",
"ethers-core",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -20,7 +20,7 @@ hex = "0.4.3"
rmp-serde = "1.1.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6228e0f", features = ["eth"] }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha", features = ["eth"] }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -295,9 +312,9 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"nectar_process_lib",
"serde",
"serde_json",
"uqbar_process_lib",
"wit-bindgen",
]
@ -378,23 +395,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -15,7 +15,7 @@ anyhow = "1.0"
bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -295,10 +312,10 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"nectar_process_lib",
"serde",
"serde_json",
"thiserror",
"uqbar_process_lib",
"wit-bindgen",
]
@ -379,23 +396,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -16,7 +16,7 @@ bincode = "1.3.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

@ -160,6 +160,23 @@ dependencies = [
"unicase",
]
[[package]]
name = "nectar_process_lib"
version = "0.5.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?tag=v0.5.0-alpha#dee786a3bdfbf2a02a1f3fc3ffac0918b0313f6a"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -296,10 +313,10 @@ dependencies = [
"anyhow",
"bincode",
"indexmap",
"nectar_process_lib",
"serde",
"serde_json",
"thiserror",
"uqbar_process_lib",
"wit-bindgen",
]
@ -380,23 +397,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "uqbar_process_lib"
version = "0.4.0"
source = "git+ssh://git@github.com/uqbar-dao/process_lib.git?rev=e72a791#e72a791d6374cfd985e5cdfa7e1a668492fdb88c"
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "url"
version = "2.5.0"

View File

@ -17,7 +17,7 @@ indexmap = "2.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", rev = "6520b95" }
nectar_process_lib = { git = "ssh://git@github.com/uqbar-dao/process_lib.git", tag = "v0.5.0-alpha" }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "efcc759" }
[lib]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -54,7 +54,7 @@ impl<'a> Deserialize<'a> for ProcessId {
D: serde::de::Deserializer<'a>,
{
let s = String::deserialize(deserializer)?;
ProcessId::from_str(&s).map_err(serde::de::Error::custom)
s.parse().map_err(serde::de::Error::custom)
}
}
@ -73,7 +73,24 @@ impl PackageId {
publisher_node: publisher_node.into(),
}
}
pub fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
pub fn _package(&self) -> &str {
&self.package_name
}
pub fn _publisher(&self) -> &str {
&self.publisher_node
}
}
impl std::str::FromStr for PackageId {
type Err = ProcessIdParseError;
/// Attempt to parse a `PackageId` from a string. The string must
/// contain exactly two segments, where segments are strings separated
/// by a colon `:`. The segments cannot themselves contain colons.
/// Please note that while any string without colons will parse successfully
/// to create a `PackageId`, not all strings without colons are actually
/// valid usernames, which the `publisher_node` field of a `PackageId` will
/// always in practice be.
fn from_str(input: &str) -> Result<Self, Self::Err> {
// split string on colons into 2 segments
let mut segments = input.split(':');
let package_name = segments
@ -92,12 +109,6 @@ impl PackageId {
publisher_node,
})
}
pub fn _package(&self) -> &str {
&self.package_name
}
pub fn _publisher(&self) -> &str {
&self.publisher_node
}
}
impl std::fmt::Display for PackageId {
@ -119,30 +130,6 @@ impl ProcessId {
publisher_node: publisher_node.into(),
}
}
pub fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
// split string on colons into 3 segments
let mut segments = input.split(':');
let process_name = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
let package_name = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
let publisher_node = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
if segments.next().is_some() {
return Err(ProcessIdParseError::TooManyColons);
}
Ok(ProcessId {
process_name,
package_name,
publisher_node,
})
}
pub fn process(&self) -> &str {
&self.process_name
}
@ -168,6 +155,40 @@ impl ProcessId {
}
}
impl std::str::FromStr for ProcessId {
type Err = ProcessIdParseError;
/// Attempts to parse a `ProcessId` from a string. To succeed, the string must contain
/// exactly 3 segments, separated by colons `:`. The segments must not contain colons.
/// Please note that while any string without colons will parse successfully
/// to create a `ProcessId`, not all strings without colons are actually
/// valid usernames, which the `publisher_node` field of a `ProcessId` will
/// always in practice be.
fn from_str(input: &str) -> Result<Self, ProcessIdParseError> {
// split string on colons into 3 segments
let mut segments = input.split(':');
let process_name = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
let package_name = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
let publisher_node = segments
.next()
.ok_or(ProcessIdParseError::MissingField)?
.to_string();
if segments.next().is_some() {
return Err(ProcessIdParseError::TooManyColons);
}
Ok(ProcessId {
process_name,
package_name,
publisher_node,
})
}
}
impl From<(&str, &str, &str)> for ProcessId {
fn from(input: (&str, &str, &str)) -> Self {
ProcessId::new(Some(input.0), input.1, input.2)
@ -248,7 +269,33 @@ impl Address {
process: process.into(),
}
}
pub fn from_str(input: &str) -> Result<Self, AddressParseError> {
pub fn en_wit(&self) -> wit::Address {
wit::Address {
node: self.node.clone(),
process: self.process.en_wit(),
}
}
pub fn de_wit(wit: wit::Address) -> Address {
Address {
node: wit.node,
process: ProcessId {
process_name: wit.process.process_name,
package_name: wit.process.package_name,
publisher_node: wit.process.publisher_node,
},
}
}
}
impl std::str::FromStr for Address {
type Err = AddressParseError;
/// Attempt to parse an `Address` from a string. The formatting structure for
/// an Address is `node@process_name:package_name:publisher_node`.
///
/// TODO: clarify if `@` can be present in process name / package name / publisher name
///
/// TODO: ensure `:` cannot sneak into first segment
fn from_str(input: &str) -> Result<Self, AddressParseError> {
// split string on colons into 4 segments,
// first one with @, next 3 with :
let mut name_rest = input.split('@');
@ -284,22 +331,6 @@ impl Address {
},
})
}
pub fn en_wit(&self) -> wit::Address {
wit::Address {
node: self.node.clone(),
process: self.process.en_wit(),
}
}
pub fn de_wit(wit: wit::Address) -> Address {
Address {
node: wit.node,
process: ProcessId {
process_name: wit.process.process_name,
package_name: wit.process.package_name,
publisher_node: wit.process.publisher_node,
},
}
}
}
impl Serialize for Address {
@ -317,7 +348,7 @@ impl<'a> Deserialize<'a> for Address {
D: serde::de::Deserializer<'a>,
{
let s = String::deserialize(deserializer)?;
Address::from_str(&s).map_err(serde::de::Error::custom)
s.parse().map_err(serde::de::Error::custom)
}
}
@ -375,7 +406,7 @@ impl std::error::Error for AddressParseError {
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Payload {
pub struct LazyLoadBlob {
pub mime: Option<String>, // MIME type
pub bytes: Vec<u8>,
}
@ -384,7 +415,7 @@ pub struct Payload {
pub struct Request {
pub inherit: bool,
pub expects_response: Option<u64>, // number of seconds until timeout
pub ipc: Vec<u8>,
pub body: Vec<u8>,
pub metadata: Option<String>, // JSON-string
pub capabilities: Vec<(Capability, Vec<u8>)>,
}
@ -392,7 +423,7 @@ pub struct Request {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Response {
pub inherit: bool,
pub ipc: Vec<u8>,
pub body: Vec<u8>,
pub metadata: Option<String>, // JSON-string
pub capabilities: Vec<(Capability, Vec<u8>)>,
}
@ -424,7 +455,7 @@ pub struct SendError {
pub kind: SendErrorKind,
pub target: Address,
pub message: Message,
pub payload: Option<Payload>,
pub lazy_load_blob: Option<LazyLoadBlob>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -437,7 +468,7 @@ pub enum SendErrorKind {
pub enum OnExit {
None,
Restart,
Requests(Vec<(Address, Request, Option<Payload>)>),
Requests(Vec<(Address, Request, Option<LazyLoadBlob>)>),
}
impl OnExit {
@ -455,11 +486,11 @@ impl OnExit {
OnExit::Restart => wit::OnExit::Restart,
OnExit::Requests(reqs) => wit::OnExit::Requests(
reqs.iter()
.map(|(address, request, payload)| {
.map(|(address, request, blob)| {
(
address.en_wit(),
en_wit_request(request.clone()),
en_wit_payload(payload.clone()),
en_wit_blob(blob.clone()),
)
})
.collect(),
@ -473,11 +504,11 @@ impl OnExit {
wit::OnExit::Restart => OnExit::Restart,
wit::OnExit::Requests(reqs) => OnExit::Requests(
reqs.into_iter()
.map(|(address, request, payload)| {
.map(|(address, request, blob)| {
(
Address::de_wit(address),
de_wit_request(request),
de_wit_payload(payload),
de_wit_blob(blob),
)
})
.collect(),
@ -491,12 +522,12 @@ impl std::fmt::Display for Message {
match self {
Message::Request(request) => write!(
f,
"Request(\n inherit: {},\n expects_response: {:?},\n ipc: {},\n metadata: {}\n capabilities: {}\n )",
"Request(\n inherit: {},\n expects_response: {:?},\n body: {},\n metadata: {}\n capabilities: {}\n )",
request.inherit,
request.expects_response,
match serde_json::from_slice::<serde_json::Value>(&request.ipc) {
match serde_json::from_slice::<serde_json::Value>(&request.body) {
Ok(json) => format!("{}", json),
Err(_) => format!("{:?}", request.ipc),
Err(_) => format!("{:?}", request.body),
},
&request.metadata.as_ref().unwrap_or(&"None".into()),
{
@ -514,11 +545,11 @@ impl std::fmt::Display for Message {
),
Message::Response((response, context)) => write!(
f,
"Response(\n inherit: {},\n ipc: {},\n metadata: {},\n context: {},\n capabilities: {}\n )",
"Response(\n inherit: {},\n body: {},\n metadata: {},\n context: {},\n capabilities: {}\n )",
response.inherit,
match serde_json::from_slice::<serde_json::Value>(&response.ipc) {
match serde_json::from_slice::<serde_json::Value>(&response.body) {
Ok(json) => format!("{}", json),
Err(_) => format!("{:?}", response.ipc),
Err(_) => format!("{:?}", response.body),
},
&response.metadata.as_ref().unwrap_or(&"None".into()),
if context.is_none() {
@ -554,7 +585,7 @@ pub fn de_wit_request(wit: wit::Request) -> Request {
Request {
inherit: wit.inherit,
expects_response: wit.expects_response,
ipc: wit.ipc,
body: wit.body,
metadata: wit.metadata,
capabilities: wit
.capabilities
@ -568,7 +599,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
wit::Request {
inherit: request.inherit,
expects_response: request.expects_response,
ipc: request.ipc,
body: request.body,
metadata: request.metadata,
capabilities: request
.capabilities
@ -581,7 +612,7 @@ pub fn en_wit_request(request: Request) -> wit::Request {
pub fn de_wit_response(wit: wit::Response) -> Response {
Response {
inherit: wit.inherit,
ipc: wit.ipc,
body: wit.body,
metadata: wit.metadata,
capabilities: wit
.capabilities
@ -594,7 +625,7 @@ pub fn de_wit_response(wit: wit::Response) -> Response {
pub fn en_wit_response(response: Response) -> wit::Response {
wit::Response {
inherit: response.inherit,
ipc: response.ipc,
body: response.body,
metadata: response.metadata,
capabilities: response
.capabilities
@ -604,20 +635,20 @@ pub fn en_wit_response(response: Response) -> wit::Response {
}
}
pub fn de_wit_payload(wit: Option<wit::Payload>) -> Option<Payload> {
pub fn de_wit_blob(wit: Option<wit::LazyLoadBlob>) -> Option<LazyLoadBlob> {
match wit {
None => None,
Some(wit) => Some(Payload {
Some(wit) => Some(LazyLoadBlob {
mime: wit.mime,
bytes: wit.bytes,
}),
}
}
pub fn en_wit_payload(load: Option<Payload>) -> Option<wit::Payload> {
pub fn en_wit_blob(load: Option<LazyLoadBlob>) -> Option<wit::LazyLoadBlob> {
match load {
None => None,
Some(load) => Some(wit::Payload {
Some(load) => Some(wit::LazyLoadBlob {
mime: load.mime,
bytes: load.bytes,
}),
@ -661,7 +692,7 @@ pub fn en_wit_send_error(error: SendError) -> wit::SendError {
wit::SendError {
kind: en_wit_send_error_kind(error.kind),
message: en_wit_message(error.message),
payload: en_wit_payload(error.payload),
lazy_load_blob: en_wit_blob(error.lazy_load_blob),
}
}
@ -798,14 +829,14 @@ pub struct KernelMessage {
pub target: Address,
pub rsvp: Rsvp,
pub message: Message,
pub payload: Option<Payload>,
pub lazy_load_blob: Option<LazyLoadBlob>,
}
impl std::fmt::Display for KernelMessage {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{{\n id: {},\n source: {},\n target: {},\n rsvp: {},\n message: {},\n payload: {},\n}}",
"{{\n id: {},\n source: {},\n target: {},\n rsvp: {},\n message: {},\n blob: {},\n}}",
self.id,
self.source,
self.target,
@ -814,7 +845,7 @@ impl std::fmt::Display for KernelMessage {
None => "None".to_string()
},
self.message,
self.payload.is_some(),
self.lazy_load_blob.is_some(),
)
}
}
@ -1002,11 +1033,11 @@ pub enum StateError {
RocksDBError { action: String, error: String },
#[error("kernel_state: startup error")]
StartupError { action: String },
#[error("kernel_state: bytes payload required for {action}")]
#[error("kernel_state: bytes blob required for {action}")]
BadBytes { action: String },
#[error("kernel_state: bad request error: {error}")]
BadRequest { error: String },
#[error("kernel_state: Bad JSON payload: {error}")]
#[error("kernel_state: Bad JSON blob: {error}")]
BadJson { error: String },
#[error("kernel_state: state not found for ProcessId {process_id}")]
NotFound { process_id: ProcessId },
@ -1109,7 +1140,7 @@ pub enum VfsResponse {
pub enum VfsError {
#[error("vfs: No capability for action {action} at path {path}")]
NoCap { action: String, path: String },
#[error("vfs: Bytes payload required for {action} at path {path}")]
#[error("vfs: Bytes blob required for {action} at path {path}")]
BadBytes { action: String, path: String },
#[error("vfs: bad request error: {error}")]
BadRequest { error: String },
@ -1119,7 +1150,7 @@ pub enum VfsError {
IOError { error: String, path: String },
#[error("vfs: kernel capability channel error: {error}")]
CapChannelFail { error: String },
#[error("vfs: Bad JSON payload: {error}")]
#[error("vfs: Bad JSON blob: {error}")]
BadJson { error: String },
#[error("vfs: File not found at path {path}")]
NotFound { path: String },

View File

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