Files
AdGuardDNS/internal/dnsserver/error.go
Andrey Meshkov 1ff64f80f5 Sync v2.12.0
2025-03-07 11:05:38 +03:00

86 lines
2.3 KiB
Go

package dnsserver
import (
"context"
"fmt"
"io"
"log/slog"
"net"
"os"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
)
// Common Errors And Error Helpers
const (
// ErrServerAlreadyStarted signals that server has been already started
// Can be returned by Server.ListenAndServe.
ErrServerAlreadyStarted errors.Error = "dnsserver: server already started"
// ErrServerNotStarted signals that server has been already stopped
// Can be returned by Server.Shutdown.
ErrServerNotStarted errors.Error = "dnsserver: server not started"
// ErrInvalidArgument signals that the argument passed to the function
// is not valid.
ErrInvalidArgument errors.Error = "dnsserver: invalid argument"
// ErrProtocol signals that the DNS message violates the protocol.
ErrProtocol errors.Error = "dnsserver: protocol error"
)
// WriteError is returned from WriteMsg.
type WriteError struct {
// Err is the underlying error.
Err error
// Protocol is either "tcp" or "udp".
Protocol string
}
// type check
var _ error = (*WriteError)(nil)
// Error implements the error interface for *WriteError.
func (err *WriteError) Error() (msg string) {
return fmt.Sprintf("%s: writing message: %s", err.Protocol, err.Err)
}
// type check
var _ errors.Wrapper = (*WriteError)(nil)
// Unwrap implements the errors.Wrapper interface for *WriteError.
func (err *WriteError) Unwrap() (unwrapped error) {
return err.Err
}
// isNonCriticalNetError is a helper that returns true if err is a net.Error and
// its Timeout method returns true.
//
// TODO(ameshkov): Replace this code with more precise error handling in each
// case. It seems like all places where this function is used should detect
// precise error conditions for exiting a loop instead of this.
func isNonCriticalNetError(err error) (ok bool) {
if errors.Is(os.ErrDeadlineExceeded, err) {
return true
}
var netErr net.Error
return errors.As(err, &netErr) && netErr.Timeout()
}
// closeWithLog closes c and logs a debug message if c.Close returns an error
// that isn't [net.ErrClosed].
//
// TODO(a.garipov): Unify error handling with regards to [io.EOF],
// net.ErrClosed, etc.
func closeWithLog(ctx context.Context, l *slog.Logger, msg string, c io.Closer) {
err := c.Close()
if err != nil && !errors.Is(err, net.ErrClosed) {
l.DebugContext(ctx, msg, slogutil.KeyError, err)
}
}