From: Sergey Matveev Date: Sun, 15 Mar 2015 16:10:07 +0000 (+0300) Subject: Merge branch 'develop' X-Git-Tag: 2.2^0 X-Git-Url: http://www.git.cypherpunks.ru/?a=commitdiff_plain;h=96f3f25cbb28e0c6d3ac777885d8336a815710ce;hp=ee417b7a377f2a099b11c632156bd8322fd21c3d;p=govpn.git Merge branch 'develop' Signed-off-by: Sergey Matveev --- diff --git a/NEWS b/NEWS index b56beac..4500296 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Release 2.2 +----------- +* Fixed several possible channel deadlocks. + Release 2.1 ----------- * Fixed Linux-related building. diff --git a/cmd/govpn-client/main.go b/cmd/govpn-client/main.go index e358d43..f4a29eb 100644 --- a/cmd/govpn-client/main.go +++ b/cmd/govpn-client/main.go @@ -102,7 +102,9 @@ MainCycle: break MainCycle case ethPkt = <-ethSink: if peer == nil { - ethReady <- struct{}{} + if len(ethPkt) > 0 { + ethReady <- struct{}{} + } continue } peer.EthProcess(ethPkt, conn, ethReady) diff --git a/cmd/govpn-server/main.go b/cmd/govpn-server/main.go index f628244..4fa5c96 100644 --- a/cmd/govpn-server/main.go +++ b/cmd/govpn-server/main.go @@ -172,7 +172,7 @@ MainCycle: } }(state) case ethEvent = <-ethSink: - if _, exists := peers[ethEvent.peer.Addr.String()]; !exists { + if s, exists := peers[ethEvent.peer.Addr.String()]; !exists || s.peer != ethEvent.peer { continue } ethEvent.peer.EthProcess(ethEvent.data, conn, ethEvent.ready) diff --git a/common.go b/common.go index b38f52b..b42673c 100644 --- a/common.go +++ b/common.go @@ -23,6 +23,7 @@ import ( "encoding/hex" "io/ioutil" "log" + "os" "os/exec" ) @@ -41,6 +42,9 @@ func ScriptCall(path, ifaceName string) ([]byte, error) { if path == "" { return nil, nil } + if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { + return nil, err + } cmd := exec.Command(path, ifaceName) var out bytes.Buffer cmd.Stdout = &out diff --git a/doc/download.texi b/doc/download.texi index d2ad657..e0ae00d 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -8,8 +8,8 @@ or by downloading prepared tarballs below. @tab @url{download/govpn-1.5.tar.xz, link} @url{download/govpn-1.5.tar.xz.sig, sign} @item 2.0 @tab 31 KiB @tab @url{download/govpn-2.0.tar.xz, link} @url{download/govpn-2.0.tar.xz.sig, sign} -@item 2.1 @tab 32 KiB -@tab @url{download/govpn-2.1.tar.xz, link} @url{download/govpn-2.1.tar.xz.sig, sign} +@item 2.2 @tab 32 KiB +@tab @url{download/govpn-2.2.tar.xz, link} @url{download/govpn-2.2.tar.xz.sig, sign} @end multitable Sourceforge.net also provides mirror for the files above: diff --git a/doc/govpn.texi b/doc/govpn.texi index 9c53ba5..3bdf72f 100644 --- a/doc/govpn.texi +++ b/doc/govpn.texi @@ -17,13 +17,11 @@ GNU General Public License for more details. @end quotation @end copying -@ifnottex @node Top @top GoVPN This manual is for GoVPN -- simple secure free software virtual private network (VPN) daemon, written entirely on Go programming language. -@end ifnottex @menu * Overview:: @@ -202,6 +200,9 @@ transport. MTU for that wlan0 is 1500 bytes. GoVPN will say that maximum MTU for the link is 1476, however it does not take in account TAP's Ethernet frame header length, that in my case is 14 bytes long (1476 - 14). +Do not forget about setting @code{GOMAXPROC} environment variable for +using more than one CPU. + GNU/Linux IPv4 client-server example: @example @@ -216,7 +217,7 @@ server% tunctl -t tap10 server% ip link set mtu 1462 dev tap10 server% ip addr add 172.16.0.1/24 dev tap10 server% ip link set up dev tap10 -server% govpn -bind 192.168.0.1:1194 +server% GOMAXPROC=4 govpn-server -bind 192.168.0.1:1194 @end example @example @@ -228,8 +229,9 @@ client% ip link set mtu 1462 dev tap10 client% ip addr add 172.16.0.2/24 dev tap10 client% ip link set up dev tap10 client% ip route add default via 172.16.0.1 +client% export GOMAXPROC=4 client% while :; do - govpn -key key.txt -id CLIENTID -iface tap10 -remote 192.168.0.1:1194 + govpn-client -key key.txt -id CLIENTID -iface tap10 -remote 192.168.0.1:1194 done @end example @@ -248,7 +250,7 @@ echo $tap EOF server% chmod 500 peers/CLIENTID/up.sh server% ifconfig em0 inet6 fe80::1/64 -server% govpn -bind fe80::1%em0 +server% GOMAXPROC=4 govpn-server -bind fe80::1%em0 @end example @example @@ -256,8 +258,9 @@ client% ifconfig me0 inet6 -ifdisabled auto_linklocal client% ifconfig tap10 client% ifconfig tap10 inet6 fc00::2/96 mtu 1462 up client% route -6 add default fc00::1 +client% export GOMAXPROC=4 client% while :; do - govpn -key key.txt -id CLIENTID -iface tap10 -remote [fe80::1%me0]:1194 + govpn-client -key key.txt -id CLIENTID -iface tap10 -remote [fe80::1%me0]:1194 done @end example diff --git a/makefile b/makefile index b1e4229..59f148e 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ .PHONY: govpn-client govpn-server -VERSION=2.0 +VERSION=2.2 LDFLAGS=-X govpn.Version $(VERSION) all: govpn-client govpn-server diff --git a/tap.go b/tap.go index 85926d7..4fee83a 100644 --- a/tap.go +++ b/tap.go @@ -26,11 +26,12 @@ import ( ) type TAP struct { - Name string - dev io.ReadWriter - buf []byte - sink chan []byte - ready chan struct{} + Name string + dev io.ReadWriter + buf []byte + sink chan []byte + ready chan struct{} + synced bool } func NewTAP(ifaceName string) (*TAP, error) { @@ -40,11 +41,12 @@ func NewTAP(ifaceName string) (*TAP, error) { return nil, err } tap := TAP{ - Name: ifaceName, - dev: tapRaw, - buf: make([]byte, maxIfacePktSize), - sink: make(chan []byte), - ready: make(chan struct{}), + Name: ifaceName, + dev: tapRaw, + buf: make([]byte, maxIfacePktSize), + sink: make(chan []byte), + ready: make(chan struct{}), + synced: false, } go func() { var n int diff --git a/transport.go b/transport.go index 3c460e6..d72fcc1 100644 --- a/transport.go +++ b/transport.go @@ -102,6 +102,7 @@ func TAPListen(ifaceName string) (*TAP, chan []byte, chan struct{}, chan struct{ sink := make(chan []byte) sinkReady := make(chan struct{}) sinkTerminate := make(chan struct{}) + sinkSkip := make(chan struct{}) go func() { heartbeat := time.Tick(heartbeatPeriodGet()) @@ -112,29 +113,34 @@ func TAPListen(ifaceName string) (*TAP, chan []byte, chan struct{}, chan struct{ case <-sinkTerminate: break ListenCycle case <-heartbeat: - sink <- make([]byte, 0) + go func() { sink <- make([]byte, 0) }() continue + case <-sinkSkip: case <-sinkReady: - if exists { - exists = false - break - } tap.ready <- struct{}{} + tap.synced = true } HeartbeatCatched: select { case <-heartbeat: - sink <- make([]byte, 0) + go func() { sink <- make([]byte, 0) }() goto HeartbeatCatched case <-sinkTerminate: break ListenCycle case pkt = <-tap.sink: + tap.synced = false sink <- pkt } } close(sink) + close(sinkReady) + close(sinkTerminate) }() - sinkReady <- struct{}{} + if exists && tap.synced { + sinkSkip <- struct{}{} + } else { + sinkReady <- struct{}{} + } return tap, sink, sinkReady, sinkTerminate, nil }