Sfoglia il codice sorgente

Added more prototypes

Toby Chui 1 mese fa
parent
commit
53099c6965
5 ha cambiato i file con 167 aggiunte e 37 eliminazioni
  1. 24 21
      main.go
  2. 36 0
      mod/bokofile/bokofile.go
  3. 1 0
      mod/bokoworker/bokoworker.go
  4. 55 0
      mod/webdav/router.go
  5. 51 16
      mod/webdav/webdav.go

+ 24 - 21
main.go

@@ -1,18 +1,34 @@
 package main
 
 import (
-	"encoding/json"
-	"fmt"
-	"os"
+	"flag"
+	"strconv"
 
-	smart "imuslab.com/bokofs/bokofsd/mod/middleware/SMART"
+	"imuslab.com/bokofs/bokofsd/mod/webdav"
 )
 
-var dir string
-
 func main() {
 
-	//Get all the devices under /dev that is either sd or nvme
+	httpPort := flag.Int("p", 80, "Port to serve on (Plain HTTP)")
+	serveSecure := flag.Bool("s", false, "Serve HTTPS. Default false")
+
+	flag.Parse()
+
+	webdavHandler := webdav.NewWebdavInterfaceServer(webdav.Options{
+		ListeningAddress: ":" + strconv.Itoa(*httpPort),
+		SecureServe:      *serveSecure,
+	})
+
+	err := webdavHandler.Start()
+	if err != nil {
+		panic(err)
+	}
+
+	select {}
+}
+
+/*
+//Get all the devices under /dev that is either sd or nvme
 	deviceFiles, err := os.ReadDir("/dev")
 	if err != nil {
 		panic(err)
@@ -43,17 +59,4 @@ func main() {
 		fmt.Println(string(js))
 
 	}
-
-	/*
-		dirFlag := flag.String("d", "./", "Directory to serve from. Default is CWD")
-		httpPort := flag.Int("p", 80, "Port to serve on (Plain HTTP)")
-		httpsPort := flag.Int("ps", 443, "Port to serve TLS on")
-		serveSecure := flag.Bool("s", false, "Serve HTTPS. Default false")
-
-		flag.Parse()
-
-		dir = *dirFlag
-
-
-	*/
-}
+*/

+ 36 - 0
mod/bokofile/bokofile.go

@@ -0,0 +1,36 @@
+package bokofile
+
+import (
+	"io"
+	"net/http"
+	"os"
+)
+
+type File struct {
+	http.File
+	io.Writer
+}
+
+func (f *File) Write(p []byte) (n int, err error) {
+	return f.Writer.Write(p)
+}
+
+func (f *File) Close() error {
+	return f.File.Close()
+}
+
+func (f *File) Read(p []byte) (n int, err error) {
+	return f.File.Read(p)
+}
+
+func (f *File) Seek(offset int64, whence int) (int64, error) {
+	return f.File.Seek(offset, whence)
+}
+
+func (f *File) Readdir(count int) ([]os.FileInfo, error) {
+	return f.File.Readdir(count)
+}
+
+func (f *File) Stat() (os.FileInfo, error) {
+	return f.File.Stat()
+}

+ 1 - 0
mod/bokoworker/bokoworker.go

