webrtc icon indicating copy to clipboard operation
webrtc copied to clipboard

Implement `GetRemoteCertificate` for `DTLSTransport` in wasm

Open v1rtl opened this issue 8 months ago • 5 comments

Description

Implements basic support for GetRemoteCertificate using getRemoteCertificates

I'm not sure how to write tests for it, do I mock JS globals?

Reference issue

Partially addresses https://github.com/libp2p/go-libp2p/issues/3277

v1rtl avatar May 05 '25 20:05 v1rtl

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests. :white_check_mark: Project coverage is 84.30%. Comparing base (0936b7d) to head (8d685da). :warning: Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3119      +/-   ##
==========================================
- Coverage   84.35%   84.30%   -0.05%     
==========================================
  Files          80       80              
  Lines        9133     9133              
==========================================
- Hits         7704     7700       -4     
- Misses       1011     1014       +3     
- Partials      418      419       +1     
Flag Coverage Δ
go 84.30% <ø> (-0.05%) :arrow_down:

Flags with carried forward coverage won't be shown. Click here to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar May 05 '25 20:05 codecov[bot]

@talentlessguy that sounds good to me! However you think is best to test it.

The WASM stuff can be frustrating. So w/e works I am in support of :)

Sean-Der avatar May 06 '25 01:05 Sean-Der

This demo in JavaScript works:

function bufferToHex(buffer) {
  const byteArray = new Uint8Array(buffer)
  return Array.from(byteArray)
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('')
    .toUpperCase()
}

async function run() {
  const pcConfig = {
    iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
  }

  const localPC = new RTCPeerConnection(pcConfig)
  const remotePC = new RTCPeerConnection(pcConfig)

  const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
  const [track] = stream.getAudioTracks()
  localPC.addTrack(track, stream)

  localPC.onicecandidate = (e) => {
    if (e.candidate) remotePC.addIceCandidate(e.candidate)
  }
  remotePC.onicecandidate = (e) => {
    if (e.candidate) localPC.addIceCandidate(e.candidate)
  }

  localPC.onconnectionstatechange = () => {
    console.log('Connection state changed:', localPC.connectionState)
    if (localPC.connectionState === 'connected') {
      const [sender] = localPC.getSenders()
      if (sender?.transport instanceof RTCDtlsTransport) {
        const dtlsTransport = sender.transport
        const certs = dtlsTransport.getRemoteCertificates()
        if (certs.length > 0) {
          console.log(`Got ${certs.length} remote certificate(s):`) // Got 1 remote certificate
          certs.forEach((cert, i) => {
            console.log(`Certificate ${i + 1}:\n${bufferToHex(cert)}`) // DER raw cert
          })
        } else {
          console.warn('No remote certificates returned.')
        }
      } else {
        console.warn('DTLS transport not available.')
      }
    }
  }

  const offer = await localPC.createOffer()
  await localPC.setLocalDescription(offer)
  await remotePC.setRemoteDescription(offer)
  const answer = await remotePC.createAnswer()
  await remotePC.setLocalDescription(answer)
  await localPC.setRemoteDescription(answer)
}

run().catch(console.error)

Outputs a DER certificate

I'll try to write tests based on this demo. I'm also not sure if pion/webrtc implements onconnectionstatechange event listening for JS, at least I haven't seen it anywhere

v1rtl avatar May 06 '25 13:05 v1rtl

OnConnectionStateChange is available for the WASM PeerConnection. Is it not working for you?

Sean-Der avatar May 06 '25 13:05 Sean-Der

OnConnectionStateChange is available for the WASM PeerConnection. Is it not working for you?

I haven't tested it personally yet. I will try to recreate the demo using Go+WASM soon-ish to make sure it works exactly the same, and then write tests that will mock Web APIs

v1rtl avatar May 06 '25 13:05 v1rtl

@v1rtl hello, I'm adding a mock and merging this right now.

JoTurk avatar Dec 04 '25 17:12 JoTurk

thank you for taking over the PR! sadly don't have enough time to finish it

v1rtl avatar Dec 06 '25 22:12 v1rtl

I'm out today but I'll push the tests and finish it once I'm home

JoTurk avatar Dec 06 '25 23:12 JoTurk

@Sean-Der for 4.3 I think we should aim to have a real browser wasm test runner, for chrome, firefox and safari, we can run it on the CI, also maybe we should start aiming for supporting WASI wasm soon :eyes:

JoTurk avatar Dec 10 '25 10:12 JoTurk