github.com/CyCoreSystems/ari@v4.8.4+incompatible/context.go (about)

     1  package ari
     2  
     3  import "context"
     4  
     5  // ChannelContextOptions describes the set of options to be used when creating a channel-bound context.
     6  type ChannelContextOptions struct {
     7  	ctx    context.Context
     8  	cancel context.CancelFunc
     9  
    10  	hangupOnEnd bool
    11  
    12  	sub Subscription
    13  }
    14  
    15  // ChannelContextOptionFunc describes a function which modifies channel context options.
    16  type ChannelContextOptionFunc func(o *ChannelContextOptions)
    17  
    18  // ChannelContext returns a context which is closed when the provided channel leaves the ARI application or the parent context is closed.  The parent context is optional, and if it is `nil`, a new background context will be created.
    19  func ChannelContext(h *ChannelHandle, opts ...ChannelContextOptionFunc) (context.Context, context.CancelFunc) {
    20  
    21  	o := new(ChannelContextOptions)
    22  	for _, opt := range opts {
    23  		opt(o)
    24  	}
    25  
    26  	if o.ctx == nil {
    27  		o.ctx, o.cancel = context.WithCancel(context.Background())
    28  	}
    29  
    30  	if o.sub == nil {
    31  		o.sub = h.Subscribe(Events.StasisEnd)
    32  	}
    33  
    34  	go func() {
    35  		defer o.cancel()
    36  
    37  		select {
    38  		case <-o.ctx.Done():
    39  		case <-o.sub.Events():
    40  		}
    41  
    42  		if o.hangupOnEnd {
    43  			h.Hangup() // nolint
    44  		}
    45  	}()
    46  
    47  	return o.ctx, o.cancel
    48  }
    49  
    50  // WithParentContext requests that the generated channel context be created from the given parent context.
    51  func WithParentContext(parent context.Context) ChannelContextOptionFunc {
    52  	return func(o *ChannelContextOptions) {
    53  		if parent != nil {
    54  			o.ctx, o.cancel = context.WithCancel(parent)
    55  		}
    56  	}
    57  }
    58  
    59  // HangupOnEnd indicates that the channel should be terminated when the channel context is terminated.  Note that this also provides an easy way to create a time scope on a channel by putting a deadline on the parent context.
    60  func HangupOnEnd() ChannelContextOptionFunc {
    61  	return func(o *ChannelContextOptions) {
    62  		o.hangupOnEnd = true
    63  	}
    64  }