feat: add support for inbound trunk registration (Receive mode) for FXO gateways like Grandstream HT813 and analog Livebox integration

This commit is contained in:
sorcier committed 2026-11-03 19:07:19 +01:00
1 parent 981c650c7a
commit 8a4d7a0504
5 files changed
+285 -37

No files matched your search

+66 -19
View File
@@ -308,15 +308,40 @@ class ConfigGenerator
$codecs = array_filter(array_map('trim', explode(',', (string)($trunk['codecs'] ?? 'alaw,ulaw'))));
$hasAuth = ($authMode !== 'ip' && $username !== '' && $secret !== '');
$lines[] = "; --- Trunk : {$trunk['name']} ({$host}:{$port} [{$trProto}]) ---";
$regMode = trim((string)($trunk['registration_mode'] ?? ''));
if (!in_array($regMode, ['send', 'receive', 'none'], true)) {
$regMode = ((int)($trunk['register'] ?? 1) === 1) ? 'send' : 'none';
}
$matchIpsRaw = trim((string)($trunk['match_ips'] ?? ''));
$hostPortDisplay = $host !== '' ? "{$host}:{$port}" : "Passerelle Réception Dynamique";
$lines[] = "; --- Trunk : {$trunk['name']} ({$hostPortDisplay} [{$trProto}] - Mode: {$regMode}) ---";
$lines[] = "[trunk-{$slug}]";
$lines[] = "type = endpoint";
$lines[] = "context = {$context}";
$lines[] = "transport = {$transport}";
if ($hasAuth) {
if ($regMode === 'receive') {
// Passerelle locale (ex: Grandstream HT813, Livebox, ATA) s'enregistrant sur Asterisk
$lines[] = "auth = trunk-{$slug}-auth";
$lines[] = "outbound_auth = trunk-{$slug}-auth";
if ($username !== '' && $username !== "trunk-{$slug}") {
$lines[] = "aors = trunk-{$slug},{$username}";
} else {
$lines[] = "aors = trunk-{$slug}";
}
if ($host !== '' || $matchIpsRaw !== '') {
$lines[] = "identify_by = auth_username,username,ip";
} else {
$lines[] = "identify_by = auth_username,username";
}
} else {
if ($hasAuth) {
$lines[] = "outbound_auth = trunk-{$slug}-auth";
}
$lines[] = "aors = trunk-{$slug}";
}
$lines[] = "aors = trunk-{$slug}";
if ($outboundProxy !== '') {
$lines[] = "outbound_proxy = {$outboundProxy}";
}
@@ -377,10 +402,16 @@ class ConfigGenerator
}
$lines[] = "";
// Section AOR du Trunk (nommée trunk-$slug)
// Section AOR du Trunk (nommée trunk-$slug et alias username si mode receive)
$lines[] = "[trunk-{$slug}]";
$lines[] = "type = aor";
$lines[] = "contact = sip:{$host}:{$port}";
if ($regMode === 'receive') {
// En mode réception, l'IP/port de la passerelle est découvert dynamiquement lors du REGISTER
$lines[] = "max_contacts = 1";
$lines[] = "remove_existing = yes";
} else {
$lines[] = "contact = sip:{$host}:{$port}";
}
$lines[] = "qualify_frequency = {$qualifyFreq}";
if ($outboundProxy !== '') {
$lines[] = "outbound_proxy = {$outboundProxy}";
@@ -396,8 +427,21 @@ class ConfigGenerator
}
$lines[] = "";
// AOR supplémentaire pour identifier l'enregistrement par identifiant/numéro (ex: 0494679572)
if ($regMode === 'receive' && $username !== '' && $username !== "trunk-{$slug}") {
$lines[] = "[{$username}]";
$lines[] = "type = aor";
$lines[] = "max_contacts = 1";
$lines[] = "remove_existing = yes";
$lines[] = "qualify_frequency = {$qualifyFreq}";
if ($outboundProxy !== '') {
$lines[] = "outbound_proxy = {$outboundProxy}";
}
$lines[] = "";
}
// Section Auth du Trunk
if ($hasAuth) {
if ($hasAuth || $regMode === 'receive') {
$lines[] = "[trunk-{$slug}-auth]";
$lines[] = "type = auth";
$lines[] = "auth_type = userpass";
@@ -406,8 +450,8 @@ class ConfigGenerator
$lines[] = "";
}
// Section Registration du Trunk
if ((int)($trunk['register'] ?? 1) === 1 && $hasAuth) {
// Section Registration du Trunk (uniquement en mode émission 'send')
if ($regMode === 'send' && (int)($trunk['register'] ?? 1) === 1 && $hasAuth) {
$serverUri = trim((string)($trunk['server_uri'] ?? '')) ?: "sip:{$host}:{$port}";
$clientUri = trim((string)($trunk['client_uri'] ?? '')) ?: "sip:{$username}@{$fromDomain}:{$port}";
$contactUser = trim((string)($trunk['contact_user'] ?? ''));
@@ -453,19 +497,22 @@ class ConfigGenerator
$lines[] = "";
}
// Section Identify (Reconnaissance d'IPs / sous-réseaux opérateur)
$matchIpsRaw = trim((string)($trunk['match_ips'] ?? ''));
$matchList = $matchIpsRaw !== ''
? array_filter(array_map('trim', preg_split('/[\s,;]+/', $matchIpsRaw) ?: []))
: [$host];
// Section Identify (Reconnaissance d'IPs / sous-réseaux opérateur ou passerelle)
if ($matchIpsRaw !== '' || ($regMode !== 'receive' && $host !== '') || ($regMode === 'receive' && $host !== '')) {
$matchList = $matchIpsRaw !== ''
? array_filter(array_map('trim', preg_split('/[\s,;]+/', $matchIpsRaw) ?: []))
: ($host !== '' ? [$host] : []);
$lines[] = "[trunk-{$slug}-identify]";
$lines[] = "type = identify";
$lines[] = "endpoint = trunk-{$slug}";
foreach ($matchList as $mIp) {
$lines[] = "match = {$mIp}";
if (!empty($matchList)) {
$lines[] = "[trunk-{$slug}-identify]";
$lines[] = "type = identify";
$lines[] = "endpoint = trunk-{$slug}";
foreach ($matchList as $mIp) {
$lines[] = "match = {$mIp}";
}
$lines[] = "";
}
}
$lines[] = "";
}
}
+6 -1
View File
@@ -128,7 +128,7 @@ class Database
CREATE TABLE IF NOT EXISTS trunks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(64) NOT NULL UNIQUE,
host VARCHAR(128) NOT NULL,
host VARCHAR(128) NOT NULL DEFAULT '',
port INTEGER NOT NULL DEFAULT 5060,
outbound_proxy VARCHAR(128) NOT NULL DEFAULT '',
transport VARCHAR(8) NOT NULL DEFAULT 'udp',
@@ -136,6 +136,7 @@ class Database
username VARCHAR(64) NOT NULL DEFAULT '',
auth_username VARCHAR(64) NOT NULL DEFAULT '',
secret VARCHAR(128) NOT NULL DEFAULT '',
registration_mode VARCHAR(16) NOT NULL DEFAULT 'send' CHECK (registration_mode IN ('send', 'receive', 'none')),
register INTEGER NOT NULL DEFAULT 1 CHECK (register IN (0, 1)),
server_uri VARCHAR(192) NOT NULL DEFAULT '',
client_uri VARCHAR(192) NOT NULL DEFAULT '',
@@ -561,6 +562,7 @@ class Database
// Colonnes universelles PJSIP supplémentaires (Session Timers, Fax T.38, Diversion, Retries, Langue, Keepalive)
$extraColumns = [
'registration_mode' => "VARCHAR(16) NOT NULL DEFAULT 'send'",
'max_retries' => "INTEGER NOT NULL DEFAULT 10000",
'forbidden_retry_interval' => "INTEGER NOT NULL DEFAULT 600",
'fatal_retry_interval' => "INTEGER NOT NULL DEFAULT 0",
@@ -579,6 +581,9 @@ class Database
foreach ($extraColumns as $colName => $colDef) {
if (!in_array($colName, $existing, true)) {
$db->exec("ALTER TABLE trunks ADD COLUMN {$colName} {$colDef}");
if ($colName === 'registration_mode') {
$db->exec("UPDATE trunks SET registration_mode = CASE WHEN register = 1 THEN 'send' ELSE 'none' END");
}
}
}
}