From 0aa9dc46dd02bbc7d3b07896c40ca44ba72dac76 Mon Sep 17 00:00:00 2001 From: John Turpish Date: Tue, 9 Aug 2022 10:19:54 -0400 Subject: [PATCH 1/4] This looks right-ish to me. Need better error type and testing. --- src/sdp.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sdp.ts b/src/sdp.ts index 31920ab..31f707b 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -66,8 +66,14 @@ export function fromMultiAddr(ma: Multiaddr, ufrag: string): RTCSessionDescripti }; } -export function munge(desc: RTCSessionDescription, ufrag: string) { - //TODO - desc.sdp.replaceAll(/^a=ice-ufrag=(.*)/, 'a=ice-ufrag=' + ufrag); - desc.sdp.replaceAll(/^a=ice-pwd=(.*)/, 'a=ice-pwd=' + ufrag); +export function munge(desc: RTCSessionDescriptionInit, ufrag: string): RTCSessionDescriptionInit { + if (desc.sdp) { + desc.sdp = desc.sdp + .replace(/^a=ice-ufrag:.*$/, 'a=ice-ufrag:' + ufrag) + .replace(/^a=ice-pwd:.*$/, 'a=ice-pwd:' + ufrag) + ; + return desc; + } else { + throw Error("Can't munge a missing SDP"); + } } From fbce43c81b3843001f74efe6f82e5407db57caef Mon Sep 17 00:00:00 2001 From: John Turpish Date: Tue, 9 Aug 2022 16:42:21 -0400 Subject: [PATCH 2/4] Added an SDP test to get started. --- package.json | 2 ++ src/sdp.ts | 33 ++++++++++++++++++--------------- src/stream.ts | 9 +++++---- test/node.js | 6 ------ test/sdp.spec.ts | 27 +++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 25 deletions(-) delete mode 100644 test/node.js create mode 100644 test/sdp.spec.ts diff --git a/package.json b/package.json index 9d5f002..46cadc0 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,12 @@ "typescript": "^4.7.4" }, "dependencies": { + "@multiformats/multiaddr": "../js-multiaddr/", "@libp2p/components": "^2.0.1", "@libp2p/interface-transport": "^1.0.2", "@libp2p/interfaces": "^3.0.3", "@libp2p/logger": "^2.0.0", + "abortable-iterator": "^4.0.2", "it-merge": "^1.0.4", "p-defer": "^4.0.0", diff --git a/src/sdp.ts b/src/sdp.ts index 31f707b..d3693cc 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -3,7 +3,8 @@ import { Multiaddr } from '@multiformats/multiaddr'; const log = logger('libp2p:webrtc:sdp'); -const P_XWEBRTC: number = 0x115; +// const P_WEBRTC: number = 0x115; +const CERTHASH_CODE: number = 466; const ANSWER_SDP_FORMAT: string = ` v=0 o=- 0 0 IN %s %s @@ -37,31 +38,33 @@ function port(ma: Multiaddr): number { return ma.toOptions().port; } function certhash(ma: Multiaddr): string { - let webrtc_value = ma - .stringTuples() - .filter((tup) => tup[0] == P_XWEBRTC) + let tups = ma.stringTuples(); + let certhash_value = tups + .filter((tup) => tup[0] == CERTHASH_CODE) .map((tup) => tup[1])[0]; - if (webrtc_value) { - return webrtc_value.split('/')[1]; + if (certhash_value) { + console.log(certhash_value); + return certhash_value; } else { throw new Error("Couldn't find a webrtc component of multiaddr:" + ma.toString()); } } function ma2sdp(ma: Multiaddr, ufrag: string): string { - return ANSWER_SDP_FORMAT.replace('/%s/', ipv(ma)) - .replace('/%s/', ip(ma)) - .replace('/%s/', ipv(ma)) - .replace('/%s/', ip(ma)) - .replace('/%s/', port(ma).toString()) - .replace('/%s/', ufrag) - .replace('/%s/', ufrag) - .replace('/%s/', certhash(ma)); + return ANSWER_SDP_FORMAT + .replace('%s', ipv(ma)) + .replace('%s', ip(ma)) + .replace('%s', ipv(ma)) + .replace('%s', ip(ma)) + .replace('%d', port(ma).toString()) + .replace('%s', ufrag) + .replace('%s', ufrag) + .replace('%s', certhash(ma)); } export function fromMultiAddr(ma: Multiaddr, ufrag: string): RTCSessionDescriptionInit { return { - type: 'offer', + type: 'answer', sdp: ma2sdp(ma, ufrag), }; } diff --git a/src/stream.ts b/src/stream.ts index 685bbe2..ae44495 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -6,6 +6,7 @@ import { Sink } from 'it-stream-types'; import { pushable, Pushable } from 'it-pushable'; import defer, { DeferredPromise } from 'p-defer'; import merge from 'it-merge'; +import { Uint8ArrayList } from 'uint8arraylist' // const log = logger('libp2p:webrtc:connection'); @@ -32,8 +33,8 @@ export class WebRTCStream implements Stream { metadata: Record; private readonly channel: RTCDataChannel; - source: Source = pushable(); - sink: Sink>; + source: Source = pushable(); + sink: Sink>; // promises opened: DeferredPromise = defer(); @@ -89,7 +90,7 @@ export class WebRTCStream implements Stream { }; } - private async _sinkFn(src: Source): Promise { + private async _sinkFn(src: Source): Promise { await this.opened.promise; if (closed || this.writeClosed) { return; @@ -107,7 +108,7 @@ export class WebRTCStream implements Stream { if (closed || this.writeClosed) { break; } - this.channel.send(buf); + this.channel.send(buf.subarray()); } } diff --git a/test/node.js b/test/node.js deleted file mode 100644 index 5c78a05..0000000 --- a/test/node.js +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-env mocha */ - -export {} - -describe('noop', () => { -}) diff --git a/test/sdp.spec.ts b/test/sdp.spec.ts new file mode 100644 index 0000000..731ab28 --- /dev/null +++ b/test/sdp.spec.ts @@ -0,0 +1,27 @@ +import { Multiaddr } from '@multiformats/multiaddr'; +import { expect } from 'chai'; +import * as underTest from '../src/sdp.js'; + +describe('SDP creation', () => { + it('handles simple blue sky easily enough', async () => { + let ma = new Multiaddr('/ip4/192.168.0.152/udp/2345/webrtc/certhash/zYAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt'); + let ufrag = 'MyUserFragment'; + let sdp = underTest.fromMultiAddr(ma, ufrag); + expect(sdp.sdp).to.equal(` +v=0 +o=- 0 0 IN IP4 192.168.0.152 +s=- +c=IN IP4 192.168.0.152 +t=0 0 +m=application 2345 UDP/DTLS/SCTP webrtc-datachannel +a=mid:0 +a=ice-options:ice2 +a=ice-ufrag:MyUserFragment +a=ice-pwd:MyUserFragment +a=fingerprint:YAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt +a=setup:actpass +a=sctp-port:5000 +a=max-message-size:100000 +`); + }); +}); From 2a8f5afe92a2c0eb192acd101aceb2d1ca33b6e7 Mon Sep 17 00:00:00 2001 From: John Turpish Date: Wed, 10 Aug 2022 14:16:07 -0400 Subject: [PATCH 3/4] Testing was indeed quite useful. --- src/sdp.ts | 5 ++--- test/sdp.spec.ts | 34 +++++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/sdp.ts b/src/sdp.ts index d3693cc..2e77028 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -43,7 +43,6 @@ function certhash(ma: Multiaddr): string { .filter((tup) => tup[0] == CERTHASH_CODE) .map((tup) => tup[1])[0]; if (certhash_value) { - console.log(certhash_value); return certhash_value; } else { throw new Error("Couldn't find a webrtc component of multiaddr:" + ma.toString()); @@ -72,8 +71,8 @@ export function fromMultiAddr(ma: Multiaddr, ufrag: string): RTCSessionDescripti export function munge(desc: RTCSessionDescriptionInit, ufrag: string): RTCSessionDescriptionInit { if (desc.sdp) { desc.sdp = desc.sdp - .replace(/^a=ice-ufrag:.*$/, 'a=ice-ufrag:' + ufrag) - .replace(/^a=ice-pwd:.*$/, 'a=ice-pwd:' + ufrag) + .replace(/\na=ice-ufrag:[^\n]*\n/, '\na=ice-ufrag:' + ufrag + '\n') + .replace(/\na=ice-pwd:[^\n]*\n/, '\na=ice-pwd:' + ufrag + '\n') ; return desc; } else { diff --git a/test/sdp.spec.ts b/test/sdp.spec.ts index 731ab28..f576a9e 100644 --- a/test/sdp.spec.ts +++ b/test/sdp.spec.ts @@ -2,12 +2,36 @@ import { Multiaddr } from '@multiformats/multiaddr'; import { expect } from 'chai'; import * as underTest from '../src/sdp.js'; +const an_sdp = ` +v=0 +o=- 0 0 IN IP4 192.168.0.152 +s=- +c=IN IP4 192.168.0.152 +t=0 0 +m=application 2345 UDP/DTLS/SCTP webrtc-datachannel +a=mid:0 +a=ice-options:ice2 +a=ice-ufrag:MyUserFragment +a=ice-pwd:MyUserFragment +a=fingerprint:mTXVsdGliYXNlIGlzIGF3ZXNvbWUhIFxvLw +a=setup:actpass +a=sctp-port:5000 +a=max-message-size:100000 +`; + describe('SDP creation', () => { it('handles simple blue sky easily enough', async () => { let ma = new Multiaddr('/ip4/192.168.0.152/udp/2345/webrtc/certhash/zYAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt'); let ufrag = 'MyUserFragment'; let sdp = underTest.fromMultiAddr(ma, ufrag); - expect(sdp.sdp).to.equal(` + expect(sdp.sdp).to.equal(an_sdp); + }); +}); + +describe('SDP munging', () => { + it('does a simple replacement', () => { + let result = underTest.munge({type:'answer',sdp: an_sdp},'someotheruserfragmentstring'); + expect(result.sdp).to.equal(` v=0 o=- 0 0 IN IP4 192.168.0.152 s=- @@ -16,12 +40,12 @@ t=0 0 m=application 2345 UDP/DTLS/SCTP webrtc-datachannel a=mid:0 a=ice-options:ice2 -a=ice-ufrag:MyUserFragment -a=ice-pwd:MyUserFragment -a=fingerprint:YAjKoNbau5KiqmHPmSxYCvn66dA1vLmwbt +a=ice-ufrag:someotheruserfragmentstring +a=ice-pwd:someotheruserfragmentstring +a=fingerprint:mTXVsdGliYXNlIGlzIGF3ZXNvbWUhIFxvLw a=setup:actpass a=sctp-port:5000 a=max-message-size:100000 `); - }); + }); }); From 42e393e124125280cbaa71a8dfd60fa838fbf984 Mon Sep 17 00:00:00 2001 From: John Turpish Date: Wed, 10 Aug 2022 14:29:27 -0400 Subject: [PATCH 4/4] Error types --- src/error.ts | 13 +++++++++++++ src/sdp.ts | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/error.ts diff --git a/src/error.ts b/src/error.ts new file mode 100644 index 0000000..c973d34 --- /dev/null +++ b/src/error.ts @@ -0,0 +1,13 @@ +export class WebRTCTransportError extends Error { + constructor(msg: string) { + super(msg); + this.name = 'WebRTCTransportError'; + } +} + +export class InvalidArgumentError extends WebRTCTransportError { + constructor(msg: string) { + super(msg); + this.name = 'WebRTC/InvalidArgumentError'; + } +} \ No newline at end of file diff --git a/src/sdp.ts b/src/sdp.ts index 2e77028..3038ce2 100644 --- a/src/sdp.ts +++ b/src/sdp.ts @@ -1,3 +1,4 @@ +import { InvalidArgumentError } from './error.js' import { logger } from '@libp2p/logger'; import { Multiaddr } from '@multiformats/multiaddr'; @@ -76,6 +77,6 @@ export function munge(desc: RTCSessionDescriptionInit, ufrag: string): RTCSessio ; return desc; } else { - throw Error("Can't munge a missing SDP"); + throw new InvalidArgumentError("Can't munge a missing SDP"); } }