respwriter

package module
v0.0.0-...-6624448 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 29, 2024 License: MPL-2.0 Imports: 8 Imported by: 0

README

respwriter package

Go Reference Go Report Card


respwriter is a Go pkg that provides a meikg/dns.HandlerFunc with support for request timeouts via a dns.ResponseWriter wrapper. Among other things, it provides:

  • NewHandler(...): Creates a new dns.HandlerFunc that wraps the given handler with a RespWriter. The returned handler will use the given logger and requestTimeout to create the RespWriter.
  • NewRespWriter(...): Creates a RespWriter which is a wrapper around dns.ResponseWriter that provides "base" capabilities for the wrapped writer. Among other things, this is useful for ensuring that the wrapped writer is not used after the context is canceled.

Example

./exampes/simple/main.go

  import (
	"fmt"
	"net"
	"time"

	"github.com/jimlambrt/respwriter"
	"github.com/miekg/dns"
)

func main() {
	mux := dns.NewServeMux()
	// wrap the handler with a 100ms timeout
	handlerWithTimeout, err := respwriter.NewHandlerFunc(100*time.Millisecond, new(dnsHandler).ServeDNS)
	if err != nil {
		fmt.Printf("Failed to create handler: %s\n", err.Error())
		return
	}
	mux.HandleFunc(".", handlerWithTimeout)
	pc, err := net.ListenPacket("udp", ":0")

	if err != nil {
		fmt.Printf("Failed to start listener: %s\n", err.Error())
		return
	}

	server := &dns.Server{
		PacketConn: pc,
		Net:        "udp",
		Handler:    mux,
		UDPSize:    65535,
		ReusePort:  true,
	}

	fmt.Printf("Starting DNS server on %s\n", pc.LocalAddr())
	err = server.ListenAndServe()
	if err != nil {
		fmt.Printf("Failed to start server: %s\n", err.Error())
		return
	}
}

type dnsHandler struct{}

func (h *dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	_, ok := w.(*respwriter.RespWriter)
	if !ok {
		// this cannot happen given the way we're using
		// respwriter.NewHandlerFunc to wrap ServeDNS
		fmt.Println("Failed to cast to RespWriter")
	}
	msg := new(dns.Msg)
	msg.SetReply(r)
	msg.Authoritative = true
	for _, question := range r.Question {
		fmt.Printf("Received query: %s\n", question.Name)
		answers := resolve(question.Name, question.Qtype)
		msg.Answer = append(msg.Answer, answers...)
	}
	w.WriteMsg(msg)
}

func resolve(domain string, qtype uint16) []dns.RR {
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(domain), qtype)
	m.RecursionDesired = true

	c := new(dns.Client)
	in, _, err := c.Exchange(m, "8.8.8.8:53")
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return in.Answer
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidParameter = errors.New("invalid parameter")

Functions

func NewHandlerFunc

func NewHandlerFunc(requestTimeout time.Duration, h dns.HandlerFunc, opt ...Option) (dns.HandlerFunc, error)

NewHandlerFunc returns a new dns.HandlerFunc that wraps the given handler with a RespWriter. The returned handler will use the given logger and requestTimeout to create the RespWriter. Options supported: WithLogger

Types

type Option

type Option func(interface{})

Option defines a common functional options type which can be used in a variadic parameter pattern.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger allows you to specify an optional logger.

type RespWriter

type RespWriter struct {
	// contains filtered or unexported fields
}

RespWriter is a wrapper around dns.ResponseWriter that provides "base" capabilities for the wrapped writer. Among other things, this is useful for ensuring that the wrapped writer is not used after the context is canceled.

func NewRespWriter

func NewRespWriter(ctx context.Context, w dns.ResponseWriter, opt ...Option) *RespWriter

NewRespWriter returns a new RespWriter that wraps the given dns.ResponseWriter.

func (*RespWriter) Close

func (rw *RespWriter) Close() error

Close closes the underlying connection.

func (*RespWriter) Hijack

func (rw *RespWriter) Hijack()

Hijack hijacks the underlying connection.

func (*RespWriter) LocalAddr

func (rw *RespWriter) LocalAddr() net.Addr

LocalAddr returns the local address of the server.

func (*RespWriter) Logger

func (rw *RespWriter) Logger() *slog.Logger

Logger returns the logger to use for logging during the request.

func (*RespWriter) RemoteAddr

func (rw *RespWriter) RemoteAddr() net.Addr

RemoteAddr returns the remote address of the client.

func (*RespWriter) RequestContext

func (rw *RespWriter) RequestContext() context.Context

RequestContext returns the context for the request.

func (*RespWriter) SetLogger

func (rw *RespWriter) SetLogger(logger *slog.Logger)

SetLogger sets the logger to use for logging during the request which allows you to override the logger passed to NewRespWriter(...)

func (*RespWriter) TsigStatus

func (rw *RespWriter) TsigStatus() error

TsigStatus returns the Tsig status of the message.

func (*RespWriter) TsigTimersOnly

func (rw *RespWriter) TsigTimersOnly(b bool)

TsigTimersOnly sets the Tsig timers only flag on the message.

func (*RespWriter) Underlying

func (rw *RespWriter) Underlying() dns.ResponseWriter

Underlying returns the underlying dns.ResponseWriter

func (*RespWriter) Write

func (rw *RespWriter) Write([]byte) (int, error)

Write writes a raw buffer to the client. If the ctx is done, it returns the ctx error.

func (*RespWriter) WriteMsg

func (rw *RespWriter) WriteMsg(msg *dns.Msg) error

WriteMsg writes a DNS message to the client. If the ctx is done, it returns the ctx error.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL