Skip to content

Commit

Permalink
added .InterfaceAddrs(..), mainly for Android support
Browse files Browse the repository at this point in the history
  • Loading branch information
betamos committed Feb 7, 2025
1 parent 67479e0 commit 73df54b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
19 changes: 9 additions & 10 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,18 @@ type conn struct {
c6 *conn6
ifaces map[int]*connInterface // key: iface.Index

// Used initially and on reload to filter interfaces to use
ifacesFn func() ([]net.Interface, error)
opts *options
}

func newConn(ifacesFn func() ([]net.Interface, error), network string) (*conn, error) {
func newConn(opts *options) (*conn, error) {

c := &conn{
ifaces: make(map[int]*connInterface),
ifacesFn: ifacesFn,
ifaces: make(map[int]*connInterface),
opts: opts,
}

var err4, err6 error
switch network {
switch opts.network {
case "udp":
c.c4, err4 = newConn4()
c.c6, err6 = newConn6()
Expand All @@ -96,15 +95,15 @@ func newConn(ifacesFn func() ([]net.Interface, error), network string) (*conn, e
// Load (or reload) ifaces and return whether anything (addresses in particular) have changed.
func (c *conn) loadIfaces() (changed bool, err error) {
ifaces := make(map[int]*connInterface) // new ifaces
netIfaces, err := c.ifacesFn()
netIfaces, err := c.opts.ifacesFn()
if err != nil {
return false, err
}
for _, netIface := range netIfaces {
if !isMulticastInterface(netIface) {
continue
}
v4, v6, err := netIfaceAddrs(netIface)
v4, v6, err := c.netIfaceAddrs(&netIface)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -246,9 +245,9 @@ func (c *conn) Close() error {
}

// Returns mDNS-suitable unicast addresses for a net.Interface
func netIfaceAddrs(iface net.Interface) (v4, v6 []netip.Addr, err error) {
func (c *conn) netIfaceAddrs(iface *net.Interface) (v4, v6 []netip.Addr, err error) {
var v6local []netip.Addr
ifaceAddrs, err := iface.Addrs()
ifaceAddrs, err := c.opts.ifaceAddrsFn(iface)
if err != nil {
return nil, nil, err
}
Expand Down
20 changes: 16 additions & 4 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ type options struct {
browser *browser
publish *Service

ifacesFn func() ([]net.Interface, error)
network string
expiry time.Duration
srcAddrs bool
ifacesFn func() ([]net.Interface, error)
ifaceAddrsFn func(*net.Interface) ([]net.Addr, error)
network string
expiry time.Duration
srcAddrs bool
}

func defaultOpts() *options {
return &options{
logger: slog.Default(),
network: "udp",
ifacesFn: net.Interfaces,
ifaceAddrsFn: func(ifi *net.Interface) ([]net.Addr, error) {
return ifi.Addrs()
},
}
}

Expand Down Expand Up @@ -100,11 +104,19 @@ func (c *Client) Logger(l *slog.Logger) *Client {
}

// Use custom network interfaces. The default is `net.Interfaces`.
// For Android support, see https://github.com/wlynxg/anet
func (c *Client) Interfaces(fn func() ([]net.Interface, error)) *Client {
c.opts.ifacesFn = fn
return c
}

// Use custom addrs for an interface. The default is `iface.Addrs()`.
// For Android support, see https://github.com/wlynxg/anet
func (c *Client) InterfaceAddrs(fn func(*net.Interface) ([]net.Addr, error)) *Client {
c.opts.ifaceAddrsFn = fn
return c
}

// Use the source addr of the UDP packets instead of the self-reported addrs over mDNS.
// This should be more accurate and also works with link-local ipv6 addresses, but it's a
// little unorthodox and not tested widely. It also prevents proxy use-cases.
Expand Down

0 comments on commit 73df54b

Please sign in to comment.