Skip to content
This repository has been archived by the owner on Jun 19, 2023. It is now read-only.

fix: Fetch local fingerprint from SDP #109

Merged
merged 12 commits into from
May 3, 2023

Conversation

ckousik
Copy link
Collaborator

@ckousik ckousik commented Apr 3, 2023

Since firefox does not support getFingerprints, we fetch the local fingerprint from the PeerConnection's localDescription field by parsing the fingerprint line from the SDP.

@p-shahi p-shahi linked an issue Apr 3, 2023 that may be closed by this pull request
@ckousik ckousik marked this pull request as ready for review April 4, 2023 06:47
Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this.

src/sdp.ts Outdated
Comment on lines 10 to 13
// import { detect } from 'detect-browser'

// const browser = detect()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over to be removed, right?

Comment on lines -215 to -241
if (localCert === undefined || localCert.getFingerprints().length === 0) {
throw invalidArgument('no fingerprint on local certificate')
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how this is handled in the js-libp2p codebase in general. Should we still use localCert.getFingerprints in case the API is available (e.g. on Chrome), or should we always use the hack through the SDP?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer the single code path across browsers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would prefer trying to use the best option and falling back on the hack. But not blocking this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Marco here, but it would be good to know (debug logs) which option was used if we're going to have different paths.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SgtPooki I've added the fallback to fetching from the SDP as requested.

@mxinden
Copy link
Member

mxinden commented Apr 9, 2023

@achingbrain @MarcoPolo any objections to merging here?

Copy link
Contributor

@MarcoPolo MarcoPolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have firefox run this test in CI?

src/sdp.ts Outdated
Comment on lines 26 to 53
const fingerprintRegex = /^a=fingerprint:(?:\w+-[0-9]+)\s(?<fingerprint>(:?[0-9a-fA-F]{2})+)$/gm
function getFingerprintFromSdp (sdp: string): string | undefined {
const searchResult = fingerprintRegex.exec(sdp)
if (searchResult == null) {
return ''
}

return searchResult.groups?.fingerprint
}
Copy link
Member

@SgtPooki SgtPooki Apr 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer regex.match.

Using /g flag with exec can cause unexpected issues with the stored lastIndex being updated and then causing match failures in later .exec calls.

JavaScript RegExp objects are stateful when they have the global or sticky flags set (e.g. /foo/g or /foo/y). They store a lastIndex from the previous match. Using this internally, exec() can be used to iterate over multiple matches in a string of text (with capture groups), as opposed to getting just the matching strings with String.prototype.match().

see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#description

Also see https://stackoverflow.com/a/3811949/592760

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @SgtPooki . I was not aware of this. I've incorporated the change and added a simple test.

src/sdp.ts Outdated
Comment on lines 26 to 28
const fingerprintRegex = /^a=fingerprint:(?:\w+-[0-9]+)\s(?<fingerprint>(:?[0-9a-fA-F]{2})+)$/gm
function getFingerprintFromSdp (sdp: string): string | undefined {
const searchResult = fingerprintRegex.exec(sdp)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const fingerprintRegex = /^a=fingerprint:(?:\w+-[0-9]+)\s(?<fingerprint>(:?[0-9a-fA-F]{2})+)$/gm
function getFingerprintFromSdp (sdp: string): string | undefined {
const searchResult = fingerprintRegex.exec(sdp)
const fingerprintRegex = /^a=fingerprint:(?:\w+-[0-9]+)\s(?<fingerprint>(:?[0-9a-fA-F]{2})+)$/m
function getFingerprintFromSdp (sdp: string): string | undefined {
const searchResult = sdp.match(fingerprintRegex)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Since firefox does not support `getFingerprints`, we fetch the local
fingerprint from the PeerConnection's `localDescription` field by
parsing the fingerprint line from the SDP.
@ckousik ckousik force-pushed the ckousik/fix-local-fingerprint-from-sdp branch from 7e26a4c to 3c87add Compare April 18, 2023 11:32
@ckousik ckousik requested a review from SgtPooki April 18, 2023 11:33
@p-shahi p-shahi requested a review from MarcoPolo April 18, 2023 21:33
@p-shahi
Copy link
Member

p-shahi commented Apr 18, 2023

@MarcoPolo ping to re-review

@ckousik
Copy link
Collaborator Author

ckousik commented Apr 19, 2023

@MarcoPolo I'm still working on firefox browser-to-server tests in CI. Could we move that work to a subsequent PR?

@ckousik
Copy link
Collaborator Author

ckousik commented Apr 24, 2023

@MarcoPolo The browser-to-server tests is running on Firefox in CI.

Copy link
Member

@SgtPooki SgtPooki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not an expert in the business logic of what is going on here, but i ran through the code and found a single potential failure that should be addressed.

src/sdp.ts Outdated
Comment on lines 47 to 52
const searchResult = sdp.match(fingerprintRegex)
if (searchResult == null) {
return ''
}

return searchResult.groups?.fingerprint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'' == null // false

Returning '' on line 49 will cause the check on line 215 in src/transports.ts, if (localFingerprint == null) { to return false. We should return undefined here, or even better:

Suggested change
const searchResult = sdp.match(fingerprintRegex)
if (searchResult == null) {
return ''
}
return searchResult.groups?.fingerprint
const searchResult = sdp.match(fingerprintRegex)
return searchResult?.groups?.fingerprint

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@@ -53,6 +53,11 @@ describe('SDP', () => {
])
})

it('extracts a fingerprint from sdp', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should add a negative test here to validate the fallback behaviour

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this just tests the regex behaviour. While there are no explicit tests for the fallback behaviour, it gets tested when the tests are run in Firefox as part of CI.

Copy link
Member

@SgtPooki SgtPooki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm but i’ll defer to primary maintainers for final approval

@p-shahi
Copy link
Member

p-shahi commented May 1, 2023

@MarcoPolo bump!

src/transport.ts Outdated
source: {
[Symbol.asyncIterator]: async function * () {
for await (const list of wrappedChannel.source) {
yield list.subarray()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may copy unnecessarily (I know this was here before).

src/stream.ts Show resolved Hide resolved
src/transport.ts Outdated Show resolved Hide resolved
examples/browser-to-server/package.json Outdated Show resolved Hide resolved
@MarcoPolo
Copy link
Contributor

Thanks a lot @SgtPooki! Your review was very helpful :)

And thanks @wemeetagain for taking a look

@MarcoPolo MarcoPolo dismissed SgtPooki’s stale review May 2, 2023 20:20

they gave a lgtm

@MarcoPolo MarcoPolo merged commit 3673d6c into main May 3, 2023
@MarcoPolo MarcoPolo deleted the ckousik/fix-local-fingerprint-from-sdp branch May 3, 2023 00:13
github-actions bot pushed a commit that referenced this pull request May 3, 2023
## [1.1.10](v1.1.9...v1.1.10) (2023-05-03)

### Bug Fixes

* Fetch local fingerprint from SDP ([#109](#109)) ([3673d6c](3673d6c))
@github-actions
Copy link

github-actions bot commented May 3, 2023

🎉 This PR is included in version 1.1.10 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Firefox fails in browser-to-server
6 participants