dialer.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package srslog
  2. import (
  3. "crypto/tls"
  4. "net"
  5. )
  6. // dialerFunctionWrapper is a simple object that consists of a dialer function
  7. // and its name. This is primarily for testing, so we can make sure that the
  8. // getDialer method returns the correct dialer function. However, if you ever
  9. // find that you need to check which dialer function you have, this would also
  10. // be useful for you without having to use reflection.
  11. type dialerFunctionWrapper struct {
  12. Name string
  13. Dialer func() (serverConn, string, error)
  14. }
  15. // Call the wrapped dialer function and return its return values.
  16. func (df dialerFunctionWrapper) Call() (serverConn, string, error) {
  17. return df.Dialer()
  18. }
  19. // getDialer returns a "dialer" function that can be called to connect to a
  20. // syslog server.
  21. //
  22. // Each dialer function is responsible for dialing the remote host and returns
  23. // a serverConn, the hostname (or a default if the Writer has not specified a
  24. // hostname), and an error in case dialing fails.
  25. //
  26. // The reason for separate dialers is that different network types may need
  27. // to dial their connection differently, yet still provide a net.Conn interface
  28. // that you can use once they have dialed. Rather than an increasingly long
  29. // conditional, we have a map of network -> dialer function (with a sane default
  30. // value), and adding a new network type is as easy as writing the dialer
  31. // function and adding it to the map.
  32. func (w *Writer) getDialer() dialerFunctionWrapper {
  33. dialers := map[string]dialerFunctionWrapper{
  34. "": dialerFunctionWrapper{"unixDialer", w.unixDialer},
  35. "tcp+tls": dialerFunctionWrapper{"tlsDialer", w.tlsDialer},
  36. }
  37. dialer, ok := dialers[w.network]
  38. if !ok {
  39. dialer = dialerFunctionWrapper{"basicDialer", w.basicDialer}
  40. }
  41. return dialer
  42. }
  43. // unixDialer uses the unixSyslog method to open a connection to the syslog
  44. // daemon running on the local machine.
  45. func (w *Writer) unixDialer() (serverConn, string, error) {
  46. sc, err := unixSyslog()
  47. hostname := w.hostname
  48. if hostname == "" {
  49. hostname = "localhost"
  50. }
  51. return sc, hostname, err
  52. }
  53. // tlsDialer connects to TLS over TCP, and is used for the "tcp+tls" network
  54. // type.
  55. func (w *Writer) tlsDialer() (serverConn, string, error) {
  56. c, err := tls.Dial("tcp", w.raddr, w.tlsConfig)
  57. var sc serverConn
  58. hostname := w.hostname
  59. if err == nil {
  60. sc = &netConn{conn: c}
  61. if hostname == "" {
  62. hostname = c.LocalAddr().String()
  63. }
  64. }
  65. return sc, hostname, err
  66. }
  67. // basicDialer is the most common dialer for syslog, and supports both TCP and
  68. // UDP connections.
  69. func (w *Writer) basicDialer() (serverConn, string, error) {
  70. c, err := net.Dial(w.network, w.raddr)
  71. var sc serverConn
  72. hostname := w.hostname
  73. if err == nil {
  74. sc = &netConn{conn: c}
  75. if hostname == "" {
  76. hostname = c.LocalAddr().String()
  77. }
  78. }
  79. return sc, hostname, err
  80. }