]> Cypherpunks.ru repositories - govpn.git/blobdiff - src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go
Use convenient simpler Go 1.9's sync.Map
[govpn.git] / src / cypherpunks.ru / govpn / cmd / govpn-server / udp.go
index 98993d30a18e5204a2f8c733c9cf8ddeea5d07c9..f074df47a6740ff390a665c3cfc94c3bfb1e0454 100644 (file)
@@ -1,6 +1,6 @@
 /*
 GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 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
@@ -36,7 +36,7 @@ func (c UDPSender) Write(data []byte) (int, error) {
 
 var (
        // Buffers for UDP parallel processing
-       udpBufs chan []byte = make(chan []byte, 1<<8)
+       udpBufs = make(chan []byte, 1<<8)
 )
 
 func startUDP() {
@@ -57,12 +57,16 @@ func startUDP() {
                var addr string
                var n int
                var err error
+               var exists bool
+               var psI interface{}
                var ps *PeerState
+               var hsI interface{}
                var hs *govpn.Handshake
+               var addrPrevI interface{}
                var addrPrev string
-               var exists bool
-               var peerId *govpn.PeerId
-               var peer *govpn.Peer
+               var peerPrevI interface{}
+               var peerPrev *PeerState
+               var peerID *govpn.PeerID
                var conf *govpn.PeerConf
                for {
                        buf = <-udpBufs
@@ -73,75 +77,94 @@ func startUDP() {
                        }
                        addr = raddr.String()
 
-                       peersLock.RLock()
-                       ps, exists = peers[addr]
-                       peersLock.RUnlock()
-                       if !exists {
-                               goto CheckHandshake
+                       psI, exists = peers.Load(addr)
+                       if exists {
+                               ps = psI.(*PeerState)
+                               go func(peer *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
+                                       peer.PktProcess(buf[:n], tap, true)
+                                       udpBufs <- buf
+                               }(ps.peer, ps.tap, buf, n)
+                               continue
                        }
-                       go func(ps *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
-                               peer.PktProcess(buf[:n], tap, true)
-                               udpBufs <- buf
-                       }(ps.peer, ps.tap, buf, n)
-                       continue
-               CheckHandshake:
-                       hsLock.RLock()
-                       hs, exists = handshakes[addr]
-                       hsLock.RUnlock()
+
+                       hsI, exists = handshakes.Load(addr)
                        if !exists {
-                               goto CheckID
+                               peerID = idsCache.Find(buf[:n])
+                               if peerID == nil {
+                                       govpn.Printf(`[identity-unknown bind="%s" addr="%s"]`, *bindAddr, addr)
+                                       udpBufs <- buf
+                                       continue
+                               }
+                               conf = confs[*peerID]
+                               if conf == nil {
+                                       govpn.Printf(
+                                               `[conf-get-failed bind="%s" peer="%s"]`,
+                                               *bindAddr, peerID.String(),
+                                       )
+                                       udpBufs <- buf
+                                       continue
+                               }
+                               hs := govpn.NewHandshake(
+                                       addr,
+                                       UDPSender{conn: conn, addr: raddr},
+                                       conf,
+                               )
+                               hs.Server(buf[:n])
+                               udpBufs <- buf
+                               handshakes.Store(addr, hs)
+                               continue
                        }
-                       peer = hs.Server(buf[:n])
+
+                       hs = hsI.(*govpn.Handshake)
+                       peer := hs.Server(buf[:n])
                        if peer == nil {
-                               goto Finished
+                               udpBufs <- buf
+                               continue
                        }
-
                        govpn.Printf(
                                `[handshake-completed bind="%s" addr="%s" peer="%s"]`,
-                               *bindAddr, addr, peerId.String(),
+                               *bindAddr, addr, peerID.String(),
                        )
                        hs.Zero()
-                       hsLock.Lock()
-                       delete(handshakes, addr)
-                       hsLock.Unlock()
+                       handshakes.Delete(addr)
 
                        go func() {
                                udpBufs <- make([]byte, govpn.MTUMax)
                                udpBufs <- make([]byte, govpn.MTUMax)
                        }()
-                       peersByIdLock.RLock()
-                       addrPrev, exists = peersById[*peer.Id]
-                       peersByIdLock.RUnlock()
+                       addrPrevI, exists = peersByID.Load(*peer.ID)
+                       if exists {
+                               addrPrev = addrPrevI.(string)
+                               peerPrevI, exists = peers.Load(addrPrev)
+                               if exists {
+                                       peerPrev = peerPrevI.(*PeerState)
+                                       exists = peerPrev == nil
+                               }
+                       }
                        if exists {
-                               peersLock.Lock()
-                               peers[addrPrev].terminator <- struct{}{}
-                               ps = &PeerState{
+                               peerPrev.terminator <- struct{}{}
+                               psNew := &PeerState{
                                        peer:       peer,
-                                       tap:        peers[addrPrev].tap,
+                                       tap:        peerPrev.tap,
                                        terminator: make(chan struct{}),
                                }
-                               go func(ps PeerState) {
-                                       govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
+                               go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
+                                       govpn.PeerTapProcessor(peer, tap, terminator)
                                        <-udpBufs
                                        <-udpBufs
-                               }(*ps)
-                               peersByIdLock.Lock()
-                               kpLock.Lock()
-                               delete(peers, addrPrev)
-                               delete(knownPeers, addrPrev)
-                               peers[addr] = ps
-                               knownPeers[addr] = &peer
-                               peersById[*peer.Id] = addr
-                               peersLock.Unlock()
-                               peersByIdLock.Unlock()
-                               kpLock.Unlock()
+                               }(psNew.peer, psNew.tap, psNew.terminator)
+                               peers.Delete(addrPrev)
+                               peers.Store(addr, psNew)
+                               knownPeers.Delete(addrPrev)
+                               knownPeers.Store(addr, &peer)
+                               peersByID.Store(*peer.ID, addr)
                                govpn.Printf(
                                        `[rehandshake-completed bind="%s" peer="%s"]`,
-                                       *bindAddr, peer.Id.String(),
+                                       *bindAddr, peer.ID.String(),
                                )
                        } else {
                                go func(addr string, peer *govpn.Peer) {
-                                       ifaceName, err := callUp(peer.Id, peer.Addr)
+                                       ifaceName, err := callUp(peer.ID, peer.Addr)
                                        if err != nil {
                                                return
                                        }
@@ -149,57 +172,30 @@ func startUDP() {
                                        if err != nil {
                                                govpn.Printf(
                                                        `[tap-failed bind="%s" peer="%s" err="%s"]`,
-                                                       *bindAddr, peer.Id.String(), err,
+                                                       *bindAddr, peer.ID.String(), err,
                                                )
                                                return
                                        }
-                                       ps = &PeerState{
+                                       psNew := &PeerState{
                                                peer:       peer,
                                                tap:        tap,
                                                terminator: make(chan struct{}),
                                        }
-                                       go func(ps PeerState) {
-                                               govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
+                                       go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
+                                               govpn.PeerTapProcessor(peer, tap, terminator)
                                                <-udpBufs
                                                <-udpBufs
-                                       }(*ps)
-                                       peersLock.Lock()
-                                       peersByIdLock.Lock()
-                                       kpLock.Lock()
-                                       peers[addr] = ps
-                                       knownPeers[addr] = &peer
-                                       peersById[*peer.Id] = addr
-                                       peersLock.Unlock()
-                                       peersByIdLock.Unlock()
-                                       kpLock.Unlock()
-                                       govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peer.Id.String())
+                                       }(psNew.peer, psNew.tap, psNew.terminator)
+                                       peers.Store(addr, psNew)
+                                       knownPeers.Store(addr, &peer)
+                                       peersByID.Store(*peer.ID, addr)
+                                       govpn.Printf(
+                                               `[peer-created bind="%s" peer="%s"]`,
+                                               *bindAddr,
+                                               peer.ID.String(),
+                                       )
                                }(addr, peer)
                        }
-                       goto Finished
-               CheckID:
-                       peerId = idsCache.Find(buf[:n])
-                       if peerId == nil {
-                               govpn.Printf(`[identity-unknown bind="%s" addr="%s"]`, *bindAddr, addr)
-                               goto Finished
-                       }
-                       conf = confs[*peerId]
-                       if conf == nil {
-                               govpn.Printf(
-                                       `[conf-get-failed bind="%s" peer="%s"]`,
-                                       *bindAddr, peerId.String(),
-                               )
-                               goto Finished
-                       }
-                       hs = govpn.NewHandshake(
-                               addr,
-                               UDPSender{conn: conn, addr: raddr},
-                               conf,
-                       )
-                       hs.Server(buf[:n])
-                       hsLock.Lock()
-                       handshakes[addr] = hs
-                       hsLock.Unlock()
-               Finished:
                        udpBufs <- buf
                }
        }()