|
|
- package p2p
-
- import (
- "bytes"
- "errors"
- "io"
-
- . "github.com/tendermint/tendermint/binary"
- )
-
- var pexErrInvalidMessage = errors.New("Invalid PEX message")
-
- const pexCh = "PEX"
-
- /*
- The PexHandler routine should be started separately from the Switch.
- It handles basic PEX communciation.
- The application is responsible for sending out a PexRequestMessage.
- */
- func PexHandler(s *Switch, addrBook *AddrBook) {
-
- for {
- inPkt := s.Receive(pexCh) // {Peer, Time, Packet}
- if inPkt == nil {
- // Client has stopped
- break
- }
-
- // decode message
- msg := decodeMessage(inPkt.Bytes)
-
- switch msg.(type) {
- case *PexRequestMessage:
- // inPkt.Peer requested some peers.
- // TODO: prevent abuse.
- addrs := 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 {
- addrBook.AddAddress(addr, srcAddr)
- }
- default:
- // Bad peer.
- s.StopPeerForError(inPkt.Peer, pexErrInvalidMessage)
- }
- }
-
- // cleanup
-
- }
-
- /* Messages */
-
- const (
- pexTypeUnknown = Byte(0x00)
- pexTypeRequest = Byte(0x01)
- pexTypeResponse = Byte(0x02)
- )
-
- // 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
- }
- }
-
- /*
- A response with peer addresses
- */
- 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 {
- Addrs []*NetAddress
- }
-
- func readPexResponseMessage(r io.Reader) *pexResponseMessage {
- numAddrs := int(ReadUInt32(r))
- addrs := []*NetAddress{}
- for i := 0; i < numAddrs; i++ {
- addr := ReadNetAddress(r)
- addrs = append(addrs, addr)
- }
- return &pexResponseMessage{
- Addrs: addrs,
- }
- }
-
- func (m *pexResponseMessage) WriteTo(w io.Writer) (n int64, err error) {
- n, err = WriteOnto(pexTypeResponse, w, n, err)
- n, err = WriteOnto(UInt32(len(m.Addrs)), w, n, err)
- for _, addr := range m.Addrs {
- n, err = WriteOnto(addr, w, n, err)
- }
- return
- }
|