@@ -11,6 +11,7 @@ package bokoworker
 type Worker struct {
 	/* Worker Properties */
 	UUID     string //UUID of this worker
+	RootPath string //The root path request by this worker, e.g. /disk1
 	DiskUUID string // Disk UUID, when provided, will be used instead of disk path
 	DiskPath string // Disk device path (e.g. /dev/sda1), Disk UUID will have higher priority
 	Subpath  string // Subpath to serve, default is root

+ 55 - 0
mod/webdav/router.go

@@ -0,0 +1,55 @@
+package webdav
+
+import (
+	"context"
+	"fmt"
+	"os"
+
+	"golang.org/x/net/webdav"
+	"imuslab.com/bokofs/bokofsd/mod/bokofile"
+)
+
+/*
+	router.go
+
+	This implement a emulated file system abstraction
+	that routes the request to the correct worker
+
+*/
+
+type RouterDir struct {
+}
+
+func (r *RouterDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
+	// Implement the Mkdir method
+	fmt.Println("Mkdir called to " + name)
+	return nil
+}
+
+func (r *RouterDir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
+	// Implement the OpenFile method
+	fmt.Println("OpenFile called to " + name)
+	thisFile := &bokofile.File{}
+	return thisFile, nil
+}
+
+func (r *RouterDir) RemoveAll(ctx context.Context, name string) error {
+	// Implement the RemoveAll method
+	fmt.Println("RemoveAll called to " + name)
+	return nil
+}
+
+func (r *RouterDir) Rename(ctx context.Context, oldName, newName string) error {
+	// Implement the Rename method
+	fmt.Println("Rename called from " + oldName + " to " + newName)
+	return nil
+}
+
+func (r *RouterDir) Stat(ctx context.Context, name string) (os.FileInfo, error) {
+	// Implement the Stat method
+	fmt.Println("Stat called to " + name)
+	return nil, nil
+}
+
+// Ensure RouterDir implements the FileSystem interface
+var _ webdav.FileSystem = (*RouterDir)(nil)

+ 51 - 16
mod/webdav/webdav.go

@@ -1,13 +1,15 @@
 package webdav
 
 import (
+	"context"
 	"fmt"
 	"log"
 	"net/http"
 	"os"
+	"sync"
+	"time"
 
 	"golang.org/x/net/webdav"
-	"imuslab.com/bokofs/bokofsd/mod/bokoworker"
 )
 
 /*
@@ -25,16 +27,24 @@ type Options struct {
 }
 
 type Server struct {
-	LoadedWorkers *bokoworker.Worker
+	LoadedWorkers sync.Map //Storing uuid to bokoworker pointer (*bokoworker.Worker)
+	RouterDir     *RouterDir
+	Options       *Options
 }
 
-func NewWebdavInterfaceServer() *Server {
-	return &Server{}
+/* NewWebdavInterfaceServer creates a new WebDAV server instance */
+func NewWebdavInterfaceServer(options Options) *Server {
+	newRouter := &RouterDir{}
+	return &Server{
+		LoadedWorkers: sync.Map{},
+		RouterDir:     newRouter,
+		Options:       &options,
+	}
 }
 
 func (s *Server) Start() error {
 	srv := &webdav.Handler{
-		FileSystem: webdav.Dir(dir),
+		FileSystem: s.RouterDir,
 		LockSystem: webdav.NewMemLS(),
 		Logger: func(r *http.Request, err error) {
 			if err != nil {
@@ -45,19 +55,44 @@ func (s *Server) Start() error {
 		},
 	}
 	http.Handle("/", srv)
-	if *serveSecure == true {
-		if _, err := os.Stat("./cert.pem"); err != nil {
-			fmt.Println("[x] No cert.pem in current directory. Please provide a valid cert")
-			return
+
+	if s.Options.SecureServe {
+		if _, err := os.Stat(s.Options.PublicKeyPath); err != nil {
+			fmt.Println("Public ket not found")
+			return err
 		}
-		if _, er := os.Stat("./key.pem"); er != nil {
-			fmt.Println("[x] No key.pem in current directory. Please provide a valid cert")
-			return
+		if _, err := os.Stat(s.Options.PrivateKeyPath); err != nil {
+			fmt.Println("Private key not found")
+			return err
 		}
-
-		go http.ListenAndServeTLS(fmt.Sprintf(":%d", *httpsPort), "cert.pem", "key.pem", nil)
 	}
-	if err := http.ListenAndServe(fmt.Sprintf(":%d", *httpPort), nil); err != nil {
-		log.Fatalf("Error with WebDAV server: %v", err)
+
+	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+	defer cancel()
+	done := make(chan error)
+
+	go func() {
+		if s.Options.SecureServe {
+			if err := http.ListenAndServeTLS(s.Options.ListeningAddress, s.Options.PublicKeyPath, s.Options.PrivateKeyPath, nil); err != nil {
+				done <- err
+			}
+		} else {
+			if err := http.ListenAndServe(s.Options.ListeningAddress, nil); err != nil {
+				log.Fatalf("Error with WebDAV server: %v", err)
+				done <- err
+			}
+		}
+	}()
+
+	select {
+	case <-ctx.Done():
+		//No error in 3 seconds. Assume all green
+		return nil
+	case success := <-done:
+		if success != nil {
+			log.Fatalf("Error with WebDAV server")
+			return success
+		}
 	}
+	return nil
 }