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.

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