tcpmachine/tcpserver/server.go

111 lines
2.5 KiB
Go
Raw Normal View History

2024-10-10 07:17:51 +02:00
package tcpserver
import (
"bufio"
"errors"
"fmt"
"io"
"log"
"net"
"strings"
"git.qowevisa.me/Qowevisa/tcpmachine/tcpcommand"
)
type ServerConfiguration struct {
MessageEndRune rune
MessageSplitRune rune
HandleClientFunc func(client net.Conn)
//
ErrorResolver func(chan error)
}
func CreateHandleClientFuncFromCommands(bundle *tcpcommand.CommandBundle, conf ServerConfiguration) (func(client net.Conn), chan error) {
clientErrors := make(chan error, 16)
return func(client net.Conn) {
connReader := bufio.NewReader(client)
for {
msg, err := connReader.ReadString(byte(conf.MessageEndRune))
if err != nil {
if errors.Is(err, io.EOF) {
break
}
clientErrors <- err
}
msgWoNl := strings.Trim(msg, string(conf.MessageEndRune))
parts := strings.Split(msgWoNl, string(conf.MessageSplitRune))
for _, cmd := range bundle.Commands {
if cmd.Command == parts[0] {
cmd.Action(parts[1:], client)
break
}
}
}
}, clientErrors
}
type Server struct {
HandleClientFunc func(client net.Conn)
Exit chan bool
//
ErrorsChannel chan error
ErrorResolver func(chan error)
}
// HandleClientFunc is NOT created by this function
// see: CreateHandleClientFuncFromCommands(bundle)
func GetDefaultConfig() ServerConfiguration {
return ServerConfiguration{
ErrorResolver: func(c chan error) {
for err := range c {
log.Printf("DefConfig:Error: %v\n", err)
}
},
}
}
func CreateServer(conf ServerConfiguration) *Server {
return &Server{
HandleClientFunc: conf.HandleClientFunc,
Exit: make(chan bool, 1),
//
ErrorsChannel: make(chan error, 8),
ErrorResolver: conf.ErrorResolver,
}
}
func (s *Server) StartServer(address string) error {
if s.Exit == nil {
return fmt.Errorf("server's Exit channel is nil. Can't start server\n")
}
listener, err := net.Listen("tcp", address)
if err != nil {
return fmt.Errorf("net.Listen: %w", err)
}
defer listener.Close()
if s.ErrorsChannel == nil {
return fmt.Errorf("server's ErrorsChannel is nil. Can't start server\n")
}
if s.ErrorResolver == nil {
return fmt.Errorf("server's ErrorResolver is nil. Can't start server\n")
}
go s.ErrorResolver(s.ErrorsChannel)
log.Printf("Server started listening on %s\n", address)
loop:
for {
select {
case <-s.Exit:
break loop
default:
newCLient, err := listener.Accept()
if err != nil {
s.ErrorsChannel <- fmt.Errorf("listener.Accept: %w", err)
break
}
go s.HandleClientFunc(newCLient)
}
}
return nil
}