syslogserver.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package syslogserver
  2. import (
  3. "fmt"
  4. "net"
  5. "strings"
  6. "time"
  7. "github.com/pkg/errors"
  8. log "github.com/sirupsen/logrus"
  9. "gopkg.in/tomb.v2"
  10. )
  11. type SyslogServer struct {
  12. listenAddr string
  13. port int
  14. channel chan SyslogMessage
  15. udpConn *net.UDPConn
  16. Logger *log.Entry
  17. MaxMessageLen int
  18. }
  19. type SyslogMessage struct {
  20. Message []byte
  21. Client string
  22. }
  23. func (s *SyslogServer) Listen(listenAddr string, port int) error {
  24. s.listenAddr = listenAddr
  25. s.port = port
  26. udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", s.listenAddr, s.port))
  27. if err != nil {
  28. return errors.Wrapf(err, "could not resolve addr %s", s.listenAddr)
  29. }
  30. udpConn, err := net.ListenUDP("udp", udpAddr)
  31. if err != nil {
  32. return errors.Wrapf(err, "could not listen on port %d", s.port)
  33. }
  34. s.Logger.Debugf("listening on %s:%d", s.listenAddr, s.port)
  35. s.udpConn = udpConn
  36. err = s.udpConn.SetReadBuffer(s.MaxMessageLen) // FIXME probably
  37. if err != nil {
  38. return errors.Wrap(err, "could not set readbuffer on UDP socket")
  39. }
  40. err = s.udpConn.SetReadDeadline(time.Now().UTC().Add(100 * time.Millisecond))
  41. if err != nil {
  42. return errors.Wrap(err, "could not set read deadline on UDP socket")
  43. }
  44. return nil
  45. }
  46. func (s *SyslogServer) SetChannel(c chan SyslogMessage) {
  47. s.channel = c
  48. }
  49. func (s *SyslogServer) StartServer() *tomb.Tomb {
  50. t := tomb.Tomb{}
  51. t.Go(func() error {
  52. for {
  53. select {
  54. case <-t.Dying():
  55. s.Logger.Info("syslog server tomb is dying")
  56. err := s.KillServer()
  57. return err
  58. default:
  59. //RFC3164 says 1024 bytes max
  60. //RFC5424 says 480 bytes minimum, and should support up to 2048 bytes
  61. b := make([]byte, s.MaxMessageLen)
  62. n, addr, err := s.udpConn.ReadFrom(b)
  63. if err != nil && !strings.Contains(err.Error(), "i/o timeout") {
  64. s.Logger.Errorf("error while reading from socket : %s", err)
  65. s.udpConn.Close()
  66. return err
  67. }
  68. if err == nil {
  69. s.channel <- SyslogMessage{Message: b[:n], Client: strings.Split(addr.String(), ":")[0]}
  70. }
  71. err = s.udpConn.SetReadDeadline(time.Now().UTC().Add(100 * time.Millisecond))
  72. if err != nil {
  73. return err
  74. }
  75. }
  76. }
  77. })
  78. return &t
  79. }
  80. func (s *SyslogServer) KillServer() error {
  81. err := s.udpConn.Close()
  82. if err != nil {
  83. return errors.Wrap(err, "could not close UDP connection")
  84. }
  85. return nil
  86. }