1package resolver
2
3import (
4	"fmt"
5	"net"
6	"strings"
7	"time"
8
9	"github.com/0xERR0R/blocky/log"
10	"github.com/0xERR0R/blocky/model"
11	"github.com/0xERR0R/blocky/util"
12
13	"github.com/sirupsen/logrus"
14)
15
16func newRequest(question string, rType uint16, logger ...*logrus.Entry) *model.Request {
17	var loggerEntry *logrus.Entry
18	if len(logger) == 1 {
19		loggerEntry = logger[0]
20	} else {
21		loggerEntry = logrus.NewEntry(log.Log())
22	}
23
24	return &model.Request{
25		Req:      util.NewMsgWithQuestion(question, rType),
26		Log:      loggerEntry,
27		Protocol: model.RequestProtocolUDP,
28	}
29}
30
31func newRequestWithClient(question string, rType uint16, ip string, clientNames ...string) *model.Request {
32	return &model.Request{
33		ClientIP:    net.ParseIP(ip),
34		ClientNames: clientNames,
35		Req:         util.NewMsgWithQuestion(question, rType),
36		Log:         logrus.NewEntry(log.Log()),
37		RequestTS:   time.Time{},
38		Protocol:    model.RequestProtocolUDP,
39	}
40}
41
42func newRequestWithClientID(question string, rType uint16, ip string, requestClientID string) *model.Request {
43	return &model.Request{
44		ClientIP:        net.ParseIP(ip),
45		RequestClientID: requestClientID,
46		Req:             util.NewMsgWithQuestion(question, rType),
47		Log:             logrus.NewEntry(log.Log()),
48		RequestTS:       time.Time{},
49		Protocol:        model.RequestProtocolUDP,
50	}
51}
52
53// Resolver generic interface for all resolvers
54type Resolver interface {
55
56	// Resolve performs resolution of a DNS request
57	Resolve(req *model.Request) (*model.Response, error)
58
59	// Configuration prints current resolver configuration
60	Configuration() []string
61}
62
63// ChainedResolver represents a resolver, which can delegate result to the next one
64type ChainedResolver interface {
65	Resolver
66
67	// Next sets the next resolver
68	Next(n Resolver)
69
70	// GetNext returns the next resolver
71	GetNext() Resolver
72}
73
74// NextResolver is the base implementation of ChainedResolver
75type NextResolver struct {
76	next Resolver
77}
78
79// Next sets the next resolver
80func (r *NextResolver) Next(n Resolver) {
81	r.next = n
82}
83
84// GetNext returns the next resolver
85func (r *NextResolver) GetNext() Resolver {
86	return r.next
87}
88
89func logger(prefix string) *logrus.Entry {
90	return log.PrefixedLog(prefix)
91}
92
93func withPrefix(logger *logrus.Entry, prefix string) *logrus.Entry {
94	return logger.WithField("prefix", prefix)
95}
96
97// Chain creates a chain of resolvers
98func Chain(resolvers ...Resolver) Resolver {
99	for i, res := range resolvers {
100		if i+1 < len(resolvers) {
101			if cr, ok := res.(ChainedResolver); ok {
102				cr.Next(resolvers[i+1])
103			}
104		}
105	}
106
107	return resolvers[0]
108}
109
110// Name returns a user-friendly name of a resolver
111func Name(resolver Resolver) string {
112	return strings.Split(fmt.Sprintf("%T", resolver), ".")[1]
113}
114