2017-04-21 18:19:41 -04:00
|
|
|
# `tendermint/tendermint/p2p`
|
2015-10-25 18:21:51 -07:00
|
|
|
|
2017-04-21 18:19:41 -04:00
|
|
|
[](https://circleci.com/gh/tendermint/tendermint/p2p)
|
2016-06-21 14:40:24 -04:00
|
|
|
|
2017-04-21 18:19:41 -04:00
|
|
|
`tendermint/tendermint/p2p` provides an abstraction around peer-to-peer communication.<br/>
|
2015-10-25 18:21:51 -07:00
|
|
|
|
|
|
|
## Peer/MConnection/Channel
|
|
|
|
|
|
|
|
Each peer has one `MConnection` (multiplex connection) instance.
|
|
|
|
|
|
|
|
__multiplex__ *noun* a system or signal involving simultaneous transmission of
|
|
|
|
several messages along a single channel of communication.
|
|
|
|
|
|
|
|
Each `MConnection` handles message transmission on multiple abstract communication
|
|
|
|
`Channel`s. Each channel has a globally unique byte id.
|
|
|
|
The byte id and the relative priorities of each `Channel` are configured upon
|
|
|
|
initialization of the connection.
|
|
|
|
|
|
|
|
There are two methods for sending messages:
|
|
|
|
```go
|
|
|
|
func (m MConnection) Send(chID byte, msg interface{}) bool {}
|
|
|
|
func (m MConnection) TrySend(chID byte, msg interface{}) bool {}
|
|
|
|
```
|
|
|
|
|
|
|
|
`Send(chID, msg)` is a blocking call that waits until `msg` is successfully queued
|
|
|
|
for the channel with the given id byte `chID`. The message `msg` is serialized
|
|
|
|
using the `tendermint/wire` submodule's `WriteBinary()` reflection routine.
|
|
|
|
|
|
|
|
`TrySend(chID, msg)` is a nonblocking call that returns false if the channel's
|
|
|
|
queue is full.
|
|
|
|
|
|
|
|
`Send()` and `TrySend()` are also exposed for each `Peer`.
|
|
|
|
|
|
|
|
## Switch/Reactor
|
|
|
|
|
|
|
|
The `Switch` handles peer connections and exposes an API to receive incoming messages
|
|
|
|
on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one
|
|
|
|
or more `Channels`. So while sending outgoing messages is typically performed on the peer,
|
|
|
|
incoming messages are received on the reactor.
|
|
|
|
|
|
|
|
```go
|
|
|
|
// Declare a MyReactor reactor that handles messages on MyChannelID.
|
|
|
|
type MyReactor struct{}
|
|
|
|
|
|
|
|
func (reactor MyReactor) GetChannels() []*ChannelDescriptor {
|
|
|
|
return []*ChannelDescriptor{ChannelDescriptor{ID:MyChannelID, Priority: 1}}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (reactor MyReactor) Receive(chID byte, peer *Peer, msgBytes []byte) {
|
|
|
|
r, n, err := bytes.NewBuffer(msgBytes), new(int64), new(error)
|
|
|
|
msgString := ReadString(r, n, err)
|
|
|
|
fmt.Println(msgString)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other Reactor methods omitted for brevity
|
|
|
|
...
|
|
|
|
|
|
|
|
switch := NewSwitch([]Reactor{MyReactor{}})
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
// Send a random message to all outbound connections
|
|
|
|
for _, peer := range switch.Peers().List() {
|
|
|
|
if peer.IsOutbound() {
|
|
|
|
peer.Send(MyChannelID, "Here's a random message")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### PexReactor/AddrBook
|
|
|
|
|
|
|
|
A `PEXReactor` reactor implementation is provided to automate peer discovery.
|
|
|
|
|
|
|
|
```go
|
|
|
|
book := p2p.NewAddrBook(addrBookFilePath)
|
|
|
|
pexReactor := p2p.NewPEXReactor(book)
|
|
|
|
...
|
|
|
|
switch := NewSwitch([]Reactor{pexReactor, myReactor, ...})
|
|
|
|
```
|