syslogserver.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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.udpConn = udpConn
  35. err = s.udpConn.SetReadBuffer(s.MaxMessageLen) // FIXME probably
  36. if err != nil {
  37. return errors.Wrap(err, "could not set readbuffer on UDP socket")
  38. }
  39. err = s.udpConn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
  40. if err != nil {
  41. return errors.Wrap(err, "could not set read deadline on UDP socket")
  42. }
  43. return nil
  44. }
  45. func (s *SyslogServer) SetChannel(c chan SyslogMessage) {
  46. s.channel = c
  47. }
  48. func (s *SyslogServer) StartServer() *tomb.Tomb {
  49. t := tomb.Tomb{}
  50. t.Go(func() error {
  51. for {
  52. select {
  53. case <-t.Dying():
  54. s.Logger.Info("syslog server tomb is dying")
  55. err := s.KillServer()
  56. return err
  57. default:
  58. //RFC3164 says 1024 bytes max
  59. //RFC5424 says 480 bytes minimum, and should support up to 2048 bytes
  60. b := make([]byte, s.MaxMessageLen)
  61. n, addr, err := s.udpConn.ReadFrom(b)
  62. if err != nil && !strings.Contains(err.Error(), "i/o timeout") {
  63. s.Logger.Errorf("error while reading from socket : %s", err)
  64. s.udpConn.Close()
  65. return err
  66. }
  67. if err == nil {
  68. s.channel <- SyslogMessage{Message: b[:n], Client: strings.Split(addr.String(), ":")[0]}
  69. }
  70. err = s.udpConn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
  71. if err != nil {
  72. return err
  73. }
  74. }
  75. }
  76. })
  77. return &t
  78. }
  79. func (s *SyslogServer) KillServer() error {
  80. err := s.udpConn.Close()
  81. if err != nil {
  82. return errors.Wrap(err, "could not close UDP connection")
  83. }
  84. return nil
  85. }