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.

239 lines
4.8 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. package p2p
  2. import (
  3. "fmt"
  4. "io"
  5. "sync/atomic"
  6. "time"
  7. . "github.com/tendermint/tendermint/binary"
  8. )
  9. /* Peer */
  10. type Peer struct {
  11. outgoing bool
  12. conn *Connection
  13. channels map[string]*Channel
  14. quit chan struct{}
  15. started uint32
  16. stopped uint32
  17. }
  18. func newPeer(conn *Connection, channels map[string]*Channel) *Peer {
  19. return &Peer{
  20. conn: conn,
  21. channels: channels,
  22. quit: make(chan struct{}),
  23. stopped: 0,
  24. }
  25. }
  26. func (p *Peer) start(pktRecvQueues map[string]chan *InboundPacket, onPeerError func(*Peer, interface{})) {
  27. log.Debugf("Starting %v", p)
  28. if atomic.CompareAndSwapUint32(&p.started, 0, 1) {
  29. // on connection error
  30. onError := func(r interface{}) {
  31. p.stop()
  32. onPeerError(p, r)
  33. }
  34. p.conn.Start(p.channels, onError)
  35. for chName, _ := range p.channels {
  36. chInQueue := pktRecvQueues[chName]
  37. go p.recvHandler(chName, chInQueue)
  38. go p.sendHandler(chName)
  39. }
  40. }
  41. }
  42. func (p *Peer) stop() {
  43. if atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
  44. log.Debugf("Stopping %v", p)
  45. close(p.quit)
  46. p.conn.Stop()
  47. }
  48. }
  49. func (p *Peer) LocalAddress() *NetAddress {
  50. return p.conn.LocalAddress()
  51. }
  52. func (p *Peer) RemoteAddress() *NetAddress {
  53. return p.conn.RemoteAddress()
  54. }
  55. func (p *Peer) Channel(chName string) *Channel {
  56. return p.channels[chName]
  57. }
  58. // TryQueue returns true if the packet was successfully queued.
  59. // Returning true does not imply that the packet will be sent.
  60. func (p *Peer) TryQueue(pkt Packet) bool {
  61. channel := p.Channel(string(pkt.Channel))
  62. sendQueue := channel.sendQueue
  63. if atomic.LoadUint32(&p.stopped) == 1 {
  64. return false
  65. }
  66. sendQueue <- pkt
  67. return true
  68. select {
  69. case sendQueue <- pkt:
  70. return true
  71. default: // buffer full
  72. return false
  73. }
  74. }
  75. func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
  76. return p.RemoteAddress().WriteTo(w)
  77. }
  78. func (p *Peer) String() string {
  79. return fmt.Sprintf("Peer{%v-%v,o:%v}", p.LocalAddress(), p.RemoteAddress(), p.outgoing)
  80. }
  81. // sendHandler pulls from a channel and pushes to the connection.
  82. // Each channel gets its own sendHandler goroutine;
  83. // Golang's channel implementation handles the scheduling.
  84. func (p *Peer) sendHandler(chName string) {
  85. log.Tracef("%v sendHandler [%v]", p, chName)
  86. channel := p.channels[chName]
  87. sendQueue := channel.sendQueue
  88. FOR_LOOP:
  89. for {
  90. select {
  91. case <-p.quit:
  92. break FOR_LOOP
  93. case pkt := <-sendQueue:
  94. log.Tracef("Sending packet to peer sendQueue")
  95. // blocks until the connection is Stop'd,
  96. // which happens when this peer is Stop'd.
  97. p.conn.Send(pkt)
  98. }
  99. }
  100. log.Tracef("%v sendHandler [%v] closed", p, chName)
  101. // cleanup
  102. // (none)
  103. }
  104. // recvHandler pulls from a channel and pushes to the given pktRecvQueue.
  105. // Each channel gets its own recvHandler goroutine.
  106. // Many peers have goroutines that push to the same pktRecvQueue.
  107. // Golang's channel implementation handles the scheduling.
  108. func (p *Peer) recvHandler(chName string, pktRecvQueue chan<- *InboundPacket) {
  109. log.Tracef("%v recvHandler [%v]", p, chName)
  110. channel := p.channels[chName]
  111. recvQueue := channel.recvQueue
  112. FOR_LOOP:
  113. for {
  114. select {
  115. case <-p.quit:
  116. break FOR_LOOP
  117. case pkt := <-recvQueue:
  118. // send to pktRecvQueue
  119. inboundPacket := &InboundPacket{
  120. Peer: p,
  121. Time: Time{time.Now()},
  122. Packet: pkt,
  123. }
  124. select {
  125. case <-p.quit:
  126. break FOR_LOOP
  127. case pktRecvQueue <- inboundPacket:
  128. continue
  129. }
  130. }
  131. }
  132. log.Tracef("%v recvHandler [%v] closed", p, chName)
  133. // cleanup
  134. // (none)
  135. }
  136. /* ChannelDescriptor */
  137. type ChannelDescriptor struct {
  138. Name string
  139. SendBufferSize int
  140. RecvBufferSize int
  141. }
  142. /* Channel */
  143. type Channel struct {
  144. name string
  145. recvQueue chan Packet
  146. sendQueue chan Packet
  147. //stats Stats
  148. }
  149. func newChannel(desc ChannelDescriptor) *Channel {
  150. return &Channel{
  151. name: desc.Name,
  152. recvQueue: make(chan Packet, desc.RecvBufferSize),
  153. sendQueue: make(chan Packet, desc.SendBufferSize),
  154. }
  155. }
  156. func (c *Channel) Name() string {
  157. return c.name
  158. }
  159. func (c *Channel) RecvQueue() <-chan Packet {
  160. return c.recvQueue
  161. }
  162. func (c *Channel) SendQueue() chan<- Packet {
  163. return c.sendQueue
  164. }
  165. /* Packet */
  166. /*
  167. Packet encapsulates a ByteSlice on a Channel.
  168. */
  169. type Packet struct {
  170. Channel String
  171. Bytes ByteSlice
  172. // Hash
  173. }
  174. func NewPacket(chName String, bytes ByteSlice) Packet {
  175. return Packet{
  176. Channel: chName,
  177. Bytes: bytes,
  178. }
  179. }
  180. func (p Packet) WriteTo(w io.Writer) (n int64, err error) {
  181. n, err = WriteOnto(p.Channel, w, n, err)
  182. n, err = WriteOnto(p.Bytes, w, n, err)
  183. return
  184. }
  185. func ReadPacketSafe(r io.Reader) (pkt Packet, err error) {
  186. chName, err := ReadStringSafe(r)
  187. if err != nil {
  188. return
  189. }
  190. // TODO: packet length sanity check.
  191. bytes, err := ReadByteSliceSafe(r)
  192. if err != nil {
  193. return
  194. }
  195. return NewPacket(chName, bytes), nil
  196. }
  197. /*
  198. InboundPacket extends Packet with fields relevant to incoming packets.
  199. */
  200. type InboundPacket struct {
  201. Peer *Peer
  202. Time Time
  203. Packet
  204. }