8000 Add support for broadcasting multiple IPs by jspiro · Pull Request #13 · oleksandr/bonjour · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for broadcasting multiple IPs #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ import (

func ma 10000 in() {
// Run registration (blocking call)
s, err := bonjour.Register("Foo Service", "_foobar._tcp", "", 9999, []string{"txtv=1", "app=test"}, nil)
s, err := bonjour.Register("Foo Service", "_foobar._tcp", "", 9999, []string{"txtv=1", "app=test"}, nil, 0)
if err != nil {
log.Fatalln(err.Error())
}
Expand Down Expand Up @@ -146,7 +146,7 @@ import (

func main() {
// Run registration (blocking call)
s, err := bonjour.RegisterProxy("Proxy Service", "_foobar._tcp", "", 9999, "octopus", "10.0.0.111", []string{"txtv=1", "app=test"}, nil)
s, err := bonjour.RegisterProxy("Proxy Service", "_foobar._tcp", "", 9999, "octopus", "10.0.0.111", []string{"txtv=1", "app=test"}, nil, 0)
if err != nil {
log.Fatalln(err.Error())
}
Expand Down
19 changes: 9 additions & 10 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"strings"
"sync"

"github.com/miekg/dns"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
"github.com/miekg/dns"
)

// Main client data structure to run browse/lookup queries
Expand Down Expand Up @@ -71,7 +71,7 @@ func defaultParams(service string) *LookupParams {
return NewLookupParams("", service, "local", make(chan *ServiceEntry))
}

// Client structure incapsulates both IPv4/IPv6 UDP connections
// Client structure encapsulates both IPv4/IPv6 UDP connections
type client struct {
ipv4conn *net.UDPConn
ipv6conn *net.UDPConn
Expand Down Expand Up @@ -201,15 +201,15 @@ func (c *client) mainloop(params *LookupParams) {
entries[rr.Hdr.Name].Text = rr.Txt
entries[rr.Hdr.Name].TTL = rr.Hdr.Ttl
case *dns.A:
for k, e := range entries {
if e.HostName == rr.Hdr.Name && entries[k].AddrIPv4 == nil {
entries[k].AddrIPv4 = rr.A
for _, e := range entries {
if e.HostName == rr.Hdr.Name {
e.AddrIPv4 = append(e.AddrIPv4, rr.A)
}
}
case *dns.AAAA:
for k, e := range entries {
if e.HostName == rr.Hdr.Name && entries[k].AddrIPv6 == nil {
entries[k].AddrIPv6 = rr.AAAA
for _, e := range entries {
if e.HostName == rr.Hdr.Name {
e.AddrIPv6 = append(e.AddrIPv6, rr.AAAA)
}
}
}
Expand Down Expand Up @@ -290,15 +290,14 @@ func (c *client) query(params *LookupParams) error { 8000

// send the query
m := new(dns.Msg)
m.RecursionDesired = false
if serviceInstanceName != "" {
m.Question = []dns.Question{
dns.Question{serviceInstanceName, dns.TypeSRV, dns.ClassINET},
dns.Question{serviceInstanceName, dns.TypeTXT, dns.ClassINET},
}
m.RecursionDesired = false
} else {
m.SetQuestion(serviceName, dns.TypePTR)
m.RecursionDesired = false
}
if err := c.sendQuery(m); err != nil {
return err
Expand Down
86 changes: 49 additions & 37 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
)

var (
localDomain = "local"

// Multicast groups used by mDNS
mdnsGroupIPv4 = net.IPv4(224, 0, 0, 251)
mdnsGroupIPv6 = net.ParseIP("ff02::fb")
Expand All @@ -42,8 +44,8 @@ var (
)

// Register a service by given arguments. This call will take the system's hostname
// and lookup IP by that hostname.
func Register(instance, service, domain string, port int, text []string, iface *net.Interface) (*Server, error) {
// and lookup IP by that hostname. If ttl is 0 the default will be used.
func Register(instance, service, domain string, port int, text []string, iface *net.Interface, ttl uint32) (*Server, error) {
entry := NewServiceEntry(instance, service, domain)
entry.Port = port
entry.Text = text
Expand All @@ -55,7 +57,7 @@ func Register(instance, service, domain string, port int, text []string, iface *
return nil, fmt.Errorf("Missing service name")
}
if entry.Domain == "" {
entry.Domain = "local"
entry.Domain = localDomain
}
if entry.Port == 0 {
return nil, fmt.Errorf("Missing port")
Expand All @@ -82,9 +84,9 @@ func Register(instance, service, domain string, port int, text []string, iface *
}
for i := 0; i < len(addrs); i++ {
if ipv4 := addrs[i].To4(); ipv4 != nil {
entry.AddrIPv4 = addrs[i]
entry.AddrIPv4 = append(entry.AddrIPv4, addrs[i])
} else if ipv6 := addrs[i].To16(); ipv6 != nil {
entry.AddrIPv6 = addrs[i]
entry.AddrIPv6 = append(entry.AddrIPv6, addrs[i])
}
}

Expand All @@ -93,6 +95,10 @@ func Register(instance, service, domain string, port int, text []string, iface *
return nil, err
}

if ttl != 0 {
s.ttl = ttl
}

s.service = entry
go s.mainloop()
go s.probe()
Expand All @@ -101,8 +107,8 @@ func Register(instance, service, domain string, port int, text []string, iface *
}

// Register a service proxy by given argument. This call will skip the hostname/IP lookup and
// will use the provided values.
func RegisterProxy(instance, service, domain string, port int, host, ip string, text []string, iface *net.Interface) (*Server, error) {
// will use the provided values. If ttl is 0 the default will be used.
func RegisterProxy(instance, service, domain string, port int, host string, ips []string, text []string, iface *net.Interface, ttl uint32) (*Server, error) {
entry := NewServiceEntry(instance, service, domain)
entry.Port = port
entry.Text = text
Expand All @@ -118,7 +124,7 @@ func RegisterProxy(instance, service, domain string, port int, host, ip string,
return nil, fmt.Errorf("Missing host name")
}
if entry.Domain == "" {
entry.Domain = "local"
entry.Domain = localDomain
}
if entry.Port == 0 {
return nil, fmt.Errorf("Missing port")
Expand All @@ -128,37 +134,43 @@ func RegisterProxy(instance, service, domain string, port int, host, ip string,
entry.HostName = fmt.Sprintf("%s.%s.", trimDot(entry.HostName), trimDot(entry.Domain))
}

ipAddr := net.ParseIP(ip)
if ipAddr == nil {
return nil, fmt.Errorf("Failed to parse given IP: %v", ip)
} else if ipv4 := ipAddr.To4(); ipv4 != nil {
entry.AddrIPv4 = ipAddr
} else if ipv6 := ipAddr.To16(); ipv6 != nil {
entry.AddrIPv4 = ipAddr
} else {
return nil, fmt.Errorf("The IP is neither IPv4 nor IPv6: %#v", ipAddr)
for _, ip := range ips {
ipAddr := net.ParseIP(ip)
if ipAddr == nil {
return nil, fmt.Errorf("Failed to parse given IP: %v", ip)
} else if ipv4 := ipAddr.To4(); ipv4 != nil {
entry.AddrIPv4 = append(entry.AddrIPv4, ipAddr)
} else if ipv6 := ipAddr.To16(); ipv6 != nil {
entry.AddrIPv6 = append(entry.AddrIPv6, ipAddr)
} else {
return nil, fmt.Errorf("The IP is neither IPv4 nor IPv6: %#v", ipAddr)
}
}

s, err := newServer(iface)
if err != nil {
return nil, err
}

if ttl != 0 {
s.ttl = ttl
}

s.service = entry
go s.mainloop()
go s.probe()

return s, nil
}

// Server structure incapsulates both IPv4/IPv6 UDP connections
// Server structure encapsulates both IPv4/IPv6 UDP connections
type Server struct {
service *ServiceEntry
ipv4conn *net.UDPConn
ipv6conn *net.UDPConn
shouldShutdown bool
shutdownLock sync.Mutex
ttl uint32
service *ServiceEntry
ipv4conn *net.UDPConn
ipv6conn *net.UDPConn
shuttingDown bool
shutdownLock sync.Mutex
ttl uint32
}

// Constructs server structure
Expand Down Expand Up @@ -245,12 +257,12 @@ func (s *Server) shutdown() error {
s.shutdownLock.Lock()
defer s.shutdownLock.Unlock()

s.unregister()

if s.shouldShutdown {
if s.shuttingDown {
return nil
}
s.shouldShutdown = true
s.shuttingDown = true

s.unregister()

if s.ipv4conn != nil {
s.ipv4conn.Close()
Expand All @@ -267,7 +279,7 @@ func (s *Server) recv(c *net.UDPConn) {
return
}
buf := make([]byte, 65536)
for !s.shouldShutdown {
for !s.shuttingDown {
n, from, err := c.ReadFrom(buf)
if err != nil {
continue
Expand Down Expand Up @@ -388,27 +400,27 @@ func (s *Server) composeBrowsingAnswers(resp *dns.Msg, ttl uint32) {
}
resp.Extra = append(resp.Extra, srv, txt)

if s.service.AddrIPv4 != nil {
for _, ipv4 := range s.service.AddrIPv4 {
a := &dns.A{
Hdr: dns.RR_Header{
Name: s.service.HostName,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: ttl,
},
A: s.service.AddrIPv4,
A: ipv4,
}
resp.Extra = append(resp.Extra, a)
}
if s.service.AddrIPv6 != nil {
for _, ipv6 := range s.service.AddrIPv6 {
aaaa := &dns.AAAA{
Hdr: dns.RR_Header{
Name: s.service.HostName,
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET,
Ttl: ttl,
},
AAAA: s.service.AddrIPv6,
AAAA: ipv6,
}
resp.Extra = append(resp.Extra, aaaa)
}
Expand Down Expand Up @@ -462,27 +474,27 @@ func (s *Server) composeLookupAnswers(resp *dns.Msg, ttl uint32) {
}
resp.Answer = append(resp.Answer, srv, txt, ptr, dnssd)

if s.service.AddrIPv4 != nil {
for _, ipv4 := range s.service.AddrIPv4 {
a := &dns.A{
Hdr: dns.RR_Header{
Name: s.service.HostName,
Rrtype: dns.TypeA,
Class: dns.ClassINET | cache_flush,
Ttl: 120,
},
A: s.service.AddrIPv4,
A: ipv4,
}
resp.Extra = append(resp.Extra, a)
}
if s.service.AddrIPv6 != nil {
for _, ipv6 := range s.service.AddrIPv6 {
aaaa := &dns.AAAA{
Hdr: dns.RR_Header{
Name: s.service.HostName,
Rrtype: dns.TypeAAAA,
Class: dns.ClassINET | cache_flush,
Ttl: 120,
},
AAAA: s.service.AddrIPv6,
AAAA: ipv6,
}
resp.Extra = append(resp.Extra, aaaa)
}
Expand Down
8 changes: 4 additions & 4 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ type ServiceEntry struct {
Port int `json:"port"` // Service Port
Text []string `json:"text"` // Service info served as a TXT record
TTL uint32 `json:"ttl"` // TTL of the service record
AddrIPv4 net.IP `json:"-"` // Host machine IPv4 address
AddrIPv6 net.IP `json:"-"` // Host machine IPv6 address
AddrIPv4 []net.IP `json:"-"` // Host machine IPv4 address
AddrIPv6 []net.IP `json:"-"` // Host machine IPv6 address
}

// Constructs a ServiceEntry structure by given arguments
Expand All @@ -92,7 +92,7 @@ func NewServiceEntry(instance, service, domain string) *ServiceEntry {
0,
[]string{},
0,
nil,
nil,
[]net.IP{},
[]net.IP{},
}
}
0