Update tcpserver API
This commit is contained in:
parent
78b04e2f0c
commit
64e6494ff8
|
@ -5,35 +5,17 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.qowevisa.me/Qowevisa/tcpmachine/tcpcommand"
|
|
||||||
"git.qowevisa.me/Qowevisa/tcpmachine/tcpserver"
|
"git.qowevisa.me/Qowevisa/tcpmachine/tcpserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bundle, err := tcpcommand.CreateCommandBundle([]tcpcommand.Command{
|
server := tcpserver.CreateServer("127.0.0.1:10000")
|
||||||
{
|
server.On("PING", func(args []string, client net.Conn) {
|
||||||
Command: "PING",
|
|
||||||
Action: func(s []string, client net.Conn) {
|
|
||||||
fmt.Printf("todo..\n")
|
|
||||||
client.Write([]byte("PONG\n"))
|
client.Write([]byte("PONG\n"))
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
err := server.StartServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Printf("Error: server.StartServer: %v\n", err)
|
||||||
}
|
}
|
||||||
conf := tcpserver.GetDefaultConfig()
|
|
||||||
handler, errorChannel := tcpserver.CreateHandleClientFuncFromCommands(bundle, conf)
|
|
||||||
go func() {
|
|
||||||
for err := range errorChannel {
|
|
||||||
fmt.Printf("Error:1: %v\n", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
conf.HandleClientFunc = handler
|
|
||||||
server := tcpserver.CreateServer(conf)
|
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Minute)
|
|
||||||
server.Exit <- true
|
|
||||||
}()
|
|
||||||
server.StartServer("127.0.0.1:10000")
|
|
||||||
}
|
}
|
||||||
|
|
33
tcpserver/options.go
Normal file
33
tcpserver/options.go
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package tcpserver
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type ServerOption func(*ServerConfiguration)
|
||||||
|
|
||||||
|
// WithMessageEndRune sets the MessageEndRune in the server configuration.
|
||||||
|
func WithMessageEndRune(r rune) ServerOption {
|
||||||
|
return func(conf *ServerConfiguration) {
|
||||||
|
conf.MessageEndRune = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMessageSplitRune sets the MessageSplitRune in the server configuration.
|
||||||
|
func WithMessageSplitRune(r rune) ServerOption {
|
||||||
|
return func(conf *ServerConfiguration) {
|
||||||
|
conf.MessageSplitRune = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrorResolver sets a custom error resolver function.
|
||||||
|
func WithErrorResolver(resolver func(chan error)) ServerOption {
|
||||||
|
return func(conf *ServerConfiguration) {
|
||||||
|
conf.ErrorResolver = resolver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHandleClientFunc sets the HandleClientFunc in the server configuration.
|
||||||
|
func WithHandleClientFunc(handler func(client net.Conn)) ServerOption {
|
||||||
|
return func(conf *ServerConfiguration) {
|
||||||
|
conf.HandleClientFunc = handler
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ type ServerConfiguration struct {
|
||||||
func CreateHandleClientFuncFromCommands(bundle *tcpcommand.CommandBundle, conf ServerConfiguration) (func(client net.Conn), chan error) {
|
func CreateHandleClientFuncFromCommands(bundle *tcpcommand.CommandBundle, conf ServerConfiguration) (func(client net.Conn), chan error) {
|
||||||
clientErrors := make(chan error, 16)
|
clientErrors := make(chan error, 16)
|
||||||
return func(client net.Conn) {
|
return func(client net.Conn) {
|
||||||
|
defer client.Close()
|
||||||
connReader := bufio.NewReader(client)
|
connReader := bufio.NewReader(client)
|
||||||
for {
|
for {
|
||||||
msg, err := connReader.ReadString(byte(conf.MessageEndRune))
|
msg, err := connReader.ReadString(byte(conf.MessageEndRune))
|
||||||
|
@ -45,17 +46,53 @@ func CreateHandleClientFuncFromCommands(bundle *tcpcommand.CommandBundle, conf S
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
addr string
|
||||||
HandleClientFunc func(client net.Conn)
|
HandleClientFunc func(client net.Conn)
|
||||||
Exit chan bool
|
Exit chan bool
|
||||||
//
|
//
|
||||||
|
MessageEndRune rune
|
||||||
|
MessageSplitRune rune
|
||||||
ErrorsChannel chan error
|
ErrorsChannel chan error
|
||||||
ErrorResolver func(chan error)
|
ErrorResolver func(chan error)
|
||||||
|
//
|
||||||
|
Commands []tcpcommand.Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultHandleClientFunc(server *Server) func(net.Conn) {
|
||||||
|
return func(client net.Conn) {
|
||||||
|
defer client.Close()
|
||||||
|
connReader := bufio.NewReader(client)
|
||||||
|
for {
|
||||||
|
msg, err := connReader.ReadString(byte(server.MessageEndRune))
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
server.ErrorsChannel <- err
|
||||||
|
}
|
||||||
|
msgWoNl := strings.Trim(msg, string(server.MessageEndRune))
|
||||||
|
parts := strings.Split(msgWoNl, string(server.MessageSplitRune))
|
||||||
|
commandFound := false
|
||||||
|
for _, cmd := range server.Commands {
|
||||||
|
if cmd.Command == parts[0] {
|
||||||
|
cmd.Action(parts[1:], client)
|
||||||
|
commandFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !commandFound {
|
||||||
|
server.ErrorsChannel <- fmt.Errorf("WARN: Command %s error: %w", parts[0], commandNotHandledError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleClientFunc is NOT created by this function
|
// HandleClientFunc is NOT created by this function
|
||||||
// see: CreateHandleClientFuncFromCommands(bundle)
|
// see: CreateHandleClientFuncFromCommands(bundle)
|
||||||
func GetDefaultConfig() ServerConfiguration {
|
func GetDefaultConfig() ServerConfiguration {
|
||||||
return ServerConfiguration{
|
return ServerConfiguration{
|
||||||
|
MessageEndRune: '\n',
|
||||||
|
MessageSplitRune: ' ',
|
||||||
ErrorResolver: func(c chan error) {
|
ErrorResolver: func(c chan error) {
|
||||||
for err := range c {
|
for err := range c {
|
||||||
log.Printf("DefConfig:Error: %v\n", err)
|
log.Printf("DefConfig:Error: %v\n", err)
|
||||||
|
@ -64,33 +101,56 @@ func GetDefaultConfig() ServerConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateServer(conf ServerConfiguration) *Server {
|
func CreateServer(addr string, options ...ServerOption) *Server {
|
||||||
return &Server{
|
conf := GetDefaultConfig()
|
||||||
HandleClientFunc: conf.HandleClientFunc,
|
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(&conf)
|
||||||
|
}
|
||||||
|
var cmds []tcpcommand.Command
|
||||||
|
|
||||||
|
server := &Server{
|
||||||
|
addr: addr,
|
||||||
Exit: make(chan bool, 1),
|
Exit: make(chan bool, 1),
|
||||||
|
HandleClientFunc: conf.HandleClientFunc,
|
||||||
//
|
//
|
||||||
|
MessageEndRune: conf.MessageEndRune,
|
||||||
|
MessageSplitRune: conf.MessageSplitRune,
|
||||||
ErrorsChannel: make(chan error, 8),
|
ErrorsChannel: make(chan error, 8),
|
||||||
ErrorResolver: conf.ErrorResolver,
|
ErrorResolver: conf.ErrorResolver,
|
||||||
|
//
|
||||||
|
Commands: cmds,
|
||||||
}
|
}
|
||||||
|
if conf.HandleClientFunc == nil {
|
||||||
|
server.HandleClientFunc = defaultHandleClientFunc(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) StartServer(address string) error {
|
func (s *Server) StartServer() error {
|
||||||
if s.Exit == nil {
|
if s.Exit == nil {
|
||||||
return fmt.Errorf("server's Exit channel is nil. Can't start server\n")
|
return fmt.Errorf("server's Exit channel is nil. Can't start server")
|
||||||
}
|
}
|
||||||
listener, err := net.Listen("tcp", address)
|
if s.HandleClientFunc == nil {
|
||||||
|
return fmt.Errorf("server's HandleClientFunc is nil. Can't start server")
|
||||||
|
}
|
||||||
|
if s.ErrorsChannel == nil {
|
||||||
|
return fmt.Errorf("server's ErrorsChannel is nil. Can't start server")
|
||||||
|
}
|
||||||
|
if len(s.Commands) == 0 {
|
||||||
|
s.ErrorsChannel <- fmt.Errorf("WARN: len(s.Commands) == 0! Server is running without commands")
|
||||||
|
}
|
||||||
|
listener, err := net.Listen("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("net.Listen: %w", err)
|
return fmt.Errorf("net.Listen: %w", err)
|
||||||
}
|
}
|
||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
if s.ErrorsChannel == nil {
|
|
||||||
return fmt.Errorf("server's ErrorsChannel is nil. Can't start server\n")
|
|
||||||
}
|
|
||||||
if s.ErrorResolver == nil {
|
if s.ErrorResolver == nil {
|
||||||
return fmt.Errorf("server's ErrorResolver is nil. Can't start server\n")
|
return fmt.Errorf("server's ErrorResolver is nil. Can't start server")
|
||||||
}
|
}
|
||||||
go s.ErrorResolver(s.ErrorsChannel)
|
go s.ErrorResolver(s.ErrorsChannel)
|
||||||
log.Printf("Server started listening on %s\n", address)
|
log.Printf("Server started listening on %s\n", s.addr)
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
|
@ -108,3 +168,19 @@ loop:
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commandDuplicateError = errors.New("Command already exists in server")
|
||||||
|
var commandNotHandledError = errors.New("Command was not handled")
|
||||||
|
|
||||||
|
func (s *Server) On(command string, action func(args []string, client net.Conn)) error {
|
||||||
|
for _, cmd := range s.Commands {
|
||||||
|
if cmd.Command == command {
|
||||||
|
return fmt.Errorf("Failed addding command %s: %w ", command, commandDuplicateError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Commands = append(s.Commands, tcpcommand.Command{
|
||||||
|
Command: command,
|
||||||
|
Action: action,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user