From 54fc495fa70001b5c3c3641a2ff112713484ebd2 Mon Sep 17 00:00:00 2001 From: sorcier Date: Fri, 6 Nov 2026 16:57:25 +0100 Subject: [PATCH] fix(cluster): bind PJSIP transports to VIP and announce VIP signaling address in HA mode --- src/ConfigGenerator.php | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/ConfigGenerator.php b/src/ConfigGenerator.php index 6c95c72..44645fb 100644 --- a/src/ConfigGenerator.php +++ b/src/ConfigGenerator.php @@ -61,6 +61,25 @@ class ConfigGenerator } } + // Détection de l'IP Virtuelle (VIP) du Cluster Haute Disponibilité (HA) + $clusterSt = []; + try { + $clusterSt = $this->db->query('SELECT enabled, virtual_ip, blf_expiry FROM cluster_settings WHERE id = 1')->fetch(\PDO::FETCH_ASSOC) ?: []; + } catch (\Throwable) {} + $isHaActive = !empty($clusterSt['enabled']); + $haVip = ''; + if ($isHaActive && !empty($clusterSt['virtual_ip'])) { + $parts = explode('/', trim((string)$clusterSt['virtual_ip'])); + $candidateVip = trim($parts[0] ?? ''); + if (filter_var($candidateVip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $haVip = $candidateVip; + } + } + + // En mode HA, liaison obligatoire sur la VIP pour que tous les paquets SIP et contacts + // annoncent la VIP et non l'IP physique du serveur (élimine la perte des dialogues BLF au failover) + $sipBindHost = ($haVip !== '') ? $haVip : '0.0.0.0'; + $lines = []; $lines[] = "; ==========================================================================="; $lines[] = "; FICHIER GÉNÉRÉ AUTOMATIQUEMENT PAR NEXUSPBX ($date)"; @@ -73,7 +92,7 @@ class ConfigGenerator $lines[] = "[transport-udp]"; $lines[] = "type = transport"; $lines[] = "protocol = udp"; - $lines[] = "bind = 0.0.0.0:{$udpPort}"; + $lines[] = "bind = {$sipBindHost}:{$udpPort}"; $lines[] = "symmetric_transport = yes"; foreach ($localNetworks as $net) { $net = trim((string)$net); @@ -87,6 +106,9 @@ class ConfigGenerator if ($extUdpPort > 0) { $lines[] = "external_signaling_port = {$extUdpPort}"; } + } elseif ($haVip !== '') { + $lines[] = "external_media_address = {$haVip}"; + $lines[] = "external_signaling_address = {$haVip}"; } $lines[] = "allow_reload = no"; $lines[] = ""; @@ -96,7 +118,7 @@ class ConfigGenerator $lines[] = "[transport-tcp]"; $lines[] = "type = transport"; $lines[] = "protocol = tcp"; - $lines[] = "bind = 0.0.0.0:{$udpPort}"; + $lines[] = "bind = {$sipBindHost}:{$udpPort}"; $lines[] = "symmetric_transport = yes"; foreach ($localNetworks as $net) { $net = trim((string)$net); @@ -110,6 +132,9 @@ class ConfigGenerator if ($extUdpPort > 0) { $lines[] = "external_signaling_port = {$extUdpPort}"; } + } elseif ($haVip !== '') { + $lines[] = "external_media_address = {$haVip}"; + $lines[] = "external_signaling_address = {$haVip}"; } $lines[] = "allow_reload = no"; $lines[] = ""; @@ -153,7 +178,7 @@ class ConfigGenerator $lines[] = "[transport-tls]"; $lines[] = "type = transport"; $lines[] = "protocol = tls"; - $lines[] = "bind = 0.0.0.0:{$tlsPort}"; + $lines[] = "bind = {$sipBindHost}:{$tlsPort}"; $lines[] = "symmetric_transport = yes"; $lines[] = "cert_file = {$certPath}"; $lines[] = "priv_key_file = {$keyPath}"; @@ -180,6 +205,9 @@ class ConfigGenerator if ($extTlsPort > 0) { $lines[] = "external_signaling_port = {$extTlsPort}"; } + } elseif ($haVip !== '') { + $lines[] = "external_media_address = {$haVip}"; + $lines[] = "external_signaling_address = {$haVip}"; } $lines[] = "allow_reload = no"; $lines[] = "";