tosc-rs / mgnp

MnemOS Global Networking Protocol
Creative Commons Attribution Share Alike 4.0 International
15 stars 1 forks source link

enumerate services in a registry #27

Open hawkw opened 10 months ago

hawkw commented 10 months ago

currently, clients can attempt to remote services with a known identity. however, there's no way to look up the list of services available in the remote registry.

we should maybe add some kind of mechanism for enumerating a list of available service identities on the remote. this could be our first actual use of connection ID zero for link-control messages.

eventually this mechanism could be used to gossip routing tables for multi-hop routing.

hawkw commented 10 months ago

part of #11, maybe?

hawkw commented 10 months ago

some thoughts about this emerged fully-formed into my head while going for a run in the rain today:

we could just make the "get service list from registry" be a normal MGNP service like:

pub struct ServiceList;

impl registry::Service for ServiceList {
    type Hello = ();
    type ConnectError = ();
    type ClientMsg = EnumerateRequest;
    type ServerMsg = EnumerateChunk;

    const UUID = /* .. */.;
}

#[derive(Serialize, Deserialize, Debug)]
pub enum EnumerateRequest {
    All,
    // this is an enum to carve out possible space for 
    // "give me only some specific services" type requests later
}

#[derive(Serialize, Deserialize, Debug)]
pub struct EnumerateChunk {
    // actual service list.
    pub services: heapless::Vec<ServiceBinding, 32>;
    // the current number of this chunk. the intent here is to allow 
    // pagination by the service registry so that we can use `heapless::Vec`s
    pub chunk_num: usize,
    // total number of chunks
    pub total_chunks: usize,
    // alternatively we could just have a "is_last: bool", but i thought sending
    // total number of chunks was nicer, since it allows the client to e.g. 
    // preallocate enough storage for all the service mappings, or whatever...
}

// maps a service type UUID to an identity that implements that service.
// this could, alternatively, have been a tuple, but i thought we might
// want to retain the ability to add additional metadata later.
#[derive(Serialize, Deserialize, Debug)]
pub struct ServiceBinding {
    pub uuid: Uuid,
    pub identity: registry::Identity,
}
hawkw commented 10 months ago

i wonder if the message pagination design i sketched out in https://github.com/tosc-rs/mgnp/issues/27#issuecomment-1817298425 could be easily pulled out into a reusable utility (possibly as part of #25)...

something like this:

#[derive(Serialize, Deserialize, Debug)]
pub struct Page<T, const LEN: usize = 32> {
    /// The data for this page. 
    pub body: heapless::Vec<T, LEN>,
    /// Total number of pages in this response. 
    pub page_total: usize,
    /// This page's page number.
    ///
    /// If this is equal to `page_total`, then this is the last
    /// page in the response.
    pub page_number: usize,
}

impl<T, const LEN: usize> Page<T, LEN> {
    pub fn from_iter(i: impl Iterator<Item = T> + ExactSizeIterator) -> impl Iterator<Item = Self> {
       // ...
    }
}