From c982ccb214ba8d0fd8a30dee7439ea2db1559f6f Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 26 Aug 2017 16:23:45 +0300 Subject: [PATCH] Use convenient simpler Go 1.9's sync.Map --- VERSION | 2 +- doc/installation.texi | 16 ++--- doc/news.ru.texi | 7 ++ doc/news.texi | 7 ++ ports/govpn/Makefile | 2 +- src/cypherpunks.ru/govpn/client/client.go | 4 +- src/cypherpunks.ru/govpn/client/tcp.go | 2 +- src/cypherpunks.ru/govpn/client/udp.go | 2 +- .../govpn/cmd/govpn-server/common.go | 15 ++--- .../govpn/cmd/govpn-server/main.go | 39 +++++------ .../govpn/cmd/govpn-server/tcp.go | 45 +++++-------- .../govpn/cmd/govpn-server/udp.go | 67 +++++++------------ src/cypherpunks.ru/govpn/stats.go | 12 ++-- 13 files changed, 101 insertions(+), 119 deletions(-) diff --git a/VERSION b/VERSION index f994162..37722eb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.3 +7.4 diff --git a/doc/installation.texi b/doc/installation.texi index 9abc822..1f8a74c 100644 --- a/doc/installation.texi +++ b/doc/installation.texi @@ -11,14 +11,14 @@ Possibly GoVPN already exists in your distribution: @end itemize GoVPN is written on @url{https://golang.org/, Go} programming language -and you have to install Go compiler (1.5+ version is highly recommended, -1.4 is the minimal sufficient): @code{lang/go} port in FreeBSD and -@code{golang} package in most GNU/Linux distributions. @emph{Make} (BSD -and GNU ones are fine) is recommended for convenient building. -@url{https://www.gnu.org/software/texinfo/, Texinfo} (6.1+ version is -recommended) is used for building documentation. Possibly you also need -to install TUN/TAP interface utilities (depending on your operating -system): @command{uml-utilities} package in most GNU/Linux distributions. +and you have to install Go compiler 1.9+ version: @code{lang/go} port in +FreeBSD and @code{golang} package in most GNU/Linux distributions. +@emph{Make} (BSD and GNU ones are fine) is recommended for convenient +building. @url{https://www.gnu.org/software/texinfo/, Texinfo} (6.1+ +version is recommended) is used for building documentation. Possibly you +also need to install TUN/TAP interface utilities (depending on your +operating system): @command{uml-utilities} package in most GNU/Linux +distributions. Get @ref{Tarballs, the tarball}, check its @ref{Integrity, integrity and authenticity} and run @command{make}. diff --git a/doc/news.ru.texi b/doc/news.ru.texi index f00c3b1..08aa4c7 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -1,6 +1,13 @@ @node Новости @section Новости +@node Релиз 7.4 +@subsection Релиз 7.4 +@itemize +@item Маленький рефакторинг. Минимальная необходимая версия Go 1.9. +@item Обновлены зависимые криптографические библиотеки. +@end itemize + @node Релиз 7.3 @subsection Релиз 7.3 @itemize diff --git a/doc/news.texi b/doc/news.texi index cb119e2..03d61ef 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,6 +3,13 @@ See also this page @ref{Новости, on russian}. +@node Release 7.4 +@section Release 7.4 +@itemize +@item Tiny refactoring. Go 1.9 is minimal required version. +@item Dependant cryptographic libraries are updated. +@end itemize + @node Release 7.3 @section Release 7.3 @itemize diff --git a/ports/govpn/Makefile b/ports/govpn/Makefile index 20b78e2..8e7a2eb 100644 --- a/ports/govpn/Makefile +++ b/ports/govpn/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PORTNAME= govpn -PORTVERSION= 7.3 +PORTVERSION= 7.4 CATEGORIES= security MASTER_SITES= http://www.govpn.info/download/ diff --git a/src/cypherpunks.ru/govpn/client/client.go b/src/cypherpunks.ru/govpn/client/client.go index 8102cc6..3014bdf 100644 --- a/src/cypherpunks.ru/govpn/client/client.go +++ b/src/cypherpunks.ru/govpn/client/client.go @@ -23,6 +23,7 @@ import ( "fmt" "net" "os" + "sync" "time" "github.com/agl/ed25519" @@ -72,7 +73,7 @@ func (c *Configuration) isProxy() bool { type Client struct { idsCache *govpn.MACCache tap *govpn.TAP - knownPeers govpn.KnownPeers + knownPeers sync.Map statsPort net.Listener timeouted chan struct{} rehandshaking chan struct{} @@ -99,7 +100,6 @@ func (c *Client) MainCycle() { c.Error <- fmt.Errorf("Can't listen on stats port: %s", err.Error()) return } - c.knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer)) go govpn.StatsProcessor(c.statsPort, &c.knownPeers) } diff --git a/src/cypherpunks.ru/govpn/client/tcp.go b/src/cypherpunks.ru/govpn/client/tcp.go index 40d81ca..4bb7a5f 100644 --- a/src/cypherpunks.ru/govpn/client/tcp.go +++ b/src/cypherpunks.ru/govpn/client/tcp.go @@ -86,7 +86,7 @@ HandshakeCycle: continue } govpn.Printf(`[handshake-completed remote="%s"]`, c.config.RemoteAddress) - c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer}) + c.knownPeers.Store(c.config.RemoteAddress, &peer) if c.firstUpCall { go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress) c.firstUpCall = false diff --git a/src/cypherpunks.ru/govpn/client/udp.go b/src/cypherpunks.ru/govpn/client/udp.go index bb7045a..bb29dcc 100644 --- a/src/cypherpunks.ru/govpn/client/udp.go +++ b/src/cypherpunks.ru/govpn/client/udp.go @@ -93,7 +93,7 @@ MainCycle: continue } govpn.Printf(`[handshake-completed remote="%s"]`, c.config.RemoteAddress) - c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer}) + c.knownPeers.Store(c.config.RemoteAddress, &peer) if c.firstUpCall { go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress) c.firstUpCall = false diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go index f18d34b..e0e8e03 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go @@ -32,17 +32,10 @@ type PeerState struct { } var ( - handshakes map[string]*govpn.Handshake = make(map[string]*govpn.Handshake) - hsLock sync.RWMutex - - peers = make(map[string]*PeerState) - peersLock sync.RWMutex - - peersByID = make(map[govpn.PeerID]string) - peersByIDLock sync.RWMutex - - knownPeers govpn.KnownPeers - kpLock sync.RWMutex + handshakes sync.Map + peers sync.Map + peersByID sync.Map + knownPeers sync.Map ) func callUp(peerID *govpn.PeerID, remoteAddr string) (string, error) { diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go index 3e80975..0dfd8ab 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go @@ -58,7 +58,6 @@ func main() { log.Println(govpn.VersionGet()) confInit() - knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer)) if *egdPath != "" { log.Println("Using", *egdPath, "EGD") @@ -106,28 +105,33 @@ MainCycle: select { case <-termSignal: govpn.BothPrintf(`[terminating bind="%s"]`, *bindAddr) - for _, ps := range peers { + peers.Range(func(_, psI interface{}) bool { + ps := psI.(*PeerState) govpn.ScriptCall( confs[*ps.peer.ID].Down, ps.tap.Name, ps.peer.Addr, ) - } + return true + }) break MainCycle case <-hsHeartbeat: now := time.Now() - hsLock.Lock() - for addr, hs := range handshakes { + + handshakes.Range(func(addrI, hsI interface{}) bool { + addr := addrI.(string) + hs := hsI.(*govpn.Handshake) if hs.LastPing.Add(timeout).Before(now) { govpn.Printf(`[handshake-delete bind="%s" addr="%s"]`, *bindAddr, addr) hs.Zero() - delete(handshakes, addr) + handshakes.Delete(addr) } - } - peersLock.Lock() - peersByIDLock.Lock() - kpLock.Lock() - for addr, ps := range peers { + return true + }) + + peers.Range(func(addrI, psI interface{}) bool { + addr := addrI.(string) + ps := psI.(*PeerState) ps.peer.BusyR.Lock() needsDeletion = ps.peer.LastPing.Add(timeout).Before(now) ps.peer.BusyR.Unlock() @@ -137,9 +141,9 @@ MainCycle: *bindAddr, ps.peer.ID.String(), ) - delete(peers, addr) - delete(knownPeers, addr) - delete(peersByID, *ps.peer.ID) + peers.Delete(addr) + knownPeers.Delete(addr) + peersByID.Delete(*ps.peer.ID) go govpn.ScriptCall( confs[*ps.peer.ID].Down, ps.tap.Name, @@ -147,11 +151,8 @@ MainCycle: ) ps.terminator <- struct{}{} } - } - hsLock.Unlock() - peersLock.Unlock() - peersByIDLock.Unlock() - kpLock.Unlock() + return true + }) } } } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go index 61eb1e0..aab59b7 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go @@ -60,6 +60,9 @@ func handleTCP(conn net.Conn) { var peer *govpn.Peer var tap *govpn.TAP var conf *govpn.PeerConf + var addrPrev string + var peerPrevI interface{} + var peerPrev *PeerState for { if prev == len(buf) { break @@ -96,16 +99,13 @@ func handleTCP(conn net.Conn) { `[handshake-completed bind="%s" addr="%s" peer="%s"]`, *bindAddr, addr, peerID.String(), ) - peersByIDLock.RLock() - addrPrev, exists := peersByID[*peer.ID] - peersByIDLock.RUnlock() - var peerPrev *PeerState + addrPrevI, exists := peersByID.Load(*peer.ID) if exists { - peersLock.Lock() - peerPrev = peers[addrPrev] - if peerPrev == nil { - exists = false - peersLock.Unlock() + addrPrev = addrPrevI.(string) + peerPrevI, exists = peers.Load(addrPrev) + if exists { + peerPrev = peerPrevI.(*PeerState) + exists = peerPrev == nil } } if exists { @@ -117,16 +117,11 @@ func handleTCP(conn net.Conn) { terminator: make(chan struct{}), } go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator) - 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() + peers.Delete(addrPrev) + peers.Store(addr, ps) + knownPeers.Delete(addrPrev) + knownPeers.Store(addr, &peer) + peersByID.Store(*peer.ID, addr) govpn.Printf( `[rehandshake-completed bind="%s" peer="%s"]`, *bindAddr, peerID.String(), @@ -152,15 +147,9 @@ func handleTCP(conn net.Conn) { terminator: make(chan struct{}, 1), } go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator) - peersLock.Lock() - peersByIDLock.Lock() - kpLock.Lock() - peers[addr] = ps - peersByID[*peer.ID] = addr - knownPeers[addr] = &peer - peersLock.Unlock() - peersByIDLock.Unlock() - kpLock.Unlock() + peers.Store(addr, ps) + peersByID.Store(*peer.ID, addr) + knownPeers.Store(addr, &peer) govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peerID.String()) } break diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go index 0373517..f074df4 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go @@ -57,10 +57,15 @@ 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 peerPrevI interface{} + var peerPrev *PeerState var peerID *govpn.PeerID var conf *govpn.PeerConf for { @@ -72,10 +77,9 @@ func startUDP() { } addr = raddr.String() - peersLock.RLock() - ps, exists = peers[addr] - peersLock.RUnlock() + 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 @@ -83,9 +87,7 @@ func startUDP() { continue } - hsLock.RLock() - hs, exists = handshakes[addr] - hsLock.RUnlock() + hsI, exists = handshakes.Load(addr) if !exists { peerID = idsCache.Find(buf[:n]) if peerID == nil { @@ -109,12 +111,11 @@ func startUDP() { ) hs.Server(buf[:n]) udpBufs <- buf - hsLock.Lock() - handshakes[addr] = hs - hsLock.Unlock() + handshakes.Store(addr, hs) continue } + hs = hsI.(*govpn.Handshake) peer := hs.Server(buf[:n]) if peer == nil { udpBufs <- buf @@ -125,24 +126,19 @@ func startUDP() { *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() - var peerPrev *PeerState + addrPrevI, exists = peersByID.Load(*peer.ID) if exists { - peersLock.Lock() - peerPrev = peers[addrPrev] - if peerPrev == nil { - exists = false - peersLock.Unlock() + addrPrev = addrPrevI.(string) + peerPrevI, exists = peers.Load(addrPrev) + if exists { + peerPrev = peerPrevI.(*PeerState) + exists = peerPrev == nil } } if exists { @@ -157,16 +153,11 @@ func startUDP() { <-udpBufs <-udpBufs }(psNew.peer, psNew.tap, psNew.terminator) - peersByIDLock.Lock() - kpLock.Lock() - delete(peers, addrPrev) - delete(knownPeers, addrPrev) - peers[addr] = psNew - knownPeers[addr] = &peer - peersByID[*peer.ID] = addr - peersLock.Unlock() - peersByIDLock.Unlock() - kpLock.Unlock() + 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(), @@ -195,15 +186,9 @@ func startUDP() { <-udpBufs <-udpBufs }(psNew.peer, psNew.tap, psNew.terminator) - peersLock.Lock() - peersByIDLock.Lock() - kpLock.Lock() - peers[addr] = psNew - knownPeers[addr] = &peer - peersByID[*peer.ID] = addr - peersLock.Unlock() - peersByIDLock.Unlock() - kpLock.Unlock() + peers.Store(addr, psNew) + knownPeers.Store(addr, &peer) + peersByID.Store(*peer.ID, addr) govpn.Printf( `[peer-created bind="%s" peer="%s"]`, *bindAddr, diff --git a/src/cypherpunks.ru/govpn/stats.go b/src/cypherpunks.ru/govpn/stats.go index c8ea622..8354d39 100644 --- a/src/cypherpunks.ru/govpn/stats.go +++ b/src/cypherpunks.ru/govpn/stats.go @@ -22,6 +22,7 @@ import ( "encoding/json" "log" "net" + "sync" "time" ) @@ -29,15 +30,13 @@ const ( RWTimeout = 10 * time.Second ) -type KnownPeers map[string]**Peer - // StatsProcessor is assumed to be run in background. It accepts // connection on statsPort, reads anything one send to them and show // information about known peers in serialized JSON format. peers // argument is a reference to the map with references to the peers as // values. Map is used here because of ease of adding and removing // elements in it. -func StatsProcessor(statsPort net.Listener, peers *KnownPeers) { +func StatsProcessor(statsPort net.Listener, peers *sync.Map) { var conn net.Conn var err error var data []byte @@ -52,9 +51,10 @@ func StatsProcessor(statsPort net.Listener, peers *KnownPeers) { conn.Read(buf) conn.Write([]byte("HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n")) var peersList []*Peer - for _, peer := range *peers { - peersList = append(peersList, *peer) - } + peers.Range(func(_, peerI interface{}) bool { + peersList = append(peersList, *peerI.(**Peer)) + return true + }) data, err = json.Marshal(peersList) if err != nil { panic(err) -- 2.44.0