Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically set ice ips #663

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/libs/blueos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,23 @@ export const setKeyDataOnCockpitVehicleStorage = async (

await setCockpitStorageOnVehicle(vehicleAddress, newVehicleStorage)
}

/* eslint-disable jsdoc/require-jsdoc */
type RawIpInfo = { ip: string; service_type: string; interface_type: string }
type IpInfo = { ipv4Address: string; interfaceType: string }
/* eslint-enable jsdoc/require-jsdoc */

export const getIpsInformationFromVehicle = async (vehicleAddress: string): Promise<IpInfo[]> => {
try {
const response = await fetch(`http://${vehicleAddress}/beacon/v1.0/services`)
if (!(await response.ok)) {
throw new Error(await response.text())
}
const rawIpsInfo: RawIpInfo[] = await response.json()
return rawIpsInfo
.filter((ipInfo) => ipInfo['service_type'] === '_http')
.map((ipInfo) => ({ ipv4Address: ipInfo.ip, interfaceType: ipInfo.interface_type }))
} catch (error) {
throw new Error(`Could not get information about IPs on BlueOS. ${error}`)
}
}
76 changes: 54 additions & 22 deletions src/stores/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { computed, ref, watch } from 'vue'
import adapter from 'webrtc-adapter'

import { WebRTCManager } from '@/composables/webRTC'
import { getIpsInformationFromVehicle } from '@/libs/blueos'
import { datalogger } from '@/libs/sensors-logging'
import { isEqual } from '@/libs/utils'
import { useMainVehicleStore } from '@/stores/mainVehicle'
Expand All @@ -17,7 +18,7 @@ import type { StreamData } from '@/types/video'

export const useVideoStore = defineStore('video', () => {
const { missionName } = useMissionStore()
const { rtcConfiguration, webRTCSignallingURI } = useMainVehicleStore()
const { globalAddress, rtcConfiguration, webRTCSignallingURI } = useMainVehicleStore()
console.debug('[WebRTC] Using webrtc-adapter for', adapter.browserDetails)

const allowedIceIps = useStorage<string[]>('cockpit-allowed-stream-ips', [])
Expand Down Expand Up @@ -230,30 +231,61 @@ export const useVideoStore = defineStore('video', () => {
})

// Routine to make sure the user has chosen the allowed ICE candidate IPs, so the stream works as expected
const iceIpCheckInterval = setInterval(() => {
// Pass if there are no available IPs yet or if the user has already set the allowed ones
if (availableIceIps.value === undefined || !allowedIceIps.value.isEmpty()) {
let warningTimeout: NodeJS.Timeout | undefined = undefined
const iceIpCheckInterval = setInterval(async (): Promise<void> => {
// Pass if there are no available IPs yet
if (availableIceIps.value === undefined) return

// Cancel the check if the user has already set the allowed ICE IPs
if (!allowedIceIps.value.isEmpty()) {
clearInterval(iceIpCheckInterval)
clearTimeout(warningTimeout)
return
}
// If there's more than one IP candidate available, send a warning an clear the check routine

// If there's more than one IP candidate available, try getting information about them from BlueOS. If not
// available, send a warning an clear the check routine.
if (availableIceIps.value.length >= 1) {
Swal.fire({
html: `
<p>Cockpit detected more than one IP address being used to route the video streaming. This often
leads to video stuttering, especially if one of the IPs is from a non-wired connection.</p>
</br>
<p>To prevent issues and achieve an optimal streaming experience, please:</p>
<ol>
<li>1. Open the video configuration page (Main-menu > Configuration > Video).</li>
<li>2. Select the IP address that should be used for the video streaming.</li>
</ol>
`,
icon: 'warning',
customClass: {
htmlContainer: 'text-left',
},
})
clearInterval(iceIpCheckInterval)
try {
const ipsInfo = await getIpsInformationFromVehicle(globalAddress)
ipsInfo.forEach((ipInfo) => {
const isIceIp = availableIceIps.value.includes(ipInfo.ipv4Address)
const alreadyAllowedIp = allowedIceIps.value.includes(ipInfo.ipv4Address)
if (ipInfo.interfaceType !== 'WIRED' || alreadyAllowedIp || !isIceIp) return
console.info(`Adding the wired address '${ipInfo.ipv4Address}' to the list of allowed ICE IPs.`)
allowedIceIps.value.push(ipInfo.ipv4Address)
Comment on lines +252 to +256
Copy link
Member

@joaoantoniocardoso joaoantoniocardoso Jan 2, 2024

Choose a reason for hiding this comment

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

I'm late for the party, but just for future note, this IPv4 thing is a nightmare. I know BlueOS doesn't use IPv6, but nothing is helping to debug when the ICE strategy fails because it's using IPv6.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hey Joao, could you detail the situation where this is creating a problem? Are IPv6 addresses being offered on the allowed list right now or are you talking about manual inputed ones?

Copy link
Member

Choose a reason for hiding this comment

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

There are no restrictions on the MCM side, so when the network uses IPV6, ICE will use it, and Cockpit will not be able to use it, right?

Copy link
Member Author

@rafaellehmkuhl rafaellehmkuhl Jan 8, 2024

Choose a reason for hiding this comment

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

Got it!
I'm actually not sure.
Is beacon providing information on IPv6 addresses?
Can you check at http://blueos.local/beacon/v1.0/services? I don't have IPv6 here to check.
@Williangalvani does Beacon works with IPv6?

})
if (!allowedIceIps.value.isEmpty()) {
clearInterval(iceIpCheckInterval)
clearTimeout(warningTimeout)
return
}
} catch (error) {
console.log(error)
}

if (warningTimeout) return
warningTimeout = setTimeout(() => {
console.info('No ICE IPs selected for the allowed list. Warning user.')
Swal.fire({
html: `
<p>Cockpit detected more than one IP address being used to route the video streaming. This often
leads to video stuttering, especially if one of the IPs is from a non-wired connection.</p>
</br>
<p>To prevent issues and achieve an optimal streaming experience, please:</p>
<ol>
<li>1. Open the video configuration page (Main-menu > Configuration > Video).</li>
<li>2. Select the IP address that should be used for the video streaming.</li>
</ol>
`,
icon: 'warning',
customClass: {
htmlContainer: 'text-left',
},
})
clearInterval(iceIpCheckInterval)
return
}, 5000)
}
}, 5000)

Expand Down