diff --git a/net/v2raya/Makefile b/net/v2raya/Makefile index 33c166e15c..a3649ddd8a 100644 --- a/net/v2raya/Makefile +++ b/net/v2raya/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2rayA PKG_VERSION:=2.2.7.5 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/v2rayA/v2rayA/tar.gz/v$(PKG_VERSION)? diff --git a/net/v2raya/patches/010-reduce-GeoIP-parser-memory-usage.patch b/net/v2raya/patches/010-reduce-GeoIP-parser-memory-usage.patch new file mode 100644 index 0000000000..e4acc0a964 --- /dev/null +++ b/net/v2raya/patches/010-reduce-GeoIP-parser-memory-usage.patch @@ -0,0 +1,132 @@ +From 43b6e55b67bb6cfa7bf1ca1305b47e8b113eaef5 Mon Sep 17 00:00:00 2001 +From: ALOKY +Date: Sun, 16 Aug 2026 15:34:30 +0300 +Subject: [PATCH] reduce GeoIP parser memory usage + +Decode one GeoIP entry at a time and cache successful results. + +Signed-off-by: ALOKY +--- + service/common/parseGeoIP/parser.go | 87 +++++++++++++++++++++++++---- + 1 file changed, 77 insertions(+), 10 deletions(-) + +--- a/common/parseGeoIP/parser.go ++++ b/common/parseGeoIP/parser.go +@@ -5,31 +5,91 @@ import ( + "net" + "os" + "strings" ++ "sync" + + "github.com/v2rayA/v2rayA/core/v2ray/asset" ++ "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + ) + +-func Parser(filename string, countryCode string) ([]string, []string, error) { +- var ipv4List []string +- var ipv6List []string +- var geoIpProto GeoIPList ++type parserResult struct { ++ ipv4 []string ++ ipv6 []string ++} + ++type parserCacheKey struct { ++ path string ++ size int64 ++ modTime int64 ++ countryCode string ++} ++ ++var parserCache sync.Map ++ ++func Parser(filename string, countryCode string) ([]string, []string, error) { + realpath, err := asset.GetV2rayLocationAsset(filename) + if err != nil { +- return ipv4List, ipv6List, err ++ return nil, nil, err + } ++ info, err := os.Stat(realpath) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ cacheKey := parserCacheKey{ ++ path: realpath, ++ size: info.Size(), ++ modTime: info.ModTime().UnixNano(), ++ countryCode: countryCode, ++ } ++ if cached, ok := parserCache.Load(cacheKey); ok { ++ result := cached.(parserResult) ++ return result.ipv4, result.ipv6, nil ++ } ++ + data, err := os.ReadFile(realpath) + if err != nil { +- return ipv4List, ipv6List, err ++ return nil, nil, err + } + +- if err := proto.Unmarshal(data, &geoIpProto); err != nil { ++ ipv4List, ipv6List, err := parseGeoIP(data, countryCode) ++ if err != nil { + return ipv4List, ipv6List, err + } + +- for _, geo := range geoIpProto.Entry { +- if geo.CountryCode == countryCode { ++ parserCache.Store(cacheKey, parserResult{ipv4: ipv4List, ipv6: ipv6List}) ++ return ipv4List, ipv6List, nil ++} ++ ++func parseGeoIP(data []byte, countryCode string) ([]string, []string, error) { ++ var ipv4List []string ++ var ipv6List []string ++ ++ // GeoIPList contains repeated GeoIP messages in field 1. Decoding the ++ // complete list expands a roughly 22 MiB asset to hundreds of MiB in ++ // memory. Decode one entry at a time and stop at the requested country. ++ for len(data) > 0 { ++ number, wireType, n := protowire.ConsumeTag(data) ++ if n < 0 { ++ return ipv4List, ipv6List, protowire.ParseError(n) ++ } ++ data = data[n:] ++ ++ if number == 1 && wireType == protowire.BytesType { ++ entryData, consumed := protowire.ConsumeBytes(data) ++ if consumed < 0 { ++ return ipv4List, ipv6List, protowire.ParseError(consumed) ++ } ++ data = data[consumed:] ++ ++ var geo GeoIP ++ if err := proto.Unmarshal(entryData, &geo); err != nil { ++ return ipv4List, ipv6List, err ++ } ++ if geo.CountryCode != countryCode { ++ continue ++ } ++ + for _, c := range geo.Cidr { + ip := net.IP(c.Ip) + if strings.Contains(ip.String(), ":") { +@@ -42,8 +102,15 @@ func Parser(filename string, countryCode + ipv4List = append(ipv4List, fmt.Sprintf("%s/%d", ip.String(), c.Prefix)) + } + } +- break ++ return ipv4List, ipv6List, nil ++ } ++ ++ consumed := protowire.ConsumeFieldValue(number, wireType, data) ++ if consumed < 0 { ++ return ipv4List, ipv6List, protowire.ParseError(consumed) + } ++ data = data[consumed:] + } ++ + return ipv4List, ipv6List, nil + }