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

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
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 {