This commit is contained in:
Miek Gieben 2011-04-12 22:21:09 +02:00
parent afab5b1c10
commit 7385261dc5
1 changed files with 63 additions and 48 deletions

111
client.go
View File

@ -9,29 +9,45 @@ package dns
// This completely mirrors server.go impl. // This completely mirrors server.go impl.
import ( import (
"os" "os"
// "net"
) )
type QueryHandler interface { type QueryHandler interface {
QueryDNS(w RequestWriter, q *Msg) QueryDNS(w RequestWriter, q *Msg)
} }
// A RequestWriter interface is used by an DNS query handler to // A RequestWriter interface is used by an DNS query handler to
// construct an DNS request. // construct an DNS request.
type RequestWriter interface { type RequestWriter interface {
RemoteAddr() string RemoteAddr() string
Write([]byte) (int, os.Error) Write([]byte) (int, os.Error)
} }
/*
type conn struct {
remoteAddr net.Addr // address of remote side (sans port)
port int // port of the remote side, needed TODO(mg)
handler Handler // request handler
request []byte // the request
w chan *Msg //
hijacked bool // connection has been hijacked by hander TODO(mg)
}
type response struct {
conn *conn
req *Msg
}
*/
// QueryMux is an DNS request multiplexer. It matches the // QueryMux is an DNS request multiplexer. It matches the
// zone name of each incoming request against a list of // zone name of each incoming request against a list of
// registered patterns add calls the handler for the pattern // registered patterns add calls the handler for the pattern
// that most closely matches the zone name. // that most closely matches the zone name.
type QueryMux struct { type QueryMux struct {
m map[string]QueryHandler m map[string]QueryHandler
} }
// NewQueryMux allocates and returns a new QueryMux. // NewQueryMux allocates and returns a new QueryMux.
@ -48,7 +64,7 @@ type HandlerQueryFunc func(RequestWriter, *Msg)
// QueryDNS calls f(w, reg) // QueryDNS calls f(w, reg)
func (f HandlerQueryFunc) QueryDNS(w RequestWriter, r *Msg) { func (f HandlerQueryFunc) QueryDNS(w RequestWriter, r *Msg) {
f(w, r) f(w, r)
} }
// Helper handlers // Helper handlers
@ -56,50 +72,50 @@ func (f HandlerQueryFunc) QueryDNS(w RequestWriter, r *Msg) {
// reusing zoneMatch from server.go // reusing zoneMatch from server.go
func (mux *QueryMux) match(zone string) QueryHandler { func (mux *QueryMux) match(zone string) QueryHandler {
var h QueryHandler var h QueryHandler
var n = 0 var n = 0
for k, v := range mux.m { for k, v := range mux.m {
if !zoneMatch(k, zone) { if !zoneMatch(k, zone) {
continue continue
} }
if h == nil || len(k) > n { if h == nil || len(k) > n {
n = len(k) n = len(k)
h = v h = v
} }
} }
return h return h
} }
func (mux *QueryMux) Handle(pattern string, handler QueryHandler) { func (mux *QueryMux) Handle(pattern string, handler QueryHandler) {
if pattern == "" { if pattern == "" {
panic("dns: invalid pattern " + pattern) panic("dns: invalid pattern " + pattern)
} }
if pattern[len(pattern)-1] != '.' { // no ending . if pattern[len(pattern)-1] != '.' { // no ending .
mux.m[pattern + "."] = handler mux.m[pattern+"."] = handler
} else { } else {
mux.m[pattern]= handler mux.m[pattern] = handler
} }
} }
func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg)) { func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg)) {
mux.Handle(pattern, HandlerQueryFunc(handler)) mux.Handle(pattern, HandlerQueryFunc(handler))
} }
func (mux *QueryMux) QueryDNS(w RequestWriter, request *Msg) { func (mux *QueryMux) QueryDNS(w RequestWriter, request *Msg) {
h := mux.match(request.Question[0].Name) h := mux.match(request.Question[0].Name)
if h == nil { if h == nil {
// h = RefusedHandler() // h = RefusedHandler()
// something else // something else
} }
h.QueryDNS(w, request) h.QueryDNS(w, request)
} }
type Client struct { type Client struct {
Network string // if "tcp" a TCP query will be initiated, otherwise an UDP one Network string // if "tcp" a TCP query will be initiated, otherwise an UDP one
Attempts int // number of attempts Attempts int // number of attempts
Handler QueryHandler // handler to invoke, dns.DefaultQueryMux if nil Handler QueryHandler // handler to invoke, dns.DefaultQueryMux if nil
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
} }
@ -109,20 +125,19 @@ type Client struct {
// read requests and then call handler to reply to them. // read requests and then call handler to reply to them.
// Handler is typically nil, in which case the DefaultServeMux is used. // Handler is typically nil, in which case the DefaultServeMux is used.
func Query(w chan *Msg, handler QueryHandler) os.Error { func Query(w chan *Msg, handler QueryHandler) os.Error {
clnt := &Client{Handler: handler} clnt := &Client{Handler: handler}
return clnt.Query(w) return clnt.Query(w)
} }
func (clnt *Client) Query(w chan *Msg) os.Error { func (clnt *Client) Query(w chan *Msg) os.Error {
handler := clnt.Handler handler := clnt.Handler
if handler == nil { if handler == nil {
handler = DefaultQueryMux handler = DefaultQueryMux
} }
return nil return nil
} }
func (clnt *Client) ListenAndQuery(w chan *Msg) os.Error { func (clnt *Client) ListenAndQuery(w chan *Msg) os.Error {
/* ... */
return nil return nil
} }