91 Commits

Author SHA1 Message Date
70ce288da7 Update Rust crate sysinfo to 0.34.0
All checks were successful
continuous-integration/drone/push Build is passing
2025-03-28 00:26:47 +00:00
6aabab866c Merge pull request 'Update dependency @types/react to v18.3.19' (#296) from renovate/react-18.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #296
2025-03-24 14:51:14 +00:00
4981a41a0a Merge pull request 'Update dependency xml-formatter to v3.6.5' (#299) from renovate/xml-formatter-3.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #299
2025-03-24 14:51:04 +00:00
9daced06e4 Update dependency xml-formatter to v3.6.5
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-03-22 00:27:04 +00:00
8299065eb2 Update dependency @types/react to v18.3.19
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-03-21 00:27:17 +00:00
67549d54a3 Migrate from actix-web-actor to actix-ws
All checks were successful
continuous-integration/drone/push Build is passing
2025-03-20 22:08:02 +01:00
c0690d888e Update frontend dependencies
All checks were successful
continuous-integration/drone/push Build is passing
2025-03-20 21:39:09 +01:00
ed9fd097e9 Updated backend dependencies
All checks were successful
continuous-integration/drone/push Build is passing
2025-03-20 21:33:18 +01:00
3c8de8279b Merge pull request 'Update dependency @mui/icons-material to v6.4.7' (#290) from renovate/mui-icons-material-6.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #290
2025-03-20 20:16:29 +00:00
6d8ce34e4a Update dependency @mui/icons-material to v6.4.7
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-03-12 00:23:43 +00:00
7c7df3bdde Merge pull request 'Update Rust crate serde_json to v1.0.138' (#289) from renovate/serde_json-1.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #289
2025-03-11 13:15:48 +00:00
d9767d1011 Merge pull request 'Update dependency @mui/material to v6.4.3' (#292) from renovate/mui-material-6.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #292
2025-03-11 13:15:38 +00:00
136dfbbea0 Update dependency @mui/material to v6.4.3
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-02-05 00:12:43 +00:00
7c8a1e06af Merge pull request 'Update Rust crate clap to v4.5.28' (#291) from renovate/clap-4.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #291
2025-02-04 07:03:23 +00:00
296e7da865 Update Rust crate clap to v4.5.28
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-02-04 00:13:09 +00:00
0f84db322a Merge pull request 'Update Rust crate rand to 0.9.0' (#287) from renovate/rand-0.x into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #287
2025-02-03 20:10:56 +00:00
70ca59d96f Fix rand 0.9.0 breaking changes
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-02-03 21:03:06 +01:00
0669493d9b Update Rust crate serde_json to v1.0.138
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-02-03 00:26:37 +00:00
ef38125277 Merge pull request 'Update Rust crate log to v0.4.25' (#271) from renovate/log-0.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #271
2025-02-02 18:33:20 +00:00
4107e7f77c Merge pull request 'Update dependency @mui/x-data-grid to v7.25.0' (#288) from renovate/mui-x-data-grid-7.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #288
2025-02-02 18:32:58 +00:00
f3c6b85827 Update dependency @mui/x-data-grid to v7.25.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-02-01 00:26:36 +00:00
cf31ab6ecd Update Rust crate rand to 0.9.0
Some checks failed
renovate/artifacts Artifact file update failure
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2025-01-28 00:27:40 +00:00
76a4506a62 Update dependency @testing-library/user-event to v14.6.1
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-27 00:59:47 +00:00
c16f805df6 Update dependency @testing-library/react to v16.2.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-27 00:26:36 +00:00
7ad8b42609 Update dependency @mui/x-data-grid to v7.24.1
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-26 00:59:51 +00:00
b139dfdfee Update dependency @mui/x-charts to v7.24.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-26 00:26:29 +00:00
72c559bf10 Update dependency @mui/icons-material to v6.4.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-25 00:26:54 +00:00
9b6a813c6f Update Rust crate uuid to v1.12.1
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-24 01:00:26 +00:00
0830d81b3d Update dependency xml-formatter to v3.6.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-24 00:27:29 +00:00
3ed64003d3 Update Rust crate tokio to v1.43.0
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-23 01:02:12 +00:00
6f1e707c2f Update Rust crate tempfile to v3.15.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-23 00:27:33 +00:00
300efe5367 Update Rust crate lazy-regex to v3.4.1
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-22 01:02:20 +00:00
375ce6ca7e Update dependency vite to v6.0.11
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-22 00:27:25 +00:00
8eff09a607 Update dependency uuid to v11.0.5
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-21 01:19:51 +00:00
0885def533 Update Rust crate clap to v4.5.27
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-21 00:27:36 +00:00
48b1bc3185 Merge pull request 'Update Rust crate serde_json to v1.0.137' (#272) from renovate/serde_json-1.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #272
2025-01-20 19:24:06 +00:00
99533fabf4 Update Rust crate serde_json to v1.0.137
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-20 00:27:52 +00:00
88a1c7a96a Update Rust crate log to v0.4.25
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-20 00:27:49 +00:00
38ac6e575b Merge pull request 'Update dependency @types/react to v18.3.18' (#260) from renovate/react-18.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #260
2025-01-19 22:10:57 +00:00
51010fdea3 Merge pull request 'Update Rust crate clap to v4.5.26' (#267) from renovate/clap-4.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #267
2025-01-19 22:10:49 +00:00
9b6704c39b Merge pull request 'Update Rust crate thiserror to v2.0.11' (#270) from renovate/thiserror-2.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #270
2025-01-19 22:10:41 +00:00
8de0718650 Update Rust crate thiserror to v2.0.11
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-12 00:50:12 +00:00
10b1355c2c Update dependency @mui/x-charts to v7.23.6
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-10 00:24:35 +00:00
ec56af6a8e Update Rust crate clap to v4.5.26
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-10 00:24:32 +00:00
0549eb04d7 Update Rust crate thiserror to v2.0.10
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-09 00:24:31 +00:00
dd49c692b1 Merge pull request 'Update dependency uuid to v11.0.4' (#261) from renovate/uuid-11.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #261
2025-01-08 19:03:27 +00:00
024360ac65 Update Rust crate serde_json to v1.0.135
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-08 01:47:00 +00:00
c2f04e41f3 Update Rust crate clap to v4.5.24
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-08 00:30:03 +00:00
b8d2c6ef5a Update dependency vite to v6.0.7
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-07 00:28:49 +00:00
a7b4a132cd Update dependency uuid to v11.0.4
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-07 00:28:42 +00:00
94c9057a12 Update dependency @types/react to v18.3.18
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2025-01-06 00:25:20 +00:00
e7bc32d38f Update dependency @mui/x-data-grid to v7.23.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-06 00:25:14 +00:00
a8d0520ec5 Update dependency @fontsource/roboto to v5.1.1
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-05 01:24:44 +00:00
63d13f4c27 Update Rust crate serde to v1.0.217
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-05 00:25:44 +00:00
0c8d37033a Update Rust crate reqwest to v0.12.12
All checks were successful
continuous-integration/drone/push Build is passing
2025-01-04 01:22:36 +00:00
fd604e2869 Update Rust crate quick-xml to v0.37.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-04 00:25:44 +00:00
990057be0d Merge pull request 'Update dependency @mui/icons-material to v6.2.1' (#246) from renovate/mui-icons-material-6.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #246
2025-01-03 08:22:59 +00:00
d65ebdcb0f Merge pull request 'Update dependency @types/react to v18.3.17' (#244) from renovate/react-18.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #244
2025-01-03 08:22:31 +00:00
cd7252b864 Merge pull request 'Update dependency @mui/material to v6.2.1' (#247) from renovate/mui-material-6.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #247
2025-01-03 08:22:25 +00:00
284f9d3a94 Merge pull request 'Update Rust crate thiserror to v2.0.9' (#254) from renovate/thiserror-2.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #254
2025-01-03 08:21:28 +00:00
98f26c2bf7 Update Rust crate thiserror to v2.0.9
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-25 00:24:28 +00:00
d7db6a56d3 Update Rust crate serde_json to v1.0.134
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-24 00:24:53 +00:00
8389c026fa Update Rust crate anyhow to v1.0.95
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-23 00:24:53 +00:00
6cb5b37c23 Update Rust crate env_logger to v0.11.6
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-22 00:25:30 +00:00
058c2a4abb Update dependency vite to v6.0.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-21 00:25:36 +00:00
839a7d271b Update dependency vite to v6.0.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-20 00:25:34 +00:00
d53c5d45cf Update Rust crate thiserror to v2.0.8
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-19 00:25:21 +00:00
be4fa6f0d7 Update dependency @mui/material to v6.2.1
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-18 00:07:48 +00:00
deced2492f Update dependency @mui/icons-material to v6.2.1
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-18 00:07:45 +00:00
0eb6567eb8 Update dependency @types/react to v18.3.17
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-17 00:07:51 +00:00
2c40d50435 Update dependency @testing-library/react to v16.1.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-16 00:08:18 +00:00
5c5c54bbd7 Update dependency @mui/icons-material to v6.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-15 01:15:00 +00:00
772e14cc3d Update dependency @types/react-dom to v18.3.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-15 00:08:02 +00:00
a2802647f2 Update dependency @mui/x-charts to v7.23.2
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-14 01:15:47 +00:00
79b2db0987 Update Rust crate thiserror to v2.0.7
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-14 00:09:09 +00:00
9cbbcc3bea Merge pull request 'Update dependency vite-tsconfig-paths to v5.1.4' (#229) from renovate/vite-tsconfig-paths-5.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #229
2024-12-13 19:31:15 +00:00
f4571af3c5 Merge pull request 'Update dependency @mui/x-charts to v7.23.0' (#213) from renovate/mui-x-charts-7.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #213
2024-12-13 19:31:09 +00:00
5808589cf8 Merge pull request 'Update dependency @types/react-dom to v18.3.2' (#225) from renovate/react-dom-18.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #225
2024-12-13 19:31:01 +00:00
48e4d9a84d Merge pull request 'Update Rust crate serde to v1.0.216' (#234) from renovate/serde-1.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #234
2024-12-13 19:30:52 +00:00
5ee1abde46 Merge pull request 'Update dependency @mui/x-data-grid to v7.23.2' (#236) from renovate/mui-x-data-grid-7.x-lockfile into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #236
2024-12-13 19:30:43 +00:00
aca1c69f32 Update dependency @emotion/styled to v11.14.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-13 00:08:07 +00:00
19f71e7d68 Update dependency @mui/x-data-grid to v7.23.2
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-13 00:08:02 +00:00
7583b547c2 Update dependency @types/react to v18.3.16
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-12 00:08:14 +00:00
f67201eaa9 Update Rust crate serde to v1.0.216
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-12 00:08:12 +00:00
ba7129b67f Update dependency @emotion/react to v11.14.0
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-11 01:16:30 +00:00
0642e2910e Update dependency @types/react to v18.3.15
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-11 00:24:22 +00:00
e5968f2444 Update Rust crate tokio to v1.42.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-10 00:24:38 +00:00
1bbdbcbbaf Update dependency vite-tsconfig-paths to v5.1.4
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-09 00:24:36 +00:00
5a85e9a91f Update Rust crate thiserror to v2.0.6
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2024-12-09 00:24:31 +00:00
9cdd0920a4 Update dependency @types/react-dom to v18.3.2
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-12-07 00:29:04 +00:00
a969248744 Update dependency @mui/x-charts to v7.23.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2024-11-30 00:24:31 +00:00
11 changed files with 1272 additions and 1088 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,43 +6,43 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4.21"
env_logger = "0.11.3"
clap = { version = "4.5.20", features = ["derive", "env"] }
light-openid = { version = "1.0.2", features = ["crypto-wrapper"] }
log = "0.4.26"
env_logger = "0.11.7"
clap = { version = "4.5.32", features = ["derive", "env"] }
light-openid = { version = "1.0.4", features = ["crypto-wrapper"] }
lazy_static = "1.5.0"
actix = "0.13.3"
actix-web = "4.9.0"
actix = "0.13.5"
actix-web = "4.10.2"
actix-remote-ip = "0.1.0"
actix-session = { version = "0.10.0", features = ["cookie-session"] }
actix-session = { version = "0.10.1", features = ["cookie-session"] }
actix-identity = "0.8.0"
actix-cors = "0.7.0"
actix-files = "0.6.5"
actix-web-actors = "4.3.0"
actix-http = "3.9.0"
serde = { version = "1.0.215", features = ["derive"] }
serde_json = "1.0.132"
quick-xml = { version = "0.37.1", features = ["serialize", "overlapped-lists"] }
actix-cors = "0.7.1"
actix-files = "0.6.6"
actix-ws = "0.3.0"
actix-http = "3.10.0"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
quick-xml = { version = "0.37.2", features = ["serialize", "overlapped-lists"] }
futures-util = "0.3.31"
anyhow = "1.0.93"
actix-multipart = "0.7.0"
tempfile = "3.14.0"
reqwest = { version = "0.12.9", features = ["stream"] }
url = "2.5.0"
virt = "0.4.1"
sysinfo = { version = "0.32.0", features = ["serde"] }
uuid = { version = "1.11.0", features = ["v4", "serde"] }
lazy-regex = "3.3.0"
thiserror = "2.0.0"
image = "0.25.4"
rand = "0.8.5"
bytes = "1.8.0"
tokio = "1.41.1"
anyhow = "1.0.97"
actix-multipart = "0.7.2"
tempfile = "3.19.1"
reqwest = { version = "0.12.15", features = ["stream"] }
url = "2.5.4"
virt = "0.4.2"
sysinfo = { version = "0.34.0", features = ["serde"] }
uuid = { version = "1.16.0", features = ["v4", "serde"] }
lazy-regex = "3.4.1"
thiserror = "2.0.12"
image = "0.25.5"
rand = "0.9.0"
bytes = "1.10.1"
tokio = { version = "1.44.1", features = ["rt", "time", "macros"] }
futures = "0.3.31"
ipnetwork = "0.20.0"
ipnetwork = { version = "0.21.1", features = ["serde"] }
num = "0.4.2"
rust-embed = { version = "8.5.0" }
mime_guess = "2.0.4"
mime_guess = "2.0.5"
dotenvy = "0.15.7"
nix = { version = "0.29.0", features = ["net"] }
basic-jwt = "0.2.0"

View File

@@ -1,3 +1,3 @@
pub mod libvirt_actor;
pub mod vnc_actor;
pub mod vnc_handler;
pub mod vnc_tokens_actor;

View File

@@ -1,209 +0,0 @@
use actix::{Actor, ActorContext, AsyncContext, Handler, StreamHandler};
use actix_http::ws::Item;
use actix_web_actors::ws;
use actix_web_actors::ws::Message;
use bytes::Bytes;
use image::EncodableLayout;
use std::path::Path;
use std::time::{Duration, Instant};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::unix::{OwnedReadHalf, OwnedWriteHalf};
use tokio::net::UnixStream;
/// How often heartbeat pings are sent
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
/// How long before lack of client response causes a timeout
const CLIENT_TIMEOUT: Duration = Duration::from_secs(20);
#[derive(thiserror::Error, Debug)]
enum VNCError {
#[error("Socket file does not exists!")]
SocketDoesNotExists,
}
pub struct VNCActor {
/// Qemu -> WS
read_half: Option<OwnedReadHalf>,
/// WS -> Qemu
write_half: OwnedWriteHalf,
// Client must respond to ping at a specific interval, otherwise we drop connection
hb: Instant,
}
impl VNCActor {
pub async fn new(socket_path: &str) -> anyhow::Result<Self> {
let socket_path = Path::new(socket_path);
if !socket_path.exists() {
return Err(VNCError::SocketDoesNotExists.into());
}
let socket = UnixStream::connect(socket_path).await?;
let (read_half, write_half) = socket.into_split();
Ok(Self {
read_half: Some(read_half),
write_half,
hb: Instant::now(),
})
}
/// helper method that sends ping to client every second.
///
/// also this method checks heartbeats from client
fn hb(&self, ctx: &mut ws::WebsocketContext<Self>) {
ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
// check client heartbeats
if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
// heartbeat timed out
log::warn!("WebSocket Client heartbeat failed, disconnecting!");
ctx.stop();
return;
}
ctx.ping(b"");
});
}
fn send_to_socket(&mut self, bytes: Bytes, ctx: &mut ws::WebsocketContext<Self>) {
log::trace!("Received {} bytes for VNC socket", bytes.len());
if let Err(e) = futures::executor::block_on(self.write_half.write(bytes.as_bytes())) {
log::error!("Failed to relay bytes to VNC socket {e}");
ctx.close(None);
}
}
fn start_qemu_to_ws_end(&mut self, ctx: &mut ws::WebsocketContext<Self>) {
let mut read_half = self.read_half.take().unwrap();
let addr = ctx.address();
let future = async move {
let mut buff: [u8; 5000] = [0; 5000];
loop {
match read_half.read(&mut buff).await {
Ok(mut l) => {
if l == 0 {
log::warn!("Got empty read!");
// Ugly hack made to wait for next byte
let mut one_byte_buff: [u8; 1] = [0; 1];
match read_half.read_exact(&mut one_byte_buff).await {
Ok(b) => {
if b == 0 {
log::error!("Did not get a byte !");
let _ = addr.send(CloseWebSocketReq).await;
break;
}
buff[0] = one_byte_buff[0];
l = 1;
}
Err(e) => {
log::error!("Failed to read 1 BYTE from remote socket. Stopping now... {:?}", e);
break;
}
}
}
let to_send = SendBytesReq(Vec::from(&buff[0..l]));
if let Err(e) = addr.send(to_send).await {
log::error!("Failed to send to websocket. Stopping now... {:?}", e);
return;
}
}
Err(e) => {
log::error!("Failed to read from remote socket. Stopping now... {:?}", e);
break;
}
};
}
log::info!("Exited read loop");
};
tokio::spawn(future);
}
}
impl Actor for VNCActor {
type Context = ws::WebsocketContext<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
self.hb(ctx);
self.start_qemu_to_ws_end(ctx);
}
}
impl StreamHandler<Result<Message, ws::ProtocolError>> for VNCActor {
fn handle(&mut self, msg: Result<Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(Message::Ping(msg)) => ctx.pong(&msg),
Ok(Message::Text(_text)) => {
log::error!("Received unexpected text on VNC WebSocket!");
}
Ok(Message::Binary(bin)) => {
log::info!("Forward {} bytes to VNC server", bin.len());
self.send_to_socket(bin, ctx);
}
Ok(Message::Continuation(msg)) => match msg {
Item::FirstText(_) => {
log::error!("Received unexpected split text!");
ctx.close(None);
}
Item::FirstBinary(bin) | Item::Continue(bin) | Item::Last(bin) => {
self.send_to_socket(bin, ctx);
}
},
Ok(Message::Pong(_)) => {
log::trace!("Received PONG message");
self.hb = Instant::now();
}
Ok(Message::Close(r)) => {
log::info!("WebSocket closed. Reason={r:?}");
ctx.close(r);
}
Ok(Message::Nop) => {
log::debug!("Received Nop message")
}
Err(e) => {
log::error!("WebSocket protocol error! {e}");
ctx.close(None)
}
}
}
}
#[derive(actix::Message)]
#[rtype(result = "()")]
pub struct SendBytesReq(Vec<u8>);
impl Handler<SendBytesReq> for VNCActor {
type Result = ();
fn handle(&mut self, msg: SendBytesReq, ctx: &mut Self::Context) -> Self::Result {
log::trace!("Send {} bytes to WS", msg.0.len());
ctx.binary(msg.0);
}
}
#[derive(actix::Message)]
#[rtype(result = "()")]
pub struct CloseWebSocketReq;
impl Handler<CloseWebSocketReq> for VNCActor {
type Result = ();
fn handle(&mut self, _msg: CloseWebSocketReq, ctx: &mut Self::Context) -> Self::Result {
log::trace!("Close websocket, because VNC socket has terminated");
ctx.close(None);
}
}

View File

@@ -0,0 +1,129 @@
use actix_http::ws::Message;
use futures_util::StreamExt as _;
use std::time::{Duration, Instant};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::UnixStream;
use tokio::select;
use tokio::time::interval;
/// How often heartbeat pings are sent
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
/// How long before lack of client response causes a timeout
const CLIENT_TIMEOUT: Duration = Duration::from_secs(20);
/// Broadcast text & binary messages received from a client, respond to ping messages, and monitor
/// connection health to detect network issues and free up resources.
pub async fn handle(
mut session: actix_ws::Session,
mut msg_stream: actix_ws::MessageStream,
mut socket: UnixStream,
) {
log::info!("Connected to websocket");
let mut last_heartbeat = Instant::now();
let mut interval = interval(HEARTBEAT_INTERVAL);
let mut buf_socket = [0u8; 1024];
let reason = loop {
// waits for either `msg_stream` to receive a message from the client, the broadcast channel
// to send a message, or the heartbeat interval timer to tick, yielding the value of
// whichever one is ready first
select! {
// heartbeat interval ticked
_tick = interval.tick() => {
// if no heartbeat ping/pong received recently, close the connection
if Instant::now().duration_since(last_heartbeat) > CLIENT_TIMEOUT {
log::info!(
"client has not sent heartbeat in over {CLIENT_TIMEOUT:?}; disconnecting"
);
break None;
}
// send heartbeat ping
let _ = session.ping(b"").await;
}
msg = msg_stream.next() => {
let msg = match msg {
// received message from WebSocket client
Some(Ok(msg)) => msg,
// client WebSocket stream error
Some(Err(err)) => {
log::error!("{err}");
break None;
}
// client WebSocket stream ended
None => break None
};
log::debug!("msg: {msg:?}");
match msg {
Message::Text(_) => {
log::error!("Received unexpected text on VNC WebSocket!");
}
Message::Binary(bin) => {
log::info!("Forward {} bytes to VNC server", bin.len());
if let Err(e) = socket.write(&bin).await {
log::error!("Failed to relay bytes to VNC socket {e}");
break None;
}
}
Message::Close(reason) => {
break reason;
}
Message::Ping(bytes) => {
last_heartbeat = Instant::now();
let _ = session.pong(&bytes).await;
}
Message::Pong(_) => {
last_heartbeat = Instant::now();
}
Message::Continuation(_) => {
log::warn!("no support for continuation frames");
}
// no-op; ignore
Message::Nop => {}
};
}
// Forward socket packet to WS client
count = socket.read(&mut buf_socket) => {
let count = match count {
Ok(count) => count,
Err(e) => {
log::error!("[VNC] Failed to read from upstream! {e}");
break None;
}
};
if count == 0 {
log::warn!("[VNC] infinite loop (upstream), closing connection");
break None;
}
if let Err(e)=session.binary(buf_socket[0..count].to_vec()).await{
log::error!("[VNC] Failed to forward messages to upstream, will close connection! {e}");
break None
}
}
}
};
// attempt to close connection gracefully
let _ = session.close(reason).await;
log::info!("Disconnected from websocket");
}

View File

@@ -136,16 +136,13 @@ pub async fn server_info(client: LibVirtReq) -> HttpResult {
system.refresh_all();
let mut components = Components::new();
components.refresh_list();
components.refresh();
components.refresh(true);
let mut disks = Disks::new();
disks.refresh_list();
disks.refresh();
disks.refresh(true);
let mut networks = Networks::new();
networks.refresh_list();
networks.refresh();
networks.refresh(true);
Ok(HttpResponse::Ok().json(ServerInfo {
hypervisor: client.get_info().await?,

View File

@@ -1,11 +1,12 @@
use crate::actors::vnc_actor::VNCActor;
use crate::actors::vnc_handler;
use crate::actors::vnc_tokens_actor::VNCTokensManager;
use crate::controllers::{HttpResult, LibVirtReq};
use crate::libvirt_lib_structures::domain::DomainState;
use crate::libvirt_lib_structures::XMLUuid;
use crate::libvirt_rest_structures::vm::VMInfo;
use actix_web::{web, HttpRequest, HttpResponse};
use actix_web_actors::ws;
use actix_web::{rt, web, HttpRequest, HttpResponse};
use std::path::Path;
use tokio::net::UnixStream;
#[derive(serde::Serialize)]
struct VMInfoAndState {
@@ -324,5 +325,19 @@ pub async fn vnc(
};
log::info!("Start VNC connection on socket {socket_path}");
Ok(ws::start(VNCActor::new(&socket_path).await?, &req, stream)?)
let socket_path = Path::new(&socket_path);
if !socket_path.exists() {
log::error!("VNC socket path {socket_path:?} does not exist!");
return Ok(HttpResponse::ServiceUnavailable().json("VNC socket path does not exists!"));
}
let socket = UnixStream::connect(socket_path).await?;
let (res, session, msg_stream) = actix_ws::handle(&req, stream)?;
// spawn websocket handler (and don't await it) so that the response is returned immediately
rt::spawn(vnc_handler::handle(session, msg_stream, socket));
Ok(res)
}

View File

@@ -57,7 +57,7 @@ pub fn is_net_interface_name_valid<D: AsRef<str>>(int: D) -> bool {
/// Get the list of available network interfaces
pub fn net_list() -> Vec<String> {
let mut networks = Networks::new();
networks.refresh_list();
networks.refresh(true);
networks
.list()

View File

@@ -1,12 +1,6 @@
use rand::distributions::Alphanumeric;
use rand::Rng;
use rand::distr::{Alphanumeric, SampleString};
/// Generate a random string
pub fn rand_str(len: usize) -> String {
let s: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(len)
.map(char::from)
.collect();
s
Alphanumeric.sample_string(&mut rand::rng(), len)
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,17 +4,17 @@
"type": "module",
"private": true,
"dependencies": {
"@emotion/react": "^11.13.5",
"@emotion/styled": "^11.13.5",
"@fontsource/roboto": "^5.1.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@fontsource/roboto": "^5.2.5",
"@mdi/js": "^7.2.96",
"@mdi/react": "^1.6.1",
"@mui/icons-material": "^6.1.8",
"@mui/material": "^6.1.8",
"@mui/x-charts": "^7.22.3",
"@mui/x-data-grid": "^7.22.3",
"@mui/icons-material": "^6.4.8",
"@mui/material": "^6.4.8",
"@mui/x-charts": "^7.28.0",
"@mui/x-data-grid": "^7.28.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.0",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.5.2",
"@types/humanize-duration": "^3.27.1",
"@types/jest": "^29.5.14",
@@ -26,15 +26,15 @@
"date-and-time": "^3.6.0",
"filesize": "^10.1.6",
"humanize-duration": "^3.29.0",
"mui-file-input": "^6.0.0",
"mui-file-input": "^7.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^7.0.1",
"react-router-dom": "^7.4.0",
"react-syntax-highlighter": "^15.6.1",
"react-vnc": "^2.0.2",
"react-vnc": "^2.0.3",
"typescript": "^4.9.5",
"uuid": "^11.0.3",
"vite": "^6.0.0",
"uuid": "^11.1.0",
"vite": "^6.2.2",
"vite-tsconfig-paths": "^5.1.3",
"web-vitals": "^3.5.2",
"xml-formatter": "^3.6.0"