summaryrefslogtreecommitdiffhomepage
path: root/tun_linux.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-05-14 00:28:30 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-05-14 00:30:52 +0200
commit7e10ebe1010898c48e3f1cfc12ad42d0bb5c0fa1 (patch)
treec0a43be046bf87808ab7dd8839b8a3cd650cacde /tun_linux.go
parente21ea58db36b8caf3b7da075c9c39505449d0110 (diff)
Introduce rwcancel
Diffstat (limited to 'tun_linux.go')
-rw-r--r--tun_linux.go79
1 files changed, 13 insertions, 66 deletions
diff --git a/tun_linux.go b/tun_linux.go
index 9f60d2b..3510f94 100644
--- a/tun_linux.go
+++ b/tun_linux.go
@@ -11,6 +11,7 @@ package main
*/
import (
+ "./rwcancel"
"bytes"
"encoding/binary"
"errors"
@@ -20,7 +21,6 @@ import (
"net"
"os"
"strconv"
- "syscall"
"time"
"unsafe"
)
@@ -31,14 +31,13 @@ const (
)
type NativeTun struct {
- fd *os.File
- index int32 // if index
- name string // name of interface
- errors chan error // async error handling
- events chan TUNEvent // device related events
- nopi bool // the device was pased IFF_NO_PI
- closingReader *os.File
- closingWriter *os.File
+ fd *os.File
+ index int32 // if index
+ name string // name of interface
+ errors chan error // async error handling
+ events chan TUNEvent // device related events
+ nopi bool // the device was pased IFF_NO_PI
+ rwcancel *rwcancel.RWCancel
}
func (tun *NativeTun) File() *os.File {
@@ -305,43 +304,6 @@ func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
return tun.fd.Write(buff)
}
-type FdSet struct {
- fdset unix.FdSet
-}
-
-func (fdset *FdSet) set(i int) {
- bits := 32 << (^uint(0) >> 63)
- fdset.fdset.Bits[i/bits] |= 1 << uint(i%bits)
-}
-
-func (fdset *FdSet) check(i int) bool {
- bits := 32 << (^uint(0) >> 63)
- return (fdset.fdset.Bits[i/bits] & (1 << uint(i%bits))) != 0
-}
-
-func max(a, b int) int {
- if a > b {
- return a
- }
- return b
-}
-
-func (tun *NativeTun) readyRead() bool {
- readFd := int(tun.fd.Fd())
- closeFd := int(tun.closingReader.Fd())
- fdset := FdSet{}
- fdset.set(readFd)
- fdset.set(closeFd)
- _, err := unix.Select(max(readFd, closeFd)+1, &fdset.fdset, nil, nil, nil)
- if err != nil {
- return false
- }
- if fdset.check(closeFd) {
- return false
- }
- return fdset.check(readFd)
-}
-
func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
select {
case err := <-tun.errors:
@@ -360,24 +322,14 @@ func (tun *NativeTun) doRead(buff []byte, offset int) (int, error) {
}
}
-/* https://golang.org/src/crypto/rand/eagain.go */
-func unixIsEAGAIN(err error) bool {
- if pe, ok := err.(*os.PathError); ok {
- if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN {
- return true
- }
- }
- return false
-}
-
func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
for {
n, err := tun.doRead(buff, offset)
- if err == nil || !unixIsEAGAIN(err) {
+ if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
return n, err
}
- if !tun.readyRead() {
- return 0, errors.New("Tun device closed")
+ if !tun.rwcancel.ReadyRead() {
+ return 0, errors.New("tun device closed")
}
}
}
@@ -391,7 +343,7 @@ func (tun *NativeTun) Close() error {
if err != nil {
return err
}
- tun.closingWriter.Write([]byte{0})
+ tun.rwcancel.Cancel()
close(tun.events)
return nil
}
@@ -450,7 +402,7 @@ func CreateTUNFromFile(fd *os.File) (TUNDevice, error) {
}
var err error
- err = unix.SetNonblock(int(fd.Fd()), true)
+ device.rwcancel, err = rwcancel.NewRWCancel(int(fd.Fd()))
if err != nil {
return nil, err
}
@@ -460,11 +412,6 @@ func CreateTUNFromFile(fd *os.File) (TUNDevice, error) {
return nil, err
}
- device.closingReader, device.closingWriter, err = os.Pipe()
- if err != nil {
- return nil, err
- }
-
// start event listener
device.index, err = getIFIndex(device.name)