dialer.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. "custom": dialerFunctionWrapper{"customDialer", w.customDialer},
  37. }
  38. dialer, ok := dialers[w.network]
  39. if !ok {
  40. dialer = dialerFunctionWrapper{"basicDialer", w.basicDialer}
  41. }
  42. return dialer
  43. }
  44. // unixDialer uses the unixSyslog method to open a connection to the syslog
  45. // daemon running on the local machine.
  46. func (w *Writer) unixDialer() (serverConn, string, error) {
  47. sc, err := unixSyslog()
  48. hostname := w.hostname
  49. if hostname == "" {
  50. hostname = "localhost"
  51. }
  52. return sc, hostname, err
  53. }
  54. // tlsDialer connects to TLS over TCP, and is used for the "tcp+tls" network
  55. // type.
  56. func (w *Writer) tlsDialer() (serverConn, string, error) {
  57. c, err := tls.Dial("tcp", w.raddr, w.tlsConfig)
  58. var sc serverConn
  59. hostname := w.hostname
  60. if err == nil {
  61. sc = &netConn{conn: c}
  62. if hostname == "" {
  63. hostname = c.LocalAddr().String()
  64. }
  65. }
  66. return sc, hostname, err
  67. }
  68. // basicDialer is the most common dialer for syslog, and supports both TCP and
  69. // UDP connections.
  70. func (w *Writer) basicDialer() (serverConn, string, error) {
  71. c, err := net.Dial(w.network, w.raddr)
  72. var sc serverConn
  73. hostname := w.hostname
  74. if err == nil {
  75. sc = &netConn{conn: c}
  76. if hostname == "" {
  77. hostname = c.LocalAddr().String()
  78. }
  79. }
  80. return sc, hostname, err
  81. }
  82. // customDialer uses the custom dialer when the Writer was created
  83. // giving developers total control over how connections are made and returned.
  84. // Note it does not check if cdialer is nil, as it should only be referenced from getDialer.
  85. func (w *Writer) customDialer() (serverConn, string, error) {
  86. c, err := w.customDial(w.network, w.raddr)
  87. var sc serverConn
  88. hostname := w.hostname
  89. if err == nil {
  90. sc = &netConn{conn: c}
  91. if hostname == "" {
  92. hostname = c.LocalAddr().String()
  93. }
  94. }
  95. return sc, hostname, err
  96. }