Prechádzať zdrojové kódy

Added more KVM stuffs

TC 1 týždeň pred
rodič
commit
1399a3cba3

+ 101 - 25
dezukvmd/api.go

@@ -1,30 +1,106 @@
 package main
 
-import "net/http"
-
-// Aux APIs for USB KVM mode
-func registerLocalAuxRoutes() {
-	http.HandleFunc("/aux/switchusbkvm", auxMCU.HandleSwitchUSBToKVM)
-	http.HandleFunc("/aux/switchusbremote", auxMCU.HandleSwitchUSBToRemote)
-	http.HandleFunc("/aux/presspower", auxMCU.HandlePressPowerButton)
-	http.HandleFunc("/aux/releasepower", auxMCU.HandleReleasePowerButton)
-	http.HandleFunc("/aux/pressreset", auxMCU.HandlePressResetButton)
-	http.HandleFunc("/aux/releasereset", auxMCU.HandleReleaseResetButton)
-	http.HandleFunc("/aux/getuuid", auxMCU.HandleGetUUID)
+import (
+	"fmt"
+	"net/http"
+
+	"imuslab.com/dezukvm/dezukvmd/mod/utils"
+)
+
+func register_auth_apis(mux *http.ServeMux) {
+	// Check API for session validation
+	mux.HandleFunc("/api/v1/check", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		ok := authManager.UserIsLoggedIn(r)
+		if !ok {
+			http.Error(w, "Unauthorized", http.StatusUnauthorized)
+			return
+		}
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("{\"status\":\"ok\"}"))
+	})
+	// Login API
+	mux.HandleFunc("/api/v1/login", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		err := authManager.LoginUser(w, r)
+		if err != nil {
+			http.Error(w, "Unauthorized", http.StatusUnauthorized)
+			return
+		}
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("{\"status\":\"success\"}"))
+	})
+
+	// Logout API
+	mux.HandleFunc("/api/v1/logout", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		err := authManager.LogoutUser(w, r)
+		if err != nil {
+			http.Error(w, "Logout failed", http.StatusInternalServerError)
+			return
+		}
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("{\"status\":\"logged out\"}"))
+	})
+
 }
 
-// Dummy Aux APIs for setups that do not have an aux MCU
-func registerDummyLocalAuxRoutes() {
-	dummyHandler := func(w http.ResponseWriter, r *http.Request) {
-		w.WriteHeader(http.StatusNotImplemented)
-		w.Write([]byte("Not implemented"))
-	}
-
-	http.HandleFunc("/aux/switchusbkvm", dummyHandler)
-	http.HandleFunc("/aux/switchusbremote", dummyHandler)
-	http.HandleFunc("/aux/presspower", dummyHandler)
-	http.HandleFunc("/aux/releasepower", dummyHandler)
-	http.HandleFunc("/aux/pressreset", dummyHandler)
-	http.HandleFunc("/aux/releasereset", dummyHandler)
-	http.HandleFunc("/aux/getuuid", dummyHandler)
+func register_ipkvm_apis(mux *http.ServeMux) {
+	authManager.HandleFunc("/api/v1/stream/{uuid}/video", func(w http.ResponseWriter, r *http.Request) {
+		instanceUUID := r.PathValue("uuid")
+		fmt.Println("Requested video stream for instance UUID:", instanceUUID)
+		dezukvmManager.HandleVideoStreams(w, r, instanceUUID)
+	}, mux)
+
+	authManager.HandleFunc("/api/v1/stream/{uuid}/audio", func(w http.ResponseWriter, r *http.Request) {
+		instanceUUID := r.PathValue("uuid")
+		dezukvmManager.HandleAudioStreams(w, r, instanceUUID)
+	}, mux)
+
+	authManager.HandleFunc("/api/v1/hid/{uuid}/events", func(w http.ResponseWriter, r *http.Request) {
+		instanceUUID := r.PathValue("uuid")
+		dezukvmManager.HandleHIDEvents(w, r, instanceUUID)
+	}, mux)
+
+	authManager.HandleFunc("/api/v1/mass_storage/switch", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method != http.MethodPost {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+			return
+		}
+		instanceUUID, err := utils.PostPara(r, "uuid")
+		if err != nil {
+			http.Error(w, "Missing or invalid uuid parameter", http.StatusBadRequest)
+			return
+		}
+		side, err := utils.PostPara(r, "side")
+		if err != nil {
+			http.Error(w, "Missing or invalid side parameter", http.StatusBadRequest)
+			return
+		}
+		switch side {
+		case "kvm":
+			dezukvmManager.HandleMassStorageSideSwitch(w, r, instanceUUID, true)
+		case "remote":
+			dezukvmManager.HandleMassStorageSideSwitch(w, r, instanceUUID, false)
+		default:
+			http.Error(w, "Invalid side parameter", http.StatusBadRequest)
+		}
+	}, mux)
+
+	authManager.HandleFunc("/api/v1/instances", func(w http.ResponseWriter, r *http.Request) {
+		if r.Method == http.MethodGet {
+			dezukvmManager.HandleListInstances(w, r)
+		} else {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+		}
+	}, mux)
 }

