The libp2p daemon is a standalone binary meant to make it easy to bring peer-to-peer networking to new languages without fully porting libp2p and all of its complexities.
At the moment, this is a living document. As such, it will be susceptible to changes until stabilization.
There are two pieces to the libp2p daemon:
- Daemon: A golang daemon that manages libp2p hosts and proxies streams to the end user.
- Client: A library written in any language that controls the daemon over a protocol specified in this document, allowing end users to enjoy the benefits of peer-to-peer networking without implementing a full libp2p stack.
The libp2p daemon and client will communicate with each other over stream sockets with protobuf.
Future implementations may attempt to take advantage of shared memory (shmem) or other IPC constructs.
The data structures are defined in pb/p2pd.proto. All messages are varint-delimited.
Protocols described in pseudo-go. Items of the form [item, ...] are lists of many items.
Any response that may be an error, will take the form of:
Response{
Type: ERROR,
ErrorResponse: {
Msg: <error message>,
},
}
Clients issue an Identify
request when they wish to determine the peer ID and
listen addresses of the daemon.
Client
Request{
Type: IDENTIFY,
}
Daemon
Response{
Type: OK,
IdentifyResponse: {
Id: <daemon peer id>,
Addrs: [<daemon listen addr>, ...],
},
}
Clients issue a Connect
request when they wish to connect to a known peer on a
given set of addresses.
Client
Request{
Type: CONNECT,
ConnectRequest: {
Peer: <peer id>,
Addrs: [<addr>, ...],
timeout: time, // optional, in seconds
},
}
Daemon May return an error.
Response{
Type: OK,
}
Clients issue a Disconnect
request when they wish to disconnect from a peer
Client
Request{
Type: DISCONNECT,
DisconnectRequest: {
Peer: <peer id>,
},
}
Daemon May return an error.
Response{
Type: OK,
}
Clients can issue a LIST_PEERS
request to get a list of IDs of peers the node is connected to.
Client
Request{
Type: LIST_PEERS
}
Daemon May return an error
Response{
Type: OK,
Peers: [<PeerInfo>, ...]
}
Clients issue a StreamOpen
request when they wish to initiate an outbound
stream to a peer on one of a set of protocols.
Client
Request{
Type: STREAM_OPEN,
StreamOpenRequest: {
Peer: <peer id>,
Proto: [<protocol string>, ...],
timeout: time, // optional, in seconds
},
}
Daemon May return an error, short circuiting.
Response{
Type: OK,
StreamInfo: {
Peer: <peer id>,
Addr: <peer address connected to>,
Proto: <protocol we connected on>,
},
}
After writing the response message to the socket, the daemon begins piping the newly created stream to the client over the socket. Clients may read from and write to the socket as if it were the stream. WARNING: When using a unix socket, clients must be careful not to read excess bytes from the socket when parsing the daemon response, otherwise they risk reading into the stream output.
Clients issue a StreamHandler
request to register a handler for inbound
streams on a given protocol. Prior to issuing the request, the client must be
listening at the specified multi-address.
Client
Request{
Type: STREAM_HANDLER,
StreamHandlerRequest: {
Addr: <a multi-address that the client is listening on>,
Proto: [<protocols to route to this handler>, ...],
}
}
Daemon In the event that a stream binding already exists, this will overwrite that stream binding with the one specified in the new request.
Response{
Type: OK,
}
When peers connect to the daemon on a protocol for which our client has a registered handler, the daemon will connect to the client on the registered multi-address.
Daemon
Note: this message is NOT wrapped in a Response
object.
StreamInfo{
Peer: <peer id>,
Addr: <address of the peer>,
Proto: <protocol stream opened on>,
}
After writing the StreamInfo
message, the daemon will once again begin piping
data from the stream to the socket and vice-versa.