From 04b4a02dfc473f8539321dc52587b73f3bdde3b2 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 22 Aug 2015 19:02:13 +0300 Subject: [PATCH] Make transport less dependent on UDP nature Signed-off-by: Sergey Matveev --- src/govpn/cmd/govpn-client/main.go | 54 ++++++++++------- src/govpn/cmd/govpn-server/main.go | 95 ++++++++++++++++++++---------- src/govpn/handshake.go | 35 ++++++----- src/govpn/netconn.go | 58 ------------------ src/govpn/transport.go | 37 +++++------- src/govpn/transport_test.go | 36 +++++------ 6 files changed, 148 insertions(+), 167 deletions(-) delete mode 100644 src/govpn/netconn.go diff --git a/src/govpn/cmd/govpn-client/main.go b/src/govpn/cmd/govpn-client/main.go index 627001a..d11f843 100644 --- a/src/govpn/cmd/govpn-client/main.go +++ b/src/govpn/cmd/govpn-client/main.go @@ -78,7 +78,7 @@ func main() { if err != nil { log.Fatalln("Can not resolve address:", err) } - conn, err := net.ListenUDP("udp", bind) + conn, err := net.DialUDP("udp", bind, remote) if err != nil { log.Fatalln("Can not listen on UDP:", err) } @@ -87,6 +87,26 @@ func main() { log.Fatalln("Can not resolve remote address:", err) } + sink := make(chan []byte) + ready := make(chan struct{}) + go func() { + buf := make([]byte, govpn.MTU) + var n int + var err error + for { + <-ready + conn.SetReadDeadline(time.Now().Add(time.Second)) + n, err = conn.Read(buf) + if err != nil { + // This is needed for ticking the timeouts counter outside + sink <- nil + continue + } + sink <- buf[:n] + } + }() + ready <- struct{}{} + tap, ethSink, ethReady, _, err := govpn.TAPListen( *ifaceName, time.Second*time.Duration(timeout), @@ -95,13 +115,12 @@ func main() { if err != nil { log.Fatalln("Can not listen on TAP interface:", err) } - udpSink, udpReady := govpn.ConnListenUDP(conn) timeouts := 0 firstUpCall := true var peer *govpn.Peer var ethPkt []byte - var udpPkt govpn.UDPPkt + var pkt []byte knownPeers := govpn.KnownPeers(map[string]**govpn.Peer{remote.String(): &peer}) log.Println(govpn.VersionGet()) @@ -119,14 +138,14 @@ func main() { signal.Notify(termSignal, os.Interrupt, os.Kill) log.Println("Starting handshake") - handshake := govpn.HandshakeStart(conf, conn, remote) + handshake := govpn.HandshakeStart(remote.String(), conn, conf) MainCycle: for { if peer != nil && (peer.BytesIn+peer.BytesOut) > govpn.MaxBytesPerKey { peer.Zero() peer = nil - handshake = govpn.HandshakeStart(conf, conn, remote) + handshake = govpn.HandshakeStart(remote.String(), conn, conf) log.Println("Rehandshaking") } select { @@ -139,29 +158,24 @@ MainCycle: } continue } - peer.EthProcess(ethPkt, conn, ethReady) - case udpPkt = <-udpSink: + peer.EthProcess(ethPkt, ethReady) + case pkt = <-sink: timeouts++ if timeouts >= timeout { break MainCycle } - if udpPkt.Addr == nil { - udpReady <- struct{}{} + if pkt == nil { + ready <- struct{}{} continue } if peer == nil { - if udpPkt.Addr.String() != remote.String() { - udpReady <- struct{}{} - log.Println("Unknown handshake message") - continue - } - if govpn.IDsCache.Find(udpPkt.Data) == nil { + if govpn.IDsCache.Find(pkt) == nil { log.Println("Invalid identity in handshake packet") - udpReady <- struct{}{} + ready <- struct{}{} continue } - if p := handshake.Client(conn, udpPkt.Data); p != nil { + if p := handshake.Client(pkt); p != nil { log.Println("Handshake completed") if firstUpCall { go govpn.ScriptCall(*upPath, *ifaceName) @@ -171,14 +185,14 @@ MainCycle: handshake.Zero() handshake = nil } - udpReady <- struct{}{} + ready <- struct{}{} continue } if peer == nil { - udpReady <- struct{}{} + ready <- struct{}{} continue } - if peer.UDPProcess(udpPkt.Data, tap, udpReady) { + if peer.PktProcess(pkt, tap, ready) { timeouts = 0 } } diff --git a/src/govpn/cmd/govpn-server/main.go b/src/govpn/cmd/govpn-server/main.go index 15f8681..6e25f4c 100644 --- a/src/govpn/cmd/govpn-server/main.go +++ b/src/govpn/cmd/govpn-server/main.go @@ -22,6 +22,7 @@ package main import ( "bytes" "flag" + "io" "log" "net" "os" @@ -40,6 +41,21 @@ var ( egdPath = flag.String("egd", "", "Optional path to EGD socket") ) +type Pkt struct { + addr string + conn io.Writer + data []byte +} + +type UDPSender struct { + conn *net.UDPConn + addr *net.UDPAddr +} + +func (c UDPSender) Write(data []byte) (int, error) { + return c.conn.WriteToUDP(data, c.addr) +} + type PeerReadyEvent struct { peer *govpn.Peer iface string @@ -93,11 +109,31 @@ func main() { if err != nil { log.Fatalln("Can not resolve bind address:", err) } - conn, err := net.ListenUDP("udp", bind) + lconn, err := net.ListenUDP("udp", bind) if err != nil { log.Fatalln("Can listen on UDP:", err) } - udpSink, udpReady := govpn.ConnListenUDP(conn) + + sink := make(chan Pkt) + ready := make(chan struct{}) + go func() { + buf := make([]byte, govpn.MTU) + var n int + var raddr *net.UDPAddr + var err error + for { + <-ready + lconn.SetReadDeadline(time.Now().Add(time.Second)) + n, raddr, err = lconn.ReadFromUDP(buf) + if err != nil { + // This is needed for ticking the timeouts counter outside + sink <- Pkt{} + continue + } + sink <- Pkt{raddr.String(), UDPSender{lconn, raddr}, buf[:n]} + } + }() + ready <- struct{}{} termSignal := make(chan os.Signal, 1) signal.Notify(termSignal, os.Interrupt, os.Kill) @@ -105,7 +141,6 @@ func main() { hsHeartbeat := time.Tick(timeout) go func() { <-hsHeartbeat }() - var addr string var state *govpn.Handshake var peerState *PeerState var peer *govpn.Peer @@ -115,7 +150,7 @@ func main() { peerReadySink := make(chan PeerReadyEvent) knownPeers := govpn.KnownPeers(make(map[string]**govpn.Peer)) var peerReady PeerReadyEvent - var udpPkt govpn.UDPPkt + var pkt Pkt var ethEvent EthEvent var peerId *govpn.PeerId var peerConf *govpn.PeerConf @@ -174,15 +209,14 @@ MainCycle: state.peer.Zero() break } - addr = peerReady.peer.Addr.String() state := NewPeerState(peerReady.peer, peerReady.iface) if state == nil { continue } - peers[addr] = state - knownPeers[addr] = &peerReady.peer - states[addr].Zero() - delete(states, addr) + peers[peerReady.peer.Addr] = state + knownPeers[peerReady.peer.Addr] = &peerReady.peer + states[peerReady.peer.Addr].Zero() + delete(states, peerReady.peer.Addr) log.Println("Registered interface", peerReady.iface, "with peer", peer) go func(state *PeerState) { for data := range state.sink { @@ -194,42 +228,43 @@ MainCycle: } }(state) case ethEvent = <-ethSink: - if s, exists := peers[ethEvent.peer.Addr.String()]; !exists || s.peer != ethEvent.peer { + if s, exists := peers[ethEvent.peer.Addr]; !exists || s.peer != ethEvent.peer { continue } - ethEvent.peer.EthProcess(ethEvent.data, conn, ethEvent.ready) - case udpPkt = <-udpSink: - if udpPkt.Addr == nil { - udpReady <- struct{}{} + ethEvent.peer.EthProcess(ethEvent.data, ethEvent.ready) + case pkt = <-sink: + if pkt.data == nil { + ready <- struct{}{} continue } - addr = udpPkt.Addr.String() handshakeProcessForce = false HandshakeProcess: - if _, exists = peers[addr]; handshakeProcessForce || !exists { - peerId = govpn.IDsCache.Find(udpPkt.Data) + if _, exists = peers[pkt.addr]; handshakeProcessForce || !exists { + peerId = govpn.IDsCache.Find(pkt.data) if peerId == nil { - log.Println("Unknown identity from", addr) - udpReady <- struct{}{} + log.Println("Unknown identity from", pkt.addr) + ready <- struct{}{} continue } peerConf = peerId.Conf() if peerConf == nil { log.Println("Can not get peer configuration", peerId.String()) - udpReady <- struct{}{} + ready <- struct{}{} continue } - state, exists = states[addr] + state, exists = states[pkt.addr] if !exists { - state = govpn.HandshakeNew(udpPkt.Addr, peerConf) - states[addr] = state + state = govpn.HandshakeNew(pkt.addr, pkt.conn, peerConf) + states[pkt.addr] = state } - peer = state.Server(conn, udpPkt.Data) + peer = state.Server(pkt.data) if peer != nil { log.Println("Peer handshake finished", peer) - if _, exists = peers[addr]; exists { + if _, exists = peers[pkt.addr]; exists { go func() { - peerReadySink <- PeerReadyEvent{peer, peers[addr].tap.Name} + peerReadySink <- PeerReadyEvent{ + peer, peers[pkt.addr].tap.Name, + } }() } else { go func() { @@ -248,18 +283,18 @@ MainCycle: } } if !handshakeProcessForce { - udpReady <- struct{}{} + ready <- struct{}{} } continue } - peerState, exists = peers[addr] + peerState, exists = peers[pkt.addr] if !exists { - udpReady <- struct{}{} + ready <- struct{}{} continue } // If it fails during processing, then try to work with it // as with handshake packet - if !peerState.peer.UDPProcess(udpPkt.Data, peerState.tap, udpReady) { + if !peerState.peer.PktProcess(pkt.data, peerState.tap, ready) { handshakeProcessForce = true goto HandshakeProcess } diff --git a/src/govpn/handshake.go b/src/govpn/handshake.go index 61b5b4f..3e3d0d6 100644 --- a/src/govpn/handshake.go +++ b/src/govpn/handshake.go @@ -22,8 +22,8 @@ import ( "crypto/rand" "crypto/subtle" "encoding/binary" + "io" "log" - "net" "time" "github.com/agl/ed25519" @@ -40,7 +40,8 @@ const ( ) type Handshake struct { - addr *net.UDPAddr + addr string + conn io.Writer LastPing time.Time Conf *PeerConf dsaPubH *[ed25519.PublicKeySize]byte @@ -133,9 +134,10 @@ func dhKeyGen(priv, pub *[32]byte) *[32]byte { } // Create new handshake state. -func HandshakeNew(addr *net.UDPAddr, conf *PeerConf) *Handshake { +func HandshakeNew(addr string, conn io.Writer, conf *PeerConf) *Handshake { state := Handshake{ addr: addr, + conn: conn, LastPing: time.Now(), Conf: conf, } @@ -157,11 +159,10 @@ func idTag(id *PeerId, data []byte) []byte { } // Start handshake's procedure from the client. It is the entry point -// for starting the handshake procedure. You have to specify outgoing -// conn address, remote's addr address, our own peer configuration. -// First handshake packet will be sent immediately. -func HandshakeStart(conf *PeerConf, conn *net.UDPConn, addr *net.UDPAddr) *Handshake { - state := HandshakeNew(addr, conf) +// for starting the handshake procedure. // First handshake packet +// will be sent immediately. +func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake { + state := HandshakeNew(addr, conn, conf) var dhPubRepr *[32]byte state.dhPriv, dhPubRepr = dhKeypairGen() @@ -174,17 +175,16 @@ func HandshakeStart(conf *PeerConf, conn *net.UDPConn, addr *net.UDPAddr) *Hands salsa20.XORKeyStream(enc, dhPubRepr[:], state.rNonce[:], state.dsaPubH) data := append(state.rNonce[:], enc...) data = append(data, idTag(state.Conf.Id, state.rNonce[:])...) - conn.WriteToUDP(data, addr) + state.conn.Write(data) return state } // Process handshake message on the server side. // This function is intended to be called on server's side. -// Our outgoing conn connection and received data are required. // If this is the final handshake message, then new Peer object // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. -func (h *Handshake) Server(conn *net.UDPConn, data []byte) *Peer { +func (h *Handshake) Server(data []byte) *Peer { // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag if len(data) == 48 && h.rNonce == nil { // Generate DH keypair @@ -222,7 +222,7 @@ func (h *Handshake) Server(conn *net.UDPConn, data []byte) *Peer { salsa20.XORKeyStream(encRs, append(h.rServer[:], h.sServer[:]...), h.rNonce[:], h.key) // Send that to client - conn.WriteToUDP(append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...), h.addr) + h.conn.Write(append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...)) h.LastPing = time.Now() } else // ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag @@ -249,11 +249,12 @@ func (h *Handshake) Server(conn *net.UDPConn, data []byte) *Peer { // Send final answer to client enc := make([]byte, RSize) salsa20.XORKeyStream(enc, dec[RSize:RSize+RSize], h.rNonceNext(2), h.key) - conn.WriteToUDP(append(enc, idTag(h.Conf.Id, enc)...), h.addr) + h.conn.Write(append(enc, idTag(h.Conf.Id, enc)...)) // Switch peer peer := newPeer( h.addr, + h.conn, h.Conf, 0, keyFromSecrets(h.sServer[:], dec[RSize+RSize:RSize+RSize+SSize])) @@ -267,12 +268,10 @@ func (h *Handshake) Server(conn *net.UDPConn, data []byte) *Peer { // Process handshake message on the client side. // This function is intended to be called on client's side. -// Our outgoing conn connection, authentication -// key and received data are required. // If this is the final handshake message, then new Peer object // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. -func (h *Handshake) Client(conn *net.UDPConn, data []byte) *Peer { +func (h *Handshake) Client(data []byte) *Peer { switch len(data) { case 80: // ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag if h.key != nil { @@ -313,7 +312,7 @@ func (h *Handshake) Client(conn *net.UDPConn, data []byte) *Peer { append(h.sClient[:], sign[:]...)...)...), h.rNonceNext(1), h.key) // Send that to server - conn.WriteToUDP(append(enc, idTag(h.Conf.Id, enc)...), h.addr) + h.conn.Write(append(enc, idTag(h.Conf.Id, enc)...)) h.LastPing = time.Now() case 16: // ENC(K, R+2, RC) + IDtag if h.key == nil { @@ -330,7 +329,7 @@ func (h *Handshake) Client(conn *net.UDPConn, data []byte) *Peer { } // Switch peer - peer := newPeer(h.addr, h.Conf, 1, keyFromSecrets(h.sServer[:], h.sClient[:])) + peer := newPeer(h.addr, h.conn, h.Conf, 1, keyFromSecrets(h.sServer[:], h.sClient[:])) h.LastPing = time.Now() return peer default: diff --git a/src/govpn/netconn.go b/src/govpn/netconn.go deleted file mode 100644 index 35eb981..0000000 --- a/src/govpn/netconn.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2015 Sergey Matveev - -This program 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. - -This program 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 . -*/ - -package govpn - -import ( - "net" - "time" -) - -type UDPPkt struct { - Addr *net.UDPAddr - Data []byte -} - -// Create UDP listening goroutine. -// This function takes already listening UDP socket and a buffer where -// all UDP packet data will be saved, channel where information about -// remote address and number of written bytes are stored, and a channel -// used to tell that buffer is ready to be overwritten. -func ConnListenUDP(conn *net.UDPConn) (chan UDPPkt, chan struct{}) { - buf := make([]byte, MTU) - sink := make(chan UDPPkt) - sinkReady := make(chan struct{}) - go func(conn *net.UDPConn) { - var n int - var addr *net.UDPAddr - var err error - for { - <-sinkReady - conn.SetReadDeadline(time.Now().Add(time.Second)) - n, addr, err = conn.ReadFromUDP(buf) - if err != nil { - // This is needed for ticking the timeouts counter outside - sink <- UDPPkt{nil, nil} - continue - } - sink <- UDPPkt{addr, buf[:n]} - } - }(conn) - sinkReady <- struct{}{} - return sink, sinkReady -} diff --git a/src/govpn/transport.go b/src/govpn/transport.go index 7eca502..23f04dd 100644 --- a/src/govpn/transport.go +++ b/src/govpn/transport.go @@ -21,7 +21,6 @@ package govpn import ( "encoding/binary" "io" - "net" "time" "golang.org/x/crypto/poly1305" @@ -43,8 +42,9 @@ const ( ) type Peer struct { - Addr *net.UDPAddr + Addr string Id *PeerId + Conn io.Writer // Traffic behaviour NoiseEnable bool @@ -93,7 +93,7 @@ type Peer struct { } func (p *Peer) String() string { - return p.Id.String() + ":" + p.Addr.String() + return p.Id.String() + ":" + p.Addr } // Zero peer's memory state. @@ -201,7 +201,7 @@ func cprCycleCalculate(rate int) time.Duration { return time.Second / time.Duration(rate*(1<<10)/MTU) } -func newPeer(addr *net.UDPAddr, conf *PeerConf, nonce int, key *[SSize]byte) *Peer { +func newPeer(addr string, conn io.Writer, conf *PeerConf, nonce int, key *[SSize]byte) *Peer { now := time.Now() timeout := conf.Timeout cprCycle := cprCycleCalculate(conf.CPR) @@ -214,6 +214,7 @@ func newPeer(addr *net.UDPAddr, conf *PeerConf, nonce int, key *[SSize]byte) *Pe } peer := Peer{ Addr: addr, + Conn: conn, Timeout: timeout, Established: now, LastPing: now, @@ -236,23 +237,22 @@ func newPeer(addr *net.UDPAddr, conf *PeerConf, nonce int, key *[SSize]byte) *Pe } // Process incoming UDP packet. -// udpPkt is received data, related to the peer tap interface and // ConnListen'es synchronization channel used to tell him that he is // free to receive new packets. Authenticated and decrypted packets // will be written to the interface immediately (except heartbeat ones). -func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) bool { - p.size = len(udpPkt) +func (p *Peer) PktProcess(data []byte, tap io.Writer, ready chan struct{}) bool { + p.size = len(data) copy(p.buf, Emptiness) - copy(p.tag[:], udpPkt[p.size-poly1305.TagSize:]) - copy(p.buf[S20BS:], udpPkt[NonceSize:p.size-poly1305.TagSize]) + copy(p.tag[:], data[p.size-poly1305.TagSize:]) + copy(p.buf[S20BS:], data[NonceSize:p.size-poly1305.TagSize]) salsa20.XORKeyStream( p.buf[:S20BS+p.size-poly1305.TagSize], p.buf[:S20BS+p.size-poly1305.TagSize], - udpPkt[:NonceSize], + data[:NonceSize], p.Key, ) copy(p.keyAuth[:], p.buf[:SSize]) - if !poly1305.Verify(p.tag, udpPkt[:p.size-poly1305.TagSize], p.keyAuth) { + if !poly1305.Verify(p.tag, data[:p.size-poly1305.TagSize], p.keyAuth) { ready <- struct{}{} p.FramesUnauth++ return false @@ -263,7 +263,7 @@ func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) boo // Check from the oldest bucket, as in most cases this will result // in constant time check. // If Bucket0 is filled, then it becomes Bucket1. - p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize]) + p.NonceCipher.Decrypt(p.buf, data[:NonceSize]) ready <- struct{}{} p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize]) if _, p.nonceFound = p.nonceBucket1[p.NonceRecv]; p.nonceFound { @@ -297,25 +297,20 @@ func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) boo return true } -type WriteToUDPer interface { - WriteToUDP([]byte, *net.UDPAddr) (int, error) -} - // Process incoming Ethernet packet. -// ethPkt is received data, conn is our outgoing connection. // ready channel is TAPListen's synchronization channel used to tell him // that he is free to receive new packets. Encrypted and authenticated // packets will be sent to remote Peer side immediately. -func (p *Peer) EthProcess(ethPkt []byte, conn WriteToUDPer, ready chan struct{}) { +func (p *Peer) EthProcess(data []byte, ready chan struct{}) { p.now = time.Now() - p.size = len(ethPkt) + p.size = len(data) // If this heartbeat is necessary if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) { return } copy(p.buf, Emptiness) if p.size > 0 { - copy(p.buf[S20BS+PktSizeSize:], ethPkt) + copy(p.buf[S20BS+PktSizeSize:], data) ready <- struct{}{} binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(p.size)) p.BytesPayloadOut += int64(p.size) @@ -349,5 +344,5 @@ func (p *Peer) EthProcess(ethPkt []byte, conn WriteToUDPer, ready chan struct{}) } } p.LastSent = p.now - conn.WriteToUDP(append(p.frame, p.tag[:]...), p.Addr) + p.Conn.Write(append(p.frame, p.tag[:]...)) } diff --git a/src/govpn/transport_test.go b/src/govpn/transport_test.go index 45f4d01..5809a9f 100644 --- a/src/govpn/transport_test.go +++ b/src/govpn/transport_test.go @@ -1,7 +1,6 @@ package govpn import ( - "net" "testing" "time" ) @@ -10,16 +9,24 @@ var ( peer *Peer plaintext []byte ready chan struct{} - dummy = &Dummy{} ciphertext []byte - addr *net.UDPAddr peerId *PeerId conf *PeerConf ) +type Dummy struct{ + dst *[]byte +} + +func (d Dummy) Write(b []byte) (int, error) { + if d.dst != nil { + *d.dst = b + } + return len(b), nil +} + func init() { MTU = 1500 - addr, _ = net.ResolveUDPAddr("udp", "[::1]:1") peerId, _ = IDDecode("ffffffffffffffffffffffffffffffff") conf = &PeerConf{ Id: peerId, @@ -27,7 +34,7 @@ func init() { NoiseEnable: false, CPR: 0, } - peer = newPeer(addr, conf, 128, new([SSize]byte)) + peer = newPeer("foo", Dummy{&ciphertext}, conf, 128, new([SSize]byte)) plaintext = make([]byte, 789) ready = make(chan struct{}) go func() { @@ -37,33 +44,22 @@ func init() { }() } -type Dummy struct{} - -func (d *Dummy) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) { - ciphertext = b - return len(b), nil -} - -func (d *Dummy) Write(p []byte) (n int, err error) { - return len(p), nil -} - func BenchmarkEnc(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { peer.NonceOur = 128 - peer.EthProcess(plaintext, dummy, ready) + peer.EthProcess(plaintext, ready) } } func BenchmarkDec(b *testing.B) { - peer.EthProcess(plaintext, dummy, ready) - peer = newPeer(addr, conf, 128, new([SSize]byte)) + peer.EthProcess(plaintext, ready) + peer = newPeer("foo", Dummy{nil}, conf, 128, new([SSize]byte)) b.ResetTimer() for i := 0; i < b.N; i++ { peer.nonceBucket0 = make(map[uint64]struct{}, 1) peer.nonceBucket1 = make(map[uint64]struct{}, 1) - if !peer.UDPProcess(ciphertext, dummy, ready) { + if !peer.PktProcess(ciphertext, Dummy{nil}, ready) { b.Fail() } } -- 2.44.0