Account for PTR answers in mdns_client
En passant, ResponseA -> the more versatile Response.
This commit is contained in:
1 parent
e9b84c968d
commit
89fa52818c
3 files changed
+72
-45
No files matched your search
+26
-16
@@ -26,7 +26,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type ResponseA struct {
|
||||
type Response struct {
|
||||
Name string
|
||||
Addr net.IP
|
||||
Err error
|
||||
@@ -34,7 +34,7 @@ type ResponseA struct {
|
||||
|
||||
type responseInfo struct {
|
||||
timeout time.Time // if no answer by this time, give up
|
||||
ch chan<- *ResponseA
|
||||
ch chan<- *Response
|
||||
}
|
||||
|
||||
// Represents one query that we have sent for one name.
|
||||
@@ -60,7 +60,7 @@ type MDNSClient struct {
|
||||
type mDNSQueryInfo struct {
|
||||
name string
|
||||
querytype uint16
|
||||
responseCh chan<- *ResponseA
|
||||
responseCh chan<- *Response
|
||||
}
|
||||
|
||||
func NewMDNSClient() (*MDNSClient, error) {
|
||||
@@ -121,7 +121,7 @@ func (c *MDNSClient) Shutdown() {
|
||||
}
|
||||
|
||||
// Async
|
||||
func (c *MDNSClient) SendQuery(name string, querytype uint16, responseCh chan<- *ResponseA) {
|
||||
func (c *MDNSClient) SendQuery(name string, querytype uint16, responseCh chan<- *Response) {
|
||||
c.queryChan <- &MDNSInteraction{
|
||||
code: CSendQuery,
|
||||
payload: mDNSQueryInfo{name, querytype, responseCh},
|
||||
@@ -209,7 +209,7 @@ func (c *MDNSClient) handleSendQuery(q mDNSQueryInfo) {
|
||||
m.RecursionDesired = false
|
||||
buf, err := m.Pack()
|
||||
if err != nil {
|
||||
q.responseCh <- &ResponseA{Err: err}
|
||||
q.responseCh <- &Response{Err: err}
|
||||
close(q.responseCh)
|
||||
return
|
||||
}
|
||||
@@ -218,7 +218,7 @@ func (c *MDNSClient) handleSendQuery(q mDNSQueryInfo) {
|
||||
id: m.Id,
|
||||
}
|
||||
if _, err = c.conn.WriteTo(buf, c.addr); err != nil {
|
||||
q.responseCh <- &ResponseA{Err: err}
|
||||
q.responseCh <- &Response{Err: err}
|
||||
close(q.responseCh)
|
||||
return
|
||||
}
|
||||
@@ -235,19 +235,29 @@ func (c *MDNSClient) handleSendQuery(q mDNSQueryInfo) {
|
||||
|
||||
func (c *MDNSClient) handleResponse(r *dns.Msg) {
|
||||
for _, answer := range r.Answer {
|
||||
var name string
|
||||
var res *Response
|
||||
|
||||
switch rr := answer.(type) {
|
||||
case *dns.A:
|
||||
name := rr.Hdr.Name
|
||||
if query, found := c.inflight[name]; found {
|
||||
for _, resp := range query.responseInfos {
|
||||
resp.ch <- &ResponseA{Name: rr.Hdr.Name, Addr: rr.A}
|
||||
close(resp.ch)
|
||||
}
|
||||
delete(c.inflight, name)
|
||||
} else {
|
||||
// We've received a response that didn't match a query
|
||||
// Do we want to cache it?
|
||||
name = rr.Hdr.Name
|
||||
res = &Response{Addr: rr.A}
|
||||
case *dns.PTR:
|
||||
name = rr.Hdr.Name
|
||||
res = &Response{Name: rr.Ptr}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
if query, found := c.inflight[name]; found {
|
||||
for _, resp := range query.responseInfos {
|
||||
resp.ch <- res
|
||||
close(resp.ch)
|
||||
}
|
||||
delete(c.inflight, name)
|
||||
} else {
|
||||
// We've received a response that didn't match a query
|
||||
// Do we want to cache it?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,27 @@ var (
|
||||
successTestName = "test1.weave."
|
||||
failTestName = "test2.weave."
|
||||
testAddr = net.ParseIP("9.8.7.6")
|
||||
testInAddr = "6.7.8.9.in-addr.arpa."
|
||||
)
|
||||
|
||||
func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
|
||||
|
||||
sendAnswer := func(m *dns.Msg) {
|
||||
buf, err := m.Pack()
|
||||
checkFatal(err)
|
||||
if buf == nil {
|
||||
log.Fatal("Nil buffer")
|
||||
}
|
||||
//log.Println("minimalServer sending:", buf)
|
||||
// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
|
||||
sendconn, err := net.DialUDP("udp", nil, ipv4Addr)
|
||||
checkFatal(err)
|
||||
|
||||
_, err = sendconn.Write(buf)
|
||||
sendconn.Close()
|
||||
checkFatal(err)
|
||||
}
|
||||
|
||||
//log.Println("minimalServer received:", req)
|
||||
if len(req.Answer) > 0 {
|
||||
return // Only interested in questions.
|
||||
@@ -23,31 +41,24 @@ func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
|
||||
if len(req.Question) != 1 {
|
||||
return // We only handle single-question messages
|
||||
}
|
||||
if req.Question[0].Name != successTestName {
|
||||
return // This is not the DNS record you are looking for
|
||||
|
||||
if req.Question[0].Qtype == dns.TypeA && req.Question[0].Name == successTestName {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(req)
|
||||
hdr := dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET, Ttl: 3600}
|
||||
a := &dns.A{hdr, testAddr}
|
||||
m.Answer = append(m.Answer, a)
|
||||
sendAnswer(m)
|
||||
} else if req.Question[0].Qtype == dns.TypePTR && req.Question[0].Name == testInAddr {
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(req)
|
||||
hdr := dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypePTR,
|
||||
Class: dns.ClassINET, Ttl: 3600}
|
||||
a := &dns.PTR{hdr, successTestName}
|
||||
m.Answer = append(m.Answer, a)
|
||||
sendAnswer(m)
|
||||
}
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(req)
|
||||
|
||||
hdr := dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET, Ttl: 3600}
|
||||
a := &dns.A{hdr, testAddr}
|
||||
m.Answer = append(m.Answer, a)
|
||||
|
||||
buf, err := m.Pack()
|
||||
checkFatal(err)
|
||||
if buf == nil {
|
||||
log.Fatal("Nil buffer")
|
||||
}
|
||||
//log.Println("minimalServer sending:", buf)
|
||||
// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
|
||||
sendconn, err := net.DialUDP("udp", nil, ipv4Addr)
|
||||
checkFatal(err)
|
||||
|
||||
_, err = sendconn.Write(buf)
|
||||
sendconn.Close()
|
||||
checkFatal(err)
|
||||
}
|
||||
|
||||
func RunLocalMulticastServer() (*dns.Server, error) {
|
||||
@@ -76,14 +87,14 @@ func setup(t *testing.T) (*MDNSClient, *dns.Server, error) {
|
||||
type testContext struct {
|
||||
receivedAddr net.IP
|
||||
receivedCount int
|
||||
channel chan *ResponseA
|
||||
channel chan *Response
|
||||
}
|
||||
|
||||
func newTestContext() *testContext {
|
||||
return &testContext{channel: make(chan *ResponseA, 4)}
|
||||
return &testContext{channel: make(chan *Response, 4)}
|
||||
}
|
||||
|
||||
func (c *testContext) checkResponse(t *testing.T, channelOk bool, resp *ResponseA) {
|
||||
func (c *testContext) checkResponse(t *testing.T, channelOk bool, resp *Response) {
|
||||
if !channelOk {
|
||||
c.channel = nil
|
||||
return
|
||||
@@ -166,4 +177,10 @@ func TestAsLookup(t *testing.T) {
|
||||
|
||||
ip, err = mdnsClient.LookupLocal("foo.example.com.")
|
||||
wt.AssertErrorType(t, err, (*LookupError)(nil), "unknown hostname")
|
||||
|
||||
name, err := mdnsClient.ReverseLookupLocal(testInAddr)
|
||||
wt.AssertNoErr(t, err)
|
||||
if !(successTestName == name) {
|
||||
t.Fatalf("Expected name %s, got %s", successTestName, name)
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func mdnsLookup(client *MDNSClient, name string, qtype uint16) (*ResponseA, error) {
|
||||
channel := make(chan *ResponseA)
|
||||
func mdnsLookup(client *MDNSClient, name string, qtype uint16) (*Response, error) {
|
||||
channel := make(chan *Response)
|
||||
client.SendQuery(name, qtype, channel)
|
||||
for resp := range channel {
|
||||
Debug.Printf("Got response name %s addr %s", resp.Name, resp.Addr)
|
||||
|
||||
Reference in new issue
Block a user