prototype-cjdns-pi icon indicating copy to clipboard operation
prototype-cjdns-pi copied to clipboard

Multi-hop service advertisment model, with plugins

Open makew0rld opened this issue 6 years ago • 5 comments

This issue details an idea proposed by @darkdrgn2k, originally beginning in chat here.

Basics:

  • Nodes can send UDP packets advertising the services they have to neighbour nodes
  • Plugins can process the services, so the reaction to the info can be modularized
  • Messages can have a TTL (time-to-live) on them
    • This allows the message to be passed from node to node, decreasing the TTL until it reaches 0
    • This allows multi-hop message delivery and service advertisement without crawling the network, assuming peers do what they're told
  • Messages also have a hop number on them, a bit like a reverse TTL
    • This allows peers to know how far away nodes are geographically (roughly) and decide what to do with the info

Message format:

  • Potentially just contains a list of services, and then an interested node can reply and ask for the info for a specific service
    • This saves on space since a single UDP packet only has about 508 bytes for info to be used reliably
  • @darkdrgn2k suggested something similar to IPv6|service,service|TTL|hop|Identifier
    • I am unsure what identifier means here, in other parts of the chat he said WHATEVER as a placeholder
  • I would possibly suggest using Cap'n Proto as an efficient binary data format we can use to encode the messages in a small amount of space, instead of just plain text
    • Cap’n Proto is an insanely fast data interchange format and capability-based RPC system. Think JSON, except binary. Or think Protocol Buffers, except faster.

Logic:

  • @darkdrgn2k could you expand on this?

Modules/Plugins:

  • Base pkg that sets up this framework
  • Other pkgs can have plugins that make use of the framework
  • The framework pkg should be an optional dependency of these modules, so that they can function without needing to advertise, and needing another dependency
  • The framework should have a way to configure which pkgs notify or not, possibly in a config file and later in a Web UI for advanced users
  • We will have to decide on defaults for this, maybe it can be on a per pkg basis

makew0rld avatar Apr 19 '19 01:04 makew0rld

@darkdrgn2k suggested something similar to IPv6|service,service|TTL|hop|Identifier

What im currently theorizing. SSB uses : as delimiter but that conflicts with ipv6

We need a way of identifying each packet so that a node knows if they already received once and it came back, or if its a new one that it needs to forward

whatever or identifier needs to be figured out

Easiest way is a counter, but that could cause forged packets (if thats a problem)

darkdrgn2k avatar Apr 19 '19 04:04 darkdrgn2k

We will have to decide on defaults for this, maybe it can be on a per pkg basis

Should also have a hard limit on TTL so its not abused. IE broadcast to the WHOLE network. IE no more than 5

darkdrgn2k avatar Apr 19 '19 04:04 darkdrgn2k

Modules/Plugins:

I built this model in bash and i think its pretty simple

Main Service receive packet Content of packet is passed through every shell script in a folder (ie run-parts multhop-system-name-whatever.d/*) similat to nodeinfo.d

Each script process the packet's data and decides what to do with it (if anything).

ie the IPFS process would not care about SSB so it would skip it

The modules would place a file in that folder to deal with a certain type of service if they wanted to ie IPFS would swarm add while SSB would gossip add

darkdrgn2k avatar Apr 19 '19 04:04 darkdrgn2k

This saves on space since a single UDP packet only has about 508 bytes for info to be used reliably

I think your betting on 576 MTU which would never happen on a cjdns/yggdrasill network.

A UDP packet on a standard 1500 MTU network after header overhead is 1460 To be safe for IPSEC/GRE etc some system drop it as low as 1300 If it grows beyond that the packet is fragmented.

Also these packets are informational and will be resent at regular intervals, so if one doesn't make it.. it wont matter

darkdrgn2k avatar Apr 19 '19 04:04 darkdrgn2k

We need a way of identifying each packet so that a node knows if they already received once and it came back, or if its a new one that it needs to forward

So obviously nodes won't send the message back to where they got it from, but messages can still be received twice ofc. I'm thinking the identifier part can just be a randomly generated UUID, possibly a truncated one depending on how many bytes we get. Nodes can cache the UUIDs they know of for a certain amount of time, and recognize messages based off of that.

Easiest way is a counter, but that could cause forged packets (if thats a problem)

Maybe another way to do it would be to have a small signature using the node's public key, the same one their IP address is derived from? So that way nodes will check if the IPv6 address listed in the message matches the public key of the signed part of the message. Idk if that's too intensive or large (byte-wise) though, I'd be happy to hear your thoughts.

We will have to decide on defaults for this, maybe it can be on a per pkg basis

Should also have a hard limit on TTL so its not abused. IE broadcast to the WHOLE network. IE no more than 5

I was talking about defaults for notification, which each pkg should decide, but be able to be overriden. But about TTL, I agree yeah. This can be enforced by other nodes, who will drop any packet with a TTL larger than 5, or whatever we decide on later.

I built this model in bash and i think its pretty simple [...]

That sounds like a great model, and pretty simple too. My only concern is that passing the packet through each script could take a long time as more services/scripts get added, so we'll have to watch out for that.

Another model could be to have sub-folders like whatever.d/IPFS/ and whatever.d/SSB/, each sub-folder having multiple scripts inside it. So we only run the scripts that are known to handle IPFS services when the node gets a packet about IPFS.

I think your betting on 576 MTU which would never happen on a cjdns/yggdrasill network.

Good point. CJDNS MTU is 1304 with headers subtracted (chat, file), and Yggdrasil MTU is very high, 65535.

One thing I said you didn't comment on:

Potentially just contains a list of services, and then an interested node can reply and ask for the info for a specific service

Is this a good model, or now that we have more packet space, should nodes send out a list of all their services with their relevant info? You also didn't comment on my suggestion of using Cap'n Proto instead, what do you think of that? Especially if we're doing binary stuff like signatures, or listing many services, I think it'll be more efficient.

Some things I didn't mention in the original post:

  • These messages would need an assigned port that all the nodes use to receive them and reply to them

makew0rld avatar Apr 19 '19 17:04 makew0rld