github.com/misfo/deis@v1.0.1-0.20141111224634-e0eee0392b8a/logger/syslog/server.go (about) 1 // Package syslog implements a syslog server library. It is based on RFC 3164, 2 // as such it does not properly parse packets with an RFC 5424 header format. 3 package syslog 4 5 import ( 6 "log" 7 "net" 8 "os" 9 "strings" 10 "unicode" 11 ) 12 13 // Server is the wrapper for a syslog server. 14 type Server struct { 15 conns []net.PacketConn 16 handlers []Handler 17 shutdown bool 18 l FatalLogger 19 } 20 21 // NewServer creates an idle server. 22 func NewServer() *Server { 23 return &Server{l: log.New(os.Stderr, "", log.LstdFlags)} 24 } 25 26 // SetLogger sets logger for server errors. A running server is rather quiet and 27 // logs only fatal errors using FatalLogger interface. By default standard Go 28 // logger is used so errors are writen to stderr and after that whole 29 // application is halted. Using SetLogger you can change this behavior (log 30 // erross elsewhere and don't halt whole application). 31 func (s *Server) SetLogger(l FatalLogger) { 32 s.l = l 33 } 34 35 // AddHandler adds h to internal ordered list of handlers 36 func (s *Server) AddHandler(h Handler) { 37 s.handlers = append(s.handlers, h) 38 } 39 40 // Listen starts gorutine that receives syslog messages on specified address. 41 // addr can be a path (for unix domain sockets) or host:port (for UDP). 42 func (s *Server) Listen(addr string) error { 43 var c net.PacketConn 44 if strings.IndexRune(addr, ':') != -1 { 45 a, err := net.ResolveUDPAddr("udp", addr) 46 if err != nil { 47 return err 48 } 49 c, err = net.ListenUDP("udp", a) 50 if err != nil { 51 return err 52 } 53 } else { 54 a, err := net.ResolveUnixAddr("unixgram", addr) 55 if err != nil { 56 return err 57 } 58 c, err = net.ListenUnixgram("unixgram", a) 59 if err != nil { 60 return err 61 } 62 } 63 s.conns = append(s.conns, c) 64 go s.receiver(c) 65 return nil 66 } 67 68 // Shutdown stops server. 69 func (s *Server) Shutdown() { 70 s.shutdown = true 71 for _, c := range s.conns { 72 err := c.Close() 73 if err != nil { 74 s.l.Fatalln(err) 75 } 76 } 77 s.passToHandlers(nil) 78 s.conns = nil 79 s.handlers = nil 80 } 81 82 func isNotAlnum(r rune) bool { 83 return !(unicode.IsLetter(r) || unicode.IsNumber(r)) 84 } 85 86 func isNulCrLf(r rune) bool { 87 return r == 0 || r == '\r' || r == '\n' 88 } 89 90 func (s *Server) passToHandlers(m SyslogMessage) { 91 for _, h := range s.handlers { 92 m = h.Handle(m) 93 if m == nil { 94 break 95 } 96 } 97 } 98 99 func (s *Server) receiver(c net.PacketConn) { 100 // make packet buffer the same size as logspout 101 buf := make([]byte, 1048576) 102 for { 103 n, _, err := c.ReadFrom(buf) 104 if err != nil { 105 if !s.shutdown { 106 s.l.Fatalln("Read error:", err) 107 } 108 return 109 } 110 // pass along the incoming syslog message 111 s.passToHandlers(&Message{string(buf[:n])}) 112 } 113 }