mirror of
https://github.com/kenzok8/openwrt-packages.git
synced 2025-01-09 03:58:26 +08:00
update 2023-09-18 08:24:30
This commit is contained in:
parent
0f941aa292
commit
4fff2250b4
@ -1,7 +1,7 @@
|
||||
From 7e89f3ead620e0345c63b60c05d9f3c34ee1d9fd Mon Sep 17 00:00:00 2001
|
||||
From 208abee452a28674e521bc317fb901c4e7c2a7a9 Mon Sep 17 00:00:00 2001
|
||||
From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com>
|
||||
Date: Sun, 17 Sep 2023 19:52:38 +0800
|
||||
Subject: [PATCH 3/3] fixed #712
|
||||
Subject: [PATCH] fixed #712
|
||||
|
||||
---
|
||||
plugin/executable/nftset/nftset_linux.go | 11 ++++++++---
|
@ -1,350 +0,0 @@
|
||||
From fdfca40f4ddcffd07621c2049f17e117c1973eca Mon Sep 17 00:00:00 2001
|
||||
From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com>
|
||||
Date: Thu, 31 Aug 2023 18:09:09 +0800
|
||||
Subject: [PATCH 1/3] server: simplify udp oob handling
|
||||
|
||||
---
|
||||
pkg/server/udp.go | 71 +++++++---------
|
||||
pkg/server/udp_linux.go | 112 +++++++++++--------------
|
||||
pkg/server/udp_others.go | 4 +-
|
||||
plugin/server/udp_server/udp_server.go | 5 +-
|
||||
4 files changed, 86 insertions(+), 106 deletions(-)
|
||||
|
||||
diff --git a/pkg/server/udp.go b/pkg/server/udp.go
|
||||
index 45d689c..8980a08 100644
|
||||
--- a/pkg/server/udp.go
|
||||
+++ b/pkg/server/udp.go
|
||||
@@ -22,14 +22,14 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
+ "net"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/mlog"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/pool"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler"
|
||||
- "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/miekg/dns"
|
||||
"go.uber.org/zap"
|
||||
- "net"
|
||||
)
|
||||
|
||||
type UDPServer struct {
|
||||
@@ -53,39 +53,31 @@ func (opts *UDPServerOpts) init() {
|
||||
return
|
||||
}
|
||||
|
||||
-// cmcUDPConn can read and write cmsg.
|
||||
-type cmcUDPConn interface {
|
||||
- readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error)
|
||||
- writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error)
|
||||
-}
|
||||
-
|
||||
// ServeUDP starts a server at c. It returns if c had a read error.
|
||||
// It always returns a non-nil error.
|
||||
-func (s *UDPServer) ServeUDP(c net.PacketConn) error {
|
||||
+func (s *UDPServer) ServeUDP(c *net.UDPConn) error {
|
||||
listenerCtx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
rb := pool.GetBuf(dns.MaxMsgSize)
|
||||
defer pool.ReleaseBuf(rb)
|
||||
|
||||
- var cmc cmcUDPConn
|
||||
- var err error
|
||||
- uc, ok := c.(*net.UDPConn)
|
||||
- if ok && uc.LocalAddr().(*net.UDPAddr).IP.IsUnspecified() {
|
||||
- cmc, err = newCmc(uc)
|
||||
- if err != nil {
|
||||
- return fmt.Errorf("failed to control socket cmsg, %w", err)
|
||||
- }
|
||||
- } else {
|
||||
- cmc = newDummyCmc(c)
|
||||
+ oobReader, oobWriter, err := initOobHandler(c)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("failed to init oob handler, %w", err)
|
||||
+ }
|
||||
+ var ob []byte
|
||||
+ if oobReader != nil {
|
||||
+ ob := pool.GetBuf(1024)
|
||||
+ defer pool.ReleaseBuf(ob)
|
||||
}
|
||||
|
||||
for {
|
||||
- n, localAddr, ifIndex, remoteAddr, err := cmc.readFrom(rb)
|
||||
+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(rb, ob)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unexpected read err: %w", err)
|
||||
}
|
||||
- clientAddr := utils.GetAddrFromAddr(remoteAddr)
|
||||
+ clientAddr := remoteAddr.Addr()
|
||||
|
||||
q := new(dns.Msg)
|
||||
if err := q.Unpack(rb[:n]); err != nil {
|
||||
@@ -93,6 +85,15 @@ func (s *UDPServer) ServeUDP(c net.PacketConn) error {
|
||||
continue
|
||||
}
|
||||
|
||||
+ var dstIpFromCm net.IP
|
||||
+ if oobReader != nil {
|
||||
+ var err error
|
||||
+ dstIpFromCm, err = oobReader(ob[:oobn])
|
||||
+ if err != nil {
|
||||
+ s.opts.Logger.Error("failed to get dst address from oob", zap.Error(err))
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// handle query
|
||||
go func() {
|
||||
qCtx := query_context.NewContext(q)
|
||||
@@ -110,7 +111,12 @@ func (s *UDPServer) ServeUDP(c net.PacketConn) error {
|
||||
return
|
||||
}
|
||||
defer pool.ReleaseBuf(buf)
|
||||
- if _, err := cmc.writeTo(b, localAddr, ifIndex, remoteAddr); err != nil {
|
||||
+ var oob []byte
|
||||
+
|
||||
+ if oobWriter != nil && dstIpFromCm != nil {
|
||||
+ oob = oobWriter(dstIpFromCm)
|
||||
+ }
|
||||
+ if _, _, err := c.WriteMsgUDPAddrPort(b, oob, remoteAddr); err != nil {
|
||||
s.opts.Logger.Warn("failed to write response", zap.Stringer("client", remoteAddr), zap.Error(err))
|
||||
}
|
||||
}
|
||||
@@ -129,22 +135,5 @@ func getUDPSize(m *dns.Msg) int {
|
||||
return int(s)
|
||||
}
|
||||
|
||||
-// newDummyCmc returns a dummyCmcWrapper.
|
||||
-func newDummyCmc(c net.PacketConn) cmcUDPConn {
|
||||
- return dummyCmcWrapper{c: c}
|
||||
-}
|
||||
-
|
||||
-// dummyCmcWrapper is just a wrapper that implements cmcUDPConn but does not
|
||||
-// write or read any control msg.
|
||||
-type dummyCmcWrapper struct {
|
||||
- c net.PacketConn
|
||||
-}
|
||||
-
|
||||
-func (w dummyCmcWrapper) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) {
|
||||
- n, src, err = w.c.ReadFrom(b)
|
||||
- return
|
||||
-}
|
||||
-
|
||||
-func (w dummyCmcWrapper) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) {
|
||||
- return w.c.WriteTo(b, dst)
|
||||
-}
|
||||
+type getSrcAddrFromOOB func(oob []byte) (net.IP, error)
|
||||
+type writeSrcAddrToOOB func(a net.IP) []byte
|
||||
diff --git a/pkg/server/udp_linux.go b/pkg/server/udp_linux.go
|
||||
index 4eb466d..9728a39 100644
|
||||
--- a/pkg/server/udp_linux.go
|
||||
+++ b/pkg/server/udp_linux.go
|
||||
@@ -22,84 +22,71 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
+ "errors"
|
||||
"fmt"
|
||||
+ "net"
|
||||
+ "os"
|
||||
+
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/sys/unix"
|
||||
- "net"
|
||||
- "os"
|
||||
)
|
||||
|
||||
-type ipv4cmc struct {
|
||||
- c *ipv4.PacketConn
|
||||
-}
|
||||
-
|
||||
-func newIpv4cmc(c *ipv4.PacketConn) *ipv4cmc {
|
||||
- return &ipv4cmc{c: c}
|
||||
-}
|
||||
+var (
|
||||
+ errCmNoDstAddr = errors.New("control msg does not have dst address")
|
||||
+)
|
||||
|
||||
-func (i *ipv4cmc) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) {
|
||||
- n, cm, src, err := i.c.ReadFrom(b)
|
||||
- if cm != nil {
|
||||
- dst, IfIndex = cm.Dst, cm.IfIndex
|
||||
+func getOOBFromCM4(oob []byte) (net.IP, error) {
|
||||
+ var cm ipv4.ControlMessage
|
||||
+ if err := cm.Parse(oob); err != nil {
|
||||
+ return nil, err
|
||||
}
|
||||
- return
|
||||
-}
|
||||
-
|
||||
-func (i *ipv4cmc) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) {
|
||||
- cm := &ipv4.ControlMessage{
|
||||
- Src: src,
|
||||
- IfIndex: IfIndex,
|
||||
+ if cm.Dst == nil {
|
||||
+ return nil, errCmNoDstAddr
|
||||
}
|
||||
- return i.c.WriteTo(b, cm, dst)
|
||||
+ return cm.Dst, nil
|
||||
}
|
||||
|
||||
-type ipv6cmc struct {
|
||||
- c4 *ipv4.PacketConn // ipv4 entrypoint for sending ipv4 packages.
|
||||
- c6 *ipv6.PacketConn
|
||||
+func getOOBFromCM6(oob []byte) (net.IP, error) {
|
||||
+ var cm ipv6.ControlMessage
|
||||
+ if err := cm.Parse(oob); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ if cm.Dst == nil {
|
||||
+ return nil, errCmNoDstAddr
|
||||
+ }
|
||||
+ return cm.Dst, nil
|
||||
}
|
||||
|
||||
-func newIpv6PacketConn(c4 *ipv4.PacketConn, c6 *ipv6.PacketConn) *ipv6cmc {
|
||||
- return &ipv6cmc{c4: c4, c6: c6}
|
||||
-}
|
||||
+func srcIP2Cm(ip net.IP) []byte {
|
||||
+ if ip4 := ip.To4(); ip4 != nil {
|
||||
+ return (&ipv4.ControlMessage{
|
||||
+ Src: ip,
|
||||
+ }).Marshal()
|
||||
+ }
|
||||
|
||||
-func (i *ipv6cmc) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) {
|
||||
- n, cm, src, err := i.c6.ReadFrom(b)
|
||||
- if cm != nil {
|
||||
- dst, IfIndex = cm.Dst, cm.IfIndex
|
||||
+ if ip6 := ip.To16(); ip6 != nil {
|
||||
+ return (&ipv6.ControlMessage{
|
||||
+ Src: ip,
|
||||
+ }).Marshal()
|
||||
}
|
||||
- return
|
||||
+
|
||||
+ return nil
|
||||
}
|
||||
|
||||
-func (i *ipv6cmc) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) {
|
||||
- if src != nil {
|
||||
- // If src is ipv4, use IP_PKTINFO instead of IPV6_PKTINFO.
|
||||
- // Otherwise, sendmsg will raise "invalid argument" error.
|
||||
- // No official doc found.
|
||||
- if src4 := src.To4(); src4 != nil {
|
||||
- cm4 := &ipv4.ControlMessage{
|
||||
- Src: src4,
|
||||
- IfIndex: IfIndex,
|
||||
- }
|
||||
- return i.c4.WriteTo(b, cm4, dst)
|
||||
- }
|
||||
- }
|
||||
- cm6 := &ipv6.ControlMessage{
|
||||
- Src: src,
|
||||
- IfIndex: IfIndex,
|
||||
+func initOobHandler(c *net.UDPConn) (getSrcAddrFromOOB, writeSrcAddrToOOB, error) {
|
||||
+ if !c.LocalAddr().(*net.UDPAddr).IP.IsUnspecified() {
|
||||
+ return nil, nil, nil
|
||||
}
|
||||
- return i.c6.WriteTo(b, cm6, dst)
|
||||
-}
|
||||
|
||||
-func newCmc(c *net.UDPConn) (cmcUDPConn, error) {
|
||||
sc, err := c.SyscallConn()
|
||||
if err != nil {
|
||||
- return nil, err
|
||||
+ return nil, nil, err
|
||||
}
|
||||
|
||||
+ var getter getSrcAddrFromOOB
|
||||
+ var setter writeSrcAddrToOOB
|
||||
var controlErr error
|
||||
- var cmc cmcUDPConn
|
||||
-
|
||||
if err := sc.Control(func(fd uintptr) {
|
||||
v, err := unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_DOMAIN)
|
||||
if err != nil {
|
||||
@@ -109,27 +96,30 @@ func newCmc(c *net.UDPConn) (cmcUDPConn, error) {
|
||||
switch v {
|
||||
case unix.AF_INET:
|
||||
c4 := ipv4.NewPacketConn(c)
|
||||
- if err := c4.SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
|
||||
+ if err := c4.SetControlMessage(ipv4.FlagDst, true); err != nil {
|
||||
controlErr = fmt.Errorf("failed to set ipv4 cmsg flags, %w", err)
|
||||
}
|
||||
- cmc = newIpv4cmc(c4)
|
||||
+
|
||||
+ getter = getOOBFromCM4
|
||||
+ setter = srcIP2Cm
|
||||
return
|
||||
case unix.AF_INET6:
|
||||
c6 := ipv6.NewPacketConn(c)
|
||||
- if err := c6.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||
+ if err := c6.SetControlMessage(ipv6.FlagDst, true); err != nil {
|
||||
controlErr = fmt.Errorf("failed to set ipv6 cmsg flags, %w", err)
|
||||
}
|
||||
- cmc = newIpv6PacketConn(ipv4.NewPacketConn(c), c6)
|
||||
+ getter = getOOBFromCM6
|
||||
+ setter = srcIP2Cm
|
||||
return
|
||||
default:
|
||||
controlErr = fmt.Errorf("socket protocol %d is not supported", v)
|
||||
}
|
||||
}); err != nil {
|
||||
- return nil, fmt.Errorf("control fd err, %w", controlErr)
|
||||
+ return nil, nil, fmt.Errorf("control fd err, %w", controlErr)
|
||||
}
|
||||
|
||||
if controlErr != nil {
|
||||
- return nil, fmt.Errorf("failed to set up socket, %w", controlErr)
|
||||
+ return nil, nil, fmt.Errorf("failed to set up socket, %w", controlErr)
|
||||
}
|
||||
- return cmc, nil
|
||||
+ return getter, setter, nil
|
||||
}
|
||||
diff --git a/pkg/server/udp_others.go b/pkg/server/udp_others.go
|
||||
index 8ce6280..1e42651 100644
|
||||
--- a/pkg/server/udp_others.go
|
||||
+++ b/pkg/server/udp_others.go
|
||||
@@ -23,6 +23,6 @@ package server
|
||||
|
||||
import "net"
|
||||
|
||||
-func newCmc(c *net.UDPConn) (cmcUDPConn, error) {
|
||||
- return newDummyCmc(c), nil
|
||||
+func initOobHandler(c *net.UDPConn) (getSrcAddrFromOOB, writeSrcAddrToOOB, error) {
|
||||
+ return nil, nil, nil
|
||||
}
|
||||
diff --git a/plugin/server/udp_server/udp_server.go b/plugin/server/udp_server/udp_server.go
|
||||
index 9ed94f5..293f720 100644
|
||||
--- a/plugin/server/udp_server/udp_server.go
|
||||
+++ b/plugin/server/udp_server/udp_server.go
|
||||
@@ -21,11 +21,12 @@ package udp_server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+ "net"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/server"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/IrineSistiana/mosdns/v5/plugin/server/server_utils"
|
||||
- "net"
|
||||
)
|
||||
|
||||
const PluginType = "udp_server"
|
||||
@@ -71,7 +72,7 @@ func StartServer(bp *coremain.BP, args *Args) (*UdpServer, error) {
|
||||
}
|
||||
go func() {
|
||||
defer c.Close()
|
||||
- err := s.ServeUDP(c)
|
||||
+ err := s.ServeUDP(c.(*net.UDPConn))
|
||||
bp.M().GetSafeClose().SendCloseSignal(err)
|
||||
}()
|
||||
return &UdpServer{
|
||||
--
|
||||
2.34.8
|
||||
|
@ -1,475 +0,0 @@
|
||||
From 5687ee04b7ffb71382a8be0680e988985faeb5c1 Mon Sep 17 00:00:00 2001
|
||||
From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com>
|
||||
Date: Sun, 17 Sep 2023 08:29:31 +0800
|
||||
Subject: [PATCH 2/3] use go-bytes-pool
|
||||
|
||||
---
|
||||
go.mod | 1 +
|
||||
go.sum | 2 +
|
||||
pkg/dnsutils/net_io.go | 45 +++++----
|
||||
pkg/pool/allocator.go | 78 +---------------
|
||||
pkg/pool/allocator_test.go | 119 ------------------------
|
||||
pkg/pool/msg_buf.go | 4 +-
|
||||
pkg/pool/msg_buf_test.go | 4 +-
|
||||
pkg/server/udp.go | 6 +-
|
||||
pkg/upstream/transport/dns_conn_test.go | 4 +-
|
||||
plugin/executable/cache/cache.go | 8 +-
|
||||
10 files changed, 43 insertions(+), 228 deletions(-)
|
||||
delete mode 100644 pkg/pool/allocator_test.go
|
||||
|
||||
diff --git a/go.mod b/go.mod
|
||||
index 1a1dd43..63fa30a 100644
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -3,6 +3,7 @@ module github.com/IrineSistiana/mosdns/v5
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
+ github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686
|
||||
github.com/go-chi/chi/v5 v5.0.10
|
||||
github.com/google/nftables v0.1.0
|
||||
github.com/kardianos/service v1.2.2
|
||||
diff --git a/go.sum b/go.sum
|
||||
index 59c420f..08a330d 100644
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 h1:5R32cCep3VUDTKf3aurFKfgbvg+RScuBmZsw/DyyXco=
|
||||
+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI=
|
||||
github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a h1:GQdh/h0q0ni3L//CXusyk+7QdhBL289vdNaes1WKkHI=
|
||||
github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
diff --git a/pkg/dnsutils/net_io.go b/pkg/dnsutils/net_io.go
|
||||
index 1b8a7b1..8fc769b 100644
|
||||
--- a/pkg/dnsutils/net_io.go
|
||||
+++ b/pkg/dnsutils/net_io.go
|
||||
@@ -23,9 +23,10 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
+ "io"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/pool"
|
||||
"github.com/miekg/dns"
|
||||
- "io"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -35,45 +36,43 @@ var (
|
||||
// ReadRawMsgFromTCP reads msg from c in RFC 1035 format (msg is prefixed
|
||||
// with a two byte length field).
|
||||
// n represents how many bytes are read from c.
|
||||
-// The returned the []byte should be released by pool.ReleaseBuf.
|
||||
-func ReadRawMsgFromTCP(c io.Reader) ([]byte, int, error) {
|
||||
- n := 0
|
||||
+// The returned the *[]byte should be released by pool.ReleaseBuf.
|
||||
+func ReadRawMsgFromTCP(c io.Reader) (*[]byte, error) {
|
||||
h := pool.GetBuf(2)
|
||||
defer pool.ReleaseBuf(h)
|
||||
- nh, err := io.ReadFull(c, h)
|
||||
- n += nh
|
||||
+ _, err := io.ReadFull(c, *h)
|
||||
+
|
||||
if err != nil {
|
||||
- return nil, n, err
|
||||
+ return nil, err
|
||||
}
|
||||
|
||||
// dns length
|
||||
- length := binary.BigEndian.Uint16(h)
|
||||
+ length := binary.BigEndian.Uint16(*h)
|
||||
if length == 0 {
|
||||
- return nil, 0, errZeroLenMsg
|
||||
+ return nil, errZeroLenMsg
|
||||
}
|
||||
|
||||
- buf := pool.GetBuf(int(length))
|
||||
- nm, err := io.ReadFull(c, buf)
|
||||
- n += nm
|
||||
+ b := pool.GetBuf(int(length))
|
||||
+ _, err = io.ReadFull(c, *b)
|
||||
if err != nil {
|
||||
- pool.ReleaseBuf(buf)
|
||||
- return nil, n, err
|
||||
+ pool.ReleaseBuf(b)
|
||||
+ return nil, err
|
||||
}
|
||||
- return buf, n, nil
|
||||
+ return b, nil
|
||||
}
|
||||
|
||||
// ReadMsgFromTCP reads msg from c in RFC 1035 format (msg is prefixed
|
||||
// with a two byte length field).
|
||||
// n represents how many bytes are read from c.
|
||||
func ReadMsgFromTCP(c io.Reader) (*dns.Msg, int, error) {
|
||||
- b, n, err := ReadRawMsgFromTCP(c)
|
||||
+ b, err := ReadRawMsgFromTCP(c)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
defer pool.ReleaseBuf(b)
|
||||
|
||||
- m, err := unpackMsgWithDetailedErr(b)
|
||||
- return m, n, err
|
||||
+ m, err := unpackMsgWithDetailedErr(*b)
|
||||
+ return m, len(*b) + 2, err
|
||||
}
|
||||
|
||||
// WriteMsgToTCP packs and writes m to c in RFC 1035 format.
|
||||
@@ -96,9 +95,9 @@ func WriteRawMsgToTCP(c io.Writer, b []byte) (n int, err error) {
|
||||
buf := pool.GetBuf(len(b) + 2)
|
||||
defer pool.ReleaseBuf(buf)
|
||||
|
||||
- binary.BigEndian.PutUint16(buf[:2], uint16(len(b)))
|
||||
- copy(buf[2:], b)
|
||||
- return c.Write(buf)
|
||||
+ binary.BigEndian.PutUint16((*buf)[:2], uint16(len(b)))
|
||||
+ copy((*buf)[2:], b)
|
||||
+ return c.Write((*buf))
|
||||
}
|
||||
|
||||
func WriteMsgToUDP(c io.Writer, m *dns.Msg) (int, error) {
|
||||
@@ -118,12 +117,12 @@ func ReadMsgFromUDP(c io.Reader, bufSize int) (*dns.Msg, int, error) {
|
||||
|
||||
b := pool.GetBuf(bufSize)
|
||||
defer pool.ReleaseBuf(b)
|
||||
- n, err := c.Read(b)
|
||||
+ n, err := c.Read(*b)
|
||||
if err != nil {
|
||||
return nil, n, err
|
||||
}
|
||||
|
||||
- m, err := unpackMsgWithDetailedErr(b[:n])
|
||||
+ m, err := unpackMsgWithDetailedErr((*b)[:n])
|
||||
return m, n, err
|
||||
}
|
||||
|
||||
diff --git a/pkg/pool/allocator.go b/pkg/pool/allocator.go
|
||||
index 0bfc0bc..d8ac4ef 100644
|
||||
--- a/pkg/pool/allocator.go
|
||||
+++ b/pkg/pool/allocator.go
|
||||
@@ -20,79 +20,11 @@
|
||||
package pool
|
||||
|
||||
import (
|
||||
- "fmt"
|
||||
- "math"
|
||||
- "math/bits"
|
||||
- "sync"
|
||||
+ bytesPool "github.com/IrineSistiana/go-bytes-pool"
|
||||
)
|
||||
|
||||
// defaultBufPool is an Allocator that has a maximum capacity.
|
||||
-var defaultBufPool = NewAllocator()
|
||||
-
|
||||
-// GetBuf returns a []byte from pool with most appropriate cap.
|
||||
-// It panics if size < 0.
|
||||
-func GetBuf(size int) []byte {
|
||||
- return defaultBufPool.Get(size)
|
||||
-}
|
||||
-
|
||||
-// ReleaseBuf puts the buf to the pool.
|
||||
-func ReleaseBuf(b []byte) {
|
||||
- defaultBufPool.Release(b)
|
||||
-}
|
||||
-
|
||||
-type Allocator struct {
|
||||
- buffers []sync.Pool
|
||||
-}
|
||||
-
|
||||
-// NewAllocator initiates a []byte Allocator.
|
||||
-// The waste(memory fragmentation) of space allocation is guaranteed to be
|
||||
-// no more than 50%.
|
||||
-func NewAllocator() *Allocator {
|
||||
- alloc := &Allocator{
|
||||
- buffers: make([]sync.Pool, bits.UintSize+1),
|
||||
- }
|
||||
-
|
||||
- for i := range alloc.buffers {
|
||||
- var bufSize uint
|
||||
- if i == bits.UintSize {
|
||||
- bufSize = math.MaxUint
|
||||
- } else {
|
||||
- bufSize = 1 << i
|
||||
- }
|
||||
- alloc.buffers[i].New = func() any {
|
||||
- b := make([]byte, bufSize)
|
||||
- return &b
|
||||
- }
|
||||
- }
|
||||
- return alloc
|
||||
-}
|
||||
-
|
||||
-// Get returns a []byte from pool with most appropriate cap
|
||||
-func (alloc *Allocator) Get(size int) []byte {
|
||||
- if size < 0 {
|
||||
- panic(fmt.Sprintf("invalid slice size %d", size))
|
||||
- }
|
||||
-
|
||||
- i := shard(size)
|
||||
- v := alloc.buffers[i].Get()
|
||||
- buf := v.(*[]byte)
|
||||
- return (*buf)[0:size]
|
||||
-}
|
||||
-
|
||||
-// Release releases the buf to the allocatorL.
|
||||
-func (alloc *Allocator) Release(buf []byte) {
|
||||
- c := cap(buf)
|
||||
- i := shard(c)
|
||||
- if c == 0 || c != 1<<i {
|
||||
- panic("unexpected cap size")
|
||||
- }
|
||||
- alloc.buffers[i].Put(&buf)
|
||||
-}
|
||||
-
|
||||
-// shard returns the shard index that is suitable for the size.
|
||||
-func shard(size int) int {
|
||||
- if size <= 1 {
|
||||
- return 0
|
||||
- }
|
||||
- return bits.Len64(uint64(size - 1))
|
||||
-}
|
||||
+var (
|
||||
+ GetBuf = bytesPool.Get
|
||||
+ ReleaseBuf = bytesPool.Release
|
||||
+)
|
||||
diff --git a/pkg/pool/allocator_test.go b/pkg/pool/allocator_test.go
|
||||
deleted file mode 100644
|
||||
index 3f6d2a9..0000000
|
||||
--- a/pkg/pool/allocator_test.go
|
||||
+++ /dev/null
|
||||
@@ -1,119 +0,0 @@
|
||||
-/*
|
||||
- * Copyright (C) 2020-2022, IrineSistiana
|
||||
- *
|
||||
- * This file is part of mosdns.
|
||||
- *
|
||||
- * mosdns is free software: you can redistribute it and/or modify
|
||||
- * it under the terms of the GNU General Public License as published by
|
||||
- * the Free Software Foundation, either version 3 of the License, or
|
||||
- * (at your option) any later version.
|
||||
- *
|
||||
- * mosdns is distributed in the hope that it will be useful,
|
||||
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- * GNU General Public License for more details.
|
||||
- *
|
||||
- * You should have received a copy of the GNU General Public License
|
||||
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
- */
|
||||
-
|
||||
-package pool
|
||||
-
|
||||
-import (
|
||||
- "fmt"
|
||||
- "strconv"
|
||||
- "testing"
|
||||
-)
|
||||
-
|
||||
-func TestAllocator_Get(t *testing.T) {
|
||||
- alloc := NewAllocator()
|
||||
- tests := []struct {
|
||||
- size int
|
||||
- wantCap int
|
||||
- wantPanic bool
|
||||
- }{
|
||||
- {-1, 0, true}, // invalid
|
||||
- {0, 1, false},
|
||||
- {1, 1, false},
|
||||
- {2, 2, false},
|
||||
- {12, 16, false},
|
||||
- {256, 256, false},
|
||||
- {257, 512, false},
|
||||
- }
|
||||
- for _, tt := range tests {
|
||||
- t.Run(strconv.Itoa(tt.size), func(t *testing.T) {
|
||||
- if tt.wantPanic {
|
||||
- defer func() {
|
||||
- msg := recover()
|
||||
- if msg == nil {
|
||||
- t.Error("no panic")
|
||||
- }
|
||||
- }()
|
||||
- }
|
||||
-
|
||||
- for i := 0; i < 5; i++ {
|
||||
- b := alloc.Get(tt.size)
|
||||
- if len(b) != tt.size {
|
||||
- t.Fatalf("buffer size, want %d, got %d", tt.size, len(b))
|
||||
- }
|
||||
- if cap(b) != tt.wantCap {
|
||||
- t.Fatalf("buffer cap, want %d, got %d", tt.wantCap, cap(b))
|
||||
- }
|
||||
- alloc.Release(b)
|
||||
- }
|
||||
- })
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-func Test_shard(t *testing.T) {
|
||||
- tests := []struct {
|
||||
- size int
|
||||
- want int
|
||||
- }{
|
||||
- {-1, 0},
|
||||
- {0, 0},
|
||||
- {1, 0},
|
||||
- {2, 1},
|
||||
- {3, 2},
|
||||
- {4, 2},
|
||||
- {5, 3},
|
||||
- {8, 3},
|
||||
- {1023, 10},
|
||||
- {1024, 10},
|
||||
- {1025, 11},
|
||||
- }
|
||||
- for _, tt := range tests {
|
||||
- t.Run(strconv.Itoa(tt.size), func(t *testing.T) {
|
||||
- if got := shard(tt.size); got != tt.want {
|
||||
- t.Errorf("shard() = %v, want %v", got, tt.want)
|
||||
- }
|
||||
- })
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-func Benchmark_Allocator(b *testing.B) {
|
||||
- allocator := NewAllocator()
|
||||
-
|
||||
- for l := 0; l <= 16; l += 4 {
|
||||
- bufLen := 1 << l
|
||||
- b.Run(fmt.Sprintf("length %d", bufLen), func(b *testing.B) {
|
||||
- b.ReportAllocs()
|
||||
- for i := 0; i < b.N; i++ {
|
||||
- buf := allocator.Get(bufLen)
|
||||
- allocator.Release(buf)
|
||||
- }
|
||||
- })
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-func Benchmark_MakeByteSlice(b *testing.B) {
|
||||
- for l := 0; l <= 8; l++ {
|
||||
- bufLen := 1 << l
|
||||
- b.Run(fmt.Sprintf("length %d", bufLen), func(b *testing.B) {
|
||||
- b.ReportAllocs()
|
||||
- for i := 0; i < b.N; i++ {
|
||||
- _ = make([]byte, bufLen)
|
||||
- }
|
||||
- })
|
||||
- }
|
||||
-}
|
||||
diff --git a/pkg/pool/msg_buf.go b/pkg/pool/msg_buf.go
|
||||
index 83eea80..980a08b 100644
|
||||
--- a/pkg/pool/msg_buf.go
|
||||
+++ b/pkg/pool/msg_buf.go
|
||||
@@ -31,9 +31,9 @@ const packBufSize = 4096
|
||||
// PackBuffer packs the dns msg m to wire format.
|
||||
// Callers should release the buf by calling ReleaseBuf after they have done
|
||||
// with the wire []byte.
|
||||
-func PackBuffer(m *dns.Msg) (wire, buf []byte, err error) {
|
||||
+func PackBuffer(m *dns.Msg) (wire []byte, buf *[]byte, err error) {
|
||||
buf = GetBuf(packBufSize)
|
||||
- wire, err = m.PackBuffer(buf)
|
||||
+ wire, err = m.PackBuffer(*buf)
|
||||
if err != nil {
|
||||
ReleaseBuf(buf)
|
||||
return nil, nil, err
|
||||
diff --git a/pkg/pool/msg_buf_test.go b/pkg/pool/msg_buf_test.go
|
||||
index 0685864..02d7348 100644
|
||||
--- a/pkg/pool/msg_buf_test.go
|
||||
+++ b/pkg/pool/msg_buf_test.go
|
||||
@@ -32,7 +32,7 @@ func TestPackBuffer_No_Allocation(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
- if cap(wire) != cap(buf) {
|
||||
- t.Fatalf("wire and buf have different cap, wire %d, buf %d", cap(wire), cap(buf))
|
||||
+ if cap(wire) != cap(*buf) {
|
||||
+ t.Fatalf("wire and buf have different cap, wire %d, buf %d", cap(wire), cap(*buf))
|
||||
}
|
||||
}
|
||||
diff --git a/pkg/server/udp.go b/pkg/server/udp.go
|
||||
index 8980a08..c1c9aa9 100644
|
||||
--- a/pkg/server/udp.go
|
||||
+++ b/pkg/server/udp.go
|
||||
@@ -73,15 +73,15 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error {
|
||||
}
|
||||
|
||||
for {
|
||||
- n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(rb, ob)
|
||||
+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, ob)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unexpected read err: %w", err)
|
||||
}
|
||||
clientAddr := remoteAddr.Addr()
|
||||
|
||||
q := new(dns.Msg)
|
||||
- if err := q.Unpack(rb[:n]); err != nil {
|
||||
- s.opts.Logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", rb[:n]), zap.Stringer("from", remoteAddr))
|
||||
+ if err := q.Unpack((*rb)[:n]); err != nil {
|
||||
+ s.opts.Logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", (*rb)[:n]), zap.Stringer("from", remoteAddr))
|
||||
continue
|
||||
}
|
||||
|
||||
diff --git a/pkg/upstream/transport/dns_conn_test.go b/pkg/upstream/transport/dns_conn_test.go
|
||||
index 8c49131..c677797 100644
|
||||
--- a/pkg/upstream/transport/dns_conn_test.go
|
||||
+++ b/pkg/upstream/transport/dns_conn_test.go
|
||||
@@ -40,13 +40,13 @@ var (
|
||||
c1, c2 := net.Pipe()
|
||||
go func() {
|
||||
for {
|
||||
- m, _, readErr := dnsutils.ReadRawMsgFromTCP(c2)
|
||||
+ m, readErr := dnsutils.ReadRawMsgFromTCP(c2)
|
||||
if m != nil {
|
||||
go func() {
|
||||
defer pool.ReleaseBuf(m)
|
||||
latency := time.Millisecond * time.Duration(rand.Intn(20))
|
||||
time.Sleep(latency)
|
||||
- _, _ = dnsutils.WriteRawMsgToTCP(c2, m)
|
||||
+ _, _ = dnsutils.WriteRawMsgToTCP(c2, *m)
|
||||
}()
|
||||
}
|
||||
if readErr != nil {
|
||||
diff --git a/plugin/executable/cache/cache.go b/plugin/executable/cache/cache.go
|
||||
index 34229c7..9d2e79d 100644
|
||||
--- a/plugin/executable/cache/cache.go
|
||||
+++ b/plugin/executable/cache/cache.go
|
||||
@@ -423,27 +423,27 @@ func (c *Cache) readDump(r io.Reader) (int, error) {
|
||||
readBlock := func() error {
|
||||
h := pool.GetBuf(8)
|
||||
defer pool.ReleaseBuf(h)
|
||||
- _, err := io.ReadFull(gr, h)
|
||||
+ _, err := io.ReadFull(gr, *h)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return errReadHeaderEOF
|
||||
}
|
||||
return fmt.Errorf("failed to read block header, %w", err)
|
||||
}
|
||||
- u := binary.BigEndian.Uint64(h)
|
||||
+ u := binary.BigEndian.Uint64(*h)
|
||||
if u > dumpMaximumBlockLength {
|
||||
return fmt.Errorf("invalid header, block length is big, %d", u)
|
||||
}
|
||||
|
||||
b := pool.GetBuf(int(u))
|
||||
defer pool.ReleaseBuf(b)
|
||||
- _, err = io.ReadFull(gr, b)
|
||||
+ _, err = io.ReadFull(gr, *b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read block data, %w", err)
|
||||
}
|
||||
|
||||
block := new(CacheDumpBlock)
|
||||
- if err := proto.Unmarshal(b, block); err != nil {
|
||||
+ if err := proto.Unmarshal(*b, block); err != nil {
|
||||
return fmt.Errorf("failed to decode block data, %w", err)
|
||||
}
|
||||
|
||||
--
|
||||
2.34.8
|
||||
|
Loading…
Reference in New Issue
Block a user