Skip to content

Instantly share code, notes, and snippets.

@chantra
Created March 21, 2018 18:18
Show Gist options
  • Save chantra/dfab011267be22989b25134537963e5c to your computer and use it in GitHub Desktop.
Save chantra/dfab011267be22989b25134537963e5c to your computer and use it in GitHub Desktop.
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