mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-07 11:16:37 +00:00
Fix ws reconnect and change create site
This commit is contained in:
@@ -139,9 +139,13 @@ export async function createHybridClientServer() {
|
|||||||
logger.error("Failed to connect:", error);
|
logger.error("Failed to connect:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.sendMessageInterval(
|
// Store the ping interval stop function for cleanup if needed
|
||||||
|
const stopPingInterval = client.sendMessageInterval(
|
||||||
"remoteExitNode/ping",
|
"remoteExitNode/ping",
|
||||||
{ timestamp: Date.now() / 1000 },
|
{ timestamp: Date.now() / 1000 },
|
||||||
60000
|
60000
|
||||||
); // send every minute
|
); // send every minute
|
||||||
|
|
||||||
|
// Return client and cleanup function for potential use
|
||||||
|
return { client, stopPingInterval };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ export async function createSite(
|
|||||||
await db.transaction(async (trx) => {
|
await db.transaction(async (trx) => {
|
||||||
let newSite: Site;
|
let newSite: Site;
|
||||||
|
|
||||||
if (exitNodeId) {
|
if ((type == "wireguard" || type == "newt") && exitNodeId) {
|
||||||
// we are creating a site with an exit node (tunneled)
|
// we are creating a site with an exit node (tunneled)
|
||||||
if (!subnet) {
|
if (!subnet) {
|
||||||
return next(
|
return next(
|
||||||
@@ -264,12 +264,14 @@ export async function createSite(
|
|||||||
[newSite] = await trx
|
[newSite] = await trx
|
||||||
.insert(sites)
|
.insert(sites)
|
||||||
.values({
|
.values({
|
||||||
|
exitNodeId: exitNodeId,
|
||||||
orgId,
|
orgId,
|
||||||
name,
|
name,
|
||||||
niceId,
|
niceId,
|
||||||
address: updatedAddress || null,
|
address: updatedAddress || null,
|
||||||
type,
|
type,
|
||||||
dockerSocketEnabled: type == "newt",
|
dockerSocketEnabled: false,
|
||||||
|
online: true,
|
||||||
subnet: "0.0.0.0/0"
|
subnet: "0.0.0.0/0"
|
||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|||||||
@@ -145,11 +145,11 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async connectWithRetry(): Promise<void> {
|
private async connectWithRetry(): Promise<void> {
|
||||||
if (this.isConnecting) return;
|
if (this.isConnecting || this.isConnected) return;
|
||||||
|
|
||||||
this.isConnecting = true;
|
this.isConnecting = true;
|
||||||
|
|
||||||
while (this.shouldReconnect && !this.isConnected) {
|
while (this.shouldReconnect && !this.isConnected && this.isConnecting) {
|
||||||
try {
|
try {
|
||||||
await this.establishConnection();
|
await this.establishConnection();
|
||||||
this.isConnecting = false;
|
this.isConnecting = false;
|
||||||
@@ -157,7 +157,7 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Failed to connect: ${error}. Retrying in ${this.reconnectInterval}ms...`);
|
logger.error(`Failed to connect: ${error}. Retrying in ${this.reconnectInterval}ms...`);
|
||||||
|
|
||||||
if (!this.shouldReconnect) {
|
if (!this.shouldReconnect || !this.isConnecting) {
|
||||||
this.isConnecting = false;
|
this.isConnecting = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -172,6 +172,13 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async establishConnection(): Promise<void> {
|
private async establishConnection(): Promise<void> {
|
||||||
|
// Clean up any existing connection before establishing a new one
|
||||||
|
if (this.conn) {
|
||||||
|
this.conn.removeAllListeners();
|
||||||
|
this.conn.close();
|
||||||
|
this.conn = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the base URL to determine protocol and hostname
|
// Parse the base URL to determine protocol and hostname
|
||||||
const baseURL = new URL(this.baseURL);
|
const baseURL = new URL(this.baseURL);
|
||||||
const wsProtocol = baseURL.protocol === 'https:' ? 'wss' : 'ws';
|
const wsProtocol = baseURL.protocol === 'https:' ? 'wss' : 'ws';
|
||||||
@@ -217,9 +224,8 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
if (this.conn === null) {
|
if (this.conn === null) {
|
||||||
// Connection failed during establishment
|
// Connection failed during establishment
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
|
||||||
this.handleDisconnect();
|
|
||||||
}
|
}
|
||||||
|
// Don't call handleDisconnect here as the 'close' event will handle it
|
||||||
});
|
});
|
||||||
|
|
||||||
conn.on('pong', () => {
|
conn.on('pong', () => {
|
||||||
@@ -232,6 +238,12 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private startPingMonitor(): void {
|
private startPingMonitor(): void {
|
||||||
|
// Clear any existing ping timer to prevent duplicates
|
||||||
|
if (this.pingTimer) {
|
||||||
|
clearInterval(this.pingTimer);
|
||||||
|
this.pingTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.pingTimer = setInterval(() => {
|
this.pingTimer = setInterval(() => {
|
||||||
if (this.conn && this.conn.readyState === WebSocket.OPEN) {
|
if (this.conn && this.conn.readyState === WebSocket.OPEN) {
|
||||||
this.conn.ping();
|
this.conn.ping();
|
||||||
@@ -246,6 +258,11 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private handleDisconnect(): void {
|
private handleDisconnect(): void {
|
||||||
|
// Prevent multiple disconnect handlers from running simultaneously
|
||||||
|
if (!this.isConnected && !this.isConnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setConnected(false);
|
this.setConnected(false);
|
||||||
this.isConnecting = false;
|
this.isConnecting = false;
|
||||||
|
|
||||||
@@ -259,6 +276,12 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
this.pingTimeoutTimer = null;
|
this.pingTimeoutTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear any existing reconnect timer to prevent multiple reconnection attempts
|
||||||
|
if (this.reconnectTimer) {
|
||||||
|
clearTimeout(this.reconnectTimer);
|
||||||
|
this.reconnectTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.conn) {
|
if (this.conn) {
|
||||||
this.conn.removeAllListeners();
|
this.conn.removeAllListeners();
|
||||||
this.conn = null;
|
this.conn = null;
|
||||||
@@ -269,7 +292,7 @@ export class WebSocketClient extends EventEmitter {
|
|||||||
// Reconnect if needed
|
// Reconnect if needed
|
||||||
if (this.shouldReconnect) {
|
if (this.shouldReconnect) {
|
||||||
// Add a small delay before starting reconnection to prevent immediate retry
|
// Add a small delay before starting reconnection to prevent immediate retry
|
||||||
setTimeout(() => {
|
this.reconnectTimer = setTimeout(() => {
|
||||||
this.connectWithRetry();
|
this.connectWithRetry();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default function SiteInfoCard({}: SiteInfoCardProps) {
|
|||||||
</InfoSectionContent>
|
</InfoSectionContent>
|
||||||
</InfoSection>
|
</InfoSection>
|
||||||
|
|
||||||
{env.flags.enableClients && (
|
{env.flags.enableClients && site.type == "newt" && (
|
||||||
<InfoSection>
|
<InfoSection>
|
||||||
<InfoSectionTitle>Address</InfoSectionTitle>
|
<InfoSectionTitle>Address</InfoSectionTitle>
|
||||||
<InfoSectionContent>
|
<InfoSectionContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user