-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extracting the UDP Server logic from the UDP input (#6439)
This commit extract the UDP Server logic outside of the UDP input, this will to reuse this component and the configuration for the syslog input. It now uses a callback instead of a forwarder instance. Ref: #6361
- Loading branch information
Showing
9 changed files
with
267 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,26 @@ | ||
package udp | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/elastic/beats/filebeat/harvester" | ||
"github.com/elastic/beats/filebeat/inputsource/udp" | ||
) | ||
|
||
var defaultConfig = config{ | ||
ForwarderConfig: harvester.ForwarderConfig{ | ||
Type: "udp", | ||
}, | ||
MaxMessageSize: 10240, | ||
// TODO: What should be default port? | ||
Host: "localhost:8080", | ||
Config: udp.Config{ | ||
MaxMessageSize: 10240, | ||
// TODO: What should be default port? | ||
Host: "localhost:8080", | ||
// TODO: What should be the default timeout? | ||
Timeout: time.Minute * 5, | ||
}, | ||
} | ||
|
||
type config struct { | ||
udp.Config `config:",inline"` | ||
harvester.ForwarderConfig `config:",inline"` | ||
Host string `config:"host"` | ||
MaxMessageSize int `config:"max_message_size"` | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package inputsource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package udp | ||
|
||
import ( | ||
"net" | ||
"runtime" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
||
"github.com/elastic/beats/libbeat/logp" | ||
) | ||
|
||
const windowErrBuffer = "A message sent on a datagram socket was larger than the internal message" + | ||
" buffer or some other network limit, or the buffer used to receive a datagram into was smaller" + | ||
" than the datagram itself." | ||
|
||
// Metadata contains formations about the packet. | ||
type Metadata struct { | ||
RemoteAddr net.Addr | ||
Truncated bool | ||
} | ||
|
||
// Config options for the UDPServer | ||
type Config struct { | ||
Host string `config:"host"` | ||
MaxMessageSize int `config:"max_message_size" validate:"positive,nonzero"` | ||
Timeout time.Duration `config:"timeout"` | ||
} | ||
|
||
// Server creates a simple UDP Server and listen to a specific host:port and will send any | ||
// event received to the callback method. | ||
type Server struct { | ||
config *Config | ||
callback func(data []byte, mt Metadata) | ||
Listener net.PacketConn | ||
log *logp.Logger | ||
wg sync.WaitGroup | ||
done chan struct{} | ||
} | ||
|
||
// New returns a new UDPServer instance. | ||
func New(config *Config, callback func(data []byte, mt Metadata)) *Server { | ||
return &Server{ | ||
config: config, | ||
callback: callback, | ||
log: logp.NewLogger("udp").With("address", config.Host), | ||
done: make(chan struct{}), | ||
} | ||
} | ||
|
||
// Start starts the UDP Server and listen to incoming events. | ||
func (u *Server) Start() error { | ||
var err error | ||
u.Listener, err = net.ListenPacket("udp", u.config.Host) | ||
if err != nil { | ||
return err | ||
} | ||
u.log.Info("Started listening for UDP connection") | ||
u.wg.Add(1) | ||
go func() { | ||
defer u.wg.Done() | ||
u.run() | ||
}() | ||
return nil | ||
} | ||
|
||
func (u *Server) run() { | ||
for { | ||
select { | ||
case <-u.done: | ||
return | ||
default: | ||
} | ||
|
||
buffer := make([]byte, u.config.MaxMessageSize) | ||
u.Listener.SetDeadline(time.Now().Add(u.config.Timeout)) | ||
|
||
// If you are using Windows and you are using a fixed buffer and you get a datagram which | ||
// is bigger than the specified size of the buffer, it will return an `err` and the buffer will | ||
// contains a subset of the data. | ||
// | ||
// On Unix based system, the buffer will be truncated but no error will be returned. | ||
length, addr, err := u.Listener.ReadFrom(buffer) | ||
if err != nil { | ||
// don't log any deadline events. | ||
e, ok := err.(net.Error) | ||
if ok && e.Timeout() { | ||
continue | ||
} | ||
|
||
u.log.Errorw("Error reading from the socket", "error", err) | ||
|
||
// On Windows send the current buffer and mark it as truncated. | ||
// The buffer will have content but length will return 0, addr will be nil. | ||
if isLargerThanBuffer(err) { | ||
u.callback(buffer, Metadata{RemoteAddr: addr, Truncated: true}) | ||
continue | ||
} | ||
} | ||
|
||
if length > 0 { | ||
u.callback(buffer[:length], Metadata{RemoteAddr: addr}) | ||
} | ||
} | ||
} | ||
|
||
// Stop stops the current udp server. | ||
func (u *Server) Stop() { | ||
u.log.Info("Stopping UDP server") | ||
u.Listener.Close() | ||
close(u.done) | ||
u.wg.Wait() | ||
u.log.Info("UDP server stopped") | ||
} | ||
|
||
func isLargerThanBuffer(err error) bool { | ||
if runtime.GOOS != "windows" { | ||
return false | ||
} | ||
return strings.Contains(err.Error(), windowErrBuffer) | ||
} |
Oops, something went wrong.