package srslog import ( "crypto/tls" "net" ) // dialerFunctionWrapper is a simple object that consists of a dialer function // and its name. This is primarily for testing, so we can make sure that the // getDialer method returns the correct dialer function. However, if you ever // find that you need to check which dialer function you have, this would also // be useful for you without having to use reflection. type dialerFunctionWrapper struct { Name string Dialer func() (serverConn, string, error) } // Call the wrapped dialer function and return its return values. func (df dialerFunctionWrapper) Call() (serverConn, string, error) { return df.Dialer() } // getDialer returns a "dialer" function that can be called to connect to a // syslog server. // // Each dialer function is responsible for dialing the remote host and returns // a serverConn, the hostname (or a default if the Writer has not specified a // hostname), and an error in case dialing fails. // // The reason for separate dialers is that different network types may need // to dial their connection differently, yet still provide a net.Conn interface // that you can use once they have dialed. Rather than an increasingly long // conditional, we have a map of network -> dialer function (with a sane default // value), and adding a new network type is as easy as writing the dialer // function and adding it to the map. func (w *Writer) getDialer() dialerFunctionWrapper { dialers := map[string]dialerFunctionWrapper{ "": dialerFunctionWrapper{"unixDialer", w.unixDialer}, "tcp+tls": dialerFunctionWrapper{"tlsDialer", w.tlsDialer}, "custom": dialerFunctionWrapper{"customDialer", w.customDialer}, } dialer, ok := dialers[w.network] if !ok { dialer = dialerFunctionWrapper{"basicDialer", w.basicDialer} } return dialer } // unixDialer uses the unixSyslog method to open a connection to the syslog // daemon running on the local machine. func (w *Writer) unixDialer() (serverConn, string, error) { sc, err := unixSyslog() hostname := w.hostname if hostname == "" { hostname = "localhost" } return sc, hostname, err } // tlsDialer connects to TLS over TCP, and is used for the "tcp+tls" network // type. func (w *Writer) tlsDialer() (serverConn, string, error) { c, err := tls.Dial("tcp", w.raddr, w.tlsConfig) var sc serverConn hostname := w.hostname if err == nil { sc = &netConn{conn: c} if hostname == "" { hostname = c.LocalAddr().String() } } return sc, hostname, err } // basicDialer is the most common dialer for syslog, and supports both TCP and // UDP connections. func (w *Writer) basicDialer() (serverConn, string, error) { c, err := net.Dial(w.network, w.raddr) var sc serverConn hostname := w.hostname if err == nil { sc = &netConn{conn: c} if hostname == "" { hostname = c.LocalAddr().String() } } return sc, hostname, err } // customDialer uses the custom dialer when the Writer was created // giving developers total control over how connections are made and returned. // Note it does not check if cdialer is nil, as it should only be referenced from getDialer. func (w *Writer) customDialer() (serverConn, string, error) { c, err := w.customDial(w.network, w.raddr) var sc serverConn hostname := w.hostname if err == nil { sc = &netConn{conn: c} if hostname == "" { hostname = c.LocalAddr().String() } } return sc, hostname, err }