github.com/CyCoreSystems/ari@v4.8.4+incompatible/ext/bridgemon/bridgemon.go (about) 1 package bridgemon 2 3 import ( 4 "sync" 5 6 "github.com/CyCoreSystems/ari" 7 ) 8 9 // Monitor is a bridge monitor, which maintains bridge data. It monitors an ARI bridge for events and keeps an internal cache of the bridge's data. 10 type Monitor struct { 11 h *ari.BridgeHandle 12 13 br *ari.BridgeData 14 15 sub ari.Subscription 16 closed bool 17 18 watchers []chan *ari.BridgeData 19 watcherMu sync.Mutex 20 21 mu sync.Mutex 22 } 23 24 // New returns a new bridge monitor 25 func New(h *ari.BridgeHandle) *Monitor { 26 27 sub := h.Subscribe(ari.Events.BridgeDestroyed, ari.Events.ChannelEnteredBridge, ari.Events.ChannelLeftBridge) 28 29 m := &Monitor{ 30 h: h, 31 sub: sub, 32 } 33 34 // Monitor bridge events to keep data in sync 35 go m.monitor() 36 37 // Attempt to load initial bridge data; this may fail if the bridge has only 38 // been staged, so ignore errors here 39 data, _ := h.Data() // nolint 40 m.updateData(data) 41 42 return m 43 } 44 45 func (m *Monitor) monitor() { 46 47 defer m.Close() 48 49 for v := range m.sub.Events() { 50 if v == nil { 51 continue 52 } 53 54 switch v.GetType() { 55 case ari.Events.BridgeDestroyed: 56 e, ok := v.(*ari.BridgeDestroyed) 57 if !ok { 58 continue 59 } 60 m.updateData(&e.Bridge) 61 return // bridge is destroyed; there will be no more events 62 case ari.Events.ChannelEnteredBridge: 63 e, ok := v.(*ari.ChannelEnteredBridge) 64 if !ok { 65 continue 66 } 67 m.updateData(&e.Bridge) 68 case ari.Events.ChannelLeftBridge: 69 e, ok := v.(*ari.ChannelLeftBridge) 70 if !ok { 71 continue 72 } 73 m.updateData(&e.Bridge) 74 } 75 } 76 77 } 78 79 func (m *Monitor) updateData(data *ari.BridgeData) { 80 81 // Populate the bridge key in the bridge data, since Asterisk does not populate this field. 82 if data.Key == nil { 83 data.Key = m.h.Key() 84 } 85 86 // Update the stored data 87 m.mu.Lock() 88 m.br = data 89 m.mu.Unlock() 90 91 // Distribute new data to any watchers 92 m.watcherMu.Lock() 93 for _, w := range m.watchers { 94 select { 95 case w <- data: 96 default: 97 } 98 } 99 m.watcherMu.Unlock() 100 101 } 102 103 // Data returns the current bridge data 104 func (m *Monitor) Data() *ari.BridgeData { 105 if m == nil { 106 return nil 107 } 108 109 return m.br 110 } 111 112 // Handle returns the BridgeHandle which was used to create the bridge Monitor. 113 func (m *Monitor) Handle() *ari.BridgeHandle { 114 if m == nil { 115 return nil 116 } 117 return m.h 118 } 119 120 // Key returns the key of the monitored bridge 121 func (m *Monitor) Key() *ari.Key { 122 if m == nil || m.h == nil { 123 return nil 124 } 125 return m.h.Key() 126 } 127 128 // Watch returns a channel on which bridge data will be returned when events 129 // occur. This channel will be closed when the bridge or the monitor is 130 // destoyed. 131 // 132 // NOTE: the user should NEVER close this channel directly. 133 // 134 func (m *Monitor) Watch() <-chan *ari.BridgeData { 135 ch := make(chan *ari.BridgeData) 136 137 m.mu.Lock() 138 defer m.mu.Unlock() 139 if m.closed { 140 close(ch) 141 return ch 142 } 143 144 m.watcherMu.Lock() 145 m.watchers = append(m.watchers, ch) 146 m.watcherMu.Unlock() 147 148 return ch 149 } 150 151 // Close shuts down a bridge monitor 152 func (m *Monitor) Close() { 153 if m == nil { 154 return 155 } 156 157 m.mu.Lock() 158 if !m.closed { 159 m.closed = true 160 if m.sub != nil { 161 m.sub.Cancel() 162 } 163 } 164 m.mu.Unlock() 165 166 m.watcherMu.Lock() 167 for _, w := range m.watchers { 168 close(w) 169 } 170 m.watchers = nil 171 m.watcherMu.Unlock() 172 }