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.

182 lines
3.7 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
  1. package peer
  2. import (
  3. "atomic"
  4. "sync"
  5. )
  6. /* Peer */
  7. type Peer struct {
  8. outgoing bool
  9. conn *Connection
  10. channels map[String]*Channel
  11. mtx sync.Mutex
  12. quit chan struct{}
  13. stopped uint32
  14. }
  15. func (p *Peer) Start(peerInQueues map[String]chan *InboundMsg ) {
  16. for chName, _ := range p.channels {
  17. go p.inHandler(chName, peerInQueues[chName])
  18. go p.outHandler(chName)
  19. }
  20. }
  21. func (p *Peer) Stop() {
  22. // lock
  23. p.mtx.Lock()
  24. if atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
  25. close(p.quit)
  26. p.conn.Stop()
  27. }
  28. p.mtx.Unlock()
  29. // unlock
  30. }
  31. func (p *Peer) LocalAddress() *NetAddress {
  32. return p.conn.LocalAddress()
  33. }
  34. func (p *Peer) RemoteAddress() *NetAddress {
  35. return p.conn.RemoteAddress()
  36. }
  37. func (p *Peer) Channel(chName String) *Channel {
  38. return p.channels[chName]
  39. }
  40. // If msg isn't already in the peer's filter, then
  41. // queue the msg for output.
  42. // If the queue is full, just return false.
  43. func (p *Peer) TryQueueOut(chName String, msg Msg) bool {
  44. channel := p.Channel(chName)
  45. outQueue := channel.OutQueue()
  46. // just return if already in filter
  47. if channel.Filter().Has(msg) {
  48. return true
  49. }
  50. // lock & defer
  51. p.mtx.Lock(); defer p.mtx.Unlock()
  52. if p.stopped == 1 { return false }
  53. select {
  54. case outQueue <- msg:
  55. return true
  56. default: // buffer full
  57. return false
  58. }
  59. // unlock deferred
  60. }
  61. func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
  62. return p.RemoteAddress().WriteTo(w)
  63. }
  64. func (p *Peer) inHandler(chName String, inboundMsgQueue chan<- *InboundMsg) {
  65. channel := p.channels[chName]
  66. inQueue := channel.InQueue()
  67. FOR_LOOP:
  68. for {
  69. select {
  70. case <-quit:
  71. break FOR_LOOP
  72. case msg := <-inQueue:
  73. // add to channel filter
  74. channel.Filter().Add(msg)
  75. // send to inboundMsgQueue
  76. inboundMsg := &InboundMsg{
  77. Peer: p,
  78. Channel: channel,
  79. Time: Time(time.Now()),
  80. Msg: msg,
  81. }
  82. select {
  83. case <-quit:
  84. break FOR_LOOP
  85. case inboundMsgQueue <- inboundMsg:
  86. continue
  87. }
  88. }
  89. }
  90. // cleanup
  91. // (none)
  92. }
  93. func (p *Peer) outHandler(chName String) {
  94. outQueue := p.channels[chName].OutQueue()
  95. FOR_LOOP:
  96. for {
  97. select {
  98. case <-quit:
  99. break FOR_LOOP
  100. case msg := <-outQueue:
  101. // blocks until the connection is Stop'd,
  102. // which happens when this peer is Stop'd.
  103. p.conn.QueueOut(msg.Bytes)
  104. }
  105. }
  106. // cleanup
  107. // (none)
  108. }
  109. /* Channel */
  110. type Channel struct {
  111. name String
  112. mtx sync.Mutex
  113. filter Filter
  114. inQueue chan Msg
  115. outQueue chan Msg
  116. //stats Stats
  117. }
  118. func NewChannel(name String, filter Filter, in, out chan Msg) *Channel {
  119. return &Channel{
  120. name: name,
  121. filter: filter,
  122. inQueue: in,
  123. outQueue: out,
  124. }
  125. }
  126. func (c *Channel) InQueue() <-chan Msg {
  127. return c.inQueue
  128. }
  129. func (c *Channel) OutQueue() chan<- Msg {
  130. return c.outQueue
  131. }
  132. func (c *Channel) Add(msg Msg) {
  133. c.Filter().Add(msg)
  134. }
  135. func (c *Channel) Has(msg Msg) bool {
  136. return c.Filter().Has(msg)
  137. }
  138. // TODO: maybe don't expose this
  139. func (c *Channel) Filter() Filter {
  140. // lock & defer
  141. c.mtx.Lock(); defer c.mtx.Unlock()
  142. return c.filter
  143. // unlock deferred
  144. }
  145. // TODO: maybe don't expose this
  146. func (c *Channel) UpdateFilter(filter Filter) {
  147. // lock
  148. c.mtx.Lock()
  149. c.filter = filter
  150. c.mtx.Unlock()
  151. // unlock
  152. }