Skip to content

Commit

Permalink
video: Allow user to disable auto-retrieval of thetered IP addresses …
Browse files Browse the repository at this point in the history
…from BlueOS

This feature was asked by one of our users, which has a BlueOS based vehicle, but does not want the auto-retrieval feature, since he has an unusual network configuration where there are thetered connections but they do not want the video to come exclusively from that source.
  • Loading branch information
rafaellehmkuhl authored and ArturoManzoli committed Jul 16, 2024
1 parent cfb3de0 commit 496079f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 52 deletions.
98 changes: 51 additions & 47 deletions src/stores/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const useVideoStore = defineStore('video', () => {
console.debug('[WebRTC] Using webrtc-adapter for', adapter.browserDetails)

const allowedIceIps = useBlueOsStorage<string[]>('cockpit-allowed-stream-ips', [])
const enableAutoIceIpFetch = useBlueOsStorage('cockpit-enable-auto-ice-ip-fetch', true)
const allowedIceProtocols = useBlueOsStorage<string[]>('cockpit-allowed-stream-protocols', [])
const jitterBufferTarget = useBlueOsStorage<number | null>('cockpit-jitter-buffer-target', 0)
const zipMultipleFiles = useBlueOsStorage('cockpit-zip-multiple-video-files', false)
Expand Down Expand Up @@ -697,58 +698,60 @@ export const useVideoStore = defineStore('video', () => {
})
}

// Routine to make sure the user has chosen the allowed ICE candidate IPs, so the stream works as expected
let noIpSelectedWarningIssued = false
let selectedIpNotAvailableWarningIssued = false
const iceIpCheckInterval = setInterval(async (): Promise<void> => {
// Pass if there are no available IPs yet
if (availableIceIps.value.isEmpty()) return

if (!allowedIceIps.value.isEmpty()) {
// If the user has selected IPs, but none of them are available, warn about it, since no video will be streamed.
// Otherwise, if IPs are selected and available, clear the check routine.
const availableSelectedIps = availableIceIps.value.filter((ip) => allowedIceIps.value.includes(ip))
if (availableSelectedIps.isEmpty() && !selectedIpNotAvailableWarningIssued) {
console.warn('Selected ICE IPs are not available. Warning user.')
issueSelectedIpNotAvailableWarning()
selectedIpNotAvailableWarningIssued = true
if (enableAutoIceIpFetch.value) {
// Routine to make sure the user has chosen the allowed ICE candidate IPs, so the stream works as expected
let noIpSelectedWarningIssued = false
let selectedIpNotAvailableWarningIssued = false
const iceIpCheckInterval = setInterval(async (): Promise<void> => {
// Pass if there are no available IPs yet
if (availableIceIps.value.isEmpty()) return

if (!allowedIceIps.value.isEmpty()) {
// If the user has selected IPs, but none of them are available, warn about it, since no video will be streamed.
// Otherwise, if IPs are selected and available, clear the check routine.
const availableSelectedIps = availableIceIps.value.filter((ip) => allowedIceIps.value.includes(ip))
if (availableSelectedIps.isEmpty() && !selectedIpNotAvailableWarningIssued) {
console.warn('Selected ICE IPs are not available. Warning user.')
issueSelectedIpNotAvailableWarning()
selectedIpNotAvailableWarningIssued = true
}
clearInterval(iceIpCheckInterval)
}
clearInterval(iceIpCheckInterval)
}

// If the user has not selected any IPs and there's more than one IP candidate available, try getting information
// about them from BlueOS. If that fails, send a warning an clear the check routine.
if (allowedIceIps.value.isEmpty() && availableIceIps.value.length >= 1) {
// Try to select the IP automatically if it's a wired connection (based on BlueOS data).
try {
const ipsInfo = await getIpsInformationFromVehicle(globalAddress)
const newAllowedIps: string[] = []
ipsInfo.forEach((ipInfo) => {
const isIceIp = availableIceIps.value.includes(ipInfo.ipv4Address)
const alreadyAllowedIp = [...allowedIceIps.value, ...newAllowedIps].includes(ipInfo.ipv4Address)
const theteredInterfaceTypes = ['WIRED', 'USB']
if (!theteredInterfaceTypes.includes(ipInfo.interfaceType) || alreadyAllowedIp || !isIceIp) return
console.info(`Adding the wired address '${ipInfo.ipv4Address}' to the list of allowed ICE IPs.`)
newAllowedIps.push(ipInfo.ipv4Address)
})
allowedIceIps.value = newAllowedIps
if (!allowedIceIps.value.isEmpty()) {
Swal.fire({ text: 'Preferred video stream routes fetched from BlueOS.', icon: 'success', timer: 5000 })
// If the user has not selected any IPs and there's more than one IP candidate available, try getting information
// about them from BlueOS. If that fails, send a warning an clear the check routine.
if (allowedIceIps.value.isEmpty() && availableIceIps.value.length >= 1) {
// Try to select the IP automatically if it's a wired connection (based on BlueOS data).
try {
const ipsInfo = await getIpsInformationFromVehicle(globalAddress)
const newAllowedIps: string[] = []
ipsInfo.forEach((ipInfo) => {
const isIceIp = availableIceIps.value.includes(ipInfo.ipv4Address)
const alreadyAllowedIp = [...allowedIceIps.value, ...newAllowedIps].includes(ipInfo.ipv4Address)
const theteredInterfaceTypes = ['WIRED', 'USB']
if (!theteredInterfaceTypes.includes(ipInfo.interfaceType) || alreadyAllowedIp || !isIceIp) return
console.info(`Adding the wired address '${ipInfo.ipv4Address}' to the list of allowed ICE IPs.`)
newAllowedIps.push(ipInfo.ipv4Address)
})
allowedIceIps.value = newAllowedIps
if (!allowedIceIps.value.isEmpty()) {
Swal.fire({ text: 'Preferred video stream routes fetched from BlueOS.', icon: 'success', timer: 5000 })
}
} catch (error) {
console.error('Failed to get IP information from the vehicle:', error)
}
} catch (error) {
console.error('Failed to get IP information from the vehicle:', error)
}

// If the system was still not able to populate the allowed IPs list yet, warn the user.
// Otherwise, clear the check routine.
if (allowedIceIps.value.isEmpty() && !noIpSelectedWarningIssued) {
console.info('No ICE IPs selected for the allowed list. Warning user.')
issueNoIpSelectedWarning()
noIpSelectedWarningIssued = true
// If the system was still not able to populate the allowed IPs list yet, warn the user.
// Otherwise, clear the check routine.
if (allowedIceIps.value.isEmpty() && !noIpSelectedWarningIssued) {
console.info('No ICE IPs selected for the allowed list. Warning user.')
issueNoIpSelectedWarning()
noIpSelectedWarningIssued = true
}
clearInterval(iceIpCheckInterval)
}
clearInterval(iceIpCheckInterval)
}
}, 5000)
}, 5000)
}

// Video recording actions
const startRecordingAllStreams = (): void => {
Expand Down Expand Up @@ -797,6 +800,7 @@ export const useVideoStore = defineStore('video', () => {
return {
availableIceIps,
allowedIceIps,
enableAutoIceIpFetch,
allowedIceProtocols,
jitterBufferTarget,
zipMultipleFiles,
Expand Down
21 changes: 16 additions & 5 deletions src/views/ConfigurationVideoView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
<div class="flex-col h-full ml-[1vw] max-w-[500px]">
<ExpansiblePanel no-top-divider :is-expanded="!interfaceStore.isOnPhoneScreen">
<template #title>Allowed WebRTC remote IP Addresses</template>
<template #info
>IP Addresses of the Vehicle allowed to be used for the WebRTC ICE Routing. Usually, the IP of the
tether/cabled interface. Blank means any route. E.g: 192.168.2.2</template
>
<template #info>
IP Addresses of the Vehicle allowed to be used for the WebRTC ICE Routing. Usually, the IP of the
tether/cabled interface. Blank means any route. E.g: 192.168.2.2.
<br />
<br />
If you enable the auto-retrieval, Cockpit will try to fetch from BlueOS information about the available IP
addresses, and auto-choose those associated with wired interfaces.
</template>
<template #content>
<div class="flex justify-center align-center w-[90%] ml-2">
<div class="flex justify-center flex-col w-[90%] ml-2">
<v-combobox
v-model="allowedIceIps"
multiple
Expand All @@ -23,6 +27,13 @@
theme="dark"
density="compact"
clearable
hide-details
/>
<v-checkbox
v-model="videoStore.enableAutoIceIpFetch"
label="Enable auto-retrieval of allowed IP addresses"
hide-details
class="mb-2"
/>
</div>
</template>
Expand Down

0 comments on commit 496079f

Please sign in to comment.