+138
-2
@@ -161,9 +161,29 @@
|
||||
const conn = new BridgeSwarmConnection(payload.connId, payload.swarmId);
|
||||
this._connections.set(payload.connId, conn);
|
||||
conn.on('end', () => { if (this._connections) this._connections.delete(payload.connId); });
|
||||
const peerInfo = payload.peerInfo || {};
|
||||
const peerInfo = Object.assign({}, payload.peerInfo || {});
|
||||
const swarm = this;
|
||||
peerInfo.ban = function (banned) {
|
||||
return swarm.ban(peerInfo.publicKey, banned !== false);
|
||||
};
|
||||
console.log('[BridgeSwarm-api] Emitting connection event for connId:', payload.connId);
|
||||
this.emit('connection', conn, peerInfo);
|
||||
this.emit('connection', conn, peerInfo, payload);
|
||||
return;
|
||||
}
|
||||
if (msg.event === 'hrpc-chunk' || msg.event === 'hrpc-end' || msg.event === 'hrpc-error') {
|
||||
this.emit(msg.event, payload);
|
||||
if (this._hrpcStreams && payload.streamId && this._hrpcStreams.has(payload.streamId)) {
|
||||
const h = this._hrpcStreams.get(payload.streamId);
|
||||
if (msg.event === 'hrpc-chunk' && h.onChunk) h.onChunk(payload.chunk);
|
||||
if (msg.event === 'hrpc-end') {
|
||||
if (h.resolve) h.resolve(payload.result);
|
||||
this._hrpcStreams.delete(payload.streamId);
|
||||
}
|
||||
if (msg.event === 'hrpc-error') {
|
||||
if (h.reject) h.reject(new Error(payload.message || 'HRPC stream error'));
|
||||
this._hrpcStreams.delete(payload.streamId);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (msg.event === 'data') {
|
||||
@@ -237,6 +257,122 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Ban or unban a peer by public key hex. Also updates the host denylist.
|
||||
* @param {string} publicKeyHex
|
||||
* @param {boolean} [banned=true]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BridgeSwarm.prototype.ban = function (publicKeyHex, banned) {
|
||||
return this._init().then(() =>
|
||||
sendToBridge({
|
||||
id: generateId(),
|
||||
type: 'banPeer',
|
||||
payload: {
|
||||
swarmId: this.swarmId,
|
||||
publicKeyHex: typeof publicKeyHex === 'string' ? publicKeyHex : bufferToHex(publicKeyHex),
|
||||
banned: banned !== false,
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && !res.ok) throw new Error(res.error || 'banPeer failed');
|
||||
return res;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a serializable firewall policy for this swarm.
|
||||
* @param {{ mode: 'off'|'allowlist'|'denylist', keys?: string[] }} opts
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BridgeSwarm.prototype.setFirewall = function (opts) {
|
||||
const o = opts || {};
|
||||
return this._init().then(() =>
|
||||
sendToBridge({
|
||||
id: generateId(),
|
||||
type: 'setFirewall',
|
||||
payload: {
|
||||
swarmId: this.swarmId,
|
||||
mode: o.mode || 'off',
|
||||
keys: o.keys || [],
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && !res.ok) throw new Error(res.error || 'setFirewall failed');
|
||||
return res;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Opt-in automatic Hypercore replication on new connections.
|
||||
* When enabled, connections are taken over by the host (not usable for page chat/Protomux).
|
||||
* @param {{ enabled: boolean, coreKeyHex?: string, resourceId?: string }} opts
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BridgeSwarm.prototype.setAutoReplicate = function (opts) {
|
||||
const o = opts || {};
|
||||
return this._init().then(() =>
|
||||
sendToBridge({
|
||||
id: generateId(),
|
||||
type: 'setAutoReplicate',
|
||||
payload: {
|
||||
swarmId: this.swarmId,
|
||||
enabled: !!o.enabled,
|
||||
coreKeyHex: o.coreKeyHex,
|
||||
resourceId: o.resourceId,
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res && !res.ok) throw new Error(res.error || 'setAutoReplicate failed');
|
||||
return res;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Call an HRPC method on a connection (host-side). Unary returns result;
|
||||
* streaming methods resolve when the stream ends (with optional onChunk).
|
||||
* @param {string} connId
|
||||
* @param {string} method - ping | notify | fetchStream | streamSum | duplex
|
||||
* @param {object} [args]
|
||||
* @param {{ onChunk?: function, timeoutMs?: number }} [options]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BridgeSwarm.prototype.hrpcCall = function (connId, method, args, options) {
|
||||
const opts = options || {};
|
||||
const self = this;
|
||||
if (!self._hrpcStreams) self._hrpcStreams = new Map();
|
||||
return self._init().then(() => {
|
||||
const streamId = 'hrpc_' + Date.now() + '_' + Math.random().toString(36).slice(2);
|
||||
return sendToBridge({
|
||||
id: generateId(),
|
||||
type: 'hrpcInvoke',
|
||||
payload: { connId, method, args: args || {}, streamId },
|
||||
}).then((res) => {
|
||||
if (res && !res.ok) throw new Error(res.error || 'hrpcInvoke failed');
|
||||
if (!res.streaming) return res;
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = opts.timeoutMs > 0
|
||||
? setTimeout(() => {
|
||||
self._hrpcStreams.delete(streamId);
|
||||
reject(new Error('hrpcCall timed out'));
|
||||
}, opts.timeoutMs)
|
||||
: null;
|
||||
self._hrpcStreams.set(streamId, {
|
||||
onChunk: opts.onChunk,
|
||||
resolve: (result) => {
|
||||
if (timer) clearTimeout(timer);
|
||||
resolve({ ok: true, streamId, result: result != null ? result : null, chunksDone: true });
|
||||
},
|
||||
reject: (err) => {
|
||||
if (timer) clearTimeout(timer);
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Snapshot of current connection objects. After destroy() returns [].
|
||||
* @returns {BridgeSwarmConnection[]}
|
||||
|
||||
Reference in New Issue
Block a user