From db233f853cf2b173d4491eb61aefa73040aaec4e Mon Sep 17 00:00:00 2001 From: sorcier Date: Tue, 3 Nov 2026 19:29:57 +0100 Subject: [PATCH] fix(trunk): match PJSIP endpoint name to username in receive mode and auto-reload on trunk save --- public/api.php | 13 +++++++++ src/ConfigGenerator.php | 61 ++++++++++++++++++----------------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/public/api.php b/public/api.php index 91ecdc6..e11376e 100644 --- a/public/api.php +++ b/public/api.php @@ -1279,6 +1279,12 @@ try { $stmt->execute($params); } + $generator->writeAllConfigs(); + try { + $ami = AmiClient::fromDatabase($db); + $ami->reloadPjsipAndDialplan(); + } catch (\Throwable $e) {} + $displayHost = $host !== '' ? "{$host}:{$port}" : "Passerelle locale / HT813"; echo json_encode([ 'success' => true, @@ -1289,6 +1295,13 @@ try { case 'delete_trunk': $id = (int)($payload['id'] ?? 0); $db->prepare('DELETE FROM trunks WHERE id = :id')->execute([':id' => $id]); + + $generator->writeAllConfigs(); + try { + $ami = AmiClient::fromDatabase($db); + $ami->reloadPjsipAndDialplan(); + } catch (\Throwable $e) {} + echo json_encode([ 'success' => true, 'message' => 'Trunk SIP supprimé.', diff --git a/src/ConfigGenerator.php b/src/ConfigGenerator.php index 49ffd08..e5fbe06 100644 --- a/src/ConfigGenerator.php +++ b/src/ConfigGenerator.php @@ -315,22 +315,22 @@ class ConfigGenerator $matchIpsRaw = trim((string)($trunk['match_ips'] ?? '')); + $epName = ($regMode === 'receive' && $username !== '') ? $username : "trunk-{$slug}"; + $authName = "{$epName}-auth"; + $aorName = $epName; + $hostPortDisplay = $host !== '' ? "{$host}:{$port}" : "Passerelle Réception Dynamique"; $lines[] = "; --- Trunk : {$trunk['name']} ({$hostPortDisplay} [{$trProto}] - Mode: {$regMode}) ---"; - $lines[] = "[trunk-{$slug}]"; + $lines[] = "[{$epName}]"; $lines[] = "type = endpoint"; $lines[] = "context = {$context}"; $lines[] = "transport = {$transport}"; 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}"; - } + $lines[] = "auth = {$authName}"; + $lines[] = "outbound_auth = {$authName}"; + $lines[] = "aors = {$aorName}"; if ($host !== '' || $matchIpsRaw !== '') { $lines[] = "identify_by = auth_username,username,ip"; } else { @@ -338,9 +338,9 @@ class ConfigGenerator } } else { if ($hasAuth) { - $lines[] = "outbound_auth = trunk-{$slug}-auth"; + $lines[] = "outbound_auth = {$authName}"; } - $lines[] = "aors = trunk-{$slug}"; + $lines[] = "aors = {$aorName}"; } if ($outboundProxy !== '') { $lines[] = "outbound_proxy = {$outboundProxy}"; @@ -402,8 +402,8 @@ class ConfigGenerator } $lines[] = ""; - // Section AOR du Trunk (nommée trunk-$slug et alias username si mode receive) - $lines[] = "[trunk-{$slug}]"; + // Section AOR du Trunk + $lines[] = "[{$aorName}]"; $lines[] = "type = aor"; if ($regMode === 'receive') { // En mode réception, l'IP/port de la passerelle est découvert dynamiquement lors du REGISTER @@ -427,22 +427,9 @@ 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 || $regMode === 'receive') { - $lines[] = "[trunk-{$slug}-auth]"; + $lines[] = "[{$authName}]"; $lines[] = "type = auth"; $lines[] = "auth_type = userpass"; $lines[] = "username = {$authUsername}"; @@ -462,10 +449,10 @@ class ConfigGenerator $expiration = max(60, (int)($trunk['expiration'] ?? 3600)); $lineSupport = ((int)($trunk['line_support'] ?? 1) === 1); - $lines[] = "[trunk-{$slug}-reg]"; + $lines[] = "[{$epName}-reg]"; $lines[] = "type = registration"; $lines[] = "transport = {$transport}"; - $lines[] = "outbound_auth = trunk-{$slug}-auth"; + $lines[] = "outbound_auth = {$authName}"; $lines[] = "server_uri = {$serverUri}"; $lines[] = "client_uri = {$clientUri}"; if ($contactUser !== '') { @@ -483,7 +470,7 @@ class ConfigGenerator $lines[] = "max_random_initial_delay = 0"; if ($lineSupport) { $lines[] = "line = yes"; - $lines[] = "endpoint = trunk-{$slug}"; + $lines[] = "endpoint = {$epName}"; } $customReg = trim((string)($trunk['custom_reg_params'] ?? '')); if ($customReg !== '') { @@ -504,9 +491,9 @@ class ConfigGenerator : ($host !== '' ? [$host] : []); if (!empty($matchList)) { - $lines[] = "[trunk-{$slug}-identify]"; + $lines[] = "[{$epName}-identify]"; $lines[] = "type = identify"; - $lines[] = "endpoint = trunk-{$slug}"; + $lines[] = "endpoint = {$epName}"; foreach ($matchList as $mIp) { $lines[] = "match = {$mIp}"; } @@ -1061,6 +1048,9 @@ class ConfigGenerator foreach ($trunks as $t) { $trunkByName[trim((string)$t['name'])] = $t; $trunkByName['trunk-' . $this->slugify($t['name'])] = $t; + if (!empty($t['username'])) { + $trunkByName[trim((string)$t['username'])] = $t; + } } $patternDispatches = []; @@ -1181,10 +1171,13 @@ class ConfigGenerator } $validTrunkCount++; - $sub[] = " same => n,NoOp(Route [{$rName}] - Tentative Trunk #{$validTrunkCount} [trunk-{$tSlug}] vers \${OUTNUM})"; - $sub[] = " same => n,Dial(PJSIP/\${OUTNUM}@trunk-{$tSlug},60,tT)"; + $tEpName = ($tObj && ($tObj['registration_mode'] ?? '') === 'receive' && !empty($tObj['username'])) + ? $tObj['username'] + : "trunk-{$tSlug}"; + $sub[] = " same => n,NoOp(Route [{$rName}] - Tentative Trunk #{$validTrunkCount} [{$tEpName}] vers \${OUTNUM})"; + $sub[] = " same => n,Dial(PJSIP/\${OUTNUM}@{$tEpName},60,tT)"; $sub[] = " same => n,GotoIf(\$[\"\${DIALSTATUS}\" = \"ANSWER\" | \"\${DIALSTATUS}\" = \"BUSY\" | \"\${DIALSTATUS}\" = \"NOANSWER\" | \"\${DIALSTATUS}\" = \"CANCEL\"]?call_done)"; - $sub[] = " same => n,NoOp(Trunk [trunk-{$tSlug}] indisponible [\${DIALSTATUS}] -> Passage au Trunk / Route suivant)"; + $sub[] = " same => n,NoOp(Trunk [{$tEpName}] indisponible [\${DIALSTATUS}] -> Passage au Trunk / Route suivant)"; } // 5. Si tous les Trunks de cette route sont indisponibles