You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
Ethan Buchman 9529f12c28 more linting 7 years ago
..
trust more linting 7 years ago
upnp linting: moar fixes 7 years ago
CHANGELOG.md move into p2p package 8 years ago
Dockerfile go-p2p -> tendermint/p2p 8 years ago
README.md p2p: update readme, some minor things 7 years ago
addrbook.go lil fixes 7 years ago
addrbook_test.go minor fixes from review 7 years ago
conn_go110.go p2p: use fake net.Pipe since only >=Go1.10 implements SetDeadline 7 years ago
conn_notgo110.go p2p: netPipe for <Go1.10 in own file with own build tag 7 years ago
connection.go lil fixes 7 years ago
connection_test.go errcheck; sort some stuff out 7 years ago
fuzz.go more linting 7 years ago
listener.go lil fixes 7 years ago
listener_test.go linting errors: tackle p2p package 7 years ago
netaddress.go core: apply megacheck vet tool (unused, gosimple, staticcheck) 8 years ago
netaddress_test.go fix test using uncommon names 7 years ago
peer.go Tests almost passing 7 years ago
peer_set.go peer interface 7 years ago
peer_set_test.go linting errors: tackle p2p package 7 years ago
peer_test.go linting errors: tackle p2p package 7 years ago
pex_reactor.go more linting 7 years ago
pex_reactor_test.go errcheck; sort some stuff out 7 years ago
secret_connection.go more linting 7 years ago
secret_connection_test.go linting errors: tackle p2p package 7 years ago
switch.go address linting FIXMEs 7 years ago
switch_test.go address linting FIXMEs 7 years ago
types.go more linting 7 years ago
util.go more linting 7 years ago
version.go move into p2p package 8 years ago

README.md

tendermint/tendermint/p2p

CircleCI

tendermint/tendermint/p2p provides an abstraction around peer-to-peer communication.

MConnection

MConnection is a multiplex connection:

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 Channels. 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.

The MConnection supports three packet types: Ping, Pong, and Msg.

Ping and Pong

The ping and pong messages consist of writing a single byte to the connection; 0x1 and 0x2, respectively

When we haven't received any messages on an MConnection in a time pingTimeout, we send a ping message. When a ping is received on the MConnection, a pong is sent in response.

If a pong is not received in sufficient time, the peer's score should be decremented (TODO).

Msg

Messages in channels are chopped into smaller msgPackets for multiplexing.

type msgPacket struct {
	ChannelID byte
	EOF       byte // 1 means message ends here.
	Bytes     []byte
}

The msgPacket is serialized using go-wire, and prefixed with a 0x3. The received Bytes of a sequential set of packets are appended together until a packet with EOF=1 is received, at which point the complete serialized message is returned for processing by the corresponding channels onReceive function.

Multiplexing

Messages are sent from a single sendRoutine, which loops over a select statement that results in the sending of a ping, a pong, or a batch of data messages. The batch of data messages may include messages from multiple channels. Message bytes are queued for sending in their respective channel, with each channel holding one unsent message at a time. Messages are chosen for a batch one a time from the channel with the lowest ratio of recently sent bytes to channel priority.

Sending Messages

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.

Peer

Each peer has one MConnection instance, and includes other information such as whether the connection was outbound, whether the connection should be recreated if it closes, various identity information about the node, and other higher level thread-safe data used by the reactors.

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, ...})