]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
Add rwcancelation to darwin
authorJason A. Donenfeld <Jason@zx2c4.com>
Mon, 14 May 2018 01:55:46 +0000 (03:55 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Mon, 14 May 2018 02:02:59 +0000 (04:02 +0200)
rwcancel/rwcancel_unix.go
rwcancel/select_darwin.go [new file with mode: 0644]
rwcancel/select_linux.go [new file with mode: 0644]
tun_darwin.go

index cd3661fd8aa00b5296768060a4fc034b893b78a7..7f2c9e04d5bb411dc0c420ada964b0108300e58a 100644 (file)
@@ -77,7 +77,7 @@ func (rw *RWCancel) ReadyRead() bool {
        fdset := fdSet{}
        fdset.set(rw.fd)
        fdset.set(closeFd)
-       _, err := unix.Select(max(rw.fd, closeFd)+1, &fdset.fdset, nil, nil, nil)
+       err := unixSelect(max(rw.fd, closeFd)+1, &fdset.fdset, nil, nil, nil)
        if err != nil {
                return false
        }
@@ -92,7 +92,7 @@ func (rw *RWCancel) ReadyWrite() bool {
        fdset := fdSet{}
        fdset.set(rw.fd)
        fdset.set(closeFd)
-       _, err := unix.Select(max(rw.fd, closeFd)+1, nil, &fdset.fdset, nil, nil)
+       err := unixSelect(max(rw.fd, closeFd)+1, nil, &fdset.fdset, nil, nil)
        if err != nil {
                return false
        }
diff --git a/rwcancel/select_darwin.go b/rwcancel/select_darwin.go
new file mode 100644 (file)
index 0000000..d14edc8
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+package rwcancel
+
+import "golang.org/x/sys/unix"
+
+func unixSelect(nfd int, r *unix.FdSet, w *unix.FdSet, e *unix.FdSet, timeout *unix.Timeval) error {
+       return unix.Select(nfd, r, w, e, timeout)
+}
diff --git a/rwcancel/select_linux.go b/rwcancel/select_linux.go
new file mode 100644 (file)
index 0000000..c3d4e27
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+package rwcancel
+
+import "golang.org/x/sys/unix"
+
+func unixSelect(nfd int, r *unix.FdSet, w *unix.FdSet, e *unix.FdSet, timeout *unix.Timeval) (err error) {
+       _, err = unix.Select(nfd, r, w, e, timeout)
+       return
+}
index fa8efe0f762ac9f39e157ee45e12c6f0c3a91581..1ce039d8229f4addf1d682c8619c7a6a9eb31655 100644 (file)
@@ -6,7 +6,9 @@
 package main
 
 import (
+       "./rwcancel"
        "encoding/binary"
+       "errors"
        "fmt"
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
@@ -34,9 +36,10 @@ type sockaddrCtl struct {
 // NativeTun is a hack to work around the first 4 bytes "packet
 // information" because there doesn't seem to be an IFF_NO_PI for darwin.
 type NativeTun struct {
-       name string
-       fd   *os.File
-       mtu  int
+       name     string
+       fd       *os.File
+       rwcancel *rwcancel.RWCancel
+       mtu      int
 
        events chan TUNEvent
        errors chan error
@@ -121,6 +124,17 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
                return nil, err
        }
 
+       // set default MTU
+       err = tun.setMTU(DefaultMTU)
+       if err != nil {
+               return nil, err
+       }
+
+       tun.rwcancel, err = rwcancel.NewRWCancel(int(file.Fd()))
+       if err != nil {
+               return nil, err
+       }
+
        // TODO: Fix this very naive implementation
        go func(tun *NativeTun) {
                var (
@@ -153,10 +167,7 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
                }
        }(tun)
 
-       // set default MTU
-       err = tun.setMTU(DefaultMTU)
-
-       return tun, err
+       return tun, nil
 }
 
 func (tun *NativeTun) Name() (string, error) {
@@ -190,14 +201,30 @@ func (tun *NativeTun) Events() chan TUNEvent {
        return tun.events
 }
 
-func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
-
-       buff = buff[offset-4:]
-       n, err := tun.fd.Read(buff[:])
-       if n < 4 {
+func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
+       select {
+       case err := <-tun.errors:
                return 0, err
+       default:
+               buff := buff[offset-4:]
+               n, err := tun.fd.Read(buff[:])
+               if n < 4 {
+                       return 0, err
+               }
+               return n - 4, err
+       }
+}
+
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
+       for {
+               n, err := tun.doRead(buff, offset)
+               if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
+                       return n, err
+               }
+               if !tun.rwcancel.ReadyRead() {
+                       return 0, errors.New("tun device closed")
+               }
        }
-       return n - 4, err
 }
 
 func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
@@ -224,9 +251,13 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
 }
 
 func (tun *NativeTun) Close() error {
-       err := tun.fd.Close()
+       err1 := tun.rwcancel.Cancel()
+       err2 := tun.fd.Close()
        close(tun.events)
-       return err
+       if err1 != nil {
+               return err1
+       }
+       return err2
 }
 
 func (tun *NativeTun) setMTU(n int) error {