Fix the error handling

Added new type (copied from net package) dns.Error that carries
all errors
This commit is contained in:
Miek Gieben 2011-01-03 11:29:04 +01:00
parent d4059485d5
commit 97506dafe4
3 changed files with 45 additions and 22 deletions

View File

@ -88,8 +88,12 @@ FLAGS:
} }
for _, v := range qname { for _, v := range qname {
m.Question[0] = dns.Question{v, qtype, qclass} m.Question[0] = dns.Question{v, qtype, qclass}
m.SetId()
qr <- resolver.DnsMsg{m, nil} qr <- resolver.DnsMsg{m, nil}
in := <-qr in := <-qr
if m.Id != in.Dns.Id {
fmt.Printf("Id mismatch\n")
}
if in.Dns != nil { if in.Dns != nil {
fmt.Printf("%v\n", in.Dns) fmt.Printf("%v\n", in.Dns)
} }

7
dns.go
View File

@ -29,15 +29,14 @@ import (
const Year68 = 2 << (32 - 1) const Year68 = 2 << (32 - 1)
//&DNSError{Error: "name too long", Name: name} type Error struct {
type DNSError struct {
Error string Error string
Name string Name string
Server string Server string
Timeout bool
} }
func (e *DNSError) String() string { func (e *Error) String() string {
if e == nil { if e == nil {
return "<nil>" return "<nil>"
} }

View File

@ -10,7 +10,7 @@
// Basic usage pattern for setting up a resolver: // Basic usage pattern for setting up a resolver:
// //
// res := new(Resolver) // res := new(Resolver)
// ch := NewQuerier(res) // start new resolver // ch := res.NewQuerier() // start new resolver
// res.Servers = []string{"127.0.0.1"} // set the nameserver // res.Servers = []string{"127.0.0.1"} // set the nameserver
// //
// m := new(Msg) // prepare a new message // m := new(Msg) // prepare a new message
@ -20,6 +20,8 @@
// ch <- DnsMsg{m, nil} // send the query // ch <- DnsMsg{m, nil} // send the query
// in := <-ch // wait for reply // in := <-ch // wait for reply
// //
// Note that message id checking is left to the caller
//
package resolver package resolver
import ( import (
@ -28,6 +30,9 @@ import (
"dns" "dns"
) )
const packErr = "Failed to pack message"
const servErr = "No servers could be reached"
// When communicating with a resolver, we use this structure // When communicating with a resolver, we use this structure
// to send packets to it, for sending Error must be nil. // to send packets to it, for sending Error must be nil.
// A resolver responds with a reply packet and a possible error. // A resolver responds with a reply packet and a possible error.
@ -82,11 +87,13 @@ func query(res *Resolver, msg chan DnsMsg) {
var cerr os.Error var cerr os.Error
//if len(name) >= 256 { //if len(name) >= 256 {
out.Dns.SetId() if out.Dns.Id == 0 {
// No Id sed, set it
out.Dns.SetId()
}
sending, ok := out.Dns.Pack() sending, ok := out.Dns.Pack()
if !ok { if !ok {
//println("pack failed") msg <- DnsMsg{nil, &dns.Error{Error: packErr}}
msg <- DnsMsg{nil, nil} // todo error
continue continue
} }
@ -109,9 +116,7 @@ func query(res *Resolver, msg chan DnsMsg) {
in, err = exchange_udp(c, sending, res, true) in, err = exchange_udp(c, sending, res, true)
} }
// Check id in.id != out.id // Check id in.id != out.id, should be checked in the client!
// TODO(mg)
c.Close() c.Close()
if err != nil { if err != nil {
continue continue
@ -159,7 +164,7 @@ func axfr(res *Resolver, msg chan DnsMsg) {
out.Dns.SetId() out.Dns.SetId()
sending, ok := out.Dns.Pack() sending, ok := out.Dns.Pack()
if !ok { if !ok {
msg <- DnsMsg{nil, nil} msg <- DnsMsg{nil, &dns.Error{Error: packErr}}
} }
SERVER: SERVER:
for i := 0; i < len(res.Servers); i++ { for i := 0; i < len(res.Servers); i++ {
@ -211,6 +216,7 @@ func axfr(res *Resolver, msg chan DnsMsg) {
close(msg) close(msg)
return return
} }
// TODO(mg) check in/out ID here
// With 1 successfull server, we dont get here, so // With 1 successfull server, we dont get here, so
// We've failed // We've failed
msg <- DnsMsg{nil, err} // TODO Err msg <- DnsMsg{nil, err} // TODO Err
@ -244,7 +250,9 @@ func exchange_udp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
if send { if send {
_, err := c.Write(m) _, err := c.Write(m)
if err != nil { if err != nil {
//println("error writing") if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
} }
@ -253,12 +261,10 @@ func exchange_udp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
buf := make([]byte, dns.DefaultMsgSize) // More than enough??? buf := make([]byte, dns.DefaultMsgSize) // More than enough???
n, err := c.Read(buf) n, err := c.Read(buf)
if err != nil { if err != nil {
//println("error reading") // If timeout try the next
//println(err.String()) if e, ok := err.(net.Error); ok && e.Timeout() {
// More Go foo needed continue
//if e, ok := err.(Error); ok && e.Timeout() { }
// continue
//}
return nil, err return nil, err
} }
buf = buf[0:n] buf = buf[0:n]
@ -268,7 +274,7 @@ func exchange_udp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
} }
return in, nil return in, nil
} }
return nil, nil // todo error return nil, &dns.Error{Error: servErr}
} }
// Up to res.Attempts attempts. // Up to res.Attempts attempts.
@ -300,12 +306,18 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
// With DNS over TCP we first send the length // With DNS over TCP we first send the length
_, err := c.Write(ls) _, err := c.Write(ls)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
// And then send the message // And then send the message
_, err = c.Write(m) _, err = c.Write(m)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
} }
@ -314,6 +326,9 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
// The server replies with two bytes length // The server replies with two bytes length
_, err := c.Read(lr) _, err := c.Read(lr)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
length = uint16(lr[0])<<8 | uint16(lr[1]) length = uint16(lr[0])<<8 | uint16(lr[1])
@ -323,24 +338,29 @@ func exchange_tcp(c net.Conn, m []byte, r *Resolver, send bool) (*dns.Msg, os.Er
n, err = c.Read(buf) n, err = c.Read(buf)
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
i := n i := n
if i < int(length) { if i < int(length) {
n, err = c.Read(buf[i:]) n, err = c.Read(buf[i:])
if err != nil { if err != nil {
if e, ok := err.(net.Error); ok && e.Timeout() {
continue
}
return nil, err return nil, err
} }
i += n i += n
} }
in := new(dns.Msg) in := new(dns.Msg)
if !in.Unpack(buf) { if !in.Unpack(buf) {
// println("unpacking went wrong")
continue continue
} }
return in, nil return in, nil
} }
return nil, nil // todo error return nil, &dns.Error{Error: servErr}
} }
// Check if he SOA record exists in the Answer section of // Check if he SOA record exists in the Answer section of