interface.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // Package reuseport provides Listen and Dial functions that set socket
  2. // options in order to be able to reuse ports. You should only use this
  3. // package if you know what SO_REUSEADDR and SO_REUSEPORT are.
  4. //
  5. // For example:
  6. //
  7. // // listen on the same port. oh yeah.
  8. // l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
  9. // l2, _ := reuse.Listen("tcp", "127.0.0.1:1234")
  10. //
  11. // // dial from the same port. oh yeah.
  12. // l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
  13. // l2, _ := reuse.Listen("tcp", "127.0.0.1:1235")
  14. // c, _ := reuse.Dial("tcp", "127.0.0.1:1234", "127.0.0.1:1235")
  15. //
  16. // Note: cant dial self because tcp/ip stacks use 4-tuples to identify connections,
  17. // and doing so would clash.
  18. package reuseport
  19. import (
  20. "context"
  21. "fmt"
  22. "net"
  23. "time"
  24. )
  25. // Available returns whether or not SO_REUSEPORT or equivalent behaviour is
  26. // available in the OS.
  27. func Available() bool {
  28. return true
  29. }
  30. var listenConfig = net.ListenConfig{
  31. Control: Control,
  32. }
  33. // Listen listens at the given network and address. see net.Listen
  34. // Returns a net.Listener created from a file discriptor for a socket
  35. // with SO_REUSEPORT and SO_REUSEADDR option set.
  36. func Listen(network, address string) (net.Listener, error) {
  37. return listenConfig.Listen(context.Background(), network, address)
  38. }
  39. // ListenPacket listens at the given network and address. see net.ListenPacket
  40. // Returns a net.Listener created from a file discriptor for a socket
  41. // with SO_REUSEPORT and SO_REUSEADDR option set.
  42. func ListenPacket(network, address string) (net.PacketConn, error) {
  43. return listenConfig.ListenPacket(context.Background(), network, address)
  44. }
  45. // Dial dials the given network and address. see net.Dial
  46. // Returns a net.Conn created from a file descriptor for a socket
  47. // with SO_REUSEPORT and SO_REUSEADDR option set.
  48. func Dial(network, laddr, raddr string) (net.Conn, error) {
  49. return DialTimeout(network, laddr, raddr, time.Duration(0))
  50. }
  51. // Dial dials the given network and address, with the given timeout. see
  52. // net.DialTimeout Returns a net.Conn created from a file descriptor for
  53. // a socket with SO_REUSEPORT and SO_REUSEADDR option set.
  54. func DialTimeout(network, laddr, raddr string, timeout time.Duration) (net.Conn, error) {
  55. nla, err := ResolveAddr(network, laddr)
  56. if err != nil {
  57. return nil, fmt.Errorf("failed to resolve local addr: %w", err)
  58. }
  59. d := net.Dialer{
  60. Control: Control,
  61. LocalAddr: nla,
  62. Timeout: timeout,
  63. }
  64. return d.Dial(network, raddr)
  65. }