Fix VNC connection issue

This commit is contained in:
2023-12-07 00:23:19 +01:00
parent 7d88cd576c
commit d1a9b6c3bb
7 changed files with 78 additions and 55 deletions

View File

@ -10,6 +10,7 @@ export interface ServerConfig {
export interface ServerConstraints {
iso_max_size: number;
vnc_token_duration: number;
vm_name_size: LenConstraint;
vm_title_size: LenConstraint;
memory_size: LenConstraint;

View File

@ -1,10 +1,17 @@
import React from "react";
import React, { useEffect } from "react";
import { useParams } from "react-router-dom";
import { VncScreen } from "react-vnc";
import { ServerApi } from "../api/ServerApi";
import { VMApi, VMInfo } from "../api/VMApi";
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
import { time } from "../utils/DateUtils";
import { AsyncWidget } from "../widgets/AsyncWidget";
interface VNCTokenInfo {
url: string;
expire: number;
}
export function VNCRoute(): React.ReactElement {
const { uuid } = useParams();
@ -27,52 +34,58 @@ export function VNCRoute(): React.ReactElement {
function VNCInner(p: { vm: VMInfo }): React.ReactElement {
const snackbar = useSnackbar();
const counter = React.useRef(false);
const [url, setURL] = React.useState<string | undefined>();
const [token, setToken] = React.useState<VNCTokenInfo | undefined>();
const [counter, setCounter] = React.useState(1);
const load = async () => {
const connect = async (force: boolean) => {
try {
if (force) setCounter(counter + 1);
// Check if getting new time is useless
if ((token?.expire ?? 0) > time()) return;
setToken(undefined);
const u = await VMApi.OneShotVNCURL(p.vm);
console.info(u);
if (counter.current === false) {
counter.current = true;
setURL(u);
}
if (!token)
setToken({
expire: time() + ServerApi.Config.constraints.vnc_token_duration,
url: u,
});
} catch (e) {
console.error(e);
snackbar("Failed to initialize VNC connection!");
}
};
const reconnect = () => {
counter.current = false;
setURL(undefined);
const disconnected = () => {
connect(true);
};
useEffect(() => {
connect(false);
});
if (token === undefined)
return <p>Please wait, connecting to the machine...</p>;
return (
<AsyncWidget
loadKey={counter.current}
load={load}
ready={url !== undefined && counter.current}
errMsg="Failed to get a token to initialize VNC connection!"
build={() => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
<VncScreen
url={url!}
onDisconnect={() => {
console.info("VNC disconnected " + url);
reconnect();
}}
/>
</div>
)}
/>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
<VncScreen
url={token!.url}
onDisconnect={() => {
console.info("VNC disconnected " + token?.url);
disconnected();
}}
/>
</div>
);
}

View File

@ -0,0 +1,6 @@
/**
* Get current UNIX time, in seconds
*/
export function time(): number {
return Math.floor(new Date().getTime() / 1000);
}