conntracker.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package tunnelstate
  2. import (
  3. "net"
  4. "sync"
  5. "github.com/rs/zerolog"
  6. "github.com/cloudflare/cloudflared/connection"
  7. )
  8. type ConnTracker struct {
  9. mutex sync.RWMutex
  10. // int is the connection Index
  11. connectionInfo map[uint8]ConnectionInfo
  12. log *zerolog.Logger
  13. }
  14. type ConnectionInfo struct {
  15. IsConnected bool `json:"isConnected,omitempty"`
  16. Protocol connection.Protocol `json:"protocol,omitempty"`
  17. EdgeAddress net.IP `json:"edgeAddress,omitempty"`
  18. }
  19. // Convinience struct to extend the connection with its index.
  20. type IndexedConnectionInfo struct {
  21. ConnectionInfo
  22. Index uint8 `json:"index,omitempty"`
  23. }
  24. func NewConnTracker(
  25. log *zerolog.Logger,
  26. ) *ConnTracker {
  27. return &ConnTracker{
  28. connectionInfo: make(map[uint8]ConnectionInfo, 0),
  29. log: log,
  30. }
  31. }
  32. func (ct *ConnTracker) OnTunnelEvent(c connection.Event) {
  33. switch c.EventType {
  34. case connection.Connected:
  35. ct.mutex.Lock()
  36. ci := ConnectionInfo{
  37. IsConnected: true,
  38. Protocol: c.Protocol,
  39. EdgeAddress: c.EdgeAddress,
  40. }
  41. ct.connectionInfo[c.Index] = ci
  42. ct.mutex.Unlock()
  43. case connection.Disconnected, connection.Reconnecting, connection.RegisteringTunnel, connection.Unregistering:
  44. ct.mutex.Lock()
  45. ci := ct.connectionInfo[c.Index]
  46. ci.IsConnected = false
  47. ct.connectionInfo[c.Index] = ci
  48. ct.mutex.Unlock()
  49. default:
  50. ct.log.Error().Msgf("Unknown connection event case %v", c)
  51. }
  52. }
  53. func (ct *ConnTracker) CountActiveConns() uint {
  54. ct.mutex.RLock()
  55. defer ct.mutex.RUnlock()
  56. active := uint(0)
  57. for _, ci := range ct.connectionInfo {
  58. if ci.IsConnected {
  59. active++
  60. }
  61. }
  62. return active
  63. }
  64. // HasConnectedWith checks if we've ever had a successful connection to the edge
  65. // with said protocol.
  66. func (ct *ConnTracker) HasConnectedWith(protocol connection.Protocol) bool {
  67. ct.mutex.RLock()
  68. defer ct.mutex.RUnlock()
  69. for _, ci := range ct.connectionInfo {
  70. if ci.Protocol == protocol {
  71. return true
  72. }
  73. }
  74. return false
  75. }
  76. // Returns the connection information iff it is connected this
  77. // also leverages the [IndexedConnectionInfo] to also provide the connection index
  78. func (ct *ConnTracker) GetActiveConnections() []IndexedConnectionInfo {
  79. ct.mutex.RLock()
  80. defer ct.mutex.RUnlock()
  81. connections := make([]IndexedConnectionInfo, 0)
  82. for key, value := range ct.connectionInfo {
  83. if value.IsConnected {
  84. info := IndexedConnectionInfo{value, key}
  85. connections = append(connections, info)
  86. }
  87. }
  88. return connections
  89. }