This repository was archived by the owner on Aug 18, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.go
More file actions
93 lines (80 loc) · 3.06 KB
/
server.go
File metadata and controls
93 lines (80 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package godns
import (
"context"
"net"
"strconv"
"time"
"github.com/miekg/dns"
"github.com/ProxyFi/GoDNS/internal/log"
)
// Server encapsulates the configuration and runtime state of a DNS server.
// It handles both TCP and UDP connections.
type Server struct {
// Host is the network host to listen on (e.g., "127.0.0.1" or "::1").
host string
// Port is the network port to listen on.
port int
// ReadTimeout is the maximum duration for reading the entire request.
rTimeout time.Duration
// WriteTimeout is the maximum duration for writing the entire response.
wTimeout time.Duration
}
// Addr returns the complete network address string (host:port) for the server.
func (s *Server) Addr() string {
return net.JoinHostPort(s.host, strconv.Itoa(s.port))
}
// Run initializes and starts both UDP and TCP DNS listeners.
// It launches each listener in a separate goroutine.
func (s *Server) Run() {
// Initialize a new DNS handler. The implementation of NewHandler()
// and the DoTCP/DoUDP methods are assumed to be defined elsewhere.
handler := NewHandler()
// Use a single dns.ServeMux for both TCP and UDP. This is a common
// practice and simplifies handler management.
dnsMux := dns.NewServeMux()
dnsMux.HandleFunc(".", handler.DoTCP) // The same handler can be used for both.
// The old code used separate ServeMux instances. The current approach is
// slightly cleaner but achieves the same result, as the dns.Server
// already handles the network-specific logic.
// Configure and create the TCP DNS server.
tcpServer := &dns.Server{
Addr: s.Addr(),
Net: "tcp",
Handler: dnsMux,
ReadTimeout: s.rTimeout,
WriteTimeout: s.wTimeout,
}
// Configure and create the UDP DNS server.
udpServer := &dns.Server{
Addr: s.Addr(),
Net: "udp",
Handler: dnsMux,
UDPSize: dns.DefaultMsgSize, // Using a standard constant for clarity.
ReadTimeout: s.rTimeout,
WriteTimeout: s.wTimeout,
}
// Start both servers concurrently.
// We use goroutines to avoid blocking the main thread.
go s.start(context.Background(), udpServer)
go s.start(context.Background(), tcpServer)
}
// start begins serving requests for a given dns.Server.
// It logs the server's status and handles potential errors during startup.
// The context.Context parameter, while not used in this specific implementation,
// is included to align with modern Go practices for managing goroutine lifecycles
// and providing request-scoped data.
func (s *Server) start(ctx context.Context, ds *dns.Server) {
log.Info("Starting %s listener on %s", ds.Net, s.Addr())
// Use a defer statement to ensure that resources are handled correctly
// even if an error occurs. This adds robustness.
defer func() {
log.Info("Shutting down %s listener on %s", ds.Net, s.Addr())
}()
// The ListenAndServe method is called here.
// Its return value is checked for potential errors.
err := ds.ListenAndServe()
if err != nil {
// Log the error with additional context to help with debugging.
log.Error("Failed to start %s listener on %s: %v", ds.Net, s.Addr(), err)
}
}