Skip to content
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

Requested unicast responses are never received #15

Open
brutella opened this issue Jun 17, 2020 · 2 comments
Open

Requested unicast responses are never received #15

brutella opened this issue Jun 17, 2020 · 2 comments
Labels

Comments

@brutella
Copy link
Owner

Unicast responses are not received when listing to the multicast link local address.

@brutella brutella added the bug label Jun 17, 2020
@brutella brutella changed the title Fix issue where unicast responses are not received Requested unicast responses are never received Jun 17, 2020
brutella added a commit that referenced this issue Jun 18, 2020
At the momet we cannot receive unicast responses #15
brutella added a commit that referenced this issue Jul 24, 2020
At the momet we cannot receive unicast responses #15
@daniel-sullivan
Copy link

Regarding this bug, I've managed to recreate it in an alternate way: when the Host for a given service is in the format x.x.local. as opposed to x.local., the parseHostname() function will fail to return any meaningful result thereby causing it to appear that the response hasn't been received. I believe this is the correct functionality from my reading of the RFC (https://datatracker.ietf.org/doc/html/rfc6762#section-3) but it could trip people up.

I created a test case browse_test.go which replicates this issue attached.

package dnssd_test

import (
	"context"
	"fmt"
	"github.com/brutella/dnssd"
	"net"
	"os"
	"strings"
	"testing"
	"time"
)

func TestBrowse(t *testing.T) {
	testIface, _ := net.InterfaceByName("lo0")
	if testIface == nil {
		testIface, _ = net.InterfaceByName("lo")
	}
	if testIface == nil {
		t.Fatal("can not find the local interface")
	}

	localhost, err := os.Hostname()
	if err != nil {
		t.Fatal(err)
	}
	localhost = strings.TrimSuffix(strings.Replace(localhost, " ", "-", -1), ".local") // replace spaces with dashes and remove .local suffix
	for tName, hostValue := range map[string]string{
		"regular host": "My-Computer",
		"empty host":   "",
		"ip address":   "192.168.0.1",
	} {
		t.Run(tName, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
			defer cancel()
			cfg := dnssd.Config{
				Name:   "My Service",
				Type:   "_hap._tcp",
				Host:   hostValue,
				Port:   12334,
				Ifaces: []string{testIface.Name},
			}
			srv, err := dnssd.NewService(cfg)
			if err != nil {
				t.Fatal(err)
			}
			rs, err := dnssd.NewResponder()
			if err != nil {
				t.Fatal(err)
			}

			go func() {
				_ = rs.Respond(ctx)
			}()

			_, err = rs.Add(srv)
			if err != nil {
				t.Fatal(err)

			}

			resultChan := make(chan dnssd.BrowseEntry)
			defer close(resultChan)
			go func() {
				_ = dnssd.LookupType(ctx, fmt.Sprintf("%s.local.", cfg.Type), func(entry dnssd.BrowseEntry) {
					resultChan <- entry
				}, func(entry dnssd.BrowseEntry) {})
			}()

			select {
			case <-ctx.Done():
				t.Fatal("timeout")
			case entry := <-resultChan:
				if entry.Name != cfg.Name {
					t.Fatalf("is=%v want=%v", entry.Name, cfg.Name)
				}
				if tName == "empty host" {
					if entry.Host != localhost {
						t.Fatalf("is=%v want=%v", entry.Host, localhost)
					}
				} else {
					if entry.Host != cfg.Host {
						t.Fatalf("is=%v want=%v", entry.Host, cfg.Host)
					}
				}
				if entry.Port != cfg.Port {
					t.Fatalf("is=%v want=%v", entry.Port, cfg.Port)
				}
			}
		})
	}
}

brutella added a commit that referenced this issue Jan 20, 2025
@brutella
Copy link
Owner Author

@daniel-sullivan Thanks for reporting. This is now fixed by 86afc0a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants