Maksim Totmin 40b8afb150 refactor: common util package, ESL/AMI/security fixes, Prometheus metrics
Backend stability and security improvements:

* internal/util/ — common RandomHex helper, removed 3 duplicates
* ESL: deduplicated readMessage (locked/unlocked), net.JoinHostPort for IPv6
* AMI: synchronous reconnect() in readEventsLoop, net.JoinHostPort for IPv6
* Auth: /api/auth/refresh accepts Authorization header only (no ?token=)
* decodeJSON: http.MaxBytesReader(1<<20) body limit
* Trunks: gatewayParams() uses configured ESL.GatewayPrefix
* Config: jwt_secret_env env-var fallback
* FSCollector: time.After → time.NewTimer with defer Stop
* Monitoring: Prometheus counters (route_requests, nodes_total/healthy, uptime)
* go fmt pass across all internal/ packages
2026-06-25 19:30:36 +07:00

78 lines
2.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, prefix 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
}
// Ищем строки вида "<prefix>-ingress-xxxxx sip:..."
if strings.Contains(line, prefix+"-ingress-") {
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
}