dissertation-2-code/tun/tun.go
Jake Hillion 179025ad2b
All checks were successful
continuous-integration/drone/push Build is passing
refactored timestamping
2020-11-28 17:15:56 +00:00

97 lines
1.4 KiB
Go

package tun
import (
"github.com/pkg/taptun"
"io"
"log"
"mpbl3p/proxy"
"net"
"os"
"strings"
"sync"
"time"
)
type SourceSink struct {
tun *taptun.Tun
bufferSize int
up bool
upMu sync.Mutex
}
func NewTun(namingScheme string, bufferSize int) (ss *SourceSink, err error) {
ss = &SourceSink{}
ss.tun, err = taptun.NewTun(namingScheme)
if err != nil {
return
}
ss.bufferSize = bufferSize
ss.upMu.Lock()
go func() {
defer ss.upMu.Unlock()
for {
iface, err := net.InterfaceByName(ss.tun.String())
if err != nil {
panic(err)
}
if strings.Contains(iface.Flags.String(), "up") {
log.Println("tun is up")
ss.up = true
return
}
time.Sleep(100 * time.Millisecond)
}
}()
return
}
func (t *SourceSink) Source() (proxy.Packet, error) {
if !t.up {
t.upMu.Lock()
t.upMu.Unlock()
}
buf := make([]byte, t.bufferSize)
read, err := t.tun.Read(buf)
if err != nil {
return nil, err
}
if read == 0 {
return nil, io.EOF
}
return proxy.SimplePacket(buf[:read]), nil
}
var good, bad float64
func (t *SourceSink) Sink(packet proxy.Packet) error {
if !t.up {
t.upMu.Lock()
t.upMu.Unlock()
}
_, err := t.tun.Write(packet.Contents())
if err != nil {
switch err.(type) {
case *os.PathError:
bad += 1
log.Printf("packet loss: %f%%\n", bad*100/(good+bad))
return nil
default:
return err
}
}
good += 1
return nil
}