switch all modules to uqbar@0.2.0

This commit is contained in:
dr-frmr 2023-10-26 16:19:41 -04:00
parent 4693b5c14f
commit d40989f8f7
No known key found for this signature in database
17 changed files with 1788 additions and 2077 deletions

View File

@ -195,10 +195,7 @@ impl Guest for Component {
};
match message {
Message::Request(req) => {
let Some(ref ipc) = req.ipc else {
continue;
};
match &serde_json::from_str::<Req>(ipc) {
match &serde_json::from_slice::<Req>(&req.ipc) {
Ok(Req::LocalRequest(local_request)) => {
match handle_local_request(&our, &source, local_request, &mut state) {
Ok(None) => continue,
@ -207,7 +204,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&resp).unwrap()),
ipc: serde_json::to_vec(&resp).unwrap(),
metadata: None,
},
None,
@ -230,7 +227,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&resp).unwrap()),
ipc: serde_json::to_vec(&resp).unwrap(),
metadata: None,
},
None,
@ -270,15 +267,13 @@ impl Guest for Component {
&Request {
inherit: true, // will inherit payload!
expects_response: None,
ipc: Some(
serde_json::to_string(&Req::LocalRequest(
LocalRequest::NewPackage {
package: package_id,
mirror: true,
},
))
.unwrap(),
),
ipc: serde_json::to_vec(&Req::LocalRequest(
LocalRequest::NewPackage {
package: package_id,
mirror: true,
},
))
.unwrap(),
metadata: None,
},
None,
@ -287,22 +282,19 @@ impl Guest for Component {
}
}
Ok(Req::FTWorkerCommand(_)) => {
spawn_receive_transfer(&our, ipc);
spawn_receive_transfer(&our, &req.ipc);
}
e => {
print_to_terminal(
0,
&format!("app store bad request: {}, error {:?}", ipc, e),
&format!("app store bad request: {:?}, error {:?}", req.ipc, e),
);
continue;
}
}
}
Message::Response((response, context)) => {
let Some(ref ipc) = response.ipc else {
continue;
};
match &serde_json::from_str::<Resp>(ipc) {
match &serde_json::from_slice::<Resp>(&response.ipc) {
Ok(Resp::RemoteResponse(remote_response)) => match remote_response {
RemoteResponse::DownloadApproved => {
print_to_terminal(
@ -318,7 +310,7 @@ impl Guest for Component {
}
},
Ok(Resp::FTWorkerResult(ft_worker_result)) => {
let Ok(context) = serde_json::from_str::<FileTransferContext>(&context.unwrap_or_default()) else {
let Ok(context) = serde_json::from_slice::<FileTransferContext>(&context.unwrap_or_default()) else {
print_to_terminal(0, "file_transfer: got weird local request");
continue;
};
@ -347,7 +339,10 @@ impl Guest for Component {
e => {
print_to_terminal(
0,
&format!("app store bad response: {}, error {:?}", ipc, e),
&format!(
"app store bad response: {:?}, error {:?}",
response.ipc, e
),
);
continue;
}
@ -385,10 +380,10 @@ fn handle_local_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::New,
})?),
})?,
None,
None,
5,
@ -399,13 +394,13 @@ fn handle_local_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
true,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::Add {
full_path: package.to_string(),
entry_type: kt::AddEntryType::ZipArchive,
},
})?),
})?,
None,
Some(&payload),
5,
@ -416,13 +411,13 @@ fn handle_local_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
true,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::Add {
full_path: format!("/{}.zip", package.to_string()),
entry_type: kt::AddEntryType::NewFile,
},
})?),
})?,
None,
Some(&payload),
5,
@ -431,10 +426,10 @@ fn handle_local_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::GetEntry("/metadata.json".into()),
})?),
})?,
None,
None,
5,
@ -473,18 +468,13 @@ fn handle_local_request(
process: our.process.clone(),
},
true,
Some(serde_json::to_string(&RemoteRequest::Download(
package.clone(),
))?),
serde_json::to_vec(&RemoteRequest::Download(package.clone()))?,
None,
None,
5,
) {
Ok((_source, Message::Response((resp, _context)))) => {
let Some(ipc) = resp.ipc else {
return Err(anyhow::anyhow!("no ipc in response"))
};
let resp = serde_json::from_str::<Resp>(&ipc)?;
let resp = serde_json::from_slice::<Resp>(&resp.ipc)?;
match resp {
Resp::RemoteResponse(RemoteResponse::DownloadApproved) => {
state.requested_packages.insert(package.clone());
@ -505,10 +495,10 @@ fn handle_local_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::GetEntry("/manifest.json".into()),
})?),
})?,
None,
None,
5,
@ -528,19 +518,19 @@ fn handle_local_request(
let (_, hash_response) = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::GetHash(path.clone()),
})?),
})?,
None,
None,
5,
)?;
let Message::Response((Response { ipc: Some(ipc), .. }, _)) = hash_response else {
let Message::Response((Response { ipc, .. }, _)) = hash_response else {
return Err(anyhow::anyhow!("bad vfs response"));
};
let kt::VfsResponse::GetHash(Some(hash)) = serde_json::from_str(&ipc)? else {
let kt::VfsResponse::GetHash(Some(hash)) = serde_json::from_slice(&ipc)? else {
return Err(anyhow::anyhow!("no hash in vfs"));
};
@ -607,9 +597,9 @@ fn handle_local_request(
process: ProcessId::from_str("kernel:sys:uqbar")?,
},
false,
Some(serde_json::to_string(&kt::KernelCommand::KillProcess(
kt::ProcessId::de_wit(parsed_new_process_id.clone()),
))?),
serde_json::to_vec(&kt::KernelCommand::KillProcess(kt::ProcessId::de_wit(
parsed_new_process_id.clone(),
)))?,
None,
None,
None,
@ -620,10 +610,10 @@ fn handle_local_request(
let (_, _bytes_response) = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::GetEntry(path),
})?),
})?,
None,
None,
5,
@ -639,13 +629,13 @@ fn handle_local_request(
process: ProcessId::from_str("kernel:sys:uqbar")?,
},
false,
Some(serde_json::to_string(&kt::KernelCommand::StartProcess {
serde_json::to_vec(&kt::KernelCommand::StartProcess {
id: kt::ProcessId::de_wit(parsed_new_process_id),
wasm_bytes_handle: hash,
on_panic: entry.on_panic,
initial_capabilities,
public: entry.public,
})?),
})?,
None,
Some(&payload),
5,
@ -687,10 +677,10 @@ fn handle_remote_request(
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: package.to_string(),
action: kt::VfsAction::GetEntry(file_name.clone()),
})?),
})?,
None,
None,
5,

