core/admission/admission.go
2022-03-16 19:40:29 +08:00

90 lines
1.9 KiB
Go

package admission
import (
"net"
"strconv"
"github.com/go-gost/core/common/matcher"
"github.com/go-gost/core/logger"
)
type Admission interface {
Admit(addr string) bool
}
type options struct {
logger logger.Logger
}
type Option func(opts *options)
func LoggerOption(logger logger.Logger) Option {
return func(opts *options) {
opts.logger = logger
}
}
type admission struct {
matchers []matcher.Matcher
reversed bool
options options
}
// NewAdmission creates and initializes a new Admission using matchers as its match rules.
// The rules will be reversed if the reversed is true.
func NewAdmission(reversed bool, matchers []matcher.Matcher, opts ...Option) Admission {
options := options{}
for _, opt := range opts {
opt(&options)
}
return &admission{
matchers: matchers,
reversed: reversed,
options: options,
}
}
// NewAdmissionPatterns creates and initializes a new Admission using matcher patterns as its match rules.
// The rules will be reversed if the reverse is true.
func NewAdmissionPatterns(reversed bool, patterns []string, opts ...Option) Admission {
var matchers []matcher.Matcher
for _, pattern := range patterns {
if m := matcher.NewMatcher(pattern); m != nil {
matchers = append(matchers, m)
}
}
return NewAdmission(reversed, matchers, opts...)
}
func (p *admission) Admit(addr string) bool {
if addr == "" || p == nil || len(p.matchers) == 0 {
p.options.logger.Debugf("admission: %v is denied", addr)
return false
}
// try to strip the port
if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" {
if p, _ := strconv.Atoi(port); p > 0 { // port is valid
addr = host
}
}
var matched bool
for _, matcher := range p.matchers {
if matcher == nil {
continue
}
if matcher.Match(addr) {
matched = true
break
}
}
b := !p.reversed && matched ||
p.reversed && !matched
if !b {
p.options.logger.Debugf("admission: %v is denied", addr)
}
return b
}