2024-02-02 07:43:13 +03:00
use crate ::wit ;
2023-10-16 04:11:16 +03:00
use ring ::signature ;
2024-02-02 07:43:13 +03:00
use rusqlite ::types ::{ FromSql , FromSqlError , ToSql , ValueRef } ;
2023-10-02 23:02:53 +03:00
use serde ::{ Deserialize , Serialize } ;
2023-11-06 19:31:54 +03:00
use std ::collections ::{ HashMap , HashSet } ;
2023-10-02 23:02:53 +03:00
use thiserror ::Error ;
2023-10-08 07:56:53 +03:00
lazy_static ::lazy_static! {
2024-01-14 22:54:20 +03:00
pub static ref ETH_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " eth " ) , " distro " , " sys " ) ;
pub static ref HTTP_CLIENT_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " http_client " ) , " distro " , " sys " ) ;
pub static ref HTTP_SERVER_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " http_server " ) , " distro " , " sys " ) ;
pub static ref KERNEL_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " kernel " ) , " distro " , " sys " ) ;
pub static ref TERMINAL_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " terminal " ) , " terminal " , " sys " ) ;
pub static ref TIMER_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " timer " ) , " distro " , " sys " ) ;
pub static ref VFS_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " vfs " ) , " distro " , " sys " ) ;
pub static ref STATE_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " state " ) , " distro " , " sys " ) ;
pub static ref KV_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " kv " ) , " distro " , " sys " ) ;
pub static ref SQLITE_PROCESS_ID : ProcessId = ProcessId ::new ( Some ( " sqlite " ) , " distro " , " sys " ) ;
2023-10-08 07:56:53 +03:00
}
2023-10-02 23:02:53 +03:00
//
2023-11-03 06:43:10 +03:00
// types shared between kernel and processes. frustratingly, this is an exact copy
2023-11-17 20:59:52 +03:00
// of the types in process_lib
2023-11-03 06:43:10 +03:00
// this is because even though the types are identical, they will not match when
// used in the kernel context which generates bindings differently than the process
2023-11-17 20:59:52 +03:00
// standard library. make sure to keep this synced with process_lib.
2023-10-02 23:02:53 +03:00
//
2023-10-26 07:11:03 +03:00
pub type Context = Vec < u8 > ;
2024-01-17 09:18:33 +03:00
pub type NodeId = String ; // KNS domain name
2023-10-02 23:02:53 +03:00
2023-10-08 07:56:53 +03:00
/// process ID is a formatted unique identifier that contains
/// the publishing node's ID, the package name, and finally the process name.
/// the process name can be a random number, or a name chosen by the user.
/// the formatting is as follows:
/// `[process name]:[package name]:[node ID]`
2023-11-29 01:33:49 +03:00
#[ derive(Clone, Debug, Eq, PartialEq, Hash) ]
2023-10-08 07:56:53 +03:00
pub struct ProcessId {
process_name : String ,
package_name : String ,
publisher_node : NodeId ,
}
2023-11-29 01:33:49 +03:00
impl Serialize for ProcessId {
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
format! ( " {} " , self ) . serialize ( serializer )
}
}
impl < ' a > Deserialize < ' a > for ProcessId {
fn deserialize < D > ( deserializer : D ) -> Result < ProcessId , D ::Error >
where
D : serde ::de ::Deserializer < ' a > ,
{
let s = String ::deserialize ( deserializer ) ? ;
2024-01-09 00:49:44 +03:00
s . parse ( ) . map_err ( serde ::de ::Error ::custom )
2023-11-29 01:33:49 +03:00
}
}
2023-11-18 03:28:51 +03:00
/// PackageId is like a ProcessId, but for a package. Only contains the name
/// of the package and the name of the publisher.
#[ derive(Hash, Eq, PartialEq, Debug, Clone, Serialize, Deserialize) ]
pub struct PackageId {
package_name : String ,
publisher_node : String ,
}
impl PackageId {
2023-12-15 02:35:14 +03:00
pub fn new ( package_name : & str , publisher_node : & str ) -> Self {
2023-11-18 03:28:51 +03:00
PackageId {
package_name : package_name . into ( ) ,
publisher_node : publisher_node . into ( ) ,
}
}
2024-01-09 00:49:44 +03:00
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 > {
2023-11-18 03:28:51 +03:00
// split string on colons into 2 segments
let mut segments = input . split ( ':' ) ;
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 ( PackageId {
package_name ,
publisher_node ,
} )
}
}
impl std ::fmt ::Display for PackageId {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! ( f , " {}:{} " , self . package_name , self . publisher_node )
}
}
/// ProcessId is defined in the wit bindings, but constructors and methods
/// are defined here.
2023-10-08 07:56:53 +03:00
impl ProcessId {
/// generates a random u64 number if process_name is not declared
pub fn new ( process_name : Option < & str > , package_name : & str , publisher_node : & str ) -> Self {
ProcessId {
2023-11-03 06:43:10 +03:00
process_name : process_name
. unwrap_or ( & rand ::random ::< u64 > ( ) . to_string ( ) )
. into ( ) ,
2023-10-08 07:56:53 +03:00
package_name : package_name . into ( ) ,
publisher_node : publisher_node . into ( ) ,
2023-10-02 23:02:53 +03:00
}
}
2023-10-08 07:56:53 +03:00
pub fn process ( & self ) -> & str {
& self . process_name
}
pub fn package ( & self ) -> & str {
& self . package_name
}
2023-11-13 23:23:59 +03:00
pub fn publisher ( & self ) -> & str {
2023-10-08 07:56:53 +03:00
& self . publisher_node
}
pub fn en_wit ( & self ) -> wit ::ProcessId {
wit ::ProcessId {
process_name : self . process_name . clone ( ) ,
package_name : self . package_name . clone ( ) ,
publisher_node : self . publisher_node . clone ( ) ,
}
}
pub fn de_wit ( wit : wit ::ProcessId ) -> ProcessId {
ProcessId {
process_name : wit . process_name ,
package_name : wit . package_name ,
publisher_node : wit . publisher_node ,
2023-10-02 23:02:53 +03:00
}
}
}
2024-01-09 00:49:44 +03:00
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 ,
} )
}
}
2023-11-18 03:28:51 +03:00
impl From < ( & str , & str , & str ) > for ProcessId {
fn from ( input : ( & str , & str , & str ) ) -> Self {
ProcessId ::new ( Some ( input . 0 ) , input . 1 , input . 2 )
}
}
impl std ::fmt ::Display for ProcessId {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! (
f ,
" {}:{}:{} " ,
self . process_name , self . package_name , self . publisher_node
)
}
}
2023-11-26 06:26:53 +03:00
// impl PartialEq for ProcessId {
// fn eq(&self, other: &Self) -> bool {
// self.process_name == other.process_name
// && self.package_name == other.package_name
// && self.publisher_node == other.publisher_node
// }
// }
2023-11-18 03:28:51 +03:00
impl PartialEq < & str > for ProcessId {
fn eq ( & self , other : & & str ) -> bool {
& self . to_string ( ) = = other
}
}
impl PartialEq < ProcessId > for & str {
fn eq ( & self , other : & ProcessId ) -> bool {
self = = & other . to_string ( )
}
}
2023-10-09 02:46:12 +03:00
#[ derive(Debug) ]
2023-10-08 07:56:53 +03:00
pub enum ProcessIdParseError {
TooManyColons ,
MissingField ,
}
2023-11-18 03:28:51 +03:00
impl std ::fmt ::Display for ProcessIdParseError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! (
f ,
" {} " ,
match self {
ProcessIdParseError ::TooManyColons = > " Too many colons in ProcessId string " ,
ProcessIdParseError ::MissingField = > " Missing field in ProcessId string " ,
}
)
}
}
impl std ::error ::Error for ProcessIdParseError {
fn description ( & self ) -> & str {
match self {
ProcessIdParseError ::TooManyColons = > " Too many colons in ProcessId string " ,
ProcessIdParseError ::MissingField = > " Missing field in ProcessId string " ,
}
}
}
2023-11-29 01:33:49 +03:00
#[ derive(Clone, Debug, Hash, Eq, PartialEq) ]
2023-10-02 23:02:53 +03:00
pub struct Address {
2023-10-08 07:56:53 +03:00
pub node : NodeId ,
2023-10-02 23:02:53 +03:00
pub process : ProcessId ,
}
2023-10-08 07:56:53 +03:00
impl Address {
2023-11-18 03:28:51 +03:00
pub fn new < T > ( node : & str , process : T ) -> Address
where
T : Into < ProcessId > ,
{
Address {
node : node . to_string ( ) ,
process : process . into ( ) ,
}
}
2024-01-09 00:49:44 +03:00
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 > {
2023-11-18 03:28:51 +03:00
// split string on colons into 4 segments,
// first one with @, next 3 with :
let mut name_rest = input . split ( '@' ) ;
let node = name_rest
. next ( )
. ok_or ( AddressParseError ::MissingField ) ?
. to_string ( ) ;
let mut segments = name_rest
. next ( )
. ok_or ( AddressParseError ::MissingNodeId ) ?
. split ( ':' ) ;
let process_name = segments
. next ( )
. ok_or ( AddressParseError ::MissingField ) ?
. to_string ( ) ;
let package_name = segments
. next ( )
. ok_or ( AddressParseError ::MissingField ) ?
. to_string ( ) ;
let publisher_node = segments
. next ( )
. ok_or ( AddressParseError ::MissingField ) ?
. to_string ( ) ;
if segments . next ( ) . is_some ( ) {
return Err ( AddressParseError ::TooManyColons ) ;
}
Ok ( Address {
node ,
process : ProcessId {
process_name ,
package_name ,
publisher_node ,
} ,
} )
}
2023-10-08 07:56:53 +03:00
}
2023-11-29 01:33:49 +03:00
impl Serialize for Address {
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
where
S : serde ::ser ::Serializer ,
{
format! ( " {} " , self ) . serialize ( serializer )
}
}
impl < ' a > Deserialize < ' a > for Address {
fn deserialize < D > ( deserializer : D ) -> Result < Address , D ::Error >
where
D : serde ::de ::Deserializer < ' a > ,
{
let s = String ::deserialize ( deserializer ) ? ;
2024-01-09 00:49:44 +03:00
s . parse ( ) . map_err ( serde ::de ::Error ::custom )
2023-11-29 01:33:49 +03:00
}
}
2023-11-18 03:28:51 +03:00
impl From < ( & str , & str , & str , & str ) > for Address {
fn from ( input : ( & str , & str , & str , & str ) ) -> Self {
Address ::new ( input . 0 , ( input . 1 , input . 2 , input . 3 ) )
}
}
impl < T > From < ( & str , T ) > for Address
where
T : Into < ProcessId > ,
{
fn from ( input : ( & str , T ) ) -> Self {
Address ::new ( input . 0 , input . 1 )
}
}
impl std ::fmt ::Display for Address {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! ( f , " {}@{} " , self . node , self . process )
}
}
#[ derive(Debug) ]
2023-11-26 06:26:53 +03:00
#[ allow(dead_code) ]
2023-11-18 03:28:51 +03:00
pub enum AddressParseError {
TooManyColons ,
MissingNodeId ,
MissingField ,
}
impl std ::fmt ::Display for AddressParseError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! (
f ,
" {} " ,
match self {
AddressParseError ::TooManyColons = > " Too many colons in ProcessId string " ,
AddressParseError ::MissingNodeId = > " Node ID missing " ,
AddressParseError ::MissingField = > " Missing field in ProcessId string " ,
}
)
}
}
impl std ::error ::Error for AddressParseError {
fn description ( & self ) -> & str {
match self {
AddressParseError ::TooManyColons = > " Too many colons in ProcessId string " ,
AddressParseError ::MissingNodeId = > " Node ID missing " ,
AddressParseError ::MissingField = > " Missing field in ProcessId string " ,
}
}
}
2023-10-02 23:02:53 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
2024-01-09 00:49:44 +03:00
pub struct LazyLoadBlob {
2023-10-02 23:02:53 +03:00
pub mime : Option < String > , // MIME type
pub bytes : Vec < u8 > ,
}
2023-10-17 18:11:05 +03:00
#[ derive(Clone, Debug, PartialEq, Serialize, Deserialize) ]
2023-10-02 23:02:53 +03:00
pub struct Request {
pub inherit : bool ,
pub expects_response : Option < u64 > , // number of seconds until timeout
2024-01-09 00:49:44 +03:00
pub body : Vec < u8 > ,
2023-10-26 07:11:03 +03:00
pub metadata : Option < String > , // JSON-string
2024-01-07 05:04:51 +03:00
pub capabilities : Vec < ( Capability , Vec < u8 > ) > ,
2023-10-02 23:02:53 +03:00
}
2023-10-17 18:11:05 +03:00
#[ derive(Clone, Debug, PartialEq, Serialize, Deserialize) ]
2023-10-02 23:02:53 +03:00
pub struct Response {
2023-10-17 00:39:00 +03:00
pub inherit : bool ,
2024-01-09 00:49:44 +03:00
pub body : Vec < u8 > ,
2023-10-02 23:02:53 +03:00
pub metadata : Option < String > , // JSON-string
2024-01-07 05:04:51 +03:00
pub capabilities : Vec < ( Capability , Vec < u8 > ) > ,
2023-10-02 23:02:53 +03:00
}
2023-10-17 18:11:05 +03:00
#[ derive(Clone, Debug, PartialEq, Serialize, Deserialize) ]
2023-10-02 23:02:53 +03:00
pub enum Message {
Request ( Request ) ,
Response ( ( Response , Option < Context > ) ) ,
}
#[ derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize) ]
pub struct Capability {
pub issuer : Address ,
pub params : String , // JSON-string
}
2024-01-07 01:43:16 +03:00
impl std ::fmt ::Display for Capability {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
2024-01-12 06:54:17 +03:00
write! (
f ,
" {}({}) " ,
self . issuer ,
serde_json ::from_str ::< serde_json ::Value > ( & self . params )
. unwrap_or ( serde_json ::json! ( " invalid JSON in capability " ) )
)
2024-01-07 01:43:16 +03:00
}
2023-10-02 23:02:53 +03:00
}
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct SendError {
pub kind : SendErrorKind ,
2023-11-03 06:43:10 +03:00
pub target : Address ,
2023-10-02 23:02:53 +03:00
pub message : Message ,
2024-01-09 00:49:44 +03:00
pub lazy_load_blob : Option < LazyLoadBlob > ,
2023-10-02 23:02:53 +03:00
}
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub enum SendErrorKind {
Offline ,
Timeout ,
}
#[ derive(Clone, Debug, Serialize, Deserialize) ]
2023-12-16 00:21:06 +03:00
pub enum OnExit {
2023-10-02 23:02:53 +03:00
None ,
Restart ,
2024-01-09 00:49:44 +03:00
Requests ( Vec < ( Address , Request , Option < LazyLoadBlob > ) > ) ,
2023-10-02 23:02:53 +03:00
}
2023-12-16 00:21:06 +03:00
impl OnExit {
2023-10-02 23:02:53 +03:00
pub fn is_restart ( & self ) -> bool {
match self {
2023-12-16 00:21:06 +03:00
OnExit ::None = > false ,
OnExit ::Restart = > true ,
OnExit ::Requests ( _ ) = > false ,
}
}
2024-03-14 07:00:40 +03:00
pub fn is_none ( & self ) -> bool {
match self {
OnExit ::None = > true ,
OnExit ::Restart = > false ,
OnExit ::Requests ( _ ) = > false ,
}
}
2023-12-16 00:21:06 +03:00
pub fn en_wit ( & self ) -> wit ::OnExit {
match self {
OnExit ::None = > wit ::OnExit ::None ,
OnExit ::Restart = > wit ::OnExit ::Restart ,
OnExit ::Requests ( reqs ) = > wit ::OnExit ::Requests (
reqs . iter ( )
2024-01-09 00:49:44 +03:00
. map ( | ( address , request , blob ) | {
2023-12-16 00:21:06 +03:00
(
address . en_wit ( ) ,
en_wit_request ( request . clone ( ) ) ,
2024-01-09 00:49:44 +03:00
en_wit_blob ( blob . clone ( ) ) ,
2023-12-16 00:21:06 +03:00
)
} )
. collect ( ) ,
) ,
}
}
pub fn de_wit ( wit : wit ::OnExit ) -> Self {
match wit {
wit ::OnExit ::None = > OnExit ::None ,
wit ::OnExit ::Restart = > OnExit ::Restart ,
wit ::OnExit ::Requests ( reqs ) = > OnExit ::Requests (
reqs . into_iter ( )
2024-01-09 00:49:44 +03:00
. map ( | ( address , request , blob ) | {
2023-12-16 00:21:06 +03:00
(
Address ::de_wit ( address ) ,
de_wit_request ( request ) ,
2024-01-09 00:49:44 +03:00
de_wit_blob ( blob ) ,
2023-12-16 00:21:06 +03:00
)
} )
. collect ( ) ,
) ,
2023-10-02 23:02:53 +03:00
}
}
}
2023-11-03 06:43:10 +03:00
impl std ::fmt ::Display for Message {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
2024-01-16 23:29:16 +03:00
write! ( f , " {} " , display_message ( self , " \n " ) )
}
}
fn display_capabilities ( capabilities : & Vec < ( Capability , Vec < u8 > ) > , delimiter : & str ) -> String {
if capabilities . is_empty ( ) {
return " [], " . to_string ( ) ;
}
let mut caps_string = " [ " . to_string ( ) ;
for cap in capabilities . iter ( ) {
caps_string + = & format! ( " {} {} " , delimiter , cap . 0. to_string ( ) ) ;
}
format! ( " {} {} ] " , caps_string , delimiter )
}
fn display_message ( m : & Message , delimiter : & str ) -> String {
let lines = match m {
Message ::Request ( request ) = > {
vec! [
" Request( " . into ( ) ,
format! ( " inherit: {} , " , request . inherit ) ,
format! ( " expects_response: {:?} , " , request . expects_response ) ,
format! (
" body: {}, " ,
2024-02-27 02:46:27 +03:00
match std ::str ::from_utf8 ( & request . body ) {
Ok ( str ) = > str . to_string ( ) ,
2024-01-16 23:29:16 +03:00
Err ( _ ) = > format! ( " {:?} " , request . body ) ,
2023-11-03 06:43:10 +03:00
}
2024-01-16 23:29:16 +03:00
) ,
2024-01-16 23:29:50 +03:00
format! (
" metadata: {}, " ,
& request . metadata . as_ref ( ) . unwrap_or ( & " None " . into ( ) )
) ,
format! (
" capabilities: {} " ,
display_capabilities ( & request . capabilities , delimiter )
) ,
2024-01-16 23:29:16 +03:00
]
2024-01-16 23:29:50 +03:00
}
2024-01-16 23:29:16 +03:00
Message ::Response ( ( response , context ) ) = > {
vec! [
" Response( " . into ( ) ,
format! ( " inherit: {} , " , response . inherit ) ,
format! (
" body: {}, " ,
match serde_json ::from_slice ::< serde_json ::Value > ( & response . body ) {
Ok ( json ) = > format! ( " {} " , json ) ,
Err ( _ ) = > format! ( " {:?} " , response . body ) ,
2024-01-07 01:43:16 +03:00
}
2024-01-16 23:29:16 +03:00
) ,
2024-01-16 23:29:50 +03:00
format! (
" metadata: {}, " ,
& response . metadata . as_ref ( ) . unwrap_or ( & " None " . into ( ) )
) ,
2024-01-16 23:29:16 +03:00
format! (
" context: {}, " ,
if context . is_none ( ) {
" None " . into ( )
} else {
2024-01-16 23:29:50 +03:00
match serde_json ::from_slice ::< serde_json ::Value > ( context . as_ref ( ) . unwrap ( ) )
{
2024-01-16 23:29:16 +03:00
Ok ( json ) = > format! ( " {} " , json ) ,
Err ( _ ) = > format! ( " {:?} " , context . as_ref ( ) . unwrap ( ) ) ,
}
} ,
) ,
2024-01-16 23:29:50 +03:00
format! (
" capabilities: {} " ,
display_capabilities ( & response . capabilities , delimiter )
) ,
2024-01-16 23:29:16 +03:00
]
2023-11-03 06:43:10 +03:00
}
2024-01-16 23:29:16 +03:00
} ;
lines . into_iter ( ) . collect ::< Vec < _ > > ( ) . join ( delimiter ) + & delimiter [ .. delimiter . len ( ) - 4 ] + " ) "
2023-11-03 06:43:10 +03:00
}
//
// conversions between wit types and kernel types (annoying!)
//
pub fn de_wit_request ( wit : wit ::Request ) -> Request {
Request {
inherit : wit . inherit ,
expects_response : wit . expects_response ,
2024-01-09 00:49:44 +03:00
body : wit . body ,
2023-11-03 06:43:10 +03:00
metadata : wit . metadata ,
2024-01-05 00:06:41 +03:00
capabilities : wit
. capabilities
. iter ( )
. map ( | cap | de_wit_capability ( cap . clone ( ) ) )
. collect ( ) ,
2023-11-03 06:43:10 +03:00
}
}
pub fn en_wit_request ( request : Request ) -> wit ::Request {
wit ::Request {
inherit : request . inherit ,
expects_response : request . expects_response ,
2024-01-09 00:49:44 +03:00
body : request . body ,
2023-11-03 06:43:10 +03:00
metadata : request . metadata ,
2024-01-05 00:06:41 +03:00
capabilities : request
. capabilities
. iter ( )
. map ( | cap | en_wit_capability ( cap . clone ( ) ) )
. collect ( ) ,
2023-11-03 06:43:10 +03:00
}
}
pub fn de_wit_response ( wit : wit ::Response ) -> Response {
Response {
inherit : wit . inherit ,
2024-01-09 00:49:44 +03:00
body : wit . body ,
2023-11-03 06:43:10 +03:00
metadata : wit . metadata ,
2024-01-05 00:06:41 +03:00
capabilities : wit
. capabilities
. iter ( )
. map ( | cap | de_wit_capability ( cap . clone ( ) ) )
. collect ( ) ,
2023-11-03 06:43:10 +03:00
}
}
pub fn en_wit_response ( response : Response ) -> wit ::Response {
wit ::Response {
inherit : response . inherit ,
2024-01-09 00:49:44 +03:00
body : response . body ,
2023-11-03 06:43:10 +03:00
metadata : response . metadata ,
2024-01-05 00:06:41 +03:00
capabilities : response
. capabilities
. iter ( )
. map ( | cap | en_wit_capability ( cap . clone ( ) ) )
. collect ( ) ,
2023-11-03 06:43:10 +03:00
}
}
2024-01-09 00:49:44 +03:00
pub fn de_wit_blob ( wit : Option < wit ::LazyLoadBlob > ) -> Option < LazyLoadBlob > {
2023-11-03 06:43:10 +03:00
match wit {
None = > None ,
2024-01-09 00:49:44 +03:00
Some ( wit ) = > Some ( LazyLoadBlob {
2023-11-03 06:43:10 +03:00
mime : wit . mime ,
bytes : wit . bytes ,
} ) ,
}
}
2024-01-09 00:49:44 +03:00
pub fn en_wit_blob ( load : Option < LazyLoadBlob > ) -> Option < wit ::LazyLoadBlob > {
2023-11-03 06:43:10 +03:00
match load {
None = > None ,
2024-01-09 00:49:44 +03:00
Some ( load ) = > Some ( wit ::LazyLoadBlob {
2023-11-03 06:43:10 +03:00
mime : load . mime ,
bytes : load . bytes ,
} ) ,
}
}
2024-01-07 05:04:51 +03:00
pub fn de_wit_capability ( wit : wit ::Capability ) -> ( Capability , Vec < u8 > ) {
(
Capability {
issuer : Address {
node : wit . issuer . node ,
process : ProcessId {
process_name : wit . issuer . process . process_name ,
package_name : wit . issuer . process . package_name ,
publisher_node : wit . issuer . process . publisher_node ,
} ,
2023-11-03 06:43:10 +03:00
} ,
2024-01-07 05:04:51 +03:00
params : wit . params ,
2023-11-03 06:43:10 +03:00
} ,
2024-01-07 05:04:51 +03:00
vec! [ ] ,
)
2023-11-03 06:43:10 +03:00
}
2024-01-07 05:04:51 +03:00
pub fn en_wit_capability ( cap : ( Capability , Vec < u8 > ) ) -> wit ::Capability {
2024-01-05 00:06:41 +03:00
wit ::Capability {
2024-01-07 05:04:51 +03:00
issuer : cap . 0. issuer . en_wit ( ) ,
params : cap . 0. params ,
2023-11-03 06:43:10 +03:00
}
}
pub fn en_wit_message ( message : Message ) -> wit ::Message {
match message {
Message ::Request ( request ) = > wit ::Message ::Request ( en_wit_request ( request ) ) ,
Message ::Response ( ( response , context ) ) = > {
wit ::Message ::Response ( ( en_wit_response ( response ) , context ) )
}
}
}
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 ) ,
2024-01-09 00:49:44 +03:00
lazy_load_blob : en_wit_blob ( error . lazy_load_blob ) ,
2023-11-03 06:43:10 +03:00
}
}
pub fn en_wit_send_error_kind ( kind : SendErrorKind ) -> wit ::SendErrorKind {
match kind {
SendErrorKind ::Offline = > wit ::SendErrorKind ::Offline ,
SendErrorKind ::Timeout = > wit ::SendErrorKind ::Timeout ,
}
}
//
2023-11-17 20:59:52 +03:00
// END SYNC WITH process_lib
2023-11-03 06:43:10 +03:00
//
//
// internal message pipes between kernel and runtime modules
//
// keeps the from address so we know where to pipe error
pub type NetworkErrorSender = tokio ::sync ::mpsc ::Sender < WrappedSendError > ;
pub type NetworkErrorReceiver = tokio ::sync ::mpsc ::Receiver < WrappedSendError > ;
pub type MessageSender = tokio ::sync ::mpsc ::Sender < KernelMessage > ;
pub type MessageReceiver = tokio ::sync ::mpsc ::Receiver < KernelMessage > ;
pub type PrintSender = tokio ::sync ::mpsc ::Sender < Printout > ;
pub type PrintReceiver = tokio ::sync ::mpsc ::Receiver < Printout > ;
pub type DebugSender = tokio ::sync ::mpsc ::Sender < DebugCommand > ;
pub type DebugReceiver = tokio ::sync ::mpsc ::Receiver < DebugCommand > ;
pub type CapMessageSender = tokio ::sync ::mpsc ::Sender < CapMessage > ;
pub type CapMessageReceiver = tokio ::sync ::mpsc ::Receiver < CapMessage > ;
2024-02-27 02:46:27 +03:00
pub type ProcessMessageSender = tokio ::sync ::mpsc ::Sender < Result < KernelMessage , WrappedSendError > > ;
pub type ProcessMessageReceiver =
tokio ::sync ::mpsc ::Receiver < Result < KernelMessage , WrappedSendError > > ;
2023-11-03 06:43:10 +03:00
//
2024-01-13 23:22:19 +03:00
// types used for onchain identity system
2023-11-03 06:43:10 +03:00
//
#[ derive(Debug) ]
pub struct Keyfile {
pub username : String ,
pub routers : Vec < String > ,
pub networking_keypair : signature ::Ed25519KeyPair ,
pub jwt_secret_bytes : Vec < u8 > ,
2024-03-07 03:59:41 +03:00
pub file_key : Vec < u8 > ,
2023-11-03 06:43:10 +03:00
}
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct KeyfileVet {
2024-03-07 20:08:15 +03:00
pub password_hash : String ,
2023-11-03 06:43:10 +03:00
pub keyfile : String ,
}
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct KeyfileVetted {
pub username : String ,
pub networking_key : String ,
pub routers : Vec < String > ,
}
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct BootInfo {
2024-03-07 20:08:15 +03:00
pub password_hash : String ,
2023-11-03 06:43:10 +03:00
pub username : String ,
pub reset : bool ,
pub direct : bool ,
2024-03-06 01:45:16 +03:00
pub owner : String ,
pub signature : String ,
pub timestamp : u64 ,
2024-03-07 20:26:10 +03:00
pub chain_id : u64 ,
2023-11-03 06:43:10 +03:00
}
2023-11-29 19:32:21 +03:00
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct ImportKeyfileInfo {
2024-03-07 20:08:15 +03:00
pub password_hash : String ,
2023-11-29 19:32:21 +03:00
pub keyfile : String ,
}
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct LoginInfo {
2024-03-07 20:08:15 +03:00
pub password_hash : String ,
2023-11-29 19:32:21 +03:00
}
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub struct LoginAndResetInfo {
2024-03-07 20:08:15 +03:00
pub password_hash : String ,
2023-11-29 19:32:21 +03:00
pub direct : bool ,
}
2023-11-03 06:43:10 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct Identity {
pub name : NodeId ,
pub networking_key : String ,
pub ws_routing : Option < ( String , u16 ) > ,
pub allowed_routers : Vec < NodeId > ,
}
2023-11-29 19:32:21 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct UnencryptedIdentity {
pub name : NodeId ,
pub allowed_routers : Vec < NodeId > ,
2023-11-03 06:43:10 +03:00
}
2023-10-02 23:02:53 +03:00
//
// kernel types that runtime modules use
//
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct ProcessMetadata {
pub our : Address ,
2023-12-14 03:28:01 +03:00
pub wasm_bytes_handle : String ,
2024-05-15 03:00:48 +03:00
/// if None, use the oldest version: 0.7.0
pub wit_version : Option < u32 > ,
2023-12-16 00:21:06 +03:00
pub on_exit : OnExit ,
2023-10-06 07:12:31 +03:00
pub public : bool ,
2023-10-02 23:02:53 +03:00
}
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct KernelMessage {
pub id : u64 ,
pub source : Address ,
pub target : Address ,
pub rsvp : Rsvp ,
pub message : Message ,
2024-01-09 00:49:44 +03:00
pub lazy_load_blob : Option < LazyLoadBlob > ,
2023-10-02 23:02:53 +03:00
}
2023-11-17 20:59:52 +03:00
impl std ::fmt ::Display for KernelMessage {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! (
f ,
2024-01-09 00:49:44 +03:00
" {{ \n id: {}, \n source: {}, \n target: {}, \n rsvp: {}, \n message: {}, \n blob: {}, \n }} " ,
2023-11-17 20:59:52 +03:00
self . id ,
self . source ,
self . target ,
match & self . rsvp {
Some ( rsvp ) = > rsvp . to_string ( ) ,
None = > " None " . to_string ( )
} ,
2024-01-16 23:29:16 +03:00
display_message ( & self . message , " \n " ) ,
2024-01-09 00:49:44 +03:00
self . lazy_load_blob . is_some ( ) ,
2023-11-17 20:59:52 +03:00
)
}
}
2023-10-02 23:02:53 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct WrappedSendError {
pub id : u64 ,
pub source : Address ,
pub error : SendError ,
}
2023-12-02 08:40:42 +03:00
/// A terminal printout. Verbosity level is from low to high.
/// - `0`: always printed
/// - `1`: verbose, used for debugging
/// - `2`: very verbose: shows runtime information
/// - `3`: very verbose: shows every event in event loop
2023-10-02 23:02:53 +03:00
pub struct Printout {
pub verbosity : u8 ,
pub content : String ,
}
// kernel sets in case, e.g.,
// A requests response from B does not request response from C
// -> kernel sets `Some(A) = Rsvp` for B's request to C
pub type Rsvp = Option < Address > ;
#[ derive(Debug, Serialize, Deserialize) ]
pub enum DebugCommand {
Toggle ,
Step ,
}
2023-11-29 01:33:49 +03:00
/// IPC format for requests sent to kernel runtime module
2023-10-02 23:02:53 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub enum KernelCommand {
2023-11-29 01:33:49 +03:00
/// RUNTIME ONLY: used to notify the kernel that booting is complete and
/// all processes have been loaded in from their persisted or bootstrapped state.
2023-10-17 18:11:05 +03:00
Booted ,
2023-11-29 01:33:49 +03:00
/// Tell the kernel to install and prepare a new process for execution.
/// The process will not begin execution until the kernel receives a
/// `RunProcess` command with the same `id`.
///
/// The process that sends this command will be given messaging capabilities
/// for the new process if `public` is false.
2024-01-05 00:06:41 +03:00
///
/// All capabilities passed into initial_capabilities must be held by the source
/// of this message, or the kernel will discard them (silently for now).
2023-11-29 01:33:49 +03:00
InitializeProcess {
2023-10-08 07:56:53 +03:00
id : ProcessId ,
2023-12-14 03:28:01 +03:00
wasm_bytes_handle : String ,
2024-01-02 01:19:28 +03:00
wit_version : Option < u32 > ,
2023-12-16 00:21:06 +03:00
on_exit : OnExit ,
2024-01-05 00:06:41 +03:00
initial_capabilities : HashSet < Capability > ,
2023-10-06 07:12:31 +03:00
public : bool ,
2023-10-02 23:02:53 +03:00
} ,
2024-01-07 05:29:55 +03:00
/// Create an arbitrary capability and grant it to a process.
GrantCapabilities {
target : ProcessId ,
capabilities : Vec < Capability > ,
} ,
2024-02-07 01:48:36 +03:00
/// Drop capabilities. Does nothing if process doesn't have these caps
DropCapabilities {
target : ProcessId ,
capabilities : Vec < Capability > ,
} ,
2023-11-29 01:33:49 +03:00
/// Tell the kernel to run a process that has already been installed.
/// TODO: in the future, this command could be extended to allow for
/// resource provision.
RunProcess ( ProcessId ) ,
/// Kill a running process immediately. This may result in the dropping / mishandling of messages!
KillProcess ( ProcessId ) ,
/// RUNTIME ONLY: notify the kernel that the runtime is shutting down and it
/// should gracefully stop and persist the running processes.
2023-10-02 23:02:53 +03:00
Shutdown ,
2023-12-29 19:12:26 +03:00
/// Ask kernel to produce debugging information
Debug ( KernelPrint ) ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub enum KernelPrint {
ProcessMap ,
Process ( ProcessId ) ,
2023-12-29 19:13:01 +03:00
HasCap { on : ProcessId , cap : Capability } ,
2023-10-02 23:02:53 +03:00
}
2023-11-29 01:33:49 +03:00
/// IPC format for all KernelCommand responses
#[ derive(Debug, Serialize, Deserialize) ]
pub enum KernelResponse {
InitializedProcess ,
InitializeProcessError ,
StartedProcess ,
RunProcessError ,
KilledProcess ( ProcessId ) ,
}
2023-10-11 08:40:08 +03:00
#[ derive(Debug) ]
2023-10-02 23:02:53 +03:00
pub enum CapMessage {
2024-01-17 23:50:42 +03:00
/// root access: uncritically sign and add all `caps` to `on`
2023-10-02 23:02:53 +03:00
Add {
on : ProcessId ,
2024-01-05 00:06:41 +03:00
caps : Vec < Capability > ,
2023-10-11 08:40:08 +03:00
responder : tokio ::sync ::oneshot ::Sender < bool > ,
2023-10-02 23:02:53 +03:00
} ,
2024-02-07 01:48:36 +03:00
/// root delete: uncritically remove all `caps` from `on`
Drop {
2023-10-02 23:02:53 +03:00
on : ProcessId ,
2024-02-07 01:48:36 +03:00
caps : Vec < Capability > ,
2023-10-11 08:40:08 +03:00
responder : tokio ::sync ::oneshot ::Sender < bool > ,
2023-10-02 23:02:53 +03:00
} ,
2024-01-17 23:50:42 +03:00
/// does `on` have `cap` in its store?
2023-10-02 23:02:53 +03:00
Has {
// a bool is given in response here
on : ProcessId ,
cap : Capability ,
responder : tokio ::sync ::oneshot ::Sender < bool > ,
} ,
2024-01-17 23:50:42 +03:00
/// return all caps in `on`'s store
2023-10-02 23:02:53 +03:00
GetAll {
on : ProcessId ,
2024-01-07 05:04:51 +03:00
responder : tokio ::sync ::oneshot ::Sender < Vec < ( Capability , Vec < u8 > ) > > ,
2023-10-02 23:02:53 +03:00
} ,
2024-02-08 18:22:03 +03:00
/// Remove all caps issued by `on` from every process on the entire system
RevokeAll {
on : ProcessId ,
responder : tokio ::sync ::oneshot ::Sender < bool > ,
} ,
2024-01-17 23:50:42 +03:00
/// before `on` sends a message, filter out any bogus caps it may have attached, sign any new
/// caps it may have created, and retreive the signature for the caps in its store.
FilterCaps {
2024-01-05 00:53:19 +03:00
on : ProcessId ,
caps : Vec < Capability > ,
2024-01-07 05:04:51 +03:00
responder : tokio ::sync ::oneshot ::Sender < Vec < ( Capability , Vec < u8 > ) > > ,
2023-10-02 23:02:53 +03:00
} ,
}
2024-02-08 18:22:03 +03:00
pub type ReverseCapIndex = HashMap < ProcessId , HashMap < ProcessId , Vec < Capability > > > ;
2023-10-02 23:02:53 +03:00
pub type ProcessMap = HashMap < ProcessId , PersistedProcess > ;
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct PersistedProcess {
2023-12-14 03:28:01 +03:00
pub wasm_bytes_handle : String ,
2024-01-02 01:19:28 +03:00
pub wit_version : Option < u32 > ,
2023-12-16 00:21:06 +03:00
pub on_exit : OnExit ,
2024-01-05 02:53:23 +03:00
pub capabilities : HashMap < Capability , Vec < u8 > > ,
2023-10-06 07:12:31 +03:00
pub public : bool , // marks if a process allows messages from any process
2023-10-02 23:02:53 +03:00
}
2024-01-11 23:52:20 +03:00
impl std ::fmt ::Display for PersistedProcess {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! (
f ,
2024-05-15 03:00:48 +03:00
" Process {{ \n wasm_bytes_handle: {}, \n wit_version: {:?}, \n on_exit: {:?}, \n public: {} \n capabilities: {} \n }} " ,
2024-01-11 23:52:20 +03:00
{
if & self . wasm_bytes_handle = = " " {
" (none, this is a runtime process) "
} else {
& self . wasm_bytes_handle
}
} ,
2024-05-15 03:00:48 +03:00
self . wit_version ,
2024-01-11 23:52:20 +03:00
self . on_exit ,
self . public ,
{
let mut caps_string = " [ " . to_string ( ) ;
for cap in self . capabilities . keys ( ) {
caps_string + = & format! ( " \n {} " , cap . to_string ( ) ) ;
}
caps_string + " \n ] "
} ,
)
}
}
2024-02-15 21:59:21 +03:00
/// Represents the metadata associated with a kinode package, which is an ERC721 compatible token.
/// This is deserialized from the `metadata.json` file in a package.
/// Fields:
/// - `name`: An optional field representing the display name of the package. This does not have to be unique, and is not used for identification purposes.
/// - `description`: An optional field providing a description of the package.
/// - `image`: An optional field containing a URL to an image representing the package.
/// - `external_url`: An optional field containing a URL for more information about the package. For example, a link to the github repository.
/// - `animation_url`: An optional field containing a URL to an animation or video representing the package.
/// - `properties`: A requried field containing important information about the package.
2024-02-13 00:47:03 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct Erc721Metadata {
pub name : Option < String > ,
pub description : Option < String > ,
pub image : Option < String > ,
pub external_url : Option < String > ,
pub animation_url : Option < String > ,
2024-02-13 21:32:38 +03:00
pub properties : Erc721Properties ,
2024-02-13 00:47:03 +03:00
}
2024-02-15 21:59:21 +03:00
/// Represents critical fields of a kinode package in an ERC721 compatible format.
/// This follows the [ERC1155](https://github.com/ethereum/ercs/blob/master/ERCS/erc-1155.md#erc-1155-metadata-uri-json-schema) metadata standard.
///
/// Fields:
/// - `package_name`: The unique name of the package, used in the `PackageId`, e.g. `package_name:publisher`.
/// - `publisher`: The KNS identity of the package publisher used in the `PackageId`, e.g. `package_name:publisher`
/// - `current_version`: A string representing the current version of the package, e.g. `1.0.0`.
/// - `mirrors`: A list of NodeIds where the package can be found, providing redundancy.
/// - `code_hashes`: A map from version names to their respective SHA-256 hashes.
/// - `license`: An optional field containing the license of the package.
/// - `screenshots`: An optional field containing a list of URLs to screenshots of the package.
/// - `wit_version`: An optional field containing the version of the WIT standard that the package adheres to.
2024-02-13 00:47:03 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct Erc721Properties {
pub package_name : String ,
2023-10-21 02:15:11 +03:00
pub publisher : String ,
2024-02-13 00:47:03 +03:00
pub current_version : String ,
pub mirrors : Vec < NodeId > ,
pub code_hashes : HashMap < String , String > ,
2024-02-13 23:39:41 +03:00
pub license : Option < String > ,
pub screenshots : Option < Vec < String > > ,
2024-05-15 03:00:48 +03:00
pub wit_version : Option < u32 > ,
2023-10-21 02:15:11 +03:00
}
/// the type that gets deserialized from each entry in the array in `manifest.json`
2023-10-06 07:12:31 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub struct PackageManifestEntry {
pub process_name : String ,
pub process_wasm_path : String ,
2023-12-16 00:21:06 +03:00
pub on_exit : OnExit ,
2023-10-06 07:12:31 +03:00
pub request_networking : bool ,
2024-01-17 06:52:20 +03:00
pub request_capabilities : Vec < serde_json ::Value > ,
pub grant_capabilities : Vec < serde_json ::Value > ,
2023-10-16 20:48:14 +03:00
pub public : bool ,
2023-10-06 07:12:31 +03:00
}
2023-12-08 18:37:41 +03:00
#[ derive(Serialize, Deserialize, Debug) ]
pub enum StateAction {
GetState ( ProcessId ) ,
SetState ( ProcessId ) ,
DeleteState ( ProcessId ) ,
2023-12-11 23:10:16 +03:00
Backup ,
2023-12-08 18:37:41 +03:00
}
2023-12-14 03:28:01 +03:00
#[ derive(Serialize, Deserialize, Debug) ]
2023-12-08 18:37:41 +03:00
pub enum StateResponse {
GetState ,
SetState ,
DeleteState ,
2023-12-11 23:10:16 +03:00
Backup ,
2023-12-14 03:28:01 +03:00
Err ( StateError ) ,
2023-12-08 18:37:41 +03:00
}
2023-12-14 03:28:01 +03:00
#[ derive(Error, Debug, Serialize, Deserialize) ]
pub enum StateError {
#[ error( " kernel_state: rocksdb internal error: {error} " ) ]
RocksDBError { action : String , error : String } ,
#[ error( " kernel_state: startup error " ) ]
StartupError { action : String } ,
2024-01-09 00:49:44 +03:00
#[ error( " kernel_state: bytes blob required for {action} " ) ]
2023-12-14 03:28:01 +03:00
BadBytes { action : String } ,
#[ error( " kernel_state: bad request error: {error} " ) ]
BadRequest { error : String } ,
2024-01-09 00:49:44 +03:00
#[ error( " kernel_state: Bad JSON blob: {error} " ) ]
2023-12-14 03:28:38 +03:00
BadJson { error : String } ,
2023-12-14 03:28:01 +03:00
#[ error( " kernel_state: state not found for ProcessId {process_id} " ) ]
NotFound { process_id : ProcessId } ,
2023-12-18 23:36:22 +03:00
#[ error( " kernel_state: IO error: {error} " ) ]
IOError { error : String } ,
2023-10-02 23:02:53 +03:00
}
2023-12-14 03:28:01 +03:00
#[ allow(dead_code) ]
impl StateError {
pub fn kind ( & self ) -> & str {
match * self {
StateError ::RocksDBError { .. } = > " RocksDBError " ,
StateError ::StartupError { .. } = > " StartupError " ,
StateError ::BadBytes { .. } = > " BadBytes " ,
StateError ::BadRequest { .. } = > " BadRequest " ,
StateError ::BadJson { .. } = > " NoJson " ,
StateError ::NotFound { .. } = > " NotFound " ,
2023-12-18 23:36:22 +03:00
StateError ::IOError { .. } = > " IOError " ,
2023-12-14 03:28:01 +03:00
}
}
2023-10-02 23:02:53 +03:00
}
#[ derive(Debug, Serialize, Deserialize) ]
2023-10-07 02:25:05 +03:00
pub struct VfsRequest {
2023-12-13 19:13:00 +03:00
pub path : String ,
2023-10-07 02:25:05 +03:00
pub action : VfsAction ,
2023-10-02 23:02:53 +03:00
}
2024-01-29 02:08:48 +03:00
#[ derive(Debug, Serialize, Deserialize, PartialEq) ]
2023-10-07 02:25:05 +03:00
pub enum VfsAction {
2023-12-13 19:13:00 +03:00
CreateDrive ,
2023-12-15 02:36:03 +03:00
CreateDir ,
2023-12-13 19:13:00 +03:00
CreateDirAll ,
CreateFile ,
2023-12-30 04:55:29 +03:00
OpenFile { create : bool } ,
2023-12-13 19:13:00 +03:00
CloseFile ,
Write ,
2024-01-12 23:08:31 +03:00
WriteAll ,
2023-12-13 19:13:00 +03:00
Append ,
SyncAll ,
Read ,
ReadDir ,
2023-12-19 18:16:25 +03:00
ReadToEnd ,
2023-12-13 19:13:00 +03:00
ReadExact ( u64 ) ,
ReadToString ,
2023-12-30 05:10:10 +03:00
Seek { seek_from : SeekFrom } ,
2023-12-13 19:13:00 +03:00
RemoveFile ,
RemoveDir ,
RemoveDirAll ,
2023-12-30 05:10:10 +03:00
Rename { new_path : String } ,
2023-12-20 19:50:11 +03:00
Metadata ,
2023-12-13 19:13:00 +03:00
AddZip ,
2023-12-30 04:55:29 +03:00
CopyFile { new_path : String } ,
2023-12-13 19:13:00 +03:00
Len ,
SetLen ( u64 ) ,
Hash ,
2023-10-02 23:02:53 +03:00
}
2024-01-29 02:08:48 +03:00
#[ derive(Debug, Serialize, Deserialize, PartialEq) ]
2023-12-13 19:13:00 +03:00
pub enum SeekFrom {
Start ( u64 ) ,
End ( i64 ) ,
Current ( i64 ) ,
2023-10-02 23:02:53 +03:00
}
2023-12-20 19:50:11 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub enum FileType {
File ,
Directory ,
Symlink ,
Other ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub struct FileMetadata {
pub file_type : FileType ,
pub len : u64 ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub struct DirEntry {
pub path : String ,
pub file_type : FileType ,
}
2023-10-02 23:02:53 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub enum VfsResponse {
2023-10-07 02:25:05 +03:00
Ok ,
Err ( VfsError ) ,
2023-12-13 19:13:00 +03:00
Read ,
2023-12-30 04:55:29 +03:00
SeekFrom ( u64 ) ,
2023-12-20 19:50:11 +03:00
ReadDir ( Vec < DirEntry > ) ,
2023-12-13 19:13:00 +03:00
ReadToString ( String ) ,
2023-12-20 19:50:11 +03:00
Metadata ( FileMetadata ) ,
2023-12-13 19:13:00 +03:00
Len ( u64 ) ,
Hash ( [ u8 ; 32 ] ) ,
2023-10-07 02:25:05 +03:00
}
2023-12-13 19:13:00 +03:00
#[ derive(Error, Debug, Serialize, Deserialize) ]
2023-10-09 01:57:45 +03:00
pub enum VfsError {
2023-12-14 03:28:01 +03:00
#[ error( " vfs: No capability for action {action} at path {path} " ) ]
2023-12-13 19:13:00 +03:00
NoCap { action : String , path : String } ,
2024-01-09 00:49:44 +03:00
#[ error( " vfs: Bytes blob required for {action} at path {path} " ) ]
2023-12-13 19:13:00 +03:00
BadBytes { action : String , path : String } ,
#[ error( " vfs: bad request error: {error} " ) ]
BadRequest { error : String } ,
#[ error( " vfs: error parsing path: {path}, error: {error} " ) ]
2023-12-14 03:28:38 +03:00
ParseError { error : String , path : String } ,
2023-12-14 03:28:01 +03:00
#[ error( " vfs: IO error: {error}, at path {path} " ) ]
2023-12-14 02:27:22 +03:00
IOError { error : String , path : String } ,
#[ error( " vfs: kernel capability channel error: {error} " ) ]
CapChannelFail { error : String } ,
2024-01-09 00:49:44 +03:00
#[ error( " vfs: Bad JSON blob: {error} " ) ]
2023-12-14 03:28:38 +03:00
BadJson { error : String } ,
2023-12-14 03:28:01 +03:00
#[ error( " vfs: File not found at path {path} " ) ]
2023-12-13 19:13:00 +03:00
NotFound { path : String } ,
#[ error( " vfs: Creating directory failed at path: {path}: {error} " ) ]
CreateDirError { path : String , error : String } ,
2023-10-09 01:57:45 +03:00
}
2023-10-08 08:14:57 +03:00
#[ allow(dead_code) ]
2023-10-07 02:25:05 +03:00
impl VfsError {
pub fn kind ( & self ) -> & str {
match * self {
2023-12-13 19:13:00 +03:00
VfsError ::NoCap { .. } = > " NoCap " ,
VfsError ::BadBytes { .. } = > " BadBytes " ,
VfsError ::BadRequest { .. } = > " BadRequest " ,
VfsError ::ParseError { .. } = > " ParseError " ,
VfsError ::IOError { .. } = > " IOError " ,
2023-12-14 02:27:22 +03:00
VfsError ::CapChannelFail { .. } = > " CapChannelFail " ,
2023-12-13 19:13:00 +03:00
VfsError ::BadJson { .. } = > " NoJson " ,
VfsError ::NotFound { .. } = > " NotFound " ,
VfsError ::CreateDirError { .. } = > " CreateDirError " ,
2023-10-07 02:25:05 +03:00
}
}
}
2023-12-18 23:36:22 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub struct KvRequest {
2023-12-19 19:31:18 +03:00
pub package_id : PackageId ,
2023-12-19 19:31:55 +03:00
pub db : String ,
2023-12-18 23:36:22 +03:00
pub action : KvAction ,
}
#[ derive(Debug, Serialize, Deserialize, Clone) ]
pub enum KvAction {
2024-01-03 18:11:15 +03:00
Open ,
RemoveDb ,
2023-12-18 23:36:22 +03:00
Set { key : Vec < u8 > , tx_id : Option < u64 > } ,
Delete { key : Vec < u8 > , tx_id : Option < u64 > } ,
2023-12-18 23:38:18 +03:00
Get { key : Vec < u8 > } ,
2023-12-18 23:36:22 +03:00
BeginTx ,
Commit { tx_id : u64 } ,
Backup ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub enum KvResponse {
2023-12-18 23:38:18 +03:00
Ok ,
2023-12-18 23:36:22 +03:00
BeginTx { tx_id : u64 } ,
Get { key : Vec < u8 > } ,
Err { error : KvError } ,
}
2023-12-19 02:38:20 +03:00
#[ derive(Debug, Serialize, Deserialize, Error) ]
2023-12-18 23:36:22 +03:00
pub enum KvError {
#[ error( " kv: DbDoesNotExist " ) ]
NoDb ,
#[ error( " kv: KeyNotFound " ) ]
KeyNotFound ,
#[ error( " kv: no Tx found " ) ]
NoTx ,
2023-12-19 02:16:54 +03:00
#[ error( " kv: No capability: {error} " ) ]
2023-12-18 23:38:18 +03:00
NoCap { error : String } ,
2023-12-18 23:36:22 +03:00
#[ error( " kv: rocksdb internal error: {error} " ) ]
RocksDBError { action : String , error : String } ,
#[ error( " kv: input bytes/json/key error: {error} " ) ]
InputError { error : String } ,
#[ error( " kv: IO error: {error} " ) ]
IOError { error : String } ,
2023-12-18 23:38:18 +03:00
}
2023-12-19 02:16:54 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub struct SqliteRequest {
2023-12-19 19:31:18 +03:00
pub package_id : PackageId ,
2023-12-19 19:31:55 +03:00
pub db : String ,
2023-12-19 02:16:54 +03:00
pub action : SqliteAction ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub enum SqliteAction {
2024-01-03 18:11:15 +03:00
Open ,
RemoveDb ,
2023-12-19 02:17:48 +03:00
Write {
statement : String ,
tx_id : Option < u64 > ,
} ,
Read {
query : String ,
} ,
2023-12-19 02:16:54 +03:00
BeginTx ,
2023-12-19 02:17:48 +03:00
Commit {
tx_id : u64 ,
} ,
2023-12-19 02:16:54 +03:00
Backup ,
}
#[ derive(Debug, Serialize, Deserialize) ]
pub enum SqliteResponse {
Ok ,
Read ,
BeginTx { tx_id : u64 } ,
Err { error : SqliteError } ,
}
#[ derive(Debug, Clone, Serialize, Deserialize, PartialEq) ]
pub enum SqlValue {
Integer ( i64 ) ,
Real ( f64 ) ,
Text ( String ) ,
Blob ( Vec < u8 > ) ,
Boolean ( bool ) ,
Null ,
}
2023-12-19 02:38:20 +03:00
#[ derive(Debug, Serialize, Deserialize, Error) ]
2023-12-19 02:16:54 +03:00
pub enum SqliteError {
#[ error( " sqlite: DbDoesNotExist " ) ]
NoDb ,
#[ error( " sqlite: NoTx " ) ]
NoTx ,
#[ error( " sqlite: No capability: {error} " ) ]
NoCap { error : String } ,
#[ error( " sqlite: UnexpectedResponse " ) ]
UnexpectedResponse ,
#[ error( " sqlite: NotAWriteKeyword " ) ]
NotAWriteKeyword ,
#[ error( " sqlite: NotAReadKeyword " ) ]
NotAReadKeyword ,
#[ error( " sqlite: Invalid Parameters " ) ]
InvalidParameters ,
#[ error( " sqlite: IO error: {error} " ) ]
IOError { error : String } ,
#[ error( " sqlite: rusqlite error: {error} " ) ]
RusqliteError { error : String } ,
#[ error( " sqlite: input bytes/json/key error: {error} " ) ]
InputError { error : String } ,
2023-12-19 02:17:48 +03:00
}
2024-01-30 09:13:37 +03:00
#[ derive(Debug, Serialize, Deserialize) ]
pub enum MessageType {
Request ,
Response ,
}
2024-02-02 07:43:13 +03:00
impl std ::fmt ::Display for KvAction {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( f , " {:?} " , self )
}
}
impl From < tokio ::sync ::oneshot ::error ::RecvError > for KvError {
fn from ( err : tokio ::sync ::oneshot ::error ::RecvError ) -> Self {
KvError ::NoCap {
error : err . to_string ( ) ,
}
}
}
impl From < tokio ::sync ::mpsc ::error ::SendError < CapMessage > > for KvError {
fn from ( err : tokio ::sync ::mpsc ::error ::SendError < CapMessage > ) -> Self {
KvError ::NoCap {
error : err . to_string ( ) ,
}
}
}
impl From < std ::io ::Error > for KvError {
fn from ( err : std ::io ::Error ) -> Self {
KvError ::IOError {
error : err . to_string ( ) ,
}
}
}
impl From < tokio ::sync ::oneshot ::error ::RecvError > for VfsError {
fn from ( err : tokio ::sync ::oneshot ::error ::RecvError ) -> Self {
VfsError ::CapChannelFail {
error : err . to_string ( ) ,
}
}
}
impl From < tokio ::sync ::mpsc ::error ::SendError < CapMessage > > for VfsError {
fn from ( err : tokio ::sync ::mpsc ::error ::SendError < CapMessage > ) -> Self {
VfsError ::CapChannelFail {
error : err . to_string ( ) ,
}
}
}
impl From < std ::io ::Error > for VfsError {
fn from ( err : std ::io ::Error ) -> Self {
VfsError ::IOError {
path : " " . into ( ) ,
error : err . to_string ( ) ,
}
}
}
impl std ::fmt ::Display for VfsAction {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( f , " {:?} " , self )
}
}
impl From < std ::io ::Error > for StateError {
fn from ( err : std ::io ::Error ) -> Self {
StateError ::IOError {
error : err . to_string ( ) ,
}
}
}
impl ToSql for SqlValue {
fn to_sql ( & self ) -> rusqlite ::Result < rusqlite ::types ::ToSqlOutput > {
match self {
SqlValue ::Integer ( i ) = > i . to_sql ( ) ,
SqlValue ::Real ( f ) = > f . to_sql ( ) ,
SqlValue ::Text ( ref s ) = > s . to_sql ( ) ,
SqlValue ::Blob ( ref b ) = > b . to_sql ( ) ,
SqlValue ::Boolean ( b ) = > b . to_sql ( ) ,
SqlValue ::Null = > Ok ( rusqlite ::types ::ToSqlOutput ::Owned (
rusqlite ::types ::Value ::Null ,
) ) ,
}
}
}
impl FromSql for SqlValue {
fn column_result ( value : ValueRef < '_ > ) -> Result < Self , FromSqlError > {
match value {
ValueRef ::Integer ( i ) = > Ok ( SqlValue ::Integer ( i ) ) ,
ValueRef ::Real ( f ) = > Ok ( SqlValue ::Real ( f ) ) ,
ValueRef ::Text ( t ) = > {
let text_str = std ::str ::from_utf8 ( t ) . map_err ( | _ | FromSqlError ::InvalidType ) ? ;
Ok ( SqlValue ::Text ( text_str . to_string ( ) ) )
}
ValueRef ::Blob ( b ) = > Ok ( SqlValue ::Blob ( b . to_vec ( ) ) ) ,
_ = > Err ( FromSqlError ::InvalidType ) ,
}
}
}
impl std ::fmt ::Display for SqliteAction {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( f , " {:?} " , self )
}
}
impl From < std ::io ::Error > for SqliteError {
fn from ( err : std ::io ::Error ) -> Self {
SqliteError ::IOError {
error : err . to_string ( ) ,
}
}
}
impl From < rusqlite ::Error > for SqliteError {
fn from ( err : rusqlite ::Error ) -> Self {
SqliteError ::RusqliteError {
error : err . to_string ( ) ,
}
}
}
impl From < tokio ::sync ::oneshot ::error ::RecvError > for SqliteError {
fn from ( err : tokio ::sync ::oneshot ::error ::RecvError ) -> Self {
SqliteError ::NoCap {
error : err . to_string ( ) ,
}
}
}
impl From < tokio ::sync ::mpsc ::error ::SendError < CapMessage > > for SqliteError {
fn from ( err : tokio ::sync ::mpsc ::error ::SendError < CapMessage > ) -> Self {
SqliteError ::NoCap {
error : err . to_string ( ) ,
}
}
}
2024-02-12 20:41:11 +03:00
#[ derive(Debug, Clone, Serialize, Deserialize) ]
pub enum TimerAction {
Debug ,
SetTimer ( u64 ) ,
}
2024-02-18 01:34:29 +03:00
//
// networking protocol types
//
/// Must be parsed from message pack vector.
2024-03-05 23:10:10 +03:00
/// all Get actions must be sent from local process. used for debugging
2024-02-18 01:34:29 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
2024-03-05 23:10:10 +03:00
pub enum NetAction {
2024-02-18 01:34:29 +03:00
/// Received from a router of ours when they have a new pending passthrough for us.
/// We should respond (if we desire) by using them to initialize a routed connection
/// with the NodeId given.
ConnectionRequest ( NodeId ) ,
/// can only receive from trusted source, for now just ourselves locally,
/// in the future could get from remote provider
KnsUpdate ( KnsUpdate ) ,
KnsBatchUpdate ( Vec < KnsUpdate > ) ,
2024-03-05 23:10:10 +03:00
/// get a list of peers we are connected to
GetPeers ,
/// get the [`Identity`] struct for a single peer
GetPeer ( String ) ,
/// get the [`NodeId`] associated with a given namehash, if any
GetName ( String ) ,
/// get a user-readable diagnostics string containing networking inforamtion
GetDiagnostics ,
2024-04-02 18:33:52 +03:00
/// sign the attached blob payload, sign with our node's networking key.
/// **only accepted from our own node**
/// **the source [`Address`] will always be prepended to the payload**
Sign ,
/// given a message in blob payload, verify the message is signed by
/// the given source. if the signer is not in our representation of
/// the PKI, will not verify.
/// **the `from` [`Address`] will always be prepended to the payload**
Verify {
from : Address ,
signature : Vec < u8 > ,
2024-04-02 18:34:14 +03:00
} ,
2024-02-18 01:34:29 +03:00
}
/// For now, only sent in response to a ConnectionRequest.
/// Must be parsed from message pack vector
#[ derive(Clone, Debug, Serialize, Deserialize) ]
2024-03-05 23:10:10 +03:00
pub enum NetResponse {
2024-02-18 01:34:29 +03:00
Accepted ( NodeId ) ,
Rejected ( NodeId ) ,
2024-03-05 23:10:10 +03:00
/// response to [`NetAction::GetPeers`]
Peers ( Vec < Identity > ) ,
/// response to [`NetAction::GetPeer`]
Peer ( Option < Identity > ) ,
/// response to [`NetAction::GetName`]
Name ( Option < String > ) ,
2024-04-02 18:33:52 +03:00
/// response to [`NetAction::GetDiagnostics`]. a user-readable string.
2024-03-05 23:10:10 +03:00
Diagnostics ( String ) ,
2024-04-02 18:33:52 +03:00
/// response to [`NetAction::Sign`]. contains the signature in blob
Signed ,
/// response to [`NetAction::Verify`]. boolean indicates whether
/// the signature was valid or not. note that if the signer node
/// cannot be found in our representation of PKI, this will return false,
/// because we cannot find the networking public key to verify with.
Verified ( bool ) ,
2024-02-18 01:34:29 +03:00
}
2024-05-13 22:21:38 +03:00
#[ derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq) ]
2024-02-18 01:34:29 +03:00
pub struct KnsUpdate {
pub name : String , // actual username / domain name
pub owner : String ,
pub node : String , // hex namehash of node
pub public_key : String ,
pub ip : String ,
pub port : u16 ,
pub routers : Vec < String > ,
}