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

66 lines
2.0 KiB
Go

package asterisk
import (
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"github.com/CyCoreSystems/ari/v5"
"github.com/CyCoreSystems/ari/v5/client/native"
)
// ariOptions uses the credential issued to the Agent on the same Cell as
// native Asterisk. It never reads a historical local test credential.
func (l Loader) ariOptions() (*native.Options, error) {
if l.ConfigDir == "" {
return nil, errors.New("native Asterisk configuration directory required")
}
path := filepath.Join(l.ConfigDir, "ari-secret")
info, err := os.Lstat(path)
if err != nil {
return nil, fmt.Errorf("inspect issued Agent ARI credential: %T", err)
}
if !info.Mode().IsRegular() || info.Mode().Perm() != 0600 {
return nil, errors.New("issued Agent ARI credential must be a private regular file (0600)")
}
secret, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read issued Agent ARI credential: %T", err)
}
if len(secret) != 64 {
return nil, errors.New("issued Agent ARI credential has an invalid length")
}
if _, err := hex.DecodeString(string(secret)); err != nil {
return nil, errors.New("issued Agent ARI credential has an invalid format")
}
return &native.Options{
URL: "http://127.0.0.1:8088/ari", WebsocketURL: "ws://127.0.0.1:8088/ari/events",
Application: "go-sip-agent", Username: "go-sip-agent", Password: string(secret),
}, nil
}
// OpenARI proves that the native server accepts this Agent credential without
// creating a channel or dialing. The caller owns and must close the client.
func (l Loader) OpenARI() (ari.Client, error) {
options, err := l.ariOptions()
if err != nil {
return nil, err
}
client, err := native.Connect(options)
if err != nil {
return nil, fmt.Errorf("connect native Agent ARI: %T", err)
}
info, err := client.Asterisk().Info(nil)
if err != nil {
client.Close()
return nil, fmt.Errorf("read native Agent ARI status: %T", err)
}
if info == nil {
client.Close()
return nil, errors.New("native Agent ARI returned an empty status")
}
return client, nil
}