Try using separate workers for each TUN/TAP connection (sometimes produces duplicate packets when communicating with both the node address and a subnet address, sometimes also can't Ctrl-C to quit)

This commit is contained in:
Neil Alexander 2019-04-28 17:14:09 +01:00
parent 6469e39ff1
commit 5f66c4c95c
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
3 changed files with 376 additions and 474 deletions

75
src/tuntap/conn.go Normal file
View file

@ -0,0 +1,75 @@
package tuntap
import (
"errors"
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
)
type tunConn struct {
tun *TunAdapter
conn *yggdrasil.Conn
send chan []byte
stop chan interface{}
}
func (s *tunConn) close() {
close(s.stop)
}
func (s *tunConn) reader() error {
select {
case _, ok := <-s.stop:
if !ok {
return errors.New("session was already closed")
}
default:
}
var n int
var err error
read := make(chan bool)
b := make([]byte, 65535)
for {
go func() {
if n, err = s.conn.Read(b); err != nil {
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn read error:", err)
return
}
read <- true
}()
select {
case <-read:
if n > 0 {
s.tun.send <- b[:n]
}
case <-s.stop:
s.tun.log.Debugln("Stopping conn reader for", s)
return nil
}
}
}
func (s *tunConn) writer() error {
select {
case _, ok := <-s.stop:
if !ok {
return errors.New("session was already closed")
}
default:
}
for {
select {
case <-s.stop:
s.tun.log.Debugln("Stopping conn writer for", s)
return nil
case b, ok := <-s.send:
if !ok {
return errors.New("send closed")
}
if _, err := s.conn.Write(b); err != nil {
s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn write error:", err)
continue
}
}
}
}