Implement network connection handling

Introduced a new Connection struct and related functions in `connection.go` to facilitate network connections. Incorporated the `go-parsesyslog` package to parse incoming network data. Implemented functions in `server.go` to accept and handle incoming network connections, bolstering the application's network interaction functionality.
This commit is contained in:
Winni Neessen 2023-12-22 01:44:50 +01:00
parent 3c304797b3
commit 43b1147106
Signed by: wneessen
GPG key ID: 385AC9889632126E
4 changed files with 79 additions and 2 deletions

27
connection.go Normal file
View file

@ -0,0 +1,27 @@
package logranger
import (
"bufio"
"net"
)
// Connection represents a connection to a network resource.
type Connection struct {
conn net.Conn
id string
rb *bufio.Reader
wb *bufio.Writer
}
// NewConnection creates a new Connection object with the provided net.Conn.
// The Connection object holds a reference to the provided net.Conn, along with an ID string,
// bufio.Reader, and bufio.Writer. It returns a pointer to the created Connection object.
func NewConnection(nc net.Conn) *Connection {
c := &Connection{
conn: nc,
id: "foo",
rb: bufio.NewReader(nc),
wb: bufio.NewWriter(nc),
}
return c
}

5
go.mod
View file

@ -6,7 +6,10 @@ module github.com/wneessen/logranger
go 1.21 go 1.21
require github.com/kkyr/fig v0.4.0 require (
github.com/kkyr/fig v0.4.0
github.com/wneessen/go-parsesyslog v0.2.1
)
require ( require (
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect

2
go.sum
View file

@ -16,6 +16,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/wneessen/go-parsesyslog v0.2.1 h1:T6a6BsLb4plF1wG6MJ0aJDNtXE2Y28PMdCN97HmJi8A=
github.com/wneessen/go-parsesyslog v0.2.1/go.mod h1:xk+PXAOW/9Vc6AfrXd1tZKFyndq1jwxK+rIdlKuHpcc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -11,6 +11,11 @@ import (
"os" "os"
"strings" "strings"
"sync" "sync"
"github.com/wneessen/go-parsesyslog"
_ "github.com/wneessen/go-parsesyslog/rfc3164"
"github.com/wneessen/go-parsesyslog/rfc5424"
_ "github.com/wneessen/go-parsesyslog/rfc5424"
) )
const ( const (
@ -63,7 +68,10 @@ func (s *Server) RunWithListener(l net.Listener) error {
s.log.Error("failed to create PID file", LogErrKey, err) s.log.Error("failed to create PID file", LogErrKey, err)
os.Exit(1) os.Exit(1)
} }
_, err = pf.WriteString(fmt.Sprintf("%d", os.Getpid())) pid := os.Getpid()
s.log.Debug("creating PID file", slog.String("pid_file", pf.Name()),
slog.Int("pid", pid))
_, err = pf.WriteString(fmt.Sprintf("%d", pid))
if err != nil { if err != nil {
s.log.Error("failed to write PID to PID file", LogErrKey, err) s.log.Error("failed to write PID to PID file", LogErrKey, err)
_ = pf.Close() _ = pf.Close()
@ -74,10 +82,47 @@ func (s *Server) RunWithListener(l net.Listener) error {
// Listen for connections // Listen for connections
s.wg.Add(1) s.wg.Add(1)
go s.Listen()
return nil return nil
} }
func (s *Server) Listen() {
defer s.wg.Done()
s.log.Info("listening for new connections", slog.String("listen_addr", s.listener.Addr().String()))
for {
c, err := s.listener.Accept()
if err != nil {
s.log.Error("failed to accept new connection", LogErrKey, err)
continue
}
s.log.Debug("accepted new connection", slog.String("remote_addr", c.RemoteAddr().String()))
conn := NewConnection(c)
s.wg.Add(1)
go func(co *Connection) {
s.HandleConnection(co)
s.wg.Done()
}(conn)
}
}
func (s *Server) HandleConnection(c *Connection) {
s.log.Debug("handling connection")
defer c.conn.Close()
pa, err := parsesyslog.New(rfc5424.Type)
if err != nil {
s.log.Error("failed to initialize logger", LogErrKey, err)
return
}
lm, err := pa.ParseReader(c.rb)
if err != nil {
s.log.Error("failed to parse message", LogErrKey, err)
return
}
s.log.Info("log message received", slog.String("message", lm.Message.String()))
}
// setLogLevel sets the log level based on the value of `s.conf.Log.Level`. // setLogLevel sets the log level based on the value of `s.conf.Log.Level`.
// It creates a new `slog.HandlerOptions` and assigns the corresponding `slog.Level` // It creates a new `slog.HandlerOptions` and assigns the corresponding `slog.Level`
// based on the value of `s.conf.Log.Level`. If the value is not one of the valid levels, // based on the value of `s.conf.Log.Level`. If the value is not one of the valid levels,