111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
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
|
|
}
|