feat: basic server connection handling

This commit is contained in:
Kyren223
2024-10-05 15:27:40 +03:00
parent 0929041a9c
commit b987605cfb
5 changed files with 123 additions and 14 deletions

View File

@@ -3,13 +3,11 @@ package main
import (
"os"
"github.com/kyren223/eko/internal/server"
"github.com/kyren223/eko/internal/utils/log"
)
func main() {
log.SetDefault(log.NewLogger("Server", os.Stdout, true))
log.Debug("Eko 'Hello, World!'")
log.Info("Eko 'Hello, World!'")
log.Warn("Eko 'Hello, World!'")
log.Error("Eko 'Hello, World!'")
server.Start()
}

View File

@@ -0,0 +1,32 @@
package server
import (
"net"
"sync"
"github.com/kyren223/eko/internal/utils/log"
)
func handleClient(conn net.Conn, wg *sync.WaitGroup) {
log.Info("Handling client... %v", conn.RemoteAddr().String())
defer log.Info("Disconnecting client: %v", conn.RemoteAddr().String())
defer conn.Close()
defer wg.Done()
var request []byte
n, err := conn.Read(request)
if err != nil {
log.Error("Failed reading: %v", err)
return
}
log.Info("Read %v bytes: %v", n, string(request))
response := []byte("Server response")
n, err = conn.Write(response)
if err != nil {
log.Error("Failed writing response: %v", err)
return
}
log.Info("Responded successfully")
}

79
internal/server/server.go Normal file
View File

@@ -0,0 +1,79 @@
package server
import (
"net"
"os"
"os/signal"
"strconv"
"sync"
"syscall"
"github.com/kyren223/eko/internal/utils/log"
)
const PORT int = 7223
func Start() {
server, err := NewServer(6969)
if err != nil {
log.Error("Unable to start server: %v", err)
return
}
var wg sync.WaitGroup
stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
wg.Add(1)
go handleInterrupt(server, stopChan, &wg)
server.Listen()
wg.Wait()
}
func handleInterrupt(server *Server, stopChan <-chan os.Signal, wg *sync.WaitGroup) {
defer wg.Done()
<-stopChan
log.Info("Interrupt Occurred")
log.Info("Shutting down server...")
server.Close()
log.Info("Waiting for all connections to close")
server.Wait()
log.Info("Server has been shutdown")
}
type Server struct {
listener net.Listener
wg sync.WaitGroup
}
func NewServer(port int) (*Server, error) {
listener, err := net.Listen("tcp", ":"+strconv.Itoa(port))
if err != nil {
return nil, err
}
log.Info("Created server on port %v", port)
return &Server{listener, sync.WaitGroup{}}, nil
}
func (s *Server) Listen() {
log.Info("Server started listening... %v", s.listener.Addr().String())
for {
conn, err := s.listener.Accept()
if err != nil {
break
}
s.wg.Add(1)
go handleClient(conn, &s.wg)
}
}
// Stop stops the server. The blocked Listen call will be unlocked
func (s *Server) Close() {
s.listener.Close()
}
// Wait blocks until all active connections to the server are done
func (s *Server) Wait() {
s.wg.Wait()
}

View File

@@ -10,17 +10,17 @@ func SetDefault(l *Logger) {
}
func Debug(message string, a ...any) error {
return logger.Log(LevelDebug, message, a)
return logger.Debug(message, a...)
}
func Info(message string, a ...any) error {
return logger.Log(LevelInfo, message, a)
return logger.Info(message, a...)
}
func Warn(message string, a ...any) error {
return logger.Log(LevelWarn, message, a)
return logger.Warn(message, a...)
}
func Error(message string, a ...any) error {
return logger.Log(LevelError, message, a)
return logger.Error(message, a...)
}

View File

@@ -2,7 +2,6 @@ package log
import (
"fmt"
"go/format"
"io"
"os"
"sync"
@@ -29,27 +28,28 @@ func (l *Logger) Log(level Level, message string, a ...any) error {
timestamp := time.Now().Format(time.TimeOnly)
severity := level.String()
formattedMessage := fmt.Sprintf(message, a...)
// TODO: add support for ANSI coloring
l.mu.Lock()
_, err := fmt.Fprintf(l.writer, "[%s] [%s/%s]: %s\n", timestamp, l.name, severity, message, a)
_, err := fmt.Fprintf(l.writer, "[%s] [%s/%s]: %s\n", timestamp, l.name, severity, formattedMessage)
l.mu.Unlock()
return err
}
func (l *Logger) Debug(message string, a ...any) error {
return l.Log(LevelDebug, message, a)
return l.Log(LevelDebug, message, a...)
}
func (l *Logger) Info(message string, a ...any) error {
return l.Log(LevelInfo, message, a)
return l.Log(LevelInfo, message, a...)
}
func (l *Logger) Warn(message string, a ...any) error {
return l.Log(LevelWarn, message, a)
return l.Log(LevelWarn, message, a...)
}
func (l *Logger) Error(message string, a ...any) error {
return l.Log(LevelError, message, a)
return l.Log(LevelError, message, a...)
}