Official cwtch.im peer and server implementations. https://cwtch.im
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.

networkCheck.go 3.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package plugins
  2. import (
  3. "cwtch.im/cwtch/event"
  4. "git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
  5. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  6. "git.openprivacy.ca/openprivacy/libricochet-go/policies"
  7. "time"
  8. )
  9. // networkCheck is a convenience plugin for testing high level availability of onion services
  10. type networkCheck struct {
  11. bus event.Manager
  12. queue event.Queue
  13. acn connectivity.ACN
  14. onionsToCheck []string
  15. breakChan chan bool
  16. running bool
  17. }
  18. // NewNetworkCheck returns a Plugin that when started will attempt various network tests
  19. func NewNetworkCheck(bus event.Manager, acn connectivity.ACN) Plugin {
  20. nc := &networkCheck{bus: bus, acn: acn, queue: event.NewQueue(), breakChan: make(chan bool, 1)}
  21. return nc
  22. }
  23. func (nc *networkCheck) Start() {
  24. go nc.run()
  25. }
  26. func (nc *networkCheck) run() {
  27. nc.running = true
  28. nc.bus.Subscribe(event.ProtocolEngineStartListen, nc.queue)
  29. nc.bus.Subscribe(event.NewMessageFromPeer, nc.queue)
  30. nc.bus.Subscribe(event.PeerAcknowledgement, nc.queue)
  31. nc.bus.Subscribe(event.EncryptedGroupMessage, nc.queue)
  32. var lastMessageReceived time.Time
  33. for {
  34. select {
  35. case <-nc.breakChan:
  36. nc.running = false
  37. return
  38. case e := <-nc.queue.OutChan():
  39. switch e.EventType {
  40. // On receipt of a Listen request for an onion service we will add the onion to our list
  41. // and then we will wait a minute and check the connection for the first time (the onion should be up)
  42. // under normal operating circumstances
  43. case event.ProtocolEngineStartListen:
  44. log.Debugf("initiating connection check for %v", e.Data[event.Onion])
  45. nc.onionsToCheck = append(nc.onionsToCheck, e.Data[event.Onion])
  46. default:
  47. // if we receive either an encrypted group message or a peer acknowledgement we can assume the network
  48. // is up and running (our onion service might still not be available, but we would aim to detect that
  49. // through other actions
  50. // we reset out timer
  51. lastMessageReceived = time.Now()
  52. }
  53. case <-time.After(tickTime):
  54. // if we haven't received an action in the last minute...kick off a set of testing
  55. if time.Now().Sub(lastMessageReceived) > time.Minute {
  56. for _, onion := range nc.onionsToCheck {
  57. go nc.checkConnection(onion)
  58. }
  59. }
  60. }
  61. }
  62. }
  63. func (nc *networkCheck) Shutdown() {
  64. if nc.running {
  65. nc.queue.Shutdown()
  66. log.Debugf("shutting down network status plugin")
  67. nc.breakChan <- true
  68. }
  69. }
  70. //
  71. func (nc *networkCheck) checkConnection(onion string) {
  72. // we want to definitively time these actions out faster than tor will, because these onions should definitely be
  73. // online
  74. ClientTimeout := policies.TimeoutPolicy(time.Second * 60)
  75. err := ClientTimeout.ExecuteAction(func() error {
  76. conn, _, err := nc.acn.Open(onion)
  77. if err == nil {
  78. conn.Close()
  79. }
  80. return err
  81. })
  82. // regardless of the outcome we want to report a status to let anyone who might care know that we did do a check
  83. if err != nil {
  84. log.Debugf("publishing network error for %v", onion)
  85. nc.bus.Publish(event.NewEvent(event.NetworkStatus, map[event.Field]string{event.Onion: onion, event.Error: err.Error(), event.Status: "Error"}))
  86. } else {
  87. log.Debugf("publishing network success for %v", onion)
  88. nc.bus.Publish(event.NewEvent(event.NetworkStatus, map[event.Field]string{event.Onion: onion, event.Error: "", event.Status: "Success"}))
  89. }
  90. }