Implement IPv6 multicast again (fixes #346)

This commit is contained in:
Jakob Borg committed 2014-08-17 15:14:44 +02:00
1 parent a1fd07b27c
commit d657bc4e3d
9 files changed
+151 -52

No files matched your search

+1 -1
View File
@@ -73,7 +73,7 @@ func init() {
bs, _ = ioutil.ReadAll(gr)
Assets["favicon.png"] = bs
bs, _ = hex.DecodeString("1f8b080000096e8800ffec7d6b77dc36b2e0f7fc0ab8ef249666c56ec9763cbb8aa4bbb2e44c9487ed23d9379bcdc9ce4193e86e44244103a4e41e45f3dbb7aac0f7a3c956cbb6eebdf9608b4dbcaa0a5585aa02503c7874fafae4ed2f6f5eb2451cf8475f1c3c729c2f261376a2a2a596f345ccb64eb6d993ddbd67ec7b7ea9a6ec85d273c6430f6a84b196d32456dab02d23048b17829dbc7ef5f6fcecc5bbb7afcf2fd84cfa627b8cdd1dfb3ea3ee0cd3c2087d25bc317b6704533368260d332ad1ae60aef204839f73752574283c365dc260eca7b3b78e8997bec0be7ce98ad0e0703c662e944e059ba904409221c1f0e3d9c9cb57172f69f8f1178e03582172cce7e1fc7024c2110be70e8fa2c39159862e0c1fcee9958b1829df17fa707491959cc4da1f31d7e7c61c8eb092aff8e508bb14dc3bfa82b18340c49cb90bae8d880f47493c73fee7a82858c471e488f789bc3a1cfd1fe7ddb173a28288c772ea0be816461421b43a7b7928bcb928b50b79200e4757525c474ac7a5aad7d28b17879eb8023238f463071097b1e4be635cee8bc3bdf16ea3234f1857cb28962a2cf5d5a8c69378a174a3862fc34b98381f2806c5b19bc44cbad8d3428bd9e168c6aff0e73802421e7d810d6219fbe2282722fb83dddce03cbf82f97d05236d6ddfde1e4c6cad7c00dbd954a9d8c49a4713d79849fe6b1cc8700c6f46291cc80d6621443caa77a08106d77cb9a232fd66f132028c63f121c691a884b1a9f296ec861e198bb8e701f4ce54c5b10af6d9df76a30fdfa46533a09033e381f497fb6cf49df0af442c5dce5e89448c7658fe62871d6b989a1d6678681c607d39b35ddc7e417f167b3b6cf104fe3d857fcfe0dfd7f9f0d521ce2d5ad0f706a325feff280d10703d97a113ab689fed8dbf1641a5ee1849e3042a5426e2209bad60fd24425fedb09f54c85df80b4ac128901500f204245a0a0d205e03847937b52138c8010a9e8722ed1dc52455b13e42ae6e96e2ec7497ce8057ba4bf39ebd953db796e63d7b3915a64a7b425bda852aace1e5abb9aa91799fed7e53e5abd21beac6f9ba60af481989c2ba8f1c0ceae2aa3e8034b1132a679a80be8af3a1e835b1b783ec6d41ab3504c4fc2408f3369e3491cf612e650852249ca9afdccb0c0e903aab6480fb33fec81987343ab04e5130e5eee55ca332c6519406f0e7d3ad274f9fefb027cf76f1bfbded6faa14d4dc9389d9674f4bc867f4d98b3eb067c5fb8c904fe0f593ecf56d1d2f60b370ec71d069353ef7c50ca0dd2d18bd82dede6ef19a389ffb728ef44724bfe9a75546e06c8d68d217e7823d92012a741ec62d9200cb57deec7a2163e190cc60d36bd08115dd732d2cf59fedeeb6f6e435d498c5ff0928b13e28bcb109b8ef3b152a76029436fedf81f024675b01ff90d2f46fcfff167dd8ce3b48e50a0c8008d404b0f4917d5396bebc326393bf02ef83191033cef26580c1221be38a22c6f3f17e5e97fd1588a241cb4c61cd67d102286d40a81820a1ae194ed5540b7e69d044f01534d722d20adaf8c08213038b37d81ad7325e947bb4fc64c6ecaf93fc758d081ac894cdca6dce8e07131241301226d64af8e28030c4224f5ed56d8d9757b0d4929d7174308172bb848221c6deaa08444a33b461f05dc8af7253845f6189fd836a287bf4c48c273e580cd0bda07a72ce69ddb72b1c419076825070208e4ecb706d04e9a98ee14c35d87b009b0ce65909eab71133dab58f0e09ccf3676401b00571e6e1e8e99311b3d6ca686fef6fa3096087bde74345b571b013b6901e685de7032cc86d264394b74efc52f30cf9d223c96d8e179908487809164212cd41eb88b370a6c6a1b82ea14f15c1a68d5598da07f6476e014ee3301b001fe15f41706b7e5853128cd4cb7ca0adedea00651acffd65b440eb89e54f8ebb10571afe26d128a3d9572230b9fc179d80488406d607513c3957dc4fe07fa10d4cfae1e8e6a68c2ed630f1edede8e89d7d0b3cc66ebe4c6b7f795b9d221a68624950a2e4c49755baa6b8785a459eba0eabd8f29430ff36aad703b69dcfd10e463d93fe28f752c3f1e8a527630be0fbafc229d0e3609a733248708cd49ac23f5e19bf60947cdc408449054842e32807b53c87a03ccf45a4700e7b276ee179b519aba370ec790cbb83d55de9655a1521ae12b50f22148a41100155ae85a54c0f54d8651f3c3921e595f4506cd6801a1687f8c22a6f33087457cd7bc0cebabb1b19e5702abed7e898f641b380a5e6ecf463d2d02c9218197810d06a36eb85d8767737fac13a1e731d0f64c319545ff4c0736e7bfc9814e453950c0319566e1d3b2288e2659ff4609f2b803e98247ebbf62c4ad2851f1f6079b1ab7dc7426deba379f0add4268675fe7a87a9d05f3270ceaf4326672c14ae3086ebe5372ca529bbe63a44bb2935250a4b0417c447d0ff4ccecf42f4d873350d1d1776410518df093c67ef4979752d95031d84cfe87f271db6ba22d4eb22ad3daa75b0785a5ad32a75285830ca7804dc4ae1090f0caca74739edba0740f3abaef0a3d214be5d60ec096990683296d8821b361502dc097e8571a82406730f4c51177c3168e18d5911dd08129c861430b43ad34a148d0203a3daf5b864c554a6be1b7cf43f6b56ca003b058d1313946d141681bb985a469f5492eb264483a57c90b699fc306a99ccea8bcacfd28fc272ae0a8798273ed8c9c0cb35d6af3079d61f362c966772a7d9161ad7e83b6d173db40ac4f355f2e0a05b1c8d98f490dee9085298d592914ad1cd0d3639c1822d7c1a9f9d82354c53083f058f6d9fe8dde0df1f01ec9acdb952ea2af5a02608619be8d5aa916957b1dc800e3e8f4c66d0456093610cf1df2af866d620be04c4fe22434f7c4083b4d1fd004bb96c70314b25a0cded6d5f5f851c941c0e24a70127d05d58725ec43c4e0a82b742d834c4f34e9ceb8500fb3b092f43b266dfd987a6853dbc2f03ac180940f9c23e6cd497cb43ab9a2fd2a7fede1a7d800a6ce3a00e182820dc3310635b3737d8ef1ba15d601f3e172596ff72bb1dbab521975e2b47b7837d06953f21cc5d2535c7c6be82f5af2ae675fd994a7ea677ca225795f24c7a592ec68dd186acabf58af5a04fbba0dbc053b909ab4561d3df26d69244a09da8711668692fd55d4558b8e85ffd606a7b57be7cf528f902d0f78a81bd1c710ca3a4818b923683f65e274e936ea436c7d706c81c1589b007ef6fa9e63d207c2ab570917e1be19d59b601f86dfeaf29257f1bcbf08afbb28b7b069325b56a1d23e77d7479a9b5da902ced387c4eb698fb6adae70eff1dea70bf2dd8711f449853efdf4a5f18f607e3fe355f9a57493015faf6b6a1bf650c10a6c3efb07f7574f662195367531972e4be179f8fbe0b15f491f747e57e3ceafad8f93d1197fa7a40b4757d95780e863d7cc5fbc275afc1ed7b3d23576f130277d7e71d8a2a04f7d64ec011dbad8680d435fabe85Line truncated
bs, _ = hex.DecodeString("1f8b080000096e8800ffec7d6b77dc36b2e0f7fc0ab8ef249666c56ec9763cbb8aa4bbb2e44c9487ed23d9379bcdc9ce4193e86e44244103a4e41e45f3dbb7aac0f7a3c956cbb6eebdf9608b4dbcaa0a5585aa02503c7874fafae4ed2f6f5eb2451cf8475f1c3c729c2f261376a2a2a596f345ccb64eb6d993ddbd67ec7b7ea9a6ec85d273c6430f6a84b196d32456dab02d23048b17829dbc7ef5f6fcecc5bbb7afcf2fd84cfa627b8cdd1dfb3ea3ee0cd3c2087d25bc317b6704533368260d332ad1ae60aef204839f73752574283c365dc260eca7b3b78e8997bec0be7ce98ad0e0703c662e944e059ba904409221c1f0e3d9c9cb57172f69f8f1178e03582172cce7e1fc7024c2110be70e8fa2c39159862e0c1fcee9958b1829df17fa707491959cc4da1f31d7e7c61c8eb092aff8e508bb14dc3bfa82b18340c49cb90bae8d880f47493c73fee7a82858c471e488f789bc3a1cfd1fe7ddb173a28288c772ea0be816461421b43a7b7928bcb928b50b79200e4757525c474ac7a5aad7d28b17879eb8023238f463071097b1e4be635cee8bc3bdf16ea3234f1857cb28962a2cf5d5a8c69378a174a3862fc34b98381f2806c5b19bc44cbad8d3428bd9e168c6aff0e73802421e7d810d6219fbe2282722fb83dddce03cbf82f97d05236d6ddfde1e4c6cad7c00dbd954a9d8c49a4713d79849fe6b1cc8700c6f46291cc80d6621443caa77a08106d77cb9a232fd66f132028c63f121c691a884b1a9f296ec861e198bb8e701f4ce54c5b10af6d9df76a30fdfa46533a09033e381f497fb6cf49df0af442c5dce5e89448c7658fe62871d6b989a1d6678681c607d39b35ddc7e417f167b3b6cf104fe3d857fcfe0dfd7f9f0d521ce2d5ad0f706a325feff280d10703d97a113ab689fed8dbf1641a5ee1849e3042a5426e2209bad60fd24425fedb09f54c85df80b4ac128901500f204245a0a0d205e03847937b52138c8010a9e8722ed1dc52455b13e42ae6e96e2ec7497ce8057ba4bf39ebd953db796e63d7b3915a64a7b425bda852aace1e5abb9aa91799fed7e53e5abd21beac6f9ba60af481989c2ba8f1c0ceae2aa3e8034b1132a679a80be8af3a1e835b1b783ec6d41ab3504c4fc2408f3369e3491cf612e650852249ca9afdccb0c0e903aab6480fb33fec81987343ab04e5130e5eee55ca332c6519406f0e7d3ad274f9fefb027cf76f1bfbded6faa14d4dc9389d9674f4bc867f4d98b3eb067c5fb8c904fe0f593ecf56d1d2f60b370ec71d069353ef7c50ca0dd2d18bd82dede6ef19a389ffb728ef44724bfe9a75546e06c8d68d217e7823d92012a741ec62d9200cb57deec7a2163e190cc60d36bd08115dd732d2cf59fedeeb6f6e435d498c5ff0928b13e28bcb109b8ef3b152a76029436fedf81f024675b01ff90d2f46fcfff167dd8ce3b48e50a0c8008d404b0f4917d5396bebc326393bf02ef83191033cef26580c1221be38a22c6f3f17e5e97fd1588a241cb4c61cd67d102286d40a81820a1ae194ed5540b7e69d044f01534d722d20adaf8c08213038b37d81ad7325e947bb4fc64c6ecaf93fc758d081ac894cdca6dce8e07131241301226d64af8e28030c4224f5ed56d8d9757b0d4929d7174308172bb848221c6deaa08444a33b461f05dc8af7253845f6189fd836a287bf4c48c273e580cd0bda07a72ce69ddb72b1c419076825070208e4ecb706d04e9a98ee14c35d87b009b0ce65909eab71133dab58f0e09ccf3676401b00571e6e1e8e99311b3d6ca686fef6fa3096087bde74345b571b013b6901e685de7032cc86d264394b74efc52f30cf9d223c96d8e179908487809164212cd41eb88b370a6c6a1b82ea14f15c1a68d5598da07f6476e014ee3301b001fe15f41706b7e5853128cd4cb7ca0adedea00651acffd65b440eb89e54f8ebb10571afe26d128a3d9572230b9fc179d80488406d607513c3957dc4fe07fa10d4cfae1e8e6a68c2ed630f1edede8e89d7d0b3cc66ebe4c6b7f795b9d221a68624950a2e4c49755baa6b8785a459eba0eabd8f29430ff36aad703b69dcfd10e463d93fe28f752c3f1e8a527630be0fbafc229d0e3609a733248708cd49ac23f5e19bf60947cdc408449054842e32807b53c87a03ccf45a4700e7b276ee179b519aba370ec790cbb83d55de9655a1521ae12b50f22148a41100155ae85a54c0f54d8651f3c3921e595f4506cd6801a1687f8c22a6f33087457cd7bc0cebabb1b19e5702abed7e898f641b380a5e6ecf463d2d02c9218197810d06a36eb85d8767737fac13a1e731d0f64c319545ff4c0736e7bfc9814e453950c0319566e1d3b2288e2659ff4609f2b803e98247ebbf62c4ad2851f1f6079b1ab7dc7426deba379f0add4268675fe7a87a9d05f3270ceaf4326672c14ae3086ebe5372ca529bbe63a44bb2935250a4b0417c447d0ff4ccecf42f4d873350d1d1776410518df093c67ef4979752d95031d84cfe87f271db6ba22d4eb22ad3daa75b0785a5ad32a75285830ca7804dc4ae1090f0caca74739edba0740f3abaef0a3d214be5d60ec096990683296d8821b361502dc097e8571a82406730f4c51177c3168e18d5911dd08129c861430b43ad34a148d0203a3daf5b864c554a6be1b7cf43f6b56ca003b058d1313946d141681bb985a469f5492eb264483a57c90b699fc306a99ccea8bcacfd28fc272ae0a8798273ed8c9c0cb35d6af3079d61f362c966772a7d9161ad7e83b6d173db40ac4f355f2e0a05b1c8d98f490dee9085298d592914ad1cd0d3639c1822d7c1a9f9d82354c53083f058f6d9fe8dde0df1f01ec9acdb952ea2af5a02608619be8d5aa916957b1dc800e3e8f4c66d0456093610cf1df2af866d620be04c4fe22434f7c4083b4d1fd004bb96c70314b25a0cded6d5f5f851c941c0e24a70127d05d58725ec43c4e0a82b742d834c4f34e9ceb8500fb3b092f43b266dfd987a6853dbc2f03ac180940f9c23e6cd497cb43ab9a2fd2a7fede1a7d800a6ce3a00e182820dc3310635b3737d8ef1ba15d601f3e172596ff72bb1dbab521975e2b47b7837d06953f21cc5d2535c7c6be82f5af2ae675fd994a7ea677ca225795f24c7a592ec68dd186acabf58af5a04fbba0dbc053b909ab4561d3df26d69244a09da8711668692fd55d4558b8e85ffd606a7b57be7cf528f902d0f78a81bd1c710ca3a4818b923683f65e274e936ea436c7d706c81c1589b007ef6fa9e63d207c2ab570917e1be19d59b601f86dfeaf29257f1bcbf08afbb28b7b069325b56a1d23e77d7479a9b5da902ced387c4eb698fb6adae70eff1dea70bf2dd8711f449853efdf4a5f18f607e3fe355f9a57493015faf6b6a1bf650c10a6c3efb07f7574f662195367531972e4be179f8fbe0b15f491f747e57e3ceafad8f93d1197fa7a40b4757d95780e863d7cc5fbc275afc1ed7b3d23576f130277d7e71d8a2a04f7d64ec011dbad8680d435fabe85Line truncated
gr, _ = gzip.NewReader(bytes.NewBuffer(bs))
bs, _ = ioutil.ReadAll(gr)
Assets["index.html"] = bs
+46
View File
@@ -0,0 +1,46 @@
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package beacon
import "net"
type recv struct {
data []byte
src net.Addr
}
type dst struct {
intf string
conn *net.UDPConn
}
type Interface interface {
Send(data []byte)
Recv() ([]byte, net.Addr)
}
func genericReader(conn *net.UDPConn, outbox chan<- recv) {
bs := make([]byte, 65536)
for {
n, addr, err := conn.ReadFrom(bs)
if err != nil {
l.Warnln("multicast read:", err)
return
}
if debug {
l.Debugf("recv %d bytes from %s", n, addr)
}
c := make([]byte, n)
copy(c, bs)
select {
case outbox <- recv{c, addr}:
default:
if debug {
l.Debugln("dropping message")
}
}
}
}
+1 -35
View File
@@ -6,16 +6,6 @@ package beacon
import "net"
type recv struct {
data []byte
src net.Addr
}
type dst struct {
intf string
conn *net.UDPConn
}
type Broadcast struct {
conn *net.UDPConn
port int
@@ -36,7 +26,7 @@ func NewBroadcast(port int) (*Broadcast, error) {
outbox: make(chan recv, 16),
}
go b.reader()
go genericReader(b.conn, b.outbox)
go b.writer()
return b, nil
@@ -51,30 +41,6 @@ func (b *Broadcast) Recv() ([]byte, net.Addr) {
return recv.data, recv.src
}
func (b *Broadcast) reader() {
bs := make([]byte, 65536)
for {
n, addr, err := b.conn.ReadFrom(bs)
if err != nil {
l.Warnln("Broadcast read:", err)
return
}
if debug {
l.Debugf("recv %d bytes from %s", n, addr)
}
c := make([]byte, n)
copy(c, bs)
select {
case b.outbox <- recv{c, addr}:
default:
if debug {
l.Debugln("dropping message")
}
}
}
}
func (b *Broadcast) writer() {
for bs := range b.inbox {
+70
View File
@@ -0,0 +1,70 @@
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package beacon
import "net"
type Multicast struct {
conn *net.UDPConn
addr *net.UDPAddr
conns []dst
inbox chan []byte
outbox chan recv
}
func NewMulticast(addr string) (*Multicast, error) {
gaddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
conn, err := net.ListenMulticastUDP("udp", nil, gaddr)
if err != nil {
return nil, err
}
b := &Multicast{
conn: conn,
addr: gaddr,
inbox: make(chan []byte),
outbox: make(chan recv, 16),
}
go genericReader(b.conn, b.outbox)
go b.writer()
return b, nil
}
func (b *Multicast) Send(data []byte) {
b.inbox <- data
}
func (b *Multicast) Recv() ([]byte, net.Addr) {
recv := <-b.outbox
return recv.data, recv.src
}
func (b *Multicast) writer() {
for bs := range b.inbox {
intfs, err := net.Interfaces()
if err != nil {
l.Warnln("multicast interfaces:", err)
continue
}
for _, intf := range intfs {
if intf.Flags&net.FlagUp != 0 && intf.Flags&net.FlagMulticast != 0 {
addr := *b.addr
addr.Zone = intf.Name
_, err = b.conn.WriteTo(bs, &addr)
if err != nil {
if debug {
l.Debugln(err, "on write to", addr)
}
} else if debug {
l.Debugf("sent %d bytes to %s", len(bs), addr.String())
}
}
}
}
}
+1 -1
View File
@@ -985,7 +985,7 @@ func setTCPOptions(conn *net.TCPConn) {
}
func discovery(extPort int) *discover.Discoverer {
disc, err := discover.NewDiscoverer(myID, cfg.Options.ListenAddress, cfg.Options.LocalAnnPort)
disc, err := discover.NewDiscoverer(myID, cfg.Options.ListenAddress, cfg.Options.LocalAnnPort, cfg.Options.LocalAnnMCAddr)
if err != nil {
l.Warnf("No discovery possible (%v)", err)
return nil
+1
View File
@@ -113,6 +113,7 @@ type OptionsConfiguration struct {
GlobalAnnEnabled bool `xml:"globalAnnounceEnabled" default:"true"`
LocalAnnEnabled bool `xml:"localAnnounceEnabled" default:"true"`
LocalAnnPort int `xml:"localAnnouncePort" default:"21025"`
LocalAnnMCAddr string `xml:"localAnnounceMCAddr" default:"[ff32::5222]:21026"`
ParallelRequests int `xml:"parallelRequests" default:"16"`
MaxSendKbps int `xml:"maxSendKbps"`
RescanIntervalS int `xml:"rescanIntervalS" default:"60"`
+3
View File
@@ -30,6 +30,7 @@ func TestDefaultValues(t *testing.T) {
GlobalAnnEnabled: true,
LocalAnnEnabled: true,
LocalAnnPort: 21025,
LocalAnnMCAddr: "[ff32::5222]:21026",
ParallelRequests: 16,
MaxSendKbps: 0,
RescanIntervalS: 60,
@@ -200,6 +201,7 @@ func TestOverriddenValues(t *testing.T) {
<globalAnnounceEnabled>false</globalAnnounceEnabled>
<localAnnounceEnabled>false</localAnnounceEnabled>
<localAnnouncePort>42123</localAnnouncePort>
<localAnnounceMCAddr>quux:3232</localAnnounceMCAddr>
<parallelRequests>32</parallelRequests>
<maxSendKbps>1234</maxSendKbps>
<rescanIntervalS>600</rescanIntervalS>
@@ -218,6 +220,7 @@ func TestOverriddenValues(t *testing.T) {
GlobalAnnEnabled: false,
LocalAnnEnabled: false,
LocalAnnPort: 42123,
LocalAnnMCAddr: "quux:3232",
ParallelRequests: 32,
MaxSendKbps: 1234,
RescanIntervalS: 600,
+28 -11
View File
@@ -26,7 +26,8 @@ type Discoverer struct {
globalBcastIntv time.Duration
errorRetryIntv time.Duration
cacheLifetime time.Duration
broadcastBeacon *beacon.Broadcast
broadcastBeacon beacon.Interface
multicastBeacon beacon.Interface
registry map[protocol.NodeID][]cacheEntry
registryLock sync.RWMutex
extServer string
@@ -54,11 +55,7 @@ var (
// When we hit this many errors in succession, we stop.
const maxErrors = 30
func NewDiscoverer(id protocol.NodeID, addresses []string, localPort int) (*Discoverer, error) {
b, err := beacon.NewBroadcast(localPort)
if err != nil {
return nil, err
}
func NewDiscoverer(id protocol.NodeID, addresses []string, localPort int, localMCAddr string) (*Discoverer, error) {
disc := &Discoverer{
myID: id,
listenAddrs: addresses,
@@ -66,11 +63,26 @@ func NewDiscoverer(id protocol.NodeID, addresses []string, localPort int) (*Disc
globalBcastIntv: 1800 * time.Second,
errorRetryIntv: 60 * time.Second,
cacheLifetime: 5 * time.Minute,
broadcastBeacon: b,
registry: make(map[protocol.NodeID][]cacheEntry),
}
go disc.recvAnnouncements()
if localPort > 0 {
bb, err := beacon.NewBroadcast(localPort)
if err != nil {
return nil, err
}
disc.broadcastBeacon = bb
go disc.recvAnnouncements(bb)
}
if len(localMCAddr) > 0 {
mb, err := beacon.NewMulticast(localMCAddr)
if err != nil {
return nil, err
}
disc.multicastBeacon = mb
go disc.recvAnnouncements(mb)
}
return disc, nil
}
@@ -187,7 +199,12 @@ func (d *Discoverer) sendLocalAnnouncements() {
msg := pkt.MarshalXDR()
for {
d.broadcastBeacon.Send(msg)
if d.multicastBeacon != nil {
d.multicastBeacon.Send(msg)
}
if d.broadcastBeacon != nil {
d.broadcastBeacon.Send(msg)
}
select {
case <-d.localBcastTick:
@@ -284,9 +301,9 @@ loop:
}
}
func (d *Discoverer) recvAnnouncements() {
func (d *Discoverer) recvAnnouncements(b beacon.Interface) {
for {
buf, addr := d.broadcastBeacon.Recv()
buf, addr := b.Recv()
if debug {
l.Debugf("discover: read announcement from %s:\n%s", addr, hex.Dump(buf))
-4
View File
@@ -614,10 +614,6 @@
</label>
</div>
</div>
<div class="form-group">
<label translate for="LocalAnnPort">Local Discovery Port</label>
<input ng-disabled="!tmpOptions.LocalAnnEnabled" id="LocalAnnPort" class="form-control" type="number" ng-model="tmpOptions.LocalAnnPort">
</div>
<div class="form-group">
<div class="checkbox">
<label>