Cleanup / temp buffers for various things
This commit is contained in:
@@ -23,6 +23,10 @@ const (
|
|||||||
TimeoutInterval = 30 * time.Second
|
TimeoutInterval = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// scratchSize is large enough for the biggest buffer either the ping or the
|
||||||
|
// multicast path serializes through the shared App scratch.
|
||||||
|
const scratchSize = max(control.Size, multicast.SignedPacketSize)
|
||||||
|
|
||||||
type PingEvent struct {
|
type PingEvent struct {
|
||||||
srcVPNIP netip.Addr
|
srcVPNIP netip.Addr
|
||||||
ping control.Ping
|
ping control.Ping
|
||||||
@@ -53,8 +57,9 @@ type App struct {
|
|||||||
selfV4 netip.AddrPort
|
selfV4 netip.AddrPort
|
||||||
selfV6 netip.AddrPort
|
selfV6 netip.AddrPort
|
||||||
|
|
||||||
// Reusable scratch for multicast signature verification (event loop only).
|
// Reusable serialization scratch for outgoing pings and multicast signature
|
||||||
mcVerifyBuf []byte
|
// verification. Only touched from the Run goroutine.
|
||||||
|
scratch []byte
|
||||||
|
|
||||||
// Event channels fed by background goroutines
|
// Event channels fed by background goroutines
|
||||||
hubAddCh <-chan m.Peer
|
hubAddCh <-chan m.Peer
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ func newTestApp(t *testing.T, vpnIP string, isPublic, isRelay bool) (*App, *fake
|
|||||||
controlConn: cc,
|
controlConn: cc,
|
||||||
peersByKey: make(map[wgtypes.Key]*Peer),
|
peersByKey: make(map[wgtypes.Key]*Peer),
|
||||||
peersByIP: make(map[netip.Addr]*Peer),
|
peersByIP: make(map[netip.Addr]*Peer),
|
||||||
|
scratch: make([]byte, scratchSize),
|
||||||
hubAddCh: make(chan m.Peer),
|
hubAddCh: make(chan m.Peer),
|
||||||
hubRemoveCh: make(chan wgtypes.Key),
|
hubRemoveCh: make(chan wgtypes.Key),
|
||||||
pingCh: make(chan PingEvent),
|
pingCh: make(chan PingEvent),
|
||||||
|
|||||||
@@ -33,15 +33,18 @@ type Ping struct {
|
|||||||
Dst netip.AddrPort
|
Dst netip.AddrPort
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal encodes p into a fixed-size 51-byte array.
|
// Marshal encodes p into buf (which must be at least Size bytes) and returns
|
||||||
func (p Ping) Marshal() [Size]byte {
|
// buf[:Size]. Taking the buffer lets callers reuse one across sends; every
|
||||||
var buf [Size]byte
|
// field is written unconditionally so a reused buffer needs no pre-zeroing.
|
||||||
|
func (p Ping) Marshal(buf []byte) []byte {
|
||||||
buf[0] = version
|
buf[0] = version
|
||||||
binary.BigEndian.PutUint64(buf[1:9], uint64(p.PingTS))
|
binary.BigEndian.PutUint64(buf[1:9], uint64(p.PingTS))
|
||||||
if p.SrcV4.IsValid() {
|
if p.SrcV4.IsValid() {
|
||||||
a4 := p.SrcV4.Addr().As4()
|
a4 := p.SrcV4.Addr().As4()
|
||||||
copy(buf[9:13], a4[:])
|
copy(buf[9:13], a4[:])
|
||||||
binary.BigEndian.PutUint16(buf[13:15], p.SrcV4.Port())
|
binary.BigEndian.PutUint16(buf[13:15], p.SrcV4.Port())
|
||||||
|
} else {
|
||||||
|
clear(buf[9:15])
|
||||||
}
|
}
|
||||||
a16 := p.SrcV6.Addr().As16()
|
a16 := p.SrcV6.Addr().As16()
|
||||||
copy(buf[15:31], a16[:])
|
copy(buf[15:31], a16[:])
|
||||||
@@ -49,7 +52,7 @@ func (p Ping) Marshal() [Size]byte {
|
|||||||
a16 = p.Dst.Addr().As16()
|
a16 = p.Dst.Addr().As16()
|
||||||
copy(buf[33:49], a16[:])
|
copy(buf[33:49], a16[:])
|
||||||
binary.BigEndian.PutUint16(buf[49:51], p.Dst.Port())
|
binary.BigEndian.PutUint16(buf[49:51], p.Dst.Port())
|
||||||
return buf
|
return buf[:Size]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal decodes a Ping from a fixed-size 51-byte array.
|
// Unmarshal decodes a Ping from a fixed-size 51-byte array.
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ func TestRoundTrip(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
buf := tc.ping.Marshal()
|
var buf [control.Size]byte
|
||||||
|
tc.ping.Marshal(buf[:])
|
||||||
got, err := control.Unmarshal(buf)
|
got, err := control.Unmarshal(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unmarshal: %v", err)
|
t.Fatalf("Unmarshal: %v", err)
|
||||||
@@ -80,7 +81,8 @@ func TestUnmarshalBadVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestZeroEncoding(t *testing.T) {
|
func TestZeroEncoding(t *testing.T) {
|
||||||
buf := (control.Ping{}).Marshal()
|
var buf [control.Size]byte
|
||||||
|
(control.Ping{}).Marshal(buf[:])
|
||||||
for i, b := range buf {
|
for i, b := range buf {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
continue // version byte
|
continue // version byte
|
||||||
|
|||||||
@@ -24,9 +24,8 @@ func newUDPControlConn(localIP netip.Addr, port uint16) (*udpControlConn, error)
|
|||||||
return &udpControlConn{conn: conn}, nil
|
return &udpControlConn{conn: conn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpControlConn) SendPing(dst netip.AddrPort, ping control.Ping) error {
|
func (c *udpControlConn) SendPing(dst netip.AddrPort, ping control.Ping, buf []byte) error {
|
||||||
buf := ping.Marshal()
|
_, err := c.conn.WriteToUDP(ping.Marshal(buf), net.UDPAddrFromAddrPort(dst))
|
||||||
_, err := c.conn.WriteToUDP(buf[:], net.UDPAddrFromAddrPort(dst))
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type fakeControlConn struct {
|
|||||||
Sent []sentPing
|
Sent []sentPing
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeControlConn) SendPing(dst netip.AddrPort, ping control.Ping) error {
|
func (f *fakeControlConn) SendPing(dst netip.AddrPort, ping control.Ping, _ []byte) error {
|
||||||
f.Sent = append(f.Sent, sentPing{Dst: dst, Ping: ping})
|
f.Sent = append(f.Sent, sentPing{Dst: dst, Ping: ping})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ type WGDevice interface {
|
|||||||
|
|
||||||
// ControlConn sends pings to peers over the VPN control port.
|
// ControlConn sends pings to peers over the VPN control port.
|
||||||
// Reading is handled separately via run, which feeds the App's pingCh.
|
// Reading is handled separately via run, which feeds the App's pingCh.
|
||||||
|
// buf is a caller-provided scratch buffer (at least control.Size bytes) used to
|
||||||
|
// marshal the ping; the caller reuses one across sends.
|
||||||
type ControlConn interface {
|
type ControlConn interface {
|
||||||
SendPing(dst netip.AddrPort, ping control.Ping) error
|
SendPing(dst netip.AddrPort, ping control.Ping, buf []byte) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ func New(
|
|||||||
peersByKey: make(map[wgtypes.Key]*Peer),
|
peersByKey: make(map[wgtypes.Key]*Peer),
|
||||||
peersByIP: make(map[netip.Addr]*Peer),
|
peersByIP: make(map[netip.Addr]*Peer),
|
||||||
|
|
||||||
mcVerifyBuf: make([]byte, 0, multicast.SignedPacketSize),
|
scratch: make([]byte, scratchSize),
|
||||||
|
|
||||||
hubAddCh: hubAddCh,
|
hubAddCh: hubAddCh,
|
||||||
hubRemoveCh: hubRemoveCh,
|
hubRemoveCh: hubRemoveCh,
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ func (a *App) onMulticastDiscovery(pkt multicast.Packet) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authenticate the beacon against the peer's known sign key.
|
// Authenticate the beacon against the peer's known sign key. scratch[:0]
|
||||||
if !pkt.Verify(a.mcVerifyBuf, &peer.SignPubKey) {
|
// gives sign.Open an empty-but-capacity buffer to decode into.
|
||||||
|
if !pkt.Verify(a.scratch[:0], &peer.SignPubKey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func (a *App) sendPing(p *Peer, ts int64) {
|
|||||||
Dst: p.WGEndpoint(),
|
Dst: p.WGEndpoint(),
|
||||||
}
|
}
|
||||||
dst := netip.AddrPortFrom(p.VPNIP, ControlPort)
|
dst := netip.AddrPortFrom(p.VPNIP, ControlPort)
|
||||||
if err := a.controlConn.SendPing(dst, ping); err != nil {
|
if err := a.controlConn.SendPing(dst, ping, a.scratch); err != nil {
|
||||||
log.Printf("sendPing %v: %v", p.VPNIP, err)
|
log.Printf("sendPing %v: %v", p.VPNIP, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user