async client library starting to exist

This commit is contained in:
Miek Gieben 2011-04-12 21:44:56 +02:00
parent f3e86f9157
commit afab5b1c10
3 changed files with 138 additions and 11 deletions

View File

@ -8,6 +8,7 @@ include $(GOROOT)/src/Make.inc
TARG=dns
GOFILES=\
clientconfig.go\
client.go\
config.go\
defaults.go\
dns.go\
@ -16,7 +17,6 @@ GOFILES=\
keygen.go\
msg.go\
nsec3.go \
resolver.go\
server.go \
tsig.go\
types.go\

128
client.go Normal file
View File

@ -0,0 +1,128 @@
package dns
// A concurrent client implementation.
// Client sends query to a channel which
// will then handle the query. Returned replys
// are return on another channel. Ready for handling --- same
// setup for server - a HANDLER function that gets run
// when the query returns.
// This completely mirrors server.go impl.
import (
"os"
)
type QueryHandler interface {
QueryDNS(w RequestWriter, q *Msg)
}
// A RequestWriter interface is used by an DNS query handler to
// construct an DNS request.
type RequestWriter interface {
RemoteAddr() string
Write([]byte) (int, os.Error)
}
// QueryMux is an DNS request multiplexer. It matches the
// zone name of each incoming request against a list of
// registered patterns add calls the handler for the pattern
// that most closely matches the zone name.
type QueryMux struct {
m map[string]QueryHandler
}
// NewQueryMux allocates and returns a new QueryMux.
func NewQueryMux() *QueryMux { return &QueryMux{make(map[string]QueryHandler)} }
// DefaultQueryMux is the default QueryMux used by Query.
var DefaultQueryMux = NewQueryMux()
// The HandlerQueryFunc type is an adapter to allow the use of
// ordinary functions as DNS query handlers. If f is a function
// with the appropriate signature, HandlerQueryFunc(f) is a
// QeuryHandler object that calls f.
type HandlerQueryFunc func(RequestWriter, *Msg)
// QueryDNS calls f(w, reg)
func (f HandlerQueryFunc) QueryDNS(w RequestWriter, r *Msg) {
f(w, r)
}
// Helper handlers
// Todo
// reusing zoneMatch from server.go
func (mux *QueryMux) match(zone string) QueryHandler {
var h QueryHandler
var n = 0
for k, v := range mux.m {
if !zoneMatch(k, zone) {
continue
}
if h == nil || len(k) > n {
n = len(k)
h = v
}
}
return h
}
func (mux *QueryMux) Handle(pattern string, handler QueryHandler) {
if pattern == "" {
panic("dns: invalid pattern " + pattern)
}
if pattern[len(pattern)-1] != '.' { // no ending .
mux.m[pattern + "."] = handler
} else {
mux.m[pattern]= handler
}
}
func (mux *QueryMux) HandleQueryFunc(pattern string, handler func(RequestWriter, *Msg)) {
mux.Handle(pattern, HandlerQueryFunc(handler))
}
func (mux *QueryMux) QueryDNS(w RequestWriter, request *Msg) {
h := mux.match(request.Question[0].Name)
if h == nil {
// h = RefusedHandler()
// something else
}
h.QueryDNS(w, request)
}
type Client struct {
Network string // if "tcp" a TCP query will be initiated, otherwise an UDP one
Attempts int // number of attempts
Handler QueryHandler // handler to invoke, dns.DefaultQueryMux if nil
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
}
// Query accepts incoming DNS request,
// Write to in
// creating a new service thread for each. The service threads
// read requests and then call handler to reply to them.
// Handler is typically nil, in which case the DefaultServeMux is used.
func Query(w chan *Msg, handler QueryHandler) os.Error {
clnt := &Client{Handler: handler}
return clnt.Query(w)
}
func (clnt *Client) Query(w chan *Msg) os.Error {
handler := clnt.Handler
if handler == nil {
handler = DefaultQueryMux
}
return nil
}
func (clnt *Client) ListenAndQuery(w chan *Msg) os.Error {
return nil
}

View File

@ -18,7 +18,6 @@ type Handler interface {
// of the IP address and a boolean saying it may connect (true) or not.
}
// TODO(mg): fit axfr responses in here too???
// A ResponseWriter interface is used by an DNS handler to
// construct an DNS response.
type ResponseWriter interface {
@ -156,6 +155,15 @@ func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
// A Server defines parameters for running an DNS server.
type Server struct {
Addr string // address to listen on, ":dns" if empty
Network string // if "tcp" it will invoke a TCP listener, otherwise an UDP one
Handler Handler // handler to invoke, dns.DefaultServeMux if nil
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
}
// Serve accepts incoming DNS request on the TCP listener l,
// creating a new service thread for each. The service threads
// read requests and then call handler to reply to them.
@ -174,15 +182,6 @@ func ServeUDP(l *net.UDPConn, handler Handler) os.Error {
return srv.ServeUDP(l)
}
// A Server defines parameters for running an HTTP server.
type Server struct {
Addr string // address to listen on, ":dns" if empty
Network string // If "tcp" it will invoke a TCP listener, otherwise an UDP one
Handler Handler // handler to invoke, http.DefaultServeMux if nil
ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
}
// Fixes for udp/tcp
func (srv *Server) ListenAndServe() os.Error {
addr := srv.Addr