Fixed NAT table exhaustion possibly?
This commit is contained in:
parent
e930d3e6ac
commit
1c456702f4
|
|
@ -1,2 +1,2 @@
|
||||||
window.APP_VERSION = '1.0.5';
|
window.APP_VERSION = '1.0.6';
|
||||||
window.APP_VERSION_COLOR = 'hsl(122, 80%, 60%)';
|
window.APP_VERSION_COLOR = 'hsl(123, 80%, 60%)';
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ export default function ChatArea({ activeView, activeChannel, setActiveChannel,
|
||||||
const editTextareaRef = useRef(null);
|
const editTextareaRef = useRef(null);
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
const lastTypingTime = useRef(0);
|
const lastTypingTime = useRef(0);
|
||||||
|
const lastSentReadIdRef = useRef(null);
|
||||||
|
|
||||||
const isDMView = activeView === 'dms';
|
const isDMView = activeView === 'dms';
|
||||||
const gcObj = isDMView ? servers.find(s => s.topicHex === activeChannel && s.isGroupChat) : null;
|
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 latestMsg = currentChannelMessages[currentChannelMessages.length - 1];
|
||||||
const latestMsgId = latestMsg ? latestMsg.id : null;
|
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);
|
markChannelRead(networkChannelId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export default function GroupCallView({ channel, serverTopicHex, vcChannelId, my
|
||||||
};
|
};
|
||||||
|
|
||||||
broadcastState(); // Initial broadcast
|
broadcastState(); // Initial broadcast
|
||||||
const interval = setInterval(broadcastState, 3000);
|
const interval = setInterval(broadcastState, 10000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
|
|
|
||||||
|
|
@ -340,6 +340,12 @@ export default function ProfileSettingsModal({ profile, myKey, onClose, onSave,
|
||||||
>
|
>
|
||||||
Storage Management
|
Storage Management
|
||||||
</button>
|
</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
|
<button
|
||||||
onClick={() => setActiveTab('settings')}
|
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'}`}
|
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} />
|
<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' && (
|
{activeTab === 'settings' && (
|
||||||
<div className="max-w-2xl">
|
<div className="max-w-2xl">
|
||||||
<h2 className="text-xl font-bold text-text mb-6">App Settings</h2>
|
<h2 className="text-xl font-bold text-text mb-6">App Settings</h2>
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ class P2PNetwork {
|
||||||
this.syncTimeout = null;
|
this.syncTimeout = null;
|
||||||
this._msgTimeout = null;
|
this._msgTimeout = null;
|
||||||
this._identityTimeout = null;
|
this._identityTimeout = null;
|
||||||
|
this._reconnectTimeout = null;
|
||||||
|
|
||||||
this.transfers = {};
|
this.transfers = {};
|
||||||
this.webrtcListeners = new Set();
|
this.webrtcListeners = new Set();
|
||||||
|
|
@ -396,10 +397,14 @@ class P2PNetwork {
|
||||||
|
|
||||||
async reconnect() {
|
async reconnect() {
|
||||||
if (!this.swarm) return;
|
if (!this.swarm) return;
|
||||||
|
|
||||||
|
if (this._reconnectTimeout) return;
|
||||||
|
this._reconnectTimeout = setTimeout(() => {
|
||||||
|
this._reconnectTimeout = null;
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
console.log("[P2P] Network online event detected. Reconnecting...");
|
console.log("[P2P] Network online event detected. Reconnecting...");
|
||||||
try {
|
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(()=>{});
|
this.swarm.flush().catch(()=>{});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("[P2P] Reconnect flush failed:", e);
|
console.warn("[P2P] Reconnect flush failed:", e);
|
||||||
|
|
@ -530,7 +535,12 @@ class P2PNetwork {
|
||||||
await Promise.all(corePromises);
|
await Promise.all(corePromises);
|
||||||
|
|
||||||
// SETUP SWARM
|
// 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) => {
|
this.swarm.on('connection', (conn, info) => {
|
||||||
conn.on('error', () => {}); // Prevent ECONNRESET crashes
|
conn.on('error', () => {}); // Prevent ECONNRESET crashes
|
||||||
this.store.replicate(conn);
|
this.store.replicate(conn);
|
||||||
|
|
@ -577,7 +587,7 @@ class P2PNetwork {
|
||||||
|
|
||||||
// BACKGROUND JOINS TO PREVENT UDP FLOOD / NAT EXHAUSTION
|
// BACKGROUND JOINS TO PREVENT UDP FLOOD / NAT EXHAUSTION
|
||||||
(async () => {
|
(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') {
|
if (this.username && this.username !== 'unknown') {
|
||||||
const myTopic = b4a.alloc(32);
|
const myTopic = b4a.alloc(32);
|
||||||
|
|
@ -667,6 +677,7 @@ class P2PNetwork {
|
||||||
this.webrtcListeners.clear();
|
this.webrtcListeners.clear();
|
||||||
if (this._msgTimeout) clearTimeout(this._msgTimeout);
|
if (this._msgTimeout) clearTimeout(this._msgTimeout);
|
||||||
if (this._identityTimeout) clearTimeout(this._identityTimeout);
|
if (this._identityTimeout) clearTimeout(this._identityTimeout);
|
||||||
|
if (this._reconnectTimeout) clearTimeout(this._reconnectTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
async wipeAllData() {
|
async wipeAllData() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user