mirror of
https://github.com/1Password/onepassword-operator.git
synced 2025-10-23 07:58:04 +00:00
Add option to cosume connect events rather than polling to restart deployments
This commit is contained in:
20
vendor/github.com/schollz/peerdiscovery/.gitignore
generated
vendored
Normal file
20
vendor/github.com/schollz/peerdiscovery/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
examples/examples
|
||||
examples/ipv4/go.sum
|
||||
examples/ipv4/ipv4
|
||||
examples/ipv6/go.sum
|
||||
examples/ipv6/ipv6
|
7
vendor/github.com/schollz/peerdiscovery/Dockerfile
generated
vendored
Normal file
7
vendor/github.com/schollz/peerdiscovery/Dockerfile
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM golang
|
||||
|
||||
WORKDIR /peerdiscovery
|
||||
COPY . .
|
||||
RUN go build ./examples/ipv4/main.go
|
||||
|
||||
CMD ["/peerdiscovery/main"]
|
21
vendor/github.com/schollz/peerdiscovery/LICENSE
generated
vendored
Normal file
21
vendor/github.com/schollz/peerdiscovery/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Zack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
72
vendor/github.com/schollz/peerdiscovery/README.md
generated
vendored
Normal file
72
vendor/github.com/schollz/peerdiscovery/README.md
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# peerdiscovery
|
||||
|
||||
<img src="https://img.shields.io/badge/coverage-89%25-brightgreen.svg?style=flat-square" alt="Code coverage"> <a href="https://goreportcard.com/report/github.com/schollz/peerdiscovery"><img src="https://goreportcard.com/badge/github.com/schollz/peerdiscovery?style=flat-square" alt="Go Report"></a> <a href="https://godoc.org/github.com/schollz/peerdiscovery"><img src="http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square" alt="Go Doc"></a>
|
||||
|
||||
Pure-go library for cross-platform thread-safe local peer discovery using UDP multicast. I needed to use peer discovery for [croc](https://github.com/schollz/croc) and everything I tried had problems, so I made another one.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
Make sure you have Go 1.5+.
|
||||
|
||||
```
|
||||
go get -u github.com/schollz/peerdiscovery
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The following is a code to find the first peer on the local network and print it out.
|
||||
|
||||
```golang
|
||||
discoveries, _ := peerdiscovery.Discover(peerdiscovery.Settings{Limit: 1})
|
||||
for _, d := range discoveries {
|
||||
fmt.Printf("discovered '%s'\n", d.Address)
|
||||
}
|
||||
```
|
||||
|
||||
Here's the output when running on two computers. (*Run these gifs in sync by hitting Ctl + F5*).
|
||||
|
||||
**Computer 1:**
|
||||
|
||||

|
||||
|
||||
**Computer 2:**
|
||||
|
||||

|
||||
|
||||
For more examples, see the scanning examples ([ipv4](https://github.com/schollz/peerdiscovery/blob/master/examples/ipv4/main.go) and [ipv6](https://github.com/schollz/peerdiscovery/blob/master/examples/ipv6/main.go)) or [the docs](https://pkg.go.dev/github.com/schollz/peerdiscovery).
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
To test the peer discovery with just one host, one can launch multiple containers. The provided `Dockerfile` will run the example code.
|
||||
Please make sure to enable [Docker's IPv6 support](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/ipv6/) if you are using IPv6 for peer discovery.
|
||||
|
||||
```console
|
||||
# Build the container, named peertest
|
||||
$ docker build -t peertest .
|
||||
|
||||
# Execute the following command in multiple terminals
|
||||
$ docker run -t --rm peertest
|
||||
Scanning for 10 seconds to find LAN peers
|
||||
100% |████████████████████████████████████████| [9s:0s]Found 1 other computers
|
||||
0) '172.17.0.2' with payload 'zqrecHipCO'
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome. Feel free to...
|
||||
|
||||
- Revise documentation
|
||||
- Add new features
|
||||
- Fix bugs
|
||||
- Suggest improvements
|
||||
|
||||
## Thanks
|
||||
|
||||
Thanks [@geistesk](https://github.com/geistesk) for adding IPv6 support and a `Notify` func, and helping maintain! Thanks [@Kunde21](https://github.com/Kunde21) for providing a bug fix and massively refactoring the code in a much better way. Thanks [@robpre](https://github.com/robpre) for finding and fixing bugs. Thanks [@shvydky](https://github.com/shvydky) for adding dynamic payloads.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
9
vendor/github.com/schollz/peerdiscovery/go.mod
generated
vendored
Normal file
9
vendor/github.com/schollz/peerdiscovery/go.mod
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module github.com/schollz/peerdiscovery
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.6.1
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
|
||||
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02 // indirect
|
||||
)
|
24
vendor/github.com/schollz/peerdiscovery/go.sum
generated
vendored
Normal file
24
vendor/github.com/schollz/peerdiscovery/go.sum
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02 h1:5Ftd3YbC/kANXWCBjvppvUmv1BMakgFcBKA7MpYYp4M=
|
||||
golang.org/x/sys v0.0.0-20201113135734-0a15ea8d9b02/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
414
vendor/github.com/schollz/peerdiscovery/peerdiscovery.go
generated
vendored
Normal file
414
vendor/github.com/schollz/peerdiscovery/peerdiscovery.go
generated
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
package peerdiscovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// IPVersion specifies the version of the Internet Protocol to be used.
|
||||
type IPVersion uint
|
||||
|
||||
const (
|
||||
IPv4 IPVersion = 4
|
||||
IPv6 IPVersion = 6
|
||||
)
|
||||
|
||||
// Discovered is the structure of the discovered peers,
|
||||
// which holds their local address (port removed) and
|
||||
// a payload if there is one.
|
||||
type Discovered struct {
|
||||
// Address is the local address of a discovered peer.
|
||||
Address string
|
||||
// Payload is the associated payload from discovered peer.
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func (d Discovered) String() string {
|
||||
return fmt.Sprintf("address: %s, payload: %s", d.Address, d.Payload)
|
||||
}
|
||||
|
||||
// Settings are the settings that can be specified for
|
||||
// doing peer discovery.
|
||||
type Settings struct {
|
||||
// Limit is the number of peers to discover, use < 1 for unlimited.
|
||||
Limit int
|
||||
// Port is the port to broadcast on (the peers must also broadcast using the same port).
|
||||
// The default port is 9999.
|
||||
Port string
|
||||
// MulticastAddress specifies the multicast address.
|
||||
// You should be able to use any of 224.0.0.0/4 or ff00::/8.
|
||||
// By default it uses the Simple Service Discovery Protocol
|
||||
// address (239.255.255.250 for IPv4 or ff02::c for IPv6).
|
||||
MulticastAddress string
|
||||
// Payload is the bytes that are sent out with each broadcast. Must be short.
|
||||
Payload []byte
|
||||
// PayloadFunc is the function that will be called to dynamically generate payload
|
||||
// before every broadcast. If this pointer is nil `Payload` field will be broadcasted instead.
|
||||
PayloadFunc func() []byte
|
||||
// Delay is the amount of time between broadcasts. The default delay is 1 second.
|
||||
Delay time.Duration
|
||||
// TimeLimit is the amount of time to spend discovering, if the limit is not reached.
|
||||
// A negative limit indiciates scanning until the limit was reached or, if an
|
||||
// unlimited scanning was requested, no timeout.
|
||||
// The default time limit is 10 seconds.
|
||||
TimeLimit time.Duration
|
||||
// StopChan is a channel to stop the peer discvoery immediatley after reception.
|
||||
StopChan chan struct{}
|
||||
// AllowSelf will allow discovery the local machine (default false)
|
||||
AllowSelf bool
|
||||
// DisableBroadcast will not allow sending out a broadcast
|
||||
DisableBroadcast bool
|
||||
// IPVersion specifies the version of the Internet Protocol (default IPv4)
|
||||
IPVersion IPVersion
|
||||
// Notify will be called each time a new peer was discovered.
|
||||
// The default is nil, which means no notification whatsoever.
|
||||
Notify func(Discovered)
|
||||
|
||||
portNum int
|
||||
multicastAddressNumbers net.IP
|
||||
}
|
||||
|
||||
// peerDiscovery is the object that can do the discovery for finding LAN peers.
|
||||
type peerDiscovery struct {
|
||||
settings Settings
|
||||
|
||||
received map[string][]byte
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// initialize returns a new peerDiscovery object which can be used to discover peers.
|
||||
// The settings are optional. If any setting is not supplied, then defaults are used.
|
||||
// See the Settings for more information.
|
||||
func initialize(settings Settings) (p *peerDiscovery, err error) {
|
||||
p = new(peerDiscovery)
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
// initialize settings
|
||||
p.settings = settings
|
||||
|
||||
// defaults
|
||||
if p.settings.Port == "" {
|
||||
p.settings.Port = "9999"
|
||||
}
|
||||
if p.settings.IPVersion == 0 {
|
||||
p.settings.IPVersion = IPv4
|
||||
}
|
||||
if p.settings.MulticastAddress == "" {
|
||||
if p.settings.IPVersion == IPv4 {
|
||||
p.settings.MulticastAddress = "239.255.255.250"
|
||||
} else {
|
||||
p.settings.MulticastAddress = "ff02::c"
|
||||
}
|
||||
}
|
||||
if len(p.settings.Payload) == 0 {
|
||||
p.settings.Payload = []byte("hi")
|
||||
}
|
||||
if p.settings.Delay == 0 {
|
||||
p.settings.Delay = 1 * time.Second
|
||||
}
|
||||
if p.settings.TimeLimit == 0 {
|
||||
p.settings.TimeLimit = 10 * time.Second
|
||||
}
|
||||
if p.settings.StopChan == nil {
|
||||
p.settings.StopChan = make(chan struct{})
|
||||
}
|
||||
p.received = make(map[string][]byte)
|
||||
p.settings.multicastAddressNumbers = net.ParseIP(p.settings.MulticastAddress)
|
||||
if p.settings.multicastAddressNumbers == nil {
|
||||
err = fmt.Errorf("Multicast Address %s could not be converted to an IP",
|
||||
p.settings.MulticastAddress)
|
||||
return
|
||||
}
|
||||
p.settings.portNum, err = strconv.Atoi(p.settings.Port)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type NetPacketConn interface {
|
||||
JoinGroup(ifi *net.Interface, group net.Addr) error
|
||||
SetMulticastInterface(ini *net.Interface) error
|
||||
SetMulticastTTL(int) error
|
||||
ReadFrom(buf []byte) (int, net.Addr, error)
|
||||
WriteTo(buf []byte, dst net.Addr) (int, error)
|
||||
}
|
||||
|
||||
// Discover will use the created settings to scan for LAN peers. It will return
|
||||
// an array of the discovered peers and their associate payloads. It will not
|
||||
// return broadcasts sent to itself.
|
||||
func Discover(settings ...Settings) (discoveries []Discovered, err error) {
|
||||
s := Settings{}
|
||||
if len(settings) > 0 {
|
||||
s = settings[0]
|
||||
}
|
||||
p, err := initialize(s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.RLock()
|
||||
address := net.JoinHostPort(p.settings.MulticastAddress, p.settings.Port)
|
||||
portNum := p.settings.portNum
|
||||
|
||||
tickerDuration := p.settings.Delay
|
||||
timeLimit := p.settings.TimeLimit
|
||||
p.RUnlock()
|
||||
|
||||
// get interfaces
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Open up a connection
|
||||
c, err := net.ListenPacket(fmt.Sprintf("udp%d", p.settings.IPVersion), address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
group := p.settings.multicastAddressNumbers
|
||||
|
||||
// ipv{4,6} have an own PacketConn, which does not implement net.PacketConn
|
||||
var p2 NetPacketConn
|
||||
if p.settings.IPVersion == IPv4 {
|
||||
p2 = PacketConn4{ipv4.NewPacketConn(c)}
|
||||
} else {
|
||||
p2 = PacketConn6{ipv6.NewPacketConn(c)}
|
||||
}
|
||||
|
||||
for i := range ifaces {
|
||||
p2.JoinGroup(&ifaces[i], &net.UDPAddr{IP: group, Port: portNum})
|
||||
}
|
||||
|
||||
go p.listen()
|
||||
ticker := time.NewTicker(tickerDuration)
|
||||
defer ticker.Stop()
|
||||
start := time.Now()
|
||||
|
||||
for {
|
||||
exit := false
|
||||
|
||||
p.RLock()
|
||||
if len(p.received) >= p.settings.Limit && p.settings.Limit > 0 {
|
||||
exit = true
|
||||
}
|
||||
p.RUnlock()
|
||||
|
||||
if !s.DisableBroadcast {
|
||||
payload := p.settings.Payload
|
||||
if p.settings.PayloadFunc != nil {
|
||||
payload = p.settings.PayloadFunc()
|
||||
}
|
||||
// write to multicast
|
||||
broadcast(p2, payload, ifaces, &net.UDPAddr{IP: group, Port: portNum})
|
||||
}
|
||||
|
||||
select {
|
||||
case <-p.settings.StopChan:
|
||||
exit = true
|
||||
case <-ticker.C:
|
||||
}
|
||||
|
||||
if exit || timeLimit > 0 && time.Since(start) > timeLimit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !s.DisableBroadcast {
|
||||
payload := p.settings.Payload
|
||||
if p.settings.PayloadFunc != nil {
|
||||
payload = p.settings.PayloadFunc()
|
||||
}
|
||||
// send out broadcast that is finished
|
||||
broadcast(p2, payload, ifaces, &net.UDPAddr{IP: group, Port: portNum})
|
||||
}
|
||||
|
||||
p.RLock()
|
||||
discoveries = make([]Discovered, len(p.received))
|
||||
i := 0
|
||||
for ip, payload := range p.received {
|
||||
discoveries[i] = Discovered{
|
||||
Address: ip,
|
||||
Payload: payload,
|
||||
}
|
||||
i++
|
||||
}
|
||||
p.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func broadcast(p2 NetPacketConn, payload []byte, ifaces []net.Interface, dst net.Addr) {
|
||||
for i := range ifaces {
|
||||
if errMulticast := p2.SetMulticastInterface(&ifaces[i]); errMulticast != nil {
|
||||
continue
|
||||
}
|
||||
p2.SetMulticastTTL(2)
|
||||
if _, errMulticast := p2.WriteTo([]byte(payload), dst); errMulticast != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
|
||||
maxDatagramSize = 66507
|
||||
)
|
||||
|
||||
// Listen binds to the UDP address and port given and writes packets received
|
||||
// from that address to a buffer which is passed to a hander
|
||||
func (p *peerDiscovery) listen() (recievedBytes []byte, err error) {
|
||||
p.RLock()
|
||||
address := net.JoinHostPort(p.settings.MulticastAddress, p.settings.Port)
|
||||
portNum := p.settings.portNum
|
||||
allowSelf := p.settings.AllowSelf
|
||||
notify := p.settings.Notify
|
||||
p.RUnlock()
|
||||
localIPs := getLocalIPs()
|
||||
|
||||
// get interfaces
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// log.Println(ifaces)
|
||||
|
||||
// Open up a connection
|
||||
c, err := net.ListenPacket(fmt.Sprintf("udp%d", p.settings.IPVersion), address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
group := p.settings.multicastAddressNumbers
|
||||
var p2 NetPacketConn
|
||||
if p.settings.IPVersion == IPv4 {
|
||||
p2 = PacketConn4{ipv4.NewPacketConn(c)}
|
||||
} else {
|
||||
p2 = PacketConn6{ipv6.NewPacketConn(c)}
|
||||
}
|
||||
|
||||
for i := range ifaces {
|
||||
p2.JoinGroup(&ifaces[i], &net.UDPAddr{IP: group, Port: portNum})
|
||||
}
|
||||
|
||||
// Loop forever reading from the socket
|
||||
for {
|
||||
buffer := make([]byte, maxDatagramSize)
|
||||
var (
|
||||
n int
|
||||
src net.Addr
|
||||
errRead error
|
||||
)
|
||||
n, src, errRead = p2.ReadFrom(buffer)
|
||||
if errRead != nil {
|
||||
err = errRead
|
||||
return
|
||||
}
|
||||
|
||||
srcHost, _, _ := net.SplitHostPort(src.String())
|
||||
|
||||
if _, ok := localIPs[srcHost]; ok && !allowSelf {
|
||||
continue
|
||||
}
|
||||
|
||||
// log.Println(src, hex.Dump(buffer[:n]))
|
||||
|
||||
p.Lock()
|
||||
if _, ok := p.received[srcHost]; !ok {
|
||||
p.received[srcHost] = buffer[:n]
|
||||
}
|
||||
p.Unlock()
|
||||
|
||||
if notify != nil {
|
||||
notify(Discovered{
|
||||
Address: srcHost,
|
||||
Payload: buffer[:n],
|
||||
})
|
||||
}
|
||||
|
||||
p.RLock()
|
||||
if len(p.received) >= p.settings.Limit && p.settings.Limit > 0 {
|
||||
p.RUnlock()
|
||||
break
|
||||
}
|
||||
p.RUnlock()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// getLocalIPs returns the local ip address
|
||||
func getLocalIPs() (ips map[string]struct{}) {
|
||||
ips = make(map[string]struct{})
|
||||
ips["localhost"] = struct{}{}
|
||||
ips["127.0.0.1"] = struct{}{}
|
||||
ips["::1"] = struct{}{}
|
||||
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, address := range addrs {
|
||||
ip, _, err := net.ParseCIDR(address.String())
|
||||
if err != nil {
|
||||
// log.Printf("Failed to parse %s: %v", address.String(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
ips[ip.String()+"%"+iface.Name] = struct{}{}
|
||||
ips[ip.String()] = struct{}{}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type PacketConn4 struct {
|
||||
*ipv4.PacketConn
|
||||
}
|
||||
|
||||
// ReadFrom wraps the ipv4 ReadFrom without a control message
|
||||
func (pc4 PacketConn4) ReadFrom(buf []byte) (int, net.Addr, error) {
|
||||
n, _, addr, err := pc4.PacketConn.ReadFrom(buf)
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
// WriteTo wraps the ipv4 WriteTo without a control message
|
||||
func (pc4 PacketConn4) WriteTo(buf []byte, dst net.Addr) (int, error) {
|
||||
return pc4.PacketConn.WriteTo(buf, nil, dst)
|
||||
}
|
||||
|
||||
type PacketConn6 struct {
|
||||
*ipv6.PacketConn
|
||||
}
|
||||
|
||||
// ReadFrom wraps the ipv6 ReadFrom without a control message
|
||||
func (pc6 PacketConn6) ReadFrom(buf []byte) (int, net.Addr, error) {
|
||||
n, _, addr, err := pc6.PacketConn.ReadFrom(buf)
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
// WriteTo wraps the ipv6 WriteTo without a control message
|
||||
func (pc6 PacketConn6) WriteTo(buf []byte, dst net.Addr) (int, error) {
|
||||
return pc6.PacketConn.WriteTo(buf, nil, dst)
|
||||
}
|
||||
|
||||
// SetMulticastTTL wraps the hop limit of ipv6
|
||||
func (pc6 PacketConn6) SetMulticastTTL(i int) error {
|
||||
return pc6.SetMulticastHopLimit(i)
|
||||
}
|
Reference in New Issue
Block a user