Official cwtch.im peer and server implementations. https://cwtch.im
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

99 satır
2.2 KiB

  1. package plugins
  2. import (
  3. "cwtch.im/cwtch/event"
  4. "cwtch.im/cwtch/protocol/connections"
  5. "sync"
  6. "time"
  7. )
  8. const tickTime = 10 * time.Second
  9. const maxBakoff int = 32 // 320 seconds or ~5 min
  10. type peer struct {
  11. id string
  12. state connections.ConnectionState
  13. ticks int
  14. backoff int
  15. }
  16. type contactRetry struct {
  17. bus event.Manager
  18. queue event.Queue
  19. breakChan chan bool
  20. peers sync.Map //[string]*peer
  21. }
  22. // NewContactRetry returns a Plugin that when started will retry connecting to contacts with a backoff timing
  23. func NewContactRetry(bus event.Manager) Plugin {
  24. cr := &contactRetry{bus: bus, queue: event.NewQueue(), breakChan: make(chan bool), peers: sync.Map{}}
  25. return cr
  26. }
  27. func (cr *contactRetry) Start() {
  28. go cr.run()
  29. }
  30. func (cr *contactRetry) run() {
  31. cr.bus.Subscribe(event.PeerStateChange, cr.queue)
  32. for {
  33. select {
  34. case e := <-cr.queue.OutChan():
  35. switch e.EventType {
  36. case event.PeerStateChange:
  37. state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
  38. peer := e.Data[event.RemotePeer]
  39. cr.handleEvent(peer, state)
  40. }
  41. case <-time.After(tickTime):
  42. cr.peers.Range(func(k, v interface{}) bool {
  43. p := v.(*peer)
  44. if p.state == connections.DISCONNECTED {
  45. p.ticks++
  46. if p.ticks == p.backoff {
  47. p.ticks = 0
  48. cr.bus.Publish(event.NewEvent(event.PeerRequest, map[event.Field]string{event.RemotePeer: p.id}))
  49. }
  50. }
  51. return true
  52. })
  53. case <-cr.breakChan:
  54. return
  55. }
  56. }
  57. }
  58. func (cr *contactRetry) handleEvent(id string, state connections.ConnectionState) {
  59. if _, exists := cr.peers.Load(id); !exists {
  60. p := &peer{id: id, state: connections.DISCONNECTED, backoff: 1, ticks: 0}
  61. cr.peers.Store(id, p)
  62. return
  63. }
  64. pinf, _ := cr.peers.Load(id)
  65. p := pinf.(*peer)
  66. if state == connections.DISCONNECTED || state == connections.FAILED || state == connections.KILLED {
  67. p.state = connections.DISCONNECTED
  68. if p.backoff < maxBakoff {
  69. p.backoff *= 2
  70. }
  71. p.ticks = 0
  72. } else if state == connections.CONNECTING || state == connections.CONNECTED {
  73. p.state = state
  74. } else if state == connections.AUTHENTICATED {
  75. p.state = state
  76. p.backoff = 1
  77. }
  78. }
  79. func (cr *contactRetry) Shutdown() {
  80. cr.breakChan <- true
  81. }