97 lines
1.4 KiB
Go
97 lines
1.4 KiB
Go
package tun
|
|
|
|
import (
|
|
"github.com/JakeHillion/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
|
|
}
|