mirror of
https://github.com/cmz0228/hysteria-dev.git
synced 2025-09-21 15:36:02 +00:00
feat: WIP ACL
This commit is contained in:
79
extras/outbounds/acl/parse.go
Normal file
79
extras/outbounds/acl/parse.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package acl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var linePattern = regexp.MustCompile(`^(\w+)\s*\(([^,]+)(?:,([^,]+))?(?:,([^,]+))?\)$`)
|
||||
|
||||
type InvalidSyntaxError struct {
|
||||
Line string
|
||||
LineNum int
|
||||
}
|
||||
|
||||
func (e *InvalidSyntaxError) Error() string {
|
||||
return fmt.Sprintf("invalid syntax at line %d: %s", e.LineNum, e.Line)
|
||||
}
|
||||
|
||||
// TextRule is the struct representation of a (non-comment) line parsed from an ACL file.
|
||||
// A line can be parsed into a TextRule as long as it matches one of the following patterns:
|
||||
//
|
||||
// outbound(address)
|
||||
// outbound(address,protoPort)
|
||||
// outbound(address,protoPort,hijackAddress)
|
||||
//
|
||||
// It does not check whether any of the fields is valid - it's up to the compiler to do so.
|
||||
type TextRule struct {
|
||||
Outbound string
|
||||
Address string
|
||||
ProtoPort string
|
||||
HijackAddress string
|
||||
}
|
||||
|
||||
func parseLine(line string) *TextRule {
|
||||
matches := linePattern.FindStringSubmatch(line)
|
||||
if matches == nil {
|
||||
return nil
|
||||
}
|
||||
return &TextRule{
|
||||
Outbound: matches[1],
|
||||
Address: strings.TrimSpace(matches[2]),
|
||||
ProtoPort: strings.TrimSpace(matches[3]),
|
||||
HijackAddress: strings.TrimSpace(matches[4]),
|
||||
}
|
||||
}
|
||||
|
||||
func ParseTextRules(text string) ([]TextRule, error) {
|
||||
rules := make([]TextRule, 0)
|
||||
lineNum := 0
|
||||
for _, line := range strings.Split(text, "\n") {
|
||||
lineNum++
|
||||
// Remove comments
|
||||
if i := strings.Index(line, "#"); i >= 0 {
|
||||
line = line[:i]
|
||||
}
|
||||
line = strings.TrimSpace(line)
|
||||
// Skip empty lines
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
// Parse line
|
||||
rule := parseLine(line)
|
||||
if rule == nil {
|
||||
return nil, &InvalidSyntaxError{line, lineNum}
|
||||
}
|
||||
rules = append(rules, *rule)
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func ParseTextRulesFile(filename string) ([]TextRule, error) {
|
||||
bs, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ParseTextRules(string(bs))
|
||||
}
|
Reference in New Issue
Block a user