A new user interface for you! Read more...

File govpn-go-1.7-compat.patch of Package govpn

--- a/src/cypherpunks.ru/govpn/client/client.go
+++ b/src/cypherpunks.ru/govpn/client/client.go
@@ -23,7 +23,6 @@ import (
 	"fmt"
 	"net"
 	"os"
-	"sync"
 	"time"
 
 	"github.com/agl/ed25519"
@@ -73,7 +72,7 @@ func (c *Configuration) isProxy() bool {
 type Client struct {
 	idsCache      *govpn.MACCache
 	tap           *govpn.TAP
-	knownPeers    sync.Map
+	knownPeers    govpn.KnownPeers
 	statsPort     net.Listener
 	timeouted     chan struct{}
 	rehandshaking chan struct{}
@@ -100,6 +99,7 @@ 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)
 	}
 
--- 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.Store(c.config.RemoteAddress, &peer)
+		c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
 		if c.firstUpCall {
 			go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress)
 			c.firstUpCall = false
--- 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.Store(c.config.RemoteAddress, &peer)
+		c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
 		if c.firstUpCall {
 			go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress)
 			c.firstUpCall = false
--- a/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go
+++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go
@@ -32,10 +32,17 @@ type PeerState struct {
 }
 
 var (
-	handshakes sync.Map
-	peers      sync.Map
-	peersByID  sync.Map
-	knownPeers sync.Map
+	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
 )
 
 func callUp(peerID *govpn.PeerID, remoteAddr string) (string, error) {
--- a/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go
+++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go
@@ -58,6 +58,7 @@ func main() {
 	log.Println(govpn.VersionGet())
 
 	confInit()
+	knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer))
 
 	if *egdPath != "" {
 		log.Println("Using", *egdPath, "EGD")
@@ -105,33 +106,28 @@ MainCycle:
 		select {
 		case <-termSignal:
 			govpn.BothPrintf(`[terminating bind="%s"]`, *bindAddr)
-			peers.Range(func(_, psI interface{}) bool {
-				ps := psI.(*PeerState)
+			for _, ps := range peers {
 				govpn.ScriptCall(
 					confs[*ps.peer.ID].Down,
 					ps.tap.Name,
 					ps.peer.Addr,
 				)
-				return true
-			})
+			}
 			break MainCycle
 		case <-hsHeartbeat:
 			now := time.Now()
-
-			handshakes.Range(func(addrI, hsI interface{}) bool {
-				addr := addrI.(string)
-				hs := hsI.(*govpn.Handshake)
+			hsLock.Lock()
+			for addr, hs := range handshakes {
 				if hs.LastPing.Add(timeout).Before(now) {
 					govpn.Printf(`[handshake-delete bind="%s" addr="%s"]`, *bindAddr, addr)
 					hs.Zero()
-					handshakes.Delete(addr)
+					delete(handshakes, addr)
 				}
-				return true
-			})
-
-			peers.Range(func(addrI, psI interface{}) bool {
-				addr := addrI.(string)
-				ps := psI.(*PeerState)
+			}
+			peersLock.Lock()
+			peersByIDLock.Lock()
+			kpLock.Lock()
+			for addr, ps := range peers {
 				ps.peer.BusyR.Lock()
 				needsDeletion = ps.peer.LastPing.Add(timeout).Before(now)
 				ps.peer.BusyR.Unlock()
@@ -141,9 +137,9 @@ MainCycle:
 						*bindAddr,
 						ps.peer.ID.String(),
 					)
-					peers.Delete(addr)
-					knownPeers.Delete(addr)
-					peersByID.Delete(*ps.peer.ID)
+					delete(peers, addr)
+					delete(knownPeers, addr)
+					delete(peersByID, *ps.peer.ID)
 					go govpn.ScriptCall(
 						confs[*ps.peer.ID].Down,
 						ps.tap.Name,
@@ -151,8 +147,11 @@ MainCycle:
 					)
 					ps.terminator <- struct{}{}
 				}
-				return true
-			})
+			}
+			hsLock.Unlock()
+			peersLock.Unlock()
+			peersByIDLock.Unlock()
+			kpLock.Unlock()
 		}
 	}
 }
--- a/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go
+++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go
@@ -60,9 +60,6 @@ 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
@@ -99,13 +96,16 @@ func handleTCP(conn net.Conn) {
 			`[handshake-completed bind="%s" addr="%s" peer="%s"]`,
 			*bindAddr, addr, peerID.String(),
 		)
