This is better than waiting because while we wait, anything could happen (crash, timeout of the code who's using addrbook, ...). If we save immediately, we have much greater chances of success. |
||
---|---|---|
upnp | ||
.gitignore | ||
CHANGELOG.md | ||
Dockerfile | ||
LICENSE | ||
README.md | ||
addrbook.go | ||
addrbook_test.go | ||
config.go | ||
connection.go | ||
connection_test.go | ||
fuzz.go | ||
glide.lock | ||
glide.yaml | ||
ip_range_counter.go | ||
listener.go | ||
listener_test.go | ||
log.go | ||
netaddress.go | ||
netaddress_test.go | ||
peer.go | ||
peer_set.go | ||
peer_set_test.go | ||
peer_test.go | ||
pex_reactor.go | ||
pex_reactor_test.go | ||
secret_connection.go | ||
secret_connection_test.go | ||
switch.go | ||
switch_test.go | ||
types.go | ||
util.go | ||
version.go |
README.md
tendermint/go-p2p
tendermint/go-p2p
provides an abstraction around peer-to-peer communication.
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:
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.
// 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.
book := p2p.NewAddrBook(addrBookFilePath)
pexReactor := p2p.NewPEXReactor(book)
...
switch := NewSwitch([]Reactor{pexReactor, myReactor, ...})