BIN
dezukvmd/config/sys.db


BIN
dezukvmd/dezukvmd


+ 0 - 84
dezukvmd/ipkvm.go

@@ -1,7 +1,6 @@
 package main
 
 import (
-	"fmt"
 	"log"
 	"net/http"
 	"os"
@@ -14,7 +13,6 @@ import (
 	"imuslab.com/dezukvm/dezukvmd/mod/auth"
 	"imuslab.com/dezukvm/dezukvmd/mod/dezukvm"
 	"imuslab.com/dezukvm/dezukvmd/mod/logger"
-	"imuslab.com/dezukvm/dezukvmd/mod/utils"
 )
 
 var (
@@ -158,85 +156,3 @@ func handle_root_routing(mux *http.ServeMux) {
 		http.ServeFile(w, r, targetFilePath)
 	})
 }
-
-func register_auth_apis(mux *http.ServeMux) {
-	// Check API for session validation
-	mux.HandleFunc("/api/v1/check", func(w http.ResponseWriter, r *http.Request) {
-		if r.Method != http.MethodPost {
-			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
-			return
-		}
-		ok := authManager.UserIsLoggedIn(r)
-		if !ok {
-			http.Error(w, "Unauthorized", http.StatusUnauthorized)
-			return
-		}
-		w.WriteHeader(http.StatusOK)
-		w.Write([]byte("{\"status\":\"ok\"}"))
-	})
-	// Login API
-	mux.HandleFunc("/api/v1/login", func(w http.ResponseWriter, r *http.Request) {
-		if r.Method != http.MethodPost {
-			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
-			return
-		}
-		err := authManager.LoginUser(w, r)
-		if err != nil {
-			http.Error(w, "Unauthorized", http.StatusUnauthorized)
-			return
-		}
-		w.WriteHeader(http.StatusOK)
-		w.Write([]byte("{\"status\":\"success\"}"))
-	})
-}
-
-func register_ipkvm_apis(mux *http.ServeMux) {
-	authManager.HandleFunc("/api/v1/stream/{uuid}/video", func(w http.ResponseWriter, r *http.Request) {
-		instanceUUID := r.PathValue("uuid")
-		fmt.Println("Requested video stream for instance UUID:", instanceUUID)
-		dezukvmManager.HandleVideoStreams(w, r, instanceUUID)
-	}, mux)
-
-	authManager.HandleFunc("/api/v1/stream/{uuid}/audio", func(w http.ResponseWriter, r *http.Request) {
-		instanceUUID := r.PathValue("uuid")
-		dezukvmManager.HandleAudioStreams(w, r, instanceUUID)
-	}, mux)
-
-	authManager.HandleFunc("/api/v1/hid/{uuid}/events", func(w http.ResponseWriter, r *http.Request) {
-		instanceUUID := r.PathValue("uuid")
-		dezukvmManager.HandleHIDEvents(w, r, instanceUUID)
-	}, mux)
-
-	authManager.HandleFunc("/api/v1/mass_storage/switch", func(w http.ResponseWriter, r *http.Request) {
-		if r.Method != http.MethodPost {
-			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
-			return
-		}
-		instanceUUID, err := utils.PostPara(r, "uuid")
-		if err != nil {
-			http.Error(w, "Missing or invalid uuid parameter", http.StatusBadRequest)
-			return
-		}
-		side, err := utils.PostPara(r, "side")
-		if err != nil {
-			http.Error(w, "Missing or invalid side parameter", http.StatusBadRequest)
-			return
-		}
-		switch side {
-		case "kvm":
-			dezukvmManager.HandleMassStorageSideSwitch(w, r, instanceUUID, true)
-		case "remote":
-			dezukvmManager.HandleMassStorageSideSwitch(w, r, instanceUUID, false)
-		default:
-			http.Error(w, "Invalid side parameter", http.StatusBadRequest)
-		}
-	}, mux)
-
-	authManager.HandleFunc("/api/v1/instances", func(w http.ResponseWriter, r *http.Request) {
-		if r.Method == http.MethodGet {
-			dezukvmManager.HandleListInstances(w, r)
-		} else {
-			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
-		}
-	}, mux)
-}

+ 13 - 0
dezukvmd/www/index.html

@@ -263,6 +263,19 @@
                 });
             }
 
+            $('.sidebar .menu-bottom .item').last().on('click', function() {
+                $.ajax({
+                    url: '/api/v1/logout',
+                    type: 'POST',
+                    success: function() {
+                        location.reload();
+                    },
+                    error: function() {
+                        alert('Logout failed.');
+                    }
+                });
+            });
+
         </script>
     </body>
 </html>

+ 7 - 3
dezukvmd/www/js/kvmevt.js

@@ -408,8 +408,12 @@ function stopAudioWebSocket() {
     }
 }
 
