- Raw TCP ESL client with reconnect - GatewayAdd/GatewayDelete/GatewaySyncAll - SOFIA::gateway_* event processing - SendAsync for deadlock-free bgapi commands
78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package esl
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
// GatewayAdd создаёт gateway на FreeSWITCH через Sofia профиль.
|
|
// Использует bgapi — асинхронная команда, результат приходит как BACKGROUND_JOB событие.
|
|
func (c *Client) GatewayAdd(profile, name, proxy string) error {
|
|
cmd := fmt.Sprintf("bgapi sofia profile %s gwadd %s %s", profile, name, proxy)
|
|
if err := c.SendAsync(cmd); err != nil {
|
|
log.Printf("[esl] GatewayAdd %s: ошибка: %v", name, err)
|
|
return err
|
|
}
|
|
c.IncGatewayOps()
|
|
log.Printf("[esl] GatewayAdd %s: отправлен (%s → %s)", name, profile, proxy)
|
|
return nil
|
|
}
|
|
|
|
// GatewayDelete удаляет gateway на FreeSWITCH.
|
|
// Использует bgapi — асинхронная команда, результат приходит как BACKGROUND_JOB событие.
|
|
func (c *Client) GatewayDelete(profile, name string) error {
|
|
cmd := fmt.Sprintf("bgapi sofia profile %s gwdel %s", profile, name)
|
|
if err := c.SendAsync(cmd); err != nil {
|
|
log.Printf("[esl] GatewayDelete %s: ошибка: %v", name, err)
|
|
return err
|
|
}
|
|
c.IncGatewayOps()
|
|
log.Printf("[esl] GatewayDelete %s: отправлен", name)
|
|
return nil
|
|
}
|
|
|
|
// GatewayList возвращает список имён gateway в заданном профиле.
|
|
func (c *Client) GatewayList(profile string) ([]string, error) {
|
|
cmd := fmt.Sprintf("api sofia profile %s gwlist", profile)
|
|
_, body, err := c.Send(cmd)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("GatewayList: %w", err)
|
|
}
|
|
|
|
// Парсим вывод gwlist — имена gateway на отдельных строках
|
|
lines := strings.Split(body, "\n")
|
|
var gateways []string
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" || strings.HasPrefix(line, "Name:") || strings.HasPrefix(line, "====") {
|
|
continue
|
|
}
|
|
// Ищем строки вида "pulse-ingress-xxxxx sip:..."
|
|
if strings.Contains(line, "pulse-") {
|
|
parts := strings.Fields(line)
|
|
if len(parts) > 0 {
|
|
gateways = append(gateways, parts[0])
|
|
}
|
|
}
|
|
}
|
|
return gateways, nil
|
|
}
|
|
|
|
// GatewaySyncAll синхронизирует все ingress-транки как gateway на FS.
|
|
// Вызывается после реконнекта.
|
|
func (c *Client) GatewaySyncAll(profile string, gateways []GatewaySpec) {
|
|
for _, g := range gateways {
|
|
if err := c.GatewayAdd(profile, g.Name, g.Proxy); err != nil {
|
|
log.Printf("[esl] GatewaySyncAll: ошибка %s: %v", g.Name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// GatewaySpec описывает gateway для синхронизации.
|
|
type GatewaySpec struct {
|
|
Name string
|
|
Proxy string
|
|
}
|