mirror of
https://github.com/yggdrasil-network/water.git
synced 2025-05-19 08:25:09 +03:00
use blocking mode pre-go1.11
This commit is contained in:
parent
240a3d7b51
commit
3fe638a7bf
13 changed files with 132 additions and 95 deletions
|
@ -1,6 +1,7 @@
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- "1.11.4"
|
- "1.12.1"
|
||||||
|
- "1.10.8"
|
||||||
go_import_path: github.com/songgao/water
|
go_import_path: github.com/songgao/water
|
||||||
install: go get -u golang.org/x/lint/golint
|
install: go get -u golang.org/x/lint/golint
|
||||||
script: make ci
|
script: make ci
|
||||||
|
|
6
if.go
6
if.go
|
@ -57,10 +57,8 @@ func New(config Config) (ifce *Interface, err error) {
|
||||||
config.PlatformSpecificParams = defaultPlatformSpecificParams()
|
config.PlatformSpecificParams = defaultPlatformSpecificParams()
|
||||||
}
|
}
|
||||||
switch config.DeviceType {
|
switch config.DeviceType {
|
||||||
case TUN:
|
case TUN, TAP:
|
||||||
return newTUN(config)
|
return openDev(config)
|
||||||
case TAP:
|
|
||||||
return newTAP(config)
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unknown device type")
|
return nil, errors.New("unknown device type")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func NewTAP(ifName string) (ifce *Interface, err error) {
|
||||||
fmt.Println("Deprecated: NewTAP(..) may be removed in the future. Please use New() instead.")
|
fmt.Println("Deprecated: NewTAP(..) may be removed in the future. Please use New() instead.")
|
||||||
config := Config{DeviceType: TAP}
|
config := Config{DeviceType: TAP}
|
||||||
config.Name = ifName
|
config.Name = ifName
|
||||||
return newTAP(config)
|
return openDev(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTUN creates a new TUN interface whose name is ifName. If ifName is empty, a
|
// NewTUN creates a new TUN interface whose name is ifName. If ifName is empty, a
|
||||||
|
@ -26,5 +26,5 @@ func NewTUN(ifName string) (ifce *Interface, err error) {
|
||||||
fmt.Println("Deprecated: NewTUN(..) may be removed in the future. Please use New() instead.")
|
fmt.Println("Deprecated: NewTUN(..) may be removed in the future. Please use New() instead.")
|
||||||
config := Config{DeviceType: TUN}
|
config := Config{DeviceType: TUN}
|
||||||
config.Name = ifName
|
config.Name = ifName
|
||||||
return newTUN(config)
|
return openDev(config)
|
||||||
}
|
}
|
||||||
|
|
36
ipv4_go1.11_test.go
Normal file
36
ipv4_go1.11_test.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// +build go1.11
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCloseUnblockPendingRead(t *testing.T) {
|
||||||
|
ifce, err := New(Config{DeviceType: TUN})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("creating TUN error: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
ifce.Read(make([]byte, 1<<16))
|
||||||
|
close(c)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// make sure ifce.Close() happens after ifce.Read() blocks
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
ifce.Close()
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
t.Log("Pending Read unblocked")
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("Timeouted, pending read blocked")
|
||||||
|
}
|
||||||
|
}
|
29
ipv4_test.go
29
ipv4_test.go
|
@ -1,9 +1,7 @@
|
||||||
package water
|
package water
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const BUFFERSIZE = 1522
|
const BUFFERSIZE = 1522
|
||||||
|
@ -22,30 +20,3 @@ func startRead(t *testing.T, ifce *Interface, dataCh chan<- []byte, errCh chan<-
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCloseUnblockPendingRead(t *testing.T) {
|
|
||||||
ifce, err := New(Config{DeviceType: TUN})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("creating TUN error: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
ifce.Read(make([]byte, 1<<16))
|
|
||||||
close(c)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// make sure ifce.Close() happens after ifce.Read() blocks
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
ifce.Close()
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-c:
|
|
||||||
t.Log("Pending Read unblocked")
|
|
||||||
case <-ctx.Done():
|
|
||||||
t.Fatal("Timeouted, pending read blocked")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,7 +59,10 @@ type sockaddrCtl struct {
|
||||||
|
|
||||||
var sockaddrCtlSize uintptr = 32
|
var sockaddrCtlSize uintptr = 32
|
||||||
|
|
||||||
func newTUN(config Config) (ifce *Interface, err error) {
|
func openDev(config Config) (ifce *Interface, err error) {
|
||||||
|
if config.DeviceType != TUN {
|
||||||
|
return nil, errors.New("only tun is implemented on this platform")
|
||||||
|
}
|
||||||
var fd int
|
var fd int
|
||||||
// Supposed to be socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), but ...
|
// Supposed to be socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), but ...
|
||||||
//
|
//
|
||||||
|
@ -111,7 +114,7 @@ func newTUN(config Config) (ifce *Interface, err error) {
|
||||||
return nil, fmt.Errorf("error in syscall.Syscall6(syscall.SYS_GETSOCKOPT, ...): %v", err)
|
return nil, fmt.Errorf("error in syscall.Syscall6(syscall.SYS_GETSOCKOPT, ...): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = syscall.SetNonblock(fd, true); err != nil {
|
if err = setNonBlock(fd); err != nil {
|
||||||
return nil, fmt.Errorf("setting non-blocking error")
|
return nil, fmt.Errorf("setting non-blocking error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,10 +127,6 @@ func newTUN(config Config) (ifce *Interface, err error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTAP(config Config) (ifce *Interface, err error) {
|
|
||||||
return nil, errors.New("tap interface not implemented on this platform")
|
|
||||||
}
|
|
||||||
|
|
||||||
// tunReadCloser is a hack to work around the first 4 bytes "packet
|
// tunReadCloser 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 tunReadCloser struct {
|
type tunReadCloser struct {
|
||||||
|
|
9
syscalls_darwin_go1.11.go
Normal file
9
syscalls_darwin_go1.11.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// +build darwin,go1.11
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func setNonBlock(fd int) error {
|
||||||
|
return syscall.SetNonblock(fd, true)
|
||||||
|
}
|
10
syscalls_darwin_legacy.go
Normal file
10
syscalls_darwin_legacy.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// +build darwin,!go1.11
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
func setNonBlock(fd int) error {
|
||||||
|
// There's a but pre-go1.11 that causes 'resource temporarily unavailable'
|
||||||
|
// error in non-blocking mode. So just skip it here. Close() won't be able
|
||||||
|
// to unblock a pending read, but that's better than being broken.
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -28,54 +28,26 @@ func ioctl(fd uintptr, request uintptr, argp uintptr) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTAP(config Config) (ifce *Interface, err error) {
|
func setupFd(config Config, fd uintptr) (name string, err error) {
|
||||||
fdInt, err := syscall.Open("/dev/net/tun", os.O_RDWR|syscall.O_NONBLOCK, 0)
|
var flags uint16 = cIFFNOPI
|
||||||
if err != nil {
|
if config.DeviceType == TUN {
|
||||||
return nil, err
|
flags |= cIFFTUN
|
||||||
|
} else {
|
||||||
|
flags |= cIFFTAP
|
||||||
}
|
}
|
||||||
fd := uintptr(fdInt)
|
|
||||||
|
|
||||||
var flags uint16
|
|
||||||
flags = cIFFTAP | cIFFNOPI
|
|
||||||
if config.PlatformSpecificParams.MultiQueue {
|
if config.PlatformSpecificParams.MultiQueue {
|
||||||
flags |= cIFFMULTIQUEUE
|
flags |= cIFFMULTIQUEUE
|
||||||
}
|
}
|
||||||
name, err := createInterface(fd, config.Name, flags)
|
|
||||||
if err != nil {
|
if name, err = createInterface(fd, config.Name, flags); err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setDeviceOptions(fd, config); err != nil {
|
if err = setDeviceOptions(fd, config); err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
ifce = &Interface{isTAP: true, ReadWriteCloser: os.NewFile(fd, "tun"), name: name}
|
return name, nil
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTUN(config Config) (ifce *Interface, err error) {
|
|
||||||
fdInt, err := syscall.Open("/dev/net/tun", os.O_RDWR|syscall.O_NONBLOCK, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fd := uintptr(fdInt)
|
|
||||||
|
|
||||||
var flags uint16
|
|
||||||
flags = cIFFTUN | cIFFNOPI
|
|
||||||
if config.PlatformSpecificParams.MultiQueue {
|
|
||||||
flags |= cIFFMULTIQUEUE
|
|
||||||
}
|
|
||||||
name, err := createInterface(fd, config.Name, flags)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = setDeviceOptions(fd, config); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ifce = &Interface{isTAP: false, ReadWriteCloser: os.NewFile(fd, "tun"), name: name}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
|
func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName string, err error) {
|
||||||
|
|
27
syscalls_linux_go1.11.go
Normal file
27
syscalls_linux_go1.11.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// +build linux,go1.11
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openDev(config Config) (ifce *Interface, err error) {
|
||||||
|
var fdInt int
|
||||||
|
if fdInt, err = syscall.Open(
|
||||||
|
"/dev/net/tun", os.O_RDWR|syscall.O_NONBLOCK, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name, err := setupFd(config, uintptr(fdInt))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Interface{
|
||||||
|
isTAP: config.DeviceType == TAP,
|
||||||
|
ReadWriteCloser: os.NewFile(uintptr(fdInt), "tun"),
|
||||||
|
name: name,
|
||||||
|
}, nil
|
||||||
|
}
|
26
syscalls_linux_legacy.go
Normal file
26
syscalls_linux_legacy.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// +build linux,!go1.11
|
||||||
|
|
||||||
|
package water
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openDev(config Config) (ifce *Interface, err error) {
|
||||||
|
var file *os.File
|
||||||
|
if file, err = os.OpenFile(
|
||||||
|
"/dev/net/tun", os.O_RDWR, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name, err := setupFd(config, file.Fd())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Interface{
|
||||||
|
isTAP: config.DeviceType == TAP,
|
||||||
|
ReadWriteCloser: file,
|
||||||
|
name: name,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -4,10 +4,6 @@ package water
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
func newTAP(config Config) (ifce *Interface, err error) {
|
func openDev(config Config) (*Interface, error) {
|
||||||
return nil, errors.New("tap interface not implemented on this platform")
|
return nil, errors.New("not implemented on this platform")
|
||||||
}
|
|
||||||
|
|
||||||
func newTUN(config Config) (ifce *Interface, err error) {
|
|
||||||
return nil, errors.New("tap interface not implemented on this platform")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,11 +306,3 @@ func openDev(config Config) (ifce *Interface, err error) {
|
||||||
|
|
||||||
return nil, errIfceNameNotFound
|
return nil, errIfceNameNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTAP(config Config) (ifce *Interface, err error) {
|
|
||||||
return openDev(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTUN(config Config) (ifce *Interface, err error) {
|
|
||||||
return openDev(config)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue