mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 15:20:30 +00:00
Merge pull request #306 from neilalexander/ios
AWDL support, Android tweaks
This commit is contained in:
commit
3fa5893fd6
37
build
37
build
@ -6,13 +6,14 @@ PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
|
|||||||
|
|
||||||
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
||||||
|
|
||||||
while getopts "udmtc:l:" option
|
while getopts "udaitc:l:" option
|
||||||
do
|
do
|
||||||
case "${option}"
|
case "${option}"
|
||||||
in
|
in
|
||||||
u) UPX=true;;
|
u) UPX=true;;
|
||||||
d) DEBUG=true;;
|
d) DEBUG=true;;
|
||||||
m) MOBILE=true;;
|
i) IOS=true;;
|
||||||
|
a) ANDROID=true;;
|
||||||
t) TABLES=true;;
|
t) TABLES=true;;
|
||||||
c) GCFLAGS="$GCFLAGS $OPTARG";;
|
c) GCFLAGS="$GCFLAGS $OPTARG";;
|
||||||
l) LDFLAGS="$LDFLAGS $OPTARG";;
|
l) LDFLAGS="$LDFLAGS $OPTARG";;
|
||||||
@ -23,17 +24,23 @@ if [ -z $TABLES ]; then
|
|||||||
STRIP="-s -w"
|
STRIP="-s -w"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for CMD in `ls cmd/` ; do
|
if [ $IOS ]; then
|
||||||
echo "Building: $CMD"
|
echo "Building framework for iOS"
|
||||||
|
gomobile bind -target ios -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil
|
||||||
|
elif [ $ANDROID ]; then
|
||||||
|
echo "Building aar for Android"
|
||||||
|
gomobile bind -target android -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil
|
||||||
|
else
|
||||||
|
for CMD in `ls cmd/` ; do
|
||||||
|
echo "Building: $CMD"
|
||||||
|
|
||||||
if [ $MOBILE ]; then
|
if [ $DEBUG ]; then
|
||||||
go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags mobile -v ./cmd/$CMD
|
go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags debug -v ./cmd/$CMD
|
||||||
elif [ $DEBUG ]; then
|
else
|
||||||
go build -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" -tags debug -v ./cmd/$CMD
|
go build -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" -v ./cmd/$CMD
|
||||||
else
|
fi
|
||||||
go build -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" -v ./cmd/$CMD
|
if [ $UPX ]; then
|
||||||
fi
|
upx --brute $CMD
|
||||||
if [ $UPX ]; then
|
fi
|
||||||
upx --brute $CMD
|
done
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
@ -34,42 +34,42 @@ func (l *awdl) init(c *Core) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *awdl) create(fromAWDL chan []byte, toAWDL chan []byte, boxPubKey *crypto.BoxPubKey, sigPubKey *crypto.SigPubKey, name string) (*awdlInterface, error) {
|
func (l *awdl) create(fromAWDL chan []byte, toAWDL chan []byte /*boxPubKey *crypto.BoxPubKey, sigPubKey *crypto.SigPubKey*/, name string) (*awdlInterface, error) {
|
||||||
/*
|
|
||||||
myLinkPub, myLinkPriv := crypto.NewBoxKeys()
|
|
||||||
meta := version_getBaseMetadata()
|
|
||||||
meta.box = l.core.boxPub
|
|
||||||
meta.sig = l.core.sigPub
|
|
||||||
meta.link = *myLinkPub
|
|
||||||
metaBytes := meta.encode()
|
|
||||||
l.core.log.Println("toAWDL <- metaBytes")
|
|
||||||
toAWDL <- metaBytes
|
|
||||||
l.core.log.Println("metaBytes = <-fromAWDL")
|
|
||||||
metaBytes = <-fromAWDL
|
|
||||||
l.core.log.Println("version_metadata{}")
|
|
||||||
meta = version_metadata{}
|
|
||||||
if !meta.decode(metaBytes) || !meta.check() {
|
|
||||||
return nil, errors.New("Metadata decode failure")
|
|
||||||
}
|
|
||||||
base := version_getBaseMetadata()
|
|
||||||
if meta.ver > base.ver || meta.ver == base.ver && meta.minorVer > base.minorVer {
|
|
||||||
return nil, errors.New("Failed to connect to node: " + name + " version: " + fmt.Sprintf("%d.%d", meta.ver, meta.minorVer))
|
|
||||||
}
|
|
||||||
shared := crypto.GetSharedKey(myLinkPriv, &meta.link)
|
|
||||||
*/
|
|
||||||
shared := crypto.GetSharedKey(&l.core.boxPriv, boxPubKey)
|
|
||||||
intf := awdlInterface{
|
intf := awdlInterface{
|
||||||
awdl: l,
|
awdl: l,
|
||||||
fromAWDL: fromAWDL,
|
fromAWDL: fromAWDL,
|
||||||
toAWDL: toAWDL,
|
toAWDL: toAWDL,
|
||||||
shutdown: make(chan bool),
|
shutdown: make(chan bool),
|
||||||
peer: l.core.peers.newPeer(boxPubKey, sigPubKey, shared, name),
|
|
||||||
//peer: l.core.peers.newPeer(&meta.box, &meta.sig, shared, name),
|
|
||||||
}
|
}
|
||||||
|
l.mutex.Lock()
|
||||||
|
l.interfaces[name] = &intf
|
||||||
|
l.mutex.Unlock()
|
||||||
|
myLinkPub, myLinkPriv := crypto.NewBoxKeys()
|
||||||
|
meta := version_getBaseMetadata()
|
||||||
|
meta.box = l.core.boxPub
|
||||||
|
meta.sig = l.core.sigPub
|
||||||
|
meta.link = *myLinkPub
|
||||||
|
metaBytes := meta.encode()
|
||||||
|
l.core.log.Println("toAWDL <- metaBytes")
|
||||||
|
toAWDL <- metaBytes
|
||||||
|
l.core.log.Println("metaBytes = <-fromAWDL")
|
||||||
|
metaBytes = <-fromAWDL
|
||||||
|
l.core.log.Println("version_metadata{}")
|
||||||
|
meta = version_metadata{}
|
||||||
|
if !meta.decode(metaBytes) || !meta.check() {
|
||||||
|
return nil, errors.New("Metadata decode failure")
|
||||||
|
}
|
||||||
|
l.core.log.Println("version_getBaseMetadata{}")
|
||||||
|
base := version_getBaseMetadata()
|
||||||
|
if meta.ver > base.ver || meta.ver == base.ver && meta.minorVer > base.minorVer {
|
||||||
|
return nil, errors.New("Failed to connect to node: " + name + " version: " + fmt.Sprintf("%d.%d", meta.ver, meta.minorVer))
|
||||||
|
}
|
||||||
|
l.core.log.Println("crypto.GetSharedKey")
|
||||||
|
shared := crypto.GetSharedKey(myLinkPriv, &meta.link)
|
||||||
|
//shared := crypto.GetSharedKey(&l.core.boxPriv, boxPubKey)
|
||||||
|
l.core.log.Println("l.core.peers.newPeer")
|
||||||
|
intf.peer = l.core.peers.newPeer(&meta.box, &meta.sig, shared, name)
|
||||||
if intf.peer != nil {
|
if intf.peer != nil {
|
||||||
l.mutex.Lock()
|
|
||||||
l.interfaces[name] = &intf
|
|
||||||
l.mutex.Unlock()
|
|
||||||
intf.peer.linkOut = make(chan []byte, 1) // protocol traffic
|
intf.peer.linkOut = make(chan []byte, 1) // protocol traffic
|
||||||
intf.peer.out = func(msg []byte) {
|
intf.peer.out = func(msg []byte) {
|
||||||
defer func() { recover() }()
|
defer func() { recover() }()
|
||||||
@ -84,6 +84,7 @@ func (l *awdl) create(fromAWDL chan []byte, toAWDL chan []byte, boxPubKey *crypt
|
|||||||
go intf.peer.linkLoop()
|
go intf.peer.linkLoop()
|
||||||
return &intf, nil
|
return &intf, nil
|
||||||
}
|
}
|
||||||
|
delete(l.interfaces, name)
|
||||||
return nil, errors.New("l.core.peers.newPeer failed")
|
return nil, errors.New("l.core.peers.newPeer failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,14 @@ package yggdrasil
|
|||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"time"
|
||||||
|
|
||||||
hjson "github.com/hjson/hjson-go"
|
hjson "github.com/hjson/hjson-go"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +22,26 @@ import (
|
|||||||
// that in the case of iOS we handle reading/writing to/from TUN in Swift
|
// that in the case of iOS we handle reading/writing to/from TUN in Swift
|
||||||
// therefore we use the "dummy" TUN interface instead.
|
// therefore we use the "dummy" TUN interface instead.
|
||||||
|
|
||||||
|
func (c *Core) addStaticPeers(cfg *config.NodeConfig) {
|
||||||
|
if len(cfg.Peers) == 0 && len(cfg.InterfacePeers) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
for _, peer := range cfg.Peers {
|
||||||
|
c.AddPeer(peer, "")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
for intf, intfpeers := range cfg.InterfacePeers {
|
||||||
|
for _, peer := range intfpeers {
|
||||||
|
c.AddPeer(peer, intf)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts a node with a randomly generated config.
|
||||||
func (c *Core) StartAutoconfigure() error {
|
func (c *Core) StartAutoconfigure() error {
|
||||||
mobilelog := MobileLogger{}
|
mobilelog := MobileLogger{}
|
||||||
logger := log.New(mobilelog, "", 0)
|
logger := log.New(mobilelog, "", 0)
|
||||||
@ -40,9 +59,12 @@ func (c *Core) StartAutoconfigure() error {
|
|||||||
if err := c.Start(nc, logger); err != nil {
|
if err := c.Start(nc, logger); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
go c.addStaticPeers(nc)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Starts a node with the given JSON config. You can get JSON config (rather
|
||||||
|
// than HJSON) by using the GenerateConfigJSON() function.
|
||||||
func (c *Core) StartJSON(configjson []byte) error {
|
func (c *Core) StartJSON(configjson []byte) error {
|
||||||
mobilelog := MobileLogger{}
|
mobilelog := MobileLogger{}
|
||||||
logger := log.New(mobilelog, "", 0)
|
logger := log.New(mobilelog, "", 0)
|
||||||
@ -55,7 +77,9 @@ func (c *Core) StartJSON(configjson []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nc.IfName = "dummy"
|
nc.IfName = "dummy"
|
||||||
|
//c.log.Println(nc.MulticastInterfaces)
|
||||||
for _, ll := range nc.MulticastInterfaces {
|
for _, ll := range nc.MulticastInterfaces {
|
||||||
|
//c.log.Println("Processing MC", ll)
|
||||||
ifceExpr, err := regexp.Compile(ll)
|
ifceExpr, err := regexp.Compile(ll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -65,9 +89,11 @@ func (c *Core) StartJSON(configjson []byte) error {
|
|||||||
if err := c.Start(nc, logger); err != nil {
|
if err := c.Start(nc, logger); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
go c.addStaticPeers(nc)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates mobile-friendly configuration in JSON format.
|
||||||
func GenerateConfigJSON() []byte {
|
func GenerateConfigJSON() []byte {
|
||||||
nc := config.GenerateConfig(false)
|
nc := config.GenerateConfig(false)
|
||||||
nc.IfName = "dummy"
|
nc.IfName = "dummy"
|
||||||
@ -78,90 +104,40 @@ func GenerateConfigJSON() []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the node's IPv6 address.
|
||||||
func (c *Core) GetAddressString() string {
|
func (c *Core) GetAddressString() string {
|
||||||
return c.GetAddress().String()
|
return c.GetAddress().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the node's IPv6 subnet in CIDR notation.
|
||||||
func (c *Core) GetSubnetString() string {
|
func (c *Core) GetSubnetString() string {
|
||||||
return c.GetSubnet().String()
|
return c.GetSubnet().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the node's public encryption key.
|
||||||
|
func (c *Core) GetBoxPubKeyString() string {
|
||||||
|
return hex.EncodeToString(c.boxPub[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the node's public signing key.
|
||||||
|
func (c *Core) GetSigPubKeyString() string {
|
||||||
|
return hex.EncodeToString(c.sigPub[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a packet from the router. You will use this when implementing a
|
||||||
|
// dummy adapter in place of real TUN - when this call returns a packet, you
|
||||||
|
// will probably want to give it to the OS to write to TUN.
|
||||||
func (c *Core) RouterRecvPacket() ([]byte, error) {
|
func (c *Core) RouterRecvPacket() ([]byte, error) {
|
||||||
packet := <-c.router.tun.recv
|
packet := <-c.router.tun.recv
|
||||||
return packet, nil
|
return packet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send a packet to the router. You will use this when implementing a
|
||||||
|
// dummy adapter in place of real TUN - when the operating system tells you
|
||||||
|
// that a new packet is available from TUN, call this function to give it to
|
||||||
|
// Yggdrasil.
|
||||||
func (c *Core) RouterSendPacket(buf []byte) error {
|
func (c *Core) RouterSendPacket(buf []byte) error {
|
||||||
packet := append(util.GetBytes(), buf[:]...)
|
packet := append(util.GetBytes(), buf[:]...)
|
||||||
c.router.tun.send <- packet
|
c.router.tun.send <- packet
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) AWDLCreateInterface(boxPubKey string, sigPubKey string, name string) error {
|
|
||||||
fromAWDL := make(chan []byte, 32)
|
|
||||||
toAWDL := make(chan []byte, 32)
|
|
||||||
|
|
||||||
var boxPub crypto.BoxPubKey
|
|
||||||
var sigPub crypto.SigPubKey
|
|
||||||
boxPubHex, err := hex.DecodeString(boxPubKey)
|
|
||||||
if err != nil {
|
|
||||||
c.log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sigPubHex, err := hex.DecodeString(sigPubKey)
|
|
||||||
if err != nil {
|
|
||||||
c.log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
copy(boxPub[:], boxPubHex)
|
|
||||||
copy(sigPub[:], sigPubHex)
|
|
||||||
|
|
||||||
if intf, err := c.awdl.create(fromAWDL, toAWDL, &boxPub, &sigPub, name); err == nil {
|
|
||||||
if intf != nil {
|
|
||||||
c.log.Println(err)
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
c.log.Println("c.awdl.create didn't return an interface")
|
|
||||||
return errors.New("c.awdl.create didn't return an interface")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.log.Println(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Core) AWDLCreateInterfaceFromContext(context []byte, name string) error {
|
|
||||||
if len(context) < crypto.BoxPubKeyLen+crypto.SigPubKeyLen {
|
|
||||||
return errors.New("Not enough bytes in context")
|
|
||||||
}
|
|
||||||
boxPubKey := hex.EncodeToString(context[:crypto.BoxPubKeyLen])
|
|
||||||
sigPubKey := hex.EncodeToString(context[crypto.BoxPubKeyLen:])
|
|
||||||
return c.AWDLCreateInterface(boxPubKey, sigPubKey, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Core) AWDLShutdownInterface(name string) error {
|
|
||||||
return c.awdl.shutdown(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Core) AWDLRecvPacket(identity string) ([]byte, error) {
|
|
||||||
if intf := c.awdl.getInterface(identity); intf != nil {
|
|
||||||
return <-intf.toAWDL, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("AWDLRecvPacket identity not known: " + identity)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Core) AWDLSendPacket(identity string, buf []byte) error {
|
|
||||||
packet := append(util.GetBytes(), buf[:]...)
|
|
||||||
if intf := c.awdl.getInterface(identity); intf != nil {
|
|
||||||
intf.fromAWDL <- packet
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.New("AWDLSendPacket identity not known: " + identity)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Core) AWDLConnectionContext() []byte {
|
|
||||||
var context []byte
|
|
||||||
context = append(context, c.boxPub[:]...)
|
|
||||||
context = append(context, c.sigPub[:]...)
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
12
src/yggdrasil/mobile_android.go
Normal file
12
src/yggdrasil/mobile_android.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build android
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
type MobileLogger struct{}
|
||||||
|
|
||||||
|
func (nsl MobileLogger) Write(p []byte) (n int, err error) {
|
||||||
|
log.Println(string(p))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
@ -12,7 +12,12 @@ void Log(const char *text) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import "unsafe"
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
||||||
|
)
|
||||||
|
|
||||||
type MobileLogger struct {
|
type MobileLogger struct {
|
||||||
}
|
}
|
||||||
@ -23,3 +28,41 @@ func (nsl MobileLogger) Write(p []byte) (n int, err error) {
|
|||||||
C.Log(cstr)
|
C.Log(cstr)
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLCreateInterface(name string) error {
|
||||||
|
fromAWDL := make(chan []byte, 32)
|
||||||
|
toAWDL := make(chan []byte, 32)
|
||||||
|
|
||||||
|
if intf, err := c.awdl.create(fromAWDL, toAWDL, name); err == nil {
|
||||||
|
if intf != nil {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
c.log.Println("c.awdl.create didn't return an interface")
|
||||||
|
return errors.New("c.awdl.create didn't return an interface")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLShutdownInterface(name string) error {
|
||||||
|
return c.awdl.shutdown(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLRecvPacket(identity string) ([]byte, error) {
|
||||||
|
if intf := c.awdl.getInterface(identity); intf != nil {
|
||||||
|
return <-intf.toAWDL, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("AWDLRecvPacket identity not known: " + identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) AWDLSendPacket(identity string, buf []byte) error {
|
||||||
|
packet := append(util.GetBytes(), buf[:]...)
|
||||||
|
if intf := c.awdl.getInterface(identity); intf != nil {
|
||||||
|
intf.fromAWDL <- packet
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("AWDLSendPacket identity not known: " + identity)
|
||||||
|
}
|
||||||
|
@ -157,6 +157,6 @@ func (m *multicast) listen() {
|
|||||||
}
|
}
|
||||||
addr.Zone = from.Zone
|
addr.Zone = from.Zone
|
||||||
saddr := addr.String()
|
saddr := addr.String()
|
||||||
m.core.tcp.connect(saddr, "")
|
m.core.tcp.connect(saddr, addr.Zone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
src/yggdrasil/multicast_darwin.go
Normal file
28
src/yggdrasil/multicast_darwin.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
func multicastReuse(network string, address string, c syscall.RawConn) error {
|
||||||
|
var control error
|
||||||
|
var reuseport error
|
||||||
|
var recvanyif error
|
||||||
|
|
||||||
|
control = c.Control(func(fd uintptr) {
|
||||||
|
reuseport = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||||
|
|
||||||
|
// sys/socket.h: #define SO_RECV_ANYIF 0x1104
|
||||||
|
recvanyif = unix.SetsockoptInt(int(fd), syscall.SOL_SOCKET, 0x1104, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case reuseport != nil:
|
||||||
|
return reuseport
|
||||||
|
case recvanyif != nil:
|
||||||
|
return recvanyif
|
||||||
|
default:
|
||||||
|
return control
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// +build linux darwin netbsd freebsd openbsd dragonflybsd
|
// +build linux netbsd freebsd openbsd dragonflybsd
|
||||||
|
|
||||||
package yggdrasil
|
package yggdrasil
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ package yggdrasil
|
|||||||
// See version.go for version metadata format
|
// See version.go for version metadata format
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -88,7 +89,11 @@ func (iface *tcpInterface) init(core *Core, addr string, readTimeout int32) (err
|
|||||||
iface.tcp_timeout = default_tcp_timeout
|
iface.tcp_timeout = default_tcp_timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
iface.serv, err = net.Listen("tcp", addr)
|
ctx := context.Background()
|
||||||
|
lc := net.ListenConfig{
|
||||||
|
Control: iface.tcpContext,
|
||||||
|
}
|
||||||
|
iface.serv, err = lc.Listen(ctx, "tcp", addr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
iface.calls = make(map[string]struct{})
|
iface.calls = make(map[string]struct{})
|
||||||
iface.conns = make(map[tcpInfo](chan struct{}))
|
iface.conns = make(map[tcpInfo](chan struct{}))
|
||||||
@ -164,7 +169,9 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string, sintf string) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dialer := net.Dialer{}
|
dialer := net.Dialer{
|
||||||
|
Control: iface.tcpContext,
|
||||||
|
}
|
||||||
if sintf != "" {
|
if sintf != "" {
|
||||||
ief, err := net.InterfaceByName(sintf)
|
ief, err := net.InterfaceByName(sintf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
28
src/yggdrasil/tcp_darwin.go
Normal file
28
src/yggdrasil/tcp_darwin.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WARNING: This context is used both by net.Dialer and net.Listen in tcp.go
|
||||||
|
|
||||||
|
func (iface *tcpInterface) tcpContext(network, address string, c syscall.RawConn) error {
|
||||||
|
var control error
|
||||||
|
var recvanyif error
|
||||||
|
|
||||||
|
control = c.Control(func(fd uintptr) {
|
||||||
|
// sys/socket.h: #define SO_RECV_ANYIF 0x1104
|
||||||
|
recvanyif = unix.SetsockoptInt(int(fd), syscall.SOL_SOCKET, 0x1104, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case recvanyif != nil:
|
||||||
|
return recvanyif
|
||||||
|
default:
|
||||||
|
return control
|
||||||
|
}
|
||||||
|
}
|
13
src/yggdrasil/tcp_other.go
Normal file
13
src/yggdrasil/tcp_other.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// +build !darwin
|
||||||
|
|
||||||
|
package yggdrasil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WARNING: This context is used both by net.Dialer and net.Listen in tcp.go
|
||||||
|
|
||||||
|
func (iface *tcpInterface) tcpContext(network, address string, c syscall.RawConn) error {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user