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.

122 lines
4.3 KiB

9 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. # `tendermint/tendermint/p2p`
  2. [![CircleCI](https://circleci.com/gh/tendermint/tendermint/p2p.svg?style=svg)](https://circleci.com/gh/tendermint/tendermint/p2p)
  3. `tendermint/tendermint/p2p` provides an abstraction around peer-to-peer communication.<br/>
  4. ## MConnection
  5. `MConnection` is a multiplex connection:
  6. __multiplex__ *noun* a system or signal involving simultaneous transmission of
  7. several messages along a single channel of communication.
  8. Each `MConnection` handles message transmission on multiple abstract communication
  9. `Channel`s. Each channel has a globally unique byte id.
  10. The byte id and the relative priorities of each `Channel` are configured upon
  11. initialization of the connection.
  12. The `MConnection` supports three packet types: Ping, Pong, and Msg.
  13. ### Ping and Pong
  14. The ping and pong messages consist of writing a single byte to the connection; 0x1 and 0x2, respectively
  15. When we haven't received any messages on an `MConnection` in a time `pingTimeout`, we send a ping message.
  16. When a ping is received on the `MConnection`, a pong is sent in response.
  17. If a pong is not received in sufficient time, the peer's score should be decremented (TODO).
  18. ### Msg
  19. Messages in channels are chopped into smaller msgPackets for multiplexing.
  20. ```
  21. type msgPacket struct {
  22. ChannelID byte
  23. EOF byte // 1 means message ends here.
  24. Bytes []byte
  25. }
  26. ```
  27. The msgPacket is serialized using go-wire, and prefixed with a 0x3.
  28. The received `Bytes` of a sequential set of packets are appended together
  29. until a packet with `EOF=1` is received, at which point the complete serialized message
  30. is returned for processing by the corresponding channels `onReceive` function.
  31. ### Multiplexing
  32. Messages are sent from a single `sendRoutine`, which loops over a select statement that results in the sending
  33. of a ping, a pong, or a batch of data messages. The batch of data messages may include messages from multiple channels.
  34. Message bytes are queued for sending in their respective channel, with each channel holding one unsent message at a time.
  35. Messages are chosen for a batch one a time from the channel with the lowest ratio of recently sent bytes to channel priority.
  36. ## Sending Messages
  37. There are two methods for sending messages:
  38. ```go
  39. func (m MConnection) Send(chID byte, msg interface{}) bool {}
  40. func (m MConnection) TrySend(chID byte, msg interface{}) bool {}
  41. ```
  42. `Send(chID, msg)` is a blocking call that waits until `msg` is successfully queued
  43. for the channel with the given id byte `chID`. The message `msg` is serialized
  44. using the `tendermint/wire` submodule's `WriteBinary()` reflection routine.
  45. `TrySend(chID, msg)` is a nonblocking call that returns false if the channel's
  46. queue is full.
  47. `Send()` and `TrySend()` are also exposed for each `Peer`.
  48. ## Peer
  49. Each peer has one `MConnection` instance, and includes other information such as whether the connection
  50. was outbound, whether the connection should be recreated if it closes, various identity information about the node,
  51. and other higher level thread-safe data used by the reactors.
  52. ## Switch/Reactor
  53. The `Switch` handles peer connections and exposes an API to receive incoming messages
  54. on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one
  55. or more `Channels`. So while sending outgoing messages is typically performed on the peer,
  56. incoming messages are received on the reactor.
  57. ```go
  58. // Declare a MyReactor reactor that handles messages on MyChannelID.
  59. type MyReactor struct{}
  60. func (reactor MyReactor) GetChannels() []*ChannelDescriptor {
  61. return []*ChannelDescriptor{ChannelDescriptor{ID:MyChannelID, Priority: 1}}
  62. }
  63. func (reactor MyReactor) Receive(chID byte, peer *Peer, msgBytes []byte) {
  64. r, n, err := bytes.NewBuffer(msgBytes), new(int64), new(error)
  65. msgString := ReadString(r, n, err)
  66. fmt.Println(msgString)
  67. }
  68. // Other Reactor methods omitted for brevity
  69. ...
  70. switch := NewSwitch([]Reactor{MyReactor{}})
  71. ...
  72. // Send a random message to all outbound connections
  73. for _, peer := range switch.Peers().List() {
  74. if peer.IsOutbound() {
  75. peer.Send(MyChannelID, "Here's a random message")
  76. }
  77. }
  78. ```
  79. ### PexReactor/AddrBook
  80. A `PEXReactor` reactor implementation is provided to automate peer discovery.
  81. ```go
  82. book := p2p.NewAddrBook(addrBookFilePath)
  83. pexReactor := p2p.NewPEXReactor(book)
  84. ...
  85. switch := NewSwitch([]Reactor{pexReactor, myReactor, ...})
  86. ```