2019-11-06 15:11:13 +01:00
|
|
|
'use strict'
|
|
|
|
|
2019-11-29 16:41:08 +01:00
|
|
|
const pipe = require('it-pipe')
|
2019-11-06 15:11:13 +01:00
|
|
|
const { Connection } = require('libp2p-interfaces/src/connection')
|
2021-04-15 09:40:02 +02:00
|
|
|
const { Multiaddr } = require('multiaddr')
|
2019-11-29 16:41:08 +01:00
|
|
|
const Muxer = require('libp2p-mplex')
|
|
|
|
const Multistream = require('multistream-select')
|
2019-11-06 15:11:13 +01:00
|
|
|
const pair = require('it-pair')
|
2019-11-29 16:41:08 +01:00
|
|
|
const errCode = require('err-code')
|
|
|
|
const { codes } = require('../../src/errors')
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2019-11-29 16:41:08 +01:00
|
|
|
const mockMultiaddrConnPair = require('./mockMultiaddrConn')
|
2019-11-06 15:11:13 +01:00
|
|
|
const peerUtils = require('./creators/peer')
|
|
|
|
|
|
|
|
module.exports = async (properties = {}) => {
|
2021-04-15 09:40:02 +02:00
|
|
|
const localAddr = new Multiaddr('/ip4/127.0.0.1/tcp/8080')
|
|
|
|
const remoteAddr = new Multiaddr('/ip4/127.0.0.1/tcp/8081')
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-14 14:05:30 +02:00
|
|
|
const [localPeer, remotePeer] = await peerUtils.createPeerId({ number: 2 })
|
2019-11-06 15:11:13 +01:00
|
|
|
const openStreams = []
|
|
|
|
let streamId = 0
|
|
|
|
|
|
|
|
return new Connection({
|
2020-04-14 14:05:30 +02:00
|
|
|
localPeer: localPeer,
|
|
|
|
remotePeer: remotePeer,
|
2019-11-06 15:11:13 +01:00
|
|
|
localAddr,
|
|
|
|
remoteAddr,
|
|
|
|
stat: {
|
|
|
|
timeline: {
|
|
|
|
open: Date.now() - 10,
|
|
|
|
upgraded: Date.now()
|
|
|
|
},
|
|
|
|
direction: 'outbound',
|
2020-05-04 16:03:11 +02:00
|
|
|
encryption: '/noise',
|
2019-11-06 15:11:13 +01:00
|
|
|
multiplexer: '/mplex/6.7.0'
|
|
|
|
},
|
|
|
|
newStream: (protocols) => {
|
|
|
|
const id = streamId++
|
|
|
|
const stream = pair()
|
|
|
|
|
|
|
|
stream.close = () => stream.sink([])
|
|
|
|
stream.id = id
|
|
|
|
|
|
|
|
openStreams.push(stream)
|
|
|
|
|
|
|
|
return {
|
|
|
|
stream,
|
|
|
|
protocol: protocols[0]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
close: () => { },
|
|
|
|
getStreams: () => openStreams,
|
|
|
|
...properties
|
|
|
|
})
|
|
|
|
}
|
2019-11-29 16:41:08 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a full connection pair, without the transport or encryption
|
|
|
|
*
|
|
|
|
* @param {object} options
|
2020-10-06 14:59:43 +02:00
|
|
|
* @param {Multiaddr[]} options.addrs - Should contain two addresses for the local and remote peer respectively
|
|
|
|
* @param {Array<PeerId>} options.peers - Array containing local and remote peer ids
|
|
|
|
* @param {Map<string, Function>} options.protocols - The protocols the connections should support
|
2019-11-29 16:41:08 +01:00
|
|
|
* @returns {{inbound:Connection, outbound:Connection}}
|
|
|
|
*/
|
|
|
|
module.exports.pair = function connectionPair ({ addrs, peers, protocols }) {
|
|
|
|
const [localPeer, remotePeer] = peers
|
|
|
|
|
|
|
|
const {
|
|
|
|
inbound: inboundMaConn,
|
|
|
|
outbound: outboundMaConn
|
|
|
|
} = mockMultiaddrConnPair({ addrs, remotePeer })
|
|
|
|
|
|
|
|
const inbound = createConnection({
|
|
|
|
direction: 'inbound',
|
|
|
|
maConn: inboundMaConn,
|
|
|
|
protocols,
|
|
|
|
// Inbound connection peers are reversed
|
|
|
|
localPeer: remotePeer,
|
|
|
|
remotePeer: localPeer
|
|
|
|
})
|
|
|
|
const outbound = createConnection({
|
|
|
|
direction: 'outbound',
|
|
|
|
maConn: outboundMaConn,
|
|
|
|
protocols,
|
|
|
|
localPeer,
|
|
|
|
remotePeer
|
|
|
|
})
|
|
|
|
|
|
|
|
return { inbound, outbound }
|
|
|
|
}
|
|
|
|
|
|
|
|
function createConnection ({
|
|
|
|
direction,
|
|
|
|
maConn,
|
|
|
|
localPeer,
|
|
|
|
remotePeer,
|
|
|
|
protocols
|
|
|
|
}) {
|
|
|
|
// Create the muxer
|
|
|
|
const muxer = new Muxer({
|
|
|
|
// Run anytime a remote stream is created
|
|
|
|
onStream: async muxedStream => {
|
|
|
|
const mss = new Multistream.Listener(muxedStream)
|
|
|
|
try {
|
|
|
|
const { stream, protocol } = await mss.handle(Array.from(protocols.keys()))
|
|
|
|
connection.addStream(stream, protocol)
|
|
|
|
// Need to be able to notify a peer of this this._onStream({ connection, stream, protocol })
|
|
|
|
const handler = protocols.get(protocol)
|
|
|
|
handler({ connection, stream, protocol })
|
|
|
|
} catch (err) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// Run anytime a stream closes
|
|
|
|
onStreamEnd: muxedStream => {
|
|
|
|
connection.removeStream(muxedStream.id)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const newStream = async protocols => {
|
|
|
|
const muxedStream = muxer.newStream()
|
|
|
|
const mss = new Multistream.Dialer(muxedStream)
|
|
|
|
try {
|
|
|
|
const { stream, protocol } = await mss.select(protocols)
|
|
|
|
return { stream: { ...muxedStream, ...stream }, protocol }
|
|
|
|
} catch (err) {
|
|
|
|
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pipe all data through the muxer
|
|
|
|
pipe(maConn, muxer, maConn)
|
|
|
|
|
|
|
|
maConn.timeline.upgraded = Date.now()
|
|
|
|
|
|
|
|
// Create the connection
|
|
|
|
const connection = new Connection({
|
|
|
|
localAddr: maConn.localAddr,
|
|
|
|
remoteAddr: maConn.remoteAddr,
|
|
|
|
localPeer: localPeer,
|
|
|
|
remotePeer: remotePeer,
|
|
|
|
stat: {
|
|
|
|
direction,
|
|
|
|
timeline: maConn.timeline,
|
|
|
|
multiplexer: Muxer.multicodec,
|
|
|
|
encryption: 'N/A'
|
|
|
|
},
|
|
|
|
newStream,
|
|
|
|
getStreams: () => muxer.streams,
|
|
|
|
close: err => maConn.close(err)
|
|
|
|
})
|
|
|
|
|
|
|
|
return connection
|
|
|
|
}
|