Compare commits
2
Commits
45f546604e
..
v1.6.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91716e5233 | ||
|
|
6aa1d5d796 |
No files matched your search
@@ -38,8 +38,3 @@ Thumbs.db
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Environnement local de développement (exclu de Git)
|
||||
/.dev
|
||||
/.env
|
||||
/.env.local
|
||||
|
||||
+2
-21
@@ -19,10 +19,6 @@ $hasBranding = !empty($companyName) || !empty($companyLogo);
|
||||
|
||||
$appVerData = file_exists(__DIR__ . '/../version.json') ? json_decode((string)file_get_contents(__DIR__ . '/../version.json'), true) : [];
|
||||
$appVersion = $appVerData['version'] ?? '1.5.0';
|
||||
|
||||
// Détection de l'environnement de développement : présence de .dev local ou branche git dev
|
||||
$isDevEnv = file_exists(__DIR__ . '/../.dev')
|
||||
|| (trim((string)@shell_exec('git -C ' . escapeshellarg(__DIR__) . ' rev-parse --abbrev-ref HEAD 2>/dev/null')) === 'dev');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr" class="h-full">
|
||||
@@ -30,7 +26,7 @@ $isDevEnv = file_exists(__DIR__ . '/../.dev')
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="nexus-app-version" content="<?= htmlspecialchars($appVersion) ?>">
|
||||
<title><?= $isDevEnv ? '🛠️ [DEV] ' : '' ?>NexusPBX — Supervision & Téléphonie IP • Powered by Asterisk</title>
|
||||
<title>NexusPBX — Supervision & Téléphonie IP • Powered by Asterisk</title>
|
||||
<link rel="icon" type="image/png" href="/assets/favicon.png?v=<?= file_exists(__DIR__ . '/assets/favicon.png') ? filemtime(__DIR__ . '/assets/favicon.png') : 1 ?>">
|
||||
<link rel="apple-touch-icon" href="/assets/logo.png?v=<?= file_exists(__DIR__ . '/assets/logo.png') ? filemtime(__DIR__ . '/assets/logo.png') : 1 ?>">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
@@ -166,12 +162,7 @@ $isDevEnv = file_exists(__DIR__ . '/../.dev')
|
||||
<div class="flex items-center gap-4 mb-6">
|
||||
<img src="/assets/logo.png?v=<?= file_exists(__DIR__ . '/assets/logo.png') ? filemtime(__DIR__ . '/assets/logo.png') : 1 ?>" alt="NexusPBX Logo" class="w-20 h-20 sm:w-24 sm:h-24 object-contain shrink-0 filter drop-shadow-xl">
|
||||
<div>
|
||||
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight leading-none mb-1 flex items-center gap-2">
|
||||
NexusPBX
|
||||
<?php if ($isDevEnv): ?>
|
||||
<span class="px-2 py-0.5 text-xs font-mono font-extrabold tracking-wider rounded bg-amber-500/20 text-amber-300 border border-amber-500/40">DEV</span>
|
||||
<?php endif; ?>
|
||||
</h1>
|
||||
<h1 class="text-2xl sm:text-3xl font-black text-white tracking-tight leading-none mb-1">NexusPBX</h1>
|
||||
<p class="text-xs text-slate-300">Supervision & Téléphonie IP • Powered by Asterisk</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,9 +212,6 @@ $isDevEnv = file_exists(__DIR__ . '/../.dev')
|
||||
Nexus<span class="text-indigo-400">PBX</span>
|
||||
</div>
|
||||
<span id="app-version-badge" class="px-1.5 py-0.5 text-[10px] font-mono font-bold tracking-wider rounded bg-indigo-500/20 text-indigo-300 border border-indigo-500/30">v<?= htmlspecialchars($appVersion) ?></span>
|
||||
<?php if ($isDevEnv): ?>
|
||||
<span class="px-1.5 py-0.5 text-[10px] font-mono font-black tracking-wider rounded bg-amber-500/25 text-amber-300 border border-amber-500/50 shadow-xs shadow-amber-500/20 animate-pulse">DEV</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="text-[10px] text-slate-400 font-medium tracking-wide mt-0.5">Powered by Asterisk</div>
|
||||
</div>
|
||||
@@ -506,13 +494,6 @@ $isDevEnv = file_exists(__DIR__ . '/../.dev')
|
||||
|
||||
<!-- Boutons d'action globaux -->
|
||||
<div class="flex items-center gap-2.5">
|
||||
<?php if ($isDevEnv): ?>
|
||||
<div class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs font-bold bg-amber-500/15 text-amber-300 border border-amber-500/30">
|
||||
<span class="w-2 h-2 rounded-full bg-amber-400 animate-pulse"></span>
|
||||
<span class="hidden md:inline font-mono">SERVEUR</span> DEV
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Badge Notification Mise à Jour Disponible -->
|
||||
<button id="header-update-badge" type="button" onclick="openUpdatePanel()" style="display:none;"
|
||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs font-bold bg-amber-500/20 hover:bg-amber-500/30 text-amber-300 border border-amber-500/40 shadow-sm transition animate-pulse" title="Une mise à jour NexusPBX est disponible ! Cliquez pour voir les détails.">
|
||||
|
||||
+36
-14
@@ -67,6 +67,25 @@ class ConfigGenerator
|
||||
$lines[] = "; ===========================================================================";
|
||||
$lines[] = "";
|
||||
|
||||
$rtpTimeout = max(5, (int)($settings['rtp_timeout'] ?? 30));
|
||||
$rtpHoldTimeout = max(0, (int)($settings['rtp_timeout_hold'] ?? 0));
|
||||
$rtpKeepalive = max(0, (int)($settings['rtp_keepalive'] ?? 15));
|
||||
|
||||
$tcpKeepaliveLines = [
|
||||
"tcp_keepalive_enable = yes",
|
||||
"tcp_keepalive_idle_time = 20",
|
||||
"tcp_keepalive_interval_time = 5",
|
||||
"tcp_keepalive_probe_count = 3",
|
||||
];
|
||||
|
||||
// 0. Paramètres globaux PJSIP (Keepalive applicatif TLS/TCP toutes les 30s pour postes hors réseau / NAT)
|
||||
$lines[] = "; --- PARAMÈTRES GLOBAUX PJSIP (KEEPALIVE NAT / HORS RÉSEAU) ---";
|
||||
$lines[] = "[global]";
|
||||
$lines[] = "type = global";
|
||||
$lines[] = "keep_alive_interval = 30";
|
||||
$lines[] = "contact_expiration_check_interval = 15";
|
||||
$lines[] = "";
|
||||
|
||||
// 1. Transport UDP (Postes internes LAN & Trunks standards)
|
||||
$lines[] = "; --- TRANSPORT UDP (LAN / INTERNE) ---";
|
||||
$lines[] = "[transport-udp]";
|
||||
@@ -110,6 +129,7 @@ class ConfigGenerator
|
||||
$lines[] = "external_signaling_port = {$extUdpPort}";
|
||||
}
|
||||
}
|
||||
array_push($lines, ...$tcpKeepaliveLines);
|
||||
$lines[] = "allow_reload = no";
|
||||
$lines[] = "";
|
||||
|
||||
@@ -180,6 +200,7 @@ class ConfigGenerator
|
||||
$lines[] = "external_signaling_port = {$extTlsPort}";
|
||||
}
|
||||
}
|
||||
array_push($lines, ...$tcpKeepaliveLines);
|
||||
$lines[] = "allow_reload = no";
|
||||
$lines[] = "";
|
||||
|
||||
@@ -221,6 +242,15 @@ class ConfigGenerator
|
||||
$lines[] = "force_rport = yes";
|
||||
$lines[] = "rewrite_contact = yes";
|
||||
$lines[] = "direct_media = no";
|
||||
// Détection automatique et purge des flux RTP fantômes / morts (coupure réseau, NAT hors réseau)
|
||||
$lines[] = "rtp_timeout = {$rtpTimeout}";
|
||||
$lines[] = "rtp_timeout_hold = {$rtpHoldTimeout}";
|
||||
if ($rtpKeepalive > 0) {
|
||||
$lines[] = "rtp_keepalive = {$rtpKeepalive}";
|
||||
}
|
||||
$lines[] = "timers = yes";
|
||||
$lines[] = "timers_min_se = 90";
|
||||
$lines[] = "timers_sess_expires = 1800";
|
||||
if ($wantsTls && $hasTlsCerts) {
|
||||
// Verrouillage strict du transport TLS : refuse le repli sur UDP
|
||||
$lines[] = "transport = transport-tls";
|
||||
@@ -354,20 +384,10 @@ class ConfigGenerator
|
||||
if ($outboundProxy !== '') {
|
||||
$lines[] = "outbound_proxy = {$outboundProxy}";
|
||||
}
|
||||
if ($callerId !== '') {
|
||||
if (preg_match('/^(?:\"?([^\"<>]+?)\"?\s*)?<([^>]+)>$/u', $callerId, $cm)) {
|
||||
$cName = trim($cm[1] ?? '');
|
||||
$cNum = trim($cm[2] ?? '');
|
||||
if ($cName !== '') {
|
||||
$cNameClean = str_replace('"', '', $cName);
|
||||
$lines[] = "callerid = \"{$cNameClean}\" <{$cNum}>";
|
||||
} else {
|
||||
$lines[] = "callerid = <{$cNum}>";
|
||||
}
|
||||
} else {
|
||||
$lines[] = "callerid = {$callerId}";
|
||||
}
|
||||
}
|
||||
// Note : Ne JAMAIS positionner la directive "callerid" dans la section endpoint d'un Trunk PJSIP.
|
||||
// Dans Asterisk, "callerid" sur un endpoint sert de valeur par défaut pour les appels ENTRANTS,
|
||||
// ce qui écraserait le numéro de l'appelant externe (ex: mobile 06...).
|
||||
// Le CallerID sortant du Trunk (outbound_callerid) est appliqué uniquement dans le Dialplan sortant.
|
||||
$lines[] = "disallow = all";
|
||||
foreach ($codecs as $codec) {
|
||||
$lines[] = "allow = {$codec}";
|
||||
@@ -384,6 +404,8 @@ class ConfigGenerator
|
||||
$lines[] = "trust_id_inbound = {$trustInbound}";
|
||||
$lines[] = "trust_id_outbound = {$trustOutbound}";
|
||||
$lines[] = "timers = {$timers}";
|
||||
$lines[] = "rtp_timeout = {$rtpTimeout}";
|
||||
$lines[] = "rtp_timeout_hold = {$rtpHoldTimeout}";
|
||||
if ($rtpKeepalive > 0) {
|
||||
$lines[] = "rtp_keepalive = {$rtpKeepalive}";
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,9 +1,12 @@
|
||||
{
|
||||
"version": "1.6.4",
|
||||
"version": "1.6.6",
|
||||
"codename": "Helios",
|
||||
"release_date": "2026-11-05",
|
||||
"release_date": "2026-11-10",
|
||||
"min_php_version": "8.2",
|
||||
"changelog": [
|
||||
"PJSIP Endpoints & Trunks : injection effective de rtp_timeout, rtp_timeout_hold, rtp_keepalive et SIP Session Timers (RFC 4028) sur chaque endpoint PJSIP pour raccrocher instantanément les canaux fantômes",
|
||||
"PJSIP Global & Transports TLS/TCP : keepalive applicatif réduit à 30s (keep_alive_interval = 30), vérification expiration contacts toutes les 15s et TCP keepalives noyau (20s/5s/3) pour fiabiliser les BLF et postes hors réseau derrière NAT",
|
||||
"Trunks SIP : dissociation stricte du CallerID sortant du Trunk (suppression de callerid dans l'endpoint PJSIP pour préserver l'affichage du numéro appelant réel sur les appels entrants)",
|
||||
"Trunks SIP : suppression du forçage de from_user afin de préserver l'en-tête SIP From dynamique avec Nom d'appelant (CNAM) pour OVH / Orange",
|
||||
"Trunks SIP & Routage Sortant : activation systématique de trust_id_outbound et formatage strict du Caller ID Name (CNAM) pour affichage garanti chez les opérateurs distants (OVH, Orange, etc.)",
|
||||
"Sauvegarde & Restauration : versionnage dynamique automatique basé sur la version installée (résolution du tag figé v1.2.0)",
|
||||
|
||||
Reference in new issue
Block a user