]> Cypherpunks.ru repositories - govpn.git/commitdiff
Make transport less dependent on UDP nature
authorSergey Matveev <stargrave@stargrave.org>
Sat, 22 Aug 2015 16:02:13 +0000 (19:02 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sat, 22 Aug 2015 16:02:13 +0000 (19:02 +0300)
Signed-off-by: Sergey Matveev <stargrave@stargrave.org>
src/govpn/cmd/govpn-client/main.go
src/govpn/cmd/govpn-server/main.go
src/govpn/handshake.go
src/govpn/netconn.go [deleted file]
src/govpn/transport.go
src/govpn/transport_test.go

index 627001ab8e92d43ceae5b4b8988a7617a7961579..d11f84303d9024de86725ded3c1328a92d79540e 100644 (file)
@@ -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
                        }
                }
index 15f8681649ef2dfc6789cdcbe0ac4437ce0c18e2..6e25f4ce1342478d682f890f270bcffbec4bd858 100644 (file)
@@ -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
                        }
index 61b5b4f67dfe1f50fdb37d3c12ca032c62f8ce16..3e3d0d62b0417281f4128ecf750f0e5793012555 100644 (file)
@@ -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 (file)
index 35eb981..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-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
-}
index 7eca502ff41d69c20683d1646a6757f2a5876a10..23f04ddda4949c3782cb8429b312f1f8bcb22f73 100644 (file)
@@ -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[:]...))
 }
index 45f4d01cb6b6997bd871b7d9b6a5df29c87894d0..5809a9f4425a0a12a1edcacb38f276a5f8cf9ee2 100644 (file)
@@ -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()
                }
        }