Add MessageEndRune and MessageSplitRune with default and customizable ServerHandlerFunc
This commit is contained in:
parent
7338bc69fa
commit
6e244be880
|
@ -6,15 +6,26 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.qowevisa.me/Qowevisa/tcpmachine/tcpcommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientConfiguration struct {
|
type ClientConfiguration struct {
|
||||||
|
MessageEndRune rune
|
||||||
|
MessageSplitRune rune
|
||||||
|
//
|
||||||
Status uint32
|
Status uint32
|
||||||
ErrorResolver func(chan error)
|
ErrorResolver func(chan error)
|
||||||
|
//
|
||||||
|
ServerHandlerFunc func(server net.Conn)
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDefaultConfig() *ClientConfiguration {
|
func GetDefaultConfig() *ClientConfiguration {
|
||||||
return &ClientConfiguration{
|
return &ClientConfiguration{
|
||||||
|
MessageEndRune: '\n',
|
||||||
|
MessageSplitRune: ' ',
|
||||||
ErrorResolver: func(c chan error) {
|
ErrorResolver: func(c chan error) {
|
||||||
for err := range c {
|
for err := range c {
|
||||||
fmt.Printf("DefConfig:Error: %v\n", err)
|
fmt.Printf("DefConfig:Error: %v\n", err)
|
||||||
|
@ -26,15 +37,21 @@ func GetDefaultConfig() *ClientConfiguration {
|
||||||
type ErrorResolverFunc func(errors chan error)
|
type ErrorResolverFunc func(errors chan error)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
MessageEndRune rune
|
||||||
|
MessageSplitRune rune
|
||||||
|
//
|
||||||
addr string
|
addr string
|
||||||
Status uint32
|
Status uint32
|
||||||
exit chan bool
|
exit chan bool
|
||||||
Server net.Conn
|
Server net.Conn
|
||||||
IsConnected bool
|
IsConnected bool
|
||||||
//
|
//
|
||||||
Messages chan []byte
|
ServerHandlerFunc func(server net.Conn)
|
||||||
|
//
|
||||||
ErrorsChannel chan error
|
ErrorsChannel chan error
|
||||||
ErrorResolver ErrorResolverFunc
|
ErrorResolver ErrorResolverFunc
|
||||||
|
//
|
||||||
|
Commands []tcpcommand.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateClient(addr string, options ...ClientOption) *Client {
|
func CreateClient(addr string, options ...ClientOption) *Client {
|
||||||
|
@ -43,21 +60,68 @@ func CreateClient(addr string, options ...ClientOption) *Client {
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
opt(conf)
|
opt(conf)
|
||||||
}
|
}
|
||||||
|
c := &Client{
|
||||||
return &Client{
|
MessageEndRune: conf.MessageEndRune,
|
||||||
|
MessageSplitRune: conf.MessageSplitRune,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
Messages: make(chan []byte, 16),
|
|
||||||
ErrorResolver: conf.ErrorResolver,
|
ErrorResolver: conf.ErrorResolver,
|
||||||
ErrorsChannel: make(chan error, 8),
|
ErrorsChannel: make(chan error, 8),
|
||||||
exit: make(chan bool, 1),
|
exit: make(chan bool, 1),
|
||||||
|
ServerHandlerFunc: conf.ServerHandlerFunc,
|
||||||
}
|
}
|
||||||
|
if c.ServerHandlerFunc == nil {
|
||||||
|
c.ServerHandlerFunc = GetDefaultServerHandlerFunc(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ERROR_CLIENT_ERRRSL_NIL = errors.New("Error Resolver is nil")
|
ERROR_CLIENT_ERRRSL_NIL = errors.New("Error Resolver is nil")
|
||||||
ERROR_CLIENT_ERRCHL_NIL = errors.New("Error Channel is nil")
|
ERROR_CLIENT_ERRCHL_NIL = errors.New("Error Channel is nil")
|
||||||
|
ERROR_CLIENT_SRVHND_NIL = errors.New("Server Handler Func is nil")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetDefaultServerHandlerFunc(c *Client) func(server net.Conn) {
|
||||||
|
return func(server net.Conn) {
|
||||||
|
serverReader := bufio.NewReader(server)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c.exit:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
rawMsg, err := serverReader.ReadString(byte(c.MessageEndRune))
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
c.exit <- true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c.ErrorsChannel <- fmt.Errorf("serverReader.ReadString: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Server send us a message: %s", rawMsg)
|
||||||
|
msg := strings.TrimRight(rawMsg, string(c.MessageEndRune))
|
||||||
|
parts := strings.Split(msg, string(c.MessageSplitRune))
|
||||||
|
// ???
|
||||||
|
if len(parts) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cmd := parts[0]
|
||||||
|
found := false
|
||||||
|
for _, _cmd := range c.Commands {
|
||||||
|
if cmd == _cmd.Command {
|
||||||
|
found = true
|
||||||
|
_cmd.Action(parts[1:], server)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
fmt.Printf("Command %s was not handled\n", cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) StartClient() error {
|
func (c *Client) StartClient() error {
|
||||||
if c.Status&statusBitCustomErrorHandling == 0 {
|
if c.Status&statusBitCustomErrorHandling == 0 {
|
||||||
if c.ErrorResolver == nil {
|
if c.ErrorResolver == nil {
|
||||||
|
@ -68,30 +132,31 @@ func (c *Client) StartClient() error {
|
||||||
}
|
}
|
||||||
go c.ErrorResolver(c.ErrorsChannel)
|
go c.ErrorResolver(c.ErrorsChannel)
|
||||||
}
|
}
|
||||||
|
if c.ServerHandlerFunc == nil {
|
||||||
|
return fmt.Errorf("Can't start client: %w", ERROR_CLIENT_SRVHND_NIL)
|
||||||
|
}
|
||||||
server, err := net.Dial("tcp", c.addr)
|
server, err := net.Dial("tcp", c.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("net.Dial: %w", err)
|
return fmt.Errorf("net.Dial: %w", err)
|
||||||
}
|
}
|
||||||
serverReader := bufio.NewReader(server)
|
|
||||||
c.IsConnected = true
|
c.IsConnected = true
|
||||||
c.Server = server
|
c.Server = server
|
||||||
loop:
|
c.ServerHandlerFunc(server)
|
||||||
for {
|
return nil
|
||||||
select {
|
}
|
||||||
case <-c.exit:
|
|
||||||
break loop
|
var commandDuplicateError = errors.New("Command already exists in server")
|
||||||
default:
|
var commandNotHandledError = errors.New("Command was not handled")
|
||||||
msg, err := serverReader.ReadString('\n')
|
|
||||||
if err != nil {
|
func (c *Client) On(command string, action func(args []string, server net.Conn)) error {
|
||||||
if errors.Is(err, io.EOF) {
|
for _, cmd := range c.Commands {
|
||||||
c.exit <- true
|
if cmd.Command == command {
|
||||||
break
|
return fmt.Errorf("Failed addding command %s: %w ", command, commandDuplicateError)
|
||||||
}
|
}
|
||||||
c.ErrorsChannel <- fmt.Errorf("serverReader.ReadString: %w", err)
|
}
|
||||||
}
|
c.Commands = append(c.Commands, tcpcommand.Command{
|
||||||
fmt.Printf("Server send us a message: %s", msg)
|
Command: command,
|
||||||
c.Messages <- []byte(msg)
|
Action: action,
|
||||||
}
|
})
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package tcpclient
|
package tcpclient
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
type ClientOption func(conf *ClientConfiguration)
|
type ClientOption func(conf *ClientConfiguration)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -13,3 +15,9 @@ func WithCustomErrorHandling(fun ErrorResolverFunc) ClientOption {
|
||||||
conf.ErrorResolver = fun
|
conf.ErrorResolver = fun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithServerHandler(fun func(server net.Conn)) ClientOption {
|
||||||
|
return func(conf *ClientConfiguration) {
|
||||||
|
conf.ServerHandlerFunc = fun
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user