fix: guild mesh dual-conn uses Holepunch initiator tie-break
Keep/drop sockets with shouldKeepNewConnection, wire peerInfo on connection handlers, and preserve leave grace for stable peer maps.
This commit is contained in:
@@ -1716,8 +1716,9 @@ class PearcordGuild extends EventEmitter {
|
||||
if (this._meshConnectionHandler) {
|
||||
this.swarm.removeListener('connection', this._meshConnectionHandler)
|
||||
}
|
||||
this._meshConnectionHandler = (conn) => {
|
||||
this._registerMeshPeer(conn, { emitPeer: true })
|
||||
// Holepunch: connection handler is (socket, peerInfo)
|
||||
this._meshConnectionHandler = (conn, peerInfo) => {
|
||||
this._registerMeshPeer(conn, { emitPeer: true, peerInfo: peerInfo || null })
|
||||
}
|
||||
this._meshHandlerBound = true
|
||||
this.swarm.on('connection', this._meshConnectionHandler)
|
||||
@@ -1758,25 +1759,40 @@ class PearcordGuild extends EventEmitter {
|
||||
_registerMeshPeer (conn, opts = {}) {
|
||||
if (!conn?.remotePublicKey) return { peerId: null, isNew: false }
|
||||
const emitPeer = opts.emitPeer !== false
|
||||
const peerInfo = opts.peerInfo || null
|
||||
const peerId = b4a.toString(conn.remotePublicKey, 'hex')
|
||||
const prevConn = this.peers.get(peerId)
|
||||
const isReplacement = prevConn && prevConn !== conn
|
||||
// Hyperswarm often opens two sockets; keep the live one and drop the duplicate
|
||||
// so join/leave does not thrash the mesh status and gossip outbox.
|
||||
// Holepunch dual-connection tie-break (same rules as hyperswarm/index.js).
|
||||
const { shouldKeepNewConnection, wireSwarmConnection } = require('pearcord-shared')
|
||||
wireSwarmConnection(conn)
|
||||
if (isReplacement && prevConn && !prevConn.destroyed && !prevConn.closed) {
|
||||
const keepNew = shouldKeepNewConnection(prevConn, conn)
|
||||
if (!keepNew) {
|
||||
try {
|
||||
if (typeof prevConn.sendKeepAlive === 'function') prevConn.sendKeepAlive()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
conn.destroy()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
this._ensureMeshPeerWires(peerId, prevConn)
|
||||
const pending = this._peerLeaveGraceTimers?.get?.(peerId)
|
||||
if (pending) {
|
||||
clearTimeout(pending)
|
||||
this._peerLeaveGraceTimers.delete(peerId)
|
||||
}
|
||||
return { peerId, isNew: false, duplicate: true, peerInfo }
|
||||
}
|
||||
// Keep new: tear down old without emitting leave (swap).
|
||||
try {
|
||||
conn.destroy()
|
||||
prevConn.destroy()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
this._ensureMeshPeerWires(peerId, prevConn)
|
||||
// Cancel a pending leave grace if the peer is still live.
|
||||
const pending = this._peerLeaveGraceTimers?.get?.(peerId)
|
||||
if (pending) {
|
||||
clearTimeout(pending)
|
||||
this._peerLeaveGraceTimers.delete(peerId)
|
||||
}
|
||||
return { peerId, isNew: false, duplicate: true }
|
||||
}
|
||||
const isNew = !prevConn
|
||||
if (isReplacement) {
|
||||
@@ -1819,12 +1835,12 @@ class PearcordGuild extends EventEmitter {
|
||||
})
|
||||
}
|
||||
if (emitPeer && isNew) {
|
||||
this.emit('peer', { peerId, type: 'join' })
|
||||
this.emit('peer', { peerId, type: 'join', peerInfo })
|
||||
} else if (emitPeer && isReplacement) {
|
||||
// Soft rewire only — avoid full peer-join handshake storms.
|
||||
this.emit('peer', { peerId, type: 'replace' })
|
||||
this.emit('peer', { peerId, type: 'replace', peerInfo })
|
||||
}
|
||||
return { peerId, isNew }
|
||||
return { peerId, isNew, peerInfo }
|
||||
}
|
||||
|
||||
reconcileMeshConnectionsFromSwarm () {
|
||||
|
||||
Reference in New Issue
Block a user