From 6244af7a6a7b1cabf970b8998a149b3ea8c8280c Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:46:06 +0200 Subject: [PATCH 01/10] First implementation of the server + Test the server --- server/server.go | 26 ++++++++++++++++++++++++++ server/server_test.go | 23 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 server/server.go create mode 100644 server/server_test.go diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..e9dc635 --- /dev/null +++ b/server/server.go @@ -0,0 +1,26 @@ +package server + +import ( + "log/slog" + "net" +) + +func StartServer() { + ln, err := net.Listen("tcp", ":8080") + if err != nil { + slog.Error("Error occurred", "err", err) + } + + for { + conn, err := ln.Accept() + if err != nil { + slog.Error("Could not accept connections", "err", err) + } + + go handleConnection(conn) + } +} + +func handleConnection(conn net.Conn) { + defer conn.Close() +} diff --git a/server/server_test.go b/server/server_test.go new file mode 100644 index 0000000..89cfa5b --- /dev/null +++ b/server/server_test.go @@ -0,0 +1,23 @@ +package server_test + +import ( + "net" + "testing" + "time" + + "github.com/obakeng-develops/redis-server/server" +) + +func TestStartServer(t *testing.T) { + go server.StartServer() + + time.Sleep(100 * time.Millisecond) + + conn, err := net.Dial("tcp", "localhost:8080") + if err != nil { + t.Fatalf("Failed to connect to server: %v", err) + } + defer conn.Close() + + t.Log("Successfully connected to the server") +} From 20e2e5a6534a80713bc1f4097cd4761c6421313d Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:48:15 +0200 Subject: [PATCH 02/10] Update error messages --- server/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index e9dc635..c75f9aa 100644 --- a/server/server.go +++ b/server/server.go @@ -8,13 +8,13 @@ import ( func StartServer() { ln, err := net.Listen("tcp", ":8080") if err != nil { - slog.Error("Error occurred", "err", err) + slog.Error("An error occurred", "err", err) } for { conn, err := ln.Accept() if err != nil { - slog.Error("Could not accept connections", "err", err) + slog.Error("An error occurred", "err", err) } go handleConnection(conn) From 8de166b3290ef793a83284bd3e820999a0b59463 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:59:07 +0200 Subject: [PATCH 03/10] Update server to use a struct initialization --- server/server_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/server_test.go b/server/server_test.go index 89cfa5b..80e172e 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -9,7 +9,10 @@ import ( ) func TestStartServer(t *testing.T) { - go server.StartServer() + server := &server.Server{} + newServer := server.NewServer("tcp", ":8080") + + go newServer.StartServer() time.Sleep(100 * time.Millisecond) From b1e96b4564021761a9afac4ead83c2ca23c81f93 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:59:32 +0200 Subject: [PATCH 04/10] Create a Server struct --- server/server.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index c75f9aa..cb1d989 100644 --- a/server/server.go +++ b/server/server.go @@ -5,8 +5,20 @@ import ( "net" ) -func StartServer() { - ln, err := net.Listen("tcp", ":8080") +type Server struct { + network string + address string +} + +func (s *Server) NewServer(network, address string) *Server { + return &Server{ + network: network, + address: address, + } +} + +func (s *Server) StartServer() { + ln, err := net.Listen(s.network, s.address) if err != nil { slog.Error("An error occurred", "err", err) } From 1471dc1d3d533403ffaece1d467f883f485ac636 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:02:59 +0200 Subject: [PATCH 05/10] Remove references to network variable --- server/server.go | 6 ++---- server/server_test.go | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/server.go b/server/server.go index cb1d989..d477050 100644 --- a/server/server.go +++ b/server/server.go @@ -6,19 +6,17 @@ import ( ) type Server struct { - network string address string } -func (s *Server) NewServer(network, address string) *Server { +func (s *Server) NewServer(address string) *Server { return &Server{ - network: network, address: address, } } func (s *Server) StartServer() { - ln, err := net.Listen(s.network, s.address) + ln, err := net.Listen("tcp", s.address) if err != nil { slog.Error("An error occurred", "err", err) } diff --git a/server/server_test.go b/server/server_test.go index 80e172e..d367716 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -10,7 +10,7 @@ import ( func TestStartServer(t *testing.T) { server := &server.Server{} - newServer := server.NewServer("tcp", ":8080") + newServer := server.NewServer(":8080") go newServer.StartServer() From 048d059a8736351b98271431d1981d6188c263b1 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:04:02 +0200 Subject: [PATCH 06/10] Update port to 6379 --- server/server_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server_test.go b/server/server_test.go index d367716..dd6fb9b 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -10,13 +10,13 @@ import ( func TestStartServer(t *testing.T) { server := &server.Server{} - newServer := server.NewServer(":8080") + newServer := server.NewServer(":6379") go newServer.StartServer() time.Sleep(100 * time.Millisecond) - conn, err := net.Dial("tcp", "localhost:8080") + conn, err := net.Dial("tcp", "localhost:6379") if err != nil { t.Fatalf("Failed to connect to server: %v", err) } From 3c3a9cc8dac581011e41a7a586b6f171b9bddceb Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:49:48 +0200 Subject: [PATCH 07/10] Add returns/continue in the correct places + Make Address field public. --- server/server.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/server/server.go b/server/server.go index d477050..9a717cc 100644 --- a/server/server.go +++ b/server/server.go @@ -1,30 +1,35 @@ package server import ( + "fmt" "log/slog" "net" ) type Server struct { - address string + Address string } func (s *Server) NewServer(address string) *Server { return &Server{ - address: address, + Address: address, } } func (s *Server) StartServer() { - ln, err := net.Listen("tcp", s.address) + ln, err := net.Listen("tcp", s.Address) if err != nil { slog.Error("An error occurred", "err", err) + return } + defer ln.Close() + fmt.Println("Server is listening on port 6379...") for { conn, err := ln.Accept() if err != nil { slog.Error("An error occurred", "err", err) + continue } go handleConnection(conn) From f02f0ef8d4c73cd1703d637c212694dd086d8661 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:50:41 +0200 Subject: [PATCH 08/10] Add start command options and run function to start the server --- cmd/start.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 cmd/start.go 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 +} From a66743a884b475924e2830142096c14db034770b Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:57:53 +0200 Subject: [PATCH 09/10] Add comments + correct error messages on server --- server/server.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index 9a717cc..8328965 100644 --- a/server/server.go +++ b/server/server.go @@ -17,25 +17,30 @@ func (s *Server) NewServer(address string) *Server { } func (s *Server) StartServer() { + // Listen on port 6379 ln, err := net.Listen("tcp", s.Address) if err != nil { - slog.Error("An error occurred", "err", err) + slog.Error("Could not listen on given port", "err", err) return } defer ln.Close() fmt.Println("Server is listening on port 6379...") + // Start accepting connections for { conn, err := ln.Accept() if err != nil { - slog.Error("An error occurred", "err", err) + 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() + + fmt.Println("Hello") } From d3a0417d01cbd69a15709a23cc8d94bc03f4b788 Mon Sep 17 00:00:00 2001 From: Obakeng <60041842+obakeng-develops@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:35:35 +0200 Subject: [PATCH 10/10] Start reading data from the connection and write to client: --- server/server.go | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/server/server.go b/server/server.go index 8328965..6654d24 100644 --- a/server/server.go +++ b/server/server.go @@ -1,9 +1,11 @@ package server import ( + "bufio" "fmt" "log/slog" "net" + "strings" ) type Server struct { @@ -18,13 +20,13 @@ func (s *Server) NewServer(address string) *Server { func (s *Server) StartServer() { // Listen on port 6379 - ln, err := net.Listen("tcp", s.Address) + ln, err := net.Listen("tcp", ":6379") if err != nil { slog.Error("Could not listen on given port", "err", err) return } defer ln.Close() - fmt.Println("Server is listening on port 6379...") + fmt.Printf("Server is listening on port %s...", s.Address) // Start accepting connections for { @@ -42,5 +44,28 @@ func (s *Server) StartServer() { func handleConnection(conn net.Conn) { defer conn.Close() - fmt.Println("Hello") + 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 + } + } }