Skip to content

Client ConnectWithContext now includes a buffered channel size setting #166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 58 additions & 12 deletions client/native/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,25 @@ type Options struct {

// ConnectWithContext creates and connects a new Client to Asterisk ARI.
// Providing a Context allows the caller to control the lifetime of the connection.
func ConnectWithContext(ctx context.Context, opts *Options) (ari.Client, error) {
c := New(opts)
// If you want to receive channel messages when the connection is Up (true) or Down (false),
// specify a non-zero sizeForMsgConnectedChannel. This value sets the size of the buffered channel (when non-zero).
// Caller receives the ari.Client, channel for reading the MsgConnected messages (if non-nil), and a error (nil if success).
func ConnectWithContext(ctx context.Context, sizeForMsgConnectedChannel int, opts *Options) (ari.Client, chan bool, error) {
c := NewWithChannelMsgConnected(opts, sizeForMsgConnectedChannel)

err := c.ConnectWithContext(ctx)
if err != nil {
return c, err
return c, c.chanMsgConnected, err
}

info, err := c.Asterisk().Info(nil)
if err != nil {
return c, err
return c, c.chanMsgConnected, err
}

c.node = info.SystemInfo.EntityID

return c, err
return c, c.chanMsgConnected, err
}

// Connect creates and connects a new Client to Asterisk ARI.
Expand All @@ -90,9 +93,11 @@ func Connect(opts *Options) (ari.Client, error) {
return c, err
}

// New creates a new ari.Client. This function should not be used directly unless you need finer control.
// NewWithChannelMsgConnected creates a new ari.Client and configures a channel for connection up/down messages.
// If sizeForMsgConnectedChannel is 0, then no channel will be created and no messages will be sent.
// This function should not be used directly unless you need finer control.
// nolint: gocyclo
func New(opts *Options) *Client {
func NewWithChannelMsgConnected(opts *Options, sizeForMsgConnectedChannel int) *Client {
if opts == nil {
opts = new(Options)
}
Expand Down Expand Up @@ -143,12 +148,26 @@ func New(opts *Options) *Client {
&slog.HandlerOptions{Level: slog.LevelError}))
}

var chanMsgConnected chan bool
if sizeForMsgConnectedChannel > 0 {
chanMsgConnected = make(chan bool, sizeForMsgConnectedChannel)
} else {
chanMsgConnected = nil
}

return &Client{
appName: opts.Application,
Options: opts,
appName: opts.Application,
Options: opts,
chanMsgConnected: chanMsgConnected,
}
}

// New creates a new ari.Client. This function should not be used directly unless you need finer control.
// nolint: gocyclo
func New(opts *Options) *Client {
return NewWithChannelMsgConnected(opts, 0)
}

// Client describes a native ARI client, which connects directly to an Asterisk HTTP-based ARI service.
type Client struct {
appName string
Expand All @@ -158,6 +177,9 @@ type Client struct {
// opts are the configuration options for the client
Options *Options

// golang buffered channel to send Connection Up (true) or Down (false) messages to the caller
chanMsgConnected chan bool

// WSConfig describes the configuration for the websocket connection to Asterisk, from which events will be received.
WSConfig *websocket.Config

Expand Down Expand Up @@ -191,7 +213,14 @@ func (c *Client) Close() {
c.cancel()
}

c.connected = false
if c.connected {
c.connected = false
if c.chanMsgConnected != nil {
c.chanMsgConnected <- false
}
}

c.chanMsgConnected = nil
}

// Application returns the ARI Application accessors for this client
Expand Down Expand Up @@ -348,6 +377,10 @@ func (c *Client) listen(ctx context.Context, wg *sync.WaitGroup) {
signalUp.Do(wg.Done)
}

if c.chanMsgConnected != nil {
c.chanMsgConnected = nil
}

return
}

Expand Down Expand Up @@ -375,6 +408,9 @@ func (c *Client) listen(ctx context.Context, wg *sync.WaitGroup) {

// We are connected
c.connected = true
if c.chanMsgConnected != nil {
c.chanMsgConnected <- true
}

// Signal that we are connected (the first time only)
if wg != nil {
Expand All @@ -387,13 +423,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.chanMsgConnected != nil {
c.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.chanMsgConnected != nil {
c.chanMsgConnected <- false
}
}

err = ws.Close()
if err != nil {
Expand Down