-		addrPrevI, exists := peersByID.Load(*peer.ID)
+		peersByIDLock.RLock()
+		addrPrev, exists := peersByID[*peer.ID]
+		peersByIDLock.RUnlock()
+		var peerPrev *PeerState
 		if exists {
-			addrPrev = addrPrevI.(string)
-			peerPrevI, exists = peers.Load(addrPrev)
-			if exists {
-				peerPrev = peerPrevI.(*PeerState)
-				exists = peerPrev == nil
+			peersLock.Lock()
+			peerPrev = peers[addrPrev]
+			if peerPrev == nil {
+				exists = false
+				peersLock.Unlock()
 			}
 		}
 		if exists {
@@ -117,11 +117,16 @@ func handleTCP(conn net.Conn) {
 				terminator: make(chan struct{}),
 			}
 			go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
-			peers.Delete(addrPrev)
-			peers.Store(addr, ps)
-			knownPeers.Delete(addrPrev)
-			knownPeers.Store(addr, &peer)
-			peersByID.Store(*peer.ID, addr)
+			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()
 			govpn.Printf(
 				`[rehandshake-completed bind="%s" peer="%s"]`,
 				*bindAddr, peerID.String(),
@@ -147,9 +152,15 @@ func handleTCP(conn net.Conn) {
 				terminator: make(chan struct{}, 1),
 			}
 			go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
-			peers.Store(addr, ps)
-			peersByID.Store(*peer.ID, addr)
-			knownPeers.Store(addr, &peer)
+			peersLock.Lock()
+			peersByIDLock.Lock()
+			kpLock.Lock()
+			peers[addr] = ps
+			peersByID[*peer.ID] = addr
+			knownPeers[addr] = &peer
+			peersLock.Unlock()
+			peersByIDLock.Unlock()
+			kpLock.Unlock()
 			govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peerID.String())
 		}
 		break
--- a/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go
+++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go
@@ -57,15 +57,10 @@ 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 peerPrevI interface{}
-		var peerPrev *PeerState
+		var exists bool
 		var peerID *govpn.PeerID
 		var conf *govpn.PeerConf
 		for {
@@ -77,9 +72,10 @@ func startUDP() {
 			}
 			addr = raddr.String()
 
-			psI, exists = peers.Load(addr)
+			peersLock.RLock()
+			ps, exists = peers[addr]
+			peersLock.RUnlock()
 			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
@@ -87,7 +83,9 @@ func startUDP() {
 				continue
 			}
 
-			hsI, exists = handshakes.Load(addr)
+			hsLock.RLock()
+			hs, exists = handshakes[addr]
+			hsLock.RUnlock()
 			if !exists {
 				peerID = idsCache.Find(buf[:n])
 				if peerID == nil {
@@ -111,11 +109,12 @@ func startUDP() {
 				)
 				hs.Server(buf[:n])
 				udpBufs <- buf
-				handshakes.Store(addr, hs)
+				hsLock.Lock()
+				handshakes[addr] = hs
+				hsLock.Unlock()
 				continue
 			}
 
-			hs = hsI.(*govpn.Handshake)
 			peer := hs.Server(buf[:n])
 			if peer == nil {
 				udpBufs <- buf
@@ -126,19 +125,24 @@ func startUDP() {
 				*bindAddr, addr, peerID.String(),
 			)
 			hs.Zero()
-			handshakes.Delete(addr)
+			hsLock.Lock()
+			delete(handshakes, addr)
+			hsLock.Unlock()
 
 			go func() {
 				udpBufs <- make([]byte, govpn.MTUMax)
 				udpBufs <- make([]byte, govpn.MTUMax)
 			}()
-			addrPrevI, exists = peersByID.Load(*peer.ID)
+			peersByIDLock.RLock()
+			addrPrev, exists = peersByID[*peer.ID]
+			peersByIDLock.RUnlock()
+			var peerPrev *PeerState
 			if exists {
-				addrPrev = addrPrevI.(string)
-				peerPrevI, exists = peers.Load(addrPrev)
-				if exists {
-					peerPrev = peerPrevI.(*PeerState)
-					exists = peerPrev == nil
+				peersLock.Lock()
+				peerPrev = peers[addrPrev]
+				if peerPrev == nil {
+					exists = false
+					peersLock.Unlock()
 				}
 			}
 			if exists {
@@ -153,11 +157,16 @@ func startUDP() {
 					<-udpBufs
 					<-udpBufs
 				}(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)
+				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()
 				govpn.Printf(
 					`[rehandshake-completed bind="%s" peer="%s"]`,
 					*bindAddr, peer.ID.String(),
@@ -186,9 +195,15 @@ func startUDP() {
 						<-udpBufs
 						<-udpBufs
 					}(psNew.peer, psNew.tap, psNew.terminator)
-					peers.Store(addr, psNew)
-					knownPeers.Store(addr, &peer)
-					peersByID.Store(*peer.ID, addr)
+					peersLock.Lock()
+					peersByIDLock.Lock()
+					kpLock.Lock()
+					peers[addr] = psNew
+					knownPeers[addr] = &peer
+					peersByID[*peer.ID] = addr
+					peersLock.Unlock()
+					peersByIDLock.Unlock()
+					kpLock.Unlock()
 					govpn.Printf(
 						`[peer-created bind="%s" peer="%s"]`,
 						*bindAddr,
--- a/src/cypherpunks.ru/govpn/stats.go
+++ b/src/cypherpunks.ru/govpn/stats.go
@@ -22,7 +22,6 @@ import (
 	"encoding/json"
 	"log"
 	"net"
-	"sync"
 	"time"
 )
 
@@ -30,13 +29,15 @@ 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 *sync.Map) {
+func StatsProcessor(statsPort net.Listener, peers *KnownPeers) {
 	var conn net.Conn
 	var err error
 	var data []byte
@@ -51,10 +52,9 @@ func StatsProcessor(statsPort net.Listen
 		conn.Read(buf)
 		conn.Write([]byte("HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n"))
 		var peersList []*Peer
-		peers.Range(func(_, peerI interface{}) bool {
-			peersList = append(peersList, *peerI.(**Peer))
-			return true
-		})
+		for _, peer := range *peers {
+			peersList = append(peersList, *peer)
+		}
 		data, err = json.Marshal(peersList)
 		if err != nil {
 			panic(err)