mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 22:25:07 +03:00
Merge branch 'develop' of https://github.com/yggdrasil-network/yggdrasil-go into yggdrasil-v0.4.7-develop
This commit is contained in:
commit
35cc180647
20 changed files with 309 additions and 178 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -26,6 +26,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- in case of vulnerabilities.
|
||||
-->
|
||||
|
||||
## [0.4.7] - 2022-11-20
|
||||
|
||||
### Added
|
||||
|
||||
- Dropped outbound peerings will now try to reconnect after a single second, rather than waiting up to 60 seconds for the normal peer timer
|
||||
|
||||
### Changed
|
||||
|
||||
- Session encryption keys are now rotated at most once per minute, which reduces CPU usage and improves throughput on fast low latency links
|
||||
- Buffers are now reused in the session encryption handler, which improves session throughput and reduces memory allocations
|
||||
- Buffers are now reused in the router for DHT and path traffic, which improves overall routing throughput and reduces memory allocations
|
||||
|
||||
### Fixed
|
||||
|
||||
- A bug in the admin socket where requests fail unless `arguments` is specified has been fixed
|
||||
- Certificates on TLS listeners will no longer expire after a year
|
||||
- The `-address` and `-subnet` command line options now return a useful warning when no configuration is specified
|
||||
|
||||
## [0.4.6] - 2022-10-25
|
||||
|
||||
### Added
|
||||
|
|
|
@ -17,9 +17,12 @@ import (
|
|||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/RiV-chain/RiV-mesh/src/core"
|
||||
"github.com/gologme/log"
|
||||
|
||||
c "github.com/RiV-chain/RiV-mesh/src/core"
|
||||
)
|
||||
|
||||
type keySet struct {
|
||||
|
@ -41,6 +44,8 @@ func main() {
|
|||
fmt.Println("-----")
|
||||
fmt.Println("Priv:", hex.EncodeToString(newKey.priv))
|
||||
fmt.Println("Pub:", hex.EncodeToString(newKey.pub))
|
||||
logger := log.New(os.Stdout, "", log.Flags())
|
||||
core, _ := c.New(newKey.priv, logger, nil)
|
||||
addr := core.AddrForKey(newKey.pub)
|
||||
fmt.Println("IP:", net.IP(addr[:]).String())
|
||||
}
|
||||
|
|
|
@ -253,7 +253,12 @@ func run(args yggArgs, ctx context.Context) {
|
|||
return
|
||||
default:
|
||||
// No flags were provided, therefore print the list of flags to stdout.
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
|
||||
if args.getaddr || args.getsnet {
|
||||
fmt.Println("\nError: You need to specify some config data using -useconf or -useconffile.")
|
||||
}
|
||||
}
|
||||
// Have we got a working configuration? If we don't then it probably means
|
||||
// that neither -autoconf, -useconf or -useconffile were set above. Stop
|
||||
|
|
|
@ -13,8 +13,9 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
|
||||
c "github.com/RiV-chain/RiV-mesh/src/core"
|
||||
"github.com/cheggaaa/pb/v3"
|
||||
"github.com/RiV-chain/RiV-mesh/src/address"
|
||||
"github.com/gologme/log"
|
||||
)
|
||||
|
||||
var numHosts = flag.Int("hosts", 1, "number of host vars to generate")
|
||||
|
@ -35,7 +36,6 @@ func main() {
|
|||
println("Can't generate less keys than hosts.")
|
||||
return
|
||||
}
|
||||
|
||||
var keys []keySet
|
||||
for i := 0; i < *numHosts+1; i++ {
|
||||
keys = append(keys, newKey())
|
||||
|
@ -77,7 +77,9 @@ func newKey() keySet {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ip := net.IP(address.AddrForKey(pub)[:]).String()
|
||||
logger := log.New(os.Stdout, "", log.Flags())
|
||||
core, _ := c.New(priv, logger, nil)
|
||||
ip := net.IP(core.AddrForKey(pub)[:]).String()
|
||||
return keySet{priv[:], pub[:], ip}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@ import (
|
|||
"github.com/RiV-chain/RiV-mesh/src/ipv6rwc"
|
||||
"github.com/RiV-chain/RiV-mesh/src/multicast"
|
||||
"github.com/RiV-chain/RiV-mesh/src/version"
|
||||
|
||||
_ "golang.org/x/mobile/bind"
|
||||
)
|
||||
|
||||
// RiV-mesh mobile package is meant to "plug the gap" for mobile support, as
|
||||
|
@ -83,10 +81,10 @@ func (m *Mesh) StartJSON(configjson []byte) error {
|
|||
options := []multicast.SetupOption{}
|
||||
for _, intf := range m.config.MulticastInterfaces {
|
||||
options = append(options, multicast.MulticastInterface{
|
||||
Regex: regexp.MustCompile(intf.Regex),
|
||||
Beacon: intf.Beacon,
|
||||
Listen: intf.Listen,
|
||||
Port: intf.Port,
|
||||
Regex: regexp.MustCompile(intf.Regex),
|
||||
Beacon: intf.Beacon,
|
||||
Listen: intf.Listen,
|
||||
Port: intf.Port,
|
||||
Priority: uint8(intf.Priority),
|
||||
})
|
||||
}
|
||||
|
@ -159,6 +157,11 @@ func (m *Mesh) Stop() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Retry resets the peer connection timer and tries to dial them immediately.
|
||||
func (m *Mesh) RetryPeersNow() {
|
||||
m.core.RetryPeersNow()
|
||||
}
|
||||
|
||||
// GenerateConfigJSON generates mobile-friendly configuration in JSON format
|
||||
func GenerateConfigJSON() []byte {
|
||||
nc := defaults.GenerateConfig()
|
||||
|
|
|
@ -3,7 +3,7 @@ package mobile
|
|||
import "testing"
|
||||
|
||||
func TestStartYggdrasil(t *testing.T) {
|
||||
ygg := &Mesh{}
|
||||
mesh := &Mesh{}
|
||||
if err := mesh.StartAutoconfigure(); err != nil {
|
||||
t.Fatalf("Failed to start Mesh: %s", err)
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module github.com/RiV-chain/RiV-mesh
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2
|
||||
github.com/Arceliar/ironwood v0.0.0-20221115123222-ec61cea2f439
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979
|
||||
github.com/cheggaaa/pb/v3 v3.0.8
|
||||
github.com/gologme/log v1.2.0
|
||||
|
|
54
go.sum
54
go.sum
|
@ -1,15 +1,16 @@
|
|||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2 h1:Usab30pNT2i/vZvpXcN9uOr5IO1RZPcUqoGH0DIAPnU=
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk=
|
||||
github.com/Arceliar/ironwood v0.0.0-20221115123222-ec61cea2f439 h1:eOW6/XIs06TnUn9GPCnfv71CQZw8edP3u3mH3lZt6iM=
|
||||
github.com/Arceliar/ironwood v0.0.0-20221115123222-ec61cea2f439/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk=
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979 h1:WndgpSW13S32VLQ3ugUxx2EnnWmgba1kCqPkd4Gk1yQ=
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
|
@ -42,8 +43,6 @@ github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwM
|
|||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw=
|
||||
github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
|
||||
github.com/kardianos/minwinsvc v1.0.0 h1:+JfAi8IBJna0jY2dJGZqi7o15z13JelFIklJCAENALA=
|
||||
github.com/kardianos/minwinsvc v1.0.0/go.mod h1:Bgd0oc+D0Qo3bBytmNtyRKVlp85dAloLKhfxanPFFRc=
|
||||
github.com/kardianos/minwinsvc v1.0.2 h1:JmZKFJQrmTGa/WiW+vkJXKmfzdjabuEW4Tirj5lLdR0=
|
||||
github.com/kardianos/minwinsvc v1.0.2/go.mod h1:LUZNYhNmxujx2tR7FbdxqYJ9XDDoCd3MQcl1o//FWl4=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
|
@ -62,40 +61,26 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
|||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/vikulin/sctp v0.0.0-20220918193719-c8cee09143f6 h1:j8DBhVyu5IOrjL8TKrodj8hrPhu1UcDLU39WInResBg=
|
||||
github.com/vikulin/sctp v0.0.0-20220918193719-c8cee09143f6/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221007162951-ee34dc8ef4fb h1:BsQ30cGdJOu4vvpDcbGxV2lFHJI9wZ0/vEQ0tGkPwtY=
|
||||
github.com/vikulin/sctp v0.0.0-20221007162951-ee34dc8ef4fb/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221007163900-14c90ba6cef7 h1:t8SpyJRWXFn2oFCOrx41xiHW5Paq0hI3MDvfNVXmSUg=
|
||||
github.com/vikulin/sctp v0.0.0-20221007163900-14c90ba6cef7/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221007164225-10d5e6ecb1f3 h1:PjcompCCBrsiwQ6cl0bVNpBMVBsWO6u3ZGDRIsIA9is=
|
||||
github.com/vikulin/sctp v0.0.0-20221007164225-10d5e6ecb1f3/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221007165105-a2fb1402929e h1:2L3RhOd9P1uAIH32fe2Yj1VhA5m9pwQxlfNcxxaDzGk=
|
||||
github.com/vikulin/sctp v0.0.0-20221007165105-a2fb1402929e/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009173008-ba8cb1782eb2 h1:TScABL/GNdjRpUD0aG8ppV7aOjWAh/jyLic9BUMVAmU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009173008-ba8cb1782eb2/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009173321-b95fb2a7e8a8 h1:45QFbCDBaje6CtEVNzW3v961p9kg5OtkDqesrAXhr78=
|
||||
github.com/vikulin/sctp v0.0.0-20221009173321-b95fb2a7e8a8/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009175920-231a1a8f897c h1:ErkH7lmFcxa8fGsiJYZULCslf7vFCEtsmFeSSnMAyjU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009175920-231a1a8f897c/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009183851-886ddb1d294f h1:wR6HtyVHroyQ/NcKA6xnRfqbOBlqMoEtL9qxcM/2BPc=
|
||||
github.com/vikulin/sctp v0.0.0-20221009183851-886ddb1d294f/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/vikulin/sctp v0.0.0-20221009200520-ae0f2830e422 h1:KJn6ovcNlavPTgdK2uKJoonWPP3GTb8x4FyYPIrwpZw=
|
||||
github.com/vikulin/sctp v0.0.0-20221009200520-ae0f2830e422/go.mod h1:wbWp47D/qXkQrDuO8qSeUXdLN9qXNZzIgLGDQIoJlJU=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
|
@ -110,35 +95,26 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
|
||||
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e h1:zSgtO19fpg781xknwqiQPmOHaASr6E7ZVlTseLd9Fx4=
|
||||
golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210927181540-4e4d966f7476/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211011170408-caeb26a5c8c0/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@ -149,7 +125,6 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS
|
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -163,7 +138,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -183,12 +157,9 @@ golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
|||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -200,6 +171,9 @@ golang.zx2c4.com/wireguard/windows v0.4.12 h1:CUmbdWKVNzTSsVb4yUAiEwL3KsabdJkEPd
|
|||
golang.zx2c4.com/wireguard/windows v0.4.12/go.mod h1:PW4y+d9oY83XU9rRwRwrJDwEMuhVjMxu2gfD1cfzS7w=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -7,83 +7,83 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestAddress_Address_IsValid(t *testing.T) {
|
||||
func (c *Core) TestAddress_Address_IsValid(t *testing.T) {
|
||||
var address Address
|
||||
rand.Read(address[:])
|
||||
|
||||
address[0] = 0
|
||||
|
||||
if address.IsValid() {
|
||||
if c.IsValidAddress(address) {
|
||||
t.Fatal("invalid address marked as valid")
|
||||
}
|
||||
|
||||
address[0] = 0xfd
|
||||
|
||||
if address.IsValid() {
|
||||
if c.IsValidAddress(address) {
|
||||
t.Fatal("invalid address marked as valid")
|
||||
}
|
||||
|
||||
address[0] = 0xfc
|
||||
|
||||
if !address.IsValid() {
|
||||
if !c.IsValidAddress(address) {
|
||||
t.Fatal("valid address marked as invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Subnet_IsValid(t *testing.T) {
|
||||
func (c *Core) TestAddress_Subnet_IsValid(t *testing.T) {
|
||||
var subnet Subnet
|
||||
rand.Read(subnet[:])
|
||||
|
||||
subnet[0] = 0
|
||||
|
||||
if subnet.IsValid() {
|
||||
if c.IsValidSubnet(subnet) {
|
||||
t.Fatal("invalid subnet marked as valid")
|
||||
}
|
||||
|
||||
subnet[0] = 0xfc
|
||||
|
||||
if subnet.IsValid() {
|
||||
if c.IsValidSubnet(subnet) {
|
||||
t.Fatal("invalid subnet marked as valid")
|
||||
}
|
||||
|
||||
subnet[0] = 0xfd
|
||||
|
||||
if !subnet.IsValid() {
|
||||
if !c.IsValidSubnet(subnet) {
|
||||
t.Fatal("valid subnet marked as invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_AddrForKey(t *testing.T) {
|
||||
func (c *Core) TestAddress_AddrForKey(t *testing.T) {
|
||||
publicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 222, 61, 205, 18, 57, 36, 203, 181, 82, 86,
|
||||
251, 141, 171, 8, 170, 152, 227, 5, 82, 138, 184, 79, 65, 158, 110, 251,
|
||||
}
|
||||
|
||||
expectedAddress := Address{
|
||||
f, c, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
0xfc, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
}
|
||||
|
||||
if *AddrForKey(publicKey) != expectedAddress {
|
||||
if *c.AddrForKey(publicKey) != expectedAddress {
|
||||
t.Fatal("invalid address returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_SubnetForKey(t *testing.T) {
|
||||
func (c *Core) TestAddress_SubnetForKey(t *testing.T) {
|
||||
publicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 222, 61, 205, 18, 57, 36, 203, 181, 82, 86,
|
||||
251, 141, 171, 8, 170, 152, 227, 5, 82, 138, 184, 79, 65, 158, 110, 251,
|
||||
}
|
||||
|
||||
expectedSubnet := Subnet{f, d, 0, 132, 138, 96, 79, 187, 126}
|
||||
expectedSubnet := Subnet{0xfd, 0, 132, 138, 96, 79, 187, 126}
|
||||
|
||||
if *SubnetForKey(publicKey) != expectedSubnet {
|
||||
if *c.SubnetForKey(publicKey) != expectedSubnet {
|
||||
t.Fatal("invalid subnet returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Address_GetKey(t *testing.T) {
|
||||
func (c *Core) TestAddress_Address_GetKey(t *testing.T) {
|
||||
address := Address{
|
||||
f, c, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
0xfc, 0, 132, 138, 96, 79, 187, 126, 67, 132, 101, 219, 141, 182, 104, 149,
|
||||
}
|
||||
|
||||
expectedPublicKey := ed25519.PublicKey{
|
||||
|
@ -93,13 +93,13 @@ func TestAddress_Address_GetKey(t *testing.T) {
|
|||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
}
|
||||
|
||||
if !bytes.Equal(address.GetKey(), expectedPublicKey) {
|
||||
if !bytes.Equal(c.GetAddressKey(address), expectedPublicKey) {
|
||||
t.Fatal("invalid public key returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddress_Subnet_GetKey(t *testing.T) {
|
||||
subnet := Subnet{f, d, 0, 132, 138, 96, 79, 187, 126}
|
||||
func (c *Core) TestAddress_Subnet_GetKey(t *testing.T) {
|
||||
subnet := Subnet{0xfd, 0, 132, 138, 96, 79, 187, 126}
|
||||
|
||||
expectedPublicKey := ed25519.PublicKey{
|
||||
189, 186, 207, 216, 34, 64, 255, 255,
|
||||
|
@ -108,7 +108,7 @@ func TestAddress_Subnet_GetKey(t *testing.T) {
|
|||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
}
|
||||
|
||||
if !bytes.Equal(subnet.GetKey(), expectedPublicKey) {
|
||||
if !bytes.Equal(c.GetSubnetKey(subnet), expectedPublicKey) {
|
||||
t.Fatal("invalid public key returned")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,21 +188,25 @@ func (c *Core) SetLogger(log Logger) {
|
|||
// This adds the peer to the peer list, so that they will be called again if the
|
||||
// connection drops.
|
||||
|
||||
func (c *Core) AddPeer(peer string, intf string) error {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
func (c *Core) AddPeer(uri string, sourceInterface string) error {
|
||||
var known bool
|
||||
phony.Block(c, func() {
|
||||
_, known = c.config._peers[Peer{uri, sourceInterface}]
|
||||
})
|
||||
if known {
|
||||
return fmt.Errorf("peer already configured")
|
||||
}
|
||||
u, err := url.Parse(peer)
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
c.log.Errorln("Failed to parse peer url:", peer, err)
|
||||
return err
|
||||
}
|
||||
if err := c.CallPeer(u, intf); err != nil {
|
||||
c.log.Errorln("Failed to add peer:", err)
|
||||
info, err := c.links.call(u, sourceInterface, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
phony.Block(c, func() {
|
||||
c.config._peers[Peer{uri, sourceInterface}] = &info
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -245,7 +249,7 @@ func (c *Core) RemovePeers() error {
|
|||
// This does not add the peer to the peer list, so if the connection drops, the
|
||||
// peer will not be called again automatically.
|
||||
func (c *Core) CallPeer(u *url.URL, sintf string) error {
|
||||
_, err := c.links.call(u, sintf)
|
||||
_, err := c.links.call(u, sintf, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
// The Core object represents the Mesh node. You should create a Core
|
||||
// object for each Mesh node you plan to run.
|
||||
type Core struct {
|
||||
address Address
|
||||
address Address
|
||||
// This is the main data structure that holds everything else for a node
|
||||
// We're going to keep our own copy of the provided config - that way we can
|
||||
// guarantee that it will be covered by the mutex
|
||||
|
@ -123,6 +123,13 @@ func (c *Core) _addPeerLoop() {
|
|||
})
|
||||
}
|
||||
|
||||
func (c *Core) RetryPeersNow() {
|
||||
if c.addPeerTimer != nil && !c.addPeerTimer.Stop() {
|
||||
<-c.addPeerTimer.C
|
||||
}
|
||||
c.Act(nil, c._addPeerLoop)
|
||||
}
|
||||
|
||||
// Stop shuts down the Mesh node.
|
||||
func (c *Core) Stop() {
|
||||
phony.Block(c, func() {
|
||||
|
|
107
src/core/link.go
107
src/core/link.go
|
@ -22,64 +22,69 @@ import (
|
|||
|
||||
// linkInfo is used as a map key
|
||||
type linkInfo struct {
|
||||
linkType string // Type of link, e.g. TCP, AWDL
|
||||
local string // Local name or address
|
||||
remote string // Remote name or address
|
||||
linkType string // Type of link, e.g. TCP, AWDL
|
||||
local string // Local name or address
|
||||
remote string // Remote name or address
|
||||
}
|
||||
|
||||
type linkDial struct {
|
||||
url *url.URL
|
||||
sintf string
|
||||
}
|
||||
|
||||
type link struct {
|
||||
lname string
|
||||
links *links
|
||||
conn *linkConn
|
||||
options linkOptions
|
||||
info linkInfo
|
||||
incoming bool
|
||||
force bool
|
||||
lname string
|
||||
links *links
|
||||
conn *linkConn
|
||||
options linkOptions
|
||||
info linkInfo
|
||||
incoming bool
|
||||
force bool
|
||||
}
|
||||
|
||||
type linkOptions struct {
|
||||
pinnedEd25519Keys map[keyArray]struct{}
|
||||
pinnedEd25519Keys map[keyArray]struct{}
|
||||
priority uint8
|
||||
}
|
||||
|
||||
type Listener struct {
|
||||
net.Listener
|
||||
closed chan struct{}
|
||||
net.Listener
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
func (l *Listener) Close() error {
|
||||
err := l.Listener.Close()
|
||||
<-l.closed
|
||||
return err
|
||||
err := l.Listener.Close()
|
||||
<-l.closed
|
||||
return err
|
||||
}
|
||||
|
||||
func (l *links) shutdown() {
|
||||
phony.Block(l.tcp, func() {
|
||||
for l := range l.tcp._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
phony.Block(l.tls, func() {
|
||||
for l := range l.tls._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
phony.Block(l.unix, func() {
|
||||
for l := range l.unix._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
phony.Block(l.tcp, func() {
|
||||
for l := range l.tcp._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
phony.Block(l.tls, func() {
|
||||
for l := range l.tls._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
phony.Block(l.unix, func() {
|
||||
for l := range l.unix._listeners {
|
||||
_ = l.Close()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (l *links) isConnectedTo(info linkInfo) bool {
|
||||
var isConnected bool
|
||||
phony.Block(l, func() {
|
||||
_, isConnected = l._links[info]
|
||||
})
|
||||
return isConnected
|
||||
var isConnected bool
|
||||
phony.Block(l, func() {
|
||||
_, isConnected = l._links[info]
|
||||
})
|
||||
return isConnected
|
||||
}
|
||||
|
||||
func (l *links) create(conn net.Conn, name string, info linkInfo, incoming, force bool, options linkOptions) error {
|
||||
func (l *links) create(conn net.Conn, dial *linkDial, name string, info linkInfo, incoming, force bool, options linkOptions) error {
|
||||
intf := link{
|
||||
conn: &linkConn{
|
||||
Conn: conn,
|
||||
|
@ -93,14 +98,14 @@ func (l *links) create(conn net.Conn, name string, info linkInfo, incoming, forc
|
|||
force: force,
|
||||
}
|
||||
go func() {
|
||||
if err := intf.handler(); err != nil {
|
||||
if err := intf.handler(dial); err != nil {
|
||||
l.core.log.Errorf("Link handler %s error (%s): %s", name, conn.RemoteAddr(), err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (intf *link) handler() error {
|
||||
func (intf *link) handler(dial *linkDial) error {
|
||||
defer intf.conn.Close() // nolint:errcheck
|
||||
|
||||
// Don't connect to this link more than once.
|
||||
|
@ -203,6 +208,30 @@ func (intf *link) handler() error {
|
|||
intf.links.core.log.Infof("Disconnected %s %s: %s, source %s; error: %s",
|
||||
dir, strings.ToUpper(intf.info.linkType), remoteStr, localStr, err)
|
||||
}
|
||||
|
||||
if !intf.incoming && dial != nil {
|
||||
// The connection was one that we dialled, so wait a second and try to
|
||||
// dial it again.
|
||||
var retry func(attempt int)
|
||||
retry = func(attempt int) {
|
||||
// intf.links.core.log.Infof("Retrying %s (attempt %d of 5)...", dial.url.String(), attempt)
|
||||
errch := make(chan error, 1)
|
||||
if _, err := intf.links.call(dial.url, dial.sintf, errch); err != nil {
|
||||
return
|
||||
}
|
||||
if err := <-errch; err != nil {
|
||||
if attempt < 3 {
|
||||
time.AfterFunc(time.Second, func() {
|
||||
retry(attempt + 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
time.AfterFunc(time.Second, func() {
|
||||
retry(1)
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ package core
|
|||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
@ -51,9 +51,12 @@ func (l *links) init(c *Core) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
|
||||
info := linkInfoFor(u.Scheme, sintf, u.Host)
|
||||
func (l *links) call(u *url.URL, sintf string, errch chan<- error) (info linkInfo, err error) {
|
||||
info = linkInfoFor(u.Scheme, sintf, u.Host)
|
||||
if l.isConnectedTo(info) {
|
||||
if errch != nil {
|
||||
close(errch) // already connected, no error
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
options := linkOptions{
|
||||
|
@ -62,6 +65,9 @@ func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
|
|||
for _, pubkey := range u.Query()["key"] {
|
||||
sigPub, err := hex.DecodeString(pubkey)
|
||||
if err != nil {
|
||||
if errch != nil {
|
||||
close(errch)
|
||||
}
|
||||
return info, fmt.Errorf("pinned key contains invalid hex characters")
|
||||
}
|
||||
var sigPubKey keyArray
|
||||
|
@ -71,6 +77,9 @@ func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
|
|||
if p := u.Query().Get("priority"); p != "" {
|
||||
pi, err := strconv.ParseUint(p, 10, 8)
|
||||
if err != nil {
|
||||
if errch != nil {
|
||||
close(errch)
|
||||
}
|
||||
return info, fmt.Errorf("priority invalid: %w", err)
|
||||
}
|
||||
options.priority = uint8(pi)
|
||||
|
@ -78,15 +87,27 @@ func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
|
|||
switch info.linkType {
|
||||
case "tcp":
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.tcp.dial(u, options, sintf); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial TCP %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
case "socks":
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.socks.dial(u, options); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial SOCKS %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -109,30 +130,57 @@ func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
|
|||
}
|
||||
}
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.tls.dial(u, options, sintf, tlsSNI); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial TLS %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
case "unix":
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.unix.dial(u, options, sintf); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial UNIX %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
case "sctp":
|
||||
go func() {
|
||||
case "sctp":
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.sctp.dial(u, options, sintf); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial SCTP %s: %s\n", u.Host, err)
|
||||
}
|
||||
}()
|
||||
l.core.log.Warnf("Failed to dial SCTP %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
case "mpath":
|
||||
go func() {
|
||||
if errch != nil {
|
||||
defer close(errch)
|
||||
}
|
||||
if err := l.mpath.dial(u, options, sintf); err != nil && err != io.EOF {
|
||||
l.core.log.Warnf("Failed to dial MPATH %s: %s\n", u.Host, err)
|
||||
if errch != nil {
|
||||
errch <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
default:
|
||||
if errch != nil {
|
||||
close(errch)
|
||||
}
|
||||
return info, errors.New("unknown call scheme: " + u.Scheme)
|
||||
}
|
||||
return info, nil
|
||||
|
@ -148,8 +196,8 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
|||
listener, err = l.tls.listen(u, sintf)
|
||||
case "unix":
|
||||
listener, err = l.unix.listen(u, sintf)
|
||||
case "sctp":
|
||||
listener, err = l.sctp.listen(u, sintf)
|
||||
case "sctp":
|
||||
listener, err = l.sctp.listen(u, sintf)
|
||||
case "mpath":
|
||||
listener, err = l.mpath.listen(u, sintf)
|
||||
default:
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/getlantern/multipath"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
|
@ -39,8 +40,12 @@ func (l *linkMPATH) dial(url *url.URL, options linkOptions, sintf string) error
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uri := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
return l.handler(uri, info, conn, options, false, false)
|
||||
name := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
sintf: sintf,
|
||||
}
|
||||
return l.handler(dial, name, info, conn, options, false, false)
|
||||
}
|
||||
|
||||
func (l *linkMPATH) listen(url *url.URL, sintf string) (*Listener, error) {
|
||||
|
@ -74,10 +79,10 @@ func (l *linkMPATH) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
cancel()
|
||||
break
|
||||
}
|
||||
addr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
name := fmt.Sprintf("mpath://%s", addr)
|
||||
info := linkInfoFor("mpath", sintf, strings.SplitN(addr.IP.String(), "%", 2)[0])
|
||||
if err = l.handler(name, info, conn, linkOptions{}, true, addr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
raddr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
name := fmt.Sprintf("mpath://%s", raddr)
|
||||
info := linkInfoFor("mpath", sintf, strings.SplitN(raddr.IP.String(), "%", 2)[0])
|
||||
if err = l.handler(nil, name, info, conn, linkOptionsForListener(url), true, raddr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
l.core.log.Errorln("Failed to create inbound link:", err)
|
||||
}
|
||||
}
|
||||
|
@ -88,9 +93,10 @@ func (l *linkMPATH) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
func (l *linkMPATH) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
func (l *linkMPATH) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
return l.links.create(
|
||||
conn, // connection
|
||||
dial, // connection URL
|
||||
name, // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
|
@ -146,7 +152,7 @@ func (l *linkMPATH) connFor(url *url.URL, sinterfaces string) (net.Conn, error)
|
|||
if sinterfaces != "" {
|
||||
sintfarray := strings.Split(sinterfaces, ",")
|
||||
for _, dst := range remoteTargets {
|
||||
for _, sintf := range sintfarray {
|
||||
for _, sintf := range sintfarray {
|
||||
ief, err := net.InterfaceByName(sintf)
|
||||
if err != nil {
|
||||
l.core.log.Errorln("interface %s not found", sintf)
|
||||
|
|
|
@ -5,12 +5,12 @@ package core
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
sctp "github.com/vikulin/sctp"
|
||||
|
@ -47,7 +47,7 @@ func (l *linkSCTP) dial(url *url.URL, options linkOptions, sintf string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
raddress := l.getAddress(dst.String()+":"+port)
|
||||
raddress := l.getAddress(dst.String() + ":" + port)
|
||||
var conn net.Conn
|
||||
laddress := l.getAddress("0.0.0.0:0")
|
||||
conn, err = sctp.NewSCTPConnection(laddress, laddress.AddressFamily, sctp.InitMsg{NumOstreams: 2, MaxInstreams: 2, MaxAttempts: 2, MaxInitTimeout: 5}, sctp.OneToOne, false)
|
||||
|
@ -63,7 +63,11 @@ func (l *linkSCTP) dial(url *url.URL, options linkOptions, sintf string) error {
|
|||
//l.core.log.Printf("Read buffer %d", rbuf)
|
||||
//l.core.log.Printf("Write buffer %d", wbuf)
|
||||
conn.(*sctp.SCTPConn).SetEvents(sctp.SCTP_EVENT_DATA_IO)
|
||||
return l.handler(url.String(), info, conn, options, false, false)
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
sintf: sintf,
|
||||
}
|
||||
return l.handler(dial, url.String(), info, conn, options, false, false)
|
||||
}
|
||||
|
||||
func (l *linkSCTP) listen(url *url.URL, sintf string) (*Listener, error) {
|
||||
|
@ -102,9 +106,9 @@ func (l *linkSCTP) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
}
|
||||
addr := conn.RemoteAddr().(*sctp.SCTPAddr)
|
||||
ips, err := json.Marshal(addr.IPAddrs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
name := fmt.Sprintf("sctp://%s", ips)
|
||||
info := linkInfoFor("sctp", sintf, string(ips))
|
||||
//conn.(*sctp.SCTPConn).SetWriteBuffer(324288)
|
||||
|
@ -113,8 +117,8 @@ func (l *linkSCTP) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
rbuf, _ := conn.(*sctp.SCTPConn).GetReadBuffer()
|
||||
|
||||
l.core.log.Printf("Read buffer %d", rbuf)
|
||||
l.core.log.Printf("Write buffer %d", wbuf)
|
||||
if err = l.handler(name, info, conn, linkOptions{}, true, addr.IPAddrs[0].IP.IsLinkLocalUnicast()); err != nil {
|
||||
l.core.log.Printf("Write buffer %d", wbuf)
|
||||
if err = l.handler(nil, name, info, conn, linkOptionsForListener(url), true, addr.IPAddrs[0].IP.IsLinkLocalUnicast()); err != nil {
|
||||
l.core.log.Errorln("Failed to create inbound link:", err)
|
||||
}
|
||||
}
|
||||
|
@ -125,9 +129,10 @@ func (l *linkSCTP) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
func (l *linkSCTP) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming bool, force bool) error {
|
||||
func (l *linkSCTP) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
return l.links.create(
|
||||
conn, // connection
|
||||
dial, // connection URL
|
||||
name, // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
|
@ -161,7 +166,7 @@ func (l *linkSCTP) getAddress(host string) *sctp.SCTPAddr {
|
|||
}
|
||||
for _, i := range strings.Split(ip, ",") {
|
||||
if a, err := net.ResolveIPAddr("ip", i); err == nil {
|
||||
fmt.Sprintf("Resolved address '%s' to %s", i, a)
|
||||
l.core.log.Printf("Resolved address '%s' to %s", i, a)
|
||||
ips = append(ips, *a)
|
||||
} else {
|
||||
l.core.log.Errorln("Error resolving address '%s': %v", i, err)
|
||||
|
|
|
@ -37,16 +37,20 @@ func (l *linkSOCKS) dial(url *url.URL, options linkOptions) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.handler(url.String(), info, conn, options, false)
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
}
|
||||
return l.handler(dial, info, conn, options, false)
|
||||
}
|
||||
|
||||
func (l *linkSOCKS) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming bool) error {
|
||||
func (l *linkSOCKS) handler(dial *linkDial, info linkInfo, conn net.Conn, options linkOptions, incoming bool) error {
|
||||
return l.links.create(
|
||||
conn, // connection
|
||||
name, // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
false, // not forced
|
||||
options, // connection options
|
||||
conn, // connection
|
||||
dial, // connection URL
|
||||
dial.url.String(), // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
false, // not forced
|
||||
options, // connection options
|
||||
)
|
||||
}
|
||||
|
|
|
@ -47,8 +47,12 @@ func (l *linkTCP) dial(url *url.URL, options linkOptions, sintf string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uri := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
return l.handler(uri, info, conn, options, false, false)
|
||||
name := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
sintf: sintf,
|
||||
}
|
||||
return l.handler(dial, name, info, conn, options, false, false)
|
||||
}
|
||||
|
||||
func (l *linkTCP) listen(url *url.URL, sintf string) (*Listener, error) {
|
||||
|
@ -86,7 +90,7 @@ func (l *linkTCP) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
raddr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
name := fmt.Sprintf("tcp://%s", raddr)
|
||||
info := linkInfoFor("tcp", sintf, tcpIDFor(laddr, raddr))
|
||||
if err = l.handler(name, info, conn, linkOptionsForListener(url), true, raddr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
if err = l.handler(nil, name, info, conn, linkOptionsForListener(url), true, raddr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
l.core.log.Errorln("Failed to create inbound link:", err)
|
||||
}
|
||||
}
|
||||
|
@ -97,9 +101,10 @@ func (l *linkTCP) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
func (l *linkTCP) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
func (l *linkTCP) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
return l.links.create(
|
||||
conn, // connection
|
||||
dial, // connection URL
|
||||
name, // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
|
|
|
@ -69,8 +69,12 @@ func (l *linkTLS) dial(url *url.URL, options linkOptions, sintf, sni string) err
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
uri := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
return l.handler(uri, info, conn, options, false, false)
|
||||
name := strings.TrimRight(strings.SplitN(url.String(), "?", 2)[0], "/")
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
sintf: sintf,
|
||||
}
|
||||
return l.handler(dial, name, info, conn, options, false, false)
|
||||
}
|
||||
|
||||
func (l *linkTLS) listen(url *url.URL, sintf string) (*Listener, error) {
|
||||
|
@ -109,7 +113,7 @@ func (l *linkTLS) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
raddr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
name := fmt.Sprintf("tls://%s", raddr)
|
||||
info := linkInfoFor("tls", sintf, tcpIDFor(laddr, raddr))
|
||||
if err = l.handler(name, info, conn, linkOptionsForListener(url), true, raddr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
if err = l.handler(nil, name, info, conn, linkOptionsForListener(url), true, raddr.IP.IsLinkLocalUnicast()); err != nil {
|
||||
l.core.log.Errorln("Failed to create inbound link:", err)
|
||||
}
|
||||
}
|
||||
|
@ -120,20 +124,18 @@ func (l *linkTLS) listen(url *url.URL, sintf string) (*Listener, error) {
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
// RFC5280 section 4.1.2.5
|
||||
var notAfterNeverExpires = time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC)
|
||||
|
||||
func (l *linkTLS) generateConfig() (*tls.Config, error) {
|
||||
certBuf := &bytes.Buffer{}
|
||||
|
||||
// TODO: because NotAfter is finite, we should add some mechanism to
|
||||
// regenerate the certificate and restart the listeners periodically
|
||||
// for nodes with very high uptimes. Perhaps regenerate certs and restart
|
||||
// listeners every few months or so.
|
||||
cert := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: hex.EncodeToString(l.links.core.public[:]),
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365),
|
||||
NotAfter: notAfterNeverExpires,
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
|
@ -167,6 +169,6 @@ func (l *linkTLS) generateConfig() (*tls.Config, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (l *linkTLS) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
return l.tcp.handler(name, info, conn, options, incoming, force)
|
||||
func (l *linkTLS) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming, force bool) error {
|
||||
return l.tcp.handler(dial, name, info, conn, options, incoming, force)
|
||||
}
|
||||
|
|
|
@ -45,7 +45,10 @@ func (l *linkUNIX) dial(url *url.URL, options linkOptions, _ string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.handler(url.String(), info, conn, options, false)
|
||||
dial := &linkDial{
|
||||
url: url,
|
||||
}
|
||||
return l.handler(dial, url.String(), info, conn, options, false)
|
||||
}
|
||||
|
||||
func (l *linkUNIX) listen(url *url.URL, _ string) (*Listener, error) {
|
||||
|
@ -74,7 +77,7 @@ func (l *linkUNIX) listen(url *url.URL, _ string) (*Listener, error) {
|
|||
break
|
||||
}
|
||||
info := linkInfoFor("unix", "", url.String())
|
||||
if err = l.handler(url.String(), info, conn, linkOptionsForListener(url), true); err != nil {
|
||||
if err = l.handler(nil, url.String(), info, conn, linkOptionsForListener(url), true); err != nil {
|
||||
l.core.log.Errorln("Failed to create inbound link:", err)
|
||||
}
|
||||
}
|
||||
|
@ -85,9 +88,10 @@ func (l *linkUNIX) listen(url *url.URL, _ string) (*Listener, error) {
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
func (l *linkUNIX) handler(name string, info linkInfo, conn net.Conn, options linkOptions, incoming bool) error {
|
||||
func (l *linkUNIX) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming bool) error {
|
||||
return l.links.create(
|
||||
conn, // connection
|
||||
dial, // connection URL
|
||||
name, // connection name
|
||||
info, // connection info
|
||||
incoming, // not incoming
|
||||
|
|
|
@ -30,6 +30,7 @@ type Multicast struct {
|
|||
_isOpen bool
|
||||
_listeners map[string]*listenerInfo
|
||||
_interfaces map[string]*interfaceInfo
|
||||
_timer *time.Timer
|
||||
config struct {
|
||||
_groupAddr GroupAddress
|
||||
_interfaces map[MulticastInterface]struct{}
|
||||
|
@ -206,6 +207,15 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
|||
return interfaces
|
||||
}
|
||||
|
||||
func (m *Multicast) AnnounceNow() {
|
||||
phony.Block(m, func() {
|
||||
if m._timer != nil && !m._timer.Stop() {
|
||||
<-m._timer.C
|
||||
}
|
||||
m.Act(nil, m._announce)
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Multicast) _announce() {
|
||||
if !m._isOpen {
|
||||
return
|
||||
|
@ -328,7 +338,7 @@ func (m *Multicast) _announce() {
|
|||
break
|
||||
}
|
||||
}
|
||||
time.AfterFunc(time.Second, func() {
|
||||
m._timer = time.AfterFunc(time.Second, func() {
|
||||
m.Act(nil, m._announce)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue