169 lines
6.9 KiB
Markdown
169 lines
6.9 KiB
Markdown
# P2pChat
|
|
|
|
## Wire-Protocol
|
|
|
|
The protocol is separated into two parts.
|
|
The lower layer takes care of p2p coordination while the upper chat layer sits on top of it.
|
|
|
|
### P2P
|
|
|
|
This protocol layer takes care of establishing a coherent Peer-to-Peer network over which arbitrary data can be transported from one node to another without regard to the underlying network topology.
|
|
|
|
It requires datagram transport from the IP layer between nodes full messh reachability is not required.
|
|
To upper layers (e.g. the chat protocol) it offers unreliable transport between arbitrary nodes of the network and addressing by node IDs instead of IP addresses.
|
|
|
|
#### Concepts
|
|
|
|
- **netid**: A unique 32bit identifier of each node
|
|
- **local neighbor**: A local neighbor of node A is another node B that can be directly contacted by node A without NAT or firewalling.
|
|
- **remote neighbor**: A remote neighbor of node A is another node B that is part of the same P2P network but which cannot be reached directly via UDP datagrams and only through traversing the P2P network.
|
|
|
|
#### General Protocol Provisions
|
|
|
|
The protocol is encoded in binary and uses the following common header:
|
|
|
|
```
|
|
0 7 8 15 16 23 24 31
|
|
+-----------+-----------+-----------+------------+
|
|
| magic | version | message | flags |
|
|
| | | type | |
|
|
+-----------+-----------+-----------+------------+
|
|
| nonce |
|
|
| |
|
|
+-----------+-----------+-----------+------------+
|
|
| src netid |
|
|
| |
|
|
+-----------+-----------+-----------+------------+
|
|
| dst netid |
|
|
| |
|
|
+-----------+-----------+-----------+------------+
|
|
```
|
|
|
|
- *magic*: The 8 bit constant value `0xAC`. It identifies this message as a P2P message.
|
|
- *version*: 8 bit unsigned integer denoting the protocol version. In this spec always `0x01`.
|
|
- *message type*: 8 bit identifying the type of payload this message carries.
|
|
- *nonce*: A 32 bit, randomly generated, unique number associated with each packet.
|
|
- *src netid*: The unique identifier of the node who originated this message.
|
|
- *dst netidc*: The unique identifier of the node who this message is intended for.
|
|
|
|
| Flag Bit | Name | Description |
|
|
| -------- | :--: | ----------- |
|
|
| `10000000` | NO_FORWARD | This message should not be forwarded even if the recipient is not the target node |
|
|
| `01000000` | *reserved* | |
|
|
| `00100000` | *reserved* | |
|
|
| `00010000` | *reserved* | |
|
|
| `00001000` | *reserved* | |
|
|
| `00000100` | *reserved* | |
|
|
| `00000010` | *reserved* | |
|
|
| `00000001` | *reserved* | |
|
|
|
|
If a node receives a message without the NO_FORWARD flag set, and its own netid is not the *dst netid*, then it SHOULD forward the message unaltered to all its connected neighbors.
|
|
To prevent packet loops, all participating nodes MUST store a hash of each received packet and not forward packets again that it has already processed. The local hash table SHOULD NOT be cleared more often than every 5 minutes.
|
|
|
|
#### Special netids
|
|
|
|
The following special netids are defined:
|
|
|
|
| netid | name | description |
|
|
| :---: | ---- | ----------- |
|
|
| `0` | any node | For message forwarding, all nodes consider this *dst netid* their own and do not forward the message |
|
|
| `0xFFFFFFFF` | all nodes | For message forwarding, all nodes consider *dst netid* their own and forward the message to all their neighbors |
|
|
|
|
#### Message Type *Hello*
|
|
|
|
- Message Type: `0x01`
|
|
|
|
This message is the introductory message that a new node sends to any node of the network it can reach and which identifies the new one.
|
|
It has no payload.
|
|
|
|
Any node which receives a *Hello* message SHOULD add the sending node to it's local neighbor table and associate the src IP address of the packet with that sending node.
|
|
|
|
#### Message Type *Goodbye*
|
|
|
|
- Message Type: `0x02`
|
|
|
|
This message type MAY be sent by a node who is going offline or which is intending to leave the network.
|
|
It has no payload.
|
|
|
|
#### Message Type *Ping*
|
|
|
|
- Message Type `0x03`
|
|
|
|
A message which MAY be originated by a node to check for reachability of other nodes in the network.
|
|
Nodes which receive this message SHOULD respond with a *Pong* message.
|
|
It has no payload.
|
|
|
|
#### Message Type *Pong*
|
|
|
|
- Message Type `0x04`
|
|
|
|
A message which MUST ONLY be originated by a node in response to a previous *Ping* message.
|
|
It has no payload.
|
|
|
|
#### Message Type *Inform*
|
|
|
|
- Message Type `0x05`
|
|
|
|
This message may be sent by a node to inform it's neighbors about other neighbors.
|
|
|
|
For example, if Node A is a local neighbor of Node B, Node B could use this message to signal a third Node C that Node A exists.
|
|
Node C could then try to reach Node A on it's own and/or add it to it's remote neighbor table.
|
|
|
|
It has the following payload:
|
|
```
|
|
0 7 8 15 16 23 24 31
|
|
+-----------+-----------+-----------+------------+
|
|
| subject netid |
|
|
| |
|
|
+-----------+-----------+-----------+------------+
|
|
| subject ip address |
|
|
| |
|
|
+ + + + +
|
|
| |
|
|
| |
|
|
+ + + + +
|
|
| |
|
|
| |
|
|
+ + + + +
|
|
| |
|
|
| |
|
|
+-----------+-----------+-----------+------------+
|
|
| subject port |
|
|
| |
|
|
+-----------+-----------+
|
|
```
|
|
|
|
- *subject netid*: The netid of the third node which is being informed about (Node A in the example above).
|
|
- *subject ip address*: The IP Address at which the third node was reachable for the node which originated this message.
|
|
It is always assumed to be an IPv6 address by default but the special *IPv4-mapped address space* `::ffff:0:0/96` may be used to encode an IPv4 address in the last 32 bits.
|
|
- *subject port*: The port at which the third node was reachable for the node with originated this message.
|
|
|
|
#### Message Type *Data*
|
|
|
|
- Message Type `0x10`
|
|
|
|
This message is used for actual data transfer between nodes.
|
|
It's payload makes up the remainder of the UDP datagram and the content is up to the upper protocol to decide.
|
|
|
|
|
|
### Chat
|
|
|
|
TODO
|
|
|
|
## Installation
|
|
|
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
|
by adding `p2p_chat` to your list of dependencies in `mix.exs`:
|
|
|
|
```elixir
|
|
def deps do
|
|
[
|
|
{:p2p_chat, "~> 0.1.0"}
|
|
]
|
|
end
|
|
```
|
|
|
|
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
|
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
|
be found at <https://hexdocs.pm/p2p_chat>.
|
|
|