-
-
 window.addEventListener('beforeunload', function() {
     stopAudioWebSocket();
-});
+});
+
+// Disconnect both HID and Audio WebSockets
+function disconnectRemote(){
+    stopAudioWebSocket();
+    stopWebSocket();
+}

+ 27 - 0
dezukvmd/www/js/viewport.js

@@ -22,6 +22,12 @@ $(document).ready(function() {
     if (localStorage.getItem('dontShowAudioTipsAgain') === 'true') {
         $('#audioTips').remove();
     }
+
+    // Hide advanced menu by default
+    const advMenu = document.getElementById('advance-menu');
+    if (advMenu && !advMenu.classList.contains('hide')) {
+        advMenu.classList.add('hide');
+    }
 });
 
 /* Mass Storage Switch */
@@ -73,6 +79,27 @@ function handleDontShowAudioTipsAgain(){
     $('#audioTips').remove();
 }
 
+function toggleAdvanceMenu() {
+    const advMenu = document.getElementById('advance-menu');
+    advMenu.classList.toggle('hide');
+    const btn = document.getElementById('btnToggleAdvanceMenu');
+    const icon = btn.querySelector('i');
+    if (advMenu.classList.contains('hide')) {
+        icon.classList.remove('angle', 'up');
+        icon.classList.add('angle', 'down');
+    } else {
+        icon.classList.remove('angle', 'down');
+        icon.classList.add('angle', 'up');
+    }
+}
+
+
+
+
+   
+
+
+
 function toggleFullScreen(){
     let elem = document.documentElement;
     if (!document.fullscreenElement) {

+ 52 - 8
dezukvmd/www/viewport.css

@@ -1,18 +1,62 @@
-body {
-    
-}
-
-
 #menu {
-    height: 42px;
-    width: 120px;
-    overflow: hidden;
+    height: auto; /* allow dynamic height */
+    overflow: visible;
     position: fixed;
     top: 0.4em;
     left: 50%;
     transform: translateX(-50%);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    z-index: 1001;
+    background-color: #fafafa;
+    border-radius: 8px;
+    padding-top: 0.4em;
+    padding-left: 0.6em;
+    padding-right: 0.4em;
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
 }
 
+#advance-menu, #basic-menu {
+    width: 100%;
+    display: flex;
+    justify-content: center;
+    margin-bottom: 4px;
+    transition: max-height 0.3s ease, opacity 0.3s ease;
+}
+
+#advance-menu {
+    flex-direction: row;
+    max-height: 42px;
+    opacity: 1;
+    overflow: hidden;
+}
+
+#advance-menu.hide {
+    max-height: 0;
+    opacity: 0;
+    margin-bottom: 0;
+    pointer-events: none;
+}
+
+#basic-menu button{
+    border: 0 !important;
+    box-shadow: none !important;
+    background-color: transparent;
+}
+
+#basic-menu button:hover{
+    background-color: transparent;
+    opacity: 0.7;
+}
+
+
+#basic-menu button:focus {
+    background-color: transparent;
+    outline: none;
+}
+
+
 #streamWrapper{
     margin: 0;
     padding: 0;

+ 19 - 10
dezukvmd/www/viewport.html

@@ -15,18 +15,27 @@
 </head>
 <body>
     <div id="streamWrapper">
-         <img id="remoteCapture" src="" oncontextmenu="return false;"></img>
+        <img id="remoteCapture" src="" oncontextmenu="return false;"></img>
     </div>
    <div id="menu">
-        <button class="ui mini icon button" id="btnStorageKvm" onclick="switchMassStorageToKvm()" title="Switch Storage to KVM">
-            <i class="hdd icon"></i>
-        </button>
-        <button class="ui mini icon button" id="btnStorageRemote" onclick="switchMassStorageToRemote()" title="Switch Storage to Remote">
-            <i class="cloud upload icon"></i>
-        </button>
-        <button class="ui mini icon button" id="btnFullScreen" onclick="toggleFullScreen()" title="Fullscreen">
-            <i class="expand icon"></i>
-        </button>
+        <div id="advance-menu">
+            <button class="ui mini icon button" id="btnStorageKvm" onclick="switchMassStorageToKvm()" title="Switch Storage to KVM">
+                <i class="hdd icon"></i>
+            </button>
+            <button class="ui mini icon button" id="btnStorageRemote" onclick="switchMassStorageToRemote()" title="Switch Storage to Remote">
+                <i class="cloud upload icon"></i>
+            </button>
+           
+        </div>
+        <div id="basic-menu">
+             <button class="ui mini basic icon button" id="btnFullScreen" onclick="toggleFullScreen()" title="Fullscreen">
+                <i style="font-weight: bolder;" class="expand icon"></i>
+            </button>
+            <button class="ui mini basic icon button" id="btnToggleAdvanceMenu" onclick="toggleAdvanceMenu()" title="Show/Hide Advanced Menu">
+                <i style="font-weight: bolder;" class="angle down icon"></i>
+            </button>
+        </div>
+        
     </div>
     
     <div id="audioTips" class="ui left aligned message">