mirror of
				https://git.zx2c4.com/wireguard-go
				synced 2025-10-27 02:10:26 +08:00 
			
		
		
		
	tun: use netpoll instead of rwcancel
The new sysconn function of Go 1.12 makes this possible:
package main
import "log"
import "os"
import "unsafe"
import "time"
import "syscall"
import "sync"
import "golang.org/x/sys/unix"
func main() {
	fd, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
	if err != nil {
		log.Fatal(err)
	}
	var ifr [unix.IFNAMSIZ + 64]byte
	copy(ifr[:], []byte("cheese"))
	*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = unix.IFF_TUN
	var errno syscall.Errno
	s, _ := fd.SyscallConn()
	s.Control(func(fd uintptr) {
		_, _, errno = unix.Syscall(
			unix.SYS_IOCTL,
			fd,
			uintptr(unix.TUNSETIFF),
			uintptr(unsafe.Pointer(&ifr[0])),
		)
	})
	if errno != 0 {
		log.Fatal(errno)
	}
	b := [4]byte{}
	wait := sync.WaitGroup{}
	wait.Add(1)
	go func() {
		_, err := fd.Read(b[:])
		log.Print("Read errored: ", err)
		wait.Done()
	}()
	time.Sleep(time.Second)
	log.Print("Closing")
	err = fd.Close()
	if err != nil {
		log.Print("Close errored: " , err)
	}
	wait.Wait()
	log.Print("Exiting")
}
			
			
This commit is contained in:
		
							
								
								
									
										5
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								main.go
									
									
									
									
									
								
							| @@ -145,6 +145,11 @@ func main() { | |||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		err = syscall.SetNonblock(int(fd), true) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		file := os.NewFile(uintptr(fd), "") | 		file := os.NewFile(uintptr(fd), "") | ||||||
| 		return tun.CreateTUNFromFile(file, DefaultMTU) | 		return tun.CreateTUNFromFile(file, DefaultMTU) | ||||||
| 	}() | 	}() | ||||||
|   | |||||||
| @@ -38,4 +38,4 @@ func (tun *nativeTun) operateOnFd(fn func(fd uintptr)) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.errors <- fmt.Errorf("unable to control sysconn for tunfile: %s", err.Error()) | 		tun.errors <- fmt.Errorf("unable to control sysconn for tunfile: %s", err.Error()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,11 +6,9 @@ | |||||||
| package tun | package tun | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"golang.org/x/net/ipv6" | 	"golang.org/x/net/ipv6" | ||||||
| 	"golang.org/x/sys/unix" | 	"golang.org/x/sys/unix" | ||||||
| 	"golang.zx2c4.com/wireguard/rwcancel" |  | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -36,7 +34,6 @@ type sockaddrCtl struct { | |||||||
| type nativeTun struct { | type nativeTun struct { | ||||||
| 	name        string | 	name        string | ||||||
| 	tunFile     *os.File | 	tunFile     *os.File | ||||||
| 	rwcancel    *rwcancel.RWCancel |  | ||||||
| 	events      chan TUNEvent | 	events      chan TUNEvent | ||||||
| 	errors      chan error | 	errors      chan error | ||||||
| 	routeSocket int | 	routeSocket int | ||||||
| @@ -154,6 +151,10 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) { | |||||||
| 		return nil, fmt.Errorf("SYS_CONNECT: %v", errno) | 		return nil, fmt.Errorf("SYS_CONNECT: %v", errno) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	err = syscall.SetNonblock(fd, true) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
| 	tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""), mtu) | 	tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""), mtu) | ||||||
|  |  | ||||||
| 	if err == nil && name == "utun" { | 	if err == nil && name == "utun" { | ||||||
| @@ -191,14 +192,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tun.operateOnFd(func (fd uintptr) { |  | ||||||
| 		tun.rwcancel, err = rwcancel.NewRWCancel(int(fd)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		tun.tunFile.Close() |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.tunFile.Close() | 		tun.tunFile.Close() | ||||||
| @@ -249,7 +242,7 @@ func (tun *nativeTun) Events() chan TUNEvent { | |||||||
| 	return tun.events | 	return tun.events | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | ||||||
| 	select { | 	select { | ||||||
| 	case err := <-tun.errors: | 	case err := <-tun.errors: | ||||||
| 		return 0, err | 		return 0, err | ||||||
| @@ -263,18 +256,6 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { |  | ||||||
| 	for { |  | ||||||
| 		n, err := tun.doRead(buff, offset) |  | ||||||
| 		if err == nil || !rwcancel.RetryAfterError(err) { |  | ||||||
| 			return n, err |  | ||||||
| 		} |  | ||||||
| 		if !tun.rwcancel.ReadyRead() { |  | ||||||
| 			return 0, errors.New("tun device closed") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | ||||||
|  |  | ||||||
| 	// reserve space for header | 	// reserve space for header | ||||||
| @@ -299,12 +280,11 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Close() error { | func (tun *nativeTun) Close() error { | ||||||
| 	var err3 error | 	var err2 error | ||||||
| 	err1 := tun.rwcancel.Cancel() | 	err1 := tun.tunFile.Close() | ||||||
| 	err2 := tun.tunFile.Close() |  | ||||||
| 	if tun.routeSocket != -1 { | 	if tun.routeSocket != -1 { | ||||||
| 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | ||||||
| 		err3 = unix.Close(tun.routeSocket) | 		err2 = unix.Close(tun.routeSocket) | ||||||
| 		tun.routeSocket = -1 | 		tun.routeSocket = -1 | ||||||
| 	} else if tun.events != nil { | 	} else if tun.events != nil { | ||||||
| 		close(tun.events) | 		close(tun.events) | ||||||
| @@ -312,10 +292,7 @@ func (tun *nativeTun) Close() error { | |||||||
| 	if err1 != nil { | 	if err1 != nil { | ||||||
| 		return err1 | 		return err1 | ||||||
| 	} | 	} | ||||||
| 	if err2 != nil { | 	return err2 | ||||||
| 		return err2 |  | ||||||
| 	} |  | ||||||
| 	return err3 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) setMTU(n int) error { | func (tun *nativeTun) setMTU(n int) error { | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"golang.org/x/net/ipv6" | 	"golang.org/x/net/ipv6" | ||||||
| 	"golang.org/x/sys/unix" | 	"golang.org/x/sys/unix" | ||||||
| 	"golang.zx2c4.com/wireguard/rwcancel" |  | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| 	"syscall" | 	"syscall" | ||||||
| @@ -52,7 +51,6 @@ type ifstat struct { | |||||||
| type nativeTun struct { | type nativeTun struct { | ||||||
| 	name        string | 	name        string | ||||||
| 	tunFile     *os.File | 	tunFile     *os.File | ||||||
| 	rwcancel    *rwcancel.RWCancel |  | ||||||
| 	events      chan TUNEvent | 	events      chan TUNEvent | ||||||
| 	errors      chan error | 	errors      chan error | ||||||
| 	routeSocket int | 	routeSocket int | ||||||
| @@ -333,14 +331,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tun.operateOnFd(func(fd uintptr) { |  | ||||||
| 		tun.rwcancel, err = rwcancel.NewRWCancel(int(fd)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		tun.tunFile.Close() |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.tunFile.Close() | 		tun.tunFile.Close() | ||||||
| @@ -379,7 +369,7 @@ func (tun *nativeTun) Events() chan TUNEvent { | |||||||
| 	return tun.events | 	return tun.events | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | ||||||
| 	select { | 	select { | ||||||
| 	case err := <-tun.errors: | 	case err := <-tun.errors: | ||||||
| 		return 0, err | 		return 0, err | ||||||
| @@ -393,18 +383,6 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { |  | ||||||
| 	for { |  | ||||||
| 		n, err := tun.doRead(buff, offset) |  | ||||||
| 		if err == nil || !rwcancel.RetryAfterError(err) { |  | ||||||
| 			return n, err |  | ||||||
| 		} |  | ||||||
| 		if !tun.rwcancel.ReadyRead() { |  | ||||||
| 			return 0, errors.New("tun device closed") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | ||||||
|  |  | ||||||
| 	// reserve space for header | 	// reserve space for header | ||||||
| @@ -429,13 +407,12 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Close() error { | func (tun *nativeTun) Close() error { | ||||||
| 	var err4 error | 	var err3 error | ||||||
| 	err1 := tun.rwcancel.Cancel() | 	err1 := tun.tunFile.Close() | ||||||
| 	err2 := tun.tunFile.Close() | 	err2 := tunDestroy(tun.name) | ||||||
| 	err3 := tunDestroy(tun.name) |  | ||||||
| 	if tun.routeSocket != -1 { | 	if tun.routeSocket != -1 { | ||||||
| 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | ||||||
| 		err4 = unix.Close(tun.routeSocket) | 		err3 = unix.Close(tun.routeSocket) | ||||||
| 		tun.routeSocket = -1 | 		tun.routeSocket = -1 | ||||||
| 	} else if tun.events != nil { | 	} else if tun.events != nil { | ||||||
| 		close(tun.events) | 		close(tun.events) | ||||||
| @@ -446,10 +423,7 @@ func (tun *nativeTun) Close() error { | |||||||
| 	if err2 != nil { | 	if err2 != nil { | ||||||
| 		return err2 | 		return err2 | ||||||
| 	} | 	} | ||||||
| 	if err3 != nil { | 	return err3 | ||||||
| 		return err3 |  | ||||||
| 	} |  | ||||||
| 	return err4 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) setMTU(n int) error { | func (tun *nativeTun) setMTU(n int) error { | ||||||
|   | |||||||
| @@ -31,7 +31,6 @@ const ( | |||||||
|  |  | ||||||
| type nativeTun struct { | type nativeTun struct { | ||||||
| 	tunFile                 *os.File | 	tunFile                 *os.File | ||||||
| 	fdCancel                *rwcancel.RWCancel |  | ||||||
| 	index                   int32         // if index | 	index                   int32         // if index | ||||||
| 	name                    string        // name of interface | 	name                    string        // name of interface | ||||||
| 	errors                  chan error    // async error handling | 	errors                  chan error    // async error handling | ||||||
| @@ -307,7 +306,7 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | |||||||
| 	return tun.tunFile.Write(buff) | 	return tun.tunFile.Write(buff) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | ||||||
| 	select { | 	select { | ||||||
| 	case err := <-tun.errors: | 	case err := <-tun.errors: | ||||||
| 		return 0, err | 		return 0, err | ||||||
| @@ -325,18 +324,6 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { |  | ||||||
| 	for { |  | ||||||
| 		n, err := tun.doRead(buff, offset) |  | ||||||
| 		if err == nil || !rwcancel.RetryAfterError(err) { |  | ||||||
| 			return n, err |  | ||||||
| 		} |  | ||||||
| 		if !tun.fdCancel.ReadyRead() { |  | ||||||
| 			return 0, errors.New("tun device closed") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (tun *nativeTun) Events() chan TUNEvent { | func (tun *nativeTun) Events() chan TUNEvent { | ||||||
| 	return tun.events | 	return tun.events | ||||||
| } | } | ||||||
| @@ -352,30 +339,20 @@ func (tun *nativeTun) Close() error { | |||||||
| 		close(tun.events) | 		close(tun.events) | ||||||
| 	} | 	} | ||||||
| 	err2 := tun.tunFile.Close() | 	err2 := tun.tunFile.Close() | ||||||
| 	err3 := tun.fdCancel.Cancel() |  | ||||||
|  |  | ||||||
| 	if err1 != nil { | 	if err1 != nil { | ||||||
| 		return err1 | 		return err1 | ||||||
| 	} | 	} | ||||||
| 	if err2 != nil { | 	return err2 | ||||||
| 		return err2 |  | ||||||
| 	} |  | ||||||
| 	return err3 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func CreateTUN(name string, mtu int) (TUNDevice, error) { | func CreateTUN(name string, mtu int) (TUNDevice, error) { | ||||||
| 	nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0) | 	tunFile, err := os.OpenFile(cloneDevicePath, os.O_RDWR, 0) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fd := os.NewFile(uintptr(nfd), cloneDevicePath) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// create new device | 	// create new device | ||||||
|  |  | ||||||
| 	var ifr [ifReqSize]byte | 	var ifr [ifReqSize]byte | ||||||
| 	var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI (disabled for TUN status hack) | 	var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI (disabled for TUN status hack) | ||||||
| 	nameBytes := []byte(name) | 	nameBytes := []byte(name) | ||||||
| @@ -385,17 +362,20 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) { | |||||||
| 	copy(ifr[:], nameBytes) | 	copy(ifr[:], nameBytes) | ||||||
| 	*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags | 	*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags | ||||||
|  |  | ||||||
| 	_, _, errno := unix.Syscall( | 	var errno syscall.Errno | ||||||
| 		unix.SYS_IOCTL, | 	(&nativeTun{tunFile: tunFile}).operateOnFd(func(fd uintptr) { | ||||||
| 		nfd, | 		_, _, errno = unix.Syscall( | ||||||
| 		uintptr(unix.TUNSETIFF), | 			unix.SYS_IOCTL, | ||||||
| 		uintptr(unsafe.Pointer(&ifr[0])), | 			fd, | ||||||
| 	) | 			uintptr(unix.TUNSETIFF), | ||||||
|  | 			uintptr(unsafe.Pointer(&ifr[0])), | ||||||
|  | 		) | ||||||
|  | 	}) | ||||||
| 	if errno != 0 { | 	if errno != 0 { | ||||||
| 		return nil, errno | 		return nil, errno | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return CreateTUNFromFile(fd, mtu) | 	return CreateTUNFromFile(tunFile, mtu) | ||||||
| } | } | ||||||
|  |  | ||||||
| func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | ||||||
| @@ -408,14 +388,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | |||||||
| 	} | 	} | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	tun.operateOnFd(func(fd uintptr) { |  | ||||||
| 		tun.fdCancel, err = rwcancel.NewRWCancel(int(fd)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		tun.tunFile.Close() |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	_, err = tun.Name() | 	_, err = tun.Name() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.tunFile.Close() | 		tun.tunFile.Close() | ||||||
|   | |||||||
| @@ -6,11 +6,9 @@ | |||||||
| package tun | package tun | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"golang.org/x/net/ipv6" | 	"golang.org/x/net/ipv6" | ||||||
| 	"golang.org/x/sys/unix" | 	"golang.org/x/sys/unix" | ||||||
| 	"golang.zx2c4.com/wireguard/rwcancel" |  | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -30,7 +28,6 @@ const _TUNSIFMODE = 0x8004745d | |||||||
| type nativeTun struct { | type nativeTun struct { | ||||||
| 	name        string | 	name        string | ||||||
| 	tunFile     *os.File | 	tunFile     *os.File | ||||||
| 	rwcancel    *rwcancel.RWCancel |  | ||||||
| 	events      chan TUNEvent | 	events      chan TUNEvent | ||||||
| 	errors      chan error | 	errors      chan error | ||||||
| 	routeSocket int | 	routeSocket int | ||||||
| @@ -167,14 +164,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tun.operateOnFd(func(fd uintptr) { |  | ||||||
| 		tun.rwcancel, err = rwcancel.NewRWCancel(int(fd)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		tun.tunFile.Close() |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | 	tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.tunFile.Close() | 		tun.tunFile.Close() | ||||||
| @@ -211,7 +200,7 @@ func (tun *nativeTun) Events() chan TUNEvent { | |||||||
| 	return tun.events | 	return tun.events | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | ||||||
| 	select { | 	select { | ||||||
| 	case err := <-tun.errors: | 	case err := <-tun.errors: | ||||||
| 		return 0, err | 		return 0, err | ||||||
| @@ -225,18 +214,6 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { |  | ||||||
| 	for { |  | ||||||
| 		n, err := tun.doRead(buff, offset) |  | ||||||
| 		if err == nil || !rwcancel.RetryAfterError(err) { |  | ||||||
| 			return n, err |  | ||||||
| 		} |  | ||||||
| 		if !tun.rwcancel.ReadyRead() { |  | ||||||
| 			return 0, errors.New("tun device closed") |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | ||||||
|  |  | ||||||
| 	// reserve space for header | 	// reserve space for header | ||||||
| @@ -261,12 +238,11 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) Close() error { | func (tun *nativeTun) Close() error { | ||||||
| 	var err3 error | 	var err2 error | ||||||
| 	err1 := tun.rwcancel.Cancel() | 	err1 := tun.tunFile.Close() | ||||||
| 	err2 := tun.tunFile.Close() |  | ||||||
| 	if tun.routeSocket != -1 { | 	if tun.routeSocket != -1 { | ||||||
| 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | 		unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR) | ||||||
| 		err3 = unix.Close(tun.routeSocket) | 		err2 = unix.Close(tun.routeSocket) | ||||||
| 		tun.routeSocket = -1 | 		tun.routeSocket = -1 | ||||||
| 	} else if tun.events != nil { | 	} else if tun.events != nil { | ||||||
| 		close(tun.events) | 		close(tun.events) | ||||||
| @@ -274,10 +250,7 @@ func (tun *nativeTun) Close() error { | |||||||
| 	if err1 != nil { | 	if err1 != nil { | ||||||
| 		return err1 | 		return err1 | ||||||
| 	} | 	} | ||||||
| 	if err2 != nil { | 	return err2 | ||||||
| 		return err2 |  | ||||||
| 	} |  | ||||||
| 	return err3 |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (tun *nativeTun) setMTU(n int) error { | func (tun *nativeTun) setMTU(n int) error { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jason A. Donenfeld
					Jason A. Donenfeld