Fixed NAT table exhaustion possibly?

This commit is contained in:
0% [█ █ █ █ █ █ █ █ █ █] 100% 2026-06-16 19:28:44 -05:00
parent e930d3e6ac
commit 1c456702f4
5 changed files with 86 additions and 8 deletions

View File

@ -1,2 +1,2 @@
window.APP_VERSION = '1.0.5';
window.APP_VERSION_COLOR = 'hsl(122, 80%, 60%)';
window.APP_VERSION = '1.0.6';
window.APP_VERSION_COLOR = 'hsl(123, 80%, 60%)';

View File

@ -176,6 +176,7 @@ export default function ChatArea({ activeView, activeChannel, setActiveChannel,
const editTextareaRef = useRef(null);
const fileInputRef = useRef(null);
const lastTypingTime = useRef(0);
const lastSentReadIdRef = useRef(null);
const isDMView = activeView === 'dms';
const gcObj = isDMView ? servers.find(s => s.topicHex === activeChannel && s.isGroupChat) : null;
@ -384,7 +385,10 @@ export default function ChatArea({ activeView, activeChannel, setActiveChannel,
const latestMsg = currentChannelMessages[currentChannelMessages.length - 1];
const latestMsgId = latestMsg ? latestMsg.id : null;
if (latestMsgId) network.sendReadReceipt(networkChannelId, latestMsgId);
if (latestMsgId && latestMsgId !== lastSentReadIdRef.current) {
network.sendReadReceipt(networkChannelId, latestMsgId);
lastSentReadIdRef.current = latestMsgId;
}
markChannelRead(networkChannelId);
};

View File

@ -58,7 +58,7 @@ export default function GroupCallView({ channel, serverTopicHex, vcChannelId, my
};
broadcastState(); // Initial broadcast
const interval = setInterval(broadcastState, 3000);
const interval = setInterval(broadcastState, 10000);
return () => {
clearInterval(interval);

View File

@ -340,6 +340,12 @@ export default function ProfileSettingsModal({ profile, myKey, onClose, onSave,
>
Storage Management
</button>
<button
onClick={() => setActiveTab('network')}
className={`text-left px-3 py-1.5 rounded text-sm font-medium ${activeTab === 'network' ? 'bg-panel text-text' : 'text-muted hover:bg-panel/50 hover:text-text'}`}
>
Network & Diagnostics
</button>
<button
onClick={() => setActiveTab('settings')}
className={`text-left px-3 py-1.5 rounded text-sm font-medium ${activeTab === 'settings' ? 'bg-panel text-text' : 'text-muted hover:bg-panel/50 hover:text-text'}`}
@ -721,6 +727,63 @@ export default function ProfileSettingsModal({ profile, myKey, onClose, onSave,
<StorageSettings dms={dms} servers={servers} knownUsers={knownUsers} />
)}
{activeTab === 'network' && (
<div className="max-w-2xl">
<h2 className="text-xl font-bold text-text mb-6">Network & Diagnostics</h2>
<div className="bg-surface rounded-lg p-6 mb-6">
<h3 className="text-muted uppercase text-xs font-bold mb-4">Connection Status</h3>
<div className="grid grid-cols-2 gap-4 mb-4">
<div className="bg-panel p-4 rounded border border-surface">
<div className="text-xs text-muted uppercase font-bold mb-1">DHT Status</div>
<div className="text-lg font-bold text-green-500">
{network.swarm?.dht?.ephemeral !== false ? 'Client Mode (Safe)' : 'Routing Mode (Warning)'}
</div>
</div>
<div className="bg-panel p-4 rounded border border-surface">
<div className="text-xs text-muted uppercase font-bold mb-1">Active Peers</div>
<div className="text-lg font-bold text-text">{network.peers.size}</div>
</div>
<div className="bg-panel p-4 rounded border border-surface">
<div className="text-xs text-muted uppercase font-bold mb-1">Joined Topics</div>
<div className="text-lg font-bold text-text">{network.joinedTopics.size}</div>
</div>
<div className="bg-panel p-4 rounded border border-surface">
<div className="text-xs text-muted uppercase font-bold mb-1">Pending Connections</div>
<div className="text-lg font-bold text-text">{network.swarm?.connecting || 0}</div>
</div>
</div>
<div className="bg-panel p-4 rounded border border-surface">
<h4 className="text-sm font-bold text-text mb-2">NAT / Router Health</h4>
<p className="text-xs text-muted mb-4">
If your router's NAT table is exhausted, you will see 0 peers and fail to connect to other services (like VNC).
Client Mode prevents Peercord from routing background traffic for the network, which protects your router.
</p>
<p className="text-xs text-yellow-500 font-bold mb-4">
Note: If you still cannot connect to anyone, your router's NAT table may currently be full from a previous session. Please restart your router to clear it.
</p>
<button
onClick={() => {
if (network.swarm) {
console.info("--- NETWORK DIAGNOSTICS ---");
console.info("Peers:", network.peers.size);
console.info("Topics:", network.joinedTopics.size);
console.info("Connecting:", network.swarm.connecting);
console.info("DHT Ephemeral:", network.swarm.dht?.ephemeral);
console.info("---------------------------");
alert("Diagnostics logged to F10 Console.");
}
}}
className="bg-accent hover:opacity-90 text-white px-4 py-2 rounded text-sm font-medium transition-opacity"
>
Run Diagnostics (Check F10 Console)
</button>
</div>
</div>
</div>
)}
{activeTab === 'settings' && (
<div className="max-w-2xl">
<h2 className="text-xl font-bold text-text mb-6">App Settings</h2>

View File

@ -48,6 +48,7 @@ class P2PNetwork {
this.syncTimeout = null;
this._msgTimeout = null;
this._identityTimeout = null;
this._reconnectTimeout = null;
this.transfers = {};
this.webrtcListeners = new Set();
@ -396,10 +397,14 @@ class P2PNetwork {
async reconnect() {
if (!this.swarm) return;
if (this._reconnectTimeout) return;
this._reconnectTimeout = setTimeout(() => {
this._reconnectTimeout = null;
}, 5000);
console.log("[P2P] Network online event detected. Reconnecting...");
try {
// Hyperswarm handles reconnections automatically.
// Forcing a non-blocking flush is enough to kickstart the DHT without causing a UDP flood.
this.swarm.flush().catch(()=>{});
} catch (e) {
console.warn("[P2P] Reconnect flush failed:", e);
@ -530,7 +535,12 @@ class P2PNetwork {
await Promise.all(corePromises);
// SETUP SWARM
this.swarm = new Hyperswarm({ keyPair: { publicKey, secretKey } });
this.swarm = new Hyperswarm({
keyPair: { publicKey, secretKey },
ephemeral: true, // CRITICAL FIX: Prevents node from becoming a routing node and exhausting router NAT table
maxPeers: 128
});
this.swarm.on('connection', (conn, info) => {
conn.on('error', () => {}); // Prevent ECONNRESET crashes
this.store.replicate(conn);
@ -577,7 +587,7 @@ class P2PNetwork {
// BACKGROUND JOINS TO PREVENT UDP FLOOD / NAT EXHAUSTION
(async () => {
const pace = () => new Promise(r => setTimeout(r, 400)); // 400ms between DHT lookups
const pace = () => new Promise(r => setTimeout(r, 1000)); // 1000ms between DHT lookups
if (this.username && this.username !== 'unknown') {
const myTopic = b4a.alloc(32);
@ -667,6 +677,7 @@ class P2PNetwork {
this.webrtcListeners.clear();
if (this._msgTimeout) clearTimeout(this._msgTimeout);
if (this._identityTimeout) clearTimeout(this._identityTimeout);
if (this._reconnectTimeout) clearTimeout(this._reconnectTimeout);
}
async wipeAllData() {