|
@@ -1,6 +1,7 @@
|
|
|
package srs
|
|
|
|
|
|
import (
|
|
|
+ "bufio"
|
|
|
"compress/zlib"
|
|
|
"encoding/binary"
|
|
|
"io"
|
|
@@ -11,7 +12,7 @@ import (
|
|
|
"github.com/sagernet/sing/common"
|
|
|
"github.com/sagernet/sing/common/domain"
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
- "github.com/sagernet/sing/common/rw"
|
|
|
+ "github.com/sagernet/sing/common/varbin"
|
|
|
|
|
|
"go4.org/netipx"
|
|
|
)
|
|
@@ -38,7 +39,7 @@ const (
|
|
|
ruleItemFinal uint8 = 0xFF
|
|
|
)
|
|
|
|
|
|
-func Read(reader io.Reader, recovery bool) (ruleSet option.PlainRuleSet, err error) {
|
|
|
+func Read(reader io.Reader, recover bool) (ruleSet option.PlainRuleSet, err error) {
|
|
|
var magicBytes [3]byte
|
|
|
_, err = io.ReadFull(reader, magicBytes[:])
|
|
|
if err != nil {
|
|
@@ -60,13 +61,14 @@ func Read(reader io.Reader, recovery bool) (ruleSet option.PlainRuleSet, err err
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- length, err := rw.ReadUVariant(zReader)
|
|
|
+ bReader := bufio.NewReader(zReader)
|
|
|
+ length, err := binary.ReadUvarint(bReader)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
ruleSet.Rules = make([]option.HeadlessRule, length)
|
|
|
for i := uint64(0); i < length; i++ {
|
|
|
- ruleSet.Rules[i], err = readRule(zReader, recovery)
|
|
|
+ ruleSet.Rules[i], err = readRule(bReader, recover)
|
|
|
if err != nil {
|
|
|
err = E.Cause(err, "read rule[", i, "]")
|
|
|
return
|
|
@@ -88,20 +90,25 @@ func Write(writer io.Writer, ruleSet option.PlainRuleSet) error {
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- err = rw.WriteUVariant(zWriter, uint64(len(ruleSet.Rules)))
|
|
|
+ bWriter := bufio.NewWriter(zWriter)
|
|
|
+ _, err = varbin.WriteUvarint(bWriter, uint64(len(ruleSet.Rules)))
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
for _, rule := range ruleSet.Rules {
|
|
|
- err = writeRule(zWriter, rule)
|
|
|
+ err = writeRule(bWriter, rule)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
+ err = bWriter.Flush()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
return zWriter.Close()
|
|
|
}
|
|
|
|
|
|
-func readRule(reader io.Reader, recovery bool) (rule option.HeadlessRule, err error) {
|
|
|
+func readRule(reader varbin.Reader, recover bool) (rule option.HeadlessRule, err error) {
|
|
|
var ruleType uint8
|
|
|
err = binary.Read(reader, binary.BigEndian, &ruleType)
|
|
|
if err != nil {
|
|
@@ -110,17 +117,17 @@ func readRule(reader io.Reader, recovery bool) (rule option.HeadlessRule, err er
|
|
|
switch ruleType {
|
|
|
case 0:
|
|
|
rule.Type = C.RuleTypeDefault
|
|
|
- rule.DefaultOptions, err = readDefaultRule(reader, recovery)
|
|
|
+ rule.DefaultOptions, err = readDefaultRule(reader, recover)
|
|
|
case 1:
|
|
|
rule.Type = C.RuleTypeLogical
|
|
|
- rule.LogicalOptions, err = readLogicalRule(reader, recovery)
|
|
|
+ rule.LogicalOptions, err = readLogicalRule(reader, recover)
|
|
|
default:
|
|
|
err = E.New("unknown rule type: ", ruleType)
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func writeRule(writer io.Writer, rule option.HeadlessRule) error {
|
|
|
+func writeRule(writer varbin.Writer, rule option.HeadlessRule) error {
|
|
|
switch rule.Type {
|
|
|
case C.RuleTypeDefault:
|
|
|
return writeDefaultRule(writer, rule.DefaultOptions)
|
|
@@ -131,7 +138,7 @@ func writeRule(writer io.Writer, rule option.HeadlessRule) error {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func readDefaultRule(reader io.Reader, recovery bool) (rule option.DefaultHeadlessRule, err error) {
|
|
|
+func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHeadlessRule, err error) {
|
|
|
var lastItemType uint8
|
|
|
for {
|
|
|
var itemType uint8
|
|
@@ -158,6 +165,9 @@ func readDefaultRule(reader io.Reader, recovery bool) (rule option.DefaultHeadle
|
|
|
return
|
|
|
}
|
|
|
rule.DomainMatcher = matcher
|
|
|
+ if recover {
|
|
|
+ rule.Domain, rule.DomainSuffix = matcher.Dump()
|
|
|
+ }
|
|
|
case ruleItemDomainKeyword:
|
|
|
rule.DomainKeyword, err = readRuleItemString(reader)
|
|
|
case ruleItemDomainRegex:
|
|
@@ -167,7 +177,7 @@ func readDefaultRule(reader io.Reader, recovery bool) (rule option.DefaultHeadle
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- if recovery {
|
|
|
+ if recover {
|
|
|
rule.SourceIPCIDR = common.Map(rule.SourceIPSet.Prefixes(), netip.Prefix.String)
|
|
|
}
|
|
|
case ruleItemIPCIDR:
|
|
@@ -175,7 +185,7 @@ func readDefaultRule(reader io.Reader, recovery bool) (rule option.DefaultHeadle
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- if recovery {
|
|
|
+ if recover {
|
|
|
rule.IPCIDR = common.Map(rule.IPSet.Prefixes(), netip.Prefix.String)
|
|
|
}
|
|
|
case ruleItemSourcePort:
|
|
@@ -209,7 +219,7 @@ func readDefaultRule(reader io.Reader, recovery bool) (rule option.DefaultHeadle
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func writeDefaultRule(writer io.Writer, rule option.DefaultHeadlessRule) error {
|
|
|
+func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule) error {
|
|
|
err := binary.Write(writer, binary.BigEndian, uint8(0))
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -327,73 +337,31 @@ func writeDefaultRule(writer io.Writer, rule option.DefaultHeadlessRule) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func readRuleItemString(reader io.Reader) ([]string, error) {
|
|
|
- length, err := rw.ReadUVariant(reader)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- value := make([]string, length)
|
|
|
- for i := uint64(0); i < length; i++ {
|
|
|
- value[i], err = rw.ReadVString(reader)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
- return value, nil
|
|
|
+func readRuleItemString(reader varbin.Reader) ([]string, error) {
|
|
|
+ return varbin.ReadValue[[]string](reader, binary.BigEndian)
|
|
|
}
|
|
|
|
|
|
-func writeRuleItemString(writer io.Writer, itemType uint8, value []string) error {
|
|
|
- err := binary.Write(writer, binary.BigEndian, itemType)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- err = rw.WriteUVariant(writer, uint64(len(value)))
|
|
|
+func writeRuleItemString(writer varbin.Writer, itemType uint8, value []string) error {
|
|
|
+ err := writer.WriteByte(itemType)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- for _, item := range value {
|
|
|
- err = rw.WriteVString(writer, item)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
- return nil
|
|
|
+ return varbin.Write(writer, binary.BigEndian, value)
|
|
|
}
|
|
|
|
|
|
-func readRuleItemUint16(reader io.Reader) ([]uint16, error) {
|
|
|
- length, err := rw.ReadUVariant(reader)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- value := make([]uint16, length)
|
|
|
- for i := uint64(0); i < length; i++ {
|
|
|
- err = binary.Read(reader, binary.BigEndian, &value[i])
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
- return value, nil
|
|
|
+func readRuleItemUint16(reader varbin.Reader) ([]uint16, error) {
|
|
|
+ return varbin.ReadValue[[]uint16](reader, binary.BigEndian)
|
|
|
}
|
|
|
|
|
|
-func writeRuleItemUint16(writer io.Writer, itemType uint8, value []uint16) error {
|
|
|
- err := binary.Write(writer, binary.BigEndian, itemType)
|
|
|
+func writeRuleItemUint16(writer varbin.Writer, itemType uint8, value []uint16) error {
|
|
|
+ err := writer.WriteByte(itemType)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- err = rw.WriteUVariant(writer, uint64(len(value)))
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- for _, item := range value {
|
|
|
- err = binary.Write(writer, binary.BigEndian, item)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
- return nil
|
|
|
+ return varbin.Write(writer, binary.BigEndian, value)
|
|
|
}
|
|
|
|
|
|
-func writeRuleItemCIDR(writer io.Writer, itemType uint8, value []string) error {
|
|
|
+func writeRuleItemCIDR(writer varbin.Writer, itemType uint8, value []string) error {
|
|
|
var builder netipx.IPSetBuilder
|
|
|
for i, prefixString := range value {
|
|
|
prefix, err := netip.ParsePrefix(prefixString)
|
|
@@ -419,9 +387,8 @@ func writeRuleItemCIDR(writer io.Writer, itemType uint8, value []string) error {
|
|
|
return writeIPSet(writer, ipSet)
|
|
|
}
|
|
|
|
|
|
-func readLogicalRule(reader io.Reader, recovery bool) (logicalRule option.LogicalHeadlessRule, err error) {
|
|
|
- var mode uint8
|
|
|
- err = binary.Read(reader, binary.BigEndian, &mode)
|
|
|
+func readLogicalRule(reader varbin.Reader, recovery bool) (logicalRule option.LogicalHeadlessRule, err error) {
|
|
|
+ mode, err := reader.ReadByte()
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
@@ -434,7 +401,7 @@ func readLogicalRule(reader io.Reader, recovery bool) (logicalRule option.Logica
|
|
|
err = E.New("unknown logical mode: ", mode)
|
|
|
return
|
|
|
}
|
|
|
- length, err := rw.ReadUVariant(reader)
|
|
|
+ length, err := binary.ReadUvarint(reader)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
@@ -453,7 +420,7 @@ func readLogicalRule(reader io.Reader, recovery bool) (logicalRule option.Logica
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func writeLogicalRule(writer io.Writer, logicalRule option.LogicalHeadlessRule) error {
|
|
|
+func writeLogicalRule(writer varbin.Writer, logicalRule option.LogicalHeadlessRule) error {
|
|
|
err := binary.Write(writer, binary.BigEndian, uint8(1))
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -469,7 +436,7 @@ func writeLogicalRule(writer io.Writer, logicalRule option.LogicalHeadlessRule)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- err = rw.WriteUVariant(writer, uint64(len(logicalRule.Rules)))
|
|
|
+ _, err = varbin.WriteUvarint(writer, uint64(len(logicalRule.Rules)))
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|