Skip to content

Commit

Permalink
Merge pull request #43 from Tantalor93/options
Browse files Browse the repository at this point in the history
use configuration options for constructing client
  • Loading branch information
Tantalor93 authored Oct 28, 2024
2 parents 65c7881 + fae0e83 commit 656a57d
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 40 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

# Dependency directories (remove the comment below to include it)
# vendor/

*.iml
.idea
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ go get github.com/tantalor93/doq-go

## Examples
```
// create new DoQ Client
client, err := doq.NewClient("dns.adguard-dns.com:853", doq.Options{})
if err != nil {
panic(err)
}
// create client with default settings resolving via AdGuard DoQ Server
client := doq.NewClient("dns.adguard-dns.com:853")
// create new query
// prepare payload
q := dns.Msg{}
q.SetQuestion("www.google.com.", dns.TypeA)
// send query
var resp *dns.Msg
resp, err = client.Send(context.Background(), &q)
fmt.Println(resp ,err)
// send DNS query
r, err := client.Send(context.Background(), &q)
if err != nil {
panic(err)
}
// do something with response
fmt.Println(dns.RcodeToString[r.Rcode])
```
39 changes: 13 additions & 26 deletions doq/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,27 @@ type Client struct {
conn quic.Connection

addr string
tlsconfig *tls.Config
tlsConfig *tls.Config
writeTimeout time.Duration
readTimeout time.Duration
connectTimeout time.Duration
}

// Options encapsulates configuration options for doq.Client.
// By default, WriteTimeout, ReadTimeout and ConnectTimeout is zero, meaning there is no timeout.
type Options struct {
TLSConfig *tls.Config
WriteTimeout time.Duration
ReadTimeout time.Duration
ConnectTimeout time.Duration
}

// NewClient creates a new doq.Client used for sending DoQ queries.
func NewClient(addr string, options Options) *Client {
client := Client{}

client.addr = addr

if options.TLSConfig == nil {
client.tlsconfig = &tls.Config{MinVersion: tls.VersionTLS12}
} else {
client.tlsconfig = options.TLSConfig.Clone()
func NewClient(addr string, opts ...Option) *Client {
client := &Client{
addr: addr,
tlsConfig: &tls.Config{MinVersion: tls.VersionTLS12},
}
for _, opt := range opts {
opt.apply(client)
}

// override protocol negotiation to DoQ, all the other stuff (like certificates, cert pools, insecure skip) is up to the user of library
client.tlsconfig.NextProtos = []string{"doq"}
client.readTimeout = options.ReadTimeout
client.writeTimeout = options.WriteTimeout
client.connectTimeout = options.ConnectTimeout
// override protocol negotiation to DoQ, all the other stuff (like certificates, cert pools, insecure skip)
// is up to the user of library
client.tlsConfig.NextProtos = []string{"doq"}

return &client
return client
}

func (c *Client) dial(ctx context.Context) error {
Expand All @@ -76,7 +63,7 @@ func (c *Client) dial(ctx context.Context) error {
done := make(chan interface{})

go func() {
conn, err := quic.DialAddrEarly(connectCtx, c.addr, c.tlsconfig, nil)
conn, err := quic.DialAddrEarly(connectCtx, c.addr, c.tlsConfig, nil)
if err != nil {
done <- err
return
Expand Down
9 changes: 5 additions & 4 deletions doq/client_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package doq
package doq_test

import (
"context"
Expand All @@ -15,6 +15,7 @@ import (
"github.com/quic-go/quic-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tantalor93/doq-go/doq"
)

type doqServer struct {
Expand Down Expand Up @@ -85,7 +86,7 @@ func Test(t *testing.T) {
server.start()
defer server.stop()

client := NewClient(server.addr, Options{TLSConfig: generateTLSConfig()})
client := doq.NewClient(server.addr, doq.WithTLSConfig(generateTLSConfig()))

msg := dns.Msg{}
msg.SetQuestion("example.org.", dns.TypeA)
Expand All @@ -102,7 +103,7 @@ func TestWriteTimeout(t *testing.T) {
server.start()
defer server.stop()

client := NewClient(server.addr, Options{TLSConfig: generateTLSConfig(), WriteTimeout: 1 * time.Nanosecond})
client := doq.NewClient(server.addr, doq.WithTLSConfig(generateTLSConfig()), doq.WithWriteTimeout(time.Nanosecond))

msg := dns.Msg{}
msg.SetQuestion("example.org.", dns.TypeA)
Expand All @@ -117,7 +118,7 @@ func TestReadTimeout(t *testing.T) {
server.start()
defer server.stop()

client := NewClient(server.addr, Options{TLSConfig: generateTLSConfig(), ReadTimeout: 1 * time.Nanosecond})
client := doq.NewClient(server.addr, doq.WithTLSConfig(generateTLSConfig()), doq.WithReadTimeout(time.Nanosecond))

msg := dns.Msg{}
msg.SetQuestion("example.org.", dns.TypeA)
Expand Down
71 changes: 71 additions & 0 deletions doq/opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package doq

import (
"crypto/tls"
"time"
)

// Option represents configuration options for doq.Client.
type Option interface {
apply(c *Client)
}

type tlsConfigOption struct {
tlsConfig *tls.Config
}

func (o *tlsConfigOption) apply(c *Client) {
c.tlsConfig = o.tlsConfig.Clone()
}

// WithTLSConfig is a configuration option that sets TLS configuration for the doq.Client.
func WithTLSConfig(c *tls.Config) Option {
return &tlsConfigOption{
tlsConfig: c,
}
}

type writeTimeoutOption struct {
writeTimeout time.Duration
}

func (o *writeTimeoutOption) apply(c *Client) {
c.writeTimeout = o.writeTimeout
}

// WithWriteTimeout is a configuration option that sets write timeout for the doq.Client.
func WithWriteTimeout(t time.Duration) Option {
return &writeTimeoutOption{
writeTimeout: t,
}
}

type readTimeoutOption struct {
readTimeout time.Duration
}

func (o *readTimeoutOption) apply(c *Client) {
c.readTimeout = o.readTimeout
}

// WithReadTimeout is a configuration option that sets read timeout for the doq.Client.
func WithReadTimeout(t time.Duration) Option {
return &readTimeoutOption{
readTimeout: t,
}
}

type connectTimeoutOption struct {
connectTimeout time.Duration
}

func (o *connectTimeoutOption) apply(c *Client) {
c.connectTimeout = o.connectTimeout
}

// WithConnectTimeout is a configuration option that sets connect timeout for the doq.Client.
func WithConnectTimeout(t time.Duration) Option {
return &connectTimeoutOption{
connectTimeout: t,
}
}

0 comments on commit 656a57d

Please sign in to comment.