From 07b5011a848c50e8327157d7e5c8e8b836559663 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 3 Jan 2023 14:46:52 +0530 Subject: [PATCH 01/52] browser-to-browser over relayv1 --- package.json | 12 +- proto_ts/peer_transport/pb/hs.ts | 97 +++++++++++ src/index.ts | 6 + src/muxer.ts | 11 +- src/peer_transport/listener.ts | 36 +++++ src/peer_transport/pb/hs.proto | 14 ++ src/peer_transport/transport.ts | 266 +++++++++++++++++++++++++++++++ src/stream.ts | 1 - test/peer.browser.spec.ts | 82 ++++++++++ 9 files changed, 514 insertions(+), 11 deletions(-) create mode 100644 proto_ts/peer_transport/pb/hs.ts create mode 100644 src/peer_transport/listener.ts create mode 100644 src/peer_transport/pb/hs.proto create mode 100644 src/peer_transport/transport.ts create mode 100644 test/peer.browser.spec.ts diff --git a/package.json b/package.json index b7325aa..ce9fd53 100644 --- a/package.json +++ b/package.json @@ -124,10 +124,12 @@ }, "scripts": { "generate:proto": "npx protoc --ts_out proto_ts --proto_path src src/*.proto", + "generate:webrtc-peer": "npx protoc --ts_out proto_ts --proto_path src src/peer_transport/pb/hs.proto", "build": "aegir build", "test": "aegir test -t browser", "test:chrome": "aegir test -t browser -f \"./dist/test/**/*.spec.js\" --cov", "test:firefox": "aegir test -t browser -f \"./dist/test/**/*.spec.js\" -- --browser firefox", + "test:peer": "aegir test -t browser -f \"./dist/test/peer.browser.spec.js\"", "lint": "aegir lint", "lint:fix": "aegir lint --fix", "clean": "aegir clean", @@ -142,29 +144,35 @@ "@libp2p/interface-transport": "^2.0.0", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^1.1.15", - "@multiformats/multiaddr": "^11.0.3", + "@multiformats/multiaddr": "../libp2p/js-multiaddr", "@protobuf-ts/runtime": "^2.8.0", "err-code": "^3.0.1", + "it-handshake": "^4.1.2", "it-length-prefixed": "^8.0.3", "it-merge": "^2.0.0", + "it-pb-stream": "^2.0.3", "it-pipe": "^2.0.4", "it-pushable": "^3.1.0", "it-stream-types": "^1.0.4", "multiformats": "^10.0.0", "multihashes": "^4.0.3", "p-defer": "^4.0.0", + "protons-runtime": "^4.0.1", "uint8arraylist": "^2.3.3", "uint8arrays": "^4.0.2", "uuid": "^9.0.0" }, "devDependencies": { "@libp2p/interface-mocks": "^8.0.1", + "@libp2p/mplex": "7.0.0", "@libp2p/peer-id-factory": "^1.0.19", + "@libp2p/websockets": "^5.0.2", "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "@types/uuid": "^8.3.4", "aegir": "^37.6.6", "it-first": "^2.0.0", - "libp2p": "^0.40.0" + "libp2p": "^0.41.0", + "protons": "^6.0.1" } } diff --git a/proto_ts/peer_transport/pb/hs.ts b/proto_ts/peer_transport/pb/hs.ts new file mode 100644 index 0000000..7859658 --- /dev/null +++ b/proto_ts/peer_transport/pb/hs.ts @@ -0,0 +1,97 @@ +// @generated by protobuf-ts 2.8.2 +// @generated from protobuf file "peer_transport/pb/hs.proto" (package "webrtc_peer.pb", syntax proto2) +// tslint:disable +import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; +import type { IBinaryWriter } from "@protobuf-ts/runtime"; +import { WireType } from "@protobuf-ts/runtime"; +import type { BinaryReadOptions } from "@protobuf-ts/runtime"; +import type { IBinaryReader } from "@protobuf-ts/runtime"; +import { UnknownFieldHandler } from "@protobuf-ts/runtime"; +import type { PartialMessage } from "@protobuf-ts/runtime"; +import { reflectionMergePartial } from "@protobuf-ts/runtime"; +import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; +import { MessageType } from "@protobuf-ts/runtime"; +/** + * @generated from protobuf message webrtc_peer.pb.Message + */ +export interface Message { + /** + * @generated from protobuf field: webrtc_peer.pb.Message.MessageType type = 1; + */ + type: Message_MessageType; + /** + * @generated from protobuf field: string data = 2; + */ + data: string; +} +/** + * @generated from protobuf enum webrtc_peer.pb.Message.MessageType + */ +export enum Message_MessageType { + /** + * @generated from protobuf enum value: OFFER = 0; + */ + OFFER = 0, + /** + * @generated from protobuf enum value: ANSWER = 1; + */ + ANSWER = 1, + /** + * @generated from protobuf enum value: CANDIDATE = 2; + */ + CANDIDATE = 2 +} +// @generated message type with reflection information, may provide speed optimized methods +class Message$Type extends MessageType { + constructor() { + super("webrtc_peer.pb.Message", [ + { no: 1, name: "type", kind: "enum", T: () => ["webrtc_peer.pb.Message.MessageType", Message_MessageType] }, + { no: 2, name: "data", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): Message { + const message = { type: 0, data: "" }; + globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Message): Message { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* webrtc_peer.pb.Message.MessageType type */ 1: + message.type = reader.int32(); + break; + case /* string data */ 2: + message.data = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: Message, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* webrtc_peer.pb.Message.MessageType type = 1; */ + if (message.type !== 0) + writer.tag(1, WireType.Varint).int32(message.type); + /* string data = 2; */ + if (message.data !== "") + writer.tag(2, WireType.LengthDelimited).string(message.data); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message webrtc_peer.pb.Message + */ +export const Message = new Message$Type(); diff --git a/src/index.ts b/src/index.ts index 826069a..b6afae8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,12 @@ import type { Transport } from '@libp2p/interface-transport' +import type {WebRTCPeerTransportComponents, WebRTCPeerTransportInit} from './peer_transport/transport.js' +import { WebRTCPeerTransport } from './peer_transport/transport.js' import { WebRTCTransport, WebRTCTransportComponents } from './transport.js' export function webRTC (): (components: WebRTCTransportComponents) => Transport { return (components: WebRTCTransportComponents) => new WebRTCTransport(components) } + +export function webRTCPeer (init: WebRTCPeerTransportInit): (components: WebRTCPeerTransportComponents) => Transport { + return (components: WebRTCPeerTransportComponents) => new WebRTCPeerTransport(components, init) +} diff --git a/src/muxer.ts b/src/muxer.ts index 7b0eb83..2d145f5 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -14,14 +14,13 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory { /** * The string representation of the protocol, required by `StreamMuxerFactory` */ - protocol: string = '/webrtc' - constructor (peerConnection: RTCPeerConnection) { + constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc') { this.peerConnection = peerConnection } createStreamMuxer (init?: StreamMuxerInit | undefined): StreamMuxer { - return new DataChannelMuxer(this.peerConnection, init) + return new DataChannelMuxer(this.peerConnection, this.protocol, init) } } @@ -33,10 +32,6 @@ export class DataChannelMuxer implements StreamMuxer { * WebRTC Peer Connection */ private readonly peerConnection: RTCPeerConnection - /** - * The protocol as represented in the multiaddress - */ - readonly protocol: string = '/webrtc' /** * Array of streams in the data channel @@ -63,7 +58,7 @@ export class DataChannelMuxer implements StreamMuxer { */ sink: Sink> = nopSink; - constructor (peerConnection: RTCPeerConnection, init?: StreamMuxerInit) { + constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc', init?: StreamMuxerInit) { /** * Initialized stream muxer */ diff --git a/src/peer_transport/listener.ts b/src/peer_transport/listener.ts new file mode 100644 index 0000000..5d5093a --- /dev/null +++ b/src/peer_transport/listener.ts @@ -0,0 +1,36 @@ +// import type { ConnectionManager } from '@libp2p/interface-connection-manager' +import type { PeerId } from '@libp2p/interface-peer-id'; +import type { ListenerEvents, TransportManager, Upgrader } from '@libp2p/interface-transport'; +import type { Listener } from '@libp2p/interface-transport'; +import { EventEmitter } from '@libp2p/interfaces/events'; +import { multiaddr, Multiaddr } from '@multiformats/multiaddr'; + +export interface ListenerOptions { + peerId: PeerId, + upgrader: Upgrader, + transportManager: TransportManager +} + +export class WebRTCPeerListener extends EventEmitter implements Listener { + constructor( + private readonly opts: ListenerOptions, + ) { + super() + } + + private listeningAddrs: Multiaddr[] = [] + async listen(ma: Multiaddr): Promise { + const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) + const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) + const listener = tpt?.createListener({ ...this.opts }) + await listener?.listen(baseAddr) + const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId}`) + this.listeningAddrs.push(listeningAddr) + listener?.addEventListener('close', () => { + this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) + }) + } + + getAddrs(): Multiaddr[] { return this.listeningAddrs } + async close() { } +} diff --git a/src/peer_transport/pb/hs.proto b/src/peer_transport/pb/hs.proto new file mode 100644 index 0000000..cc11597 --- /dev/null +++ b/src/peer_transport/pb/hs.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +package webrtc_peer.pb; + +message Message { + enum MessageType { + OFFER = 0; + ANSWER = 1; + CANDIDATE = 2; + } + + required MessageType type = 1; + required string data = 2; +} diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts new file mode 100644 index 0000000..acf8663 --- /dev/null +++ b/src/peer_transport/transport.ts @@ -0,0 +1,266 @@ +import type {Connection} from "@libp2p/interface-connection"; +import {CreateListenerOptions, DialOptions, Listener, symbol, Transport} from "@libp2p/interface-transport"; +import type {ConnectionHandler, TransportManager, Upgrader} from "@libp2p/interface-transport"; +import {multiaddr, Multiaddr} from "@multiformats/multiaddr"; +import type {IncomingStreamData} from "@libp2p/interface-registrar" +import {pbStream, ProtobufStream} from 'it-pb-stream' +import pDefer, {DeferredPromise} from "p-defer"; +import type {Registrar} from '@libp2p/interface-registrar' +import type {PeerId} from "@libp2p/interface-peer-id"; +import {abortableDuplex} from 'abortable-iterator' +import {TimeoutController} from 'timeout-abort-controller' +import {WebRTCMultiaddrConnection} from "../maconn.js"; +import type {Startable} from "@libp2p/interfaces/startable" +import {DataChannelMuxerFactory} from "../muxer.js"; +import {WebRTCPeerListener} from "./listener.js"; +import type {PeerStore} from '@libp2p/interface-peer-store' +import {logger} from "@libp2p/logger"; +import * as pb from '../../proto_ts/peer_transport/pb/hs.js' + +const log = logger('webrtc-peer') + +const TIMEOUT = 30 * 1000 +export const TRANSPORT = '/webrtc-peer' +export const PROTOCOL = '/webrtc-peer/0.0.1' +export const CODE = 281 + +export type WebRTCPeerTransportInit = { + rtcConfiguration?: RTCConfiguration +} + +export type WebRTCPeerTransportComponents = { + peerId: PeerId + registrar: Registrar + upgrader: Upgrader + transportManager: TransportManager + peerStore: PeerStore +}; + +export class WebRTCPeerTransport implements Transport, Startable { + private _started = false + private handler?: ConnectionHandler + + constructor( + private readonly components: WebRTCPeerTransportComponents, + private readonly init: WebRTCPeerTransportInit, + ) {} + + isStarted() { + return this._started + } + + async start() { + await this.components.registrar.handle(PROTOCOL, this._onProtocol.bind(this)) + // this.components.peerStore.addEventListener('change:multiaddrs', (event) => { + // const { peerId } = event.detail + // }) + } + async stop() { + await this.components.registrar.unhandle(PROTOCOL) + } + + createListener(options: CreateListenerOptions): Listener { + return new WebRTCPeerListener(this.components) + } + + get [Symbol.toStringTag](): string { + return '@libp2p/webrtc-peer' + } + + get [symbol](): true { + return true + } + + filter(multiaddrs: Multiaddr[]): Multiaddr[] { + return multiaddrs.filter((ma) => { + const codes = ma.protoCodes() + return codes.includes(CODE) + }) + } + + /* + * dial connects to a remote via the circuit relay or any other protocol + * and proceeds to upgrade to a webrtc connection. + * multiaddr of the form: /webrtc-peer/p2p/ + * For a circuit relay, this will be of the form + * /p2p//p2p-circuit/p2p//webrtc-sdp/p2p/ + */ + async dial(ma: Multiaddr, options: DialOptions): Promise { + // extract peer id + const addrs = ma.toString().split('/webrtc-peer') + const relayed = multiaddr(addrs[0]) + // const destination = multiaddr(addrs[addrs.length - 1]) + // + log(this.init) + + if (!options.signal) { + options.signal = new AbortSignal() + } + const connection = await this.components.transportManager.dial(relayed) + const rawStream = await connection.newStream([PROTOCOL], options) + const stream = pbStream(abortableDuplex(rawStream, options.signal)) + + const pc = new RTCPeerConnection(this.init.rtcConfiguration) + const channel = pc.createDataChannel("init") + const offer = await pc.createOffer() + await pc.setLocalDescription(offer) + + const connectedPromise = pDefer(); + pc.onconnectionstatechange = (_) => { + switch (pc.connectionState) { + case 'connected': + return connectedPromise.resolve(0); + case 'closed': + case 'disconnected': + case 'failed': + return connectedPromise.reject(); + } + } + options.signal.onabort = connectedPromise.reject + pc.onicecandidate = ({candidate}) => { + writeMessage(stream, { + type: pb.Message_MessageType.CANDIDATE, + data: candidate ? JSON.stringify(candidate) : '', + }); + } + // write offer + writeMessage(stream, {type: pb.Message_MessageType.OFFER, data: offer.sdp!}) + + // read answer + const answerMessage = await readMessage(stream) + if (answerMessage.type != pb.Message_MessageType.ANSWER) { + throw new Error('should read answer') + } + + const answerSdp = new RTCSessionDescription({type: 'answer', sdp: answerMessage.data}) + await pc.setRemoteDescription(answerSdp) + + let continueReading = true + while (continueReading) { + const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) + if (result === 0) { + break; + } + + const message = result as pb.Message + if (message.type != pb.Message_MessageType.CANDIDATE) { + continue + } + + if (message.data == '') { + continueReading = false + break + } + + const candidate = new RTCIceCandidate(JSON.parse(message.data)) + pc.addIceCandidate(candidate) + } + + await connectedPromise.promise + rawStream.close() + channel.close() + const result = options.upgrader.upgradeOutbound( + new WebRTCMultiaddrConnection({ + peerConnection: pc, + timeline: {open: (new Date()).getTime()}, + remoteAddr: connection.remoteAddr, + }), + { + skipProtection: true, + skipEncryption: true, + muxerFactory: new DataChannelMuxerFactory(pc, '/webrtc-peer'), + } + ) + // TODO: hack + await new Promise(res => setTimeout(res, 100)) + return result + } + + async _onProtocol({connection, stream: rawStream}: IncomingStreamData) { + const timeoutController = new TimeoutController(TIMEOUT) + const signal = timeoutController.signal + const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)) + const pc = new RTCPeerConnection(this.init.rtcConfiguration) + + const connectedPromise: DeferredPromise = pDefer() + signal.onabort = () => connectedPromise.reject() + // candidate callbacks + pc.onicecandidate = ({candidate}) => { + writeMessage(stream, { + type: pb.Message_MessageType.CANDIDATE, + data: candidate ? JSON.stringify(candidate!.toJSON()) : '', + }) + } + pc.onconnectionstatechange = (_) => { + log.trace('received pc state: ', pc.connectionState) + switch (pc.connectionState) { + case 'connected': + connectedPromise.resolve(0) + break + case 'failed': + case 'disconnected': + case 'closed': + connectedPromise.reject() + } + } + + const pbOffer = await readMessage(stream) + if (pbOffer.type != pb.Message_MessageType.OFFER) { + throw new Error('initial message should be an offer') + } + const offer = new RTCSessionDescription({ + type: 'offer', + sdp: pbOffer.data, + }) + + await pc.setRemoteDescription(offer) + log.trace('offer', offer) + const answer = await pc.createAnswer() + await pc.setLocalDescription(answer) + writeMessage(stream, {type: pb.Message_MessageType.ANSWER, data: answer.sdp!}) + log.trace('answer', offer) + let continueReading = true + while (continueReading) { + const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) + if (result === 0) { + break; + } + + const message = result as pb.Message + if (message.type != pb.Message_MessageType.CANDIDATE) { + throw new Error('should only receive trickle candidates') + } + if (message.data === '') { + continueReading = false + break + } + + const candidate = new RTCIceCandidate(JSON.parse(message.data)) + await pc.addIceCandidate(candidate) + } + await connectedPromise.promise; + rawStream.close() + const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-peer') + const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ + peerConnection: pc, + timeline: {open: (new Date()).getTime()}, + remoteAddr: connection.remoteAddr, + }), { + skipEncryption: true, + skipProtection: true, + muxerFactory + }) + if (this.handler) { + this.handler(conn) + } + } +} + +function writeMessage(stream: ProtobufStream, message: pb.Message) { + stream.writeLP(pb.Message.toBinary(message)) +} + +async function readMessage(stream: ProtobufStream): Promise { + const raw = await stream.readLP() + return pb.Message.fromBinary(raw.subarray()) +} diff --git a/src/stream.ts b/src/stream.ts index 77ca333..a05918c 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -204,7 +204,6 @@ export class WebRTCStream implements Stream { constructor (opts: StreamInitOpts) { this.channel = opts.channel this.id = this.channel.label - this.stat = opts.stat switch (this.channel.readyState) { case 'open': diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts new file mode 100644 index 0000000..7a484fd --- /dev/null +++ b/test/peer.browser.spec.ts @@ -0,0 +1,82 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions */ + +import {createLibp2p} from 'libp2p' +import {webRTCPeer} from '../src' +import {webSockets} from '@libp2p/websockets' +import * as filters from '@libp2p/websockets/filters' +import {mplex} from '@libp2p/mplex' +import {noise} from '@chainsafe/libp2p-noise' +import {multiaddr} from '@multiformats/multiaddr' +import pDefer from 'p-defer' +import {pipe} from 'it-pipe' +import {fromString} from 'uint8arrays/from-string' +import {toString} from 'uint8arrays/to-string' +import first from 'it-first' +import { expect } from 'aegir/chai' + +describe('test relay', () => { + it('can connect via sdp', async () => { + const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmPTaKo3xkWH7spf1i8JP79FXHt6BGXMrqhvBZyBTxCUaz'); + const listener = await createLibp2p({ + transports: [ + webRTCPeer({}), + webSockets({ + filter: filters.all, + }), + ], + streamMuxers: [mplex()], + connectionEncryption: [noise()], + relay: { + enabled: true, + autoRelay: { + enabled: true, + maxListeners: 2, + } + }, + }) + const dialer = await createLibp2p({ + transports: [ + webRTCPeer({}), + webSockets({ + filter: filters.all, + }), + ], + streamMuxers: [mplex()], + connectionEncryption: [noise()], + }) + + await listener.start() + await dialer.start() + + + const relaying = pDefer() + listener.peerStore.addEventListener('change:multiaddrs', (event) => { + const {peerId} = event.detail + + // Updated self multiaddrs? + if (peerId.equals(listener.peerId)) { + const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` + console.log(`Advertising with a relay address of ${listener.getMultiaddrs()[0].toString()}`) + relaying.resolve(webrtcAddr) + } + }) + + listener.handle('/echo/1.0.0', ({stream}) => { + void pipe(stream, stream) + }) + + await listener.dial(relayAddress) + const dialAddr = multiaddr(await relaying.promise) + const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) + const input = fromString('test') + const output = await pipe( + [input], + stream, + async (source) => await first(source), + ); + expect(toString(output!.subarray())).to.equals('test') + console.log('read data', output!.subarray()) + }) +}) + +export {} From cf7c2bd30e2e1a9ff33ba89571d8e0c6e31e09b4 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 3 Jan 2023 23:02:26 +0530 Subject: [PATCH 02/52] debug --- src/peer_transport/transport.ts | 9 +++- src/transport.ts | 74 ++++++++++++++++++--------------- test/peer.browser.spec.ts | 70 ++++++++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 37 deletions(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index acf8663..da0ec4f 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -96,7 +96,14 @@ export class WebRTCPeerTransport implements Transport, Startable { if (!options.signal) { options.signal = new AbortSignal() } - const connection = await this.components.transportManager.dial(relayed) + let connection + try { + connection = await this.components.transportManager.dial(relayed) + } catch (err) { + console.log(err) + throw err + } + const rawStream = await connection.newStream([PROTOCOL], options) const stream = pbStream(abortableDuplex(rawStream, options.signal)) diff --git a/src/transport.ts b/src/transport.ts index 6fc10bd..58c628e 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -1,22 +1,23 @@ -import { noise as Noise } from '@chainsafe/libp2p-noise' -import type { Connection } from '@libp2p/interface-connection' -import type { PeerId } from '@libp2p/interface-peer-id' -import { CreateListenerOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' -import { logger } from '@libp2p/logger' -import * as p from '@libp2p/peer-id' -import type { Multiaddr } from '@multiformats/multiaddr' +import {noise as Noise} from '@chainsafe/libp2p-noise' +import type {Connection} from '@libp2p/interface-connection' +import type {PeerId} from '@libp2p/interface-peer-id' +import {CreateListenerOptions, Listener, ListenerEvents, symbol, Transport} from '@libp2p/interface-transport' +import {logger} from '@libp2p/logger' +// import * as p from '@libp2p/peer-id' +import type {Multiaddr} from '@multiformats/multiaddr' import * as multihashes from 'multihashes' import defer from 'p-defer' -import { v4 as genUuid } from 'uuid' -import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { concat } from 'uint8arrays/concat' - -import { dataChannelError, inappropriateMultiaddr, unimplemented, invalidArgument } from './error.js' -import { WebRTCMultiaddrConnection } from './maconn.js' -import { DataChannelMuxerFactory } from './muxer.js' -import type { WebRTCDialOptions } from './options.js' +import {v4 as genUuid} from 'uuid' +import {fromString as uint8arrayFromString} from 'uint8arrays/from-string' +import {concat} from 'uint8arrays/concat' + +import {dataChannelError, inappropriateMultiaddr, invalidArgument} from './error.js' +import {WebRTCMultiaddrConnection} from './maconn.js' +import {DataChannelMuxerFactory} from './muxer.js' +import type {WebRTCDialOptions} from './options.js' import * as sdp from './sdp.js' -import { WebRTCStream } from './stream.js' +import {WebRTCStream} from './stream.js' +import { EventEmitter } from '@libp2p/interfaces/events' const log = logger('libp2p:webrtc:transport') @@ -53,14 +54,14 @@ export class WebRTCTransport implements Transport { */ private readonly components: WebRTCTransportComponents - constructor (components: WebRTCTransportComponents) { + constructor(components: WebRTCTransportComponents) { this.components = components } /** * Dial a given multiaddr */ - async dial (ma: Multiaddr, options: WebRTCDialOptions): Promise { + async dial(ma: Multiaddr, options: WebRTCDialOptions): Promise { const rawConn = await this._connect(ma, options) log(`dialing address - ${ma.toString()}`) return rawConn @@ -69,35 +70,39 @@ export class WebRTCTransport implements Transport { /** * Create transport listeners no supported by browsers */ - createListener (options: CreateListenerOptions): Listener { - throw unimplemented('WebRTCTransport.createListener') + createListener(options: CreateListenerOptions): Listener { + return Object.assign(new EventEmitter(), { + listen: async (_: Multiaddr) => {}, + getAddrs: () => [], + close: async () => {}, + }) } /** * Takes a list of `Multiaddr`s and returns only valid addresses for the transport */ - filter (multiaddrs: Multiaddr[]): Multiaddr[] { + filter(multiaddrs: Multiaddr[]): Multiaddr[] { return multiaddrs.filter(validMa) } /** * Implement toString() for WebRTCTransport */ - get [Symbol.toStringTag] (): string { + get [Symbol.toStringTag](): string { return '@libp2p/webrtc' } /** * Symbol.for('@libp2p/transport') */ - get [symbol] (): true { + get [symbol](): true { return true } /** * Connect to a peer using a multiaddr */ - async _connect (ma: Multiaddr, options: WebRTCDialOptions): Promise { + async _connect(ma: Multiaddr, options: WebRTCDialOptions): Promise { const rps = ma.getPeerId() if (rps === null) { @@ -115,13 +120,13 @@ export class WebRTCTransport implements Transport { namedCurve: 'P-256', hash: sdp.toSupportedHashFunction(remoteCerthash.name) } as any) - const peerConnection = new RTCPeerConnection({ certificates: [certificate] }) + const peerConnection = new RTCPeerConnection({certificates: [certificate]}) // create data channel for running the noise handshake. Once the data channel is opened, // the remote will initiate the noise handshake. This is used to confirm the identity of // the peer. const dataChannelOpenPromise = defer() - const handshakeDataChannel = peerConnection.createDataChannel('handshake', { negotiated: true, id: 0 }) + const handshakeDataChannel = peerConnection.createDataChannel('handshake', {negotiated: true, id: 0}) const handhsakeTimeout = setTimeout(() => { const error = `Data channel was never opened: state: ${handshakeDataChannel.readyState}` log.error(error) @@ -160,7 +165,7 @@ export class WebRTCTransport implements Transport { await dataChannelOpenPromise.promise const myPeerId = this.components.peerId - const theirPeerId = p.peerIdFromString(rps) + // const theirPeerId = p.peerIdFromString(rps) // Do noise handshake. // Set the Noise Prologue to libp2p-webrtc-noise: before starting the actual Noise handshake. @@ -169,13 +174,13 @@ export class WebRTCTransport implements Transport { // Since we use the default crypto interface and do not use a static key or early data, // we pass in undefined for these parameters. - const noiseInit = { staticNoiseKey: undefined, extensions: undefined, crypto: undefined, prologueBytes: fingerprintsPrologue } + const noiseInit = {staticNoiseKey: undefined, extensions: undefined, crypto: undefined, prologueBytes: fingerprintsPrologue} const noise = Noise(noiseInit)() - const wrappedChannel = new WebRTCStream({ channel: handshakeDataChannel, stat: { direction: 'outbound', timeline: { open: 1 } } }) + const wrappedChannel = new WebRTCStream({channel: handshakeDataChannel, stat: {direction: 'outbound', timeline: {open: 1}}}) const wrappedDuplex = { ...wrappedChannel, source: { - [Symbol.asyncIterator]: async function * () { + [Symbol.asyncIterator]: async function* () { for await (const list of wrappedChannel.source) { yield list.subarray() } @@ -197,16 +202,17 @@ export class WebRTCTransport implements Transport { // For outbound connections, the remote is expected to start the noise handshake. // Therefore, we need to secure an inbound noise connection from the remote. - await noise.secureInbound(myPeerId, wrappedDuplex, theirPeerId) + await noise.secureInbound(myPeerId, wrappedDuplex) - return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory }) + await new Promise(res => setTimeout(res, 100)) + return options.upgrader.upgradeOutbound(maConn, {skipProtection: true, skipEncryption: true, muxerFactory}) } /** * Generate a noise prologue from the peer connection's certificate. * noise prologue = bytes('libp2p-webrtc-noise:') + noise-responder fingerprint + noise-initiator fingerprint */ - private generateNoisePrologue (pc: RTCPeerConnection, hashName: multihashes.HashName, ma: Multiaddr): Uint8Array { + private generateNoisePrologue(pc: RTCPeerConnection, hashName: multihashes.HashName, ma: Multiaddr): Uint8Array { if (pc.getConfiguration().certificates?.length === 0) { throw invalidArgument('no local certificate') } @@ -237,7 +243,7 @@ export class WebRTCTransport implements Transport { * Determine if a given multiaddr contains a WebRTC Code (280), * a Certhash Code (466) and a PeerId */ -function validMa (ma: Multiaddr): boolean { +function validMa(ma: Multiaddr): boolean { const codes = ma.protoCodes() return codes.includes(WEBRTC_CODE) && codes.includes(CERTHASH_CODE) && ma.getPeerId() != null } diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 7a484fd..49c66e2 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-expressions */ import {createLibp2p} from 'libp2p' -import {webRTCPeer} from '../src' +import {webRTC, webRTCPeer} from '../src' import {webSockets} from '@libp2p/websockets' import * as filters from '@libp2p/websockets/filters' import {mplex} from '@libp2p/mplex' @@ -15,7 +15,7 @@ import first from 'it-first' import { expect } from 'aegir/chai' describe('test relay', () => { - it('can connect via sdp', async () => { + it.skip('can connect over ws relay', async () => { const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmPTaKo3xkWH7spf1i8JP79FXHt6BGXMrqhvBZyBTxCUaz'); const listener = await createLibp2p({ transports: [ @@ -77,6 +77,72 @@ describe('test relay', () => { expect(toString(output!.subarray())).to.equals('test') console.log('read data', output!.subarray()) }) + + it('can connect over webrtc relay', async () => { + const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiAPJJtPGt5IW6ADFgtF3emYXZemfmYklaygdxRTUZN6Vw/p2p/QmQSDKcFSmNqWX6auHxMmsADHZcD89xYtaxMYgUGjP5Ej7'); + const listener = await createLibp2p({ + transports: [ + webRTCPeer({}), + webRTC(), + ], + streamMuxers: [mplex()], + connectionEncryption: [noise()], + relay: { + enabled: true, + autoRelay: { + enabled: true, + maxListeners: 2, + } + }, + }) + const dialer = await createLibp2p({ + transports: [ + webRTCPeer({}), + webRTC(), + ], + streamMuxers: [mplex()], + connectionEncryption: [noise()], + }) + + await listener.start() + await dialer.start() + + + const relaying = pDefer() + listener.peerStore.addEventListener('change:multiaddrs', (event) => { + const {peerId} = event.detail + + // Updated self multiaddrs? + if (peerId.equals(listener.peerId)) { + const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` + console.log(`Advertising with a relay address of ${listener.getMultiaddrs()[0].toString()}`) + relaying.resolve(webrtcAddr) + } + }) + + listener.handle('/echo/1.0.0', ({stream}) => { + void pipe(stream, stream) + }) + + console.log('listener connecting') + await listener.dial(relayAddress) + console.log('listener connected') + const addr = await relaying.promise + console.log('addr', addr) + const dialAddr = multiaddr(addr) + console.log('dialer connecting') + const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) + console.log('dialer connected') + const input = fromString('test') + const output = await pipe( + [input], + stream, + async (source) => await first(source), + ); + expect(toString(output!.subarray())).to.equals('test') + console.log('read data', output!.subarray()) + + }) }) export {} From f2fc6e3f6b15d7e0e7d096a2d96eae92b7bd8024 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Thu, 5 Jan 2023 11:13:28 +0530 Subject: [PATCH 03/52] fix race condition --- package.json | 8 +- src/index.ts | 2 +- src/muxer.ts | 9 +- src/peer_transport/listener.ts | 49 ++++++----- src/peer_transport/transport.ts | 140 ++++++++++++++++---------------- src/sdp.ts | 9 +- src/stream.ts | 34 ++++++-- src/transport.ts | 112 +++++++++++++------------ test/peer.browser.spec.ts | 81 +++++++++--------- 9 files changed, 238 insertions(+), 206 deletions(-) diff --git a/package.json b/package.json index ce9fd53..ce95a91 100644 --- a/package.json +++ b/package.json @@ -140,11 +140,12 @@ "@chainsafe/libp2p-noise": "^10.0.0", "@libp2p/interface-connection": "^3.0.2", "@libp2p/interface-peer-id": "^1.0.5", - "@libp2p/interface-stream-muxer": "^3.0.0", + "@libp2p/interface-stream-muxer": "^3.0.4", "@libp2p/interface-transport": "^2.0.0", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^1.1.15", "@multiformats/multiaddr": "../libp2p/js-multiaddr", + "@multiformats/mafmt": "../libp2p/js-mafmt", "@protobuf-ts/runtime": "^2.8.0", "err-code": "^3.0.1", "it-handshake": "^4.1.2", @@ -158,13 +159,14 @@ "multihashes": "^4.0.3", "p-defer": "^4.0.0", "protons-runtime": "^4.0.1", + "timeout-abort-controller": "^3.0.0", "uint8arraylist": "^2.3.3", "uint8arrays": "^4.0.2", "uuid": "^9.0.0" }, "devDependencies": { "@libp2p/interface-mocks": "^8.0.1", - "@libp2p/mplex": "7.0.0", + "@libp2p/mplex": "^7.1.1", "@libp2p/peer-id-factory": "^1.0.19", "@libp2p/websockets": "^5.0.2", "@protobuf-ts/plugin": "^2.8.0", @@ -172,7 +174,7 @@ "@types/uuid": "^8.3.4", "aegir": "^37.6.6", "it-first": "^2.0.0", - "libp2p": "^0.41.0", + "libp2p": "file:../js-libp2p", "protons": "^6.0.1" } } diff --git a/src/index.ts b/src/index.ts index b6afae8..fb5a117 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import type { Transport } from '@libp2p/interface-transport' -import type {WebRTCPeerTransportComponents, WebRTCPeerTransportInit} from './peer_transport/transport.js' +import type { WebRTCPeerTransportComponents, WebRTCPeerTransportInit } from './peer_transport/transport.js' import { WebRTCPeerTransport } from './peer_transport/transport.js' import { WebRTCTransport, WebRTCTransportComponents } from './transport.js' diff --git a/src/muxer.ts b/src/muxer.ts index 2d145f5..e101002 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -11,12 +11,13 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory { */ private readonly peerConnection: RTCPeerConnection - /** - * The string representation of the protocol, required by `StreamMuxerFactory` - */ - constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc') { this.peerConnection = peerConnection + // reject any datachannels as the muxer is not yet ready to process + // streams + this.peerConnection.ondatachannel = ({ channel }) => { + channel.close() + } } createStreamMuxer (init?: StreamMuxerInit | undefined): StreamMuxer { diff --git a/src/peer_transport/listener.ts b/src/peer_transport/listener.ts index 5d5093a..c537dae 100644 --- a/src/peer_transport/listener.ts +++ b/src/peer_transport/listener.ts @@ -1,36 +1,35 @@ // import type { ConnectionManager } from '@libp2p/interface-connection-manager' -import type { PeerId } from '@libp2p/interface-peer-id'; -import type { ListenerEvents, TransportManager, Upgrader } from '@libp2p/interface-transport'; -import type { Listener } from '@libp2p/interface-transport'; -import { EventEmitter } from '@libp2p/interfaces/events'; -import { multiaddr, Multiaddr } from '@multiformats/multiaddr'; +import type { PeerId } from '@libp2p/interface-peer-id' +import type { ListenerEvents, TransportManager, Upgrader, Listener } from '@libp2p/interface-transport' +import { EventEmitter } from '@libp2p/interfaces/events' +import { multiaddr, Multiaddr } from '@multiformats/multiaddr' export interface ListenerOptions { - peerId: PeerId, - upgrader: Upgrader, - transportManager: TransportManager + peerId: PeerId + upgrader: Upgrader + transportManager: TransportManager } export class WebRTCPeerListener extends EventEmitter implements Listener { - constructor( - private readonly opts: ListenerOptions, - ) { - super() - } + constructor ( + private readonly opts: ListenerOptions + ) { + super() + } private listeningAddrs: Multiaddr[] = [] - async listen(ma: Multiaddr): Promise { - const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) - const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) - const listener = tpt?.createListener({ ...this.opts }) - await listener?.listen(baseAddr) - const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId}`) - this.listeningAddrs.push(listeningAddr) - listener?.addEventListener('close', () => { - this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) - }) + async listen (ma: Multiaddr): Promise { + const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) + const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) + const listener = tpt?.createListener({ ...this.opts }) + await listener?.listen(baseAddr) + const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId}`) + this.listeningAddrs.push(listeningAddr) + listener?.addEventListener('close', () => { + this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) + }) } - getAddrs(): Multiaddr[] { return this.listeningAddrs } - async close() { } + getAddrs (): Multiaddr[] { return this.listeningAddrs } + async close () { } } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index da0ec4f..7e92ec2 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -1,77 +1,80 @@ -import type {Connection} from "@libp2p/interface-connection"; -import {CreateListenerOptions, DialOptions, Listener, symbol, Transport} from "@libp2p/interface-transport"; -import type {ConnectionHandler, TransportManager, Upgrader} from "@libp2p/interface-transport"; -import {multiaddr, Multiaddr} from "@multiformats/multiaddr"; -import type {IncomingStreamData} from "@libp2p/interface-registrar" -import {pbStream, ProtobufStream} from 'it-pb-stream' -import pDefer, {DeferredPromise} from "p-defer"; -import type {Registrar} from '@libp2p/interface-registrar' -import type {PeerId} from "@libp2p/interface-peer-id"; -import {abortableDuplex} from 'abortable-iterator' -import {TimeoutController} from 'timeout-abort-controller' -import {WebRTCMultiaddrConnection} from "../maconn.js"; -import type {Startable} from "@libp2p/interfaces/startable" -import {DataChannelMuxerFactory} from "../muxer.js"; -import {WebRTCPeerListener} from "./listener.js"; -import type {PeerStore} from '@libp2p/interface-peer-store' -import {logger} from "@libp2p/logger"; +import type { Connection } from '@libp2p/interface-connection' +import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' +import type { ConnectionHandler, TransportManager, Upgrader } from '@libp2p/interface-transport' +import { multiaddr, Multiaddr } from '@multiformats/multiaddr' +import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' +import { pbStream, ProtobufStream } from 'it-pb-stream' +import pDefer, { DeferredPromise } from 'p-defer' +import type { PeerId } from '@libp2p/interface-peer-id' +import { abortableDuplex } from 'abortable-iterator' +import { TimeoutController } from 'timeout-abort-controller' +import { WebRTCMultiaddrConnection } from '../maconn.js' +import type { Startable } from '@libp2p/interfaces/startable' +import { DataChannelMuxerFactory } from '../muxer.js' +import { WebRTCPeerListener } from './listener.js' +import type { PeerStore } from '@libp2p/interface-peer-store' +import { logger } from '@libp2p/logger' import * as pb from '../../proto_ts/peer_transport/pb/hs.js' +// import type { ConnectionManager } from '@libp2p/interface-connection-manager' +// import * as p from '@libp2p/peer-id' -const log = logger('webrtc-peer') +const log = logger('libp2p:webrtc:peer') const TIMEOUT = 30 * 1000 export const TRANSPORT = '/webrtc-peer' export const PROTOCOL = '/webrtc-peer/0.0.1' export const CODE = 281 -export type WebRTCPeerTransportInit = { +export interface WebRTCPeerTransportInit { rtcConfiguration?: RTCConfiguration } -export type WebRTCPeerTransportComponents = { +export interface WebRTCPeerTransportComponents { peerId: PeerId registrar: Registrar upgrader: Upgrader transportManager: TransportManager + // connectionManager: ConnectionManager peerStore: PeerStore -}; +} export class WebRTCPeerTransport implements Transport, Startable { - private _started = false - private handler?: ConnectionHandler + private readonly _started = false + private readonly handler?: ConnectionHandler - constructor( + constructor ( private readonly components: WebRTCPeerTransportComponents, - private readonly init: WebRTCPeerTransportInit, + private readonly init: WebRTCPeerTransportInit ) {} - isStarted() { + isStarted () { return this._started } - async start() { + async start () { await this.components.registrar.handle(PROTOCOL, this._onProtocol.bind(this)) // this.components.peerStore.addEventListener('change:multiaddrs', (event) => { // const { peerId } = event.detail // }) } - async stop() { + + async stop () { await this.components.registrar.unhandle(PROTOCOL) } - createListener(options: CreateListenerOptions): Listener { + createListener (options: CreateListenerOptions): Listener { return new WebRTCPeerListener(this.components) } - get [Symbol.toStringTag](): string { + get [Symbol.toStringTag] (): string { return '@libp2p/webrtc-peer' } - get [symbol](): true { + get [symbol] (): true { return true } - filter(multiaddrs: Multiaddr[]): Multiaddr[] { + filter (multiaddrs: Multiaddr[]): Multiaddr[] { return multiaddrs.filter((ma) => { const codes = ma.protoCodes() return codes.includes(CODE) @@ -85,53 +88,51 @@ export class WebRTCPeerTransport implements Transport, Startable { * For a circuit relay, this will be of the form * /p2p//p2p-circuit/p2p//webrtc-sdp/p2p/ */ - async dial(ma: Multiaddr, options: DialOptions): Promise { + async dial (ma: Multiaddr, options: DialOptions): Promise { // extract peer id + // const remotePeerId = ma.getPeerId() + // if (!remotePeerId) { + // throw("peerId should be present in multiaddr") + // } + // const remotePeer = p.peerIdFromString(remotePeerId) const addrs = ma.toString().split('/webrtc-peer') const relayed = multiaddr(addrs[0]) // const destination = multiaddr(addrs[addrs.length - 1]) // - log(this.init) - - if (!options.signal) { + if (options.signal == null) { options.signal = new AbortSignal() } - let connection - try { - connection = await this.components.transportManager.dial(relayed) - } catch (err) { - console.log(err) - throw err - } + + const connection = await this.components.transportManager.dial(relayed) const rawStream = await connection.newStream([PROTOCOL], options) const stream = pbStream(abortableDuplex(rawStream, options.signal)) const pc = new RTCPeerConnection(this.init.rtcConfiguration) - const channel = pc.createDataChannel("init") + const channel = pc.createDataChannel('init') const offer = await pc.createOffer() await pc.setLocalDescription(offer) - const connectedPromise = pDefer(); + const connectedPromise = pDefer() pc.onconnectionstatechange = (_) => { switch (pc.connectionState) { case 'connected': - return connectedPromise.resolve(0); + return connectedPromise.resolve(0) case 'closed': case 'disconnected': case 'failed': - return connectedPromise.reject(); + return connectedPromise.reject() } } options.signal.onabort = connectedPromise.reject - pc.onicecandidate = ({candidate}) => { + pc.onicecandidate = ({ candidate }) => { writeMessage(stream, { type: pb.Message_MessageType.CANDIDATE, - data: candidate ? JSON.stringify(candidate) : '', - }); + data: (candidate != null) ? JSON.stringify(candidate) : '' + }) } // write offer - writeMessage(stream, {type: pb.Message_MessageType.OFFER, data: offer.sdp!}) + writeMessage(stream, { type: pb.Message_MessageType.OFFER, data: offer.sdp! }) // read answer const answerMessage = await readMessage(stream) @@ -139,14 +140,14 @@ export class WebRTCPeerTransport implements Transport, Startable { throw new Error('should read answer') } - const answerSdp = new RTCSessionDescription({type: 'answer', sdp: answerMessage.data}) + const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data }) await pc.setRemoteDescription(answerSdp) let continueReading = true while (continueReading) { const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) if (result === 0) { - break; + break } const message = result as pb.Message @@ -169,21 +170,22 @@ export class WebRTCPeerTransport implements Transport, Startable { const result = options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ peerConnection: pc, - timeline: {open: (new Date()).getTime()}, - remoteAddr: connection.remoteAddr, + timeline: { open: (new Date()).getTime() }, + remoteAddr: connection.remoteAddr }), { skipProtection: true, skipEncryption: true, - muxerFactory: new DataChannelMuxerFactory(pc, '/webrtc-peer'), + muxerFactory: new DataChannelMuxerFactory(pc, '/webrtc-peer') } ) + void connection.close() // TODO: hack await new Promise(res => setTimeout(res, 100)) - return result + return await result } - async _onProtocol({connection, stream: rawStream}: IncomingStreamData) { + async _onProtocol ({ connection, stream: rawStream }: IncomingStreamData) { const timeoutController = new TimeoutController(TIMEOUT) const signal = timeoutController.signal const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)) @@ -192,10 +194,10 @@ export class WebRTCPeerTransport implements Transport, Startable { const connectedPromise: DeferredPromise = pDefer() signal.onabort = () => connectedPromise.reject() // candidate callbacks - pc.onicecandidate = ({candidate}) => { + pc.onicecandidate = ({ candidate }) => { writeMessage(stream, { type: pb.Message_MessageType.CANDIDATE, - data: candidate ? JSON.stringify(candidate!.toJSON()) : '', + data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' }) } pc.onconnectionstatechange = (_) => { @@ -217,20 +219,20 @@ export class WebRTCPeerTransport implements Transport, Startable { } const offer = new RTCSessionDescription({ type: 'offer', - sdp: pbOffer.data, + sdp: pbOffer.data }) await pc.setRemoteDescription(offer) log.trace('offer', offer) const answer = await pc.createAnswer() await pc.setLocalDescription(answer) - writeMessage(stream, {type: pb.Message_MessageType.ANSWER, data: answer.sdp!}) + writeMessage(stream, { type: pb.Message_MessageType.ANSWER, data: answer.sdp! }) log.trace('answer', offer) let continueReading = true while (continueReading) { const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) if (result === 0) { - break; + break } const message = result as pb.Message @@ -245,29 +247,29 @@ export class WebRTCPeerTransport implements Transport, Startable { const candidate = new RTCIceCandidate(JSON.parse(message.data)) await pc.addIceCandidate(candidate) } - await connectedPromise.promise; + await connectedPromise.promise rawStream.close() const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-peer') const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, - timeline: {open: (new Date()).getTime()}, - remoteAddr: connection.remoteAddr, + timeline: { open: (new Date()).getTime() }, + remoteAddr: connection.remoteAddr }), { skipEncryption: true, skipProtection: true, muxerFactory }) - if (this.handler) { + if (this.handler != null) { this.handler(conn) } } } -function writeMessage(stream: ProtobufStream, message: pb.Message) { +function writeMessage (stream: ProtobufStream, message: pb.Message) { stream.writeLP(pb.Message.toBinary(message)) } -async function readMessage(stream: ProtobufStream): Promise { +async function readMessage (stream: ProtobufStream): Promise { const raw = await stream.readLP() return pb.Message.fromBinary(raw.subarray()) } diff --git a/src/sdp.ts b/src/sdp.ts index 10b1591..fff45df 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -12,10 +12,11 @@ const log = logger('libp2p:webrtc:sdp') * Get base2 | identity decoders */ export const mbdecoder: any = (function () { - const decoders = Object.values(bases).map((b) => b.decoder) - let acc = decoders[0].or(decoders[1]) - decoders.slice(2).forEach((d) => (acc = acc.or(d))) - return acc + // const decoders = Object.values(bases).map((b) => b.decoder) + // let acc = decoders[0].or(decoders[1]) + // decoders.slice(2).forEach((d) => (acc = acc.or(d))) + // return acc + return bases.base64url.decoder })() /** diff --git a/src/stream.ts b/src/stream.ts index a05918c..20535df 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -7,6 +7,7 @@ import { pushable } from 'it-pushable' import defer, { DeferredPromise } from 'p-defer' import type { Source, Sink } from 'it-stream-types' import { Uint8ArrayList } from 'uint8arraylist' +// import { toString as uint8arrayToString } from 'uint8arrays/to-string' import * as pb from '../proto_ts/message.js' @@ -196,6 +197,11 @@ export class WebRTCStream implements Stream { */ closeWritePromise: DeferredPromise = defer(); + /** + * Boolean value specifying if channel was closed locally + */ + localClosed: boolean = false + /** * Callback to invoke when the stream is closed. */ @@ -234,7 +240,9 @@ export class WebRTCStream implements Stream { } this.channel.onclose = (_evt) => { - this.close() + if (!this.localClosed) { + this.close() + } } this.channel.onerror = (evt) => { @@ -245,11 +253,13 @@ export class WebRTCStream implements Stream { const self = this // reader pipe - this.channel.onmessage = async ({ data }) => { - if (data === null || data.length === 0) { + this.channel.onmessage = async ({ data: d }) => { + const data = d as ArrayBuffer + if (data.byteLength === 0) { return } - this._innersrc.push(new Uint8Array(data as ArrayBufferLike)) + // console.log('incoming', this.channel.id, (data as ArrayBuffer).byteLength) + this._innersrc.push(new Uint8Array(data)) } // pipe framed protobuf messages through a length prefixed decoder, and @@ -261,6 +271,7 @@ export class WebRTCStream implements Stream { for await (const buf of source) { const message = self.processIncomingProtobuf(buf.subarray()) if (message != null) { + // console.log('read', uint8arrayToString(message)) yield new Uint8ArrayList(message) } } @@ -303,6 +314,8 @@ export class WebRTCStream implements Stream { const msgbuf = pb.Message.toBinary({ message: buf.subarray() }) const sendbuf = lengthPrefixed.encode.single(msgbuf) + // console.log('wrote ', uint8arrayToString(msgbuf)) + this.channel.send(sendbuf.subarray()) } } @@ -313,7 +326,7 @@ export class WebRTCStream implements Stream { processIncomingProtobuf (buffer: Uint8Array): Uint8Array | undefined { const message = pb.Message.fromBinary(buffer) - if (message.flag !== undefined) { + if (message.flag) { const [currentState, nextState] = this.streamState.transition({ direction: 'inbound', flag: message.flag }) if (currentState !== nextState) { @@ -340,11 +353,18 @@ export class WebRTCStream implements Stream { /** * Close a stream for reading and writing */ - close (): void { + async close (): Promise { + if (this.channel.readyState === 'closed') { + return + } + this.localClosed = true this.stat.timeline.close = new Date().getTime() this.streamState.state = StreamStates.CLOSED - this._innersrc.end() this.closeWritePromise.resolve() + // await close callback + this.channel.addEventListener('close', () => { + this._innersrc.end() + }) this.channel.close() if (this.closeCb !== undefined) { diff --git a/src/transport.ts b/src/transport.ts index 58c628e..63782d5 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -1,23 +1,24 @@ -import {noise as Noise} from '@chainsafe/libp2p-noise' -import type {Connection} from '@libp2p/interface-connection' -import type {PeerId} from '@libp2p/interface-peer-id' -import {CreateListenerOptions, Listener, ListenerEvents, symbol, Transport} from '@libp2p/interface-transport' -import {logger} from '@libp2p/logger' -// import * as p from '@libp2p/peer-id' -import type {Multiaddr} from '@multiformats/multiaddr' +import { noise as Noise } from '@chainsafe/libp2p-noise' +import type { Connection } from '@libp2p/interface-connection' +import type { PeerId } from '@libp2p/interface-peer-id' +import { CreateListenerOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' +import { logger } from '@libp2p/logger' +import * as p from '@libp2p/peer-id' +import { multiaddr, Multiaddr } from '@multiformats/multiaddr' import * as multihashes from 'multihashes' import defer from 'p-defer' -import {v4 as genUuid} from 'uuid' -import {fromString as uint8arrayFromString} from 'uint8arrays/from-string' -import {concat} from 'uint8arrays/concat' - -import {dataChannelError, inappropriateMultiaddr, invalidArgument} from './error.js' -import {WebRTCMultiaddrConnection} from './maconn.js' -import {DataChannelMuxerFactory} from './muxer.js' -import type {WebRTCDialOptions} from './options.js' +import { v4 as genUuid } from 'uuid' +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { concat } from 'uint8arrays/concat' + +import { dataChannelError, invalidArgument } from './error.js' +import { WebRTCMultiaddrConnection } from './maconn.js' +import { DataChannelMuxerFactory } from './muxer.js' +import type { WebRTCDialOptions } from './options.js' import * as sdp from './sdp.js' -import {WebRTCStream} from './stream.js' -import { EventEmitter } from '@libp2p/interfaces/events' +import { WebRTCStream } from './stream.js' +import * as mafmt from '@multiformats/mafmt' +// import { EventEmitter } from '@libp2p/interfaces/events' const log = logger('libp2p:webrtc:transport') @@ -54,14 +55,14 @@ export class WebRTCTransport implements Transport { */ private readonly components: WebRTCTransportComponents - constructor(components: WebRTCTransportComponents) { + constructor (components: WebRTCTransportComponents) { this.components = components } /** * Dial a given multiaddr */ - async dial(ma: Multiaddr, options: WebRTCDialOptions): Promise { + async dial (ma: Multiaddr, options: WebRTCDialOptions): Promise { const rawConn = await this._connect(ma, options) log(`dialing address - ${ma.toString()}`) return rawConn @@ -70,46 +71,43 @@ export class WebRTCTransport implements Transport { /** * Create transport listeners no supported by browsers */ - createListener(options: CreateListenerOptions): Listener { - return Object.assign(new EventEmitter(), { - listen: async (_: Multiaddr) => {}, - getAddrs: () => [], - close: async () => {}, - }) + createListener (options: CreateListenerOptions): Listener { + throw 'browser does not support listening' + // return Object.assign(new EventEmitter(), { + // listen: async (_: Multiaddr) => {}, + // getAddrs: () => [], + // close: async () => {}, + // }) } /** * Takes a list of `Multiaddr`s and returns only valid addresses for the transport */ - filter(multiaddrs: Multiaddr[]): Multiaddr[] { + filter (multiaddrs: Multiaddr[]): Multiaddr[] { return multiaddrs.filter(validMa) } /** * Implement toString() for WebRTCTransport */ - get [Symbol.toStringTag](): string { + get [Symbol.toStringTag] (): string { return '@libp2p/webrtc' } /** * Symbol.for('@libp2p/transport') */ - get [symbol](): true { + get [symbol] (): true { return true } /** * Connect to a peer using a multiaddr */ - async _connect(ma: Multiaddr, options: WebRTCDialOptions): Promise { - const rps = ma.getPeerId() - - if (rps === null) { - throw inappropriateMultiaddr("we need to have the remote's PeerId") - } - - const remoteCerthash = sdp.decodeCerthash(sdp.certhash(ma)) + async _connect (ma: Multiaddr, options: WebRTCDialOptions): Promise { + const addr = extractDialableMa(ma) + const remotePeerId = addr.getPeerId() + const remoteCerthash = sdp.decodeCerthash(sdp.certhash(addr)) // ECDSA is preferred over RSA here. From our testing we find that P-256 elliptic // curve is supported by Pion, webrtc-rs, as well as Chromium (P-228 and P-384 @@ -120,13 +118,13 @@ export class WebRTCTransport implements Transport { namedCurve: 'P-256', hash: sdp.toSupportedHashFunction(remoteCerthash.name) } as any) - const peerConnection = new RTCPeerConnection({certificates: [certificate]}) + const peerConnection = new RTCPeerConnection({ certificates: [certificate] }) // create data channel for running the noise handshake. Once the data channel is opened, // the remote will initiate the noise handshake. This is used to confirm the identity of // the peer. const dataChannelOpenPromise = defer() - const handshakeDataChannel = peerConnection.createDataChannel('handshake', {negotiated: true, id: 0}) + const handshakeDataChannel = peerConnection.createDataChannel('handshake', { negotiated: true, id: 0 }) const handhsakeTimeout = setTimeout(() => { const error = `Data channel was never opened: state: ${handshakeDataChannel.readyState}` log.error(error) @@ -165,7 +163,7 @@ export class WebRTCTransport implements Transport { await dataChannelOpenPromise.promise const myPeerId = this.components.peerId - // const theirPeerId = p.peerIdFromString(rps) + const theirPeerId = remotePeerId != null ? p.peerIdFromString(remotePeerId) : undefined // Do noise handshake. // Set the Noise Prologue to libp2p-webrtc-noise: before starting the actual Noise handshake. @@ -174,13 +172,13 @@ export class WebRTCTransport implements Transport { // Since we use the default crypto interface and do not use a static key or early data, // we pass in undefined for these parameters. - const noiseInit = {staticNoiseKey: undefined, extensions: undefined, crypto: undefined, prologueBytes: fingerprintsPrologue} + const noiseInit = { staticNoiseKey: undefined, extensions: undefined, crypto: undefined, prologueBytes: fingerprintsPrologue } const noise = Noise(noiseInit)() - const wrappedChannel = new WebRTCStream({channel: handshakeDataChannel, stat: {direction: 'outbound', timeline: {open: 1}}}) + const wrappedChannel = new WebRTCStream({ channel: handshakeDataChannel, stat: { direction: 'outbound', timeline: { open: 1 } } }) const wrappedDuplex = { ...wrappedChannel, source: { - [Symbol.asyncIterator]: async function* () { + [Symbol.asyncIterator]: async function * () { for await (const list of wrappedChannel.source) { yield list.subarray() } @@ -192,7 +190,7 @@ export class WebRTCTransport implements Transport { // handshake ensures that the stream opening callback is set up const maConn = new WebRTCMultiaddrConnection({ peerConnection, - remoteAddr: ma, + remoteAddr: addr, timeline: { open: (new Date()).getTime() } @@ -202,17 +200,17 @@ export class WebRTCTransport implements Transport { // For outbound connections, the remote is expected to start the noise handshake. // Therefore, we need to secure an inbound noise connection from the remote. - await noise.secureInbound(myPeerId, wrappedDuplex) + await noise.secureInbound(myPeerId, wrappedDuplex, theirPeerId) + // maConn.remoteAddr = maConn.remoteAddr.decapsulateCode(421).encapsulate(multiaddr(`/p2p/${secureConn.remotePeer}`)) - await new Promise(res => setTimeout(res, 100)) - return options.upgrader.upgradeOutbound(maConn, {skipProtection: true, skipEncryption: true, muxerFactory}) + return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory }) } /** * Generate a noise prologue from the peer connection's certificate. * noise prologue = bytes('libp2p-webrtc-noise:') + noise-responder fingerprint + noise-initiator fingerprint */ - private generateNoisePrologue(pc: RTCPeerConnection, hashName: multihashes.HashName, ma: Multiaddr): Uint8Array { + private generateNoisePrologue (pc: RTCPeerConnection, hashName: multihashes.HashName, ma: Multiaddr): Uint8Array { if (pc.getConfiguration().certificates?.length === 0) { throw invalidArgument('no local certificate') } @@ -243,7 +241,21 @@ export class WebRTCTransport implements Transport { * Determine if a given multiaddr contains a WebRTC Code (280), * a Certhash Code (466) and a PeerId */ -function validMa(ma: Multiaddr): boolean { - const codes = ma.protoCodes() - return codes.includes(WEBRTC_CODE) && codes.includes(CERTHASH_CODE) && ma.getPeerId() != null +function validMa (ma: Multiaddr): boolean { + return mafmt.WebRTC.matches(ma) +} + +/** + * + */ +function extractDialableMa (ma: Multiaddr): Multiaddr { + const addrString = ma.toString() + const certhash = addrString.match(/\/certhash\/\w+/) + const addr = addrString.split(/\/certhash\/\w+/) + let result = multiaddr(addr[0] + certhash![0]) + if (addr.length > 1 && addr[1].startsWith('/p2p')) { + const peer = addr[1].match(/\/p2p\/\w+/)![0] + result = result.encapsulate(peer) + } + return result } diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 49c66e2..b4928f7 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -1,28 +1,28 @@ /* eslint-disable @typescript-eslint/no-unused-expressions */ -import {createLibp2p} from 'libp2p' -import {webRTC, webRTCPeer} from '../src' -import {webSockets} from '@libp2p/websockets' +import { createLibp2p } from 'libp2p' +import { webRTC, webRTCPeer } from '../src' +import { webSockets } from '@libp2p/websockets' import * as filters from '@libp2p/websockets/filters' -import {mplex} from '@libp2p/mplex' -import {noise} from '@chainsafe/libp2p-noise' -import {multiaddr} from '@multiformats/multiaddr' +import { mplex } from '@libp2p/mplex' +import { noise } from '@chainsafe/libp2p-noise' +import { multiaddr } from '@multiformats/multiaddr' import pDefer from 'p-defer' -import {pipe} from 'it-pipe' -import {fromString} from 'uint8arrays/from-string' -import {toString} from 'uint8arrays/to-string' +import { pipe } from 'it-pipe' +import { fromString } from 'uint8arrays/from-string' +import { toString } from 'uint8arrays/to-string' import first from 'it-first' import { expect } from 'aegir/chai' -describe('test relay', () => { - it.skip('can connect over ws relay', async () => { - const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmPTaKo3xkWH7spf1i8JP79FXHt6BGXMrqhvBZyBTxCUaz'); +describe.skip('test relay', () => { + it('can connect over ws relay', async () => { + const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmceBZS6MN8uX4vvRdpTnu9Ga2uhHzRnVYLYPTnyWHkyHc') const listener = await createLibp2p({ transports: [ webRTCPeer({}), webSockets({ - filter: filters.all, - }), + filter: filters.all + }) ], streamMuxers: [mplex()], connectionEncryption: [noise()], @@ -30,38 +30,39 @@ describe('test relay', () => { enabled: true, autoRelay: { enabled: true, - maxListeners: 2, + maxListeners: 2 } - }, + } }) const dialer = await createLibp2p({ transports: [ webRTCPeer({}), webSockets({ - filter: filters.all, - }), + filter: filters.all + }) ], streamMuxers: [mplex()], connectionEncryption: [noise()], + identify: { + timeout: 30000 + } }) await listener.start() await dialer.start() - const relaying = pDefer() listener.peerStore.addEventListener('change:multiaddrs', (event) => { - const {peerId} = event.detail + const { peerId } = event.detail // Updated self multiaddrs? if (peerId.equals(listener.peerId)) { const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` - console.log(`Advertising with a relay address of ${listener.getMultiaddrs()[0].toString()}`) relaying.resolve(webrtcAddr) } }) - listener.handle('/echo/1.0.0', ({stream}) => { + listener.handle('/echo/1.0.0', ({ stream }) => { void pipe(stream, stream) }) @@ -72,18 +73,18 @@ describe('test relay', () => { const output = await pipe( [input], stream, - async (source) => await first(source), - ); + async (source) => await first(source) + ) expect(toString(output!.subarray())).to.equals('test') console.log('read data', output!.subarray()) }) - it('can connect over webrtc relay', async () => { - const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiAPJJtPGt5IW6ADFgtF3emYXZemfmYklaygdxRTUZN6Vw/p2p/QmQSDKcFSmNqWX6auHxMmsADHZcD89xYtaxMYgUGjP5Ej7'); + it.only('can connect over webrtc relay', async () => { + const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiBMYhADacrAg34fe9Vfj9cy6ZaNx5EqhLnWtol9zFvO5A/p2p/QmZxycy737ycr2vGWwT9HreJGAtNu3EGLAfwuGrMfBxVF4') const listener = await createLibp2p({ transports: [ webRTCPeer({}), - webRTC(), + webRTC() ], streamMuxers: [mplex()], connectionEncryption: [noise()], @@ -91,57 +92,51 @@ describe('test relay', () => { enabled: true, autoRelay: { enabled: true, - maxListeners: 2, + maxListeners: 2 } - }, + } }) const dialer = await createLibp2p({ transports: [ webRTCPeer({}), - webRTC(), + webRTC() ], streamMuxers: [mplex()], connectionEncryption: [noise()], + relay: { + enabled: true + } }) await listener.start() await dialer.start() - const relaying = pDefer() listener.peerStore.addEventListener('change:multiaddrs', (event) => { - const {peerId} = event.detail + const { peerId } = event.detail - // Updated self multiaddrs? if (peerId.equals(listener.peerId)) { const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` - console.log(`Advertising with a relay address of ${listener.getMultiaddrs()[0].toString()}`) relaying.resolve(webrtcAddr) } }) - listener.handle('/echo/1.0.0', ({stream}) => { + listener.handle('/echo/1.0.0', ({ stream }) => { void pipe(stream, stream) }) - console.log('listener connecting') await listener.dial(relayAddress) - console.log('listener connected') const addr = await relaying.promise - console.log('addr', addr) const dialAddr = multiaddr(addr) - console.log('dialer connecting') const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) - console.log('dialer connected') const input = fromString('test') const output = await pipe( [input], stream, - async (source) => await first(source), - ); + async (source) => await first(source) + ) expect(toString(output!.subarray())).to.equals('test') console.log('read data', output!.subarray()) - }) }) From 3abb6618217dad8f662cc82037c39e5d013e2518 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Mon, 6 Feb 2023 10:06:41 +0530 Subject: [PATCH 04/52] fixes --- src/peer_transport/transport.ts | 2 +- src/stream.ts | 1 - src/transport.ts | 30 +++++++----------------------- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 7e92ec2..96bf529 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -67,7 +67,7 @@ export class WebRTCPeerTransport implements Transport, Startable { } get [Symbol.toStringTag] (): string { - return '@libp2p/webrtc-peer' + return '@libp2p/webrtc-direct' } get [symbol] (): true { diff --git a/src/stream.ts b/src/stream.ts index 9090510..71a20d9 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -251,7 +251,6 @@ export class WebRTCStream implements Stream { } this.channel.onerror = (evt) => { - // @ts-expect-error const err = (evt as RTCErrorEvent).error this.abort(err) } diff --git a/src/transport.ts b/src/transport.ts index 01f79ec..c8736de 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -4,7 +4,7 @@ import type { PeerId } from '@libp2p/interface-peer-id' import { CreateListenerOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' import { logger } from '@libp2p/logger' import * as p from '@libp2p/peer-id' -import { multiaddr, Multiaddr } from '@multiformats/multiaddr' +import type { Multiaddr } from '@multiformats/multiaddr' import * as multihashes from 'multihashes' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { concat } from 'uint8arrays/concat' @@ -68,12 +68,7 @@ export class WebRTCTransport implements Transport { * Create transport listeners no supported by browsers */ createListener (options: CreateListenerOptions): Listener { - throw 'browser does not support listening' - // return Object.assign(new EventEmitter(), { - // listen: async (_: Multiaddr) => {}, - // getAddrs: () => [], - // close: async () => {}, - // }) + throw unimplemented('WebRTCTransport.createListener') } /** @@ -202,7 +197,6 @@ export class WebRTCTransport implements Transport { // For outbound connections, the remote is expected to start the noise handshake. // Therefore, we need to secure an inbound noise connection from the remote. await noise.secureInbound(myPeerId, wrappedDuplex, theirPeerId) - // maConn.remoteAddr = maConn.remoteAddr.decapsulateCode(421).encapsulate(multiaddr(`/p2p/${secureConn.remotePeer}`)) return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory }) } @@ -238,21 +232,11 @@ export class WebRTCTransport implements Transport { } } -function validMa (ma: Multiaddr): boolean { - return mafmt.WebRTC.matches(ma) -} - /** - * + * Determine if a given multiaddr contains a WebRTC Code (280), + * a Certhash Code (466) and a PeerId */ -function extractDialableMa (ma: Multiaddr): Multiaddr { - const addrString = ma.toString() - const certhash = addrString.match(/\/certhash\/\w+/) - const addr = addrString.split(/\/certhash\/\w+/) - let result = multiaddr(addr[0] + certhash![0]) - if (addr.length > 1 && addr[1].startsWith('/p2p')) { - const peer = addr[1].match(/\/p2p\/\w+/)![0] - result = result.encapsulate(peer) - } - return result +function validMa (ma: Multiaddr): boolean { + const codes = ma.protoCodes() + return codes.includes(WEBRTC_CODE) && codes.includes(CERTHASH_CODE) && ma.getPeerId() != null } From e50dd76b4791ead8b5bb497bd7458d999a322995 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 8 Feb 2023 15:01:25 +0530 Subject: [PATCH 05/52] browser to browser --- package.json | 8 +- proto_ts/peer_transport/pb/hs.ts | 97 ----------- src/index.ts | 8 +- src/peer_transport/pb/hs.proto | 14 -- src/peer_transport/pb/index.proto | 16 ++ src/peer_transport/pb/index.ts | 92 +++++++++++ src/peer_transport/transport.ts | 177 ++++++++------------ src/peer_transport/util.ts | 29 ++++ test/peer.browser.spec.ts | 264 +++++++++++++++--------------- 9 files changed, 350 insertions(+), 355 deletions(-) delete mode 100644 proto_ts/peer_transport/pb/hs.ts delete mode 100644 src/peer_transport/pb/hs.proto create mode 100644 src/peer_transport/pb/index.proto create mode 100644 src/peer_transport/pb/index.ts create mode 100644 src/peer_transport/util.ts diff --git a/package.json b/package.json index 82c8974..d841985 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ }, "scripts": { "generate:proto": "npx protoc --ts_out proto_ts --proto_path src src/*.proto", - "generate:webrtc-peer": "npx protoc --ts_out proto_ts --proto_path src src/peer_transport/pb/hs.proto", + "generate:webrtc-direct": "protons src/peer_transport/pb/index.proto", "build": "aegir build", "test": "aegir test -t browser", "test:chrome": "aegir test -t browser -f \"./dist/test/**/*.spec.js\" --cov", @@ -144,8 +144,8 @@ "@libp2p/interface-transport": "^2.0.0", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^2.0.0", + "@multiformats/mafmt": "^11.0.3", "@multiformats/multiaddr": "^11.0.3", - "@multiformats/mafmt": "../libp2p/js-mafmt", "@protobuf-ts/runtime": "^2.8.0", "err-code": "^3.0.1", "it-handshake": "^4.1.2", @@ -172,7 +172,7 @@ "@protobuf-ts/protoc": "^2.8.0", "aegir": "^37.6.6", "it-first": "^2.0.0", - "protons": "^6.0.1", - "libp2p": "^0.41.0" + "libp2p": "^0.41.0", + "protons": "^6.0.1" } } diff --git a/proto_ts/peer_transport/pb/hs.ts b/proto_ts/peer_transport/pb/hs.ts deleted file mode 100644 index 7859658..0000000 --- a/proto_ts/peer_transport/pb/hs.ts +++ /dev/null @@ -1,97 +0,0 @@ -// @generated by protobuf-ts 2.8.2 -// @generated from protobuf file "peer_transport/pb/hs.proto" (package "webrtc_peer.pb", syntax proto2) -// tslint:disable -import type { BinaryWriteOptions } from "@protobuf-ts/runtime"; -import type { IBinaryWriter } from "@protobuf-ts/runtime"; -import { WireType } from "@protobuf-ts/runtime"; -import type { BinaryReadOptions } from "@protobuf-ts/runtime"; -import type { IBinaryReader } from "@protobuf-ts/runtime"; -import { UnknownFieldHandler } from "@protobuf-ts/runtime"; -import type { PartialMessage } from "@protobuf-ts/runtime"; -import { reflectionMergePartial } from "@protobuf-ts/runtime"; -import { MESSAGE_TYPE } from "@protobuf-ts/runtime"; -import { MessageType } from "@protobuf-ts/runtime"; -/** - * @generated from protobuf message webrtc_peer.pb.Message - */ -export interface Message { - /** - * @generated from protobuf field: webrtc_peer.pb.Message.MessageType type = 1; - */ - type: Message_MessageType; - /** - * @generated from protobuf field: string data = 2; - */ - data: string; -} -/** - * @generated from protobuf enum webrtc_peer.pb.Message.MessageType - */ -export enum Message_MessageType { - /** - * @generated from protobuf enum value: OFFER = 0; - */ - OFFER = 0, - /** - * @generated from protobuf enum value: ANSWER = 1; - */ - ANSWER = 1, - /** - * @generated from protobuf enum value: CANDIDATE = 2; - */ - CANDIDATE = 2 -} -// @generated message type with reflection information, may provide speed optimized methods -class Message$Type extends MessageType { - constructor() { - super("webrtc_peer.pb.Message", [ - { no: 1, name: "type", kind: "enum", T: () => ["webrtc_peer.pb.Message.MessageType", Message_MessageType] }, - { no: 2, name: "data", kind: "scalar", T: 9 /*ScalarType.STRING*/ } - ]); - } - create(value?: PartialMessage): Message { - const message = { type: 0, data: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Message): Message { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* webrtc_peer.pb.Message.MessageType type */ 1: - message.type = reader.int32(); - break; - case /* string data */ 2: - message.data = reader.string(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: Message, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* webrtc_peer.pb.Message.MessageType type = 1; */ - if (message.type !== 0) - writer.tag(1, WireType.Varint).int32(message.type); - /* string data = 2; */ - if (message.data !== "") - writer.tag(2, WireType.LengthDelimited).string(message.data); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message webrtc_peer.pb.Message - */ -export const Message = new Message$Type(); diff --git a/src/index.ts b/src/index.ts index fb5a117..4c3c8b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ import type { Transport } from '@libp2p/interface-transport' -import type { WebRTCPeerTransportComponents, WebRTCPeerTransportInit } from './peer_transport/transport.js' -import { WebRTCPeerTransport } from './peer_transport/transport.js' +import type { WebRTCDirectTransportComponents, WebRTCPeerTransportInit } from './peer_transport/transport.js' +import { WebRTCDirectTransport } from './peer_transport/transport.js' import { WebRTCTransport, WebRTCTransportComponents } from './transport.js' export function webRTC (): (components: WebRTCTransportComponents) => Transport { return (components: WebRTCTransportComponents) => new WebRTCTransport(components) } -export function webRTCPeer (init: WebRTCPeerTransportInit): (components: WebRTCPeerTransportComponents) => Transport { - return (components: WebRTCPeerTransportComponents) => new WebRTCPeerTransport(components, init) +export function webRTCDirect (init: WebRTCPeerTransportInit): (components: WebRTCDirectTransportComponents) => Transport { + return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components, init) } diff --git a/src/peer_transport/pb/hs.proto b/src/peer_transport/pb/hs.proto deleted file mode 100644 index cc11597..0000000 --- a/src/peer_transport/pb/hs.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto2"; - -package webrtc_peer.pb; - -message Message { - enum MessageType { - OFFER = 0; - ANSWER = 1; - CANDIDATE = 2; - } - - required MessageType type = 1; - required string data = 2; -} diff --git a/src/peer_transport/pb/index.proto b/src/peer_transport/pb/index.proto new file mode 100644 index 0000000..ac2fa68 --- /dev/null +++ b/src/peer_transport/pb/index.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +message Message { + // Specifies type in `data` field. + enum Type { + // String of `RTCSessionDescription.sdp` + SDP_OFFER = 0; + // String of `RTCSessionDescription.sdp` + SDP_ANSWER = 1; + // String of `RTCIceCandidate.toJSON()` + ICE_CANDIDATE = 2; + } + + optional Type type = 1; + optional string data = 2; +} \ No newline at end of file diff --git a/src/peer_transport/pb/index.ts b/src/peer_transport/pb/index.ts new file mode 100644 index 0000000..627fd35 --- /dev/null +++ b/src/peer_transport/pb/index.ts @@ -0,0 +1,92 @@ +/* eslint-disable import/export */ +/* eslint-disable complexity */ +/* eslint-disable @typescript-eslint/no-namespace */ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ +/* eslint-disable @typescript-eslint/no-empty-interface */ + +import { enumeration, encodeMessage, decodeMessage, message } from 'protons-runtime' +import type { Uint8ArrayList } from 'uint8arraylist' +import type { Codec } from 'protons-runtime' + +export interface Message { + type?: Message.Type + data?: string +} + +export namespace Message { + export enum Type { + SDP_OFFER = 'SDP_OFFER', + SDP_ANSWER = 'SDP_ANSWER', + ICE_CANDIDATE = 'ICE_CANDIDATE' + } + + enum __TypeValues { + SDP_OFFER = 0, + SDP_ANSWER = 1, + ICE_CANDIDATE = 2 + } + + export namespace Type { + export const codec = (): Codec => { + return enumeration(__TypeValues) + } + } + + let _codec: Codec + + export const codec = (): Codec => { + if (_codec == null) { + _codec = message((obj, w, opts = {}) => { + if (opts.lengthDelimited !== false) { + w.fork() + } + + if (obj.type != null) { + w.uint32(8) + Message.Type.codec().encode(obj.type, w) + } + + if (obj.data != null) { + w.uint32(18) + w.string(obj.data) + } + + if (opts.lengthDelimited !== false) { + w.ldelim() + } + }, (reader, length) => { + const obj: any = {} + + const end = length == null ? reader.len : reader.pos + length + + while (reader.pos < end) { + const tag = reader.uint32() + + switch (tag >>> 3) { + case 1: + obj.type = Message.Type.codec().decode(reader) + break + case 2: + obj.data = reader.string() + break + default: + reader.skipType(tag & 7) + break + } + } + + return obj + }) + } + + return _codec + } + + export const encode = (obj: Message): Uint8Array => { + return encodeMessage(obj, Message.codec()) + } + + export const decode = (buf: Uint8Array | Uint8ArrayList): Message => { + return decodeMessage(buf, Message.codec()) + } +} diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 96bf529..dfab1ab 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -3,7 +3,7 @@ import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from import type { ConnectionHandler, TransportManager, Upgrader } from '@libp2p/interface-transport' import { multiaddr, Multiaddr } from '@multiformats/multiaddr' import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' -import { pbStream, ProtobufStream } from 'it-pb-stream' +import { pbStream } from 'it-pb-stream' import pDefer, { DeferredPromise } from 'p-defer' import type { PeerId } from '@libp2p/interface-peer-id' import { abortableDuplex } from 'abortable-iterator' @@ -14,36 +14,34 @@ import { DataChannelMuxerFactory } from '../muxer.js' import { WebRTCPeerListener } from './listener.js' import type { PeerStore } from '@libp2p/interface-peer-store' import { logger } from '@libp2p/logger' -import * as pb from '../../proto_ts/peer_transport/pb/hs.js' -// import type { ConnectionManager } from '@libp2p/interface-connection-manager' -// import * as p from '@libp2p/peer-id' +import * as pb from './pb/index.js' +import { readCandidatesUntilConnected } from './util.js' const log = logger('libp2p:webrtc:peer') const TIMEOUT = 30 * 1000 -export const TRANSPORT = '/webrtc-peer' -export const PROTOCOL = '/webrtc-peer/0.0.1' -export const CODE = 281 +export const TRANSPORT = '/webrtc-direct' +export const PROTOCOL = '/webrtc-direct/0.0.1' +export const CODE = 276 export interface WebRTCPeerTransportInit { rtcConfiguration?: RTCConfiguration } -export interface WebRTCPeerTransportComponents { +export interface WebRTCDirectTransportComponents { peerId: PeerId registrar: Registrar upgrader: Upgrader transportManager: TransportManager - // connectionManager: ConnectionManager peerStore: PeerStore } -export class WebRTCPeerTransport implements Transport, Startable { +export class WebRTCDirectTransport implements Transport, Startable { private readonly _started = false private readonly handler?: ConnectionHandler constructor ( - private readonly components: WebRTCPeerTransportComponents, + private readonly components: WebRTCDirectTransportComponents, private readonly init: WebRTCPeerTransportInit ) {} @@ -86,87 +84,75 @@ export class WebRTCPeerTransport implements Transport, Startable { * and proceeds to upgrade to a webrtc connection. * multiaddr of the form: /webrtc-peer/p2p/ * For a circuit relay, this will be of the form - * /p2p//p2p-circuit/p2p//webrtc-sdp/p2p/ + * /p2p//p2p-circuit/webrtc-direct/p2p/ */ async dial (ma: Multiaddr, options: DialOptions): Promise { // extract peer id - // const remotePeerId = ma.getPeerId() // if (!remotePeerId) { // throw("peerId should be present in multiaddr") // } - // const remotePeer = p.peerIdFromString(remotePeerId) - const addrs = ma.toString().split('/webrtc-peer') - const relayed = multiaddr(addrs[0]) - // const destination = multiaddr(addrs[addrs.length - 1]) - // + + const addrs = ma.toString().split(TRANSPORT) + // look for remote peerId + let relayed = multiaddr(addrs[0]) + const remotePeerId = ma.getPeerId() + if (remotePeerId != null) { + relayed = relayed.encapsulate(multiaddr(`/p2p/${remotePeerId}`)) + } if (options.signal == null) { options.signal = new AbortSignal() } const connection = await this.components.transportManager.dial(relayed) - const rawStream = await connection.newStream([PROTOCOL], options) - const stream = pbStream(abortableDuplex(rawStream, options.signal)) + const stream = pbStream(abortableDuplex(rawStream, options.signal)).pb(pb.Message) + // setup peer connection const pc = new RTCPeerConnection(this.init.rtcConfiguration) + // the label is not relevant to connection initiation but can be + // useful for debugging const channel = pc.createDataChannel('init') - const offer = await pc.createOffer() - await pc.setLocalDescription(offer) - const connectedPromise = pDefer() + const connectedPromise = pDefer() pc.onconnectionstatechange = (_) => { switch (pc.connectionState) { case 'connected': - return connectedPromise.resolve(0) + return connectedPromise.resolve() case 'closed': case 'disconnected': case 'failed': return connectedPromise.reject() } } + options.signal.onabort = connectedPromise.reject + // setup callback to write ICE candidates to the remote + // peer pc.onicecandidate = ({ candidate }) => { - writeMessage(stream, { - type: pb.Message_MessageType.CANDIDATE, + stream.write({ + type: pb.Message.Type.ICE_CANDIDATE, data: (candidate != null) ? JSON.stringify(candidate) : '' }) } - // write offer - writeMessage(stream, { type: pb.Message_MessageType.OFFER, data: offer.sdp! }) - // read answer - const answerMessage = await readMessage(stream) - if (answerMessage.type != pb.Message_MessageType.ANSWER) { - throw new Error('should read answer') + // read offer + const offerMessage = await stream.read() + if (offerMessage.type !== pb.Message.Type.SDP_OFFER) { + throw new Error('remote should send an SDP offer') } - const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data }) - await pc.setRemoteDescription(answerSdp) + const offerSdp = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) + await pc.setRemoteDescription(offerSdp) - let continueReading = true - while (continueReading) { - const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) - if (result === 0) { - break - } + // create an answer + const answerSdp = await pc.createAnswer() + // write the answer to the stream + stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) + // set answer as local description + pc.setLocalDescription(answerSdp) - const message = result as pb.Message - if (message.type != pb.Message_MessageType.CANDIDATE) { - continue - } + await readCandidatesUntilConnected(connectedPromise, pc, stream) - if (message.data == '') { - continueReading = false - break - } - - const candidate = new RTCIceCandidate(JSON.parse(message.data)) - pc.addIceCandidate(candidate) - } - - await connectedPromise.promise - rawStream.close() - channel.close() const result = options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ peerConnection: pc, @@ -176,35 +162,38 @@ export class WebRTCPeerTransport implements Transport, Startable { { skipProtection: true, skipEncryption: true, - muxerFactory: new DataChannelMuxerFactory(pc, '/webrtc-peer') + muxerFactory: new DataChannelMuxerFactory(pc, TRANSPORT) } ) + // close streams + rawStream.close() + channel.close() void connection.close() // TODO: hack - await new Promise(res => setTimeout(res, 100)) + // await new Promise(res => setTimeout(res, 100)) return await result } async _onProtocol ({ connection, stream: rawStream }: IncomingStreamData) { const timeoutController = new TimeoutController(TIMEOUT) const signal = timeoutController.signal - const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)) + const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)).pb(pb.Message) const pc = new RTCPeerConnection(this.init.rtcConfiguration) - const connectedPromise: DeferredPromise = pDefer() + const connectedPromise: DeferredPromise = pDefer() signal.onabort = () => connectedPromise.reject() // candidate callbacks pc.onicecandidate = ({ candidate }) => { - writeMessage(stream, { - type: pb.Message_MessageType.CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' + stream.write({ + type: pb.Message.Type.ICE_CANDIDATE, + data: (candidate != null) ? JSON.stringify(candidate) : '' }) } pc.onconnectionstatechange = (_) => { log.trace('received pc state: ', pc.connectionState) switch (pc.connectionState) { case 'connected': - connectedPromise.resolve(0) + connectedPromise.resolve() break case 'failed': case 'disconnected': @@ -213,43 +202,25 @@ export class WebRTCPeerTransport implements Transport, Startable { } } - const pbOffer = await readMessage(stream) - if (pbOffer.type != pb.Message_MessageType.OFFER) { - throw new Error('initial message should be an offer') + // create and write an SDP offer + const offer = await pc.createOffer() + pc.setLocalDescription(offer) + stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) + + // read an SDP anwer + const pbAnswer = await stream.read() + if (pbAnswer.type != pb.Message.Type.SDP_ANSWER) { + throw new Error('response message should be an SDP answer') } - const offer = new RTCSessionDescription({ - type: 'offer', - sdp: pbOffer.data + const answer = new RTCSessionDescription({ + type: 'answer', + sdp: pbAnswer.data }) + await pc.setRemoteDescription(answer) - await pc.setRemoteDescription(offer) - log.trace('offer', offer) - const answer = await pc.createAnswer() - await pc.setLocalDescription(answer) - writeMessage(stream, { type: pb.Message_MessageType.ANSWER, data: answer.sdp! }) - log.trace('answer', offer) - let continueReading = true - while (continueReading) { - const result = await Promise.race([connectedPromise.promise, readMessage(stream)]) - if (result === 0) { - break - } - - const message = result as pb.Message - if (message.type != pb.Message_MessageType.CANDIDATE) { - throw new Error('should only receive trickle candidates') - } - if (message.data === '') { - continueReading = false - break - } - - const candidate = new RTCIceCandidate(JSON.parse(message.data)) - await pc.addIceCandidate(candidate) - } - await connectedPromise.promise - rawStream.close() - const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-peer') + // wait until candidates are connected + await readCandidatesUntilConnected(connectedPromise, pc, stream) + const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-direct') const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, timeline: { open: (new Date()).getTime() }, @@ -259,17 +230,9 @@ export class WebRTCPeerTransport implements Transport, Startable { skipProtection: true, muxerFactory }) + rawStream.close() if (this.handler != null) { this.handler(conn) } } } - -function writeMessage (stream: ProtobufStream, message: pb.Message) { - stream.writeLP(pb.Message.toBinary(message)) -} - -async function readMessage (stream: ProtobufStream): Promise { - const raw = await stream.readLP() - return pb.Message.fromBinary(raw.subarray()) -} diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts new file mode 100644 index 0000000..9555e99 --- /dev/null +++ b/src/peer_transport/util.ts @@ -0,0 +1,29 @@ +import type { DeferredPromise } from "p-defer" +import * as pb from './pb/index.js' + +type MessageStream = { + read: () => Promise, + write: (d: pb.Message) => void | Promise +}; +export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream) => { + while (true) { + const readResult = await Promise.race([connectedPromise.promise, stream.read()]) + // check if readResult is a message + if (readResult instanceof Object) { + const message = readResult as pb.Message + if (message.type !== pb.Message.Type.ICE_CANDIDATE) { + throw new Error('expected only ice candidates') + } + // end of candidates has been signalled + if (message.data == null || message.data === '') { + break + } + await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) + } else { + // connected promise resolved + break + } + } + await connectedPromise +} +export {} \ No newline at end of file diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index b4928f7..ac2713f 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -1,143 +1,149 @@ -/* eslint-disable @typescript-eslint/no-unused-expressions */ - -import { createLibp2p } from 'libp2p' -import { webRTC, webRTCPeer } from '../src' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { mplex } from '@libp2p/mplex' -import { noise } from '@chainsafe/libp2p-noise' -import { multiaddr } from '@multiformats/multiaddr' -import pDefer from 'p-defer' -import { pipe } from 'it-pipe' -import { fromString } from 'uint8arrays/from-string' -import { toString } from 'uint8arrays/to-string' -import first from 'it-first' -import { expect } from 'aegir/chai' - -describe.skip('test relay', () => { - it('can connect over ws relay', async () => { - const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmceBZS6MN8uX4vvRdpTnu9Ga2uhHzRnVYLYPTnyWHkyHc') - const listener = await createLibp2p({ - transports: [ - webRTCPeer({}), - webSockets({ - filter: filters.all - }) - ], - streamMuxers: [mplex()], - connectionEncryption: [noise()], - relay: { - enabled: true, - autoRelay: { - enabled: true, - maxListeners: 2 - } - } - }) - const dialer = await createLibp2p({ - transports: [ - webRTCPeer({}), - webSockets({ - filter: filters.all - }) - ], - streamMuxers: [mplex()], - connectionEncryption: [noise()], - identify: { - timeout: 30000 - } - }) +// import { createLibp2p } from 'libp2p' +// import { webRTC, webRTCPeer } from '../src' +// import { webSockets } from '@libp2p/websockets' +// import * as filters from '@libp2p/websockets/filters' +// import { mplex } from '@libp2p/mplex' +// import { noise } from '@chainsafe/libp2p-noise' +// import { multiaddr } from '@multiformats/multiaddr' +// import pDefer from 'p-defer' +// import { pipe } from 'it-pipe' +// import { fromString } from 'uint8arrays/from-string' +// import { toString } from 'uint8arrays/to-string' +// import first from 'it-first' +// import { expect } from 'aegir/chai' - await listener.start() - await dialer.start() +// describe.skip('test relay', () => { +// it('can connect over ws relay', async () => { +// const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmceBZS6MN8uX4vvRdpTnu9Ga2uhHzRnVYLYPTnyWHkyHc') +// const listener = await createLibp2p({ +// transports: [ +// webRTCPeer({}), +// webSockets({ +// filter: filters.all +// }) +// ], +// streamMuxers: [mplex()], +// connectionEncryption: [noise()], +// relay: { +// enabled: true, +// autoRelay: { +// enabled: true, +// maxListeners: 2 +// } +// } +// }) +// const dialer = await createLibp2p({ +// transports: [ +// webRTCPeer({}), +// webSockets({ +// filter: filters.all +// }) +// ], +// streamMuxers: [mplex()], +// connectionEncryption: [noise()], +// identify: { +// timeout: 30000 +// } +// }) - const relaying = pDefer() - listener.peerStore.addEventListener('change:multiaddrs', (event) => { - const { peerId } = event.detail +// await listener.start() +// await dialer.start() - // Updated self multiaddrs? - if (peerId.equals(listener.peerId)) { - const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` - relaying.resolve(webrtcAddr) - } - }) +// const relaying = pDefer() +// listener.peerStore.addEventListener('change:multiaddrs', (event) => { +// const { peerId } = event.detail - listener.handle('/echo/1.0.0', ({ stream }) => { - void pipe(stream, stream) - }) +// // Updated self multiaddrs? +// if (peerId.equals(listener.peerId)) { +// const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` +// relaying.resolve(webrtcAddr) +// } +// }) - await listener.dial(relayAddress) - const dialAddr = multiaddr(await relaying.promise) - const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) - const input = fromString('test') - const output = await pipe( - [input], - stream, - async (source) => await first(source) - ) - expect(toString(output!.subarray())).to.equals('test') - console.log('read data', output!.subarray()) - }) - - it.only('can connect over webrtc relay', async () => { - const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiBMYhADacrAg34fe9Vfj9cy6ZaNx5EqhLnWtol9zFvO5A/p2p/QmZxycy737ycr2vGWwT9HreJGAtNu3EGLAfwuGrMfBxVF4') - const listener = await createLibp2p({ - transports: [ - webRTCPeer({}), - webRTC() - ], - streamMuxers: [mplex()], - connectionEncryption: [noise()], - relay: { - enabled: true, - autoRelay: { - enabled: true, - maxListeners: 2 - } - } - }) - const dialer = await createLibp2p({ - transports: [ - webRTCPeer({}), - webRTC() - ], - streamMuxers: [mplex()], - connectionEncryption: [noise()], - relay: { - enabled: true - } - }) +// listener.handle('/echo/1.0.0', ({ stream }) => { +// void pipe(stream, stream) +// }) - await listener.start() - await dialer.start() +// await listener.dial(relayAddress) +// const dialAddr = multiaddr(await relaying.promise) +// const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) +// const input = fromString('test') +// const output = await pipe( +// [input], +// stream, +// async (source) => await first(source) +// ) +// expect(toString(output!.subarray())).to.equals('test') +// console.log('read data', output!.subarray()) +// }) - const relaying = pDefer() - listener.peerStore.addEventListener('change:multiaddrs', (event) => { - const { peerId } = event.detail +// it.only('can connect over webrtc relay', async () => { +// const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiBMYhADacrAg34fe9Vfj9cy6ZaNx5EqhLnWtol9zFvO5A/p2p/QmZxycy737ycr2vGWwT9HreJGAtNu3EGLAfwuGrMfBxVF4') +// const listener = await createLibp2p({ +// transports: [ +// webRTCPeer({}), +// webRTC() +// ], +// streamMuxers: [mplex()], +// connectionEncryption: [noise()], +// relay: { +// enabled: true, +// autoRelay: { +// enabled: true, +// maxListeners: 2 +// } +// } +// }) +// const dialer = await createLibp2p({ +// transports: [ +// webRTCPeer({}), +// webRTC() +// ], +// streamMuxers: [mplex()], +// connectionEncryption: [noise()], +// relay: { +// enabled: true +// } +// }) - if (peerId.equals(listener.peerId)) { - const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` - relaying.resolve(webrtcAddr) - } - }) +// await listener.start() +// await dialer.start() + +// const relaying = pDefer() +// listener.peerStore.addEventListener('change:multiaddrs', (event) => { +// const { peerId } = event.detail + +// if (peerId.equals(listener.peerId)) { +// const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` +// relaying.resolve(webrtcAddr) +// } +// }) + +// listener.handle('/echo/1.0.0', ({ stream }) => { +// void pipe(stream, stream) +// }) + +// await listener.dial(relayAddress) +// const addr = await relaying.promise +// const dialAddr = multiaddr(addr) +// const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) +// const input = fromString('test') +// const output = await pipe( +// [input], +// stream, +// async (source) => await first(source) +// ) +// expect(toString(output!.subarray())).to.equals('test') +// console.log('read data', output!.subarray()) +// }) +// }) + +describe('webrtc_direct handlers', () => { + it('handles incoming connection', () => { - listener.handle('/echo/1.0.0', ({ stream }) => { - void pipe(stream, stream) + }) - await listener.dial(relayAddress) - const addr = await relaying.promise - const dialAddr = multiaddr(addr) - const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) - const input = fromString('test') - const output = await pipe( - [input], - stream, - async (source) => await first(source) - ) - expect(toString(output!.subarray())).to.equals('test') - console.log('read data', output!.subarray()) - }) }) export {} From 84c5b3c51d3e0c80ff35d6fa9cb6ab8428a9cbdb Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 8 Feb 2023 15:59:42 +0530 Subject: [PATCH 06/52] fix tests --- package.json | 1 + src/peer_transport/handler.ts | 136 ++++++++++++++++++++++++++++++++ src/peer_transport/listener.ts | 2 +- src/peer_transport/transport.ts | 121 ++++------------------------ src/peer_transport/util.ts | 48 +++++------ test/peer.browser.spec.ts | 27 +++++-- 6 files changed, 197 insertions(+), 138 deletions(-) create mode 100644 src/peer_transport/handler.ts diff --git a/package.json b/package.json index d841985..3445d8b 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "@protobuf-ts/protoc": "^2.8.0", "aegir": "^37.6.6", "it-first": "^2.0.0", + "it-pair": "^2.0.3", "libp2p": "^0.41.0", "protons": "^6.0.1" } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts new file mode 100644 index 0000000..fd2056a --- /dev/null +++ b/src/peer_transport/handler.ts @@ -0,0 +1,136 @@ +import type { IncomingStreamData } from '@libp2p/interface-registrar' +import { pbStream } from 'it-pb-stream' +import pDefer, { type DeferredPromise } from 'p-defer' +import { TimeoutController } from 'timeout-abort-controller' +import { readCandidatesUntilConnected } from './util' +import * as pb from './pb/index.js' +import { abortableDuplex } from 'abortable-iterator' +import { logger } from '@libp2p/logger' +import type { Stream } from '@libp2p/interface-connection' + +const DEFAULT_TIMEOUT = 30 * 1000 + +const log = logger('libp2p:webrtc:peer') + +export type IncomingStreamOpts = { rtcConfiguration?: RTCConfiguration } & IncomingStreamData + +export async function handleIncomingStream ({ rtcConfiguration, stream: rawStream }: IncomingStreamOpts): Promise { + const timeoutController = new TimeoutController(DEFAULT_TIMEOUT) + const signal = timeoutController.signal + const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)).pb(pb.Message) + const pc = new RTCPeerConnection(rtcConfiguration) + + const connectedPromise: DeferredPromise = pDefer() + signal.onabort = () => connectedPromise.reject() + // candidate callbacks + pc.onicecandidate = ({ candidate }) => { + stream.write({ + type: pb.Message.Type.ICE_CANDIDATE, + data: (candidate != null) ? JSON.stringify(candidate) : '' + }) + } + + // setup callback for peerconnection state change + pc.onconnectionstatechange = (_) => { + log.trace('received pc state: ', pc.connectionState) + switch (pc.connectionState) { + case 'connected': + connectedPromise.resolve() + break + case 'failed': + case 'disconnected': + case 'closed': + connectedPromise.reject() + break + default: + break + connectedPromise.reject() + } + } + // we create the channel so that the peerconnection has a component for + // which to collect candidates + const channel = pc.createDataChannel('init') + + // create and write an SDP offer + const offer = await pc.createOffer() + pc.setLocalDescription(offer) + stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) + log('wrote offer') + + // read an SDP anwer + const pbAnswer = await stream.read() + if (pbAnswer.type !== pb.Message.Type.SDP_ANSWER) { + throw new Error('response message should be an SDP answer') + } + const answer = new RTCSessionDescription({ + type: 'answer', + sdp: pbAnswer.data + }) + await pc.setRemoteDescription(answer) + + // wait until candidates are connected + await readCandidatesUntilConnected(connectedPromise, pc, stream) + // close the dummy channel + channel.close() + return pc +} + +export interface ConnectOptions { + stream: Stream + signal: AbortSignal + rtcConfiguration?: RTCConfiguration +} + +export async function connect ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise { + const stream = pbStream(abortableDuplex(rawStream, signal)).pb(pb.Message) + + // setup peer connection + const pc = new RTCPeerConnection(rtcConfiguration) + // the label is not relevant to connection initiation but can be + // useful for debugging + + const connectedPromise = pDefer() + pc.onconnectionstatechange = (_) => { + switch (pc.connectionState) { + case 'connected': + return connectedPromise.resolve() + case 'closed': + case 'disconnected': + case 'failed': + return connectedPromise.reject() + default: + } + } + + // reject the connectedPromise if the signal aborts + signal.onabort = connectedPromise.reject + // setup callback to write ICE candidates to the remote + // peer + pc.onicecandidate = ({ candidate }) => { + stream.write({ + type: pb.Message.Type.ICE_CANDIDATE, + data: (candidate != null) ? JSON.stringify(candidate) : '' + }) + } + + // read offer + const offerMessage = await stream.read() + log('read offer') + if (offerMessage.type !== pb.Message.Type.SDP_OFFER) { + throw new Error('remote should send an SDP offer') + } + + const offerSdp = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) + await pc.setRemoteDescription(offerSdp) + + // create an answer + const answerSdp = await pc.createAnswer() + // write the answer to the stream + stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) + // set answer as local description + pc.setLocalDescription(answerSdp) + + await readCandidatesUntilConnected(connectedPromise, pc, stream) + return pc +} +export { } diff --git a/src/peer_transport/listener.ts b/src/peer_transport/listener.ts index c537dae..f2be808 100644 --- a/src/peer_transport/listener.ts +++ b/src/peer_transport/listener.ts @@ -23,7 +23,7 @@ export class WebRTCPeerListener extends EventEmitter implements const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) const listener = tpt?.createListener({ ...this.opts }) await listener?.listen(baseAddr) - const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId}`) + const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId.toString()}`) this.listeningAddrs.push(listeningAddr) listener?.addEventListener('close', () => { this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index dfab1ab..43eed92 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -3,23 +3,17 @@ import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from import type { ConnectionHandler, TransportManager, Upgrader } from '@libp2p/interface-transport' import { multiaddr, Multiaddr } from '@multiformats/multiaddr' import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' -import { pbStream } from 'it-pb-stream' -import pDefer, { DeferredPromise } from 'p-defer' import type { PeerId } from '@libp2p/interface-peer-id' -import { abortableDuplex } from 'abortable-iterator' -import { TimeoutController } from 'timeout-abort-controller' import { WebRTCMultiaddrConnection } from '../maconn.js' import type { Startable } from '@libp2p/interfaces/startable' import { DataChannelMuxerFactory } from '../muxer.js' import { WebRTCPeerListener } from './listener.js' import type { PeerStore } from '@libp2p/interface-peer-store' import { logger } from '@libp2p/logger' -import * as pb from './pb/index.js' -import { readCandidatesUntilConnected } from './util.js' +import { connect, handleIncomingStream } from './handler.js' const log = logger('libp2p:webrtc:peer') -const TIMEOUT = 30 * 1000 export const TRANSPORT = '/webrtc-direct' export const PROTOCOL = '/webrtc-direct/0.0.1' export const CODE = 276 @@ -87,11 +81,7 @@ export class WebRTCDirectTransport implements Transport, Startable { * /p2p//p2p-circuit/webrtc-direct/p2p/ */ async dial (ma: Multiaddr, options: DialOptions): Promise { - // extract peer id - // if (!remotePeerId) { - // throw("peerId should be present in multiaddr") - // } - + log.trace('dialing address: ', ma) const addrs = ma.toString().split(TRANSPORT) // look for remote peerId let relayed = multiaddr(addrs[0]) @@ -99,59 +89,19 @@ export class WebRTCDirectTransport implements Transport, Startable { if (remotePeerId != null) { relayed = relayed.encapsulate(multiaddr(`/p2p/${remotePeerId}`)) } + const controller = new AbortController() if (options.signal == null) { - options.signal = new AbortSignal() + options.signal = controller.signal } const connection = await this.components.transportManager.dial(relayed) const rawStream = await connection.newStream([PROTOCOL], options) - const stream = pbStream(abortableDuplex(rawStream, options.signal)).pb(pb.Message) - - // setup peer connection - const pc = new RTCPeerConnection(this.init.rtcConfiguration) - // the label is not relevant to connection initiation but can be - // useful for debugging - const channel = pc.createDataChannel('init') - - const connectedPromise = pDefer() - pc.onconnectionstatechange = (_) => { - switch (pc.connectionState) { - case 'connected': - return connectedPromise.resolve() - case 'closed': - case 'disconnected': - case 'failed': - return connectedPromise.reject() - } - } - - options.signal.onabort = connectedPromise.reject - // setup callback to write ICE candidates to the remote - // peer - pc.onicecandidate = ({ candidate }) => { - stream.write({ - type: pb.Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate) : '' - }) - } - - // read offer - const offerMessage = await stream.read() - if (offerMessage.type !== pb.Message.Type.SDP_OFFER) { - throw new Error('remote should send an SDP offer') - } - - const offerSdp = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) - await pc.setRemoteDescription(offerSdp) - - // create an answer - const answerSdp = await pc.createAnswer() - // write the answer to the stream - stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) - // set answer as local description - pc.setLocalDescription(answerSdp) - await readCandidatesUntilConnected(connectedPromise, pc, stream) + const pc = await connect({ + stream: rawStream, + rtcConfiguration: this.init.rtcConfiguration, + signal: options.signal + }) const result = options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ @@ -167,59 +117,18 @@ export class WebRTCDirectTransport implements Transport, Startable { ) // close streams rawStream.close() - channel.close() void connection.close() // TODO: hack // await new Promise(res => setTimeout(res, 100)) return await result } - async _onProtocol ({ connection, stream: rawStream }: IncomingStreamData) { - const timeoutController = new TimeoutController(TIMEOUT) - const signal = timeoutController.signal - const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)).pb(pb.Message) - const pc = new RTCPeerConnection(this.init.rtcConfiguration) - - const connectedPromise: DeferredPromise = pDefer() - signal.onabort = () => connectedPromise.reject() - // candidate callbacks - pc.onicecandidate = ({ candidate }) => { - stream.write({ - type: pb.Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate) : '' - }) - } - pc.onconnectionstatechange = (_) => { - log.trace('received pc state: ', pc.connectionState) - switch (pc.connectionState) { - case 'connected': - connectedPromise.resolve() - break - case 'failed': - case 'disconnected': - case 'closed': - connectedPromise.reject() - } - } - - // create and write an SDP offer - const offer = await pc.createOffer() - pc.setLocalDescription(offer) - stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) - - // read an SDP anwer - const pbAnswer = await stream.read() - if (pbAnswer.type != pb.Message.Type.SDP_ANSWER) { - throw new Error('response message should be an SDP answer') - } - const answer = new RTCSessionDescription({ - type: 'answer', - sdp: pbAnswer.data + async _onProtocol ({ connection, stream }: IncomingStreamData) { + const pc = await handleIncomingStream({ + rtcConfiguration: this.init.rtcConfiguration, + connection, + stream }) - await pc.setRemoteDescription(answer) - - // wait until candidates are connected - await readCandidatesUntilConnected(connectedPromise, pc, stream) const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-direct') const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, @@ -230,7 +139,7 @@ export class WebRTCDirectTransport implements Transport, Startable { skipProtection: true, muxerFactory }) - rawStream.close() + stream.close() if (this.handler != null) { this.handler(conn) } diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index 9555e99..4a38f8a 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -1,29 +1,29 @@ -import type { DeferredPromise } from "p-defer" +import type { DeferredPromise } from 'p-defer' import * as pb from './pb/index.js' -type MessageStream = { - read: () => Promise, - write: (d: pb.Message) => void | Promise -}; +interface MessageStream { + read: () => Promise + write: (d: pb.Message) => void | Promise +} export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream) => { - while (true) { - const readResult = await Promise.race([connectedPromise.promise, stream.read()]) - // check if readResult is a message - if (readResult instanceof Object) { - const message = readResult as pb.Message - if (message.type !== pb.Message.Type.ICE_CANDIDATE) { - throw new Error('expected only ice candidates') - } - // end of candidates has been signalled - if (message.data == null || message.data === '') { - break - } - await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) - } else { - // connected promise resolved - break - } + while (true) { + const readResult = await Promise.race([connectedPromise.promise, stream.read()]) + // check if readResult is a message + if (readResult instanceof Object) { + const message = readResult + if (message.type !== pb.Message.Type.ICE_CANDIDATE) { + throw new Error('expected only ice candidates') + } + // end of candidates has been signalled + if (message.data == null || message.data === '') { + break + } + await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) + } else { + // connected promise resolved + break } - await connectedPromise + } + await connectedPromise } -export {} \ No newline at end of file +export {} diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index ac2713f..453b358 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -138,12 +138,25 @@ // }) // }) -describe('webrtc_direct handlers', () => { - it('handles incoming connection', () => { - - - }) - +import { mockConnection, mockMultiaddrConnection, mockStream } from '@libp2p/interface-mocks' +import { createEd25519PeerId } from '@libp2p/peer-id-factory' +import { expect } from 'aegir/chai' +import { pair } from 'it-pair' +import { connect, handleIncomingStream } from '../src/peer_transport/handler' + +describe.skip('webrtc_direct handlers', () => { + it('handles incoming connection', async () => { + const stream = mockStream(pair()) + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const controller = new AbortController() + const initiatorPromise = connect({ stream, signal: controller.signal }) + const receiverPromise = handleIncomingStream({ stream, connection }) + await expect(initiatorPromise).to.be.fulfilled() + await expect(receiverPromise).to.be.fulfilled() + }) }) -export {} +export { } From 5e3d29e5d42f63ec460f95d373e6a98b64337c22 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 8 Feb 2023 18:28:41 +0530 Subject: [PATCH 07/52] add tests for handlers --- src/peer_transport/handler.ts | 14 +- src/peer_transport/transport.ts | 8 +- src/peer_transport/util.ts | 11 +- test/peer.browser.spec.ts | 258 ++++++++++++++------------------ 4 files changed, 132 insertions(+), 159 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index fd2056a..c9dfd83 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -32,7 +32,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea // setup callback for peerconnection state change pc.onconnectionstatechange = (_) => { - log.trace('received pc state: ', pc.connectionState) + log.trace('receiver peerConnectionState state: ', pc.connectionState) switch (pc.connectionState) { case 'connected': connectedPromise.resolve() @@ -44,7 +44,6 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea break default: break - connectedPromise.reject() } } // we create the channel so that the peerconnection has a component for @@ -53,14 +52,14 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea // create and write an SDP offer const offer = await pc.createOffer() - pc.setLocalDescription(offer) + await pc.setLocalDescription(offer) stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) - log('wrote offer') // read an SDP anwer const pbAnswer = await stream.read() if (pbAnswer.type !== pb.Message.Type.SDP_ANSWER) { - throw new Error('response message should be an SDP answer') + // TODO: Find better way to print undefined without linter complaining + throw new Error(`expected message type SDP_ANSWER, received: ${pbAnswer.type ?? 'undefined'} `) } const answer = new RTCSessionDescription({ type: 'answer', @@ -89,7 +88,7 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: // the label is not relevant to connection initiation but can be // useful for debugging - const connectedPromise = pDefer() + const connectedPromise = pDefer() pc.onconnectionstatechange = (_) => { switch (pc.connectionState) { case 'connected': @@ -115,7 +114,6 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: // read offer const offerMessage = await stream.read() - log('read offer') if (offerMessage.type !== pb.Message.Type.SDP_OFFER) { throw new Error('remote should send an SDP offer') } @@ -128,7 +126,7 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: // write the answer to the stream stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) // set answer as local description - pc.setLocalDescription(answerSdp) + await pc.setLocalDescription(answerSdp) await readCandidatesUntilConnected(connectedPromise, pc, stream) return pc diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 43eed92..56fe70a 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -37,14 +37,18 @@ export class WebRTCDirectTransport implements Transport, Startable { constructor ( private readonly components: WebRTCDirectTransportComponents, private readonly init: WebRTCPeerTransportInit - ) {} + ) { + this._onProtocol = this._onProtocol.bind(this) + } isStarted () { return this._started } async start () { - await this.components.registrar.handle(PROTOCOL, this._onProtocol.bind(this)) + await this.components.registrar.handle(PROTOCOL, (data) => { + this._onProtocol(data).catch(err => log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err)) + }) // this.components.peerStore.addEventListener('change:multiaddrs', (event) => { // const { peerId } = event.detail // }) diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index 4a38f8a..7efb152 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -1,3 +1,4 @@ +import { logger } from '@libp2p/logger' import type { DeferredPromise } from 'p-defer' import * as pb from './pb/index.js' @@ -5,7 +6,10 @@ interface MessageStream { read: () => Promise write: (d: pb.Message) => void | Promise } -export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream) => { + +const log = logger('libp2p:webrtc:peer:util') + +export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream) => { while (true) { const readResult = await Promise.race([connectedPromise.promise, stream.read()]) // check if readResult is a message @@ -16,14 +20,17 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro } // end of candidates has been signalled if (message.data == null || message.data === '') { + log.trace('end-of-candidates received') break } + + log.trace('received new ICE candidate: %s', message.data) await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) } else { // connected promise resolved break } } - await connectedPromise + await connectedPromise.promise } export {} diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 453b358..08d4087 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -1,161 +1,125 @@ -// import { createLibp2p } from 'libp2p' -// import { webRTC, webRTCPeer } from '../src' -// import { webSockets } from '@libp2p/websockets' -// import * as filters from '@libp2p/websockets/filters' -// import { mplex } from '@libp2p/mplex' -// import { noise } from '@chainsafe/libp2p-noise' -// import { multiaddr } from '@multiformats/multiaddr' -// import pDefer from 'p-defer' -// import { pipe } from 'it-pipe' -// import { fromString } from 'uint8arrays/from-string' -// import { toString } from 'uint8arrays/to-string' -// import first from 'it-first' -// import { expect } from 'aegir/chai' - -// describe.skip('test relay', () => { -// it('can connect over ws relay', async () => { -// const relayAddress = multiaddr('/ip4/192.168.1.101/tcp/4003/ws/p2p/QmceBZS6MN8uX4vvRdpTnu9Ga2uhHzRnVYLYPTnyWHkyHc') -// const listener = await createLibp2p({ -// transports: [ -// webRTCPeer({}), -// webSockets({ -// filter: filters.all -// }) -// ], -// streamMuxers: [mplex()], -// connectionEncryption: [noise()], -// relay: { -// enabled: true, -// autoRelay: { -// enabled: true, -// maxListeners: 2 -// } -// } -// }) -// const dialer = await createLibp2p({ -// transports: [ -// webRTCPeer({}), -// webSockets({ -// filter: filters.all -// }) -// ], -// streamMuxers: [mplex()], -// connectionEncryption: [noise()], -// identify: { -// timeout: 30000 -// } -// }) - -// await listener.start() -// await dialer.start() - -// const relaying = pDefer() -// listener.peerStore.addEventListener('change:multiaddrs', (event) => { -// const { peerId } = event.detail - -// // Updated self multiaddrs? -// if (peerId.equals(listener.peerId)) { -// const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` -// relaying.resolve(webrtcAddr) -// } -// }) - -// listener.handle('/echo/1.0.0', ({ stream }) => { -// void pipe(stream, stream) -// }) - -// await listener.dial(relayAddress) -// const dialAddr = multiaddr(await relaying.promise) -// const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) -// const input = fromString('test') -// const output = await pipe( -// [input], -// stream, -// async (source) => await first(source) -// ) -// expect(toString(output!.subarray())).to.equals('test') -// console.log('read data', output!.subarray()) -// }) - -// it.only('can connect over webrtc relay', async () => { -// const relayAddress = multiaddr('/ip4/192.168.1.101/udp/4004/webrtc/certhash/uEiBMYhADacrAg34fe9Vfj9cy6ZaNx5EqhLnWtol9zFvO5A/p2p/QmZxycy737ycr2vGWwT9HreJGAtNu3EGLAfwuGrMfBxVF4') -// const listener = await createLibp2p({ -// transports: [ -// webRTCPeer({}), -// webRTC() -// ], -// streamMuxers: [mplex()], -// connectionEncryption: [noise()], -// relay: { -// enabled: true, -// autoRelay: { -// enabled: true, -// maxListeners: 2 -// } -// } -// }) -// const dialer = await createLibp2p({ -// transports: [ -// webRTCPeer({}), -// webRTC() -// ], -// streamMuxers: [mplex()], -// connectionEncryption: [noise()], -// relay: { -// enabled: true -// } -// }) - -// await listener.start() -// await dialer.start() - -// const relaying = pDefer() -// listener.peerStore.addEventListener('change:multiaddrs', (event) => { -// const { peerId } = event.detail - -// if (peerId.equals(listener.peerId)) { -// const webrtcAddr = `${listener.getMultiaddrs()[0].toString()}/webrtc-peer/p2p/${peerId}` -// relaying.resolve(webrtcAddr) -// } -// }) - -// listener.handle('/echo/1.0.0', ({ stream }) => { -// void pipe(stream, stream) -// }) - -// await listener.dial(relayAddress) -// const addr = await relaying.promise -// const dialAddr = multiaddr(addr) -// const stream = await dialer.dialProtocol(dialAddr, ['/echo/1.0.0']) -// const input = fromString('test') -// const output = await pipe( -// [input], -// stream, -// async (source) => await first(source) -// ) -// expect(toString(output!.subarray())).to.equals('test') -// console.log('read data', output!.subarray()) -// }) -// }) - import { mockConnection, mockMultiaddrConnection, mockStream } from '@libp2p/interface-mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { expect } from 'aegir/chai' import { pair } from 'it-pair' +import { duplexPair } from 'it-pair/duplex' +import { pbStream } from 'it-pb-stream' import { connect, handleIncomingStream } from '../src/peer_transport/handler' +import { Message } from '../src/peer_transport/pb/index.js' -describe.skip('webrtc_direct handlers', () => { - it('handles incoming connection', async () => { - const stream = mockStream(pair()) +describe('webrtc direct basic', () => { + it('should connect', async () => { + const [receiver, initiator] = duplexPair() const dstPeerId = await createEd25519PeerId() const connection = mockConnection( mockMultiaddrConnection(pair(), dstPeerId) ) const controller = new AbortController() - const initiatorPromise = connect({ stream, signal: controller.signal }) - const receiverPromise = handleIncomingStream({ stream, connection }) - await expect(initiatorPromise).to.be.fulfilled() - await expect(receiverPromise).to.be.fulfilled() + const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + await expect(initiatorPeerConnectionPromise).to.be.fulfilled() + await expect(receiverPeerConnectionPromise).to.be.fulfilled() + const [pc0, pc1] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) + expect(pc0.connectionState).eq('connected') + expect(pc1.connectionState).eq('connected') + }) +}) + +describe('webrtc direct receiver', () => { + it('should fail receiving on invalid sdp answer', async () => { + const [receiver, initiator] = duplexPair() + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + const stream = pbStream(initiator).pb(Message) + const offerSDP = await stream.read() + expect(offerSDP.data).to.not.be.undefined() + expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) + // check SDP + { + const pc = new RTCPeerConnection() + const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) + await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() + } + + stream.write({ type: Message.Type.SDP_ANSWER, data: 'bad' }) + await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/Failed to execute 'setRemoteDescription'/) + }) + + it('should fail on receiving candidate before answer', async () => { + const [receiver, initiator] = duplexPair() + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + const stream = pbStream(initiator).pb(Message) + const offerSDP = await stream.read() + expect(offerSDP.data).to.not.be.undefined() + expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) + // check SDP + { + const pc = new RTCPeerConnection() + const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) + await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() + // set up a callback to write a candidate + pc.onicecandidate = ({ candidate }) => { + stream.write({ + type: Message.Type.ICE_CANDIDATE, + data: (candidate != null) ? JSON.stringify(candidate) : '' + }) + } + // set the answer + const answer = await pc.createAnswer() + await pc.setLocalDescription(answer) + } + + await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/expected message type SDP_ANSWER/) + }) + + it('should fail on receiving invalid candidate', async () => { + const [receiver, initiator] = duplexPair() + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + const stream = pbStream(initiator).pb(Message) + const offerSDP = await stream.read() + expect(offerSDP.data).to.not.be.undefined() + expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) + // check SDP + { + const pc = new RTCPeerConnection() + const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) + await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() + // create the answer + const answer = await pc.createAnswer() + // write the answer + stream.write({ type: Message.Type.SDP_ANSWER, data: answer.sdp }) + // set answer as local description + await pc.setLocalDescription(answer) + // send broken candidate + stream.write({ + type: Message.Type.ICE_CANDIDATE, + data: 'bad candidate' + }) + } + + await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/bad candidate/) + }) +}) + +describe('webrtc direct dialer', () => { + it('should fail on invalid sdp offer', async () => { + const [receiver, initiator] = duplexPair() + const controller = new AbortController() + const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) + const stream = pbStream(receiver).pb(Message) + stream.write({ type: Message.Type.SDP_OFFER, data: 'bad' }) + await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/Failed to execute 'setRemoteDescription'/) }) }) From 43246b49396c27bcabeba2952fbf5542ae329511 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 8 Feb 2023 19:25:18 +0530 Subject: [PATCH 08/52] fix dep-check --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 3445d8b..b63ab7f 100644 --- a/package.json +++ b/package.json @@ -142,11 +142,13 @@ "@libp2p/interface-peer-id": "^2.0.0", "@libp2p/interface-stream-muxer": "^3.0.0", "@libp2p/interface-transport": "^2.0.0", + "@libp2p/interfaces": "^3.3.1", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^2.0.0", "@multiformats/mafmt": "^11.0.3", "@multiformats/multiaddr": "^11.0.3", "@protobuf-ts/runtime": "^2.8.0", + "abortable-iterator": "^4.0.2", "err-code": "^3.0.1", "it-handshake": "^4.1.2", "it-length-prefixed": "^8.0.3", From 6472150e7bceb045494f128a11f14bb82cfea569 Mon Sep 17 00:00:00 2001 From: David DiMaria Date: Mon, 13 Feb 2023 08:37:18 -0700 Subject: [PATCH 09/52] Add browser to browser example with Node and Go relays --- examples/browser-to-browser/README.md | 34 +++++ examples/browser-to-browser/dialer.js | 31 +++++ examples/browser-to-browser/index.html | 41 ++++++ examples/browser-to-browser/index.js | 51 ++++++++ examples/browser-to-browser/package.json | 25 ++++ examples/browser-to-browser/relay.js | 38 ++++++ examples/browser-to-browser/tests/test.js | 97 ++++++++++++++ examples/browser-to-browser/vite.config.js | 11 ++ examples/go-libp2p-server/go.mod | 1 + examples/go-libp2p-server/go.sum | 2 + examples/go-libp2p-server/relay.go | 141 +++++++++++++++++++++ 11 files changed, 472 insertions(+) create mode 100644 examples/browser-to-browser/README.md create mode 100644 examples/browser-to-browser/dialer.js create mode 100644 examples/browser-to-browser/index.html create mode 100644 examples/browser-to-browser/index.js create mode 100644 examples/browser-to-browser/package.json create mode 100644 examples/browser-to-browser/relay.js create mode 100644 examples/browser-to-browser/tests/test.js create mode 100644 examples/browser-to-browser/vite.config.js create mode 100644 examples/go-libp2p-server/relay.go diff --git a/examples/browser-to-browser/README.md b/examples/browser-to-browser/README.md new file mode 100644 index 0000000..fb3d997 --- /dev/null +++ b/examples/browser-to-browser/README.md @@ -0,0 +1,34 @@ +# js-libp2p-webrtc Browser to Server + +This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. + +## Running the Go Server + +To run the Go LibP2P WebRTC server: + +```shell +npm run go-libp2p-server +``` + +Copy the multiaddress in the output. + +## Running the Example + +In a separate console tab, install dependencies and start the Vite server: + +```shell +npm i && npm run start +``` + +The browser window will automatically open. +Using the copied multiaddress from the Go server, paste it into the `Server MultiAddress` input and click the `Connect` button. +Once the peer is connected, click the message section will appear. Enter a message and click the `Send` button. + +The output should look like: + +```text +Dialing /ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb +Peer connected '/ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb' +Sending message 'hello' +Received message 'hello' +``` \ No newline at end of file diff --git a/examples/browser-to-browser/dialer.js b/examples/browser-to-browser/dialer.js new file mode 100644 index 0000000..d6f7af5 --- /dev/null +++ b/examples/browser-to-browser/dialer.js @@ -0,0 +1,31 @@ +import { createLibp2p } from 'libp2p' +import { webSockets } from '@libp2p/websockets' +import { noise } from '@chainsafe/libp2p-noise' +import { mplex } from '@libp2p/mplex' +import { multiaddr } from '@multiformats/multiaddr' + +async function main () { + const autoRelayNodeAddr = process.argv[2] + if (!autoRelayNodeAddr) { + throw new Error('the auto relay node address needs to be specified') + } + + const node = await createLibp2p({ + transports: [ + webSockets() + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + mplex() + ] + }) + + console.log(`Node started with id ${node.peerId.toString()}`) + + const conn = await node.dial(multiaddr(autoRelayNodeAddr)) + console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) +} + +main() \ No newline at end of file diff --git a/examples/browser-to-browser/index.html b/examples/browser-to-browser/index.html new file mode 100644 index 0000000..24ff11f --- /dev/null +++ b/examples/browser-to-browser/index.html @@ -0,0 +1,41 @@ + + + + + + js-libp2p WebRTC + + + +
+
+ + + +
+
+ + + +
+
+
+ + + diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js new file mode 100644 index 0000000..5e1f7a8 --- /dev/null +++ b/examples/browser-to-browser/index.js @@ -0,0 +1,51 @@ +import { createLibp2p } from 'libp2p' +import { noise } from '@chainsafe/libp2p-noise' +import { multiaddr } from '@multiformats/multiaddr' +import { pipe } from "it-pipe"; +import { fromString, toString } from "uint8arrays"; +import { webRTCDirect } from 'js-libp2p-webrtc' +import { webSockets } from '@libp2p/websockets' +import { pushable } from 'it-pushable'; +import { mplex } from '@libp2p/mplex' + +let stream; +const output = document.getElementById('output') +const sendSection = document.getElementById('send-section') +const appendOutput = (line) => { + const div = document.createElement("div") + div.appendChild(document.createTextNode(line)) + output.append(div) +} +const clean = (line) => line.replaceAll('\n', '') +const sender = pushable() + +const node = await createLibp2p({ + transports: [webSockets()], + connectionEncryption: [noise()], + streamMuxers: [mplex()], +}) + +await node.start() + +node.connectionManager.addEventListener('peer:connect', (connection) => { + appendOutput(`Peer connected '${node.getConnections().map(c => c.remoteAddr.toString())}'`) + sendSection.style.display = 'block' +}) + +window.connect.onclick = async () => { + const ma = multiaddr('/ip4/127.0.0.1/tcp/56166/ws/p2p/12D3KooWRMcdvWm1eQELXJNaWVowT6cbVwXwsoHDckZx64pXBP9G') + appendOutput(`Dialing '${ma}'`) + stream = await node.dialProtocol(ma, ['/echo/1.0.0']) + pipe(sender, stream, async (src) => { + for await(const buf of src) { + const response = toString(buf.subarray()) + appendOutput(`Received message '${clean(response)}'`) + } + }) +} + +window.send.onclick = async () => { + const message = `${window.message.value}\n` + appendOutput(`Sending message '${clean(message)}'`) + sender.push(fromString(message)) +} diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json new file mode 100644 index 0000000..1c93527 --- /dev/null +++ b/examples/browser-to-browser/package.json @@ -0,0 +1,25 @@ +{ + "name": "js-libp2p-webrtc-browser-to-server", + "version": "1.0.0", + "description": "Connect a browser to a server", + "type": "module", + "scripts": { + "start": "vite", + "build": "vite build", + "go-libp2p-server": "cd ../go-libp2p-server && go run ./main.go", + "test": "npm run build && playwright test tests" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^11.0.0", + "@libp2p/websockets": "^5.0.3", + "@multiformats/multiaddr": "^11.0.5", + "it-pushable": "^3.1.0", + "js-libp2p-webrtc": "file:../../", + "libp2p": "^0.42.0", + "vite": "^3.1.0" + }, + "devDependencies": { + "@playwright/test": "^1.30.0", + "test-util-ipfs-example": "^1.0.2" + } +} diff --git a/examples/browser-to-browser/relay.js b/examples/browser-to-browser/relay.js new file mode 100644 index 0000000..878d3f5 --- /dev/null +++ b/examples/browser-to-browser/relay.js @@ -0,0 +1,38 @@ +import { createLibp2p } from 'libp2p' +import { webSockets } from '@libp2p/websockets' +import { noise } from '@chainsafe/libp2p-noise' +import { mplex } from '@libp2p/mplex' + +async function main () { + const node = await createLibp2p({ + addresses: { + listen: ['/ip4/0.0.0.0/tcp/0/ws'] + // TODO check "What is next?" section + // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] + }, + transports: [ + webSockets() + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + mplex() + ], + relay: { + enabled: true, + hop: { + enabled: true + }, + advertise: { + enabled: true, + } + } + }) + + console.log(`Node started with id ${node.peerId.toString()}`) + console.log('Listening on:') + node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) +} + +main() \ No newline at end of file diff --git a/examples/browser-to-browser/tests/test.js b/examples/browser-to-browser/tests/test.js new file mode 100644 index 0000000..13f80cd --- /dev/null +++ b/examples/browser-to-browser/tests/test.js @@ -0,0 +1,97 @@ +/* eslint-disable no-console */ +import { test, expect } from '@playwright/test' +import { playwright } from 'test-util-ipfs-example' +import { spawn, exec } from 'child_process' +import { existsSync } from 'fs' + +// Setup +const play = test.extend({ + ...playwright.servers() +}) + +async function spawnGoLibp2p() { + if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server')) { + await new Promise((resolve, reject) => { + exec('go build', + { cwd: '../../examples/go-libp2p-server' }, + (error, stdout, stderr) => { + if (error) { + throw (`exec error: ${error}`) + } + resolve() + }) + }) + } + + const server = spawn('./go-libp2p-server', [], { cwd: '../../examples/go-libp2p-server', killSignal: 'SIGINT' }) + server.stderr.on('data', (data) => { + console.log(`stderr: ${data}`, typeof data) + }) + const serverAddr = await (new Promise(resolve => { + server.stdout.on('data', (data) => { + console.log(`stdout: ${data}`, typeof data) + const addr = String(data).match(/p2p addr: ([^\s]*)/) + if (addr !== null && addr.length > 0) { + resolve(addr[1]) + } + }) + })) + return { server, serverAddr } +} + +play.describe('bundle ipfs with parceljs:', () => { + // DOM + const connectBtn = '#connect' + const connectAddr = '#peer' + const messageInput = '#message' + const sendBtn = '#send' + const output = '#output' + + let server + let serverAddr + + // eslint-disable-next-line no-empty-pattern + play.beforeAll(async ({ }, testInfo) => { + testInfo.setTimeout(5 * 60_000) + const s = await spawnGoLibp2p() + server = s.server + serverAddr = s.serverAddr + console.log('Server addr:', serverAddr) + }, {}) + + play.afterAll(() => { + server.kill('SIGINT') + }) + + play.beforeEach(async ({ servers, page }) => { + const url = `http://localhost:${servers[0].port}/` + console.log(url) + await page.goto(url) + }) + + play('should connect to a go-libp2p node over webtransport', async ({ page }) => { + const message = 'hello' + + // add the go libp2p multiaddress to the input field and submit + await page.fill(connectAddr, serverAddr) + await page.click(connectBtn) + + // send the relay message to the go libp2p server + await page.fill(messageInput, message) + await page.click(sendBtn) + + await page.waitForSelector('#output:has(div)') + + // Expected output: + // + // Dialing '${serverAddr}' + // Peer connected '${serverAddr}' + // Sending message '${message}' + // Received message '${message}' + const connections = await page.textContent(output) + expect(connections).toContain(`Dialing '${serverAddr}'`) + expect(connections).toContain(`Peer connected '${serverAddr}'`) + expect(connections).toContain(`Sending message '${message}'`) + expect(connections).toContain(`Received message '${message}'`) + }) +}) \ No newline at end of file diff --git a/examples/browser-to-browser/vite.config.js b/examples/browser-to-browser/vite.config.js new file mode 100644 index 0000000..353f32b --- /dev/null +++ b/examples/browser-to-browser/vite.config.js @@ -0,0 +1,11 @@ +export default { + build: { + target: 'es2022' + }, + optimizeDeps: { + esbuildOptions: { target: 'es2022', supported: { bigint: true } } + }, + server: { + open: true + } +} \ No newline at end of file diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index a501dae..4d51311 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -39,6 +39,7 @@ require ( github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect + github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect diff --git a/examples/go-libp2p-server/go.sum b/examples/go-libp2p-server/go.sum index c2d52ec..4734f42 100644 --- a/examples/go-libp2p-server/go.sum +++ b/examples/go-libp2p-server/go.sum @@ -261,6 +261,8 @@ github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnF github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= +github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= diff --git a/examples/go-libp2p-server/relay.go b/examples/go-libp2p-server/relay.go new file mode 100644 index 0000000..7d579f5 --- /dev/null +++ b/examples/go-libp2p-server/relay.go @@ -0,0 +1,141 @@ +package main + +import ( + "bufio" + "crypto/rand" + "fmt" + "log" + "net" + "os" + "os/signal" + "syscall" + + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/network" + // "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/muxer/mplex" + ma "github.com/multiformats/go-multiaddr" + relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" + webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" +) + +var listenerIp = net.IPv4(127, 0, 0, 1) + +func init() { + ifaces, err := net.Interfaces() + if err != nil { + return + } + for _, iface := range ifaces { + if iface.Flags&net.FlagUp == 0 { + continue + } + addrs, err := iface.Addrs() + if err != nil { + return + } + for _, addr := range addrs { + // bind to private non-loopback ip + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { + if ipnet.IP.To4() != nil { + listenerIp = ipnet.IP.To4() + return + } + } + } + } +} + +func echoHandler(stream network.Stream) { + for { + reader := bufio.NewReader(stream) + str, err := reader.ReadString('\n') + log.Printf("err: %s", err) + if err != nil { + return + } + log.Printf("echo: %s", str) + _, err = stream.Write([]byte(str)) + if err != nil { + log.Printf("err: %v", err) + return + } + } +} + +func main() { + makeRelayV1() + // host := makeRelayV1() + // host.SetStreamHandler("/echo/1.0.0", echoHandler) + // defer host.Close() + // remoteInfo := peer.AddrInfo{ + // ID: host.ID(), + // Addrs: host.Network().ListenAddresses(), + // } + + // remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) + // fmt.Println("p2p addr: ", remoteAddrs[0]) + + fmt.Println("press Ctrl+C to quit") + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) + <-ch +} + +func createHost() host.Host { + h, err := libp2p.New( + libp2p.Transport(webrtc.New), + libp2p.ListenAddrStrings( + fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), + ), + libp2p.DisableRelay(), + libp2p.Ping(true), + ) + if err != nil { + panic(err) + } + + return h +} + +func makeRelayV1() { + r := rand.Reader + // Generate a key pair for this host. We will use it at least + // to obtain a valid host ID. + priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r) + if err != nil { + panic(err) + } + + opts := []libp2p.Option{ + libp2p.DefaultTransports, + libp2p.ListenAddrStrings( + "/ip4/0.0.0.0/tcp/4003/ws", + ), + libp2p.Identity(priv), + libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), + libp2p.EnableRelay(), + } + + host, err := libp2p.New(opts...) + if err != nil { + panic(err) + } + + _, err = relay.NewRelay(host) + if err != nil { + panic(err) + } + + fmt.Println(host.Mux().Protocols()) + + for _, addr := range host.Addrs() { + a, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", host.ID().Pretty())) + if err != nil { + panic(err) + } + fmt.Println(addr.Encapsulate(a)) + } +} From 83cd25428460eb8f0410a2b74409120c30e34525 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 14 Feb 2023 18:47:04 +0530 Subject: [PATCH 10/52] fix browser-to-browser example --- examples/browser-to-browser/index.html | 2 +- examples/browser-to-browser/index.js | 50 ++++++++++++++++++-------- examples/go-libp2p-server/relay.go | 26 ++++---------- package.json | 5 +-- src/peer_transport/handler.ts | 4 +-- src/peer_transport/transport.ts | 40 ++++++++++++--------- test/peer.browser.spec.ts | 25 ++++++++++++- 7 files changed, 96 insertions(+), 56 deletions(-) diff --git a/examples/browser-to-browser/index.html b/examples/browser-to-browser/index.html index 24ff11f..62374cf 100644 --- a/examples/browser-to-browser/index.html +++ b/examples/browser-to-browser/index.html @@ -25,7 +25,7 @@
- +
diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 5e1f7a8..f6e4e2a 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -1,12 +1,13 @@ -import { createLibp2p } from 'libp2p' -import { noise } from '@chainsafe/libp2p-noise' import { multiaddr } from '@multiformats/multiaddr' import { pipe } from "it-pipe"; import { fromString, toString } from "uint8arrays"; import { webRTCDirect } from 'js-libp2p-webrtc' import { webSockets } from '@libp2p/websockets' +import * as filters from '@libp2p/websockets/filters' import { pushable } from 'it-pushable'; import { mplex } from '@libp2p/mplex' +import { createLibp2p } from 'libp2p'; +import { noise } from '@chainsafe/libp2p-noise'; let stream; const output = document.getElementById('output') @@ -20,28 +21,49 @@ const clean = (line) => line.replaceAll('\n', '') const sender = pushable() const node = await createLibp2p({ - transports: [webSockets()], + transports: [ + webSockets({ + filter: filters.all, + }), + webRTCDirect({}), + ], connectionEncryption: [noise()], streamMuxers: [mplex()], + relay: { + enabled: true, + autoRelay: { + enabled: true, + }, + }, }) await node.start() -node.connectionManager.addEventListener('peer:connect', (connection) => { - appendOutput(`Peer connected '${node.getConnections().map(c => c.remoteAddr.toString())}'`) - sendSection.style.display = 'block' +// handle the echo protocol +await node.handle('/echo/1.0.0', ({ stream, connection }) => { + void pipe(stream, stream) }) -window.connect.onclick = async () => { - const ma = multiaddr('/ip4/127.0.0.1/tcp/56166/ws/p2p/12D3KooWRMcdvWm1eQELXJNaWVowT6cbVwXwsoHDckZx64pXBP9G') - appendOutput(`Dialing '${ma}'`) - stream = await node.dialProtocol(ma, ['/echo/1.0.0']) - pipe(sender, stream, async (src) => { - for await(const buf of src) { - const response = toString(buf.subarray()) - appendOutput(`Received message '${clean(response)}'`) +node.peerStore.addEventListener('change:multiaddrs', (event) => { + const { peerId } = event.detail + if (node.getMultiaddrs().length === 0 || !node.peerId.equals(peerId)) { + return + } + node.getMultiaddrs().forEach((ma) => { + if (ma.protoCodes().includes(290)) { + const webrtcDirectAddress = ma.encapsulate(multiaddr(`/p2p-webrtc-direct/p2p/${node.peerId}`)) + appendOutput(`Listening on ${webrtcDirectAddress}`) } }) +}) + +window.connect.onclick = async () => { + const ma = multiaddr(document.getElementById("peer").value) + appendOutput(`Dialing '${ma}'`) + const connection = await node.dial(ma) + console.log('dial completed') + stream = await connection.newStream(['/echo/1.0.0']) + console.log('stream', stream) } window.send.onclick = async () => { diff --git a/examples/go-libp2p-server/relay.go b/examples/go-libp2p-server/relay.go index 7d579f5..71654fd 100644 --- a/examples/go-libp2p-server/relay.go +++ b/examples/go-libp2p-server/relay.go @@ -6,19 +6,17 @@ import ( "fmt" "log" "net" - "os" - "os/signal" - "syscall" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" + // "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/muxer/mplex" - ma "github.com/multiformats/go-multiaddr" relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" + ma "github.com/multiformats/go-multiaddr" ) var listenerIp = net.IPv4(127, 0, 0, 1) @@ -67,21 +65,8 @@ func echoHandler(stream network.Stream) { func main() { makeRelayV1() - // host := makeRelayV1() - // host.SetStreamHandler("/echo/1.0.0", echoHandler) - // defer host.Close() - // remoteInfo := peer.AddrInfo{ - // ID: host.ID(), - // Addrs: host.Network().ListenAddresses(), - // } - - // remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) - // fmt.Println("p2p addr: ", remoteAddrs[0]) - fmt.Println("press Ctrl+C to quit") - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) - <-ch + select{} } func createHost() host.Host { @@ -100,7 +85,7 @@ func createHost() host.Host { return h } -func makeRelayV1() { +func makeRelayV1() host.Host { r := rand.Reader // Generate a key pair for this host. We will use it at least // to obtain a valid host ID. @@ -114,8 +99,8 @@ func makeRelayV1() { libp2p.ListenAddrStrings( "/ip4/0.0.0.0/tcp/4003/ws", ), - libp2p.Identity(priv), libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), + libp2p.Identity(priv), libp2p.EnableRelay(), } @@ -138,4 +123,5 @@ func makeRelayV1() { } fmt.Println(addr.Encapsulate(a)) } + return host } diff --git a/package.json b/package.json index b63ab7f..15f4a80 100644 --- a/package.json +++ b/package.json @@ -169,13 +169,14 @@ "@libp2p/interface-mocks": "^9.0.0", "@libp2p/mplex": "^7.1.1", "@libp2p/peer-id-factory": "^2.0.0", - "@libp2p/websockets": "^5.0.2", + "@libp2p/websockets": "^5.0.3", "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "aegir": "^37.6.6", "it-first": "^2.0.0", "it-pair": "^2.0.3", "libp2p": "^0.41.0", - "protons": "^6.0.1" + "protons": "^6.0.1", + "sinon": "^15.0.1" } } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index c9dfd83..d4357a7 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -26,7 +26,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea pc.onicecandidate = ({ candidate }) => { stream.write({ type: pb.Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate) : '' + data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' }) } @@ -108,7 +108,7 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: pc.onicecandidate = ({ candidate }) => { stream.write({ type: pb.Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate) : '' + data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' }) } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 56fe70a..2735a15 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -14,8 +14,12 @@ import { connect, handleIncomingStream } from './handler.js' const log = logger('libp2p:webrtc:peer') -export const TRANSPORT = '/webrtc-direct' -export const PROTOCOL = '/webrtc-direct/0.0.1' +// TODO(ckousik): This is the wrong protocol name and code. They +// will be changed to /webrtc-direct, /webrtc-direct/0.0.1, and 281 +// respectively once https://github.com/multiformats/js-multiaddr/pull/309 +// is merged. +export const TRANSPORT = '/p2p-webrtc-direct' +export const PROTOCOL = '/p2p-webrtc-direct/0.0.1' export const CODE = 276 export interface WebRTCPeerTransportInit { @@ -49,9 +53,6 @@ export class WebRTCDirectTransport implements Transport, Startable { await this.components.registrar.handle(PROTOCOL, (data) => { this._onProtocol(data).catch(err => log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err)) }) - // this.components.peerStore.addEventListener('change:multiaddrs', (event) => { - // const { peerId } = event.detail - // }) } async stop () { @@ -80,25 +81,34 @@ export class WebRTCDirectTransport implements Transport, Startable { /* * dial connects to a remote via the circuit relay or any other protocol * and proceeds to upgrade to a webrtc connection. - * multiaddr of the form: /webrtc-peer/p2p/ + * multiaddr of the form: /webrtc-direct/p2p/ * For a circuit relay, this will be of the form * /p2p//p2p-circuit/webrtc-direct/p2p/ */ async dial (ma: Multiaddr, options: DialOptions): Promise { log.trace('dialing address: ', ma) const addrs = ma.toString().split(TRANSPORT) + if (addrs.length !== 2) { + // TODO(ckousik): Change to errCode + throw new Error('invalid multiaddr') + } // look for remote peerId - let relayed = multiaddr(addrs[0]) - const remotePeerId = ma.getPeerId() - if (remotePeerId != null) { - relayed = relayed.encapsulate(multiaddr(`/p2p/${remotePeerId}`)) + const remoteAddr = multiaddr(addrs[0]) + const destination = multiaddr(addrs[1]) + + const destinationIdString = destination.getPeerId() + if (destinationIdString == null) { + // TODO(ckousik): Change to errCode + throw new Error('bad destination') } + const controller = new AbortController() if (options.signal == null) { options.signal = controller.signal } - const connection = await this.components.transportManager.dial(relayed) + const connection = await this.components.transportManager.dial(remoteAddr) + const rawStream = await connection.newStream([PROTOCOL], options) const pc = await connect({ @@ -107,7 +117,9 @@ export class WebRTCDirectTransport implements Transport, Startable { signal: options.signal }) - const result = options.upgrader.upgradeOutbound( + rawStream.close() + void connection.close() + return await options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ peerConnection: pc, timeline: { open: (new Date()).getTime() }, @@ -120,11 +132,7 @@ export class WebRTCDirectTransport implements Transport, Startable { } ) // close streams - rawStream.close() - void connection.close() // TODO: hack - // await new Promise(res => setTimeout(res, 100)) - return await result } async _onProtocol ({ connection, stream }: IncomingStreamData) { diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 08d4087..a00420a 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -1,11 +1,14 @@ -import { mockConnection, mockMultiaddrConnection, mockStream } from '@libp2p/interface-mocks' +import { mockConnection, mockMultiaddrConnection, mockRegistrar, mockStream, mockUpgrader } from '@libp2p/interface-mocks' import { createEd25519PeerId } from '@libp2p/peer-id-factory' +import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import { pair } from 'it-pair' import { duplexPair } from 'it-pair/duplex' import { pbStream } from 'it-pb-stream' +import sinon from 'sinon' import { connect, handleIncomingStream } from '../src/peer_transport/handler' import { Message } from '../src/peer_transport/pb/index.js' +import { WebRTCDirectTransport } from '../src/peer_transport/transport' describe('webrtc direct basic', () => { it('should connect', async () => { @@ -123,4 +126,24 @@ describe('webrtc direct dialer', () => { }) }) +// TODO(ckousik): This test will fail until https://github.com/multiformats/js-multiaddr/pull/309 +// is merged. +describe.skip('webrtc direct filter', () => { + it('can filter multiaddrs to dial', async () => { + const transport = new WebRTCDirectTransport({ + transportManager: sinon.stub() as any, + peerId: sinon.stub() as any, + registrar: mockRegistrar(), + upgrader: mockUpgrader(), + peerStore: sinon.stub() as any + }, {}) + + const valid = [ + multiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p-circuit/webrtc-direct') + ] + + expect(transport.filter(valid)).length(1) + }) +}) + export { } From f786bdbd8fe7d1900a7143562b7ddaa2c0edb9ca Mon Sep 17 00:00:00 2001 From: David DiMaria Date: Tue, 14 Feb 2023 07:02:04 -0700 Subject: [PATCH 11/52] Attempt to fix example --- examples/browser-to-browser/index.js | 10 +++++++++- examples/browser-to-browser/package.json | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index f6e4e2a..e50c4d7 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -41,6 +41,7 @@ await node.start() // handle the echo protocol await node.handle('/echo/1.0.0', ({ stream, connection }) => { + console.log(stream) void pipe(stream, stream) }) @@ -53,16 +54,23 @@ node.peerStore.addEventListener('change:multiaddrs', (event) => { if (ma.protoCodes().includes(290)) { const webrtcDirectAddress = ma.encapsulate(multiaddr(`/p2p-webrtc-direct/p2p/${node.peerId}`)) appendOutput(`Listening on ${webrtcDirectAddress}`) + sendSection.style.display = 'block' } }) }) window.connect.onclick = async () => { - const ma = multiaddr(document.getElementById("peer").value) + const ma = multiaddr(window.peer.value) appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) console.log('dial completed') stream = await connection.newStream(['/echo/1.0.0']) + pipe(sender, stream, async (src) => { + for await(const buf of src) { + const response = toString(buf.subarray()) + appendOutput(`Received message '${clean(response)}'`) + } + }) console.log('stream', stream) } diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 1c93527..63c7858 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "vite", "build": "vite build", - "go-libp2p-server": "cd ../go-libp2p-server && go run ./main.go", + "go-libp2p-server": "cd ../go-libp2p-server && go run ./relay.go", "test": "npm run build && playwright test tests" }, "dependencies": { From 5a08ed78f2d986521f71aa66e9ce68ebf372a2b9 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 14 Feb 2023 20:10:35 +0530 Subject: [PATCH 12/52] race condition --- examples/browser-to-browser/index.js | 4 ++-- src/peer_transport/transport.ts | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index e50c4d7..2ed295c 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -40,7 +40,7 @@ const node = await createLibp2p({ await node.start() // handle the echo protocol -await node.handle('/echo/1.0.0', ({ stream, connection }) => { +await node.handle('/echo/1.0.0', ({ stream }) => { console.log(stream) void pipe(stream, stream) }) @@ -64,7 +64,7 @@ window.connect.onclick = async () => { appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) console.log('dial completed') - stream = await connection.newStream(['/echo/1.0.0']) + stream = await connection.newStream(['/echo/1.0.0']).catch((err) => console.log(err)) pipe(sender, stream, async (src) => { for await(const buf of src) { const response = toString(buf.subarray()) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 2735a15..baa1024 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -119,6 +119,11 @@ export class WebRTCDirectTransport implements Transport, Startable { rawStream.close() void connection.close() + // TODO(ckousik): Remove this delay. This is required because + // after the connection is initiated, there is a race condition + // between creating a new stream and the remote having the datachannel + // callbacks, and onStream callbacks set up. + await new Promise((resolve) => setTimeout(resolve, 100)) return await options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ peerConnection: pc, @@ -131,8 +136,6 @@ export class WebRTCDirectTransport implements Transport, Startable { muxerFactory: new DataChannelMuxerFactory(pc, TRANSPORT) } ) - // close streams - // TODO: hack } async _onProtocol ({ connection, stream }: IncomingStreamData) { From 0ba969c4e2d8fe59dcd163990027451cfd97740e Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 15 Feb 2023 19:18:58 +0530 Subject: [PATCH 13/52] buffer incoming streams before upgrade --- examples/browser-to-browser/README.md | 8 +- examples/browser-to-browser/index.js | 17 ++- examples/browser-to-browser/package.json | 2 +- examples/go-libp2p-server/go.mod | 6 +- examples/go-libp2p-server/relay.go | 127 ----------------------- examples/go-libp2p-server/relay/main.go | 61 +++++++++++ src/muxer.ts | 45 +++++++- src/peer_transport/handler.ts | 12 ++- src/peer_transport/transport.ts | 14 +-- src/stream.ts | 8 ++ test/peer.browser.spec.ts | 2 +- 11 files changed, 143 insertions(+), 159 deletions(-) delete mode 100644 examples/go-libp2p-server/relay.go create mode 100644 examples/go-libp2p-server/relay/main.go diff --git a/examples/browser-to-browser/README.md b/examples/browser-to-browser/README.md index fb3d997..de5e465 100644 --- a/examples/browser-to-browser/README.md +++ b/examples/browser-to-browser/README.md @@ -2,15 +2,15 @@ This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. -## Running the Go Server +## Running a relay -To run the Go LibP2P WebRTC server: +To run the Go LibP2P relay: ```shell -npm run go-libp2p-server +npm run go-relay ``` -Copy the multiaddress in the output. +Copy one of the multiaddress in the output. ## Running the Example diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 2ed295c..2e2cffb 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -41,8 +41,14 @@ await node.start() // handle the echo protocol await node.handle('/echo/1.0.0', ({ stream }) => { - console.log(stream) - void pipe(stream, stream) + console.log('handling stream: ', stream) + void pipe(stream, async function * (source) { + for await (const buf of source) { + const incoming = toString(buf.subarray()) + appendOutput('Received from remote: ' + incoming) + yield buf + } + },stream) }) node.peerStore.addEventListener('change:multiaddrs', (event) => { @@ -64,14 +70,17 @@ window.connect.onclick = async () => { appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) console.log('dial completed') - stream = await connection.newStream(['/echo/1.0.0']).catch((err) => console.log(err)) + if (!ma.protoCodes().includes(276)) { + return + } + stream = await connection.newStream(['/echo/1.0.0']) pipe(sender, stream, async (src) => { for await(const buf of src) { const response = toString(buf.subarray()) appendOutput(`Received message '${clean(response)}'`) } }) - console.log('stream', stream) + console.log('created stream', stream) } window.send.onclick = async () => { diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 63c7858..2eba47d 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "vite", "build": "vite build", - "go-libp2p-server": "cd ../go-libp2p-server && go run ./relay.go", + "go-relay": "cd ../go-libp2p-server && go run ./relay", "test": "npm run build && playwright test tests" }, "dependencies": { diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index 4d51311..b87c3fb 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -4,7 +4,10 @@ go 1.18 replace github.com/libp2p/go-libp2p => github.com/ckousik/go-libp2p v0.24.3-0.20230114095059-115caff3ca87 -require github.com/libp2p/go-libp2p v0.23.2 +require ( + github.com/libp2p/go-libp2p v0.23.2 + github.com/multiformats/go-multiaddr v0.8.0 +) require ( github.com/benbjohnson/clock v1.3.0 // indirect @@ -60,7 +63,6 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr v0.8.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.1.1 // indirect diff --git a/examples/go-libp2p-server/relay.go b/examples/go-libp2p-server/relay.go deleted file mode 100644 index 71654fd..0000000 --- a/examples/go-libp2p-server/relay.go +++ /dev/null @@ -1,127 +0,0 @@ -package main - -import ( - "bufio" - "crypto/rand" - "fmt" - "log" - "net" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/network" - - // "github.com/libp2p/go-libp2p/core/peer" - "github.com/libp2p/go-libp2p/p2p/muxer/mplex" - relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" - webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" - ma "github.com/multiformats/go-multiaddr" -) - -var listenerIp = net.IPv4(127, 0, 0, 1) - -func init() { - ifaces, err := net.Interfaces() - if err != nil { - return - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue - } - addrs, err := iface.Addrs() - if err != nil { - return - } - for _, addr := range addrs { - // bind to private non-loopback ip - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { - if ipnet.IP.To4() != nil { - listenerIp = ipnet.IP.To4() - return - } - } - } - } -} - -func echoHandler(stream network.Stream) { - for { - reader := bufio.NewReader(stream) - str, err := reader.ReadString('\n') - log.Printf("err: %s", err) - if err != nil { - return - } - log.Printf("echo: %s", str) - _, err = stream.Write([]byte(str)) - if err != nil { - log.Printf("err: %v", err) - return - } - } -} - -func main() { - makeRelayV1() - fmt.Println("press Ctrl+C to quit") - select{} -} - -func createHost() host.Host { - h, err := libp2p.New( - libp2p.Transport(webrtc.New), - libp2p.ListenAddrStrings( - fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), - ), - libp2p.DisableRelay(), - libp2p.Ping(true), - ) - if err != nil { - panic(err) - } - - return h -} - -func makeRelayV1() host.Host { - r := rand.Reader - // Generate a key pair for this host. We will use it at least - // to obtain a valid host ID. - priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r) - if err != nil { - panic(err) - } - - opts := []libp2p.Option{ - libp2p.DefaultTransports, - libp2p.ListenAddrStrings( - "/ip4/0.0.0.0/tcp/4003/ws", - ), - libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), - libp2p.Identity(priv), - libp2p.EnableRelay(), - } - - host, err := libp2p.New(opts...) - if err != nil { - panic(err) - } - - _, err = relay.NewRelay(host) - if err != nil { - panic(err) - } - - fmt.Println(host.Mux().Protocols()) - - for _, addr := range host.Addrs() { - a, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", host.ID().Pretty())) - if err != nil { - panic(err) - } - fmt.Println(addr.Encapsulate(a)) - } - return host -} diff --git a/examples/go-libp2p-server/relay/main.go b/examples/go-libp2p-server/relay/main.go new file mode 100644 index 0000000..f991084 --- /dev/null +++ b/examples/go-libp2p-server/relay/main.go @@ -0,0 +1,61 @@ +package main + +import ( + "crypto/rand" + "fmt" + + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/host" + + // "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/muxer/mplex" + relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" + ma "github.com/multiformats/go-multiaddr" +) + +func main() { + makeRelayV1() + select {} +} + +func makeRelayV1() host.Host { + r := rand.Reader + // Generate a key pair for this host. We will use it at least + // to obtain a valid host ID. + priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r) + if err != nil { + panic(err) + } + + opts := []libp2p.Option{ + libp2p.DefaultTransports, + libp2p.ListenAddrStrings( + "/ip4/0.0.0.0/tcp/4003/ws", + ), + libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), + libp2p.Identity(priv), + libp2p.EnableRelay(), + } + + host, err := libp2p.New(opts...) + if err != nil { + panic(err) + } + + _, err = relay.NewRelay(host) + if err != nil { + panic(err) + } + + fmt.Println(host.Mux().Protocols()) + + for _, addr := range host.Addrs() { + a, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", host.ID().Pretty())) + if err != nil { + panic(err) + } + fmt.Println(addr.Encapsulate(a)) + } + return host +} diff --git a/src/muxer.ts b/src/muxer.ts index c1276dc..7484878 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -10,18 +10,29 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory { * WebRTC Peer Connection */ private readonly peerConnection: RTCPeerConnection + private streamBuffer: WebRTCStream[] = [] constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc') { this.peerConnection = peerConnection // reject any datachannels as the muxer is not yet ready to process // streams this.peerConnection.ondatachannel = ({ channel }) => { - channel.close() + const stream = new WebRTCStream({ + channel, + stat: { + direction: 'inbound', + timeline: { open: 0 } + }, + closeCb: (_stream) => { + this.streamBuffer = this.streamBuffer.filter(s => !_stream.eq(s)) + } + }) + this.streamBuffer.push(stream) } } createStreamMuxer (init?: StreamMuxerInit | undefined): StreamMuxer { - return new DataChannelMuxer(this.peerConnection, this.protocol, init) + return new DataChannelMuxer(this.peerConnection, this.streamBuffer, this.protocol, init) } } @@ -59,7 +70,7 @@ export class DataChannelMuxer implements StreamMuxer { */ sink: Sink> = nopSink; - constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc', init?: StreamMuxerInit) { + constructor (peerConnection: RTCPeerConnection, streams: Stream[], readonly protocol = '/webrtc', init?: StreamMuxerInit) { /** * Initialized stream muxer */ @@ -85,12 +96,25 @@ export class DataChannelMuxer implements StreamMuxer { open: 0 } }, - closeCb: init?.onStreamEnd + closeCb: this.wrapStreamEnd(init?.onIncomingStream) }) if ((init?.onIncomingStream) != null) { init.onIncomingStream(stream) } + this.streams.push(stream) + } + + if (init?.onIncomingStream != null) { + streams.forEach((_stream) => { + if (_stream.stat.timeline.close != null) { + return + } + (_stream as WebRTCStream).closeCb = this.wrapStreamEnd(init.onStreamEnd) + this.streams.push(_stream) + // @ts-expect-error + void Promise.resolve().then(() => init?.onIncomingStream(_stream)) + }) } } @@ -105,9 +129,20 @@ export class DataChannelMuxer implements StreamMuxer { open: 0 } }, - closeCb: this.init?.onStreamEnd + closeCb: this.wrapStreamEnd(this.init?.onStreamEnd) }) + this.streams.push(stream) return stream } + + private wrapStreamEnd (onStreamEnd?: (s: Stream) => void): (stream: Stream) => void { + const self = this + return (_stream) => { + self.streams = self.streams.filter(s => !(_stream instanceof WebRTCStream && (_stream).eq(s))) + if (onStreamEnd != null) { + onStreamEnd(_stream) + } + } + } } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index d4357a7..97ea707 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -7,6 +7,8 @@ import * as pb from './pb/index.js' import { abortableDuplex } from 'abortable-iterator' import { logger } from '@libp2p/logger' import type { Stream } from '@libp2p/interface-connection' +import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer' +import { DataChannelMuxerFactory } from '../muxer' const DEFAULT_TIMEOUT = 30 * 1000 @@ -14,11 +16,12 @@ const log = logger('libp2p:webrtc:peer') export type IncomingStreamOpts = { rtcConfiguration?: RTCConfiguration } & IncomingStreamData -export async function handleIncomingStream ({ rtcConfiguration, stream: rawStream }: IncomingStreamOpts): Promise { +export async function handleIncomingStream ({ rtcConfiguration, stream: rawStream }: IncomingStreamOpts): Promise<[RTCPeerConnection, StreamMuxerFactory]> { const timeoutController = new TimeoutController(DEFAULT_TIMEOUT) const signal = timeoutController.signal const stream = pbStream(abortableDuplex(rawStream, timeoutController.signal)).pb(pb.Message) const pc = new RTCPeerConnection(rtcConfiguration) + const muxerFactory = new DataChannelMuxerFactory(pc) const connectedPromise: DeferredPromise = pDefer() signal.onabort = () => connectedPromise.reject() @@ -71,7 +74,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea await readCandidatesUntilConnected(connectedPromise, pc, stream) // close the dummy channel channel.close() - return pc + return [pc, muxerFactory] } export interface ConnectOptions { @@ -80,11 +83,12 @@ export interface ConnectOptions { rtcConfiguration?: RTCConfiguration } -export async function connect ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise { +export async function connect ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise<[RTCPeerConnection, StreamMuxerFactory]> { const stream = pbStream(abortableDuplex(rawStream, signal)).pb(pb.Message) // setup peer connection const pc = new RTCPeerConnection(rtcConfiguration) + const muxerFactory = new DataChannelMuxerFactory(pc) // the label is not relevant to connection initiation but can be // useful for debugging @@ -129,6 +133,6 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: await pc.setLocalDescription(answerSdp) await readCandidatesUntilConnected(connectedPromise, pc, stream) - return pc + return [pc, muxerFactory] } export { } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index baa1024..6f356a3 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -6,7 +6,6 @@ import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' import type { PeerId } from '@libp2p/interface-peer-id' import { WebRTCMultiaddrConnection } from '../maconn.js' import type { Startable } from '@libp2p/interfaces/startable' -import { DataChannelMuxerFactory } from '../muxer.js' import { WebRTCPeerListener } from './listener.js' import type { PeerStore } from '@libp2p/interface-peer-store' import { logger } from '@libp2p/logger' @@ -111,19 +110,13 @@ export class WebRTCDirectTransport implements Transport, Startable { const rawStream = await connection.newStream([PROTOCOL], options) - const pc = await connect({ + const [pc, muxerFactory] = await connect({ stream: rawStream, rtcConfiguration: this.init.rtcConfiguration, signal: options.signal }) rawStream.close() - void connection.close() - // TODO(ckousik): Remove this delay. This is required because - // after the connection is initiated, there is a race condition - // between creating a new stream and the remote having the datachannel - // callbacks, and onStream callbacks set up. - await new Promise((resolve) => setTimeout(resolve, 100)) return await options.upgrader.upgradeOutbound( new WebRTCMultiaddrConnection({ peerConnection: pc, @@ -133,18 +126,17 @@ export class WebRTCDirectTransport implements Transport, Startable { { skipProtection: true, skipEncryption: true, - muxerFactory: new DataChannelMuxerFactory(pc, TRANSPORT) + muxerFactory } ) } async _onProtocol ({ connection, stream }: IncomingStreamData) { - const pc = await handleIncomingStream({ + const [pc, muxerFactory] = await handleIncomingStream({ rtcConfiguration: this.init.rtcConfiguration, connection, stream }) - const muxerFactory = new DataChannelMuxerFactory(pc, '/webrtc-direct') const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, timeline: { open: (new Date()).getTime() }, diff --git a/src/stream.ts b/src/stream.ts index 71a20d9..01ba5b2 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -455,4 +455,12 @@ export class WebRTCStream implements Stream { } } } + + eq (stream: Stream): boolean { + if (stream instanceof WebRTCStream) { + const s = stream + return s.channel.id === this.channel.id + } + return false + } } diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index a00420a..91d7a00 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -22,7 +22,7 @@ describe('webrtc direct basic', () => { const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) await expect(initiatorPeerConnectionPromise).to.be.fulfilled() await expect(receiverPeerConnectionPromise).to.be.fulfilled() - const [pc0, pc1] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) + const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) expect(pc0.connectionState).eq('connected') expect(pc1.connectionState).eq('connected') }) From e1bf7de76c52ce2aded6882d7dc23775f0f7ab40 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 15 Feb 2023 19:49:25 +0530 Subject: [PATCH 14/52] update stream protocol name --- src/peer_transport/transport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 6f356a3..77a341b 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -18,7 +18,7 @@ const log = logger('libp2p:webrtc:peer') // respectively once https://github.com/multiformats/js-multiaddr/pull/309 // is merged. export const TRANSPORT = '/p2p-webrtc-direct' -export const PROTOCOL = '/p2p-webrtc-direct/0.0.1' +export const PROTOCOL = '/webrtc-signaling/0.0.1' export const CODE = 276 export interface WebRTCPeerTransportInit { From eafad87a5f3c7281e4b03524641673e7e5cdbe43 Mon Sep 17 00:00:00 2001 From: David DiMaria Date: Fri, 17 Feb 2023 16:32:10 -0700 Subject: [PATCH 15/52] Complete the browser-to-browser example --- examples/browser-to-browser/README.md | 51 +++++++++++---- examples/browser-to-browser/dialer.js | 31 --------- examples/browser-to-browser/index.html | 4 +- examples/browser-to-browser/index.js | 80 ++++++++++++++---------- examples/browser-to-browser/package.json | 1 + 5 files changed, 91 insertions(+), 76 deletions(-) delete mode 100644 examples/browser-to-browser/dialer.js diff --git a/examples/browser-to-browser/README.md b/examples/browser-to-browser/README.md index de5e465..a3e514d 100644 --- a/examples/browser-to-browser/README.md +++ b/examples/browser-to-browser/README.md @@ -1,16 +1,22 @@ -# js-libp2p-webrtc Browser to Server +# js-libp2p-webrtc Browser to Browser This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. -## Running a relay +## Running the Relay Server -To run the Go LibP2P relay: +For browsers to communicate, we first need to run the Go LibP2P relay server: ```shell npm run go-relay ``` -Copy one of the multiaddress in the output. +Alternatively, a NodeJS relay server is available: + +```shell +npm run node-relay +``` + +Copy one of the multiaddresses in the output. ## Running the Example @@ -20,15 +26,38 @@ In a separate console tab, install dependencies and start the Vite server: npm i && npm run start ``` -The browser window will automatically open. -Using the copied multiaddress from the Go server, paste it into the `Server MultiAddress` input and click the `Connect` button. -Once the peer is connected, click the message section will appear. Enter a message and click the `Send` button. +The browser window will automatically open. Let's call this `Browser A`. +Using the copied multiaddress from the Go or NodeJS relay server, paste it into the `Remote MultiAddress` input and click the `Connect` button. +`Browser A` is now connected to the relay server. +Copy the multiaddress located after the `Listening on` message. + +Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`. +Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button. +`Browser B` is now connected to `Browser A`. +Copy the multiaddress located after the `Listening on` message. + +Using the copied multiaddress from `Listening on` section in `Browser B`, paste it into the `Remote MultiAddress` input in `Browser A` and click the `Connect` button. +`Browser A` is now connected to `Browser B`. + +The peers are now connected to each other. Enter a message and click the `Send` button in either/both browsers and see the echo'd messages. The output should look like: +`Browser A` +```text +Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk' +Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-webrtc-direct/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC +Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-webrtc-direct/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9' +Sending message 'helloa' +Received message 'helloa' +Received message 'hellob' +``` + +`Browser B` ```text -Dialing /ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb -Peer connected '/ip4/10.0.1.5/udp/54375/webrtc/certhash/uEiADy8JubdWrAzseyzfXFyCpdRN02eWZg86tjCrTCA5dbQ/p2p/12D3KooWEG7N4bnZfFBNZE7WG6xm2P4Sr6sonMwyD4HCAqApEthb' -Sending message 'hello' -Received message 'hello' +Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-webrtc-direct/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC' +Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-webrtc-direct/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9 +Received message 'helloa' +Sending message 'hellob' +Received message 'hellob' ``` \ No newline at end of file diff --git a/examples/browser-to-browser/dialer.js b/examples/browser-to-browser/dialer.js deleted file mode 100644 index d6f7af5..0000000 --- a/examples/browser-to-browser/dialer.js +++ /dev/null @@ -1,31 +0,0 @@ -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' -import { multiaddr } from '@multiformats/multiaddr' - -async function main () { - const autoRelayNodeAddr = process.argv[2] - if (!autoRelayNodeAddr) { - throw new Error('the auto relay node address needs to be specified') - } - - const node = await createLibp2p({ - transports: [ - webSockets() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - mplex() - ] - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - - const conn = await node.dial(multiaddr(autoRelayNodeAddr)) - console.log(`Connected to the auto relay node via ${conn.remoteAddr.toString()}`) -} - -main() \ No newline at end of file diff --git a/examples/browser-to-browser/index.html b/examples/browser-to-browser/index.html index 62374cf..6030d8e 100644 --- a/examples/browser-to-browser/index.html +++ b/examples/browser-to-browser/index.html @@ -17,7 +17,7 @@ #send-section { display: none; } - input[type='text'] { + input[type="text"] { width: 800px; } @@ -25,7 +25,7 @@
- +
diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 2e2cffb..4f8428d 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -1,23 +1,26 @@ -import { multiaddr } from '@multiformats/multiaddr' -import { pipe } from "it-pipe"; -import { fromString, toString } from "uint8arrays"; -import { webRTCDirect } from 'js-libp2p-webrtc' -import { webSockets } from '@libp2p/websockets' -import * as filters from '@libp2p/websockets/filters' -import { pushable } from 'it-pushable'; -import { mplex } from '@libp2p/mplex' -import { createLibp2p } from 'libp2p'; -import { noise } from '@chainsafe/libp2p-noise'; +import { multiaddr } from "@multiformats/multiaddr" +import { pipe } from "it-pipe" +import { fromString, toString } from "uint8arrays" +import { webRTCDirect } from "js-libp2p-webrtc" +import { webSockets } from "@libp2p/websockets" +import * as filters from "@libp2p/websockets/filters" +import { pushable } from "it-pushable" +import { mplex } from "@libp2p/mplex" +import { createLibp2p } from "libp2p" +import { noise } from "@chainsafe/libp2p-noise" -let stream; -const output = document.getElementById('output') -const sendSection = document.getElementById('send-section') +// singletons +let outgoing_stream +let webrtcDirectAddress + +const output = document.getElementById("output") +const sendSection = document.getElementById("send-section") const appendOutput = (line) => { const div = document.createElement("div") div.appendChild(document.createTextNode(line)) output.append(div) } -const clean = (line) => line.replaceAll('\n', '') +const clean = (line) => line.replaceAll("\n", "") const sender = pushable() const node = await createLibp2p({ @@ -40,27 +43,39 @@ const node = await createLibp2p({ await node.start() // handle the echo protocol -await node.handle('/echo/1.0.0', ({ stream }) => { - console.log('handling stream: ', stream) - void pipe(stream, async function * (source) { - for await (const buf of source) { - const incoming = toString(buf.subarray()) - appendOutput('Received from remote: ' + incoming) - yield buf - } - },stream) +await node.handle("/echo/1.0.0", ({ stream }) => { + pipe( + stream, + async function* (source) { + for await (const buf of source) { + const incoming = toString(buf.subarray()) + appendOutput(`Received message '${clean(incoming)}'`) + yield buf + } + }, + stream + ) }) -node.peerStore.addEventListener('change:multiaddrs', (event) => { +node.peerStore.addEventListener("change:multiaddrs", (event) => { const { peerId } = event.detail + if (node.getMultiaddrs().length === 0 || !node.peerId.equals(peerId)) { return } + node.getMultiaddrs().forEach((ma) => { if (ma.protoCodes().includes(290)) { - const webrtcDirectAddress = ma.encapsulate(multiaddr(`/p2p-webrtc-direct/p2p/${node.peerId}`)) - appendOutput(`Listening on ${webrtcDirectAddress}`) - sendSection.style.display = 'block' + const newWebrtcDirectAddress = ma.encapsulate( + multiaddr(`/p2p-webrtc-direct/p2p/${node.peerId}`) + ) + + // only update if the address is new + if (newWebrtcDirectAddress?.toString() !== webrtcDirectAddress?.toString()) { + appendOutput(`Listening on ${newWebrtcDirectAddress}`) + sendSection.style.display = "block" + webrtcDirectAddress = newWebrtcDirectAddress + } } }) }) @@ -69,18 +84,19 @@ window.connect.onclick = async () => { const ma = multiaddr(window.peer.value) appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) - console.log('dial completed') + if (!ma.protoCodes().includes(276)) { return } - stream = await connection.newStream(['/echo/1.0.0']) - pipe(sender, stream, async (src) => { - for await(const buf of src) { + + outgoing_stream = await connection.newStream(["/echo/1.0.0"]) + + pipe(sender, outgoing_stream, async (src) => { + for await (const buf of src) { const response = toString(buf.subarray()) appendOutput(`Received message '${clean(response)}'`) } }) - console.log('created stream', stream) } window.send.onclick = async () => { diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 2eba47d..f1d4df7 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -7,6 +7,7 @@ "start": "vite", "build": "vite build", "go-relay": "cd ../go-libp2p-server && go run ./relay", + "node-relay": "node relay.js", "test": "npm run build && playwright test tests" }, "dependencies": { From 40d72fbf2b5c42ad6c8fd2104a0729096d77ffb4 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 22 Feb 2023 04:42:25 +0530 Subject: [PATCH 16/52] address review --- src/muxer.ts | 25 ++++++----- src/peer_transport/transport.ts | 74 ++++++++++++++++++++------------- src/stream.ts | 1 - 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/muxer.ts b/src/muxer.ts index 7484878..5ef7629 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -14,8 +14,7 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory { constructor (peerConnection: RTCPeerConnection, readonly protocol = '/webrtc') { this.peerConnection = peerConnection - // reject any datachannels as the muxer is not yet ready to process - // streams + // store any datachannels opened before upgrade has been completed this.peerConnection.ondatachannel = ({ channel }) => { const stream = new WebRTCStream({ channel, @@ -58,7 +57,7 @@ export class DataChannelMuxer implements StreamMuxer { /** * Close or abort all tracked streams and stop the muxer */ - close: (err?: Error | undefined) => void = () => {} + close: (err?: Error | undefined) => void = () => { } /** * The stream source, a no-op as the transport natively supports multiplexing @@ -99,22 +98,22 @@ export class DataChannelMuxer implements StreamMuxer { closeCb: this.wrapStreamEnd(init?.onIncomingStream) }) + this.streams.push(stream) if ((init?.onIncomingStream) != null) { init.onIncomingStream(stream) } - this.streams.push(stream) } - if (init?.onIncomingStream != null) { - streams.forEach((_stream) => { - if (_stream.stat.timeline.close != null) { - return - } - (_stream as WebRTCStream).closeCb = this.wrapStreamEnd(init.onStreamEnd) - this.streams.push(_stream) - // @ts-expect-error - void Promise.resolve().then(() => init?.onIncomingStream(_stream)) + // wrap open streams with the onStreamEnd callback + this.streams = streams + .filter(stream => stream.stat.timeline.close == null) + .map(stream => { + (stream as WebRTCStream).closeCb = this.wrapStreamEnd(init?.onStreamEnd) + return stream }) + const onIncomingStream = init?.onIncomingStream + if (onIncomingStream != null) { + this.streams.forEach(s => onIncomingStream(s)) } } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 77a341b..3aa833a 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -110,43 +110,57 @@ export class WebRTCDirectTransport implements Transport, Startable { const rawStream = await connection.newStream([PROTOCOL], options) - const [pc, muxerFactory] = await connect({ - stream: rawStream, - rtcConfiguration: this.init.rtcConfiguration, - signal: options.signal - }) + try { + const [pc, muxerFactory] = await connect({ + stream: rawStream, + rtcConfiguration: this.init.rtcConfiguration, + signal: options.signal + }) + const result = await options.upgrader.upgradeOutbound( + new WebRTCMultiaddrConnection({ + peerConnection: pc, + timeline: { open: (new Date()).getTime() }, + remoteAddr: connection.remoteAddr + }), + { + skipProtection: true, + skipEncryption: true, + muxerFactory + } + ) + + // close the stream if SDP has been exchanged successfully + rawStream.close() + return result + } catch (err) { + // reset the stream in case of any error + rawStream.reset() + throw err + } + } - rawStream.close() - return await options.upgrader.upgradeOutbound( - new WebRTCMultiaddrConnection({ + async _onProtocol ({ connection, stream }: IncomingStreamData) { + let conn + try { + const [pc, muxerFactory] = await handleIncomingStream({ + rtcConfiguration: this.init.rtcConfiguration, + connection, + stream + }) + conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, timeline: { open: (new Date()).getTime() }, remoteAddr: connection.remoteAddr - }), - { - skipProtection: true, + }), { skipEncryption: true, + skipProtection: true, muxerFactory - } - ) - } + }) + } catch (err) { + stream.reset() + throw err + } - async _onProtocol ({ connection, stream }: IncomingStreamData) { - const [pc, muxerFactory] = await handleIncomingStream({ - rtcConfiguration: this.init.rtcConfiguration, - connection, - stream - }) - const conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ - peerConnection: pc, - timeline: { open: (new Date()).getTime() }, - remoteAddr: connection.remoteAddr - }), { - skipEncryption: true, - skipProtection: true, - muxerFactory - }) - stream.close() if (this.handler != null) { this.handler(conn) } diff --git a/src/stream.ts b/src/stream.ts index 01ba5b2..8d48bef 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -7,7 +7,6 @@ import { pushable } from 'it-pushable' import defer, { DeferredPromise } from 'p-defer' import type { Source } from 'it-stream-types' import { Uint8ArrayList } from 'uint8arraylist' -// import { toString as uint8arrayToString } from 'uint8arrays/to-string' import * as pb from '../proto_ts/message.js' From c24fb7ed8ecbe7926d40033205d736fb24a2a6dc Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 22 Feb 2023 04:50:27 +0530 Subject: [PATCH 17/52] clarify circuit relay code usage --- examples/browser-to-browser/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 4f8428d..609eb5d 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -80,12 +80,15 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { }) }) +const CIRCUIT_RELAY_CODE = 276 +const isCircuitRelayMultiaddr = (ma) => ma.protoCodes().includes(CIRCUIT_RELAY_CODE) + window.connect.onclick = async () => { const ma = multiaddr(window.peer.value) appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) - if (!ma.protoCodes().includes(276)) { + if (!isCircuitRelayMultiaddr(ma)) { return } From df5ce02c7bee85e9dc5f2f1e3ff6088a95c4f917 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 22 Feb 2023 05:00:00 +0530 Subject: [PATCH 18/52] fix lint --- src/error.ts | 18 +++++++++--------- src/maconn.ts | 8 ++++---- src/muxer.ts | 6 +++--- src/peer_transport/handler.ts | 6 +++--- src/peer_transport/listener.ts | 28 ++++++++++++++-------------- src/peer_transport/transport.ts | 10 +++++----- src/peer_transport/util.ts | 2 +- src/sdp.ts | 3 ++- src/stream.ts | 22 +++++++++++----------- src/util.ts | 2 +- test/maconn.browser.spec.ts | 2 +- test/stream.browser.spec.ts | 2 +- test/util.ts | 2 +- 13 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/error.ts b/src/error.ts index fe05ec1..d0b5285 100644 --- a/src/error.ts +++ b/src/error.ts @@ -28,7 +28,7 @@ export class ConnectionClosedError extends WebRTCTransportError { } } -export function connectionClosedError (state: RTCPeerConnectionState, msg: string) { +export function connectionClosedError (state: RTCPeerConnectionState, msg: string): Error { return errCode(new ConnectionClosedError(state, msg), codes.ERR_CONNECTION_CLOSED) } @@ -39,7 +39,7 @@ export class DataChannelError extends WebRTCTransportError { } } -export function dataChannelError (streamLabel: string, msg: string) { +export function dataChannelError (streamLabel: string, msg: string): Error { return errCode(new DataChannelError(streamLabel, msg), codes.ERR_DATA_CHANNEL) } @@ -50,7 +50,7 @@ export class InappropriateMultiaddrError extends WebRTCTransportError { } } -export function inappropriateMultiaddr (msg: string) { +export function inappropriateMultiaddr (msg: string): Error { return errCode(new InappropriateMultiaddrError(msg), codes.ERR_INVALID_MULTIADDR) } @@ -61,7 +61,7 @@ export class InvalidArgumentError extends WebRTCTransportError { } } -export function invalidArgument (msg: string) { +export function invalidArgument (msg: string): Error { return errCode(new InvalidArgumentError(msg), codes.ERR_INVALID_PARAMETERS) } @@ -72,7 +72,7 @@ export class InvalidFingerprintError extends WebRTCTransportError { } } -export function invalidFingerprint (fingerprint: string, source: string) { +export function invalidFingerprint (fingerprint: string, source: string): Error { return errCode(new InvalidFingerprintError(fingerprint, source), codes.ERR_INVALID_FINGERPRINT) } @@ -83,7 +83,7 @@ export class OperationAbortedError extends WebRTCTransportError { } } -export function operationAborted (context: string, reason: string) { +export function operationAborted (context: string, reason: string): Error { return errCode(new OperationAbortedError(context, reason), codes.ERR_ALREADY_ABORTED) } @@ -94,7 +94,7 @@ export class OverStreamLimitError extends WebRTCTransportError { } } -export function overStreamLimit (dir: Direction, proto: string) { +export function overStreamLimit (dir: Direction, proto: string): Error { const code = dir === 'inbound' ? codes.ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS : codes.ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS return errCode(new OverStreamLimitError(`${dir} stream limit reached for protocol - ${proto}`), code) } @@ -106,7 +106,7 @@ export class UnimplementedError extends WebRTCTransportError { } } -export function unimplemented (methodName: string) { +export function unimplemented (methodName: string): Error { return errCode(new UnimplementedError(methodName), codes.ERR_NOT_IMPLEMENTED) } @@ -118,6 +118,6 @@ export class UnsupportedHashAlgorithmError extends WebRTCTransportError { } } -export function unsupportedHashAlgorithm (algorithm: string) { +export function unsupportedHashAlgorithm (algorithm: string): Error { return errCode(new UnsupportedHashAlgorithmError(algorithm), codes.ERR_HASH_NOT_SUPPORTED) } diff --git a/src/maconn.ts b/src/maconn.ts index 49c67e1..0814874 100644 --- a/src/maconn.ts +++ b/src/maconn.ts @@ -28,17 +28,17 @@ export class WebRTCMultiaddrConnection implements MultiaddrConnection { /** * WebRTC Peer Connection */ - readonly peerConnection: RTCPeerConnection; + readonly peerConnection: RTCPeerConnection /** * The multiaddr address used to communicate with the remote peer */ - remoteAddr: Multiaddr; + remoteAddr: Multiaddr /** * Holds the lifecycle times of the connection */ - timeline: MultiaddrConnectionTimeline; + timeline: MultiaddrConnectionTimeline /** * The stream source, a no-op as the transport natively supports multiplexing @@ -48,7 +48,7 @@ export class WebRTCMultiaddrConnection implements MultiaddrConnection { /** * The stream destination, a no-op as the transport natively supports multiplexing */ - sink: Sink> = nopSink; + sink: Sink> = nopSink constructor (init: WebRTCMultiaddrConnectionInit) { this.remoteAddr = init.remoteAddr diff --git a/src/muxer.ts b/src/muxer.ts index 5ef7629..b1b55be 100644 --- a/src/muxer.ts +++ b/src/muxer.ts @@ -62,12 +62,12 @@ export class DataChannelMuxer implements StreamMuxer { /** * The stream source, a no-op as the transport natively supports multiplexing */ - source: Source = nopSource; + source: Source = nopSource /** * The stream destination, a no-op as the transport natively supports multiplexing */ - sink: Sink> = nopSink; + sink: Sink> = nopSink constructor (peerConnection: RTCPeerConnection, streams: Stream[], readonly protocol = '/webrtc', init?: StreamMuxerInit) { /** @@ -113,7 +113,7 @@ export class DataChannelMuxer implements StreamMuxer { }) const onIncomingStream = init?.onIncomingStream if (onIncomingStream != null) { - this.streams.forEach(s => onIncomingStream(s)) + this.streams.forEach(s => { onIncomingStream(s) }) } } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 97ea707..530ee78 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -24,7 +24,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea const muxerFactory = new DataChannelMuxerFactory(pc) const connectedPromise: DeferredPromise = pDefer() - signal.onabort = () => connectedPromise.reject() + signal.onabort = () => { connectedPromise.reject() } // candidate callbacks pc.onicecandidate = ({ candidate }) => { stream.write({ @@ -96,11 +96,11 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: pc.onconnectionstatechange = (_) => { switch (pc.connectionState) { case 'connected': - return connectedPromise.resolve() + { connectedPromise.resolve(); return } case 'closed': case 'disconnected': case 'failed': - return connectedPromise.reject() + { connectedPromise.reject(); break } default: } } diff --git a/src/peer_transport/listener.ts b/src/peer_transport/listener.ts index f2be808..6eca4cf 100644 --- a/src/peer_transport/listener.ts +++ b/src/peer_transport/listener.ts @@ -17,19 +17,19 @@ export class WebRTCPeerListener extends EventEmitter implements super() } - private listeningAddrs: Multiaddr[] = [] - async listen (ma: Multiaddr): Promise { - const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) - const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) - const listener = tpt?.createListener({ ...this.opts }) - await listener?.listen(baseAddr) - const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId.toString()}`) - this.listeningAddrs.push(listeningAddr) - listener?.addEventListener('close', () => { - this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) - }) - } + private listeningAddrs: Multiaddr[] = [] + async listen (ma: Multiaddr): Promise { + const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) + const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) + const listener = tpt?.createListener({ ...this.opts }) + await listener?.listen(baseAddr) + const listeningAddr = ma.encapsulate(`/p2p/${this.opts.peerId.toString()}`) + this.listeningAddrs.push(listeningAddr) + listener?.addEventListener('close', () => { + this.listeningAddrs = this.listeningAddrs.filter(a => a !== listeningAddr) + }) + } - getAddrs (): Multiaddr[] { return this.listeningAddrs } - async close () { } + getAddrs (): Multiaddr[] { return this.listeningAddrs } + async close (): Promise { } } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 3aa833a..c610f05 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -44,17 +44,17 @@ export class WebRTCDirectTransport implements Transport, Startable { this._onProtocol = this._onProtocol.bind(this) } - isStarted () { + isStarted (): boolean { return this._started } - async start () { + async start (): Promise { await this.components.registrar.handle(PROTOCOL, (data) => { - this._onProtocol(data).catch(err => log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err)) + this._onProtocol(data).catch(err => { log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) }) }) } - async stop () { + async stop (): Promise { await this.components.registrar.unhandle(PROTOCOL) } @@ -139,7 +139,7 @@ export class WebRTCDirectTransport implements Transport, Startable { } } - async _onProtocol ({ connection, stream }: IncomingStreamData) { + async _onProtocol ({ connection, stream }: IncomingStreamData): Promise { let conn try { const [pc, muxerFactory] = await handleIncomingStream({ diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index 7efb152..d9ba4ed 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -9,7 +9,7 @@ interface MessageStream { const log = logger('libp2p:webrtc:peer:util') -export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream) => { +export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream): Promise => { while (true) { const readResult = await Promise.race([connectedPromise.promise, stream.read()]) // check if readResult is a message diff --git a/src/sdp.ts b/src/sdp.ts index fc5632e..8c3b6c6 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -2,6 +2,7 @@ import { logger } from '@libp2p/logger' import type { Multiaddr } from '@multiformats/multiaddr' import { bases } from 'multiformats/basics' import * as multihashes from 'multihashes' +import type { HashCode, HashName } from 'multihashes' import { inappropriateMultiaddr, invalidArgument, invalidFingerprint, unsupportedHashAlgorithm } from './error.js' import { CERTHASH_CODE } from './transport.js' @@ -44,7 +45,7 @@ export function certhash (ma: Multiaddr): string { /** * Convert a certhash into a multihash */ -export function decodeCerthash (certhash: string) { +export function decodeCerthash (certhash: string): { code: HashCode, name: HashName, length: number, digest: Uint8Array } { const mbdecoded = mbdecoder.decode(certhash) return multihashes.decode(mbdecoded) } diff --git a/src/stream.ts b/src/stream.ts index 8d48bef..ae77edd 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -156,55 +156,55 @@ export class WebRTCStream implements Stream { /** * Unique identifier for a stream */ - id: string; + id: string /** * Stats about this stream */ - stat: StreamStat; + stat: StreamStat /** * User defined stream metadata */ - metadata: Record; + metadata: Record /** * The data channel used to send and receive data */ - private readonly channel: RTCDataChannel; + private readonly channel: RTCDataChannel /** * The current state of the stream */ - streamState = new StreamState(); + streamState = new StreamState() /** * Read unwrapped protobuf data from the underlying datachannel. * _src is exposed to the user via the `source` getter to . */ - private readonly _src: Source; + private readonly _src: Source /** * push data from the underlying datachannel to the length prefix decoder * and then the protobuf decoder. */ - private readonly _innersrc = pushable(); + private readonly _innersrc = pushable() /** * Deferred promise that resolves when the underlying datachannel is in the * open state. */ - opened: DeferredPromise = defer(); + opened: DeferredPromise = defer() /** * sinkCreated is set to true once the sinkFunction is invoked */ - _sinkCalled: boolean = false; + _sinkCalled: boolean = false /** * Triggers a generator which can be used to close the sink. */ - closeWritePromise: DeferredPromise = defer(); + closeWritePromise: DeferredPromise = defer() /** * Callback to invoke when the stream is closed. @@ -436,7 +436,7 @@ export class WebRTCStream implements Stream { private _sendFlag (flag: pb.Message_Flag): void { try { log.trace('Sending flag: %s', flag.toString()) - const msgbuf = pb.Message.toBinary({ flag: flag }) + const msgbuf = pb.Message.toBinary({ flag }) this.channel.send(lengthPrefixed.encode.single(msgbuf).subarray()) } catch (err) { if (err instanceof Error) { diff --git a/src/util.ts b/src/util.ts index 0270d36..71cf481 100644 --- a/src/util.ts +++ b/src/util.ts @@ -2,7 +2,7 @@ export const nopSource = { async * [Symbol.asyncIterator] () {} } -export const nopSink = async (_: any) => {} +export const nopSink = async (_: any): Promise => {} const charset = Array.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') export const genUfrag = (len: number): string => [...Array(len)].map(() => charset.at(Math.floor(Math.random() * charset.length))).join('') diff --git a/test/maconn.browser.spec.ts b/test/maconn.browser.spec.ts index ffc68f7..9db987f 100644 --- a/test/maconn.browser.spec.ts +++ b/test/maconn.browser.spec.ts @@ -10,7 +10,7 @@ describe('Multiaddr Connection', () => { peerConnection.createDataChannel('whatever', { negotiated: true, id: 91 }) const remoteAddr = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ') const maConn = new WebRTCMultiaddrConnection({ - peerConnection: peerConnection, + peerConnection, remoteAddr, timeline: { open: (new Date()).getTime() diff --git a/test/stream.browser.spec.ts b/test/stream.browser.spec.ts index 89cab56..ce606cb 100644 --- a/test/stream.browser.spec.ts +++ b/test/stream.browser.spec.ts @@ -14,7 +14,7 @@ function setup (): { peerConnection: RTCPeerConnection, datachannel: RTCDataChan function generatePbByFlag (flag?: pb.Message_Flag): Uint8Array { const testPb: pb.Message = { - flag: flag, + flag, message: bytes.fromString(TEST_MESSAGE) } return pb.Message.toBinary(testPb) diff --git a/test/util.ts b/test/util.ts index e13bbf7..70c492b 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,6 +1,6 @@ import { expect } from 'aegir/chai' -export const expectError = (error: unknown, message: string) => { +export const expectError = (error: unknown, message: string): void => { if (error instanceof Error) { expect(error.message).to.equal(message) } else { From 20e7c28ea7b19e22351c9e0d2a6df3260e02596e Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 22 Feb 2023 05:07:45 +0530 Subject: [PATCH 19/52] add explicit eslint dependency --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index d239b79..df85ac6 100644 --- a/package.json +++ b/package.json @@ -173,6 +173,7 @@ "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "aegir": "^38.1.6", + "eslint-plugin-etc": "^2.0.2", "it-first": "^2.0.0", "it-pair": "^2.0.3", "libp2p": "^0.41.0", From 8ea980b8c7ed023c20bdb9cc6016543f2dfd9d59 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Wed, 22 Feb 2023 05:12:47 +0530 Subject: [PATCH 20/52] fix dependencies --- package.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index df85ac6..54bd642 100644 --- a/package.json +++ b/package.json @@ -140,17 +140,17 @@ "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/interface-connection": "^3.0.2", "@libp2p/interface-peer-id": "^2.0.0", + "@libp2p/interface-peer-store": "^1.2.8", + "@libp2p/interface-registrar": "^2.0.8", "@libp2p/interface-stream-muxer": "^3.0.0", "@libp2p/interface-transport": "^2.0.0", "@libp2p/interfaces": "^3.3.1", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^2.0.0", - "@multiformats/mafmt": "^11.0.3", "@multiformats/multiaddr": "^11.0.3", "@protobuf-ts/runtime": "^2.8.0", "abortable-iterator": "^4.0.2", "err-code": "^3.0.1", - "it-handshake": "^4.1.2", "it-length-prefixed": "^8.0.3", "it-merge": "^2.0.0", "it-pb-stream": "^2.0.3", @@ -167,16 +167,12 @@ }, "devDependencies": { "@libp2p/interface-mocks": "^9.0.0", - "@libp2p/mplex": "^7.1.1", "@libp2p/peer-id-factory": "^2.0.0", - "@libp2p/websockets": "^5.0.3", "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "aegir": "^38.1.6", "eslint-plugin-etc": "^2.0.2", - "it-first": "^2.0.0", "it-pair": "^2.0.3", - "libp2p": "^0.41.0", "protons": "^6.0.1", "sinon": "^15.0.1" } From d622b277a052193b47d29366290868dc5bca554f Mon Sep 17 00:00:00 2001 From: David DiMaria Date: Wed, 22 Feb 2023 15:49:45 -0700 Subject: [PATCH 21/52] Implement single browser for browser-to-browser in CI --- examples/browser-to-browser/index.html | 1 + examples/browser-to-browser/index.js | 4 +++- examples/browser-to-browser/package.json | 1 + examples/browser-to-browser/tests/test.js | 26 +++++++++++++--------- examples/go-libp2p-server/relay/.gitignore | 1 + examples/go-libp2p-server/relay/main.go | 4 ++-- 6 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 examples/go-libp2p-server/relay/.gitignore diff --git a/examples/browser-to-browser/index.html b/examples/browser-to-browser/index.html index 6030d8e..7f2374b 100644 --- a/examples/browser-to-browser/index.html +++ b/examples/browser-to-browser/index.html @@ -34,6 +34,7 @@
+
diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 609eb5d..659c95b 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -15,6 +15,7 @@ let webrtcDirectAddress const output = document.getElementById("output") const sendSection = document.getElementById("send-section") +const peer = document.getElementById("peer") const appendOutput = (line) => { const div = document.createElement("div") div.appendChild(document.createTextNode(line)) @@ -72,9 +73,10 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { // only update if the address is new if (newWebrtcDirectAddress?.toString() !== webrtcDirectAddress?.toString()) { - appendOutput(`Listening on ${newWebrtcDirectAddress}`) + appendOutput(`Listening on '${newWebrtcDirectAddress}'`) sendSection.style.display = "block" webrtcDirectAddress = newWebrtcDirectAddress + connected_peer.innerText = webrtcDirectAddress } } }) diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index f1d4df7..2956c10 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -13,6 +13,7 @@ "dependencies": { "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/websockets": "^5.0.3", + "@libp2p/mplex": "^7.0.0", "@multiformats/multiaddr": "^11.0.5", "it-pushable": "^3.1.0", "js-libp2p-webrtc": "file:../../", diff --git a/examples/browser-to-browser/tests/test.js b/examples/browser-to-browser/tests/test.js index 13f80cd..260f5bc 100644 --- a/examples/browser-to-browser/tests/test.js +++ b/examples/browser-to-browser/tests/test.js @@ -10,10 +10,10 @@ const play = test.extend({ }) async function spawnGoLibp2p() { - if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server')) { + if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server/relay')) { await new Promise((resolve, reject) => { exec('go build', - { cwd: '../../examples/go-libp2p-server' }, + { cwd: '../../examples/go-libp2p-server/relay' }, (error, stdout, stderr) => { if (error) { throw (`exec error: ${error}`) @@ -23,7 +23,7 @@ async function spawnGoLibp2p() { }) } - const server = spawn('./go-libp2p-server', [], { cwd: '../../examples/go-libp2p-server', killSignal: 'SIGINT' }) + const server = spawn('./relay', [], { cwd: '../../examples/go-libp2p-server/relay', killSignal: 'SIGINT' }) server.stderr.on('data', (data) => { console.log(`stderr: ${data}`, typeof data) }) @@ -39,10 +39,11 @@ async function spawnGoLibp2p() { return { server, serverAddr } } -play.describe('bundle ipfs with parceljs:', () => { +play.describe('browser to browser example:', () => { // DOM const connectBtn = '#connect' const connectAddr = '#peer' + const connectPeerAddr = '#connected_peer' const messageInput = '#message' const sendBtn = '#send' const output = '#output' @@ -65,11 +66,10 @@ play.describe('bundle ipfs with parceljs:', () => { play.beforeEach(async ({ servers, page }) => { const url = `http://localhost:${servers[0].port}/` - console.log(url) await page.goto(url) }) - play('should connect to a go-libp2p node over webtransport', async ({ page }) => { + play('should connect to a go-libp2p relay node', async ({ page }) => { const message = 'hello' // add the go libp2p multiaddress to the input field and submit @@ -85,13 +85,19 @@ play.describe('bundle ipfs with parceljs:', () => { // Expected output: // // Dialing '${serverAddr}' - // Peer connected '${serverAddr}' + // Peer connected '${peer}' // Sending message '${message}' // Received message '${message}' const connections = await page.textContent(output) + + + await page.waitForSelector('#connected_peer:contains(ip)') + const peer = await page.textContent(connectPeerAddr) expect(connections).toContain(`Dialing '${serverAddr}'`) - expect(connections).toContain(`Peer connected '${serverAddr}'`) + expect(connections).toContain(`Listening on '${peer}'`) + + // TODO(ddimaria) load second page and use ${peer} as the connectAddr expect(connections).toContain(`Sending message '${message}'`) - expect(connections).toContain(`Received message '${message}'`) + // expect(connections).toContain(`Received message '${message}'`) }) -}) \ No newline at end of file +}) diff --git a/examples/go-libp2p-server/relay/.gitignore b/examples/go-libp2p-server/relay/.gitignore new file mode 100644 index 0000000..38200f1 --- /dev/null +++ b/examples/go-libp2p-server/relay/.gitignore @@ -0,0 +1 @@ +relay \ No newline at end of file diff --git a/examples/go-libp2p-server/relay/main.go b/examples/go-libp2p-server/relay/main.go index f991084..7a6f179 100644 --- a/examples/go-libp2p-server/relay/main.go +++ b/examples/go-libp2p-server/relay/main.go @@ -48,14 +48,14 @@ func makeRelayV1() host.Host { panic(err) } - fmt.Println(host.Mux().Protocols()) + // fmt.Println(host.Mux().Protocols()) for _, addr := range host.Addrs() { a, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", host.ID().Pretty())) if err != nil { panic(err) } - fmt.Println(addr.Encapsulate(a)) + fmt.Println("p2p addr: ", addr.Encapsulate(a)) } return host } From ddad0469fb34e31567a790ebadf0a36463b25dbd Mon Sep 17 00:00:00 2001 From: David DiMaria Date: Wed, 22 Feb 2023 16:27:53 -0700 Subject: [PATCH 22/52] Complete playwright test for communicating browsers and add to CI --- .github/workflows/examples.yml | 1 + examples/browser-to-browser/tests/test.js | 75 ++++++++++++++--------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index b9381fc..d5474fc 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -20,6 +20,7 @@ jobs: matrix: project: - browser-to-server + - browser-to-browser defaults: run: working-directory: examples/${{ matrix.project }} diff --git a/examples/browser-to-browser/tests/test.js b/examples/browser-to-browser/tests/test.js index 260f5bc..bcbbeb0 100644 --- a/examples/browser-to-browser/tests/test.js +++ b/examples/browser-to-browser/tests/test.js @@ -9,6 +9,18 @@ const play = test.extend({ ...playwright.servers() }) + +// DOM +const connectBtn = '#connect' +const connectAddr = '#peer' +const connectPeerAddr = '#connected_peer' +const messageInput = '#message' +const sendBtn = '#send' +const output = '#output' + +const message = 'hello' +let url + async function spawnGoLibp2p() { if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server/relay')) { await new Promise((resolve, reject) => { @@ -40,40 +52,36 @@ async function spawnGoLibp2p() { } play.describe('browser to browser example:', () => { - // DOM - const connectBtn = '#connect' - const connectAddr = '#peer' - const connectPeerAddr = '#connected_peer' - const messageInput = '#message' - const sendBtn = '#send' - const output = '#output' - let server let serverAddr // eslint-disable-next-line no-empty-pattern - play.beforeAll(async ({ }, testInfo) => { + play.beforeAll(async ({ servers }, testInfo) => { testInfo.setTimeout(5 * 60_000) const s = await spawnGoLibp2p() server = s.server serverAddr = s.serverAddr console.log('Server addr:', serverAddr) + url = `http://localhost:${servers[0].port}/` }, {}) play.afterAll(() => { server.kill('SIGINT') }) - play.beforeEach(async ({ servers, page }) => { - const url = `http://localhost:${servers[0].port}/` + play.beforeEach(async ({ page }) => { await page.goto(url) }) - play('should connect to a go-libp2p relay node', async ({ page }) => { - const message = 'hello' - - // add the go libp2p multiaddress to the input field and submit - await page.fill(connectAddr, serverAddr) + play('should connect to a go-libp2p relay node', async ({ page, context }) => { + let peer = await per_page(page, serverAddr) + + // load second page and use `peer` as the connectAddr + const pageTwo = await context.newPage(); + await pageTwo.goto(url) + let newPeer = await per_page(pageTwo, peer) + + await page.fill(connectAddr, newPeer) await page.click(connectBtn) // send the relay message to the go libp2p server @@ -81,23 +89,34 @@ play.describe('browser to browser example:', () => { await page.click(sendBtn) await page.waitForSelector('#output:has(div)') + const connections = await page.textContent(output) // Expected output: // - // Dialing '${serverAddr}' - // Peer connected '${peer}' // Sending message '${message}' // Received message '${message}' - const connections = await page.textContent(output) - - - await page.waitForSelector('#connected_peer:contains(ip)') - const peer = await page.textContent(connectPeerAddr) - expect(connections).toContain(`Dialing '${serverAddr}'`) - expect(connections).toContain(`Listening on '${peer}'`) - - // TODO(ddimaria) load second page and use ${peer} as the connectAddr expect(connections).toContain(`Sending message '${message}'`) - // expect(connections).toContain(`Received message '${message}'`) + expect(connections).toContain(`Received message '${message}'`) }) }) + +async function per_page(page, address) { + // add the go libp2p multiaddress to the input field and submit + await page.fill(connectAddr, address) + await page.click(connectBtn) + await page.fill(messageInput, message) + + await page.waitForSelector('#output:has(div)') + + // Expected output: + // + // Dialing '${serverAddr}' + // Listening on '${peer}' + const connections = await page.textContent(output) + const peer = await page.textContent(connectPeerAddr) + + expect(connections).toContain(`Dialing '${address}'`) + expect(connections).toContain(`Listening on '${peer}'`) + + return peer +} From 602adc9567f5f042c2305c7b5f69f237b7f69879 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 24 Feb 2023 21:54:32 +0530 Subject: [PATCH 23/52] wrap errors --- src/peer_transport/handler.ts | 22 ++++++++++++++++++---- src/peer_transport/util.ts | 7 ++++++- test/peer.browser.spec.ts | 4 ++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 530ee78..c7ae24c 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -55,7 +55,11 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea // create and write an SDP offer const offer = await pc.createOffer() - await pc.setLocalDescription(offer) + await pc.setLocalDescription(offer).catch(err => { + log.error('could not execute setLocalDescription', err) + throw new Error('Failed to set localDescription') + }) + stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) // read an SDP anwer @@ -68,7 +72,11 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea type: 'answer', sdp: pbAnswer.data }) - await pc.setRemoteDescription(answer) + + await pc.setRemoteDescription(answer).catch(err => { + log.error('could not execute setRemoteDescription', err) + throw new Error('Failed to set remoteDescription') + }) // wait until candidates are connected await readCandidatesUntilConnected(connectedPromise, pc, stream) @@ -123,14 +131,20 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: } const offerSdp = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) - await pc.setRemoteDescription(offerSdp) + await pc.setRemoteDescription(offerSdp).catch(err => { + log.error('could not execute setRemoteDescription', err) + throw new Error('Failed to set remoteDescription') + }) // create an answer const answerSdp = await pc.createAnswer() // write the answer to the stream stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) // set answer as local description - await pc.setLocalDescription(answerSdp) + await pc.setLocalDescription(answerSdp).catch(err => { + log.error('could not execute setLocalDescription', err) + throw new Error('Failed to set localDescription') + }) await readCandidatesUntilConnected(connectedPromise, pc, stream) return [pc, muxerFactory] diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index d9ba4ed..e95fe3f 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -25,7 +25,12 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro } log.trace('received new ICE candidate: %s', message.data) - await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) + try { + await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(message.data))) + } catch (err) { + log.error('bad candidate received: ', err) + throw new Error('bad candidate received') + } } else { // connected promise resolved break diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 91d7a00..867a9c9 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -48,7 +48,7 @@ describe('webrtc direct receiver', () => { } stream.write({ type: Message.Type.SDP_ANSWER, data: 'bad' }) - await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/Failed to execute 'setRemoteDescription'/) + await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/Failed to set remoteDescription/) }) it('should fail on receiving candidate before answer', async () => { @@ -122,7 +122,7 @@ describe('webrtc direct dialer', () => { const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) const stream = pbStream(receiver).pb(Message) stream.write({ type: Message.Type.SDP_OFFER, data: 'bad' }) - await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/Failed to execute 'setRemoteDescription'/) + await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/Failed to set remoteDescription/) }) }) From c8c288817473d8b3d48c60ede50a54c22ef49c23 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Mon, 6 Mar 2023 18:00:56 +0530 Subject: [PATCH 24/52] fix connection initiation --- src/peer_transport/handler.ts | 75 ++++++++++++------------- test/peer.browser.spec.ts | 103 ++++++++++------------------------ 2 files changed, 67 insertions(+), 111 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index c7ae24c..254d775 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -49,39 +49,35 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea break } } - // we create the channel so that the peerconnection has a component for - // which to collect candidates - const channel = pc.createDataChannel('init') - - // create and write an SDP offer - const offer = await pc.createOffer() - await pc.setLocalDescription(offer).catch(err => { - log.error('could not execute setLocalDescription', err) - throw new Error('Failed to set localDescription') - }) - - stream.write({ type: pb.Message.Type.SDP_OFFER, data: offer.sdp }) - - // read an SDP anwer - const pbAnswer = await stream.read() - if (pbAnswer.type !== pb.Message.Type.SDP_ANSWER) { + // read an SDP offer + const pbOffer = await stream.read() + if (pbOffer.type !== pb.Message.Type.SDP_OFFER) { // TODO: Find better way to print undefined without linter complaining - throw new Error(`expected message type SDP_ANSWER, received: ${pbAnswer.type ?? 'undefined'} `) + throw new Error(`expected message type SDP_OFFER, received: ${pbOffer.type ?? 'undefined'} `) } - const answer = new RTCSessionDescription({ - type: 'answer', - sdp: pbAnswer.data + const offer = new RTCSessionDescription({ + type: 'offer', + sdp: pbOffer.data }) - await pc.setRemoteDescription(answer).catch(err => { + await pc.setRemoteDescription(offer).catch(err => { log.error('could not execute setRemoteDescription', err) throw new Error('Failed to set remoteDescription') }) + // create and write an SDP answer + const answer = await pc.createAnswer() + // write the answer to the remote + stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answer.sdp }) + + await pc.setLocalDescription(answer).catch(err => { + log.error('could not execute setLocalDescription', err) + throw new Error('Failed to set localDescription') + }) + // wait until candidates are connected await readCandidatesUntilConnected(connectedPromise, pc, stream) // close the dummy channel - channel.close() return [pc, muxerFactory] } @@ -115,6 +111,9 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: // reject the connectedPromise if the signal aborts signal.onabort = connectedPromise.reject + // we create the channel so that the peerconnection has a component for + // which to collect candidates + const channel = pc.createDataChannel('init') // setup callback to write ICE candidates to the remote // peer pc.onicecandidate = ({ candidate }) => { @@ -123,30 +122,30 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' }) } + // create an offer + const offerSdp = await pc.createOffer() + // write the offer to the stream + stream.write({ type: pb.Message.Type.SDP_OFFER, data: offerSdp.sdp }) + // set offer as local description + await pc.setLocalDescription(offerSdp).catch(err => { + log.error('could not execute setLocalDescription', err) + throw new Error('Failed to set localDescription') + }) - // read offer - const offerMessage = await stream.read() - if (offerMessage.type !== pb.Message.Type.SDP_OFFER) { - throw new Error('remote should send an SDP offer') + // read answer + const answerMessage = await stream.read() + if (answerMessage.type !== pb.Message.Type.SDP_ANSWER) { + throw new Error('remote should send an SDP answer') } - const offerSdp = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) - await pc.setRemoteDescription(offerSdp).catch(err => { + const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data }) + await pc.setRemoteDescription(answerSdp).catch(err => { log.error('could not execute setRemoteDescription', err) throw new Error('Failed to set remoteDescription') }) - // create an answer - const answerSdp = await pc.createAnswer() - // write the answer to the stream - stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answerSdp.sdp }) - // set answer as local description - await pc.setLocalDescription(answerSdp).catch(err => { - log.error('could not execute setLocalDescription', err) - throw new Error('Failed to set localDescription') - }) - await readCandidatesUntilConnected(connectedPromise, pc, stream) + channel.close() return [pc, muxerFactory] } export { } diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 867a9c9..b813caa 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -10,7 +10,7 @@ import { connect, handleIncomingStream } from '../src/peer_transport/handler' import { Message } from '../src/peer_transport/pb/index.js' import { WebRTCDirectTransport } from '../src/peer_transport/transport' -describe('webrtc direct basic', () => { +describe('webrtc-w3c basic', () => { it('should connect', async () => { const [receiver, initiator] = duplexPair() const dstPeerId = await createEd25519PeerId() @@ -28,8 +28,8 @@ describe('webrtc direct basic', () => { }) }) -describe('webrtc direct receiver', () => { - it('should fail receiving on invalid sdp answer', async () => { +describe('webrtc-w3c receiver', () => { + it('should fail receiving on invalid sdp offer', async () => { const [receiver, initiator] = duplexPair() const dstPeerId = await createEd25519PeerId() const connection = mockConnection( @@ -37,92 +37,49 @@ describe('webrtc direct receiver', () => { ) const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) const stream = pbStream(initiator).pb(Message) - const offerSDP = await stream.read() - expect(offerSDP.data).to.not.be.undefined() - expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) - // check SDP - { - const pc = new RTCPeerConnection() - const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) - await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() - } - stream.write({ type: Message.Type.SDP_ANSWER, data: 'bad' }) + stream.write({ type: Message.Type.SDP_OFFER, data: 'bad' }) await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/Failed to set remoteDescription/) }) +}) - it('should fail on receiving candidate before answer', async () => { +describe('webrtc-w3c dialer', () => { + it('should fail receiving on invalid sdp answer', async () => { const [receiver, initiator] = duplexPair() - const dstPeerId = await createEd25519PeerId() - const connection = mockConnection( - mockMultiaddrConnection(pair(), dstPeerId) - ) - const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) - const stream = pbStream(initiator).pb(Message) - const offerSDP = await stream.read() - expect(offerSDP.data).to.not.be.undefined() - expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) - // check SDP + const controller = new AbortController() + const initiatorPeerConnectionPromise = connect({ signal: controller.signal, stream: mockStream(initiator) }) + const stream = pbStream(receiver).pb(Message) + { - const pc = new RTCPeerConnection() - const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) - await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() - // set up a callback to write a candidate - pc.onicecandidate = ({ candidate }) => { - stream.write({ - type: Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate) : '' - }) - } - // set the answer - const answer = await pc.createAnswer() - await pc.setLocalDescription(answer) + const offerMessage = await stream.read() + expect(offerMessage.type).to.eq(Message.Type.SDP_OFFER) } - await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/expected message type SDP_ANSWER/) + stream.write({ type: Message.Type.SDP_ANSWER, data: 'bad' }) + await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/Failed to set remoteDescription/) }) - it('should fail on receiving invalid candidate', async () => { + it('should fail on receiving a candidate before an answer', async () => { const [receiver, initiator] = duplexPair() - const dstPeerId = await createEd25519PeerId() - const connection = mockConnection( - mockMultiaddrConnection(pair(), dstPeerId) - ) - const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) - const stream = pbStream(initiator).pb(Message) - const offerSDP = await stream.read() - expect(offerSDP.data).to.not.be.undefined() - expect(offerSDP.type).to.eq(Message.Type.SDP_OFFER) - // check SDP + const controller = new AbortController() + const initiatorPeerConnectionPromise = connect({ signal: controller.signal, stream: mockStream(initiator) }) + const stream = pbStream(receiver).pb(Message) + + const pc = new RTCPeerConnection() + pc.onicecandidate = ({ candidate }) => { + stream.write({ type: Message.Type.ICE_CANDIDATE, data: JSON.stringify(candidate?.toJSON()) }) + } { - const pc = new RTCPeerConnection() - const offer = new RTCSessionDescription({ type: 'offer', sdp: offerSDP.data }) - await expect(pc.setRemoteDescription(offer)).to.be.fulfilled() - // create the answer + const offerMessage = await stream.read() + expect(offerMessage.type).to.eq(Message.Type.SDP_OFFER) + const offer = new RTCSessionDescription({ type: 'offer', sdp: offerMessage.data }) + await pc.setRemoteDescription(offer) + const answer = await pc.createAnswer() - // write the answer - stream.write({ type: Message.Type.SDP_ANSWER, data: answer.sdp }) - // set answer as local description await pc.setLocalDescription(answer) - // send broken candidate - stream.write({ - type: Message.Type.ICE_CANDIDATE, - data: 'bad candidate' - }) } - await expect(receiverPeerConnectionPromise).to.be.rejectedWith(/bad candidate/) - }) -}) - -describe('webrtc direct dialer', () => { - it('should fail on invalid sdp offer', async () => { - const [receiver, initiator] = duplexPair() - const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) - const stream = pbStream(receiver).pb(Message) - stream.write({ type: Message.Type.SDP_OFFER, data: 'bad' }) - await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/Failed to set remoteDescription/) + await expect(initiatorPeerConnectionPromise).to.be.rejectedWith(/remote should send an SDP answer/) }) }) From 41c8e2d2b403b8a6fc89d4e53ee48aafa45c6a0f Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Mon, 6 Mar 2023 18:03:30 +0530 Subject: [PATCH 25/52] unskip filter test --- package.json | 2 +- src/peer_transport/transport.ts | 6 +++--- test/peer.browser.spec.ts | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 54bd642..534b046 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ "@libp2p/interfaces": "^3.3.1", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^2.0.0", - "@multiformats/multiaddr": "^11.0.3", + "@multiformats/multiaddr": "^11.5.0", "@protobuf-ts/runtime": "^2.8.0", "abortable-iterator": "^4.0.2", "err-code": "^3.0.1", diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index c610f05..51b3ca9 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -17,9 +17,9 @@ const log = logger('libp2p:webrtc:peer') // will be changed to /webrtc-direct, /webrtc-direct/0.0.1, and 281 // respectively once https://github.com/multiformats/js-multiaddr/pull/309 // is merged. -export const TRANSPORT = '/p2p-webrtc-direct' +export const TRANSPORT = '/webrtc-w3c' export const PROTOCOL = '/webrtc-signaling/0.0.1' -export const CODE = 276 +export const CODE = 281 export interface WebRTCPeerTransportInit { rtcConfiguration?: RTCConfiguration @@ -63,7 +63,7 @@ export class WebRTCDirectTransport implements Transport, Startable { } get [Symbol.toStringTag] (): string { - return '@libp2p/webrtc-direct' + return '@libp2p/webrtc-w3c' } get [symbol] (): true { diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index b813caa..2f38900 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -83,9 +83,7 @@ describe('webrtc-w3c dialer', () => { }) }) -// TODO(ckousik): This test will fail until https://github.com/multiformats/js-multiaddr/pull/309 -// is merged. -describe.skip('webrtc direct filter', () => { +describe('webrtc-w3c filter', () => { it('can filter multiaddrs to dial', async () => { const transport = new WebRTCDirectTransport({ transportManager: sinon.stub() as any, @@ -96,7 +94,7 @@ describe.skip('webrtc direct filter', () => { }, {}) const valid = [ - multiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p-circuit/webrtc-direct') + multiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p-circuit/webrtc-w3c') ] expect(transport.filter(valid)).length(1) From 40fd90c90e723c893dabbf1a5c7d69b448c3e2ef Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 7 Mar 2023 21:37:09 +0530 Subject: [PATCH 26/52] fix Go version to 1.19 for compiling go-libp2p --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index d5474fc..91d5fdd 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -31,7 +31,7 @@ jobs: node-version: lts/* - uses: actions/setup-go@v3 with: - go-version: '>=1.19.0' + go-version: '1.19' - name: Install dependencies run: npm install working-directory: . @@ -45,4 +45,4 @@ jobs: - name: Run tests run: npm run test env: - CI: true \ No newline at end of file + CI: true From d4a68585da504e9235a228ba1d6a5d0306dc3dba Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 7 Mar 2023 22:17:05 +0530 Subject: [PATCH 27/52] fix protocol codes and update multiaddr library --- examples/browser-to-browser/index.js | 15 ++++++++++----- examples/browser-to-browser/package.json | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index 659c95b..ac94e98 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -13,6 +13,9 @@ import { noise } from "@chainsafe/libp2p-noise" let outgoing_stream let webrtcDirectAddress +const CIRCUIT_RELAY_CODE = 290 +const WEBRTC_W3C_CODE = 281 + const output = document.getElementById("output") const sendSection = document.getElementById("send-section") const peer = document.getElementById("peer") @@ -45,6 +48,7 @@ await node.start() // handle the echo protocol await node.handle("/echo/1.0.0", ({ stream }) => { + console.log("incoming stream") pipe( stream, async function* (source) { @@ -66,9 +70,9 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { } node.getMultiaddrs().forEach((ma) => { - if (ma.protoCodes().includes(290)) { + if (ma.protoCodes().includes(CIRCUIT_RELAY_CODE)) { const newWebrtcDirectAddress = ma.encapsulate( - multiaddr(`/p2p-webrtc-direct/p2p/${node.peerId}`) + multiaddr(`/webrtc-w3c/p2p/${node.peerId}`) ) // only update if the address is new @@ -82,15 +86,16 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { }) }) -const CIRCUIT_RELAY_CODE = 276 -const isCircuitRelayMultiaddr = (ma) => ma.protoCodes().includes(CIRCUIT_RELAY_CODE) +const isWebrtcW3C = (ma) => { + return ma.protoCodes().includes(WEBRTC_W3C_CODE) +} window.connect.onclick = async () => { const ma = multiaddr(window.peer.value) appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) - if (!isCircuitRelayMultiaddr(ma)) { + if (!isWebrtcW3C(ma)) { return } diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 2956c10..2f2c834 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -14,7 +14,7 @@ "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/websockets": "^5.0.3", "@libp2p/mplex": "^7.0.0", - "@multiformats/multiaddr": "^11.0.5", + "@multiformats/multiaddr": "^11.5.0", "it-pushable": "^3.1.0", "js-libp2p-webrtc": "file:../../", "libp2p": "^0.42.0", From 0b6a80f4e62b62a9d9fc7adc7466695e1b0519c7 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 7 Mar 2023 22:32:43 +0530 Subject: [PATCH 28/52] skip localhost test on firefox --- package.json | 1 + test/peer.browser.spec.ts | 35 ++++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index fcf286b..ecef22b 100644 --- a/package.json +++ b/package.json @@ -171,6 +171,7 @@ "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "aegir": "^38.1.6", + "detect-browser": "^5.3.0", "eslint-plugin-etc": "^2.0.2", "it-pair": "^2.0.3", "protons": "^6.0.1", diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 2f38900..78b7c2b 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -9,23 +9,28 @@ import sinon from 'sinon' import { connect, handleIncomingStream } from '../src/peer_transport/handler' import { Message } from '../src/peer_transport/pb/index.js' import { WebRTCDirectTransport } from '../src/peer_transport/transport' +import { detect } from 'detect-browser' + +const browser = detect() describe('webrtc-w3c basic', () => { - it('should connect', async () => { - const [receiver, initiator] = duplexPair() - const dstPeerId = await createEd25519PeerId() - const connection = mockConnection( - mockMultiaddrConnection(pair(), dstPeerId) - ) - const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) - const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) - await expect(initiatorPeerConnectionPromise).to.be.fulfilled() - await expect(receiverPeerConnectionPromise).to.be.fulfilled() - const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) - expect(pc0.connectionState).eq('connected') - expect(pc1.connectionState).eq('connected') - }) + if ((browser != null) && browser.name !== 'firefox') { + it('should connect', async () => { + const [receiver, initiator] = duplexPair() + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const controller = new AbortController() + const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + await expect(initiatorPeerConnectionPromise).to.be.fulfilled() + await expect(receiverPeerConnectionPromise).to.be.fulfilled() + const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) + expect(pc0.connectionState).eq('connected') + expect(pc1.connectionState).eq('connected') + }) + } }) describe('webrtc-w3c receiver', () => { From 6e8b3f6ae390001d42eb0c95254159dd3d1276b2 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 7 Mar 2023 22:37:57 +0530 Subject: [PATCH 29/52] nicer fix --- test/peer.browser.spec.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 78b7c2b..bc00679 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -14,23 +14,22 @@ import { detect } from 'detect-browser' const browser = detect() describe('webrtc-w3c basic', () => { - if ((browser != null) && browser.name !== 'firefox') { - it('should connect', async () => { - const [receiver, initiator] = duplexPair() - const dstPeerId = await createEd25519PeerId() - const connection = mockConnection( - mockMultiaddrConnection(pair(), dstPeerId) - ) - const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) - const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) - await expect(initiatorPeerConnectionPromise).to.be.fulfilled() - await expect(receiverPeerConnectionPromise).to.be.fulfilled() - const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) - expect(pc0.connectionState).eq('connected') - expect(pc1.connectionState).eq('connected') - }) - } + const runner: any = ((browser != null) && browser.name !== 'firefox') ? it : it.skip + runner('should connect', async () => { + const [receiver, initiator] = duplexPair() + const dstPeerId = await createEd25519PeerId() + const connection = mockConnection( + mockMultiaddrConnection(pair(), dstPeerId) + ) + const controller = new AbortController() + const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) + const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) + await expect(initiatorPeerConnectionPromise).to.be.fulfilled() + await expect(receiverPeerConnectionPromise).to.be.fulfilled() + const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) + expect(pc0.connectionState).eq('connected') + expect(pc1.connectionState).eq('connected') + }) }) describe('webrtc-w3c receiver', () => { From 32aa87763d653a95931cac1ed096d69376f61439 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Thu, 9 Mar 2023 14:40:59 +0530 Subject: [PATCH 30/52] add tests example tests for firefox and chrome --- examples/browser-to-browser/package.json | 4 +++- src/index.ts | 4 ++-- src/peer_transport/handler.ts | 4 ++-- src/peer_transport/listener.ts | 13 +++++++++++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 2f2c834..5959e2c 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -8,7 +8,9 @@ "build": "vite build", "go-relay": "cd ../go-libp2p-server && go run ./relay", "node-relay": "node relay.js", - "test": "npm run build && playwright test tests" + "test:firefox": "npm run build && playwright test --browser=firefox tests", + "test:chrome": "npm run build && playwright test tests", + "test": "npm run test:firefox && npm run test:chrome" }, "dependencies": { "@chainsafe/libp2p-noise": "^11.0.0", diff --git a/src/index.ts b/src/index.ts index 4c3c8b1..405e401 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,6 @@ export function webRTC (): (components: WebRTCTransportComponents) => Transport return (components: WebRTCTransportComponents) => new WebRTCTransport(components) } -export function webRTCDirect (init: WebRTCPeerTransportInit): (components: WebRTCDirectTransportComponents) => Transport { - return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components, init) +export function webRTCDirect (init?: WebRTCPeerTransportInit): (components: WebRTCDirectTransportComponents) => Transport { + return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components, init ?? {}) } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 254d775..6250c7f 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -2,13 +2,13 @@ import type { IncomingStreamData } from '@libp2p/interface-registrar' import { pbStream } from 'it-pb-stream' import pDefer, { type DeferredPromise } from 'p-defer' import { TimeoutController } from 'timeout-abort-controller' -import { readCandidatesUntilConnected } from './util' +import { readCandidatesUntilConnected } from './util.js' import * as pb from './pb/index.js' import { abortableDuplex } from 'abortable-iterator' import { logger } from '@libp2p/logger' import type { Stream } from '@libp2p/interface-connection' import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer' -import { DataChannelMuxerFactory } from '../muxer' +import { DataChannelMuxerFactory } from '../muxer.js' const DEFAULT_TIMEOUT = 30 * 1000 diff --git a/src/peer_transport/listener.ts b/src/peer_transport/listener.ts index 6eca4cf..3edf328 100644 --- a/src/peer_transport/listener.ts +++ b/src/peer_transport/listener.ts @@ -1,8 +1,9 @@ -// import type { ConnectionManager } from '@libp2p/interface-connection-manager' import type { PeerId } from '@libp2p/interface-peer-id' import type { ListenerEvents, TransportManager, Upgrader, Listener } from '@libp2p/interface-transport' import { EventEmitter } from '@libp2p/interfaces/events' import { multiaddr, Multiaddr } from '@multiformats/multiaddr' +import { inappropriateMultiaddr } from '../error.js' +import { TRANSPORT } from './transport.js' export interface ListenerOptions { peerId: PeerId @@ -17,9 +18,17 @@ export class WebRTCPeerListener extends EventEmitter implements super() } + private getBaseAddress (ma: Multiaddr): Multiaddr { + const addrs = ma.toString().split(TRANSPORT) + if (addrs.length < 2) { + throw inappropriateMultiaddr('base address not found') + } + return multiaddr(addrs[0]) + } + private listeningAddrs: Multiaddr[] = [] async listen (ma: Multiaddr): Promise { - const baseAddr = multiaddr(ma.toString().split('/webrtc-peer').find(a => a !== '')) + const baseAddr = this.getBaseAddress(ma) const tpt = this.opts.transportManager.transportForMultiaddr(baseAddr) const listener = tpt?.createListener({ ...this.opts }) await listener?.listen(baseAddr) From d1676452a46cb5de56f3f3c748eefcc2532652bd Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 21 Mar 2023 13:29:39 +0530 Subject: [PATCH 31/52] Start rename (bugs) --- examples/browser-to-browser/index.js | 26 +- examples/browser-to-browser/package.json | 6 +- examples/browser-to-browser/relay.js | 38 -- examples/browser-to-server/index.js | 1 + examples/browser-to-server/package.json | 6 +- examples/browser-to-server/vite.config.js | 3 - examples/go-libp2p-server/go.mod | 91 ++-- examples/go-libp2p-server/go.sum | 627 ++++------------------ examples/go-libp2p-server/main.go | 168 +++--- examples/go-libp2p-server/relay/main.go | 8 +- package.json | 2 +- src/peer_transport/transport.ts | 12 +- src/transport.ts | 2 +- test/peer.browser.spec.ts | 10 +- test/transport.browser.spec.ts | 15 +- 15 files changed, 265 insertions(+), 750 deletions(-) delete mode 100644 examples/browser-to-browser/relay.js diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index ac94e98..a182e3f 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -7,6 +7,7 @@ import * as filters from "@libp2p/websockets/filters" import { pushable } from "it-pushable" import { mplex } from "@libp2p/mplex" import { createLibp2p } from "libp2p" +import { circuitRelayTransport } from 'libp2p/circuit-relay' import { noise } from "@chainsafe/libp2p-noise" // singletons @@ -14,7 +15,7 @@ let outgoing_stream let webrtcDirectAddress const CIRCUIT_RELAY_CODE = 290 -const WEBRTC_W3C_CODE = 281 +const WEBRTC_CODE = 281 const output = document.getElementById("output") const sendSection = document.getElementById("send-section") @@ -33,15 +34,12 @@ const node = await createLibp2p({ filter: filters.all, }), webRTCDirect({}), + circuitRelayTransport({ + discoverRelays: 1, + }), ], connectionEncryption: [noise()], streamMuxers: [mplex()], - relay: { - enabled: true, - autoRelay: { - enabled: true, - }, - }, }) await node.start() @@ -71,13 +69,13 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { node.getMultiaddrs().forEach((ma) => { if (ma.protoCodes().includes(CIRCUIT_RELAY_CODE)) { - const newWebrtcDirectAddress = ma.encapsulate( - multiaddr(`/webrtc-w3c/p2p/${node.peerId}`) - ) + const newWebrtcDirectAddress = multiaddr(ma.toString() + '/webrtc/p2p/' + node.peerId) + + const webrtcAddrString = newWebrtcDirectAddress.toString() // only update if the address is new if (newWebrtcDirectAddress?.toString() !== webrtcDirectAddress?.toString()) { - appendOutput(`Listening on '${newWebrtcDirectAddress}'`) + appendOutput(`Listening on '${webrtcAddrString}'`) sendSection.style.display = "block" webrtcDirectAddress = newWebrtcDirectAddress connected_peer.innerText = webrtcDirectAddress @@ -86,8 +84,8 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { }) }) -const isWebrtcW3C = (ma) => { - return ma.protoCodes().includes(WEBRTC_W3C_CODE) +const isWebrtc = (ma) => { + return ma.protoCodes().includes(WEBRTC_CODE) } window.connect.onclick = async () => { @@ -95,7 +93,7 @@ window.connect.onclick = async () => { appendOutput(`Dialing '${ma}'`) const connection = await node.dial(ma) - if (!isWebrtcW3C(ma)) { + if (!isWebrtc(ma)) { return } diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 5959e2c..6ae0392 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -16,11 +16,11 @@ "@chainsafe/libp2p-noise": "^11.0.0", "@libp2p/websockets": "^5.0.3", "@libp2p/mplex": "^7.0.0", - "@multiformats/multiaddr": "^11.5.0", + "@multiformats/multiaddr": "^12.0.0", "it-pushable": "^3.1.0", "js-libp2p-webrtc": "file:../../", - "libp2p": "^0.42.0", - "vite": "^3.1.0" + "libp2p": "^0.43.0", + "vite": "^4.2.1" }, "devDependencies": { "@playwright/test": "^1.30.0", diff --git a/examples/browser-to-browser/relay.js b/examples/browser-to-browser/relay.js deleted file mode 100644 index 878d3f5..0000000 --- a/examples/browser-to-browser/relay.js +++ /dev/null @@ -1,38 +0,0 @@ -import { createLibp2p } from 'libp2p' -import { webSockets } from '@libp2p/websockets' -import { noise } from '@chainsafe/libp2p-noise' -import { mplex } from '@libp2p/mplex' - -async function main () { - const node = await createLibp2p({ - addresses: { - listen: ['/ip4/0.0.0.0/tcp/0/ws'] - // TODO check "What is next?" section - // announce: ['/dns4/auto-relay.libp2p.io/tcp/443/wss/p2p/QmWDn2LY8nannvSWJzruUYoLZ4vV83vfCBwd8DipvdgQc3'] - }, - transports: [ - webSockets() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - mplex() - ], - relay: { - enabled: true, - hop: { - enabled: true - }, - advertise: { - enabled: true, - } - } - }) - - console.log(`Node started with id ${node.peerId.toString()}`) - console.log('Listening on:') - node.getMultiaddrs().forEach((ma) => console.log(ma.toString())) -} - -main() \ No newline at end of file diff --git a/examples/browser-to-server/index.js b/examples/browser-to-server/index.js index bca8130..e07a1ee 100644 --- a/examples/browser-to-server/index.js +++ b/examples/browser-to-server/index.js @@ -20,6 +20,7 @@ const sender = pushable() const node = await createLibp2p({ transports: [webRTC()], connectionEncryption: [noise()], + relay: null, }); await node.start() diff --git a/examples/browser-to-server/package.json b/examples/browser-to-server/package.json index c6d71ee..b9b4cf5 100644 --- a/examples/browser-to-server/package.json +++ b/examples/browser-to-server/package.json @@ -11,11 +11,11 @@ }, "dependencies": { "@chainsafe/libp2p-noise": "^11.0.0", - "@multiformats/multiaddr": "^11.0.5", + "@multiformats/multiaddr": "^12.0.0", "it-pushable": "^3.1.0", "@libp2p/webrtc": "^1.0.3", - "libp2p": "^0.42.0", - "vite": "^3.1.0" + "libp2p": "^0.43.0", + "vite": "^4.2.1" }, "devDependencies": { "@playwright/test": "^1.30.0", diff --git a/examples/browser-to-server/vite.config.js b/examples/browser-to-server/vite.config.js index 353f32b..9b2e2a7 100644 --- a/examples/browser-to-server/vite.config.js +++ b/examples/browser-to-server/vite.config.js @@ -5,7 +5,4 @@ export default { optimizeDeps: { esbuildOptions: { target: 'es2022', supported: { bigint: true } } }, - server: { - open: true - } } \ No newline at end of file diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index b87c3fb..e5119bd 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -1,11 +1,9 @@ -module github.com/little-bear-labs/js-libp2p/go-libp2p-server +module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server go 1.18 -replace github.com/libp2p/go-libp2p => github.com/ckousik/go-libp2p v0.24.3-0.20230114095059-115caff3ca87 - require ( - github.com/libp2p/go-libp2p v0.23.2 + github.com/libp2p/go-libp2p v0.26.3 github.com/multiformats/go-multiaddr v0.8.0 ) @@ -13,7 +11,7 @@ require ( github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect @@ -25,38 +23,32 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/huin/goupnp v1.0.3 // indirect - github.com/ipfs/go-cid v0.3.2 // indirect + github.com/huin/goupnp v1.1.0 // indirect + github.com/ipfs/go-cid v0.4.0 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.15.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/koron/go-ssdp v0.0.3 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/koron/go-ssdp v0.0.4 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect - github.com/lucas-clemente/quic-go v0.31.1 // indirect - github.com/marten-seemann/qpack v0.3.0 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect - github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/marten-seemann/webtransport-go v0.4.3 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.50 // indirect + github.com/miekg/dns v1.1.52 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.0 // indirect @@ -65,52 +57,41 @@ require ( github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multicodec v0.7.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-multistream v0.3.3 // indirect + github.com/multiformats/go-multistream v0.4.1 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.5.1 // indirect + github.com/onsi/ginkgo/v2 v2.9.1 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.1.5 // indirect - github.com/pion/ice/v2 v2.2.13 // indirect - github.com/pion/interceptor v0.1.12 // indirect - github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.5 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.10 // indirect - github.com/pion/rtp v1.7.13 // indirect - github.com/pion/sctp v1.8.5 // indirect - github.com/pion/sdp/v3 v3.0.6 // indirect - github.com/pion/srtp/v2 v2.0.11 // indirect - github.com/pion/stun v0.3.5 // indirect - github.com/pion/transport v0.14.1 // indirect - github.com/pion/turn/v2 v2.0.9 // indirect - github.com/pion/udp v0.1.1 // indirect - github.com/pion/webrtc/v3 v3.1.50 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.2.1 // indirect + github.com/quic-go/qtls-go1-20 v0.1.1 // indirect + github.com/quic-go/quic-go v0.33.0 // indirect + github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/stretchr/testify v1.8.2 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/dig v1.15.0 // indirect - go.uber.org/fx v1.18.2 // indirect - go.uber.org/multierr v1.9.0 // indirect + go.uber.org/dig v1.16.1 // indirect + go.uber.org/fx v1.19.2 // indirect + go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect - golang.org/x/tools v0.3.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.7.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect + nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/examples/go-libp2p-server/go.sum b/examples/go-libp2p-server/go.sum index 4734f42..2a59fd1 100644 --- a/examples/go-libp2p-server/go.sum +++ b/examples/go-libp2p-server/go.sum @@ -2,75 +2,28 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/ckousik/go-libp2p v0.24.3-0.20230114095059-115caff3ca87 h1:Cg1+PfCSO3K1928Qbz2tefBQU5FbDdQA53sDLTX5+GY= -github.com/ckousik/go-libp2p v0.24.3-0.20230114095059-115caff3ca87/go.mod h1:1ADSR7GzrvUdHo52Hj2Te4Q5Jj00eZLN+o/FxRePOyg= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -92,35 +45,35 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -130,47 +83,22 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= @@ -180,38 +108,23 @@ github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8v github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM= -github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= +github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= -github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= +github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA= +github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= @@ -221,45 +134,42 @@ github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+ github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM= -github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= -github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= -github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= +github.com/libp2p/go-libp2p v0.26.3 h1:6g/psubqwdaBqNNoidbRKSTBEYgaOuKBhHl8Q5tO+PM= +github.com/libp2p/go-libp2p v0.26.3/go.mod h1:x75BN32YbwuY0Awm2Uix4d4KOz+/4piInkp4Wr3yOo8= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= @@ -275,20 +185,11 @@ github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtI github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4= -github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE= -github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g= -github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= -github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE= -github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/marten-seemann/webtransport-go v0.4.3 h1:vkt5o/Ci+luknRteWdYGYH1KcB7ziup+J+1PzZJIvmg= -github.com/marten-seemann/webtransport-go v0.4.3/go.mod h1:4xcfySgZMLP4aG5GBGj1egP7NlpfwgYJ1WJMvPPiVMU= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -297,8 +198,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c= +github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -310,10 +211,11 @@ github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1 github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -329,124 +231,59 @@ github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2 github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= -github.com/multiformats/go-multicodec v0.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ= -github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o= -github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg= +github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= +github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= -github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= +github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= +github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= +github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= -github.com/pion/dtls/v2 v2.1.5 h1:jlh2vtIyUBShchoTDqpCCqiYCyRFJ/lvf/gQ8TALs+c= -github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= -github.com/pion/ice/v2 v2.2.12/go.mod h1:z2KXVFyRkmjetRlaVRgjO9U3ShKwzhlUylvxKfHfd5A= -github.com/pion/ice/v2 v2.2.13 h1:NvLtzwcyob6wXgFqLmVQbGB3s9zzWmOegNMKYig5l9M= -github.com/pion/ice/v2 v2.2.13/go.mod h1:eFO4/1zCI+a3OFVt7l7kP+5jWCuZo8FwU2UwEa3+164= -github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= -github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= -github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= -github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.8.5 h1:JCc25nghnXWOlSn3OVtEnA9PjQ2JsxQbG+CXZ1UkJKQ= -github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= -github.com/pion/srtp/v2 v2.0.10/go.mod h1:XEeSWaK9PfuMs7zxXyiN252AHPbH12NX5q/CFDWtUuA= -github.com/pion/srtp/v2 v2.0.11 h1:6cEEgT1oCLWgE+BynbfaSMAxtsqU0M096x9dNH6olY0= -github.com/pion/srtp/v2 v2.0.11/go.mod h1:vzHprzbuVoYJ9NfaRMycnFrkHcLSaLVuBZDOtFQNZjY= -github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= -github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= -github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= -github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= -github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= -github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= -github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw= -github.com/pion/turn/v2 v2.0.9 h1:jcDPw0Vfd5I4iTc7s0Upfc2aMnyu2lgJ9vV0SUrNC1o= -github.com/pion/turn/v2 v2.0.9/go.mod h1:DQlwUwx7hL8Xya6TTAabbd9DdKXTNR96Xf5g5Qqso/M= -github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= -github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pion/webrtc/v3 v3.1.50 h1:wLMo1+re4WMZ9Kun9qcGcY+XoHkE3i0CXrrc0sjhVCk= -github.com/pion/webrtc/v3 v3.1.50/go.mod h1:y9n09weIXB+sjb9mi0GBBewNxo4TKUQm5qdtT5v3/X4= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= +github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= +github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= +github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= +github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= +github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -471,177 +308,99 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go. github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= -go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= -go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU= -go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= +go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -649,100 +408,42 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -751,51 +452,14 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -803,109 +467,32 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -914,15 +501,9 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/examples/go-libp2p-server/main.go b/examples/go-libp2p-server/main.go index 90d42fe..daaa1ce 100644 --- a/examples/go-libp2p-server/main.go +++ b/examples/go-libp2p-server/main.go @@ -1,95 +1,95 @@ package main -import ( - "bufio" - "fmt" - "log" - "net" - "os" - "os/signal" - "syscall" +// import ( +// "bufio" +// "fmt" +// "log" +// "net" +// "os" +// "os/signal" +// "syscall" - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/host" - "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/peer" - webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" -) +// "github.com/libp2p/go-libp2p" +// "github.com/libp2p/go-libp2p/core/host" +// "github.com/libp2p/go-libp2p/core/network" +// "github.com/libp2p/go-libp2p/core/peer" +// webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" +// ) -var listenerIp = net.IPv4(127, 0, 0, 1) +// var listenerIp = net.IPv4(127, 0, 0, 1) -func init() { - ifaces, err := net.Interfaces() - if err != nil { - return - } - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue - } - addrs, err := iface.Addrs() - if err != nil { - return - } - for _, addr := range addrs { - // bind to private non-loopback ip - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { - if ipnet.IP.To4() != nil { - listenerIp = ipnet.IP.To4() - return - } - } - } - } -} +// func init() { +// ifaces, err := net.Interfaces() +// if err != nil { +// return +// } +// for _, iface := range ifaces { +// if iface.Flags&net.FlagUp == 0 { +// continue +// } +// addrs, err := iface.Addrs() +// if err != nil { +// return +// } +// for _, addr := range addrs { +// // bind to private non-loopback ip +// if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { +// if ipnet.IP.To4() != nil { +// listenerIp = ipnet.IP.To4() +// return +// } +// } +// } +// } +// } -func echoHandler(stream network.Stream) { - for { - reader := bufio.NewReader(stream) - str, err := reader.ReadString('\n') - log.Printf("err: %s", err) - if err != nil { - return - } - log.Printf("echo: %s", str) - _, err = stream.Write([]byte(str)) - if err != nil { - log.Printf("err: %v", err) - return - } - } -} +// func echoHandler(stream network.Stream) { +// for { +// reader := bufio.NewReader(stream) +// str, err := reader.ReadString('\n') +// log.Printf("err: %s", err) +// if err != nil { +// return +// } +// log.Printf("echo: %s", str) +// _, err = stream.Write([]byte(str)) +// if err != nil { +// log.Printf("err: %v", err) +// return +// } +// } +// } -func main() { - host := createHost() - host.SetStreamHandler("/echo/1.0.0", echoHandler) - defer host.Close() - remoteInfo := peer.AddrInfo{ - ID: host.ID(), - Addrs: host.Network().ListenAddresses(), - } +// func main() { +// host := createHost() +// host.SetStreamHandler("/echo/1.0.0", echoHandler) +// defer host.Close() +// remoteInfo := peer.AddrInfo{ +// ID: host.ID(), +// Addrs: host.Network().ListenAddresses(), +// } - remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) - fmt.Println("p2p addr: ", remoteAddrs[0]) +// remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) +// fmt.Println("p2p addr: ", remoteAddrs[0]) - fmt.Println("press Ctrl+C to quit") - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) - <-ch -} +// fmt.Println("press Ctrl+C to quit") +// ch := make(chan os.Signal, 1) +// signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) +// <-ch +// } -func createHost() host.Host { - h, err := libp2p.New( - libp2p.Transport(webrtc.New), - libp2p.ListenAddrStrings( - fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), - ), - libp2p.DisableRelay(), - libp2p.Ping(true), - ) - if err != nil { - panic(err) - } +// func createHost() host.Host { +// h, err := libp2p.New( +// libp2p.Transport(webrtc.New), +// libp2p.ListenAddrStrings( +// fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), +// ), +// libp2p.DisableRelay(), +// libp2p.Ping(true), +// ) +// if err != nil { +// panic(err) +// } - return h -} +// return h +// } diff --git a/examples/go-libp2p-server/relay/main.go b/examples/go-libp2p-server/relay/main.go index 7a6f179..ad1a5e7 100644 --- a/examples/go-libp2p-server/relay/main.go +++ b/examples/go-libp2p-server/relay/main.go @@ -10,16 +10,16 @@ import ( // "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/muxer/mplex" - relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" + relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" ma "github.com/multiformats/go-multiaddr" ) func main() { - makeRelayV1() + makeRelayV2() select {} } -func makeRelayV1() host.Host { +func makeRelayV2() host.Host { r := rand.Reader // Generate a key pair for this host. We will use it at least // to obtain a valid host ID. @@ -43,7 +43,7 @@ func makeRelayV1() host.Host { panic(err) } - _, err = relay.NewRelay(host) + _, err = relay.New(host) if err != nil { panic(err) } diff --git a/package.json b/package.json index ecef22b..695175e 100644 --- a/package.json +++ b/package.json @@ -147,7 +147,7 @@ "@libp2p/interfaces": "^3.2.0", "@libp2p/logger": "^2.0.0", "@libp2p/peer-id": "^2.0.0", - "@multiformats/multiaddr": "^11.5.0", + "@multiformats/multiaddr": "^12.0.0", "@protobuf-ts/runtime": "^2.8.0", "abortable-iterator": "^4.0.2", "err-code": "^3.0.1", diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 51b3ca9..f257ad9 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -13,11 +13,7 @@ import { connect, handleIncomingStream } from './handler.js' const log = logger('libp2p:webrtc:peer') -// TODO(ckousik): This is the wrong protocol name and code. They -// will be changed to /webrtc-direct, /webrtc-direct/0.0.1, and 281 -// respectively once https://github.com/multiformats/js-multiaddr/pull/309 -// is merged. -export const TRANSPORT = '/webrtc-w3c' +export const TRANSPORT = '/webrtc' export const PROTOCOL = '/webrtc-signaling/0.0.1' export const CODE = 281 @@ -63,7 +59,7 @@ export class WebRTCDirectTransport implements Transport, Startable { } get [Symbol.toStringTag] (): string { - return '@libp2p/webrtc-w3c' + return '@libp2p/webrtc' } get [symbol] (): true { @@ -80,9 +76,9 @@ export class WebRTCDirectTransport implements Transport, Startable { /* * dial connects to a remote via the circuit relay or any other protocol * and proceeds to upgrade to a webrtc connection. - * multiaddr of the form: /webrtc-direct/p2p/ + * multiaddr of the form: /webrtc/p2p/ * For a circuit relay, this will be of the form - * /p2p//p2p-circuit/webrtc-direct/p2p/ + * /p2p//p2p-circuit/webrtc/p2p/ */ async dial (ma: Multiaddr, options: DialOptions): Promise { log.trace('dialing address: ', ma) diff --git a/src/transport.ts b/src/transport.ts index c8736de..dd24d35 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -82,7 +82,7 @@ export class WebRTCTransport implements Transport { * Implement toString() for WebRTCTransport */ get [Symbol.toStringTag] (): string { - return '@libp2p/webrtc' + return '@libp2p/webrtc-direct' } /** diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index bc00679..b4614cc 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -13,7 +13,7 @@ import { detect } from 'detect-browser' const browser = detect() -describe('webrtc-w3c basic', () => { +describe('webrtc basic', () => { const runner: any = ((browser != null) && browser.name !== 'firefox') ? it : it.skip runner('should connect', async () => { const [receiver, initiator] = duplexPair() @@ -32,7 +32,7 @@ describe('webrtc-w3c basic', () => { }) }) -describe('webrtc-w3c receiver', () => { +describe('webrtc receiver', () => { it('should fail receiving on invalid sdp offer', async () => { const [receiver, initiator] = duplexPair() const dstPeerId = await createEd25519PeerId() @@ -47,7 +47,7 @@ describe('webrtc-w3c receiver', () => { }) }) -describe('webrtc-w3c dialer', () => { +describe('webrtc dialer', () => { it('should fail receiving on invalid sdp answer', async () => { const [receiver, initiator] = duplexPair() const controller = new AbortController() @@ -87,7 +87,7 @@ describe('webrtc-w3c dialer', () => { }) }) -describe('webrtc-w3c filter', () => { +describe('webrtc filter', () => { it('can filter multiaddrs to dial', async () => { const transport = new WebRTCDirectTransport({ transportManager: sinon.stub() as any, @@ -98,7 +98,7 @@ describe('webrtc-w3c filter', () => { }, {}) const valid = [ - multiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p-circuit/webrtc-w3c') + multiaddr('/ip4/127.0.0.1/tcp/1234/ws/p2p-circuit/webrtc') ] expect(transport.filter(valid)).length(1) diff --git a/test/transport.browser.spec.ts b/test/transport.browser.spec.ts index e52946c..a3a308c 100644 --- a/test/transport.browser.spec.ts +++ b/test/transport.browser.spec.ts @@ -50,7 +50,7 @@ describe('WebRTC Transport', () => { it('toString property getter', () => { const t = new underTest.WebRTCTransport(components) const s = t[Symbol.toStringTag] - expect(s).to.equal('@libp2p/webrtc') + expect(s).to.equal('@libp2p/webrtc-direct') }) it('symbol property getter', () => { @@ -62,20 +62,19 @@ describe('WebRTC Transport', () => { it('transport filter filters out invalid multiaddrs', async () => { const mas: Multiaddr[] = [ '/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ', - '/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd', - '/ip4/1.2.3.4/udp/1234/webrtc/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd', + '/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd', + '/ip4/1.2.3.4/udp/1234/webrtc-direct/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd', '/ip4/1.2.3.4/udp/1234/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd' ].map((s) => multiaddr(s)) const t = new underTest.WebRTCTransport(components) const result = t.filter(mas) - const expected: Multiaddr[] = [ - multiaddr('/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd') - ] + const expected = + multiaddr('/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd') assert.isNotNull(result) expect(result.constructor.name).to.equal('Array') - expect(expected.constructor.name).to.equal('Array') - expect(result).to.eql(expected) + expect(result).to.have.length(1) + expect(result[0].equals(expected)).to.be.true() }) it('throws WebRTC transport error when dialing a multiaddr without a PeerId', async () => { From 55c4f7bdb96374dcbbeead9eea5df53d0f09a612 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Thu, 23 Mar 2023 20:05:14 +0530 Subject: [PATCH 32/52] use js relay in browser-to-browser tests --- examples/browser-to-browser/tests/test.js | 57 +++++++++++------------ 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/examples/browser-to-browser/tests/test.js b/examples/browser-to-browser/tests/test.js index bcbbeb0..f9c06d7 100644 --- a/examples/browser-to-browser/tests/test.js +++ b/examples/browser-to-browser/tests/test.js @@ -1,8 +1,12 @@ /* eslint-disable no-console */ import { test, expect } from '@playwright/test' import { playwright } from 'test-util-ipfs-example' -import { spawn, exec } from 'child_process' -import { existsSync } from 'fs' +import { createLibp2p } from 'libp2p' +import { circuitRelayServer } from 'libp2p/circuit-relay' +import { webSockets } from '@libp2p/websockets' +import * as filters from '@libp2p/websockets/filters' +import { mplex } from '@libp2p/mplex' +import { noise } from '@chainsafe/libp2p-noise' // Setup const play = test.extend({ @@ -21,33 +25,24 @@ const output = '#output' const message = 'hello' let url -async function spawnGoLibp2p() { - if (!existsSync('../../examples/go-libp2p-server/go-libp2p-server/relay')) { - await new Promise((resolve, reject) => { - exec('go build', - { cwd: '../../examples/go-libp2p-server/relay' }, - (error, stdout, stderr) => { - if (error) { - throw (`exec error: ${error}`) - } - resolve() - }) - }) - } - - const server = spawn('./relay', [], { cwd: '../../examples/go-libp2p-server/relay', killSignal: 'SIGINT' }) - server.stderr.on('data', (data) => { - console.log(`stderr: ${data}`, typeof data) +// we spawn a js libp2p relay +async function spawnRelay() { + const server = await createLibp2p({ + addresses: { + listen: ['/ip4/127.0.0.1/tcp/0/ws'] + }, + transports: [ + webSockets({ + filter: filters.all + }), + ], + connectionEncryption: [noise()], + streamMuxers: [mplex()], + relay: circuitRelayServer({}), }) - const serverAddr = await (new Promise(resolve => { - server.stdout.on('data', (data) => { - console.log(`stdout: ${data}`, typeof data) - const addr = String(data).match(/p2p addr: ([^\s]*)/) - if (addr !== null && addr.length > 0) { - resolve(addr[1]) - } - }) - })) + + const serverAddr = server.getMultiaddrs()[0].toString() + return { server, serverAddr } } @@ -58,7 +53,7 @@ play.describe('browser to browser example:', () => { // eslint-disable-next-line no-empty-pattern play.beforeAll(async ({ servers }, testInfo) => { testInfo.setTimeout(5 * 60_000) - const s = await spawnGoLibp2p() + const s = await spawnRelay() server = s.server serverAddr = s.serverAddr console.log('Server addr:', serverAddr) @@ -66,14 +61,14 @@ play.describe('browser to browser example:', () => { }, {}) play.afterAll(() => { - server.kill('SIGINT') + server.stop() }) play.beforeEach(async ({ page }) => { await page.goto(url) }) - play('should connect to a go-libp2p relay node', async ({ page, context }) => { + play('should connect to a relay node', async ({ page, context }) => { let peer = await per_page(page, serverAddr) // load second page and use `peer` as the connectAddr From e7a262345cc13a4ec91500f1974a57a7132a111e Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 24 Mar 2023 17:48:35 +0530 Subject: [PATCH 33/52] hacky fixes to tests --- examples/browser-to-browser/README.md | 10 +- examples/browser-to-browser/package.json | 3 +- examples/browser-to-browser/relay.js | 22 +++ examples/browser-to-server/index.js | 11 +- examples/browser-to-server/package.json | 2 +- examples/browser-to-server/tests/test.js | 12 +- examples/go-libp2p-server/go.mod | 29 +++- examples/go-libp2p-server/go.sum | 131 +++++++++++++++- examples/go-libp2p-server/main.go | 168 ++++++++++----------- examples/go-libp2p-server/relay/.gitignore | 1 - examples/go-libp2p-server/relay/main.go | 61 -------- src/peer_transport/transport.ts | 4 +- 12 files changed, 281 insertions(+), 173 deletions(-) create mode 100644 examples/browser-to-browser/relay.js delete mode 100644 examples/go-libp2p-server/relay/.gitignore delete mode 100644 examples/go-libp2p-server/relay/main.go diff --git a/examples/browser-to-browser/README.md b/examples/browser-to-browser/README.md index a3e514d..f24c036 100644 --- a/examples/browser-to-browser/README.md +++ b/examples/browser-to-browser/README.md @@ -4,16 +4,10 @@ This example leverages the [vite bundler](https://vitejs.dev/) to compile and se ## Running the Relay Server -For browsers to communicate, we first need to run the Go LibP2P relay server: +For browsers to communicate, we first need to run the LibP2P relay server: ```shell -npm run go-relay -``` - -Alternatively, a NodeJS relay server is available: - -```shell -npm run node-relay +npm run relay ``` Copy one of the multiaddresses in the output. diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 6ae0392..3862be3 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -6,8 +6,7 @@ "scripts": { "start": "vite", "build": "vite build", - "go-relay": "cd ../go-libp2p-server && go run ./relay", - "node-relay": "node relay.js", + "relay": "node relay.js", "test:firefox": "npm run build && playwright test --browser=firefox tests", "test:chrome": "npm run build && playwright test tests", "test": "npm run test:firefox && npm run test:chrome" diff --git a/examples/browser-to-browser/relay.js b/examples/browser-to-browser/relay.js new file mode 100644 index 0000000..0247a2b --- /dev/null +++ b/examples/browser-to-browser/relay.js @@ -0,0 +1,22 @@ +import { mplex } from "@libp2p/mplex" +import { createLibp2p } from "libp2p" +import { noise } from "@chainsafe/libp2p-noise" +import { circuitRelayServer } from 'libp2p/circuit-relay' +import { webSockets } from '@libp2p/websockets' +import * as filters from '@libp2p/websockets/filters' + +const server = await createLibp2p({ + addresses: { + listen: ['/ip4/127.0.0.1/tcp/0/ws'] + }, + transports: [ + webSockets({ + filter: filters.all + }), + ], + connectionEncryption: [noise()], + streamMuxers: [mplex()], + relay: circuitRelayServer({}), +}) + +console.log("p2p addr: ", server.getMultiaddrs().map((ma) => ma.toString())) diff --git a/examples/browser-to-server/index.js b/examples/browser-to-server/index.js index e07a1ee..44004cf 100644 --- a/examples/browser-to-server/index.js +++ b/examples/browser-to-server/index.js @@ -20,7 +20,6 @@ const sender = pushable() const node = await createLibp2p({ transports: [webRTC()], connectionEncryption: [noise()], - relay: null, }); await node.start() @@ -31,7 +30,15 @@ node.connectionManager.addEventListener('peer:connect', (connection) => { }) window.connect.onclick = async () => { - const ma = multiaddr(window.peer.value) + + + // TODO!!(ckousik): hack until webrtc is renamed in Go. Remove once + // complete + let candidateMa = window.peer.value + candidateMa = candidateMa.replace(/\/webrtc\/certhash/, "/webrtc-direct/certhash") + const ma = multiaddr(candidateMa) + + appendOutput(`Dialing '${ma}'`) stream = await node.dialProtocol(ma, ['/echo/1.0.0']) pipe(sender, stream, async (src) => { diff --git a/examples/browser-to-server/package.json b/examples/browser-to-server/package.json index b9b4cf5..70a1b25 100644 --- a/examples/browser-to-server/package.json +++ b/examples/browser-to-server/package.json @@ -14,7 +14,7 @@ "@multiformats/multiaddr": "^12.0.0", "it-pushable": "^3.1.0", "@libp2p/webrtc": "^1.0.3", - "libp2p": "^0.43.0", + "libp2p": "^0.43.2", "vite": "^4.2.1" }, "devDependencies": { diff --git a/examples/browser-to-server/tests/test.js b/examples/browser-to-server/tests/test.js index 13f80cd..3ff6ffd 100644 --- a/examples/browser-to-server/tests/test.js +++ b/examples/browser-to-server/tests/test.js @@ -69,7 +69,7 @@ play.describe('bundle ipfs with parceljs:', () => { await page.goto(url) }) - play('should connect to a go-libp2p node over webtransport', async ({ page }) => { + play('should connect to a go-libp2p node over webrtc', async ({ page }) => { const message = 'hello' // add the go libp2p multiaddress to the input field and submit @@ -89,8 +89,14 @@ play.describe('bundle ipfs with parceljs:', () => { // Sending message '${message}' // Received message '${message}' const connections = await page.textContent(output) - expect(connections).toContain(`Dialing '${serverAddr}'`) - expect(connections).toContain(`Peer connected '${serverAddr}'`) + + + // TODO: These are disabled until the webrtc protocol rename is completed in Go + // expect(connections).toContain(`Dialing '${serverAddr}'`) + // expect(connections).toContain(`Peer connected '${serverAddr}'`) + + + expect(connections).toContain(`Sending message '${message}'`) expect(connections).toContain(`Received message '${message}'`) }) diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index e5119bd..be41be4 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -2,10 +2,9 @@ module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server go 1.18 -require ( - github.com/libp2p/go-libp2p v0.26.3 - github.com/multiformats/go-multiaddr v0.8.0 -) +replace github.com/libp2p/go-libp2p v0.26.3 => github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a + +require github.com/libp2p/go-libp2p v0.26.3 require ( github.com/benbjohnson/clock v1.3.0 // indirect @@ -26,6 +25,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/huin/goupnp v1.1.0 // indirect github.com/ipfs/go-cid v0.4.0 // indirect @@ -39,7 +39,6 @@ require ( github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect - github.com/libp2p/go-mplex v0.7.0 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect @@ -55,6 +54,7 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.8.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect @@ -65,6 +65,24 @@ require ( github.com/onsi/ginkgo/v2 v2.9.1 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pion/datachannel v1.5.5 // indirect + github.com/pion/dtls/v2 v2.1.5 // indirect + github.com/pion/ice/v2 v2.2.13 // indirect + github.com/pion/interceptor v0.1.12 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/mdns v0.0.5 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.10 // indirect + github.com/pion/rtp v1.7.13 // indirect + github.com/pion/sctp v1.8.6 // indirect + github.com/pion/sdp/v3 v3.0.6 // indirect + github.com/pion/srtp/v2 v2.0.11 // indirect + github.com/pion/stun v0.4.0 // indirect + github.com/pion/transport v0.14.1 // indirect + github.com/pion/transport/v2 v2.0.0 // indirect + github.com/pion/turn/v2 v2.0.9 // indirect + github.com/pion/udp v0.1.1 // indirect + github.com/pion/webrtc/v3 v3.1.51 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect @@ -76,6 +94,7 @@ require ( github.com/quic-go/quic-go v0.33.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/stretchr/testify v1.8.2 // indirect go.uber.org/atomic v1.10.0 // indirect diff --git a/examples/go-libp2p-server/go.sum b/examples/go-libp2p-server/go.sum index 2a59fd1..7cbfb7c 100644 --- a/examples/go-libp2p-server/go.sum +++ b/examples/go-libp2p-server/go.sum @@ -8,6 +8,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a h1:kDV4AzT/08bsfnmbsIkxrFwyTCEGu4Q14o7VB5wDW/M= +github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a/go.mod h1:9sYpBoWyKexAe5mP6V92siMQ9v2DJAlQyJIGfqfnpeI= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= @@ -51,6 +53,7 @@ github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwU github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -92,11 +95,20 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -111,6 +123,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -119,6 +133,7 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= @@ -152,8 +167,8 @@ github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfo github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -166,13 +181,9 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.26.3 h1:6g/psubqwdaBqNNoidbRKSTBEYgaOuKBhHl8Q5tO+PM= -github.com/libp2p/go-libp2p v0.26.3/go.mod h1:x75BN32YbwuY0Awm2Uix4d4KOz+/4piInkp4Wr3yOo8= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= -github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= @@ -245,14 +256,66 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= +github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= +github.com/pion/dtls/v2 v2.1.5 h1:jlh2vtIyUBShchoTDqpCCqiYCyRFJ/lvf/gQ8TALs+c= +github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= +github.com/pion/ice/v2 v2.2.13 h1:NvLtzwcyob6wXgFqLmVQbGB3s9zzWmOegNMKYig5l9M= +github.com/pion/ice/v2 v2.2.13/go.mod h1:eFO4/1zCI+a3OFVt7l7kP+5jWCuZo8FwU2UwEa3+164= +github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= +github.com/pion/interceptor v0.1.12 h1:CslaNriCFUItiXS5o+hh5lpL0t0ytQkFnUcbbCs2Zq8= +github.com/pion/interceptor v0.1.12/go.mod h1:bDtgAD9dRkBZpWHGKaoKb42FhDHTG2rX8Ii9LRALLVA= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= +github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= +github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= +github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= +github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= +github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= +github.com/pion/sctp v1.8.6 h1:CUex11Vkt9YS++VhLf8b55O3VqKrWL6W3SDwX4jAqsI= +github.com/pion/sctp v1.8.6/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= +github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= +github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= +github.com/pion/srtp/v2 v2.0.11 h1:6cEEgT1oCLWgE+BynbfaSMAxtsqU0M096x9dNH6olY0= +github.com/pion/srtp/v2 v2.0.11/go.mod h1:vzHprzbuVoYJ9NfaRMycnFrkHcLSaLVuBZDOtFQNZjY= +github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= +github.com/pion/stun v0.4.0 h1:vgRrbBE2htWHy7l3Zsxckk7rkjnjOsSM7PHZnBwo8rk= +github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= +github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= +github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= +github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= +github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= +github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= +github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4= +github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= +github.com/pion/turn/v2 v2.0.9 h1:jcDPw0Vfd5I4iTc7s0Upfc2aMnyu2lgJ9vV0SUrNC1o= +github.com/pion/turn/v2 v2.0.9/go.mod h1:DQlwUwx7hL8Xya6TTAabbd9DdKXTNR96Xf5g5Qqso/M= +github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= +github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= +github.com/pion/webrtc/v3 v3.1.51 h1:uU9vHdY63O3uRFJiDskH0qFJ+219bAH28qOt5csSWcM= +github.com/pion/webrtc/v3 v3.1.51/go.mod h1:sbRNshM9l0zRDQgZRP9K5RTzlsdBmqmyO8KbxngG8jQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -282,8 +345,11 @@ github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3l github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -320,9 +386,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -336,6 +404,7 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= @@ -362,6 +431,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -376,6 +448,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -391,10 +464,21 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -410,6 +494,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -421,25 +506,47 @@ golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -455,9 +562,11 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -480,19 +589,31 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/examples/go-libp2p-server/main.go b/examples/go-libp2p-server/main.go index daaa1ce..90d42fe 100644 --- a/examples/go-libp2p-server/main.go +++ b/examples/go-libp2p-server/main.go @@ -1,95 +1,95 @@ package main -// import ( -// "bufio" -// "fmt" -// "log" -// "net" -// "os" -// "os/signal" -// "syscall" +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "os/signal" + "syscall" -// "github.com/libp2p/go-libp2p" -// "github.com/libp2p/go-libp2p/core/host" -// "github.com/libp2p/go-libp2p/core/network" -// "github.com/libp2p/go-libp2p/core/peer" -// webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" -// ) + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" + webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" +) -// var listenerIp = net.IPv4(127, 0, 0, 1) +var listenerIp = net.IPv4(127, 0, 0, 1) -// func init() { -// ifaces, err := net.Interfaces() -// if err != nil { -// return -// } -// for _, iface := range ifaces { -// if iface.Flags&net.FlagUp == 0 { -// continue -// } -// addrs, err := iface.Addrs() -// if err != nil { -// return -// } -// for _, addr := range addrs { -// // bind to private non-loopback ip -// if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { -// if ipnet.IP.To4() != nil { -// listenerIp = ipnet.IP.To4() -// return -// } -// } -// } -// } -// } +func init() { + ifaces, err := net.Interfaces() + if err != nil { + return + } + for _, iface := range ifaces { + if iface.Flags&net.FlagUp == 0 { + continue + } + addrs, err := iface.Addrs() + if err != nil { + return + } + for _, addr := range addrs { + // bind to private non-loopback ip + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() { + if ipnet.IP.To4() != nil { + listenerIp = ipnet.IP.To4() + return + } + } + } + } +} -// func echoHandler(stream network.Stream) { -// for { -// reader := bufio.NewReader(stream) -// str, err := reader.ReadString('\n') -// log.Printf("err: %s", err) -// if err != nil { -// return -// } -// log.Printf("echo: %s", str) -// _, err = stream.Write([]byte(str)) -// if err != nil { -// log.Printf("err: %v", err) -// return -// } -// } -// } +func echoHandler(stream network.Stream) { + for { + reader := bufio.NewReader(stream) + str, err := reader.ReadString('\n') + log.Printf("err: %s", err) + if err != nil { + return + } + log.Printf("echo: %s", str) + _, err = stream.Write([]byte(str)) + if err != nil { + log.Printf("err: %v", err) + return + } + } +} -// func main() { -// host := createHost() -// host.SetStreamHandler("/echo/1.0.0", echoHandler) -// defer host.Close() -// remoteInfo := peer.AddrInfo{ -// ID: host.ID(), -// Addrs: host.Network().ListenAddresses(), -// } +func main() { + host := createHost() + host.SetStreamHandler("/echo/1.0.0", echoHandler) + defer host.Close() + remoteInfo := peer.AddrInfo{ + ID: host.ID(), + Addrs: host.Network().ListenAddresses(), + } -// remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) -// fmt.Println("p2p addr: ", remoteAddrs[0]) + remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo) + fmt.Println("p2p addr: ", remoteAddrs[0]) -// fmt.Println("press Ctrl+C to quit") -// ch := make(chan os.Signal, 1) -// signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) -// <-ch -// } + fmt.Println("press Ctrl+C to quit") + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT) + <-ch +} -// func createHost() host.Host { -// h, err := libp2p.New( -// libp2p.Transport(webrtc.New), -// libp2p.ListenAddrStrings( -// fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), -// ), -// libp2p.DisableRelay(), -// libp2p.Ping(true), -// ) -// if err != nil { -// panic(err) -// } +func createHost() host.Host { + h, err := libp2p.New( + libp2p.Transport(webrtc.New), + libp2p.ListenAddrStrings( + fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), + ), + libp2p.DisableRelay(), + libp2p.Ping(true), + ) + if err != nil { + panic(err) + } -// return h -// } + return h +} diff --git a/examples/go-libp2p-server/relay/.gitignore b/examples/go-libp2p-server/relay/.gitignore deleted file mode 100644 index 38200f1..0000000 --- a/examples/go-libp2p-server/relay/.gitignore +++ /dev/null @@ -1 +0,0 @@ -relay \ No newline at end of file diff --git a/examples/go-libp2p-server/relay/main.go b/examples/go-libp2p-server/relay/main.go deleted file mode 100644 index ad1a5e7..0000000 --- a/examples/go-libp2p-server/relay/main.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "crypto/rand" - "fmt" - - "github.com/libp2p/go-libp2p" - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/host" - - // "github.com/libp2p/go-libp2p/core/peer" - "github.com/libp2p/go-libp2p/p2p/muxer/mplex" - relay "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" - ma "github.com/multiformats/go-multiaddr" -) - -func main() { - makeRelayV2() - select {} -} - -func makeRelayV2() host.Host { - r := rand.Reader - // Generate a key pair for this host. We will use it at least - // to obtain a valid host ID. - priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r) - if err != nil { - panic(err) - } - - opts := []libp2p.Option{ - libp2p.DefaultTransports, - libp2p.ListenAddrStrings( - "/ip4/0.0.0.0/tcp/4003/ws", - ), - libp2p.Muxer("/mplex/6.7.0", mplex.DefaultTransport), - libp2p.Identity(priv), - libp2p.EnableRelay(), - } - - host, err := libp2p.New(opts...) - if err != nil { - panic(err) - } - - _, err = relay.New(host) - if err != nil { - panic(err) - } - - // fmt.Println(host.Mux().Protocols()) - - for _, addr := range host.Addrs() { - a, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", host.ID().Pretty())) - if err != nil { - panic(err) - } - fmt.Println("p2p addr: ", addr.Encapsulate(a)) - } - return host -} diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index f257ad9..1c867ce 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -30,7 +30,7 @@ export interface WebRTCDirectTransportComponents { } export class WebRTCDirectTransport implements Transport, Startable { - private readonly _started = false + private _started = false private readonly handler?: ConnectionHandler constructor ( @@ -48,10 +48,12 @@ export class WebRTCDirectTransport implements Transport, Startable { await this.components.registrar.handle(PROTOCOL, (data) => { this._onProtocol(data).catch(err => { log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) }) }) + this._started = true } async stop (): Promise { await this.components.registrar.unhandle(PROTOCOL) + this._started = false } createListener (options: CreateListenerOptions): Listener { From 45f47f2ae84908b9a1cf1da6cdaaad4d7c2ca23e Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 24 Mar 2023 20:59:44 +0530 Subject: [PATCH 34/52] fix firefox issue --- examples/browser-to-browser/index.js | 4 +-- examples/browser-to-server/index.js | 4 +-- package.json | 4 +-- src/index.ts | 14 +++++----- src/peer_transport/handler.ts | 32 +++------------------- src/peer_transport/transport.ts | 14 +++++----- src/peer_transport/util.ts | 41 +++++++++++++++++++++++++++- src/transport.ts | 13 +++++---- test/peer.browser.spec.ts | 13 ++++++--- test/transport.browser.spec.ts | 22 +++++++-------- 10 files changed, 91 insertions(+), 70 deletions(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index a182e3f..ba023b9 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -1,7 +1,7 @@ import { multiaddr } from "@multiformats/multiaddr" import { pipe } from "it-pipe" import { fromString, toString } from "uint8arrays" -import { webRTCDirect } from "js-libp2p-webrtc" +import { webRTC } from "js-libp2p-webrtc" import { webSockets } from "@libp2p/websockets" import * as filters from "@libp2p/websockets/filters" import { pushable } from "it-pushable" @@ -33,7 +33,7 @@ const node = await createLibp2p({ webSockets({ filter: filters.all, }), - webRTCDirect({}), + webRTC({}), circuitRelayTransport({ discoverRelays: 1, }), diff --git a/examples/browser-to-server/index.js b/examples/browser-to-server/index.js index 44004cf..7e180c3 100644 --- a/examples/browser-to-server/index.js +++ b/examples/browser-to-server/index.js @@ -3,7 +3,7 @@ import { noise } from '@chainsafe/libp2p-noise' import { multiaddr } from '@multiformats/multiaddr' import { pipe } from "it-pipe"; import { fromString, toString } from "uint8arrays"; -import { webRTC } from '@libp2p/webrtc' +import { webRTCDirect } from '@libp2p/webrtc' import { pushable } from 'it-pushable'; let stream; @@ -18,7 +18,7 @@ const clean = (line) => line.replaceAll('\n', '') const sender = pushable() const node = await createLibp2p({ - transports: [webRTC()], + transports: [webRTCDirect()], connectionEncryption: [noise()], }); diff --git a/package.json b/package.json index 695175e..193900f 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,8 @@ "protons-runtime": "^4.0.1", "timeout-abort-controller": "^3.0.0", "uint8arraylist": "^2.3.3", - "uint8arrays": "^4.0.2" + "uint8arrays": "^4.0.2", + "detect-browser": "^5.3.0" }, "devDependencies": { "@libp2p/interface-mocks": "^9.0.0", @@ -171,7 +172,6 @@ "@protobuf-ts/plugin": "^2.8.0", "@protobuf-ts/protoc": "^2.8.0", "aegir": "^38.1.6", - "detect-browser": "^5.3.0", "eslint-plugin-etc": "^2.0.2", "it-pair": "^2.0.3", "protons": "^6.0.1", diff --git a/src/index.ts b/src/index.ts index 405e401..ef6600c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,12 @@ import type { Transport } from '@libp2p/interface-transport' -import type { WebRTCDirectTransportComponents, WebRTCPeerTransportInit } from './peer_transport/transport.js' -import { WebRTCDirectTransport } from './peer_transport/transport.js' -import { WebRTCTransport, WebRTCTransportComponents } from './transport.js' +import type { WebRTCTransportComponents, WebRTCTransportInit } from './peer_transport/transport.js' +import { WebRTCTransport } from './peer_transport/transport.js' +import { WebRTCDirectTransport, WebRTCDirectTransportComponents } from './transport.js' -export function webRTC (): (components: WebRTCTransportComponents) => Transport { - return (components: WebRTCTransportComponents) => new WebRTCTransport(components) +export function webRTCDirect (): (components: WebRTCDirectTransportComponents) => Transport { + return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components) } -export function webRTCDirect (init?: WebRTCPeerTransportInit): (components: WebRTCDirectTransportComponents) => Transport { - return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components, init ?? {}) +export function webRTC (init?: WebRTCTransportInit): (components: WebRTCTransportComponents) => Transport { + return (components: WebRTCTransportComponents) => new WebRTCTransport(components, init ?? {}) } diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 6250c7f..1ad80ab 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -2,7 +2,7 @@ import type { IncomingStreamData } from '@libp2p/interface-registrar' import { pbStream } from 'it-pb-stream' import pDefer, { type DeferredPromise } from 'p-defer' import { TimeoutController } from 'timeout-abort-controller' -import { readCandidatesUntilConnected } from './util.js' +import { readCandidatesUntilConnected, resolveOnConnected } from './util.js' import * as pb from './pb/index.js' import { abortableDuplex } from 'abortable-iterator' import { logger } from '@libp2p/logger' @@ -33,22 +33,8 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea }) } - // setup callback for peerconnection state change - pc.onconnectionstatechange = (_) => { - log.trace('receiver peerConnectionState state: ', pc.connectionState) - switch (pc.connectionState) { - case 'connected': - connectedPromise.resolve() - break - case 'failed': - case 'disconnected': - case 'closed': - connectedPromise.reject() - break - default: - break - } - } + resolveOnConnected(pc, connectedPromise) + // read an SDP offer const pbOffer = await stream.read() if (pbOffer.type !== pb.Message.Type.SDP_OFFER) { @@ -97,17 +83,7 @@ export async function connect ({ rtcConfiguration, signal, stream: rawStream }: // useful for debugging const connectedPromise = pDefer() - pc.onconnectionstatechange = (_) => { - switch (pc.connectionState) { - case 'connected': - { connectedPromise.resolve(); return } - case 'closed': - case 'disconnected': - case 'failed': - { connectedPromise.reject(); break } - default: - } - } + resolveOnConnected(pc, connectedPromise) // reject the connectedPromise if the signal aborts signal.onabort = connectedPromise.reject diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 1c867ce..d18e405 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -1,7 +1,7 @@ import type { Connection } from '@libp2p/interface-connection' import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' import type { ConnectionHandler, TransportManager, Upgrader } from '@libp2p/interface-transport' -import { multiaddr, Multiaddr } from '@multiformats/multiaddr' +import { multiaddr, Multiaddr, protocols } from '@multiformats/multiaddr' import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' import type { PeerId } from '@libp2p/interface-peer-id' import { WebRTCMultiaddrConnection } from '../maconn.js' @@ -15,13 +15,13 @@ const log = logger('libp2p:webrtc:peer') export const TRANSPORT = '/webrtc' export const PROTOCOL = '/webrtc-signaling/0.0.1' -export const CODE = 281 +export const CODE = protocols('webrtc').code -export interface WebRTCPeerTransportInit { +export interface WebRTCTransportInit { rtcConfiguration?: RTCConfiguration } -export interface WebRTCDirectTransportComponents { +export interface WebRTCTransportComponents { peerId: PeerId registrar: Registrar upgrader: Upgrader @@ -29,13 +29,13 @@ export interface WebRTCDirectTransportComponents { peerStore: PeerStore } -export class WebRTCDirectTransport implements Transport, Startable { +export class WebRTCTransport implements Transport, Startable { private _started = false private readonly handler?: ConnectionHandler constructor ( - private readonly components: WebRTCDirectTransportComponents, - private readonly init: WebRTCPeerTransportInit + private readonly components: WebRTCTransportComponents, + private readonly init: WebRTCTransportInit ) { this._onProtocol = this._onProtocol.bind(this) } diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index e95fe3f..4d0016b 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -1,6 +1,10 @@ import { logger } from '@libp2p/logger' import type { DeferredPromise } from 'p-defer' import * as pb from './pb/index.js' +import { detect } from 'detect-browser' + +const browser = detect() +const isFirefox = ((browser != null) && browser.name === 'firefox') interface MessageStream { read: () => Promise @@ -38,4 +42,39 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro } await connectedPromise.promise } -export {} + +export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise): void { + if (!isFirefox) { + pc.onconnectionstatechange = (_) => { + log.trace('receiver peerConnectionState state: ', pc.connectionState) + switch (pc.connectionState) { + case 'connected': + promise.resolve() + break + case 'failed': + case 'disconnected': + case 'closed': + promise.reject() + break + default: + break + } + } + } else { + pc.oniceconnectionstatechange = (_) => { + switch (pc.iceConnectionState) { + case 'connected': + promise.resolve() + break + case 'failed': + case 'disconnected': + case 'closed': + promise.reject() + break + default: + break + } + } + } +} +export { } diff --git a/src/transport.ts b/src/transport.ts index dd24d35..95d8c62 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -15,6 +15,7 @@ import type { WebRTCDialOptions } from './options.js' import * as sdp from './sdp.js' import { WebRTCStream } from './stream.js' import { genUfrag } from './util.js' +import { protocols } from '@multiformats/multiaddr' const log = logger('libp2p:webrtc:transport') @@ -28,30 +29,30 @@ const HANDSHAKE_TIMEOUT_MS = 10_000 * * {@link https://github.com/multiformats/multiaddr/blob/master/protocols.csv} */ -export const WEBRTC_CODE: number = 280 +export const WEBRTC_CODE: number = protocols('webrtc-direct').code /** * Created by converting the hexadecimal protocol code to an integer. * * {@link https://github.com/multiformats/multiaddr/blob/master/protocols.csv} */ -export const CERTHASH_CODE: number = 466 +export const CERTHASH_CODE: number = protocols('certhash').code /** * The peer for this transport */ // @TODO(ddimaria): seems like an unnessary abstraction, consider removing -export interface WebRTCTransportComponents { +export interface WebRTCDirectTransportComponents { peerId: PeerId } -export class WebRTCTransport implements Transport { +export class WebRTCDirectTransport implements Transport { /** * The peer for this transport */ - private readonly components: WebRTCTransportComponents + private readonly components: WebRTCDirectTransportComponents - constructor (components: WebRTCTransportComponents) { + constructor (components: WebRTCDirectTransportComponents) { this.components = components } diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index b4614cc..376989b 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -8,14 +8,14 @@ import { pbStream } from 'it-pb-stream' import sinon from 'sinon' import { connect, handleIncomingStream } from '../src/peer_transport/handler' import { Message } from '../src/peer_transport/pb/index.js' -import { WebRTCDirectTransport } from '../src/peer_transport/transport' +import { WebRTCTransport } from '../src/peer_transport/transport' import { detect } from 'detect-browser' const browser = detect() describe('webrtc basic', () => { - const runner: any = ((browser != null) && browser.name !== 'firefox') ? it : it.skip - runner('should connect', async () => { + const isFirefox = ((browser != null) && browser.name === 'firefox') + it('should connect', async () => { const [receiver, initiator] = duplexPair() const dstPeerId = await createEd25519PeerId() const connection = mockConnection( @@ -27,6 +27,11 @@ describe('webrtc basic', () => { await expect(initiatorPeerConnectionPromise).to.be.fulfilled() await expect(receiverPeerConnectionPromise).to.be.fulfilled() const [[pc0], [pc1]] = await Promise.all([initiatorPeerConnectionPromise, receiverPeerConnectionPromise]) + if (isFirefox) { + expect(pc0.iceConnectionState).eq('connected') + expect(pc1.iceConnectionState).eq('connected') + return + } expect(pc0.connectionState).eq('connected') expect(pc1.connectionState).eq('connected') }) @@ -89,7 +94,7 @@ describe('webrtc dialer', () => { describe('webrtc filter', () => { it('can filter multiaddrs to dial', async () => { - const transport = new WebRTCDirectTransport({ + const transport = new WebRTCTransport({ transportManager: sinon.stub() as any, peerId: sinon.stub() as any, registrar: mockRegistrar(), diff --git a/test/transport.browser.spec.ts b/test/transport.browser.spec.ts index a3a308c..ec7f1ef 100644 --- a/test/transport.browser.spec.ts +++ b/test/transport.browser.spec.ts @@ -15,7 +15,7 @@ function ignoredDialOption (): CreateListenerOptions { } describe('WebRTC Transport', () => { - let components: underTest.WebRTCTransportComponents + let components: underTest.WebRTCDirectTransportComponents before(async () => { components = { @@ -24,13 +24,13 @@ describe('WebRTC Transport', () => { }) it('can construct', () => { - const t = new underTest.WebRTCTransport(components) - expect(t.constructor.name).to.equal('WebRTCTransport') + const t = new underTest.WebRTCDirectTransport(components) + expect(t.constructor.name).to.equal('WebRTCDirectTransport') }) it('can dial', async () => { - const ma = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd') - const transport = new underTest.WebRTCTransport(components) + const ma = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd') + const transport = new underTest.WebRTCDirectTransport(components) const options = ignoredDialOption() // don't await as this isn't an e2e test @@ -38,7 +38,7 @@ describe('WebRTC Transport', () => { }) it('createListner throws', () => { - const t = new underTest.WebRTCTransport(components) + const t = new underTest.WebRTCDirectTransport(components) try { t.createListener(ignoredDialOption()) expect('Should have thrown').to.equal('but did not') @@ -48,13 +48,13 @@ describe('WebRTC Transport', () => { }) it('toString property getter', () => { - const t = new underTest.WebRTCTransport(components) + const t = new underTest.WebRTCDirectTransport(components) const s = t[Symbol.toStringTag] expect(s).to.equal('@libp2p/webrtc-direct') }) it('symbol property getter', () => { - const t = new underTest.WebRTCTransport(components) + const t = new underTest.WebRTCDirectTransport(components) const s = t[symbol] expect(s).to.equal(true) }) @@ -66,7 +66,7 @@ describe('WebRTC Transport', () => { '/ip4/1.2.3.4/udp/1234/webrtc-direct/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd', '/ip4/1.2.3.4/udp/1234/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd' ].map((s) => multiaddr(s)) - const t = new underTest.WebRTCTransport(components) + const t = new underTest.WebRTCDirectTransport(components) const result = t.filter(mas) const expected = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ/p2p/12D3KooWGDMwwqrpcYKpKCgxuKT2NfqPqa94QnkoBBpqvCaiCzWd') @@ -78,8 +78,8 @@ describe('WebRTC Transport', () => { }) it('throws WebRTC transport error when dialing a multiaddr without a PeerId', async () => { - const ma = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ') - const transport = new underTest.WebRTCTransport(components) + const ma = multiaddr('/ip4/1.2.3.4/udp/1234/webrtc-direct/certhash/uEiAUqV7kzvM1wI5DYDc1RbcekYVmXli_Qprlw3IkiEg6tQ') + const transport = new underTest.WebRTCDirectTransport(components) try { await transport.dial(ma, ignoredDialOption()) From 05c783d503e9279cb29729b6b0f491cd14edc53f Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 24 Mar 2023 21:14:03 +0530 Subject: [PATCH 35/52] more fixes --- examples/browser-to-browser/tests/test.js | 2 +- examples/browser-to-server/package.json | 2 +- examples/go-libp2p-server/go.mod | 1 + src/index.ts | 6 ++++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/browser-to-browser/tests/test.js b/examples/browser-to-browser/tests/test.js index f9c06d7..d24bd6e 100644 --- a/examples/browser-to-browser/tests/test.js +++ b/examples/browser-to-browser/tests/test.js @@ -79,7 +79,7 @@ play.describe('browser to browser example:', () => { await page.fill(connectAddr, newPeer) await page.click(connectBtn) - // send the relay message to the go libp2p server + // send the relay message to the peer over the relay await page.fill(messageInput, message) await page.click(sendBtn) diff --git a/examples/browser-to-server/package.json b/examples/browser-to-server/package.json index 70a1b25..1dfc40f 100644 --- a/examples/browser-to-server/package.json +++ b/examples/browser-to-server/package.json @@ -13,7 +13,7 @@ "@chainsafe/libp2p-noise": "^11.0.0", "@multiformats/multiaddr": "^12.0.0", "it-pushable": "^3.1.0", - "@libp2p/webrtc": "^1.0.3", + "@libp2p/webrtc": "file:../../", "libp2p": "^0.43.2", "vite": "^4.2.1" }, diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index be41be4..6854cfd 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -2,6 +2,7 @@ module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server go 1.18 +// TODO: Remove this once webrtc is merged into Go libp2p replace github.com/libp2p/go-libp2p v0.26.3 => github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a require github.com/libp2p/go-libp2p v0.26.3 diff --git a/src/index.ts b/src/index.ts index ef6600c..fcf78b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,10 +3,12 @@ import type { WebRTCTransportComponents, WebRTCTransportInit } from './peer_tran import { WebRTCTransport } from './peer_transport/transport.js' import { WebRTCDirectTransport, WebRTCDirectTransportComponents } from './transport.js' -export function webRTCDirect (): (components: WebRTCDirectTransportComponents) => Transport { +function webRTCDirect (): (components: WebRTCDirectTransportComponents) => Transport { return (components: WebRTCDirectTransportComponents) => new WebRTCDirectTransport(components) } -export function webRTC (init?: WebRTCTransportInit): (components: WebRTCTransportComponents) => Transport { +function webRTC (init?: WebRTCTransportInit): (components: WebRTCTransportComponents) => Transport { return (components: WebRTCTransportComponents) => new WebRTCTransport(components, init ?? {}) } + +export { webRTC, webRTCDirect } From eb64c85e66db9c1abe406ea4e566e7f227cf50f4 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 24 Mar 2023 21:22:43 +0530 Subject: [PATCH 36/52] fixes --- examples/browser-to-browser/package.json | 4 ++-- src/peer_transport/transport.ts | 10 ++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/examples/browser-to-browser/package.json b/examples/browser-to-browser/package.json index 3862be3..ecee66d 100644 --- a/examples/browser-to-browser/package.json +++ b/examples/browser-to-browser/package.json @@ -1,7 +1,7 @@ { - "name": "js-libp2p-webrtc-browser-to-server", + "name": "js-libp2p-webrtc-private-to-private", "version": "1.0.0", - "description": "Connect a browser to a server", + "description": "Connect a browser to another browser", "type": "module", "scripts": { "start": "vite", diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index d18e405..a470b88 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -1,6 +1,6 @@ import type { Connection } from '@libp2p/interface-connection' import { CreateListenerOptions, DialOptions, Listener, symbol, Transport } from '@libp2p/interface-transport' -import type { ConnectionHandler, TransportManager, Upgrader } from '@libp2p/interface-transport' +import type { TransportManager, Upgrader } from '@libp2p/interface-transport' import { multiaddr, Multiaddr, protocols } from '@multiformats/multiaddr' import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar' import type { PeerId } from '@libp2p/interface-peer-id' @@ -31,7 +31,6 @@ export interface WebRTCTransportComponents { export class WebRTCTransport implements Transport, Startable { private _started = false - private readonly handler?: ConnectionHandler constructor ( private readonly components: WebRTCTransportComponents, @@ -138,14 +137,13 @@ export class WebRTCTransport implements Transport, Startable { } async _onProtocol ({ connection, stream }: IncomingStreamData): Promise { - let conn try { const [pc, muxerFactory] = await handleIncomingStream({ rtcConfiguration: this.init.rtcConfiguration, connection, stream }) - conn = await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ + await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({ peerConnection: pc, timeline: { open: (new Date()).getTime() }, remoteAddr: connection.remoteAddr @@ -158,9 +156,5 @@ export class WebRTCTransport implements Transport, Startable { stream.reset() throw err } - - if (this.handler != null) { - this.handler(conn) - } } } From 9d831a8c9674fe7bfe8a1b55a7cbab3fe4238ddb Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Tue, 28 Mar 2023 16:41:01 +0530 Subject: [PATCH 37/52] fix review comments --- src/peer_transport/handler.ts | 3 +-- src/peer_transport/transport.ts | 12 ++++++------ src/peer_transport/util.ts | 1 - src/stream.ts | 2 -- test/peer.browser.spec.ts | 8 ++++---- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 1ad80ab..a24d29e 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -63,7 +63,6 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea // wait until candidates are connected await readCandidatesUntilConnected(connectedPromise, pc, stream) - // close the dummy channel return [pc, muxerFactory] } @@ -73,7 +72,7 @@ export interface ConnectOptions { rtcConfiguration?: RTCConfiguration } -export async function connect ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise<[RTCPeerConnection, StreamMuxerFactory]> { +export async function initiateConnection ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise<[RTCPeerConnection, StreamMuxerFactory]> { const stream = pbStream(abortableDuplex(rawStream, signal)).pb(pb.Message) // setup peer connection diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index a470b88..a8c59c9 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -9,7 +9,9 @@ import type { Startable } from '@libp2p/interfaces/startable' import { WebRTCPeerListener } from './listener.js' import type { PeerStore } from '@libp2p/interface-peer-store' import { logger } from '@libp2p/logger' -import { connect, handleIncomingStream } from './handler.js' +import { initiateConnection, handleIncomingStream } from './handler.js' +import { CodeError } from '@libp2p/interfaces/errors' +import { codes } from '../error.js' const log = logger('libp2p:webrtc:peer') @@ -85,8 +87,7 @@ export class WebRTCTransport implements Transport, Startable { log.trace('dialing address: ', ma) const addrs = ma.toString().split(TRANSPORT) if (addrs.length !== 2) { - // TODO(ckousik): Change to errCode - throw new Error('invalid multiaddr') + throw new CodeError('invalid multiaddr', codes.ERR_INVALID_MULTIADDR) } // look for remote peerId const remoteAddr = multiaddr(addrs[0]) @@ -94,8 +95,7 @@ export class WebRTCTransport implements Transport, Startable { const destinationIdString = destination.getPeerId() if (destinationIdString == null) { - // TODO(ckousik): Change to errCode - throw new Error('bad destination') + throw new CodeError('bad destination', codes.ERR_INVALID_MULTIADDR) } const controller = new AbortController() @@ -108,7 +108,7 @@ export class WebRTCTransport implements Transport, Startable { const rawStream = await connection.newStream([PROTOCOL], options) try { - const [pc, muxerFactory] = await connect({ + const [pc, muxerFactory] = await initiateConnection({ stream: rawStream, rtcConfiguration: this.init.rtcConfiguration, signal: options.signal diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index 4d0016b..f18b2f5 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -77,4 +77,3 @@ export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredProm } } } -export { } diff --git a/src/stream.ts b/src/stream.ts index ae77edd..e4cc1cb 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -421,8 +421,6 @@ export class WebRTCStream implements Stream { * @see this.closeWrite */ reset (): void { - // TODO Why are you resetting the stat here? - this.stat = defaultStat(this.stat.direction) const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: pb.Message_Flag.RESET }) if (currentState === nextState) { // No change, no op diff --git a/test/peer.browser.spec.ts b/test/peer.browser.spec.ts index 376989b..6c1dcde 100644 --- a/test/peer.browser.spec.ts +++ b/test/peer.browser.spec.ts @@ -6,7 +6,7 @@ import { pair } from 'it-pair' import { duplexPair } from 'it-pair/duplex' import { pbStream } from 'it-pb-stream' import sinon from 'sinon' -import { connect, handleIncomingStream } from '../src/peer_transport/handler' +import { initiateConnection, handleIncomingStream } from '../src/peer_transport/handler' import { Message } from '../src/peer_transport/pb/index.js' import { WebRTCTransport } from '../src/peer_transport/transport' import { detect } from 'detect-browser' @@ -22,7 +22,7 @@ describe('webrtc basic', () => { mockMultiaddrConnection(pair(), dstPeerId) ) const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ stream: mockStream(initiator), signal: controller.signal }) + const initiatorPeerConnectionPromise = initiateConnection({ stream: mockStream(initiator), signal: controller.signal }) const receiverPeerConnectionPromise = handleIncomingStream({ stream: mockStream(receiver), connection }) await expect(initiatorPeerConnectionPromise).to.be.fulfilled() await expect(receiverPeerConnectionPromise).to.be.fulfilled() @@ -56,7 +56,7 @@ describe('webrtc dialer', () => { it('should fail receiving on invalid sdp answer', async () => { const [receiver, initiator] = duplexPair() const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ signal: controller.signal, stream: mockStream(initiator) }) + const initiatorPeerConnectionPromise = initiateConnection({ signal: controller.signal, stream: mockStream(initiator) }) const stream = pbStream(receiver).pb(Message) { @@ -71,7 +71,7 @@ describe('webrtc dialer', () => { it('should fail on receiving a candidate before an answer', async () => { const [receiver, initiator] = duplexPair() const controller = new AbortController() - const initiatorPeerConnectionPromise = connect({ signal: controller.signal, stream: mockStream(initiator) }) + const initiatorPeerConnectionPromise = initiateConnection({ signal: controller.signal, stream: mockStream(initiator) }) const stream = pbStream(receiver).pb(Message) const pc = new RTCPeerConnection() From 08575d48ce1394efc34b2c436ad54f6da7af4b00 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 30 Mar 2023 11:02:40 -0700 Subject: [PATCH 38/52] Support dialing shorter circuit addrs --- src/peer_transport/transport.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index a8c59c9..e556940 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -90,7 +90,7 @@ export class WebRTCTransport implements Transport, Startable { throw new CodeError('invalid multiaddr', codes.ERR_INVALID_MULTIADDR) } // look for remote peerId - const remoteAddr = multiaddr(addrs[0]) + let remoteAddr = multiaddr(addrs[0]) const destination = multiaddr(addrs[1]) const destinationIdString = destination.getPeerId() @@ -103,6 +103,14 @@ export class WebRTCTransport implements Transport, Startable { options.signal = controller.signal } + const lastProtoInRemote = remoteAddr.protos().pop() + if (lastProtoInRemote === undefined) { + throw new CodeError('invalid multiaddr', codes.ERR_INVALID_MULTIADDR) + } + if (lastProtoInRemote.name !== 'p2p') { + remoteAddr = remoteAddr.encapsulate(`/p2p/${destinationIdString}`) + } + const connection = await this.components.transportManager.dial(remoteAddr) const rawStream = await connection.newStream([PROTOCOL], options) From f2df5583683b436d8a937b125ebffb2aa6e40acd Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 30 Mar 2023 11:06:00 -0700 Subject: [PATCH 39/52] Use shorter multiaddr in example --- examples/browser-to-browser/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index ba023b9..c87d791 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -1,4 +1,4 @@ -import { multiaddr } from "@multiformats/multiaddr" +import { multiaddr, protocols } from "@multiformats/multiaddr" import { pipe } from "it-pipe" import { fromString, toString } from "uint8arrays" import { webRTC } from "js-libp2p-webrtc" @@ -69,6 +69,9 @@ node.peerStore.addEventListener("change:multiaddrs", (event) => { node.getMultiaddrs().forEach((ma) => { if (ma.protoCodes().includes(CIRCUIT_RELAY_CODE)) { + if (ma.protos().pop()?.name === 'p2p') { + ma = ma.decapsulateCode(protocols('p2p').code) + } const newWebrtcDirectAddress = multiaddr(ma.toString() + '/webrtc/p2p/' + node.peerId) const webrtcAddrString = newWebrtcDirectAddress.toString() From a8efbfec70e97990271dae47ee608be02c814378 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Fri, 31 Mar 2023 16:23:52 +0530 Subject: [PATCH 40/52] add answerpromise --- src/peer_transport/handler.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index a24d29e..46125d5 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -24,13 +24,22 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea const muxerFactory = new DataChannelMuxerFactory(pc) const connectedPromise: DeferredPromise = pDefer() + const answerSentPromise: DeferredPromise = pDefer() + signal.onabort = () => { connectedPromise.reject() } // candidate callbacks pc.onicecandidate = ({ candidate }) => { - stream.write({ - type: pb.Message.Type.ICE_CANDIDATE, - data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' - }) + answerSentPromise.promise.then( + () => { + stream.write({ + type: pb.Message.Type.ICE_CANDIDATE, + data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : '' + }) + }, + (err) => { + log.error('cannot set candidate since sending answer failed', err) + } + ) } resolveOnConnected(pc, connectedPromise) @@ -52,15 +61,22 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea }) // create and write an SDP answer - const answer = await pc.createAnswer() + const answer = await pc.createAnswer().catch(err => { + log.error('could not execute createAnswer', err) + answerSentPromise.reject(err) + throw new Error('Failed to create answer') + }) // write the answer to the remote stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answer.sdp }) await pc.setLocalDescription(answer).catch(err => { log.error('could not execute setLocalDescription', err) + answerSentPromise.reject(err) throw new Error('Failed to set localDescription') }) + answerSentPromise.resolve() + // wait until candidates are connected await readCandidatesUntilConnected(connectedPromise, pc, stream) return [pc, muxerFactory] From 0a9f5d31711abf551c65ebcdccc561a86923cc73 Mon Sep 17 00:00:00 2001 From: Chinmay Kousik Date: Mon, 3 Apr 2023 17:39:29 +0530 Subject: [PATCH 41/52] Fix README for example --- examples/browser-to-browser/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/browser-to-browser/README.md b/examples/browser-to-browser/README.md index f24c036..866513c 100644 --- a/examples/browser-to-browser/README.md +++ b/examples/browser-to-browser/README.md @@ -2,6 +2,10 @@ This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. +## Build the `@libp2p/webrtc` package + +Build the `@libp2p/webrtc` package by calling `npm i && npm run build` in the repository root. + ## Running the Relay Server For browsers to communicate, we first need to run the LibP2P relay server: @@ -54,4 +58,4 @@ Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwK Received message 'helloa' Sending message 'hellob' Received message 'hellob' -``` \ No newline at end of file +``` From a86eb4bfb411821bca20ea5e3a7c6e60169770e6 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 3 Apr 2023 09:00:55 -0700 Subject: [PATCH 42/52] Remove singleton --- examples/browser-to-browser/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/browser-to-browser/index.js b/examples/browser-to-browser/index.js index c87d791..5341eb7 100644 --- a/examples/browser-to-browser/index.js +++ b/examples/browser-to-browser/index.js @@ -10,8 +10,6 @@ import { createLibp2p } from "libp2p" import { circuitRelayTransport } from 'libp2p/circuit-relay' import { noise } from "@chainsafe/libp2p-noise" -// singletons -let outgoing_stream let webrtcDirectAddress const CIRCUIT_RELAY_CODE = 290 @@ -100,7 +98,7 @@ window.connect.onclick = async () => { return } - outgoing_stream = await connection.newStream(["/echo/1.0.0"]) + const outgoing_stream = await connection.newStream(["/echo/1.0.0"]) pipe(sender, outgoing_stream, async (src) => { for await (const buf of src) { From 497e7e2f6c57d66a1dc0a308c67a0c4f2a78bbaf Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 3 Apr 2023 11:46:08 -0700 Subject: [PATCH 43/52] Type the promise --- examples/browser-to-server/tests/test.js | 4 ++-- src/peer_transport/handler.ts | 2 +- src/peer_transport/util.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/browser-to-server/tests/test.js b/examples/browser-to-server/tests/test.js index 3ff6ffd..15e2699 100644 --- a/examples/browser-to-server/tests/test.js +++ b/examples/browser-to-server/tests/test.js @@ -33,7 +33,7 @@ async function spawnGoLibp2p() { const addr = String(data).match(/p2p addr: ([^\s]*)/) if (addr !== null && addr.length > 0) { resolve(addr[1]) - } + } }) })) return { server, serverAddr } @@ -71,7 +71,7 @@ play.describe('bundle ipfs with parceljs:', () => { play('should connect to a go-libp2p node over webrtc', async ({ page }) => { const message = 'hello' - + // add the go libp2p multiaddress to the input field and submit await page.fill(connectAddr, serverAddr) await page.click(connectBtn) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 46125d5..997d8cd 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -97,7 +97,7 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra // the label is not relevant to connection initiation but can be // useful for debugging - const connectedPromise = pDefer() + const connectedPromise: DeferredPromise = pDefer() resolveOnConnected(pc, connectedPromise) // reject the connectedPromise if the signal aborts diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index f18b2f5..edc7388 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -13,7 +13,7 @@ interface MessageStream { const log = logger('libp2p:webrtc:peer:util') -export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream): Promise => { +export const readCandidatesUntilConnected = async (connectedPromise: DeferredPromise, pc: RTCPeerConnection, stream: MessageStream): Promise => { while (true) { const readResult = await Promise.race([connectedPromise.promise, stream.read()]) // check if readResult is a message @@ -43,7 +43,7 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro await connectedPromise.promise } -export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise): void { +export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise): void { if (!isFirefox) { pc.onconnectionstatechange = (_) => { log.trace('receiver peerConnectionState state: ', pc.connectionState) From 57ad0321adff62c59e1aaa537805c96ecfeb1bce Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 3 Apr 2023 13:43:04 -0700 Subject: [PATCH 44/52] Fix comment --- src/peer_transport/handler.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 997d8cd..54fadec 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -94,16 +94,15 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra // setup peer connection const pc = new RTCPeerConnection(rtcConfiguration) const muxerFactory = new DataChannelMuxerFactory(pc) - // the label is not relevant to connection initiation but can be - // useful for debugging const connectedPromise: DeferredPromise = pDefer() resolveOnConnected(pc, connectedPromise) // reject the connectedPromise if the signal aborts signal.onabort = connectedPromise.reject - // we create the channel so that the peerconnection has a component for - // which to collect candidates + // we create the channel so that the peerconnection has a component for which + // to collect candidates. The label is not relevant to connection initiation + // but can be useful for debugging const channel = pc.createDataChannel('init') // setup callback to write ICE candidates to the remote // peer From c30664b352069a62a67dcc0bb1fb7158992bc7ae Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 3 Apr 2023 13:46:14 -0700 Subject: [PATCH 45/52] Refactor: Consolidate event handlers in resolveOnConnected --- src/peer_transport/util.ts | 43 ++++++++++++-------------------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/src/peer_transport/util.ts b/src/peer_transport/util.ts index edc7388..862649a 100644 --- a/src/peer_transport/util.ts +++ b/src/peer_transport/util.ts @@ -44,36 +44,19 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro } export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise): void { - if (!isFirefox) { - pc.onconnectionstatechange = (_) => { - log.trace('receiver peerConnectionState state: ', pc.connectionState) - switch (pc.connectionState) { - case 'connected': - promise.resolve() - break - case 'failed': - case 'disconnected': - case 'closed': - promise.reject() - break - default: - break - } - } - } else { - pc.oniceconnectionstatechange = (_) => { - switch (pc.iceConnectionState) { - case 'connected': - promise.resolve() - break - case 'failed': - case 'disconnected': - case 'closed': - promise.reject() - break - default: - break - } + pc[isFirefox ? 'oniceconnectionstatechange' : 'onconnectionstatechange'] = (_) => { + log.trace('receiver peerConnectionState state: ', pc.connectionState) + switch (isFirefox ? pc.iceConnectionState : pc.connectionState) { + case 'connected': + promise.resolve() + break + case 'failed': + case 'disconnected': + case 'closed': + promise.reject() + break + default: + break } } } From 257101e22d77feb8115e90cc8842ac5ca09ddb11 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Mon, 3 Apr 2023 14:38:09 -0700 Subject: [PATCH 46/52] Nits --- src/peer_transport/handler.ts | 1 - src/peer_transport/transport.ts | 3 +-- src/stream.ts | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index 54fadec..b8e4d05 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -138,4 +138,3 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra channel.close() return [pc, muxerFactory] } -export { } diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index e556940..6d94146 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -38,7 +38,6 @@ export class WebRTCTransport implements Transport, Startable { private readonly components: WebRTCTransportComponents, private readonly init: WebRTCTransportInit ) { - this._onProtocol = this._onProtocol.bind(this) } isStarted (): boolean { @@ -98,8 +97,8 @@ export class WebRTCTransport implements Transport, Startable { throw new CodeError('bad destination', codes.ERR_INVALID_MULTIADDR) } - const controller = new AbortController() if (options.signal == null) { + const controller = new AbortController() options.signal = controller.signal } diff --git a/src/stream.ts b/src/stream.ts index e4cc1cb..2f61de9 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -455,8 +455,7 @@ export class WebRTCStream implements Stream { eq (stream: Stream): boolean { if (stream instanceof WebRTCStream) { - const s = stream - return s.channel.id === this.channel.id + return stream.channel.id === this.channel.id } return false } From 489876b3727d2af051d99c2e31c2947d73e5c091 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Tue, 4 Apr 2023 11:16:55 -0700 Subject: [PATCH 47/52] Update go multiaddr dep --- examples/go-libp2p-server/go.mod | 6 +++--- examples/go-libp2p-server/go.sum | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index 6854cfd..bf78c5a 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -29,7 +29,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/huin/goupnp v1.1.0 // indirect - github.com/ipfs/go-cid v0.4.0 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect @@ -55,7 +55,7 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr v0.8.0 // indirect + github.com/multiformats/go-multiaddr v0.9.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect @@ -108,7 +108,7 @@ require ( golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/sys v0.7.0 // indirect golang.org/x/text v0.8.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/examples/go-libp2p-server/go.sum b/examples/go-libp2p-server/go.sum index 7cbfb7c..0efb552 100644 --- a/examples/go-libp2p-server/go.sum +++ b/examples/go-libp2p-server/go.sum @@ -140,6 +140,8 @@ github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA= github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= @@ -238,6 +240,8 @@ github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -534,6 +538,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= From 256fc951d66b8bba061697e519b1a187a9d694fc Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Tue, 4 Apr 2023 11:50:36 -0700 Subject: [PATCH 48/52] Fix browser-to-server example --- examples/browser-to-server/tests/test.js | 7 +++---- examples/go-libp2p-server/go.mod | 2 +- examples/go-libp2p-server/go.sum | 10 ++-------- examples/go-libp2p-server/main.go | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/examples/browser-to-server/tests/test.js b/examples/browser-to-server/tests/test.js index 15e2699..8f304e7 100644 --- a/examples/browser-to-server/tests/test.js +++ b/examples/browser-to-server/tests/test.js @@ -91,13 +91,12 @@ play.describe('bundle ipfs with parceljs:', () => { const connections = await page.textContent(output) - // TODO: These are disabled until the webrtc protocol rename is completed in Go - // expect(connections).toContain(`Dialing '${serverAddr}'`) - // expect(connections).toContain(`Peer connected '${serverAddr}'`) + expect(connections).toContain(`Dialing '${serverAddr}'`) + expect(connections).toContain(`Peer connected '${serverAddr}'`) expect(connections).toContain(`Sending message '${message}'`) expect(connections).toContain(`Received message '${message}'`) }) -}) \ No newline at end of file +}) diff --git a/examples/go-libp2p-server/go.mod b/examples/go-libp2p-server/go.mod index bf78c5a..0742d25 100644 --- a/examples/go-libp2p-server/go.mod +++ b/examples/go-libp2p-server/go.mod @@ -3,7 +3,7 @@ module github.com/libp2p/js-libp2p-webrtc/examples/go-libp2p-server go 1.18 // TODO: Remove this once webrtc is merged into Go libp2p -replace github.com/libp2p/go-libp2p v0.26.3 => github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a +replace github.com/libp2p/go-libp2p => github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 require github.com/libp2p/go-libp2p v0.26.3 diff --git a/examples/go-libp2p-server/go.sum b/examples/go-libp2p-server/go.sum index 0efb552..3407f2e 100644 --- a/examples/go-libp2p-server/go.sum +++ b/examples/go-libp2p-server/go.sum @@ -8,8 +8,6 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a h1:kDV4AzT/08bsfnmbsIkxrFwyTCEGu4Q14o7VB5wDW/M= -github.com/GlenDC/go-libp2p v0.24.3-0.20230323141540-522fa8afe30a/go.mod h1:9sYpBoWyKexAe5mP6V92siMQ9v2DJAlQyJIGfqfnpeI= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= @@ -138,8 +136,6 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7 github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ipfs/go-cid v0.4.0 h1:a4pdZq0sx6ZSxbCizebnKiMCx/xI/aBBFlB73IgH4rA= -github.com/ipfs/go-cid v0.4.0/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= @@ -183,6 +179,8 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= +github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3 h1:PbtmtrIDY1Us9qeGJdHO1nfp0Jik1KZIP64/KYK43YI= +github.com/libp2p/go-libp2p v0.26.1-0.20230404184453-257fbfba50c3/go.mod h1:PwdLfPiWNhYkb96Wqc2uDFd/+0SGE07/IvjAoFiYG70= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= @@ -238,8 +236,6 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= -github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= @@ -536,8 +532,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/examples/go-libp2p-server/main.go b/examples/go-libp2p-server/main.go index 90d42fe..a5f99e6 100644 --- a/examples/go-libp2p-server/main.go +++ b/examples/go-libp2p-server/main.go @@ -82,7 +82,7 @@ func createHost() host.Host { h, err := libp2p.New( libp2p.Transport(webrtc.New), libp2p.ListenAddrStrings( - fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp), + fmt.Sprintf("/ip4/%s/udp/0/webrtc-direct", listenerIp), ), libp2p.DisableRelay(), libp2p.Ping(true), From 7b9e98f8e505921ddaf82ea58d8db325655c3fb9 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Tue, 4 Apr 2023 11:50:49 -0700 Subject: [PATCH 49/52] Nit --- src/peer_transport/handler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/peer_transport/handler.ts b/src/peer_transport/handler.ts index b8e4d05..659a847 100644 --- a/src/peer_transport/handler.ts +++ b/src/peer_transport/handler.ts @@ -47,7 +47,6 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea // read an SDP offer const pbOffer = await stream.read() if (pbOffer.type !== pb.Message.Type.SDP_OFFER) { - // TODO: Find better way to print undefined without linter complaining throw new Error(`expected message type SDP_OFFER, received: ${pbOffer.type ?? 'undefined'} `) } const offer = new RTCSessionDescription({ From 57779d4e726cd2b6cb14c35bea15f9da8d0769c5 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 6 Apr 2023 15:38:19 -0700 Subject: [PATCH 50/52] Workaround to not listen on p2p-circuit --- src/transport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport.ts b/src/transport.ts index 95d8c62..6c6a452 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -239,5 +239,5 @@ export class WebRTCDirectTransport implements Transport { */ function validMa (ma: Multiaddr): boolean { const codes = ma.protoCodes() - return codes.includes(WEBRTC_CODE) && codes.includes(CERTHASH_CODE) && ma.getPeerId() != null + return codes.includes(WEBRTC_CODE) && codes.includes(CERTHASH_CODE) && ma.getPeerId() != null && !codes.includes(protocols('p2p-circuit').code) } From 218427519d219194b1370f34d4f0df73c5b5773f Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Thu, 6 Apr 2023 16:04:20 -0700 Subject: [PATCH 51/52] workaround: Fix multiaddr splitting --- src/peer_transport/transport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index 6d94146..baac6af 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -84,13 +84,13 @@ export class WebRTCTransport implements Transport, Startable { */ async dial (ma: Multiaddr, options: DialOptions): Promise { log.trace('dialing address: ', ma) - const addrs = ma.toString().split(TRANSPORT) + const addrs = ma.toString().split(`${TRANSPORT}/`) if (addrs.length !== 2) { throw new CodeError('invalid multiaddr', codes.ERR_INVALID_MULTIADDR) } // look for remote peerId let remoteAddr = multiaddr(addrs[0]) - const destination = multiaddr(addrs[1]) + const destination = multiaddr('/' + addrs[1]) const destinationIdString = destination.getPeerId() if (destinationIdString == null) { From 2f77031feb146ae2a5d842453f25288391558e66 Mon Sep 17 00:00:00 2001 From: Marco Munizaga Date: Fri, 7 Apr 2023 13:40:53 -0700 Subject: [PATCH 52/52] Small rename cleanup --- src/peer_transport/transport.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/peer_transport/transport.ts b/src/peer_transport/transport.ts index baac6af..05b2590 100644 --- a/src/peer_transport/transport.ts +++ b/src/peer_transport/transport.ts @@ -16,7 +16,7 @@ import { codes } from '../error.js' const log = logger('libp2p:webrtc:peer') export const TRANSPORT = '/webrtc' -export const PROTOCOL = '/webrtc-signaling/0.0.1' +export const SIGNALING_PROTO_ID = '/webrtc-signaling/0.0.1' export const CODE = protocols('webrtc').code export interface WebRTCTransportInit { @@ -45,14 +45,14 @@ export class WebRTCTransport implements Transport, Startable { } async start (): Promise { - await this.components.registrar.handle(PROTOCOL, (data) => { + await this.components.registrar.handle(SIGNALING_PROTO_ID, (data) => { this._onProtocol(data).catch(err => { log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) }) }) this._started = true } async stop (): Promise { - await this.components.registrar.unhandle(PROTOCOL) + await this.components.registrar.unhandle(SIGNALING_PROTO_ID) this._started = false } @@ -112,7 +112,7 @@ export class WebRTCTransport implements Transport, Startable { const connection = await this.components.transportManager.dial(remoteAddr) - const rawStream = await connection.newStream([PROTOCOL], options) + const rawStream = await connection.newStream([SIGNALING_PROTO_ID], options) try { const [pc, muxerFactory] = await initiateConnection({