complete rewrite the resolver side
make it mirror the server side and thus async and concurrent
This commit is contained in:
parent
b4ee9829bc
commit
135772de9f
4
TODO
4
TODO
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
Guidelines for the API:
|
Guidelines for the API:
|
||||||
o symmetrical, client side should be mirrored in the server
|
o symmetrical, client side should be mirrored in the server
|
||||||
o clean, small API
|
o clean, small API
|
||||||
o fast data structures (rb-tree, when they come available)
|
o fast data structures (rb-tree, when they come available)
|
||||||
o api-use should be self documenting
|
o api-use should be self documenting
|
||||||
|
o multiple queries in api
|
||||||
|
|
||||||
o make questions fqdns -- add last dot
|
o make questions fqdns -- add last dot
|
||||||
o zone structure -- only as rb-tree
|
o zone structure -- only as rb-tree or other radix tree
|
||||||
o compression (only ownernames?)
|
o compression (only ownernames?)
|
||||||
|
|
||||||
o Key2DS, also for offline keys -- need to parse them ofcourse
|
o Key2DS, also for offline keys -- need to parse them ofcourse
|
||||||
|
|
|
@ -89,10 +89,10 @@ Flags:
|
||||||
m.MsgHdr.RecursionDesired = *rd
|
m.MsgHdr.RecursionDesired = *rd
|
||||||
m.Question = make([]dns.Question, 1)
|
m.Question = make([]dns.Question, 1)
|
||||||
if *dnssec || *nsid {
|
if *dnssec || *nsid {
|
||||||
opt := new(dns.RR_OPT)
|
opt := new(dns.RR_OPT)
|
||||||
opt.SetDo()
|
opt.SetDo()
|
||||||
opt.SetVersion(0)
|
opt.SetVersion(0)
|
||||||
opt.SetUDPSize(dns.DefaultMsgSize)
|
opt.SetUDPSize(dns.DefaultMsgSize)
|
||||||
if *nsid {
|
if *nsid {
|
||||||
opt.SetNsid("")
|
opt.SetNsid("")
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ func shortMsg(in *dns.Msg) *dns.Msg {
|
||||||
for i := 0; i < len(in.Extra); i++ {
|
for i := 0; i < len(in.Extra); i++ {
|
||||||
in.Extra[i] = shortRR(in.Extra[i])
|
in.Extra[i] = shortRR(in.Extra[i])
|
||||||
}
|
}
|
||||||
return in
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
func shortRR(r dns.RR) dns.RR {
|
func shortRR(r dns.RR) dns.RR {
|
||||||
|
@ -138,8 +138,8 @@ func shortRR(r dns.RR) dns.RR {
|
||||||
t.PublicKey = "( ... )"
|
t.PublicKey = "( ... )"
|
||||||
case *dns.RR_RRSIG:
|
case *dns.RR_RRSIG:
|
||||||
t.Signature = "( ... )"
|
t.Signature = "( ... )"
|
||||||
case *dns.RR_NSEC3:
|
case *dns.RR_NSEC3:
|
||||||
t.Salt = "-" // nobody cares
|
t.Salt = "-" // nobody cares
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
5
dns.go
5
dns.go
|
@ -86,7 +86,11 @@ type Conn struct {
|
||||||
// The remote port number of the connection.
|
// The remote port number of the connection.
|
||||||
Port int
|
Port int
|
||||||
|
|
||||||
|
// Remove server (for resolver)
|
||||||
|
RemoteAddr string
|
||||||
|
|
||||||
// If TSIG is used, this holds all the information.
|
// If TSIG is used, this holds all the information.
|
||||||
|
// If unused is must be nil.
|
||||||
Tsig *Tsig
|
Tsig *Tsig
|
||||||
|
|
||||||
// Timeout in sec before giving up on a connection.
|
// Timeout in sec before giving up on a connection.
|
||||||
|
@ -366,7 +370,6 @@ func (d *Conn) Exchange(request []byte, nosend bool) (reply []byte, err os.Error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Layer violation to save memory. Its okay then...
|
|
||||||
reply = d.NewBuffer()
|
reply = d.NewBuffer()
|
||||||
n, err = d.Read(reply)
|
n, err = d.Read(reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
1
msg.go
1
msg.go
|
@ -44,6 +44,7 @@ var (
|
||||||
ErrSigGen os.Error = &Error{Error: "bad signature generation"}
|
ErrSigGen os.Error = &Error{Error: "bad signature generation"}
|
||||||
ErrAuth os.Error = &Error{Error: "bad authentication"}
|
ErrAuth os.Error = &Error{Error: "bad authentication"}
|
||||||
ErrXfrSoa os.Error = &Error{Error: "no SOA seen"}
|
ErrXfrSoa os.Error = &Error{Error: "no SOA seen"}
|
||||||
|
ErrHandle os.Error = &Error{Error: "the handle is nill"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// A manually-unpacked version of (id, bits).
|
// A manually-unpacked version of (id, bits).
|
||||||
|
|
55
resolver.go
55
resolver.go
|
@ -8,9 +8,58 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Query struct {
|
||||||
|
Msg *Msg
|
||||||
|
Conn *Conn
|
||||||
|
Err os.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// A query implementation that is asyn. and concurrent. Is also
|
||||||
|
// completely mirrors the server side implementation
|
||||||
|
|
||||||
|
func QueryTCP(in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||||
|
query("tcp", in, out, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryUDP(in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||||
|
query("udp", in, out, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func query(n string, in, out chan Query, f func(*Conn, *Msg, chan Query)) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case q := <-in:
|
||||||
|
c, err := net.Dial(n, "", q.Conn.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
//out <- nil
|
||||||
|
}
|
||||||
|
if n == "tcp" {
|
||||||
|
q.Conn.SetTCPConn(c.(*net.TCPConn), nil)
|
||||||
|
} else {
|
||||||
|
q.Conn.SetUDPConn(c.(*net.UDPConn), nil)
|
||||||
|
}
|
||||||
|
go f(q.Conn, q.Msg, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("not reached")
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryAndServeTCP(in chan Query, f func(*Conn, *Msg, chan Query)) chan Query {
|
||||||
|
out := make(chan Query)
|
||||||
|
go QueryTCP(in, out, f)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryAndServeUDP(in chan Query, f func(*Conn, *Msg, chan Query)) chan Query {
|
||||||
|
out := make(chan Query)
|
||||||
|
go QueryUDP(in, out, f)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
Servers []string // servers to use
|
Servers []string // servers to use
|
||||||
Search []string // suffixes to append to local name (not implemented)
|
Search []string // suffixes to append to local name (not implemented)
|
||||||
|
@ -47,7 +96,7 @@ func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(res.Servers); i++ {
|
for i := 0; i < len(res.Servers); i++ {
|
||||||
var d *Conn
|
var d *Conn
|
||||||
server := res.Servers[i] + ":" + port
|
server := res.Servers[i] + ":" + port
|
||||||
t := time.Nanoseconds()
|
t := time.Nanoseconds()
|
||||||
if res.Tcp {
|
if res.Tcp {
|
||||||
|
@ -68,7 +117,7 @@ func (res *Resolver) QueryTsig(q *Msg, tsig *Tsig) (d *Msg, err os.Error) {
|
||||||
}
|
}
|
||||||
in.Unpack(inb) // Discard error.
|
in.Unpack(inb) // Discard error.
|
||||||
res.Rtt[server] = time.Nanoseconds() - t
|
res.Rtt[server] = time.Nanoseconds() - t
|
||||||
d.Close()
|
d.Close()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -102,7 +151,7 @@ func (res *Resolver) XfrTsig(q *Msg, t *Tsig, m chan Xfr) {
|
||||||
Server:
|
Server:
|
||||||
for i := 0; i < len(res.Servers); i++ {
|
for i := 0; i < len(res.Servers); i++ {
|
||||||
server := res.Servers[i] + ":" + port
|
server := res.Servers[i] + ":" + port
|
||||||
d, err := Dial("tcp", "", server)
|
d, err := Dial("tcp", "", server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue Server
|
continue Server
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// DNS server implementation
|
// DNS server implementation.
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func HandleTCP(l *net.TCPListener, f func(*Conn, *Msg)) os.Error {
|
||||||
// connections. The function f may not be nil.
|
// connections. The function f may not be nil.
|
||||||
func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error {
|
func ListenAndServeTCP(addr string, f func(*Conn, *Msg)) os.Error {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return &Error{Error: "The handle function may not be nil"}
|
return ErrHandle
|
||||||
}
|
}
|
||||||
a, err := net.ResolveTCPAddr(addr)
|
a, err := net.ResolveTCPAddr(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue