Add rwcancelation to darwin

This commit is contained in:
Jason A. Donenfeld 2018-05-14 03:55:46 +02:00
parent f738c45a68
commit 5f5503afa8
4 changed files with 73 additions and 17 deletions

View file

@ -77,7 +77,7 @@ func (rw *RWCancel) ReadyRead() bool {
fdset := fdSet{} fdset := fdSet{}
fdset.set(rw.fd) fdset.set(rw.fd)
fdset.set(closeFd) 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 { if err != nil {
return false return false
} }
@ -92,7 +92,7 @@ func (rw *RWCancel) ReadyWrite() bool {
fdset := fdSet{} fdset := fdSet{}
fdset.set(rw.fd) fdset.set(rw.fd)
fdset.set(closeFd) 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 { if err != nil {
return false return false
} }

12
rwcancel/select_darwin.go Normal file
View file

@ -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)
}

13
rwcancel/select_linux.go Normal file
View file

@ -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
}

View file

@ -6,7 +6,9 @@
package main package main
import ( import (
"./rwcancel"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -34,9 +36,10 @@ type sockaddrCtl struct {
// NativeTun is a hack to work around the first 4 bytes "packet // 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. // information" because there doesn't seem to be an IFF_NO_PI for darwin.
type NativeTun struct { type NativeTun struct {
name string name string
fd *os.File fd *os.File
mtu int rwcancel *rwcancel.RWCancel
mtu int
events chan TUNEvent events chan TUNEvent
errors chan error errors chan error
@ -121,6 +124,17 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
return nil, err 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 // TODO: Fix this very naive implementation
go func(tun *NativeTun) { go func(tun *NativeTun) {
var ( var (
@ -153,10 +167,7 @@ func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
} }
}(tun) }(tun)
// set default MTU return tun, nil
err = tun.setMTU(DefaultMTU)
return tun, err
} }
func (tun *NativeTun) Name() (string, error) { func (tun *NativeTun) Name() (string, error) {
@ -190,14 +201,30 @@ func (tun *NativeTun) Events() chan TUNEvent {
return tun.events return tun.events
} }
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
select {
buff = buff[offset-4:] case err := <-tun.errors:
n, err := tun.fd.Read(buff[:])
if n < 4 {
return 0, err 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) { 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 { func (tun *NativeTun) Close() error {
err := tun.fd.Close() err1 := tun.rwcancel.Cancel()
err2 := tun.fd.Close()
close(tun.events) close(tun.events)
return err if err1 != nil {
return err1
}
return err2
} }
func (tun *NativeTun) setMTU(n int) error { func (tun *NativeTun) setMTU(n int) error {