Fix VNC connection issue
This commit is contained in:
		@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								virtweb_frontend/src/utils/DateUtils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								virtweb_frontend/src/utils/DateUtils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Get current UNIX time, in seconds
 | 
			
		||||
 */
 | 
			
		||||
export function time(): number {
 | 
			
		||||
  return Math.floor(new Date().getTime() / 1000);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user