mirror of
https://github.com/amnezia-vpn/amneziawg-go.git
synced 2026-05-26 13:50:38 +00:00
f6542209f4
* feat: ranged H1-H4 * feat: S3, S4 support * chore: updated awg-tools version --------- Co-authored-by: Yaroslav Gurov <ygurov@proton.me>
98 lines
2.7 KiB
Go
98 lines
2.7 KiB
Go
package awg
|
|
|
|
import (
|
|
"cmp"
|
|
"fmt"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type MagicHeader struct {
|
|
Min uint32
|
|
Max uint32
|
|
}
|
|
|
|
func NewMagicHeaderSameValue(value uint32) MagicHeader {
|
|
return MagicHeader{Min: value, Max: value}
|
|
}
|
|
|
|
func NewMagicHeader(min, max uint32) (MagicHeader, error) {
|
|
if min > max {
|
|
return MagicHeader{}, fmt.Errorf("min (%d) cannot be greater than max (%d)", min, max)
|
|
}
|
|
|
|
return MagicHeader{Min: min, Max: max}, nil
|
|
}
|
|
|
|
func ParseMagicHeader(key, value string) (MagicHeader, error) {
|
|
hyphenIdx := strings.Index(value, "-")
|
|
if hyphenIdx == -1 {
|
|
// if there is no hyphen, we treat it as single magic header value
|
|
magicHeader, err := strconv.ParseUint(value, 10, 32)
|
|
if err != nil {
|
|
return MagicHeader{}, fmt.Errorf("parse key: %s; value: %s; %w", key, value, err)
|
|
}
|
|
|
|
return NewMagicHeader(uint32(magicHeader), uint32(magicHeader))
|
|
}
|
|
|
|
minStr := value[:hyphenIdx]
|
|
maxStr := value[hyphenIdx+1:]
|
|
if len(minStr) == 0 || len(maxStr) == 0 {
|
|
return MagicHeader{}, fmt.Errorf("invalid value for key: %s; value: %s; expected format: min-max", key, value)
|
|
}
|
|
|
|
min, err := strconv.ParseUint(minStr, 10, 32)
|
|
if err != nil {
|
|
return MagicHeader{}, fmt.Errorf("parse min key: %s; value: %s; %w", key, minStr, err)
|
|
}
|
|
|
|
max, err := strconv.ParseUint(maxStr, 10, 32)
|
|
if err != nil {
|
|
return MagicHeader{}, fmt.Errorf("parse max key: %s; value: %s; %w", key, maxStr, err)
|
|
}
|
|
|
|
magicHeader, err := NewMagicHeader(uint32(min), uint32(max))
|
|
if err != nil {
|
|
return MagicHeader{}, fmt.Errorf("new magicHeader key: %s; value: %s-%s; %w", key, minStr, maxStr, err)
|
|
}
|
|
|
|
return magicHeader, nil
|
|
}
|
|
|
|
type MagicHeaders struct {
|
|
Values []MagicHeader
|
|
randomGenerator RandomNumberGenerator[uint32]
|
|
}
|
|
|
|
func NewMagicHeaders(headerValues []MagicHeader) (MagicHeaders, error) {
|
|
if len(headerValues) != 4 {
|
|
return MagicHeaders{}, fmt.Errorf("all header types should be included: %v", headerValues)
|
|
}
|
|
|
|
sortedMagicHeaders := slices.SortedFunc(slices.Values(headerValues), func(lhs MagicHeader, rhs MagicHeader) int {
|
|
return cmp.Compare(lhs.Min, rhs.Min)
|
|
})
|
|
|
|
for i := range 3 {
|
|
if sortedMagicHeaders[i].Max >= sortedMagicHeaders[i+1].Min {
|
|
return MagicHeaders{}, fmt.Errorf(
|
|
"magic headers shouldn't overlap; %v > %v",
|
|
sortedMagicHeaders[i].Max,
|
|
sortedMagicHeaders[i+1].Min,
|
|
)
|
|
}
|
|
}
|
|
|
|
return MagicHeaders{Values: headerValues, randomGenerator: NewPRNG[uint32]()}, nil
|
|
}
|
|
|
|
func (mh *MagicHeaders) Get(defaultMsgType uint32) (uint32, error) {
|
|
if defaultMsgType == 0 || defaultMsgType > 4 {
|
|
return 0, fmt.Errorf("invalid msg type: %d", defaultMsgType)
|
|
}
|
|
|
|
return mh.randomGenerator.RandomSizeInRange(mh.Values[defaultMsgType-1].Min, mh.Values[defaultMsgType-1].Max), nil
|
|
}
|