diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 49a2e0f..5d47cab 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,5 +1,6 @@ builds: - binary: cosmium + main: ./cmd/server goos: - darwin - linux diff --git a/Makefile b/Makefile index 7ecec31..8b2fdbf 100644 --- a/Makefile +++ b/Makefile @@ -4,28 +4,44 @@ GOTEST=$(GOCMD) test GOCLEAN=$(GOCMD) clean BINARY_NAME=cosmium +SERVER_LOCATION=./cmd/server + +SHARED_LIB_LOCATION=./sharedlibrary +SHARED_LIB_OPT=-buildmode=c-shared DIST_DIR=dist all: test build-all -build-all: build-darwin-arm64 build-darwin-amd64 build-linux-amd64 build-windows-amd64 +build-all: build-darwin-arm64 build-darwin-amd64 build-linux-amd64 build-linux-arm64 build-windows-amd64 build-windows-arm64 build-darwin-arm64: @echo "Building macOS ARM binary..." - @GOOS=darwin GOARCH=arm64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-darwin-arm64 . + @GOOS=darwin GOARCH=arm64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-darwin-arm64 $(SERVER_LOCATION) build-darwin-amd64: @echo "Building macOS x64 binary..." - @GOOS=darwin GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-darwin-amd64 . + @GOOS=darwin GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-darwin-amd64 $(SERVER_LOCATION) build-linux-amd64: @echo "Building Linux x64 binary..." - @GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-linux-amd64 . + @GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-linux-amd64 $(SERVER_LOCATION) + +build-linux-arm64: + @echo "Building Linux ARM binary..." + @GOOS=linux GOARCH=arm64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-linux-arm64 $(SERVER_LOCATION) build-windows-amd64: @echo "Building Windows x64 binary..." - @GOOS=windows GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-windows-amd64.exe . + @GOOS=windows GOARCH=amd64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-windows-amd64.exe $(SERVER_LOCATION) + +build-windows-arm64: + @echo "Building Windows ARM binary..." + @GOOS=windows GOARCH=arm64 $(GOBUILD) -o $(DIST_DIR)/$(BINARY_NAME)-windows-arm64.exe $(SERVER_LOCATION) + +build-sharedlib-linux-amd64: + @echo "Building shared library for Linux x64..." + @GOOS=linux GOARCH=amd64 $(GOBUILD) $(SHARED_LIB_OPT) -o $(DIST_DIR)/$(BINARY_NAME)-linux-amd64.so $(SHARED_LIB_LOCATION) generate-parser-nosql: pigeon -o ./parsers/nosql/nosql.go ./parsers/nosql/nosql.peg diff --git a/README.md b/README.md index e2e02e1..fadc294 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,11 @@ You can download the latest version of Cosmium from the [GitHub Releases page](h Cosmium is available for the following platforms: - **Linux**: cosmium-linux-amd64 +- **Linux on ARM**: cosmium-linux-arm64 - **macOS**: cosmium-darwin-amd64 - **macOS on Apple Silicon**: cosmium-darwin-arm64 - **Windows**: cosmium-windows-amd64.exe +- **Windows on ARM**: cosmium-windows-arm64.exe ### Running Cosmium diff --git a/api/router.go b/api/router.go index 5408f17..8ac3138 100644 --- a/api/router.go +++ b/api/router.go @@ -1,6 +1,7 @@ package api import ( + "context" "fmt" "net/http" @@ -12,6 +13,10 @@ import ( tlsprovider "github.com/pikami/cosmium/internal/tls_provider" ) +type Server struct { + StopServer chan interface{} +} + func CreateRouter() *gin.Engine { router := gin.Default(func(e *gin.Engine) { e.RedirectTrailingSlash = false @@ -57,42 +62,60 @@ func CreateRouter() *gin.Engine { return router } -func StartAPI() { +func StartAPI() *Server { if !config.Config.Debug { gin.SetMode(gin.ReleaseMode) } router := CreateRouter() listenAddress := fmt.Sprintf(":%d", config.Config.Port) + stopChan := make(chan interface{}) - if config.Config.TLS_CertificatePath != "" && config.Config.TLS_CertificateKey != "" { - err := router.RunTLS( - listenAddress, - config.Config.TLS_CertificatePath, - config.Config.TLS_CertificateKey) + server := &http.Server{ + Addr: listenAddress, + Handler: router.Handler(), + } + + go func() { + <-stopChan + logger.Info("Shutting down server...") + err := server.Shutdown(context.TODO()) if err != nil { - logger.Error("Failed to start HTTPS server:", err) + logger.Error("Failed to shutdown server:", err) + } + }() + + go func() { + if config.Config.DisableTls { + logger.Infof("Listening and serving HTTP on %s\n", server.Addr) + err := server.ListenAndServe() + if err != nil { + logger.Error("Failed to start HTTP server:", err) + } + return } - return - } + if config.Config.TLS_CertificatePath != "" && config.Config.TLS_CertificateKey != "" { + logger.Infof("Listening and serving HTTPS on %s\n", server.Addr) + err := server.ListenAndServeTLS( + config.Config.TLS_CertificatePath, + config.Config.TLS_CertificateKey) + if err != nil { + logger.Error("Failed to start HTTPS server:", err) + } + return + } else { + tlsConfig := tlsprovider.GetDefaultTlsConfig() + server.TLSConfig = tlsConfig - if config.Config.DisableTls { - router.Run(listenAddress) - } + logger.Infof("Listening and serving HTTPS on %s\n", server.Addr) + err := server.ListenAndServeTLS("", "") + if err != nil { + logger.Error("Failed to start HTTPS server:", err) + } + return + } + }() - tlsConfig := tlsprovider.GetDefaultTlsConfig() - server := &http.Server{ - Addr: listenAddress, - Handler: router.Handler(), - TLSConfig: tlsConfig, - } - - logger.Infof("Listening and serving HTTPS on %s\n", server.Addr) - err := server.ListenAndServeTLS("", "") - if err != nil { - logger.Error("Failed to start HTTPS server:", err) - } - - router.Run() + return &Server{StopServer: stopChan} } diff --git a/main.go b/cmd/server/server.go similarity index 79% rename from main.go rename to cmd/server/server.go index 178db53..5cfb8cc 100644 --- a/main.go +++ b/cmd/server/server.go @@ -15,18 +15,21 @@ func main() { repositories.InitializeRepository() - go api.StartAPI() + server := api.StartAPI() - waitForExit() + waitForExit(server) } -func waitForExit() { +func waitForExit(server *api.Server) { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) // Block until a exit signal is received <-sigs + // Stop the server + server.StopServer <- true + if config.Config.PersistDataFilePath != "" { repositories.SaveStateFS(config.Config.PersistDataFilePath) } diff --git a/sharedlibrary/sharedlibrary.go b/sharedlibrary/sharedlibrary.go new file mode 100644 index 0000000..bbacea6 --- /dev/null +++ b/sharedlibrary/sharedlibrary.go @@ -0,0 +1,52 @@ +package main + +import "C" +import ( + "encoding/json" + + "github.com/pikami/cosmium/api" + "github.com/pikami/cosmium/api/config" + "github.com/pikami/cosmium/internal/repositories" +) + +var currentServer *api.Server + +//export Configure +func Configure(configurationJSON *C.char) bool { + var configuration config.ServerConfig + err := json.Unmarshal([]byte(C.GoString(configurationJSON)), &configuration) + if err != nil { + return false + } + config.Config = configuration + return true +} + +//export InitializeRepository +func InitializeRepository() { + repositories.InitializeRepository() +} + +//export StartAPI +func StartAPI() { + currentServer = api.StartAPI() +} + +//export StopAPI +func StopAPI() { + if currentServer == nil { + currentServer.StopServer <- true + currentServer = nil + } +} + +//export GetState +func GetState() *C.char { + stateJSON, err := repositories.GetState() + if err != nil { + return nil + } + return C.CString(stateJSON) +} + +func main() {}