Compare commits
No commits in common. "6e244be880fe28105b2e55cc52703eef7cd83381" and "64e6494ff8a87e41361b72b83f2a72391dd33572" have entirely different histories.
6e244be880
...
64e6494ff8
|
@ -1,14 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.qowevisa.me/Qowevisa/tcpmachine/tcpclient"
|
"git.qowevisa.me/Qowevisa/tcpmachine/tcpclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
client := tcpclient.CreateClient("127.0.0.1:10000")
|
conf := tcpclient.GetDefaultConfig()
|
||||||
|
client := tcpclient.CreateClient(conf)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if client.IsConnected {
|
if client.IsConnected {
|
||||||
|
@ -19,11 +19,8 @@ func main() {
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
client.Server.Write([]byte("PING\n"))
|
client.Server.Write([]byte("PING\n"))
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
client.ErrorsChannel <- fmt.Errorf("test err")
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
err := client.StartClient()
|
go client.ErrorResolver(client.ErrorsChannel)
|
||||||
if err != nil {
|
client.StartClient("127.0.0.1:10000")
|
||||||
fmt.Printf("ERROR: StartClient: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,26 +6,14 @@ 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
|
|
||||||
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)
|
||||||
|
@ -34,63 +22,40 @@ func GetDefaultConfig() *ClientConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorResolverFunc func(errors chan error)
|
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
MessageEndRune rune
|
|
||||||
MessageSplitRune rune
|
|
||||||
//
|
|
||||||
addr string
|
|
||||||
Status uint32
|
|
||||||
exit chan bool
|
exit chan bool
|
||||||
Server net.Conn
|
Server net.Conn
|
||||||
IsConnected bool
|
IsConnected bool
|
||||||
//
|
//
|
||||||
ServerHandlerFunc func(server net.Conn)
|
Messages chan []byte
|
||||||
//
|
|
||||||
ErrorsChannel chan error
|
ErrorsChannel chan error
|
||||||
ErrorResolver ErrorResolverFunc
|
ErrorResolver func(chan error)
|
||||||
//
|
|
||||||
Commands []tcpcommand.Command
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateClient(addr string, options ...ClientOption) *Client {
|
func CreateClient(conf ClientConfiguration) *Client {
|
||||||
conf := GetDefaultConfig()
|
return &Client{
|
||||||
|
Messages: make(chan []byte, 16),
|
||||||
for _, opt := range options {
|
|
||||||
opt(conf)
|
|
||||||
}
|
|
||||||
c := &Client{
|
|
||||||
MessageEndRune: conf.MessageEndRune,
|
|
||||||
MessageSplitRune: conf.MessageSplitRune,
|
|
||||||
addr: addr,
|
|
||||||
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 (
|
func (c *Client) StartClient(addr string) error {
|
||||||
ERROR_CLIENT_ERRRSL_NIL = errors.New("Error Resolver is nil")
|
server, err := net.Dial("tcp", addr)
|
||||||
ERROR_CLIENT_ERRCHL_NIL = errors.New("Error Channel is nil")
|
if err != nil {
|
||||||
ERROR_CLIENT_SRVHND_NIL = errors.New("Server Handler Func is nil")
|
return fmt.Errorf("net.Dial: %w", err)
|
||||||
)
|
}
|
||||||
|
|
||||||
func GetDefaultServerHandlerFunc(c *Client) func(server net.Conn) {
|
|
||||||
return func(server net.Conn) {
|
|
||||||
serverReader := bufio.NewReader(server)
|
serverReader := bufio.NewReader(server)
|
||||||
|
c.IsConnected = true
|
||||||
|
c.Server = server
|
||||||
|
loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.exit:
|
case <-c.exit:
|
||||||
return
|
break loop
|
||||||
default:
|
default:
|
||||||
rawMsg, err := serverReader.ReadString(byte(c.MessageEndRune))
|
msg, err := serverReader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, io.EOF) {
|
if errors.Is(err, io.EOF) {
|
||||||
c.exit <- true
|
c.exit <- true
|
||||||
|
@ -98,65 +63,9 @@ func GetDefaultServerHandlerFunc(c *Client) func(server net.Conn) {
|
||||||
}
|
}
|
||||||
c.ErrorsChannel <- fmt.Errorf("serverReader.ReadString: %w", err)
|
c.ErrorsChannel <- fmt.Errorf("serverReader.ReadString: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Server send us a message: %s", rawMsg)
|
fmt.Printf("Server send us a message: %s", msg)
|
||||||
msg := strings.TrimRight(rawMsg, string(c.MessageEndRune))
|
c.Messages <- []byte(msg)
|
||||||
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 {
|
|
||||||
if c.Status&statusBitCustomErrorHandling == 0 {
|
|
||||||
if c.ErrorResolver == nil {
|
|
||||||
return fmt.Errorf("Can't start client: %w", ERROR_CLIENT_ERRRSL_NIL)
|
|
||||||
}
|
|
||||||
if c.ErrorResolver == nil {
|
|
||||||
return fmt.Errorf("Can't start client: %w", ERROR_CLIENT_ERRCHL_NIL)
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("net.Dial: %w", err)
|
|
||||||
}
|
|
||||||
c.IsConnected = true
|
|
||||||
c.Server = server
|
|
||||||
c.ServerHandlerFunc(server)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var commandDuplicateError = errors.New("Command already exists in server")
|
|
||||||
var commandNotHandledError = errors.New("Command was not handled")
|
|
||||||
|
|
||||||
func (c *Client) On(command string, action func(args []string, server net.Conn)) error {
|
|
||||||
for _, cmd := range c.Commands {
|
|
||||||
if cmd.Command == command {
|
|
||||||
return fmt.Errorf("Failed addding command %s: %w ", command, commandDuplicateError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.Commands = append(c.Commands, tcpcommand.Command{
|
|
||||||
Command: command,
|
|
||||||
Action: action,
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package tcpclient
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type ClientOption func(conf *ClientConfiguration)
|
|
||||||
|
|
||||||
const (
|
|
||||||
statusBitNothing = 0
|
|
||||||
statusBitCustomErrorHandling = 1 << iota
|
|
||||||
)
|
|
||||||
|
|
||||||
func WithCustomErrorHandling(fun ErrorResolverFunc) ClientOption {
|
|
||||||
return func(conf *ClientConfiguration) {
|
|
||||||
conf.Status |= statusBitCustomErrorHandling
|
|
||||||
conf.ErrorResolver = fun
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithServerHandler(fun func(server net.Conn)) ClientOption {
|
|
||||||
return func(conf *ClientConfiguration) {
|
|
||||||
conf.ServerHandlerFunc = fun
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ package tcpserver
|
||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
type ServerOption func(conf *ServerConfiguration)
|
type ServerOption func(*ServerConfiguration)
|
||||||
|
|
||||||
// WithMessageEndRune sets the MessageEndRune in the server configuration.
|
// WithMessageEndRune sets the MessageEndRune in the server configuration.
|
||||||
func WithMessageEndRune(r rune) ServerOption {
|
func WithMessageEndRune(r rune) ServerOption {
|
||||||
|
@ -31,9 +31,3 @@ func WithHandleClientFunc(handler func(client net.Conn)) ServerOption {
|
||||||
conf.HandleClientFunc = handler
|
conf.HandleClientFunc = handler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithLoggingLevel(level ServerLoggingLevel) ServerOption {
|
|
||||||
return func(conf *ServerConfiguration) {
|
|
||||||
conf.LogLevel = level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,23 +12,10 @@ import (
|
||||||
"git.qowevisa.me/Qowevisa/tcpmachine/tcpcommand"
|
"git.qowevisa.me/Qowevisa/tcpmachine/tcpcommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServerLoggingLevel int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LogLevel_Nothing = 0
|
|
||||||
LogLevel_Connection = 1 << iota
|
|
||||||
LogLevel_Messages
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
LogLevel_ALL = LogLevel_Connection | LogLevel_Messages
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServerConfiguration struct {
|
type ServerConfiguration struct {
|
||||||
MessageEndRune rune
|
MessageEndRune rune
|
||||||
MessageSplitRune rune
|
MessageSplitRune rune
|
||||||
HandleClientFunc func(client net.Conn)
|
HandleClientFunc func(client net.Conn)
|
||||||
LogLevel ServerLoggingLevel
|
|
||||||
//
|
//
|
||||||
ErrorResolver func(chan error)
|
ErrorResolver func(chan error)
|
||||||
}
|
}
|
||||||
|
@ -60,27 +47,19 @@ func CreateHandleClientFuncFromCommands(bundle *tcpcommand.CommandBundle, conf S
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
addr string
|
addr string
|
||||||
PreHandlerClientFunc func(client net.Conn)
|
|
||||||
HandleClientFunc func(client net.Conn)
|
HandleClientFunc func(client net.Conn)
|
||||||
// Use PostHandlerClientFunc in your HandleClientFunc if you
|
|
||||||
// use custom HandleClientFunc
|
|
||||||
PostHandlerClientFunc func(client net.Conn)
|
|
||||||
Exit chan bool
|
Exit chan bool
|
||||||
//
|
//
|
||||||
MessageEndRune rune
|
MessageEndRune rune
|
||||||
MessageSplitRune rune
|
MessageSplitRune rune
|
||||||
ErrorsChannel chan error
|
ErrorsChannel chan error
|
||||||
ErrorResolver func(chan error)
|
ErrorResolver func(chan error)
|
||||||
LogLevel ServerLoggingLevel
|
|
||||||
//
|
//
|
||||||
Commands []tcpcommand.Command
|
Commands []tcpcommand.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultHandleClientFunc(server *Server) func(net.Conn) {
|
func defaultHandleClientFunc(server *Server) func(net.Conn) {
|
||||||
return func(client net.Conn) {
|
return func(client net.Conn) {
|
||||||
if server.PostHandlerClientFunc != nil {
|
|
||||||
defer server.PostHandlerClientFunc(client)
|
|
||||||
}
|
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
connReader := bufio.NewReader(client)
|
connReader := bufio.NewReader(client)
|
||||||
for {
|
for {
|
||||||
|
@ -94,9 +73,6 @@ func defaultHandleClientFunc(server *Server) func(net.Conn) {
|
||||||
msgWoNl := strings.Trim(msg, string(server.MessageEndRune))
|
msgWoNl := strings.Trim(msg, string(server.MessageEndRune))
|
||||||
parts := strings.Split(msgWoNl, string(server.MessageSplitRune))
|
parts := strings.Split(msgWoNl, string(server.MessageSplitRune))
|
||||||
commandFound := false
|
commandFound := false
|
||||||
if server.LogLevel&LogLevel_Messages > 0 {
|
|
||||||
log.Printf("Message received from %s : %s\n", client.RemoteAddr(), msgWoNl)
|
|
||||||
}
|
|
||||||
for _, cmd := range server.Commands {
|
for _, cmd := range server.Commands {
|
||||||
if cmd.Command == parts[0] {
|
if cmd.Command == parts[0] {
|
||||||
cmd.Action(parts[1:], client)
|
cmd.Action(parts[1:], client)
|
||||||
|
@ -111,7 +87,7 @@ func defaultHandleClientFunc(server *Server) func(net.Conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: 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{
|
||||||
|
@ -142,7 +118,6 @@ func CreateServer(addr string, options ...ServerOption) *Server {
|
||||||
MessageSplitRune: conf.MessageSplitRune,
|
MessageSplitRune: conf.MessageSplitRune,
|
||||||
ErrorsChannel: make(chan error, 8),
|
ErrorsChannel: make(chan error, 8),
|
||||||
ErrorResolver: conf.ErrorResolver,
|
ErrorResolver: conf.ErrorResolver,
|
||||||
LogLevel: conf.LogLevel,
|
|
||||||
//
|
//
|
||||||
Commands: cmds,
|
Commands: cmds,
|
||||||
}
|
}
|
||||||
|
@ -183,18 +158,12 @@ loop:
|
||||||
case <-s.Exit:
|
case <-s.Exit:
|
||||||
break loop
|
break loop
|
||||||
default:
|
default:
|
||||||
newClient, err := listener.Accept()
|
newCLient, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.ErrorsChannel <- fmt.Errorf("listener.Accept: %w", err)
|
s.ErrorsChannel <- fmt.Errorf("listener.Accept: %w", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if s.LogLevel&LogLevel_Connection > 0 {
|
go s.HandleClientFunc(newCLient)
|
||||||
fmt.Printf("New Connection from %s is accepted\n", newClient.RemoteAddr())
|
|
||||||
}
|
|
||||||
if s.PreHandlerClientFunc != nil {
|
|
||||||
s.PreHandlerClientFunc(newClient)
|
|
||||||
}
|
|
||||||
go s.HandleClientFunc(newClient)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -203,12 +172,6 @@ loop:
|
||||||
var commandDuplicateError = errors.New("Command already exists in server")
|
var commandDuplicateError = errors.New("Command already exists in server")
|
||||||
var commandNotHandledError = errors.New("Command was not handled")
|
var commandNotHandledError = errors.New("Command was not handled")
|
||||||
|
|
||||||
// On registers an action for a specific command. The action will be executed
|
|
||||||
// when the command is received from a client. For example, given the input
|
|
||||||
// string `TEST 1 2 3 4`, the command would be `TEST`, and the args would be
|
|
||||||
// []string{"1", "2", "3", "4"}.
|
|
||||||
//
|
|
||||||
// NOTE: This behavior applies only if `MessageSplitRune` is set to the default value (' ').
|
|
||||||
func (s *Server) On(command string, action func(args []string, client net.Conn)) error {
|
func (s *Server) On(command string, action func(args []string, client net.Conn)) error {
|
||||||
for _, cmd := range s.Commands {
|
for _, cmd := range s.Commands {
|
||||||
if cmd.Command == command {
|
if cmd.Command == command {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user