tendermint/peer/pex.go

114 lines
2.3 KiB
Go
Raw Normal View History

2014-07-06 00:16:05 -07:00
package peer
import (
2014-07-06 16:05:47 -07:00
"bytes"
"errors"
2014-07-06 00:16:05 -07:00
"io"
2014-07-06 16:05:47 -07:00
. "github.com/tendermint/tendermint/binary"
2014-07-06 00:16:05 -07:00
)
2014-07-06 16:05:47 -07:00
var pexErrInvalidMessage = errors.New("Invalid PEX message")
2014-07-06 00:16:05 -07:00
const pexCh = "PEX"
func peerExchangeHandler(c *Client) {
for {
2014-07-06 16:05:47 -07:00
inPkt := c.Receive(pexCh) // {Peer, Time, Packet}
if inPkt == nil {
// Client has stopped
break
}
2014-07-06 00:16:05 -07:00
// decode message
2014-07-06 16:05:47 -07:00
msg := decodeMessage(inPkt.Bytes)
switch msg.(type) {
case *pexRequestMessage:
// inPkt.Peer requested some peers.
// TODO: prevent abuse.
addrs := c.addrBook.GetSelection()
response := &pexResponseMessage{Addrs: addrs}
pkt := NewPacket(pexCh, BinaryBytes(response))
queued := inPkt.Peer.TryQueue(pkt)
if !queued {
// ignore
}
case *pexResponseMessage:
// We received some peer addresses from inPkt.Peer.
// TODO: prevent abuse.
// (We don't want to get spammed with bad peers)
srcAddr := inPkt.Peer.RemoteAddress()
for _, addr := range msg.(*pexResponseMessage).Addrs {
c.addrBook.AddAddress(addr, srcAddr)
}
default:
// Bad peer.
c.StopPeerForError(inPkt.Peer, pexErrInvalidMessage)
}
2014-07-06 00:16:05 -07:00
}
// cleanup
}
/* Messages */
const (
2014-07-06 16:05:47 -07:00
pexTypeUnknown = Byte(0x00)
pexTypeRequest = Byte(0x01)
pexTypeResponse = Byte(0x02)
2014-07-06 00:16:05 -07:00
)
2014-07-06 16:05:47 -07:00
// TODO: check for unnecessary extra bytes at the end.
func decodeMessage(bz ByteSlice) (msg Message) {
switch Byte(bz[0]) {
case pexTypeRequest:
return &pexRequestMessage{}
case pexTypeResponse:
return readPexResponseMessage(bytes.NewReader(bz[1:]))
default:
return nil
}
2014-07-06 00:16:05 -07:00
}
/*
A response with peer addresses
*/
2014-07-06 16:05:47 -07:00
type pexRequestMessage struct {
}
func (m *pexRequestMessage) WriteTo(w io.Writer) (n int64, err error) {
n, err = WriteOnto(pexTypeRequest, w, n, err)
return
}
/*
A response with peer addresses
*/
type pexResponseMessage struct {
2014-07-06 00:16:05 -07:00
Addrs []*NetAddress
}
2014-07-06 16:05:47 -07:00
func readPexResponseMessage(r io.Reader) *pexResponseMessage {
2014-07-06 00:16:05 -07:00
numAddrs := int(ReadUInt32(r))
addrs := []*NetAddress{}
for i := 0; i < numAddrs; i++ {
addr := ReadNetAddress(r)
addrs = append(addrs, addr)
}
2014-07-06 16:05:47 -07:00
return &pexResponseMessage{
2014-07-06 00:16:05 -07:00
Addrs: addrs,
}
}
2014-07-06 16:05:47 -07:00
func (m *pexResponseMessage) WriteTo(w io.Writer) (n int64, err error) {
n, err = WriteOnto(pexTypeResponse, w, n, err)
2014-07-06 00:16:05 -07:00
n, err = WriteOnto(UInt32(len(m.Addrs)), w, n, err)
for _, addr := range m.Addrs {
n, err = WriteOnto(addr, w, n, err)
}
return
}