Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added wire protocol description #9

Merged
merged 4 commits into from
Jun 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion protocol/network/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,34 @@ type StreamHandler func (Stream)

TODO: incorporate unreliable message / packet streams.

#### Communication Model - Streams
### Protocol Interface

The network protocol consists of:

- Any secure, reliable, stream transport:
- a reliable transport protocol (TCP, QUIC, SCTP, UDT, UTP, ...)
- a secure PKI based transport protocol (SSH, TLS, ...)
- a stream transport (with flow control, etc) (HTTP2, SSH, QUIC)
- Protocol stream framing, to multiplex services
- Auxiliary protocols for connectivity:
- Identify - exchange node information
- NAT - NAT Traversal (ICE)
- Relay - for when NAT Traversal fails

Both the transport and stream muxer are pluggable. Unless
constraints dictate otherwise, implementations SHOULD implement TCP and HTTP/2
for interoperability. These are the default

- any reliable transport protocol
- a secure channel encryption
- a stream multiplexor with flow control (e.g. HTTP/2, SPDY, QUIC, SSH)
- every stream protocol header

(TODO: unreliable transport)

## Properties

### Communication Model - Streams

The Network layer handles all the problems of connecting to a peer, and exposes
simple bidirectional streams. Users can both open a new stream
Expand Down
105 changes: 105 additions & 0 deletions protocol/network/wire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@

# IPFS Protocol on the Wire

Authors: [Juan Benet](http://github.com/jbenet)

Reviewers:


* * *

This [spec](../../) describes the IPFS protocol on the wire.

As explained in the [network spec](./), IPFS is [transport agnostic](./#transport-agnostic). We have the **hard constraint** of making IPFS work across _any_ duplex stream (an outgoing and an incoming stream pair, any arbitrary connection) and work on _any_ platform.

To make this work, IPFS has to solve a few problems:

- [Protocol Multiplexing](#protocol-multiplexing) - running multiple protocols over the same stream
- [multistream](#multistream) - self-describing protocol streams
- [multistream-select](#multistream-select) - a self-describing protocol selector
- [Stream Multiplexing](#stream-multiplexing) - running many independent streams over the same wire.
- [Portable Encodings](#portable-encodings) - using portable serialization formats
- [Secure Communications](#secure-communication) - using ciphersuites to establish security and privacy (like TLS).

## Protocol-Multiplexing

Protocol Multiplexing means running multiple different protocols over the same stream. This could happen sequentially (one after the other), or concurrently (at the same time, with their messages interleaved). We achieve protocol multiplexing using three pieces:

- [multistream](#multistream) - self-describing protocol streams
- [multistream-select](#multistream-select) - a self-describing protocol selector
- [Stream Multiplexing](#stream-multiplexing) - running many independent streams over the same wire.

### multistream - self-describing protocol stream

[multistream](https://github.com/jbenet/multistream) is a self-describing protocol stream format. It is extremely simple. Its goal is to define a way to add headers to protocols that describe the protocol itself. It is sort of like adding versions to a protocol, but being extremely explicit.

For example:

```
/ipfs/QmVXZiejj3sXEmxuQxF2RjmFbEiE9w7T82xDn3uYNuhbFb/ipfs-dht/0.2.3
<dht-message>
<dht-message>
...
```

### multistream-selector - self-describing protocol stream selector

[multistream-select](https://github.com/jbenet/multistream/tree/master/multistream-select) is a simple [multistream](https://github.com/jbenet/multistream) protocol that allows listing and selecting other protocols. This means that Protomux has a list of registered protocols, listens for one, and then _nests_ (or upgrades) the connection to speak the registered protocol. This takes direct advantage of multistream: it enables interleaving multiple protocols, as well as inspecting what protocols might be spoken by the remote endpoint.

For example:

```
/ipfs/QmdRKVhvzyATs3L6dosSb6w8hKuqfZK2SyPVqcYJ5VLYa2/multistream-select/0.3.0
/ipfs/QmVXZiejj3sXEmxuQxF2RjmFbEiE9w7T82xDn3uYNuhbFb/ipfs-dht/0.2.3
<dht-message>
<dht-message>
...
```

### Stream Multiplexing

Stream Multiplexing is the process of multiplexing (or combining) many different streams into a single one. This is a complicated subject because it enables protocols to run concurrently over the same wire. And all sorts of notions regarding fairness, flow control, head-of-line blocking, etc. start affecting the protocols. In practice, stream multiplexing is well understood and there are many stream multiplexing protocols. To name a few:

- HTTP/2
- SPDY
- QUIC
- SSH

IPFS nodes are free to support whatever stream multiplexors they wish, on top of the default one. The default one is there to enable even the simplest of nodes to speak multiple protocols at once. The default multiplexor will be HTTP/2 (or maybe QUIC?), but implementations for it are sparse, so we are beginning with SPDY. We simply select which protocol to use with a multistream header.

For example:

```
/ipfs/QmdRKVhvzyATs3L6dosSb6w8hKuqfZK2SyPVqcYJ5VLYa2/multistream-select/0.3.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supporting several multistream-select versions is part of the desired feature set also?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessarily, but the version is there to make it clear what version it is in a human readable sense? we don't actually need it-- the hash is enough.

/ipfs/Qmb4d8ZLuqnnVptqTxwqt3aFqgPYruAbfeksvRV1Ds8Gri/spdy/3
<spdy-header-opening-a-stream-0>
/ipfs/QmVXZiejj3sXEmxuQxF2RjmFbEiE9w7T82xDn3uYNuhbFb/ipfs-dht/0.2.3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do these hashes come from?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i should probably make real examples that are resolvable. the idea is that you'd have the specs in directories that give the protocol name + version number, and then we'd publish them with ipfs, getting a resulting root hash. this allows the hashes to be resolved for and look at the spec. but yeah, these particular hashes aren't resolvable because i made them up. perhaps they should be for more clear examples. (may also be relevant to link directly to commit objects once we have those.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is so cool.

<dht-message>
<dht-message>
<spdy-header-opening-a-stream-1>
/ipfs/QmVXZiejj3sXEmxuQxF2RjmFbEiE9w7T82xDn3uYNuhbFb/ipfs-bitswap/0.3.0
<bitswap-message>
<bitswap-message>
<spdy-header-selecting-stream-0>
<dht-message>
<dht-message>
<dht-message>
<dht-message>
<spdy-header-selecting-stream-1>
<bitswap-message>
<bitswap-message>
<bitswap-message>
<bitswap-message>
...
```

## Portable Encodings

In order to be ubiquitous, we _must_ use hyper-portable format encodings, those that are easy to use in various other platforms. Ideally these encodings are well-tested in the wild, and widely used. There may be cases where multiple encodings have to be supported (and hence we may need a [multicodec](https://github.com/jbenet/multicodec) self-describing encoding), but this has so far not been needed.

For now, we use [protobuf](https://github.com/google/protobuf) for all protocol messages exclusively, but other good candidates are [capnp](https://capnproto.org), [bson](http://bsonspec.org/), [ubjson](http://ubjson.org/).


## Secure Communications

The wire protocol is -- of course -- wrapped with encryption. We use cyphersuites similar to TLS. This is explained further in the [network spec](./#encryption).