github.com/leverly/deis@v1.0.2/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  }