Files
go-sip/internal/asterisk/answer.go
T

66 lines
1.7 KiB
Go

package asterisk
import (
"context"
"errors"
"fmt"
"github.com/CyCoreSystems/ari/v5"
)
// awaitDialUp only runs after Dial was submitted. Create enters Stasis before
// any SIP request is sent, so StasisStart alone can never prove an answer.
func awaitDialUp(ctx context.Context, sub ari.Subscription, channelID string) error {
if ctx == nil || sub == nil || channelID == "" {
return errors.New("native answer wait has no channel subscription")
}
stasis, up := false, false
for {
select {
case <-ctx.Done():
return ctx.Err()
case event, ok := <-sub.Events():
if !ok {
return errors.New("native answer subscription closed before confirmed answer")
}
if event == nil {
continue
}
switch e := event.(type) {
case *ari.StasisStart:
if e.Channel.ID == channelID {
stasis = true
}
case *ari.ChannelStateChange:
if e.Channel.ID == channelID && e.Channel.State == "Up" {
up = true
}
case *ari.ChannelDestroyed:
if e.Channel.ID == channelID {
return fmt.Errorf("native outbound channel destroyed before verified answer: cause=%d", e.Cause)
}
case *ari.ChannelHangupRequest:
if e.Channel.ID == channelID {
return fmt.Errorf("native outbound channel requested hangup before verified answer: cause=%d", e.Cause)
}
case *ari.StasisEnd:
if e.Channel.ID == channelID {
return errors.New("native outbound channel left Stasis before verified answer")
}
}
if stasis && up {
return nil
}
}
}
}
func eventBelongsToChannel(event ari.Event, channelID string) bool {
for _, key := range event.Keys() {
if key != nil && key.Kind == "channel" && key.ID == channelID {
return true
}
}
return false
}