package route import ( "net/http" "os" "os/exec" "path/filepath" "rkkvm/config" "rkkvm/http/hw/hid" "rkkvm/http/hw/stream" "rkkvm/http/middleware" "rkkvm/http/reqrsp" "rkkvm/http/ws" "strings" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" ) func Api(e *gin.Engine) { api := e.Group("/api").Use(middleware.CheckToken()) api.GET("/stream/mjpeg", stream.MjpegHandler) api.GET("/ws", ws.ConnHandler) api.POST("/stream/webrtc", stream.WebRTCPeerConnect) api.GET("/stream/webrtc", stream.WebRTCSettings) api.POST("/storage/image", uploadHandler) api.GET("/storage/image", listHandler) api.GET("/storage/image/mounted", mountedHandler) api.POST("/storage/image/mount", mountHandler) api.POST("/storage/image/unmount", unmountHandler) } func uploadHandler(c *gin.Context) { file, err := c.FormFile("file") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to get file"}) return } filePath := filepath.Join(config.Get().ISOPath, file.Filename) if err := c.SaveUploadedFile(file, filePath); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file"}) return } c.JSON(http.StatusOK, gin.H{"message": "File uploaded successfully"}) } func listHandler(c *gin.Context) { files, err := os.ReadDir(config.Get().ISOPath) if err != nil { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "get images failed", }) return } var fileNames []string for _, f := range files { if !f.IsDir() { fname := strings.ToLower(f.Name()) if strings.HasSuffix(fname, ".iso") || strings.HasSuffix(fname, ".img") { fileNames = append(fileNames, f.Name()) } } } c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{ Msg: reqrsp.MsgSuccess, Data: reqrsp.FilesRsp{ Files: fileNames, }, }) } func mountHandler(c *gin.Context) { var request struct { Filename string `json:"file"` } if err := c.ShouldBindJSON(&request); err != nil { c.JSON(http.StatusBadRequest, reqrsp.NanoKVMRsp{ Code: -1, Msg: "invalid arguments", }) return } if request.Filename == "" { unmountHandler(c) return } imageFile := filepath.Join(config.Get().ISOPath, request.Filename) _, err := os.Stat(imageFile) if os.IsNotExist(err) { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "file not exists: " + request.Filename, }) return } hid.GetHid().Close() cmds := []string{ "/hid.sh detach", "/hid.sh mount_iso " + imageFile, //+ strconv.Quote(imageFile), "/hid.sh attach", } for _, cmd := range cmds { log.Debugf("Executing: %s", cmd) cc := exec.Command("sh", "-c", cmd) cc.Stdout = os.Stdout cc.Stderr = os.Stderr if err := cc.Run(); err != nil { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "execute command failed: " + cmd, }) return } } hid.GetHid().Open() c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{ Msg: reqrsp.MsgSuccess, }) } func unmountHandler(c *gin.Context) { hid.GetHid().Close() cmds := []string{ "/hid.sh detach", "/hid.sh unmount_iso", "/hid.sh attach", } for _, cmd := range cmds { log.Debugf("Executing: %s", cmd) cc := exec.Command("sh", "-c", cmd) cc.Stdout = os.Stdout cc.Stderr = os.Stderr if err := cc.Run(); err != nil { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "execute command failed: " + cmd, }) return } } hid.GetHid().Open() c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{ Msg: reqrsp.MsgSuccess, }) } func mountedHandler(c *gin.Context) { cmd := exec.Command("/hid.sh", "mounted_iso") output, err := cmd.Output() if err != nil { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "read failed", }) return } fname := strings.TrimSpace(string(output)) _, err = os.Stat(fname) if os.IsNotExist(err) { c.JSON(http.StatusInternalServerError, reqrsp.NanoKVMRsp{ Code: -2, Msg: "file not exists: " + fname, }) return } c.JSON(http.StatusOK, reqrsp.NanoKVMRsp{ Msg: reqrsp.MsgSuccess, Data: reqrsp.FileRsp{ File: filepath.Base(fname), }, }) }