Save rtts for clients

This commit is contained in:
Miek Gieben 2012-05-04 23:18:29 +02:00
parent 52d391e251
commit fc599d23fe
4 changed files with 40 additions and 34 deletions

View File

@ -13,10 +13,7 @@ import (
"time"
)
// Check incoming TSIG message. TODO(mg)
// Need a tsigstatus for that too? Don't know yet. TODO(mg)
// Incoming (just as in os.Signal)
// Incoming (documentation just as in os.Signal)
type QueryHandler interface {
QueryDNS(w RequestWriter, q *Msg)
}
@ -32,10 +29,12 @@ type RequestWriter interface {
Receive() (*Msg, error)
// Close closes the connection with the server.
Close() error
// Dials calls the server
// Dials calls the server.
Dial() error
// TsigStatus return the TSIG validation status.
// TsigStatus returns the TSIG validation status.
TsigStatus() error
// Rtt returns the duration of the request. The value is only valid after a Send()/Receive() sequence.
Rtt() time.Duration
}
// hijacked connections...?
@ -47,6 +46,8 @@ type reply struct {
tsigRequestMAC string
tsigTimersOnly bool
tsigStatus error
rtt time.Duration
t time.Time
}
// A Request is a incoming message from a Client.
@ -190,7 +191,6 @@ func (q *Query) Query() error {
if handler == nil {
handler = DefaultQueryMux
}
//forever:
for {
select {
case in := <-q.QueryChan:
@ -247,12 +247,14 @@ func (c *Client) ExchangeBuffer(inbuf []byte, a string, outbuf []byte) (n int, e
if c.Hijacked != nil {
w.conn = c.Hijacked
}
w.t = time.Now()
if n, err = w.writeClient(inbuf); err != nil {
return 0, err
}
if n, err = w.readClient(outbuf); err != nil {
return n, err
}
w.rtt = time.Since(w.t)
return n, nil
}
@ -297,22 +299,6 @@ func (w *reply) Dial() error {
return nil
}
func (w *reply) Close() (err error) {
return w.conn.Close()
}
func (w *reply) Client() *Client {
return w.client
}
func (w *reply) Request() *Msg {
return w.req
}
func (w *reply) TsigStatus() error {
return w.tsigStatus
}
func (w *reply) Receive() (*Msg, error) {
var p []byte
m := new(Msg)
@ -323,13 +309,14 @@ func (w *reply) Receive() (*Msg, error) {
p = make([]byte, DefaultMsgSize)
}
n, err := w.readClient(p)
if err != nil {
if err != nil || n == 0 {
return nil, err
}
p = p[:n]
if ok := m.Unpack(p); !ok {
return nil, ErrUnpack
}
w.rtt = time.Since(w.t)
if m.IsTsig() {
secret := m.Extra[len(m.Extra)-1].(*RR_TSIG).Hdr.Name
if _, ok := w.Client().TsigSecret[secret]; !ok {
@ -430,6 +417,7 @@ func (w *reply) Send(m *Msg) (err error) {
return ErrPack
}
}
w.t = time.Now()
if _, err = w.writeClient(out); err != nil {
return err
}
@ -505,3 +493,18 @@ func (w *reply) writeClient(p []byte) (n int, err error) {
}
return
}
// Close implents the RequestWriter.Close method
func (w *reply) Close() (err error) { return w.conn.Close() }
// Client returns a pointer to the client
func (w *reply) Client() *Client { return w.client }
// Request returns the request contained in reply
func (w *reply) Request() *Msg { return w.req }
// TsigStatus implements the RequestWriter.TsigStatus method
func (w *reply) TsigStatus() error { return w.tsigStatus }
// Rtt implements the RequestWriter.Rtt method
func (w *reply) Rtt() time.Duration { return w.rtt }

View File

@ -27,6 +27,8 @@ func q(w dns.RequestWriter, m *dns.Msg) {
if w.TsigStatus() != nil {
fmt.Printf(";; Couldn't verify TSIG signature: %s\n", w.TsigStatus().Error())
}
// Save the Rtt in the message
r.Rtt = w.Rtt()
w.Write(r)
}
@ -222,6 +224,8 @@ forever:
}
fmt.Printf("%v", r.Reply)
fmt.Printf("\n;; Query time: %.3d µs\n", r.Reply.Rtt/1e3)
// Server maybe
}
i++
if i == len(qname) {

13
msg.go
View File

@ -80,11 +80,12 @@ type MsgHdr struct {
// The layout of a DNS message.
type Msg struct {
MsgHdr
Compress bool // If true, the message will be compressed when converted to wire format.
Question []Question // Holds the RR(s) of the question section.
Answer []RR // Holds the RR(s) of the answer section.
Ns []RR // Holds the RR(s) of the authority section.
Extra []RR // Holds the RR(s) of the additional section.
Compress bool // If true, the message will be compressed when converted to wire format.
Rtt time.Duration // Round Trip Time, time it took between sending a reply and receiving the answer.
Question []Question // Holds the RR(s) of the question section.
Answer []RR // Holds the RR(s) of the answer section.
Ns []RR // Holds the RR(s) of the authority section.
Extra []RR // Holds the RR(s) of the additional section.
}
// Map of strings for each RR wire type.
@ -373,7 +374,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
case reflect.Slice:
switch val.Type().Field(i).Tag.Get("dns") {
default:
println("dns: unknown tag packing slice", val.Type().Field(i).Tag.Get("dns"), '"', val.Type().Field(i).Tag , '"')
println("dns: unknown tag packing slice", val.Type().Field(i).Tag.Get("dns"), '"', val.Type().Field(i).Tag, '"')
return lenmsg, false
case "domain-name":
for j := 0; j < val.Field(i).Len(); j++ {

View File

@ -23,7 +23,7 @@ type Handler interface {
type ResponseWriter interface {
// RemoteAddr returns the net.Addr of the client that sent the current request.
RemoteAddr() net.Addr
// Return the status of the Tsig (TsigNone, TsigVerified or TsigBad)
// TsigSttus returns the status of the Tsig (TsigNone, TsigVerified or TsigBad).
TsigStatus() error
// Write writes a reply back to the client.
Write(*Msg) error
@ -403,6 +403,4 @@ func (w *response) Write(m *Msg) (err error) {
func (w *response) RemoteAddr() net.Addr { return w.conn.remoteAddr }
// TsigStatus implements the ResponseWriter.TsigStatus method
func (w *response) TsigStatus() error {
return w.tsigStatus
}
func (w *response) TsigStatus() error { return w.tsigStatus }