ooni-probe-cli/internal/engine/legacy/errorsx/errorsx.go

71 lines
1.9 KiB
Go
Raw Normal View History

// Package errorsx contains error extensions.
package errorsx
import (
"errors"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
// SafeErrWrapperBuilder contains a builder for ErrWrapper that
// is safe, i.e., behaves correctly when the error is nil.
type SafeErrWrapperBuilder struct {
// Error is the error, if any
Error error
// Classifier is the local error to string classifier. When there is no
// configured classifier we will use the generic classifier.
Classifier func(err error) string
// Operation is the operation that failed
Operation string
}
// MaybeBuild builds a new ErrWrapper, if b.Error is not nil, and returns
// a nil error value, instead, if b.Error is nil.
func (b SafeErrWrapperBuilder) MaybeBuild() (err error) {
if b.Error != nil {
classifier := b.Classifier
if classifier == nil {
classifier = netxlite.ClassifyGenericError
}
err = &netxlite.ErrWrapper{
Failure: classifier(b.Error),
Operation: toOperationString(b.Error, b.Operation),
WrappedErr: b.Error,
}
}
return
}
func toOperationString(err error, operation string) string {
var errwrapper *netxlite.ErrWrapper
if errors.As(err, &errwrapper) {
// Basically, as explained in ErrWrapper docs, let's
// keep the child major operation, if any.
if errwrapper.Operation == netxlite.ConnectOperation {
return errwrapper.Operation
}
if errwrapper.Operation == netxlite.HTTPRoundTripOperation {
return errwrapper.Operation
}
if errwrapper.Operation == netxlite.ResolveOperation {
return errwrapper.Operation
}
if errwrapper.Operation == netxlite.TLSHandshakeOperation {
return errwrapper.Operation
}
if errwrapper.Operation == netxlite.QUICHandshakeOperation {
return errwrapper.Operation
}
if errwrapper.Operation == "quic_handshake_start" {
return netxlite.QUICHandshakeOperation
}
if errwrapper.Operation == "quic_handshake_done" {
return netxlite.QUICHandshakeOperation
}
// FALLTHROUGH
}
return operation
}