UNPKG

@libp2p/interface-mocks

Version:
162 lines 5.32 kB
import * as STATUS from '@libp2p/interface-connection/status'; import { CodeError } from '@libp2p/interfaces/errors'; import { logger } from '@libp2p/logger'; import * as mss from '@libp2p/multistream-select'; import { peerIdFromString } from '@libp2p/peer-id'; import { duplexPair } from 'it-pair/duplex'; import { pipe } from 'it-pipe'; import { mockMultiaddrConnection } from './multiaddr-connection.js'; import { mockMuxer } from './muxer.js'; import { mockRegistrar } from './registrar.js'; const log = logger('libp2p:mock-connection'); class MockConnection { id; remoteAddr; remotePeer; direction; stat; streams; tags; muxer; maConn; constructor(init) { const { remoteAddr, remotePeer, direction, maConn, muxer } = init; this.id = `mock-connection-${Math.random()}`; this.remoteAddr = remoteAddr; this.remotePeer = remotePeer; this.direction = direction; this.stat = { status: STATUS.OPEN, direction, timeline: maConn.timeline, multiplexer: 'test-multiplexer', encryption: 'yes-yes-very-secure' }; this.streams = []; this.tags = []; this.muxer = muxer; this.maConn = maConn; } async newStream(protocols, options) { if (!Array.isArray(protocols)) { protocols = [protocols]; } if (protocols.length === 0) { throw new Error('protocols must have a length'); } if (this.stat.status !== STATUS.OPEN) { throw new CodeError('connection must be open to create streams', 'ERR_CONNECTION_CLOSED'); } const id = `${Math.random()}`; const stream = await this.muxer.newStream(id); const result = await mss.select(stream, protocols, options); const streamWithProtocol = { ...stream, ...result.stream, stat: { ...stream.stat, direction: 'outbound', protocol: result.protocol } }; this.streams.push(streamWithProtocol); return streamWithProtocol; } addStream(stream) { this.streams.push(stream); } removeStream(id) { this.streams = this.streams.filter(stream => stream.id !== id); } async close() { this.stat.status = STATUS.CLOSING; await this.maConn.close(); this.streams.forEach(s => { s.close(); }); this.stat.status = STATUS.CLOSED; this.stat.timeline.close = Date.now(); } } export function mockConnection(maConn, opts = {}) { const remoteAddr = maConn.remoteAddr; const remotePeerIdStr = remoteAddr.getPeerId() ?? '12D3KooWCrhmFM1BCPGBkNzbPfDk4cjYmtAYSpZwUBC69Qg2kZyq'; if (remotePeerIdStr == null) { throw new Error('Remote multiaddr must contain a peer id'); } const remotePeer = peerIdFromString(remotePeerIdStr); const direction = opts.direction ?? 'inbound'; const registrar = opts.registrar ?? mockRegistrar(); const muxerFactory = opts.muxerFactory ?? mockMuxer(); const muxer = muxerFactory.createStreamMuxer({ direction, onIncomingStream: (muxedStream) => { try { mss.handle(muxedStream, registrar.getProtocols()) .then(({ stream, protocol }) => { log('%s: incoming stream opened on %s', direction, protocol); muxedStream = { ...muxedStream, ...stream }; muxedStream.stat.protocol = protocol; connection.addStream(muxedStream); const { handler } = registrar.getHandler(protocol); handler({ connection, stream: muxedStream }); }).catch(err => { log.error(err); }); } catch (err) { log.error(err); } }, onStreamEnd: (muxedStream) => { connection.removeStream(muxedStream.id); } }); void pipe(maConn, muxer, maConn); const connection = new MockConnection({ remoteAddr, remotePeer, direction, maConn, muxer }); return connection; } export function mockStream(stream) { return { ...stream, close: () => { }, closeRead: () => { }, closeWrite: () => { }, abort: () => { }, reset: () => { }, stat: { direction: 'outbound', protocol: '/foo/1.0.0', timeline: { open: Date.now() } }, metadata: {}, id: `stream-${Date.now()}` }; } export function multiaddrConnectionPair(a, b) { const [peerBtoPeerA, peerAtoPeerB] = duplexPair(); return [ mockMultiaddrConnection(peerAtoPeerB, b.peerId), mockMultiaddrConnection(peerBtoPeerA, a.peerId) ]; } export function connectionPair(a, b) { const [peerBtoPeerA, peerAtoPeerB] = multiaddrConnectionPair(a, b); return [ mockConnection(peerBtoPeerA, { registrar: a.registrar }), mockConnection(peerAtoPeerB, { registrar: b.registrar }) ]; } //# sourceMappingURL=connection.js.map