diff --git a/cmd/start.go b/cmd/start.go new file mode 100644 index 0000000..94744d1 --- /dev/null +++ b/cmd/start.go @@ -0,0 +1,34 @@ +/* +Copyright © 2024 NAME HERE +*/ +package cmd + +import ( + "github.com/obakeng-develops/redis-server/server" + "github.com/spf13/cobra" +) + +type startOptions struct{} + +var startCmdOptions = &startOptions{} + +// startCmd represents the start command +var startCmd = &cobra.Command{ + Use: "start", + Short: "Starts the server", + Run: func(cmd *cobra.Command, args []string) { + startCmdOptions.run() + }, +} + +func init() { + rootCmd.AddCommand(startCmd) +} + +func (options *startOptions) run() error { + server := &server.Server{} + server.NewServer(":6379") + + server.StartServer() + return nil +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..6654d24 --- /dev/null +++ b/server/server.go @@ -0,0 +1,71 @@ +package server + +import ( + "bufio" + "fmt" + "log/slog" + "net" + "strings" +) + +type Server struct { + Address string +} + +func (s *Server) NewServer(address string) *Server { + return &Server{ + Address: address, + } +} + +func (s *Server) StartServer() { + // Listen on port 6379 + ln, err := net.Listen("tcp", ":6379") + if err != nil { + slog.Error("Could not listen on given port", "err", err) + return + } + defer ln.Close() + fmt.Printf("Server is listening on port %s...", s.Address) + + // Start accepting connections + for { + conn, err := ln.Accept() + if err != nil { + slog.Error("Could not accept connection", "err", err) + continue + } + + // Handle the connection in a goroutine + go handleConnection(conn) + } +} + +func handleConnection(conn net.Conn) { + defer conn.Close() + + reader := bufio.NewReader(conn) + for { + data, err := reader.ReadString('\n') + if err != nil { + slog.Error("Could not read data from connection", "err", err) + return + } + + message := strings.TrimSpace(data) + fmt.Println("Received message: %s", data) + + var response string + if message == "*1$4PING" { + response = "+PONG\r\n" + } else { + response = "+OK\r\n" + } + + _, err = conn.Write([]byte(response)) + if err != nil { + slog.Error("Could not write to connection", "err", err) + return + } + } +} diff --git a/server/server_test.go b/server/server_test.go new file mode 100644 index 0000000..dd6fb9b --- /dev/null +++ b/server/server_test.go @@ -0,0 +1,26 @@ +package server_test + +import ( + "net" + "testing" + "time" + + "github.com/obakeng-develops/redis-server/server" +) + +func TestStartServer(t *testing.T) { + server := &server.Server{} + newServer := server.NewServer(":6379") + + go newServer.StartServer() + + time.Sleep(100 * time.Millisecond) + + conn, err := net.Dial("tcp", "localhost:6379") + if err != nil { + t.Fatalf("Failed to connect to server: %v", err) + } + defer conn.Close() + + t.Log("Successfully connected to the server") +}