Add rwcancelation to darwin
This commit is contained in:
parent
f738c45a68
commit
5f5503afa8
|
@ -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
12
rwcancel/select_darwin.go
Normal 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
13
rwcancel/select_linux.go
Normal 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
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue