Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit c99c71a

Browse files
committed
chore: listening tcp together for dns server (#1792)
1 parent c7661d7 commit c99c71a

File tree

15 files changed

+140
-102
lines changed

15 files changed

+140
-102
lines changed

adapter/inbound/listen.go

+25-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func MPTCP() bool {
4343
return getMultiPathTCP(&lc.ListenConfig)
4444
}
4545

46-
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
46+
func preResolve(network, address string) (string, error) {
4747
switch network { // like net.Resolver.internetAddrList but filter domain to avoid call net.Resolver.lookupIPAddr
4848
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
4949
if host, port, err := net.SplitHostPort(address); err == nil {
@@ -59,11 +59,19 @@ func ListenContext(ctx context.Context, network, address string) (net.Listener,
5959
break
6060
default:
6161
if _, err := netip.ParseAddr(host); err != nil { // not ip
62-
return nil, fmt.Errorf("invalid network address: %s", address)
62+
return "", fmt.Errorf("invalid network address: %s", address)
6363
}
6464
}
6565
}
6666
}
67+
return address, nil
68+
}
69+
70+
func ListenContext(ctx context.Context, network, address string) (net.Listener, error) {
71+
address, err := preResolve(network, address)
72+
if err != nil {
73+
return nil, err
74+
}
6775

6876
mutex.RLock()
6977
defer mutex.RUnlock()
@@ -74,6 +82,21 @@ func Listen(network, address string) (net.Listener, error) {
7482
return ListenContext(context.Background(), network, address)
7583
}
7684

85+
func ListenPacketContext(ctx context.Context, network, address string) (net.PacketConn, error) {
86+
address, err := preResolve(network, address)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
mutex.RLock()
92+
defer mutex.RUnlock()
93+
return lc.ListenPacket(ctx, network, address)
94+
}
95+
96+
func ListenPacket(network, address string) (net.PacketConn, error) {
97+
return ListenPacketContext(context.Background(), network, address)
98+
}
99+
77100
func init() {
78101
keepalive.SetDisableKeepAliveCallback.Register(func(b bool) {
79102
mutex.Lock()

common/sockopt/reuse_common.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package sockopt
2+
3+
import (
4+
"net"
5+
"syscall"
6+
)
7+
8+
func RawConnReuseaddr(rc syscall.RawConn) (err error) {
9+
var innerErr error
10+
err = rc.Control(func(fd uintptr) {
11+
innerErr = reuseControl(fd)
12+
})
13+
14+
if innerErr != nil {
15+
err = innerErr
16+
}
17+
return
18+
}
19+
20+
func UDPReuseaddr(c net.PacketConn) error {
21+
if c, ok := c.(syscall.Conn); ok {
22+
rc, err := c.SyscallConn()
23+
if err != nil {
24+
return err
25+
}
26+
27+
return RawConnReuseaddr(rc)
28+
}
29+
return nil
30+
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
22

3-
package dialer
3+
package sockopt
44

5-
import (
6-
"net"
7-
)
8-
9-
func addrReuseToListenConfig(*net.ListenConfig) {}
5+
func reuseControl(fd uintptr) error { return nil }

common/sockopt/reuse_unix.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
2+
3+
package sockopt
4+
5+
import (
6+
"golang.org/x/sys/unix"
7+
)
8+
9+
func reuseControl(fd uintptr) error {
10+
e1 := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
11+
e2 := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
12+
13+
if e1 != nil {
14+
return e1
15+
}
16+
17+
if e2 != nil {
18+
return e2
19+
}
20+
21+
return nil
22+
}

common/sockopt/reuse_windows.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package sockopt
2+
3+
import (
4+
"golang.org/x/sys/windows"
5+
)
6+
7+
func reuseControl(fd uintptr) error {
8+
return windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
9+
}

common/sockopt/reuseaddr_linux.go

-19
This file was deleted.

common/sockopt/reuseaddr_other.go

-11
This file was deleted.

component/dialer/reuse_windows.go component/dialer/reuse.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ import (
55
"net"
66
"syscall"
77

8-
"golang.org/x/sys/windows"
8+
"github.com/metacubex/mihomo/common/sockopt"
99
)
1010

1111
func addrReuseToListenConfig(lc *net.ListenConfig) {
1212
addControlToListenConfig(lc, func(ctx context.Context, network, address string, c syscall.RawConn) error {
13-
return c.Control(func(fd uintptr) {
14-
windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
15-
})
13+
return sockopt.RawConnReuseaddr(c)
1614
})
1715
}

component/dialer/reuse_unix.go

-20
This file was deleted.

dns/server.go

+40-26
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"net"
77

8+
"github.com/metacubex/mihomo/adapter/inbound"
89
"github.com/metacubex/mihomo/common/sockopt"
910
"github.com/metacubex/mihomo/context"
1011
"github.com/metacubex/mihomo/log"
@@ -20,8 +21,9 @@ var (
2021
)
2122

2223
type Server struct {
23-
*D.Server
24-
handler handler
24+
handler handler
25+
tcpServer *D.Server
26+
udpServer *D.Server
2527
}
2628

2729
// ServeDNS implement D.Handler ServeDNS
@@ -55,12 +57,19 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
5557
return
5658
}
5759

58-
if server.Server != nil {
59-
server.Shutdown()
60-
server = &Server{}
61-
address = ""
60+
if server.tcpServer != nil {
61+
_ = server.tcpServer.Shutdown()
62+
server.tcpServer = nil
6263
}
6364

65+
if server.udpServer != nil {
66+
_ = server.udpServer.Shutdown()
67+
server.udpServer = nil
68+
}
69+
70+
server.handler = nil
71+
address = ""
72+
6473
if addr == "" {
6574
return
6675
}
@@ -77,31 +86,36 @@ func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
7786
return
7887
}
7988

80-
udpAddr, err := net.ResolveUDPAddr("udp", addr)
81-
if err != nil {
82-
return
83-
}
84-
85-
p, err := net.ListenUDP("udp", udpAddr)
86-
if err != nil {
87-
return
88-
}
89-
90-
err = sockopt.UDPReuseaddr(p)
91-
if err != nil {
92-
log.Warnln("Failed to Reuse UDP Address: %s", err)
93-
94-
err = nil
95-
}
96-
9789
address = addr
9890
handler := NewHandler(resolver, mapper)
9991
server = &Server{handler: handler}
100-
server.Server = &D.Server{Addr: addr, PacketConn: p, Handler: server}
10192

10293
go func() {
103-
server.ActivateAndServe()
94+
p, err := inbound.ListenPacket("udp", addr)
95+
if err != nil {
96+
log.Errorln("Start DNS server(UDP) error: %s", err.Error())
97+
return
98+
}
99+
100+
if err := sockopt.UDPReuseaddr(p); err != nil {
101+
log.Warnln("Failed to Reuse UDP Address: %s", err)
102+
}
103+
104+
log.Infoln("DNS server(UDP) listening at: %s", p.LocalAddr().String())
105+
server.udpServer = &D.Server{Addr: addr, PacketConn: p, Handler: server}
106+
_ = server.udpServer.ActivateAndServe()
107+
}()
108+
109+
go func() {
110+
l, err := inbound.Listen("tcp", addr)
111+
if err != nil {
112+
log.Errorln("Start DNS server(TCP) error: %s", err.Error())
113+
return
114+
}
115+
116+
log.Infoln("DNS server(TCP) listening at: %s", l.Addr().String())
117+
server.tcpServer = &D.Server{Addr: addr, Listener: l, Handler: server}
118+
_ = server.tcpServer.ActivateAndServe()
104119
}()
105120

106-
log.Infoln("DNS server listening at: %s", p.LocalAddr().String())
107121
}

listener/shadowsocks/udp.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ type UDPListener struct {
1818
}
1919

2020
func NewUDP(addr string, pickCipher core.Cipher, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPListener, error) {
21-
l, err := net.ListenPacket("udp", addr)
21+
l, err := inbound.ListenPacket("udp", addr)
2222
if err != nil {
2323
return nil, err
2424
}
2525

26-
err = sockopt.UDPReuseaddr(l.(*net.UDPConn))
27-
if err != nil {
26+
if err := sockopt.UDPReuseaddr(l); err != nil {
2827
log.Warnln("Failed to Reuse UDP Address: %s", err)
2928
}
3029

listener/sing_hysteria2/server.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,12 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
140140
_service := *service
141141
service := &_service // make a copy
142142

143-
ul, err := net.ListenPacket("udp", addr)
143+
ul, err := inbound.ListenPacket("udp", addr)
144144
if err != nil {
145145
return nil, err
146146
}
147147

148-
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
149-
if err != nil {
148+
if err := sockopt.UDPReuseaddr(ul); err != nil {
150149
log.Warnln("Failed to Reuse UDP Address: %s", err)
151150
}
152151

listener/sing_shadowsocks/server.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,12 @@ func New(config LC.ShadowsocksServer, tunnel C.Tunnel, additions ...inbound.Addi
8282

8383
if config.Udp {
8484
//UDP
85-
ul, err := net.ListenPacket("udp", addr)
85+
ul, err := inbound.ListenPacket("udp", addr)
8686
if err != nil {
8787
return nil, err
8888
}
8989

90-
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
91-
if err != nil {
90+
if err := sockopt.UDPReuseaddr(ul); err != nil {
9291
log.Warnln("Failed to Reuse UDP Address: %s", err)
9392
}
9493

listener/socks/udp.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ func NewUDP(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPLi
4040
inbound.WithSpecialRules(""),
4141
}
4242
}
43-
l, err := net.ListenPacket("udp", addr)
43+
l, err := inbound.ListenPacket("udp", addr)
4444
if err != nil {
4545
return nil, err
4646
}
4747

48-
if err := sockopt.UDPReuseaddr(l.(*net.UDPConn)); err != nil {
48+
if err := sockopt.UDPReuseaddr(l); err != nil {
4949
log.Warnln("Failed to Reuse UDP Address: %s", err)
5050
}
5151

listener/tuic/server.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,12 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (
152152
for _, addr := range strings.Split(config.Listen, ",") {
153153
addr := addr
154154

155-
ul, err := net.ListenPacket("udp", addr)
155+
ul, err := inbound.ListenPacket("udp", addr)
156156
if err != nil {
157157
return nil, err
158158
}
159159

160-
err = sockopt.UDPReuseaddr(ul.(*net.UDPConn))
161-
if err != nil {
160+
if err := sockopt.UDPReuseaddr(ul); err != nil {
162161
log.Warnln("Failed to Reuse UDP Address: %s", err)
163162
}
164163

0 commit comments

Comments
 (0)