From e54cfee5d81aa6a272d545133ff651e55adcd0a9 Mon Sep 17 00:00:00 2001 From: Dan Cropp Date: Wed, 5 Jun 2024 19:55:06 +0000 Subject: [PATCH 1/2] Added CreationTime, VideoMode, and VideoSourceID to the BridgeData --- bridge.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/bridge.go b/bridge.go index 6ce6135..8a0f277 100644 --- a/bridge.go +++ b/bridge.go @@ -66,13 +66,16 @@ type BridgeData struct { // Key is the cluster-unique identifier for this bridge Key *Key `json:"key"` - ID string `json:"id"` // Unique Id for this bridge - Class string `json:"bridge_class"` // Class of the bridge - Type string `json:"bridge_type"` // Type of bridge (mixing, holding, dtmf_events, proxy_media) - ChannelIDs []string `json:"channels"` // List of pariticipating channel ids - Creator string `json:"creator"` // Creating entity of the bridge - Name string `json:"name"` // The name of the bridge - Technology string `json:"technology"` // Name of the bridging technology + ID string `json:"id"` // Unique Id for this bridge + Class string `json:"bridge_class"` // Class of the bridge + Type string `json:"bridge_type"` // Type of bridge (mixing, holding, dtmf_events, proxy_media) + ChannelIDs []string `json:"channels"` // List of pariticipating channel ids + Creator string `json:"creator"` // Creating entity of the bridge + Name string `json:"name"` // The name of the bridge + Technology string `json:"technology"` // Name of the bridging technology + CreationTime string `json:"creationtime"` // Creation Time + VideoMode string `json:"video_mode"` // Video mode the bridge is using. (none, talker, sfu, single) + VideoSourceID string `json:"video_source_id"` // The ID of the channel that is the source of video in this bridge, if one exists. } // BridgeAddChannelOptions describes additional options to be applied to a channel when it is joined to a bridge From e20bfc1c8770876323e8b7d1944f46d41327349c Mon Sep 17 00:00:00 2001 From: Dan Cropp Date: Wed, 5 Jun 2024 20:09:25 +0000 Subject: [PATCH 2/2] Added support for a connection up/down buffered channel to the client. If the caller wants to be notified every time the client detects a change in the Connected/Disconnected state for the websocket (from the last known state), it should create a buffered channel of boolean, specifying the depth for the buffered channel. Then, it should pass this value in the clients Options fields. When the Client connects for the web socket, it knows it's last known state. If it is unable to connect and the last know state was connected, it updates it's last know state to disconnected. If the options Buffered channel is set, it will send a False (disconnected) message on the buffered channel. If it is able to connect the websocket and read messages, if the last known state was disconnected, it changes it to connected. If the options Buffered channel is set, it will send a True (connected) message on the buffered channel. The caller (running on a different goroutine), is responsible for retrieving any messages from the buffered channel. (Only set it if you will retrieve these messages). When the caller Closes the client, the client will cleanup and set it's Options buffered channel reference to nil. (This lets the garbage collector know the client is no longer using it). The caller should wait for the Close to complete. It is up to the caller to decide if it wants to read any buffered channel messages after calling Close. The idea behind this is many telephony applications want to know when they can communicate/control calls with Asterisk. If the connection is down, an application can change it's internal state machine to know it can't communicate with Asterisk. This allows them to notify someone of a problem. Potentially switch to a different Asterisk for call control. --- CONTRIBUTORS | 1 + client/native/client.go | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index ad9f0d8..298c087 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1,4 +1,5 @@ 0perl <444065+0perl@users.noreply.github.com> +Dan Cropp Danil Matyukhin JAF Laurel Lawson diff --git a/client/native/client.go b/client/native/client.go index 166f3a3..dba933d 100644 --- a/client/native/client.go +++ b/client/native/client.go @@ -49,6 +49,9 @@ type Options struct { // Logger provides a logger which should be used for this client. Logger *slog.Logger + + // buffered channel for sending Connection Up (true) or Down (false) messages to the caller + ChanMsgConnected chan bool } // ConnectWithContext creates and connects a new Client to Asterisk ARI. @@ -191,7 +194,14 @@ func (c *Client) Close() { c.cancel() } - c.connected = false + if c.connected { + c.connected = false + if c.Options.ChanMsgConnected != nil { + c.Options.ChanMsgConnected <- false + } + } + + c.Options.ChanMsgConnected = nil } // Application returns the ARI Application accessors for this client @@ -375,6 +385,9 @@ func (c *Client) listen(ctx context.Context, wg *sync.WaitGroup) { // We are connected c.connected = true + if c.Options.ChanMsgConnected != nil { + c.Options.ChanMsgConnected <- true + } // Signal that we are connected (the first time only) if wg != nil { @@ -387,13 +400,23 @@ func (c *Client) listen(ctx context.Context, wg *sync.WaitGroup) { case err = <-c.wsRead(ws): c.Options.Logger.Error("read failure on websocket", "error", err) - c.connected = false + if c.connected { + c.connected = false + if c.Options.ChanMsgConnected != nil { + c.Options.ChanMsgConnected <- false + } + } time.Sleep(10 * time.Millisecond) } // Make sure our websocket connection is closed before looping - c.connected = false + if c.connected { + c.connected = false + if c.Options.ChanMsgConnected != nil { + c.Options.ChanMsgConnected <- false + } + } err = ws.Close() if err != nil {