Created
March 21, 2018 18:18
-
-
Save chantra/dfab011267be22989b25134537963e5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/server.go b/server.go | |
index 685753f..8cf4038 100644 | |
--- a/server.go | |
+++ b/server.go | |
@@ -10,6 +10,8 @@ import ( | |
"net" | |
"sync" | |
"time" | |
+ | |
+ "github.com/libp2p/go-reuseport" | |
) | |
// Maximum number of TCP queries before we close the socket. | |
@@ -300,10 +302,16 @@ type Server struct { | |
// Shutdown handling | |
lock sync.RWMutex | |
started bool | |
+ // Should we use SO_REUSE_PORT | |
+ Soreuseport bool | |
} | |
// ListenAndServe starts a nameserver on the configured address in *Server. | |
func (srv *Server) ListenAndServe() error { | |
+ var l net.Listener | |
+ var p *net.UDPConn | |
+ var err error | |
+ | |
srv.lock.Lock() | |
defer srv.lock.Unlock() | |
if srv.started { | |
@@ -319,12 +327,19 @@ func (srv *Server) ListenAndServe() error { | |
switch srv.Net { | |
case "tcp", "tcp4", "tcp6": | |
a, err := net.ResolveTCPAddr(srv.Net, addr) | |
- if err != nil { | |
- return err | |
- } | |
- l, err := net.ListenTCP(srv.Net, a) | |
- if err != nil { | |
- return err | |
+ if srv.Soreuseport { | |
+ l, err = reuseport.Listen(srv.Net, a.String()) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ } else { | |
+ if err != nil { | |
+ return err | |
+ } | |
+ l, err = net.ListenTCP(srv.Net, a) | |
+ if err != nil { | |
+ return err | |
+ } | |
} | |
srv.Listener = l | |
srv.started = true | |
@@ -340,9 +355,17 @@ func (srv *Server) ListenAndServe() error { | |
network = "tcp6" | |
} | |
- l, err := tls.Listen(network, addr, srv.TLSConfig) | |
- if err != nil { | |
- return err | |
+ if srv.Soreuseport { | |
+ l, err = reuseport.Listen(srv.Net, addr) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ l = tls.NewListener(l, srv.TLSConfig) | |
+ } else { | |
+ l, err = tls.Listen(network, addr, srv.TLSConfig) | |
+ if err != nil { | |
+ return err | |
+ } | |
} | |
srv.Listener = l | |
srv.started = true | |
@@ -351,21 +374,32 @@ func (srv *Server) ListenAndServe() error { | |
srv.lock.Lock() // to satisfy the defer at the top | |
return err | |
case "udp", "udp4", "udp6": | |
- a, err := net.ResolveUDPAddr(srv.Net, addr) | |
- if err != nil { | |
- return err | |
- } | |
- l, err := net.ListenUDP(srv.Net, a) | |
- if err != nil { | |
- return err | |
+ var ok bool | |
+ if srv.Soreuseport { | |
+ pConn, err := reuseport.ListenPacket(srv.Net, addr) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if p, ok = pConn.(*net.UDPConn); !ok { | |
+ return &Error{err: "Cannot cast PacketConn to *net.UDPConn"} | |
+ } | |
+ } else { | |
+ a, err := net.ResolveUDPAddr(srv.Net, addr) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ p, err = net.ListenUDP(srv.Net, a) | |
+ if err != nil { | |
+ return err | |
+ } | |
} | |
- if e := setUDPSocketOptions(l); e != nil { | |
+ if e := setUDPSocketOptions(p); e != nil { | |
return e | |
} | |
- srv.PacketConn = l | |
+ srv.PacketConn = p | |
srv.started = true | |
srv.lock.Unlock() | |
- err = srv.serveUDP(l) | |
+ err = srv.serveUDP(p) | |
srv.lock.Lock() // to satisfy the defer at the top | |
return err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment