mirror of
https://github.com/openwrt/packages.git
synced 2026-10-13 03:37:43 +04:00
v2raya: backport memory fix for GeoIP parser
Fixes: #30285 Reported-by: ALOKY <ajm1055@uomustansiriyah.edu.iq> Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
2 files changed
+133
-1
No files matched your search
+1
-1
@@ -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)?
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
From 43b6e55b67bb6cfa7bf1ca1305b47e8b113eaef5 Mon Sep 17 00:00:00 2001
|
||||
From: ALOKY <ajm1055@uomustansiriyah.edu.iq>
|
||||
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 <ajm1055@uomustansiriyah.edu.iq>
|
||||
---
|
||||
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
|
||||
}
|
||||
Reference in new issue
Block a user