package tun import ( wgtun "golang.zx2c4.com/wireguard/tun" "io" "log" "mpbl3p/proxy" "os" ) type SourceSink struct { tun wgtun.Device } func NewTun(name string, mtu int) (t wgtun.Device, err error) { return wgtun.CreateTUN(name, mtu) } func NewFromFile(fd uintptr, mtu int) (ss *SourceSink, err error) { ss = new(SourceSink) file := os.NewFile(fd, "") ss.tun, err = wgtun.CreateTUNFromFile(file, mtu) if err != nil { return } return } func (t *SourceSink) Close() error { return t.tun.Close() } func (t *SourceSink) Source() (proxy.Packet, error) { mtu, err := t.tun.MTU() if err != nil { return nil, err } buf := make([]byte, mtu+4) read, err := t.tun.Read(buf, 4) if err != nil { return nil, err } if read == 0 { return nil, io.EOF } return proxy.SimplePacket(buf[4 : read+4]), nil } var good, bad float64 func (t *SourceSink) Sink(packet proxy.Packet) error { // make space for tun header content := make([]byte, len(packet.Contents())+4) copy(content[4:], packet.Contents()) _, err := t.tun.Write(content, 4) 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 }