View File

@ -76,33 +76,29 @@ pub fn spawn_transfer(
&Request {
inherit: !payload_or_inherit.is_some(),
expects_response: Some(61),
ipc: Some(
serde_json::to_string(&FTWorkerCommand::Send {
target: to_addr.to_string(),
file_name: file_name.into(),
timeout: 60,
})
.unwrap(),
),
metadata: None,
},
Some(
&serde_json::to_string(&FileTransferContext {
ipc: serde_json::to_vec(&FTWorkerCommand::Send {
target: to_addr.to_string(),
file_name: file_name.into(),
file_size: match &payload_or_inherit {
Some(p) => Some(p.bytes.len() as u64),
None => None, // TODO
},
start_time: std::time::SystemTime::now(),
timeout: 60,
})
.unwrap(),
),
metadata: None,
},
Some(&serde_json::to_vec(&FileTransferContext {
file_name: file_name.into(),
file_size: match &payload_or_inherit {
Some(p) => Some(p.bytes.len() as u64),
None => None, // TODO
},
start_time: std::time::SystemTime::now(),
})
.unwrap()),
payload_or_inherit.as_ref(),
);
}
pub fn spawn_receive_transfer(our: &Address, ipc: &str) {
let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_str(ipc) else {
pub fn spawn_receive_transfer(our: &Address, ipc: &[u8]) {
let Ok(FTWorkerCommand::Receive { transfer_id, .. }) = serde_json::from_slice(ipc) else {
print_to_terminal(0, "file_transfer: got weird request");
return;
};
@ -125,7 +121,7 @@ pub fn spawn_receive_transfer(our: &Address, ipc: &str) {
&Request {
inherit: true,
expects_response: None,
ipc: Some(ipc.to_string()),
ipc: ipc.to_vec(),
metadata: None,
},
None,

View File

@ -25,10 +25,8 @@ impl Guest for Component {
panic!("ft_worker: got bad init message");
};
let command = serde_json::from_str::<FTWorkerCommand>(
&req.ipc.expect("ft_worker: got empty init message"),
)
.expect("ft_worker: got unparseable init message");
let command = serde_json::from_slice::<FTWorkerCommand>(&req.ipc)
.expect("ft_worker: got unparseable init message");
match command {
FTWorkerCommand::Send {
@ -56,16 +54,14 @@ impl Guest for Component {
&Request {
inherit: false,
expects_response: Some(timeout),
ipc: Some(
serde_json::to_string(&FTWorkerCommand::Receive {
transfer_id,
file_name,
file_size,
total_chunks,
timeout,
})
.unwrap(),
),
ipc: serde_json::to_vec(&FTWorkerCommand::Receive {
transfer_id,
file_name,
file_size,
total_chunks,
timeout,
})
.unwrap(),
metadata: None,
},
None,
@ -77,7 +73,7 @@ impl Guest for Component {
}))
}
Ok((opp_worker, Message::Response((response, _)))) => {
let Ok(FTWorkerProtocol::Ready) = serde_json::from_str(&response.ipc.expect("ft_worker: got empty response")) else {
let Ok(FTWorkerProtocol::Ready) = serde_json::from_slice(&response.ipc) else {
respond_to_parent(FTWorkerResult::Err(TransferError::TargetRejected));
return;
};
@ -97,7 +93,7 @@ impl Guest for Component {
&Request {
inherit: false,
expects_response: Some(timeout),
ipc: None,
ipc: vec![],
metadata: None,
},
None,
@ -116,7 +112,7 @@ impl Guest for Component {
&Request {
inherit: false,
expects_response: None,
ipc: None,
ipc: vec![],
metadata: None,
},
None,
@ -130,9 +126,7 @@ impl Guest for Component {
respond_to_parent(FTWorkerResult::Err(TransferError::TargetRejected));
return;
};
let Ok(FTWorkerProtocol::Finished) = serde_json::from_str(
&resp.ipc.expect("ft_worker: got empty response"),
) else {
let Ok(FTWorkerProtocol::Finished) = serde_json::from_slice(&resp.ipc) else {
respond_to_parent(FTWorkerResult::Err(TransferError::TargetRejected));
return;
};
@ -153,7 +147,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&FTWorkerProtocol::Ready).unwrap()),
ipc: serde_json::to_vec(&FTWorkerProtocol::Ready).unwrap(),
metadata: None,
},
None,
@ -187,7 +181,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&FTWorkerProtocol::Finished).unwrap()),
ipc: serde_json::to_vec(&FTWorkerProtocol::Finished).unwrap(),
metadata: None,
},
None,
@ -198,10 +192,8 @@ impl Guest for Component {
&Request {
inherit: false,
expects_response: None,
ipc: Some(
serde_json::to_string(&FTWorkerResult::ReceiveSuccess(file_name))
.unwrap(),
),
ipc: serde_json::to_vec(&FTWorkerResult::ReceiveSuccess(file_name))
.unwrap(),
metadata: None,
},
None,
@ -219,7 +211,7 @@ fn respond_to_parent(result: FTWorkerResult) {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&result).unwrap()),
ipc: serde_json::to_vec(&result).unwrap(),
metadata: None,
},
None,

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
cargo_component_bindings::generate!();
use bindings::{print_to_terminal, receive, send_request, send_requests, send_response, get_payload, Guest};
use bindings::component::uq_process::types::*;
use bindings::{
get_payload, print_to_terminal, receive, send_request, send_requests, send_response, Guest,
};
use serde_json::json;
#[allow(dead_code)]
@ -11,23 +13,30 @@ struct Component;
const HOME_PAGE: &str = include_str!("home.html");
fn generate_http_binding(add: Address, path: &str, authenticated: bool) -> (Address, Request, Option<Context>, Option<Payload>) {
fn generate_http_binding(
add: Address,
path: &str,
authenticated: bool,
) -> (Address, Request, Option<Context>, Option<Payload>) {
(
add,
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": path,
"authenticated": authenticated,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
None
None,
)
}
@ -41,9 +50,8 @@ impl Guest for Component {
};
// <address, request, option<context>, option<payload>>
let http_endpoint_binding_requests: [(Address, Request, Option<Context>, Option<Payload>); 1] = [
generate_http_binding(bindings_address.clone(), "/", true),
];
let http_endpoint_binding_requests: [(Address, Request, Option<Context>, Option<Payload>);
1] = [generate_http_binding(bindings_address.clone(), "/", true)];
send_requests(&http_endpoint_binding_requests);
loop {
@ -56,122 +64,136 @@ impl Guest for Component {
continue;
};
if let Some(json) = request.ipc {
print_to_terminal(1, format!("homepage: JSON {}", json).as_str());
let message_json: serde_json::Value = match serde_json::from_str(&json) {
Ok(v) => v,
Err(_) => {
print_to_terminal(1, "homepage: failed to parse ipc JSON, skipping");
continue;
let message_json: serde_json::Value = match serde_json::from_slice(&request.ipc) {
Ok(v) => v,
Err(_) => {
print_to_terminal(1, "homepage: failed to parse ipc JSON, skipping");
continue;
}
};
if message_json["path"] == "/" && message_json["method"] == "GET" {
print_to_terminal(1, "homepage: sending response");
send_response(
&Response {
inherit: false,
ipc: serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
};
print_to_terminal(1, "homepage: parsed ipc JSON");
if message_json["path"] == "/" && message_json["method"] == "GET" {
print_to_terminal(1, "homepage: sending response");
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "text/html",
Some(&Payload {
mime: Some("text/html".to_string()),
bytes: HOME_PAGE
.replace("${our}", &our.node)
.to_string()
.as_bytes()
.to_vec(),
}),
);
} else if message_json["path"].is_string() {
send_response(
&Response {
inherit: false,
ipc: json!({
"action": "response",
"status": 404,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
mime: Some("text/html".to_string()),
bytes: "Not Found".to_string().as_bytes().to_vec(),
}),
);
} else if message_json["hello"] == "world" {
send_response(
&Response {
inherit: false,
ipc: serde_json::json!({
"hello": "to you too"
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
mime: Some("application/json".to_string()),
bytes: serde_json::json!({
"hello": "to you too"
})
.to_string()
.as_bytes()
.to_vec(),
}),
);
} else {
if let Some(payload) = get_payload() {
if let Ok(json) = serde_json::from_slice::<serde_json::Value>(&payload.bytes) {
print_to_terminal(1, format!("JSON: {}", json).as_str());
if json["message"] == "ping" {
// WebSocket pushes are sent as requests
send_request(
&Address {
node: our.node.clone(),
process: ProcessId::from_str("encryptor:sys:uqbar").unwrap(),
},
}).to_string()),
metadata: None,
},
Some(&Payload {
mime: Some("text/html".to_string()),
bytes: HOME_PAGE.replace("${our}", &our.node).to_string().as_bytes().to_vec(),
}),
);
} else if message_json["path"].is_string() {
send_response(
&Response {
inherit: false,
ipc: Some(json!({
"action": "response",
"status": 404,
"headers": {
"Content-Type": "text/html",
},
}).to_string()),
metadata: None,
},
Some(&Payload {
mime: Some("text/html".to_string()),
bytes: "Not Found"
.to_string()
.as_bytes()
.to_vec(),
}),
);
} else if message_json["hello"] == "world" {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::json!({
"hello": "to you too"
}).to_string()),
metadata: None,
},
Some(&Payload {
mime: Some("application/json".to_string()),
bytes: serde_json::json!({
"hello": "to you too"
}).to_string().as_bytes().to_vec(),
}),
);
} else {
if let Some(payload) = get_payload() {
if let Ok(json) = serde_json::from_slice::<serde_json::Value>(&payload.bytes) {
print_to_terminal(1, format!("JSON: {}", json).as_str());
if json["message"] == "ping" {
// WebSocket pushes are sent as requests
send_request(
&Address {
node: our.node.clone(),
process: ProcessId::from_str("encryptor:sys:uqbar").unwrap(),
},
&Request {
inherit: false,
expects_response: None,
ipc: Some(serde_json::json!({
"EncryptAndForwardAction": {
"channel_id": "homepage",
"forward_to": {
"node": our.node.clone(),
"process": {
"process_name": "http_server",
"package_name": "sys",
"publisher_node": "uqbar"
&Request {
inherit: false,
expects_response: None,
ipc: serde_json::json!({
"EncryptAndForwardAction": {
"channel_id": "homepage",
"forward_to": {
"node": our.node.clone(),
"process": {
"process_name": "http_server",
"package_name": "sys",
"publisher_node": "uqbar"
}
}, // node, process
"json": Some(serde_json::json!({ // this is the JSON to forward
"WebSocketPush": {
"target": {
"node": our.node.clone(),
"id": "homepage", // If the message passed in an ID then we could send to just that ID
}
}, // node, process
"json": Some(serde_json::json!({ // this is the JSON to forward
"WebSocketPush": {
"target": {
"node": our.node.clone(),
"id": "homepage", // If the message passed in an ID then we could send to just that ID
}
}
})),
}
}
})),
}
}).to_string()),
metadata: None,
},
None,
Some(&Payload {
mime: Some("application/json".to_string()),
bytes: serde_json::json!({
"pong": true
}).to_string().as_bytes().to_vec(),
}),
);
}
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
Some(&Payload {
mime: Some("application/json".to_string()),
bytes: serde_json::json!({
"pong": true
})
.to_string()
.as_bytes()
.to_vec(),
}),
);
}
}
}

View File

@ -16,18 +16,17 @@ const PROXY_HOME_PAGE: &str = include_str!("http_proxy.html");
struct Component;
fn send_http_response(status: u16, headers: HashMap<String, String>, payload_bytes: Vec<u8>) {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"status": status,
"headers": headers,
})
.to_string(),
),
ipc: serde_json::json!({
"status": status,
"headers": headers,
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -64,13 +63,16 @@ impl Guest for Component {
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": "/",
"authenticated": true,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
@ -81,13 +83,16 @@ impl Guest for Component {
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": "/static/*",
"authenticated": true,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
@ -98,13 +103,16 @@ impl Guest for Component {
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": "/list",
"authenticated": true,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
@ -115,13 +123,16 @@ impl Guest for Component {
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": "/register",
"authenticated": true,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
@ -132,13 +143,16 @@ impl Guest for Component {
Request {
inherit: false,
expects_response: None,
ipc: Some(json!({
ipc: json!({
"BindPath": {
"path": "/serve/:username/*",
"authenticated": true,
"local_only": false
}
}).to_string()),
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,
@ -160,12 +174,7 @@ impl Guest for Component {
continue;
};
let Some(json) = request.ipc else {
print_to_terminal(1, "http_proxy: no ipc json");
continue;
};
let message_json: serde_json::Value = match serde_json::from_str(&json) {
let message_json: serde_json::Value = match serde_json::from_slice(&request.ipc) {
Ok(v) => v,
Err(_) => {
print_to_terminal(1, "http_proxy: failed to parse ipc JSON, skipping");
@ -182,16 +191,16 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "text/html",
},
})
.to_string(),
),
ipc: serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -202,21 +211,20 @@ impl Guest for Component {
.to_vec(),
}),
);
} else if message_json["path"] == "/list" && message_json["method"] == "GET"
{
} else if message_json["path"] == "/list" && message_json["method"] == "GET" {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "application/json",
},
})
.to_string(),
),
ipc: serde_json::json!({
"action": "response",
"status": 200,
"headers": {
"Content-Type": "application/json",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -227,9 +235,7 @@ impl Guest for Component {
.to_vec(),
}),
);
} else if message_json["path"] == "/register"
&& message_json["method"] == "POST"
{
} else if message_json["path"] == "/register" && message_json["method"] == "POST" {
let mut status = 204;
let Some(payload) = get_payload() else {
@ -258,16 +264,16 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"action": "response",
"status": status,
"headers": {
"Content-Type": "text/html",
},
})
.to_string(),
),
ipc: serde_json::json!({
"action": "response",
"status": status,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -282,9 +288,7 @@ impl Guest for Component {
.to_vec(),
}),
);
} else if message_json["path"] == "/register"
&& message_json["method"] == "DELETE"
{
} else if message_json["path"] == "/register" && message_json["method"] == "DELETE" {
print_to_terminal(1, "HERE IN /register to delete something");
let username = message_json["query_params"]["username"]
.as_str()
@ -301,16 +305,16 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"action": "response",
"status": status,
"headers": {
"Content-Type": "text/html",
},
})
.to_string(),
),
ipc: serde_json::json!({
"action": "response",
"status": status,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -338,16 +342,16 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(
json!({
"action": "response",
"status": 403,
"headers": {
"Content-Type": "text/html",
},
})
.to_string(),
),
ipc: json!({
"action": "response",
"status": 403,
"headers": {
"Content-Type": "text/html",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -374,16 +378,16 @@ impl Guest for Component {
&Request {
inherit: true,
expects_response: None,
ipc: Some(
json!({
"method": message_json["method"],
"path": proxied_path,
"headers": message_json["headers"],
"proxy_path": raw_path,
"query_params": message_json["query_params"],
})
.to_string(),
),
ipc: json!({
"method": message_json["method"],
"path": proxied_path,
"headers": message_json["headers"],
"proxy_path": raw_path,
"query_params": message_json["query_params"],
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
None,

View File

@ -5,7 +5,10 @@ use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use bindings::component::uq_process::types::*;
use bindings::{create_capability, get_capability, has_capability, Guest, print_to_terminal, receive, send_request, send_response, spawn};
use bindings::{
create_capability, get_capability, has_capability, print_to_terminal, receive, send_request,
send_response, spawn, Guest,
};
mod kernel_types;
use kernel_types as kt;
@ -23,14 +26,16 @@ fn make_vfs_cap(kind: &str, drive: &str) -> String {
serde_json::to_string(&serde_json::json!({
"kind": kind,
"drive": drive,
})).unwrap()
}))
.unwrap()
}
fn make_db_cap(kind: &str, db: &str) -> String {
serde_json::to_string(&serde_json::json!({
"kind": kind,
"db": db,
})).unwrap()
}))
.unwrap()
}
fn forward_if_have_cap(
@ -38,7 +43,7 @@ fn forward_if_have_cap(
operation_type: &str,
// operation_type: OperationType,
db: &str,
ipc: Option<String>,
ipc: Vec<u8>,
db_to_process: &mut DbToProcess,
) -> anyhow::Result<()> {
if has_capability(&make_db_cap(operation_type, db)) {
@ -67,10 +72,7 @@ fn forward_if_have_cap(
}
}
fn handle_message (
our: &Address,
db_to_process: &mut DbToProcess,
) -> anyhow::Result<()> {
fn handle_message(our: &Address, db_to_process: &mut DbToProcess) -> anyhow::Result<()> {
let (source, message) = receive().unwrap();
// let (source, message) = receive()?;
@ -81,9 +83,9 @@ fn handle_message (
match message {
Message::Response(_) => {
return Err(kv::KeyValueError::UnexpectedResponse.into());
},
}
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
match process_lib::parse_message_ipc(&ipc)? {
kv::KeyValueMessage::New { ref db } => {
// TODO: make atomic
// (1): create vfs drive
@ -104,36 +106,38 @@ fn handle_message (
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: vfs_drive.clone(),
action: kt::VfsAction::New,
}).unwrap()),
})
.unwrap(),
None,
None,
15,
).unwrap();
)
.unwrap();
// (2)
let vfs_read = get_capability(
&vfs_address,
&make_vfs_cap("read", &vfs_drive),
).ok_or(anyhow::anyhow!("New failed: no vfs 'read' capability found"))?;
let vfs_write = get_capability(
&vfs_address,
&make_vfs_cap("write", &vfs_drive),
).ok_or(anyhow::anyhow!("New failed: no vfs 'write' capability found"))?;
let vfs_read = get_capability(&vfs_address, &make_vfs_cap("read", &vfs_drive))
.ok_or(anyhow::anyhow!(
"New failed: no vfs 'read' capability found"
))?;
let vfs_write =
get_capability(&vfs_address, &make_vfs_cap("write", &vfs_drive)).ok_or(
anyhow::anyhow!("New failed: no vfs 'write' capability found"),
)?;
let spawned_process_id = match spawn(
None,
"/key_value_worker.wasm",
&OnPanic::None, // TODO: notify us
&OnPanic::None, // TODO: notify us
&Capabilities::Some(vec![vfs_read, vfs_write]),
false, // not public
) {
Ok(spawned_process_id) => spawned_process_id,
Err(e) => {
print_to_terminal(0, &format!("couldn't spawn: {}", e));
panic!("couldn't spawn"); // TODO
},
panic!("couldn't spawn"); // TODO
}
};
// grant caps
create_capability(&source.process, &make_db_cap("read", db));
@ -166,20 +170,20 @@ fn handle_message (
},
None,
);
},
}
kv::KeyValueMessage::Write { ref db, .. } => {
forward_if_have_cap(our, "write", db, ipc, db_to_process)?;
},
}
kv::KeyValueMessage::Read { ref db, .. } => {
forward_if_have_cap(our, "read", db, ipc, db_to_process)?;
},
}
kv::KeyValueMessage::Err { error } => {
return Err(error.into());
}
}
Ok(())
},
}
}
}
@ -191,23 +195,20 @@ impl Guest for Component {
loop {
match handle_message(&our, &mut db_to_process) {
Ok(()) => {},
Ok(()) => {}
Err(e) => {
print_to_terminal(0, format!(
"key_value: error: {:?}",
e,
).as_str());
print_to_terminal(0, format!("key_value: error: {:?}", e,).as_str());
if let Some(e) = e.downcast_ref::<kv::KeyValueError>() {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&e).unwrap()),
ipc: serde_json::to_vec(&e).unwrap(),
metadata: None,
},
None,
);
}
},
}
};
}
}

View File

@ -55,7 +55,7 @@ fn send_and_await_response_wrapped(
&Request {
inherit: false,
expects_response: Some(timeout),
ipc: request_ipc,
ipc: request_ipc.unwrap_or_default().into_bytes(),
metadata: request_metadata,
},
match payload {
@ -65,7 +65,7 @@ fn send_and_await_response_wrapped(
).unwrap() else {
panic!("");
};
(ipc, metadata)
(serde_json::from_slice(&ipc).ok(), metadata)
}
fn handle_message (
@ -82,7 +82,7 @@ fn handle_message (
match message {
Message::Response(_) => { unimplemented!() },
Message::Request(Request { inherit: _ , expects_response: _, ipc, metadata: _ }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
match process_lib::parse_message_ipc(&ipc)? {
kv::KeyValueMessage::New { db } => {
let vfs_drive = format!("{}{}", PREFIX, db);
match db_handle {
@ -197,7 +197,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&e).unwrap()),
ipc: serde_json::to_vec(&e).unwrap(),
metadata: None,
},
None,

File diff suppressed because it is too large Load Diff

View File

@ -75,7 +75,7 @@ sol! {
event NodeRegistered(uint256 indexed node, bytes name);
}
fn subscribe_to_qns(from_block: u64) -> String {
fn subscribe_to_qns(from_block: u64) -> Vec<u8> {
json!({
"SubscribeEvents": {
"addresses": [
@ -94,6 +94,8 @@ fn subscribe_to_qns(from_block: u64) -> String {
}
})
.to_string()
.as_bytes()
.to_vec()
}
impl UqProcess for Component {
@ -127,12 +129,10 @@ impl UqProcess for Component {
inherit: false,
expects_response: None,
metadata: None,
ipc: Some(
serde_json::to_string(&NetActions::QnsBatchUpdate(
state.nodes.values().cloned().collect::<Vec<_>>(),
))
.unwrap(),
),
ipc: serde_json::to_vec(&NetActions::QnsBatchUpdate(
state.nodes.values().cloned().collect::<Vec<_>>(),
))
.unwrap(),
},
None,
None,
@ -148,7 +148,7 @@ impl UqProcess for Component {
expects_response: Some(5), // TODO evaluate
metadata: None,
// -1 because there could be other events in the last processed block
ipc: Some(subscribe_to_qns(state.block - 1)),
ipc: subscribe_to_qns(state.block - 1),
},
None,
None,
@ -165,16 +165,16 @@ impl UqProcess for Component {
inherit: false,
expects_response: None,
metadata: None,
ipc: Some(
json!({
"BindPath": {
"path": "/node/:name",
"authenticated": false,
"local_only": false
}
})
.to_string(),
),
ipc: json!({
"BindPath": {
"path": "/node/:name",
"authenticated": false,
"local_only": false
}
})
.to_string()
.as_bytes()
.to_vec(),
},
None,
None,
@ -193,24 +193,24 @@ impl UqProcess for Component {
};
if source.process == http_server_address {
if let Ok(ipc_json) = serde_json::from_str::<serde_json::Value>(
&request.ipc.clone().unwrap_or_default(),
) {
if let Ok(ipc_json) =
serde_json::from_slice::<serde_json::Value>(&request.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 Some(node) = state.nodes.get(name) {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"status": 200,
"headers": {
"Content-Type": "application/json",
},
})
.to_string(),
),
ipc: serde_json::json!({
"status": 200,
"headers": {
"Content-Type": "application/json",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -229,15 +229,15 @@ impl UqProcess for Component {
send_response(
&Response {
inherit: false,
ipc: Some(
serde_json::json!({
"status": 404,
"headers": {
"Content-Type": "application/json",
},
})
.to_string(),
),
ipc: serde_json::json!({
"status": 404,
"headers": {
"Content-Type": "application/json",
},
})
.to_string()
.as_bytes()
.to_vec(),
metadata: None,
},
Some(&Payload {
@ -248,14 +248,8 @@ impl UqProcess for Component {
continue;
}
let Ok(msg) = serde_json::from_str::<AllActions>(request.ipc.as_ref().unwrap()) else {
print_to_terminal(
0,
&format!(
"qns_indexer: got invalid message: {}",
request.ipc.unwrap_or_default()
),
);
let Ok(msg) = serde_json::from_slice::<AllActions>(&request.ipc) else {
print_to_terminal(0, "qns_indexer: got invalid message");
continue;
};
@ -332,12 +326,8 @@ impl UqProcess for Component {
inherit: false,
expects_response: None,
metadata: None,
ipc: Some(
serde_json::to_string(&NetActions::QnsUpdate(
update.clone(),
))
ipc: serde_json::to_vec(&NetActions::QnsUpdate(update.clone()))
.unwrap(),
),
},
None,
None,

View File

@ -36,7 +36,7 @@ fn forward_if_have_cap(
operation_type: &str,
// operation_type: OperationType,
db: &str,
ipc: Option<String>,
ipc: Vec<u8>,
db_to_process: &mut DbToProcess,
) -> anyhow::Result<()> {
if has_capability(&make_db_cap(operation_type, db)) {
@ -83,7 +83,7 @@ fn handle_message (
return Err(sq::SqliteError::UnexpectedResponse.into());
},
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
match process_lib::parse_message_ipc(&ipc)? {
sq::SqliteMessage::New { ref db } => {
// TODO: make atomic
// (1): create vfs drive
@ -104,10 +104,10 @@ fn handle_message (
let _ = process_lib::send_and_await_response(
&vfs_address,
false,
Some(serde_json::to_string(&kt::VfsRequest {
serde_json::to_vec(&kt::VfsRequest {
drive: vfs_drive.clone(),
action: kt::VfsAction::New,
}).unwrap()),
}).unwrap(),
None,
None,
15,
@ -249,7 +249,7 @@ impl Guest for Component {
send_response(
&Response {
inherit: false,
ipc: Some(serde_json::to_string(&e).unwrap()),
ipc: serde_json::to_vec(&e).unwrap(),
metadata: None,
},
None,

View File

@ -93,7 +93,7 @@ pub struct CIpcMetadata {
}
impl CPreOptionStr {
fn new(s: Option<String>) -> Self {
fn new(s: Option<Vec<u8>>) -> Self {
let (is_empty, string) = match s {
None => (0, CString::new("").unwrap()),
Some(s) => (1, CString::new(s).unwrap()),
@ -106,7 +106,7 @@ impl CPreOptionStr {
}
impl COptionStr {
fn new(s: Option<String>) -> Self {
fn new(s: Option<Vec<u8>>) -> Self {
let (is_empty, string) = match s {
None => (0, CString::new("").unwrap()),
Some(s) => (1, CString::new(s).unwrap()),
@ -118,6 +118,14 @@ impl COptionStr {
}
}
fn from_coptionstr_to_bytes(s: *const COptionStr) -> Vec<u8> {
if unsafe { (*s).is_empty == 0 } {
vec![]
} else {
from_cstr_to_string(unsafe { (*s).string }).as_bytes().to_vec()
}
}
fn from_coptionstr_to_option_string(s: *const COptionStr) -> Option<String> {
if unsafe { (*s).is_empty == 0 } {
None
@ -163,7 +171,13 @@ impl From<Option<Payload>> for CPrePayload {
fn from(p: Option<Payload>) -> Self {
let (is_empty, mime, bytes) = match p {
None => (0, COptionStr::new(None), CBytes::new_empty()),
Some(Payload { mime, bytes }) => (1, COptionStr::new(mime), CBytes::new(bytes)),
Some(Payload { mime, bytes }) => {
let mime = match mime {
Some(s) => Some(s.as_bytes().to_vec()),
None => None,
};
(1, COptionStr::new(mime), CBytes::new(bytes))
}
};
CPrePayload {
is_empty,
@ -299,7 +313,7 @@ pub extern "C" fn send_and_await_response_wrapped(
let target_node = from_cstr_to_string(target_node);
let target_process = from_cprocessid_to_processid(target_process);
let payload = from_cpayload_to_option_payload(payload);
let request_ipc = from_coptionstr_to_option_string(request_ipc);
let request_ipc = from_coptionstr_to_bytes(request_ipc);
let request_metadata = from_coptionstr_to_option_string(request_metadata);
let (
_,
@ -322,8 +336,11 @@ pub extern "C" fn send_and_await_response_wrapped(
).unwrap() else {
panic!("");
};
let ipc = CPreOptionStr::new(ipc);
let metadata = CPreOptionStr::new(metadata);
let ipc = CPreOptionStr::new(Some(ipc));
let metadata = CPreOptionStr::new(match metadata {
None => None,
Some(s) => Some(s.as_bytes().to_vec())
});
CIpcMetadata::copy_to_ptr(return_val, ipc, metadata);
}
@ -342,7 +359,7 @@ fn handle_message (
match message {
Message::Response(_) => { unimplemented!() },
Message::Request(Request { ipc, .. }) => {
match process_lib::parse_message_ipc(ipc.clone())? {
match process_lib::parse_message_ipc(&ipc)? {
sq::SqliteMessage::New { db } => {
let vfs_address = Address {
node: our.node.clone(),

View File

@ -264,15 +264,11 @@ where
super::bindings::set_state(&bincode::serialize(state).unwrap());
}
pub fn parse_message_ipc<T>(json_string: Option<String>) -> anyhow::Result<T>
pub fn parse_message_ipc<T>(json_bytes: &[u8]) -> anyhow::Result<T>
where
for<'a> T: serde::Deserialize<'a>,
{
let parsed: T = serde_json::from_str(
json_string
.ok_or(anyhow::anyhow!("json payload empty"))?
.as_str(),
)?;
let parsed: T = serde_json::from_slice(json_bytes)?;
Ok(parsed)
}

View File

@ -1,26 +0,0 @@
// https://github.com/bytecodealliance/wasmtime/blob/432b5471ec4bf6d51173def284cd418be6849a49/crates/wasi/wit/deps/random/insecure-seed.wit
/// The insecure-seed interface for seeding hash-map DoS resistance.
///
/// It is intended to be portable at least between Unix-family platforms and
/// Windows.
interface insecure-seed {
/// Return a 128-bit value that may contain a pseudo-random value.
///
/// The returned value is not required to be computed from a CSPRNG, and may
/// even be entirely deterministic. Host implementations are encouraged to
/// provide pseudo-random values to any program exposed to
/// attacker-controlled content, to enable DoS protection built into many
/// languages' hash-map implementations.
///
/// This function is intended to only be called once, by a source language
/// to initialize Denial Of Service (DoS) protection in its hash-map
/// implementation.
///
/// # Expected future evolution
///
/// This will likely be changed to a value import, to prevent it from being
/// called multiple times and potentially used for purposes other than DoS
/// protection.
insecure-seed: func() -> tuple<u64, u64>
}

View File

@ -1,23 +0,0 @@
// https://github.com/bytecodealliance/wasmtime/blob/432b5471ec4bf6d51173def284cd418be6849a49/crates/wasi/wit/deps/random/insecure.wit
/// The insecure interface for insecure pseudo-random numbers.
///
/// It is intended to be portable at least between Unix-family platforms and
/// Windows.
interface insecure {
/// Return `len` insecure pseudo-random bytes.
///
/// This function is not cryptographically secure. Do not use it for
/// anything related to security.
///
/// There are no requirements on the values of the returned bytes, however
/// implementations are encouraged to return evenly distributed values with
/// a long period.
get-insecure-random-bytes: func(len: u64) -> list<u8>
/// Return an insecure pseudo-random `u64` value.
///
/// This function returns the same type of pseudo-random data as
/// `get-insecure-random-bytes`, represented as a `u64`.
get-insecure-random-u64: func() -> u64
}

View File

@ -1,23 +0,0 @@
// https://github.com/bytecodealliance/wasmtime/blob/432b5471ec4bf6d51173def284cd418be6849a49/crates/wasi/wit/deps/random/random.wit
package wasi:random
interface random {
/// Return `len` cryptographically-secure pseudo-random bytes.
///
/// This function must produce data from an adequately seeded
/// cryptographically-secure pseudo-random number generator (CSPRNG), so it
/// must not block, from the perspective of the calling program, and the
/// returned data is always unpredictable.
///
/// This function must always return fresh pseudo-random data. Deterministic
/// environments must omit this function, rather than implementing it with
/// deterministic data.
get-random-bytes: func(len: u64) -> list<u8>
/// Return a cryptographically-secure pseudo-random `u64` value.
///
/// This function returns the same type of pseudo-random data as
/// `get-random-bytes`, represented as a `u64`.
get-random-u64: func() -> u64
}

View File

@ -1,183 +0,0 @@
package component:uq-process
interface types {
// JSON is passed over WASM boundary as a string.
type json = string
// context is a string of UTF-8 JSON.
// it is used when building a Request to save information
// that will not be part of a Response, in order to more
// easily handle ("contextualize") that Response.
type context = json
variant process-id {
id(u64),
name(string),
}
// TODO better name for this
record address {
node: string,
process: process-id,
}
record payload {
mime: option<string>,
bytes: list<u8>,
}
record request {
// if true, this request inherits context AND payload of incipient
// request, and cannot have its own context.
inherit: bool,
// if Some, this request expects a response in the number of seconds given
expects-response: option<u64>,
ipc: option<json>,
metadata: option<json>,
// to grab payload, use get_payload()
}
record response {
ipc: option<json>,
metadata: option<json>,
// to grab payload, use get_payload()
}
// a message can be a request or a response.
// within a response, there is a result which surfaces any error
// that happened because of a request.
// a successful response will contain the context of the request
// it matches, if any was set.
variant message {
request(request),
response(tuple<response, option<context>>),
}
variant capabilities {
none,
all,
some(list<signed-capability>),
}
record signed-capability {
issuer: address,
params: json,
signature: list<u8>,
}
// network errors come from trying to send a message to another node.
// a message can fail by timing out, or by the node being entirely unreachable (offline).
// in either case, the message is not delivered, and the process that sent it
// receives that message along with any assigned context and/or payload,
// and is free to handle it as it sees fit.
// note that if the message is a response, the process can issue a response again,
// and it will be directed to the same (remote) request as the original.
record send-error {
kind: send-error-kind,
message: message,
payload: option<payload>,
}
enum send-error-kind {
offline,
timeout,
}
// on-panic is a setting that determines what happens when a process panics.
// NOTE: requests should have expects-response set to false, will always be set to that by kernel
variant on-panic {
none,
restart,
requests(list<tuple<address, request, option<payload>>>),
}
}
world uq-process {
use types.{
json,
context,
address,
process-id,
payload,
request,
response,
message,
capabilities,
signed-capability,
send-error,
send-error-kind,
on-panic,
}
// entry point to all programs
export init: func(our: address)
// system utils:
import print-to-terminal: func(verbosity: u8, message: string)
import get-unix-time: func() -> u64
import get-eth-block: func() -> u64
// process management:
import set-on-panic: func(on-panic: on-panic)
import get-state: func() -> option<list<u8>>
import set-state: func(bytes: list<u8>)
import clear-state: func()
import spawn: func(id: process-id, %package: string, full-path: string, on-panic: on-panic, capabilities: capabilities) ->
option<process-id>
// capabilities management
// gives us all our signed capabilities so we can send them to others
import get-capabilities: func() -> list<signed-capability>
// gets a single specific capability
import get-capability: func(issuer: address, params: json) -> option<signed-capability>
// attaches a specific signed capability to our next message
import attach-capability: func(capability: signed-capability)
// saves capabilities to our store, so we can use them
import save-capabilities: func(capabilities: list<signed-capability>)
// check to see if the sender of a prompting message has a given capability, issued by us
// if the prompting message has a remote source, they must have attached it.
import has-capability: func(params: json) -> bool
// message I/O:
// ingest next message when it arrives along with its source.
// almost all long-running processes will call this in a loop
import receive: func() -> result<tuple<address, message>, tuple<send-error, option<context>>>
// gets payload, if any, of the message we just received
import get-payload: func() -> option<payload>
// send message(s) to target(s)
import send-request:
func(target: address, request: request, context: option<context>, payload: option<payload>)
import send-requests:
func(requests: list<tuple<address, request, option<context>, option<payload>>>)
import send-response:
func(response: response, payload: option<payload>)
// send a single request, then block (internally) until its response
// the type is Message but will always contain Response
import send-and-await-response:
func(target: address, request: request, payload: option<payload>) ->
result<tuple<address, message>, send-error>
// wasi
import wasi:random/insecure
import wasi:random/insecure-seed
import wasi:random/random
}