--- /dev/null
+name: Check autorelease deprecation
+
+on:
+ pull_request_target:
+ types: [opened, synchronize, converted_to_draft, ready_for_review, edited]
+
+jobs:
+ build:
+ name: Check autorelease deprecation
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+
+ permissions:
+ pull-requests: write
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: 0
+
+ - name: Determine branch name
+ run: |
+ BRANCH="${GITHUB_BASE_REF#refs/heads/}"
+ echo "Building for $BRANCH"
+ echo "BRANCH=$BRANCH" >> $GITHUB_ENV
+
+ - name: Determine changed packages
+ run: |
+ # only detect packages with changes
+ PKG_ROOTS=$(find . -name Makefile | \
+ grep -v ".*/src/Makefile" | \
+ sed -e 's@./\(.*\)/Makefile@\1/@')
+ CHANGES=$(git diff --diff-filter=d --name-only origin/$BRANCH...)
+
+ for ROOT in $PKG_ROOTS; do
+ for CHANGE in $CHANGES; do
+ if [[ "$CHANGE" == "$ROOT"* ]]; then
+ if grep -q '$(AUTORELEASE)' "$ROOT/Makefile"; then
+ CONTAINS_AUTORELEASE+="$ROOT"
+ fi
+ break
+ fi
+ done
+ done
+
+ if [ -n "$CONTAINS_AUTORELEASE" ]; then
+ cat > "$GITHUB_WORKSPACE/pr_comment.md" << EOF
+ Please do no longer set *PKG_RELEASE* to *AUTORELEASE* as the
+ feature is deprecated. Please use an integer instead. Below is a
+ list of affected packages including correct *PKG_RELEASE*:
+
+ EOF
+ else
+ echo "No usage of *AUTORELEASE* found in changes" > "$GITHUB_WORKSPACE/pr_comment.md"
+ fi
+
+ for ROOT in $CONTAINS_AUTORELEASE; do
+ echo -n " - ${ROOT}Makefile: PKG_RELEASE:=" >> "$GITHUB_WORKSPACE/pr_comment.md"
+ last_bump="$(git log --pretty=format:'%h %s' "$ROOT" |
+ grep --max-count=1 -e ': [uU]pdate to ' -e ': [bB]ump to ' |
+ cut -f 1 -d ' ')"
+
+ if [ -n "$last_bump" ]; then
+ echo -n $(($(git rev-list --count "$last_bump..HEAD" "$ROOT") + 2)) >> "$GITHUB_WORKSPACE/pr_comment.md"
+ else
+ echo -n $(($(git rev-list --count HEAD "$ROOT") + 2)) >> "$GITHUB_WORKSPACE/pr_comment.md"
+ fi
+ echo >> "$GITHUB_WORKSPACE/pr_comment.md"
+ done
+
+ - name: Find Comment
+ uses: peter-evans/find-comment@v2
+ id: fc
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ comment-author: 'github-actions[bot]'
+
+ - name: Create or update comment
+ uses: peter-evans/create-or-update-comment@v2
+ with:
+ comment-id: ${{ steps.fc.outputs.comment-id }}
+ issue-number: ${{ github.event.pull_request.number }}
+ body-file: 'pr_comment.md'
+ edit-mode: replace
include $(TOPDIR)/rules.mk
PKG_NAME:=php
-PKG_VERSION:=8.1.12
+PKG_VERSION:=8.1.13
PKG_RELEASE:=1
PKG_MAINTAINER:=Michael Heimpold <mhei@heimpold.de>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=http://www.php.net/distributions/
-PKG_HASH:=08243359e2204d842082269eedc15f08d2eca726d0e65b93fb11f4bfc51bbbab
+PKG_HASH:=b15ef0ccdd6760825604b3c4e3e73558dcf87c75ef1d68ef4289d8fd261ac856
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
PKG_NAME:=acme-acmesh
PKG_VERSION:=3.0.1
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_RELEASE:=9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/acmesh-official/acme.sh/tar.gz/$(PKG_VERSION)?
case $status in
0)
+ mkdir -p /etc/ssl/acme
+ if [ ! -e "/etc/ssl/acme/$main_domain.crt" ]; then
+ ln -s "$domain_dir/$main_domain.cer" "/etc/ssl/acme/$main_domain.crt"
+ fi
+ if [ ! -e "/etc/ssl/acme/$main_domain.key" ]; then
+ ln -s "$domain_dir/$main_domain.key" "/etc/ssl/acme/$main_domain.key"
+ fi
+ if [ ! -e "/etc/ssl/acme/$main_domain.fullchain.crt" ]; then
+ ln -s "$domain_dir/fullchain.cer" "/etc/ssl/acme/$main_domain.fullchain.crt"
+ fi
+ if [ ! -e "/etc/ssl/acme/$main_domain.chain.crt" ]; then
+ ln -s "$domain_dir/ca.cer" "/etc/ssl/acme/$main_domain.chain.crt"
+ fi
+
$NOTIFY renewed
exit
;;
case $status in
0)
ln -s "$domain_dir/$main_domain.cer" "/etc/ssl/acme/$main_domain.crt"
- ln -s "$domain_dir/$main_domain.key" /etc/ssl/acme
+ ln -s "$domain_dir/$main_domain.key" "/etc/ssl/acme/$main_domain.key"
ln -s "$domain_dir/fullchain.cer" "/etc/ssl/acme/$main_domain.fullchain.crt"
ln -s "$domain_dir/ca.cer" "/etc/ssl/acme/$main_domain.chain.crt"
$NOTIFY issued
PKG_NAME:=haproxy
PKG_VERSION:=2.6.6
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_RELEASE:=103
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.haproxy.org/download/2.6/src
case $ACTION in
issued|renewed)
cat \
- "/etc/ssl/acme/$main_domain.fullchain.cer" \
+ "/etc/ssl/acme/$main_domain.fullchain.crt" \
"/etc/ssl/acme/$main_domain.key" \
- >"/etc/ssl/acme/$main_domain.combined.cer"
+ >"/etc/ssl/acme/$main_domain.combined.crt"
;;
esac
--- /dev/null
+# SPDX-License-Identifier: GPL-3.0-only
+#
+# Copyright (C) ImmortalWrt.org
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=librespeed-go
+PKG_VERSION:=1.1.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/librespeed/speedtest-go/tar.gz/v$(PKG_VERSION)?
+PKG_HASH:=a65bbb94868d9ad73f85950264cb18fafb2ba5cf4788ac67981d78b863ca67c4
+
+PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
+PKG_LICENSE:=LGPL-3.0-only
+PKG_LICENSE_FILES:=LICENSE
+
+PKG_BUILD_DEPENDS:=golang/host
+PKG_BUILD_PARALLEL:=1
+PKG_USE_MIPS16:=0
+
+GO_PKG:=github.com/librespeed/speedtest
+
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/golang/golang-package.mk
+
+TAR_OPTIONS+= --strip-components 1
+TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
+
+define Package/librespeed-go
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Web Servers/Proxies
+ TITLE:=Go backend for LibreSpeed
+ URL:=https://github.com/librespeed/speedtest-go
+ DEPENDS:=$(GO_ARCH_DEPENDS)
+ USERID:=librespeed:librespeed
+endef
+
+define Package/librespeed-go/description
+ No Flash, No Java, No WebSocket, No Bullshit.
+
+ This is a very lightweight speed test implemented in JavaScript,
+ using XMLHttpRequest and Web Workers.
+endef
+
+define Package/librespeed-go/conffiles
+/etc/librespeed-go
+endef
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+
+ $(CP) $(PKG_BUILD_DIR)/web/assets/example-singleServer-progressBar.html \
+ $(PKG_BUILD_DIR)/web/assets/index.html
+
+ $(SED) 's,LibreSpeed Example,LibreSpeed for OpenWrt,g' \
+ $(PKG_BUILD_DIR)/web/assets/*.html
+endef
+
+define Package/librespeed-go/install
+ $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/speedtest $(1)/usr/bin/librespeed-go
+
+ $(INSTALL_DIR) $(1)/etc/librespeed-go
+ $(CP) $(PKG_BUILD_DIR)/database/mysql/telemetry_mysql.sql $(1)/etc/librespeed-go/
+ $(CP) $(PKG_BUILD_DIR)/database/postgresql/telemetry_postgresql.sql $(1)/etc/librespeed-go/
+
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) $(CURDIR)/files/librespeed-go.config $(1)/etc/config/librespeed-go
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) $(CURDIR)/files/librespeed-go.init $(1)/etc/init.d/librespeed-go
+endef
+
+$(eval $(call GoBinPackage,librespeed-go))
+$(eval $(call BuildPackage,librespeed-go))
--- /dev/null
+
+config librespeed-go 'config'
+ option enabled '0'
+
+ # bind address, use empty string to bind to all interfaces
+ option bind_address ''
+ # backend listen port
+ option listen_port '8989'
+
+ # change the base URL
+ # option url_base '/librespeed'
+ # proxy protocol port, use 0 to disable
+ option proxyprotocol_port '0'
+ # Server location, use zeroes to fetch from API automatically
+ option server_lat '0'
+ option server_lng '0'
+ # ipinfo.io API key, if applicable
+ option ipinfo_api_key ''
+
+ # assets directory path, defaults to `assets` in the same directory
+ # if the path cannot be found, embedded default assets will be used
+ option assets_path ''
+
+ # password for logging into statistics page, change this to enable stats page
+ # option statistics_password 'PASSWORD'
+ # redact IP addresses (boolean)
+ option redact_ip_addresses '0'
+
+ # database type for statistics data, currently supports: none, memory, bolt, mysql, postgresql
+ # if none is specified, no telemetry/stats will be recorded, and no result PNG will be generated
+ option database_type 'none'
+ # option database_hostname ''
+ # option database_name ''
+ # option database_username ''
+ # option database_password ''
+
+ # if you use `bolt` as database, set database_file to database file location
+ # option database_file '/etc/librespeed-go/speedtest.db'
+
+ # TLS and HTTP/2 settings. TLS is required for HTTP/2 (boolean)
+ option enable_tls '0'
+ option enable_http2 '0'
+
+ # if you use HTTP/2 or TLS, you need to prepare certificates and private keys
+ # option tls_cert_file '/etc/librespeed-go/cert.pem'
+ # option tls_key_file '/etc/librespeed-go/privkey.pem'
+
--- /dev/null
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2022 Tianling Shen <cnsztl@immortalwrt.org>
+
+USE_PROCD=1
+START=99
+
+CONF="librespeed-go"
+PROG="/usr/bin/librespeed-go"
+TMPCONF="/var/run/$CONF/settings.json"
+
+start_service() {
+ config_load "$CONF"
+
+ local enabled
+ config_get_bool enabled "config" "enabled" "0"
+ [ "$enabled" -eq "1" ] || return 1
+
+ mkdir -p "${TMPCONF%/*}"
+
+ json_init
+ option_cb() {
+ local name="$1"
+ local value="$2"
+
+ case "$name" in
+ "enabled") ;;
+ "enable_tls"|"enable_http2"|"redact_ip_addresses")
+ json_add_boolean "$name" "$value" ;;
+ *)
+ json_add_string "$name" "$value" ;;
+ esac
+ }
+ config_load "$CONF"
+ json_dump > "$TMPCONF"
+
+ local database_file
+ config_get database_file "config" "database_file"
+ if [ -n "$database_file" ]; then
+ mkdir -p "${database_file%/*}"
+ touch "$database_file"
+ chown librespeed "$database_file"
+ fi
+
+ procd_open_instance "$CONF"
+ procd_set_param command "$PROG"
+ procd_append_param command -c "$TMPCONF"
+
+ procd_set_param limits core="unlimited"
+ procd_set_param limits nofile="1000000 1000000"
+ procd_set_param respawn
+ procd_set_param stderr 1
+ procd_set_param user librespeed
+
+ procd_add_jail "$CONF" log
+ procd_add_jail_mount "$TMPCONF"
+ [ -z "$database_file" ] || procd_add_jail_mount_rw "$database_file"
+
+ local assets_path tls_cert_file tls_key_file
+ config_get assets_path "config" "assets_path"
+ config_get tls_cert_file "config" "tls_cert_file"
+ config_get tls_key_file "config" "tls_key_file"
+ [ -z "$assets_path" ] || procd_add_jail_mount "$assets_path"
+ [ -z "$tls_cert_file" ] || procd_add_jail_mount "$tls_cert_file"
+ [ -z "$tls_key_file" ] || procd_add_jail_mount "$tls_key_file"
+
+ procd_close_instance
+}
+
+stop_service() {
+ rm -rf "${TMPCONF%/*}"
+}
+
+reload_service() {
+ stop
+ start
+}
+
+service_triggers() {
+ procd_add_reload_trigger "$CONF"
+}
if [ "$force_root" -eq 1 ]; then
printf "\tforce user = root\n"
printf "\tforce group = root\n"
- else
- [ -n "$users" ] && printf "\tvalid users = %s\n" "$users"
fi
+ [ -n "$users" ] && printf "\tvalid users = %s\n" "$users"
[ -n "$create_mask" ] && printf "\tcreate mask = %s\n" "$create_mask"
[ -n "$dir_mask" ] && printf "\tdirectory mask = %s\n" "$dir_mask"
include $(TOPDIR)/rules.mk
PKG_NAME:=snort3
-PKG_VERSION:=3.1.29.0
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_VERSION:=3.1.47.0
+PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/snort3/snort3/archive/refs/tags/
-PKG_HASH:=becec36b57af3d65ae8289b73cd6d56bf8bde774539c74b35b0ec2262a587281
+PKG_HASH:=7565411db11b453a98f8bd88eeef0fa9f2e85416a8f595e710aa19c430228b8c
PKG_MAINTAINER:=W. Michael Petullo <mike@flyn.org>
PKG_LICENSE:=GPL-2.0-only
$(INSTALL_CONF) \
$(PKG_INSTALL_DIR)/usr/etc/snort/*.lua \
$(1)/etc/snort
+ $(INSTALL_CONF) \
+ $(PKG_INSTALL_DIR)/usr/etc/snort/file_magic.rules \
+ $(1)/etc/snort
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) \
+++ /dev/null
---- a/src/network_inspectors/appid/appid_inspector.cc
-+++ b/src/network_inspectors/appid/appid_inspector.cc
-@@ -68,7 +68,6 @@ static THREAD_LOCAL PacketTracer::Tracer
- // should probably be done outside of appid
- static void openssl_cleanup()
- {
-- CRYPTO_cleanup_all_ex_data();
- }
-
- static void add_appid_to_packet_trace(Flow& flow, const OdpContext& odp_context)
---- a/src/utils/util.cc
-+++ b/src/utils/util.cc
-@@ -111,7 +111,7 @@ int DisplayBanner()
- LogMessage(" Copyright (C) 1998-2013 Sourcefire, Inc., et al.\n");
- LogMessage(" Using DAQ version %s\n", daq_version_string());
- LogMessage(" Using LuaJIT version %s\n", ljv);
-- LogMessage(" Using %s\n", SSLeay_version(SSLEAY_VERSION));
-+ LogMessage(" Using %s\n", OpenSSL_version(SSLEAY_VERSION));
- LogMessage(" Using %s\n", pcap_lib_version());
- LogMessage(" Using PCRE version %s\n", pcre_version());
- LogMessage(" Using ZLIB version %s\n", zlib_version);
include $(TOPDIR)/rules.mk
PKG_NAME:=v2ray-geodata
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_RELEASE:=1
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
include $(INCLUDE_DIR)/package.mk
-GEOIP_VER:=202211100058
+GEOIP_VER:=202211240054
GEOIP_FILE:=geoip.dat.$(GEOIP_VER)
define Download/geoip
URL:=https://github.com/v2fly/geoip/releases/download/$(GEOIP_VER)/
URL_FILE:=geoip.dat
FILE:=$(GEOIP_FILE)
- HASH:=1951b20418a48ad8d13f72a1adb1e3cf8540967b15342ff81c7c9bed325a6874
+ HASH:=567c9a1bfe22c2ff7f468f3814aa6bb344b33393cf39507e5cbeb20c78c952b7
endef
-GEOSITE_VER:=20221110023640
+GEOSITE_VER:=20221127082021
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE)
- HASH:=35a868eb49173137b23e36948a6e6874f4380e84c4d569a8f4d6f220f78c1edc
+ HASH:=519583c593fada6cf8d629eb428652199ab715d641073f64122c1e2c68b6c43f
endef
define Package/v2ray-geodata/template
PKG_NAME:=v2rayA
PKG_VERSION:=1.5.9.1698.1
-PKG_RELEASE:=$(AUTORELEASE)
+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)?
# Additional v2ray config directory, files in it will be combined with config generated by v2rayA
option v2ray_confdir ''
+ # The executable file to run in the transparent proxy life-cycle.
+ # v2rayA will pass in the --transparent-type (tproxy, redirect)
+ # and --stage (pre-start, post-start, pre-stop, post-stop) arguments.
+ option transparent_hook ''
+
+ # The executable file to run in the v2ray-core life-cycle.
+ # v2rayA will pass in the --stage (pre-start, post-start, pre-stop, post-stop) argument.
+ option core_hook ''
+
+ # The executable file to run in the v2ray-core life-cycle.
+ # v2rayA will pass in the --stage (pre-start, post-start, pre-stop, post-stop) argument.
+ option plugin_manager ''
+
# Specify the certification path instead of automatically generating a self-signed certificate.
# Example: /etc/v2raya/grpc_certificate.crt,/etc/v2raya/grpc_private.key
option vless_grpc_inbound_cert_key ''
append_env_arg "config" "log_max_days" "3"
append_env_arg "config" "v2ray_bin"
append_env_arg "config" "v2ray_confdir"
+ append_env_arg "config" "transparent_hook"
+ append_env_arg "config" "core_hook"
+ append_env_arg "config" "plugin_manager"
append_env_arg "config" "vless_grpc_inbound_cert_key"
append_env_bool "config" "log_disable_color"
append_env_bool "config" "log_disable_timestamp"
--- /dev/null
+From 78336e55a31db578c139a5bb472aa0fc219c169d Mon Sep 17 00:00:00 2001
+From: Xiaoxu Guo <ftiasch0@gmail.com>
+Date: Thu, 4 Aug 2022 16:24:04 +0800
+Subject: [PATCH] fixed for Docker Compose
+
+---
+ service/core/iptables/tproxy.go | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/core/iptables/tproxy.go
++++ b/core/iptables/tproxy.go
+@@ -65,6 +65,7 @@ iptables -w 2 -t mangle -A TP_PRE -p udp
+
+ iptables -w 2 -t mangle -A TP_RULE -j CONNMARK --restore-mark
+ iptables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
++iptables -w 2 -t mangle -A TP_RULE -i br+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
+ `
+@@ -123,6 +124,8 @@ ip6tables -w 2 -t mangle -A TP_PRE -p ud
+
+ ip6tables -w 2 -t mangle -A TP_RULE -j CONNMARK --restore-mark
+ ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
++ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
++ip6tables -w 2 -t mangle -A TP_RULE -i br+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
+ `
+@@ -156,7 +159,7 @@ ip6tables -w 2 -t mangle -A TP_MARK -j C
+
+ func (t *tproxy) GetCleanCommands() Setter {
+ commands := `
+-ip rule del fwmark 0x40/0xc0 table 100
++ip rule del fwmark 0x40/0xc0 table 100
+ ip route del local 0.0.0.0/0 dev lo table 100
+
+ iptables -w 2 -t mangle -F TP_OUT
+@@ -172,7 +175,7 @@ iptables -w 2 -t mangle -X TP_MARK
+ `
+ if IsIPv6Supported() {
+ commands += `
+-ip -6 rule del fwmark 0x40/0xc0 table 100
++ip -6 rule del fwmark 0x40/0xc0 table 100
+ ip -6 route del local ::/0 dev lo table 100
+
+ ip6tables -w 2 -t mangle -F TP_OUT
--- /dev/null
+From 0db405f50fd652d494f2066fc5e47c41666c96db Mon Sep 17 00:00:00 2001
+From: Xiaoxu Guo <ftiasch0@gmail.com>
+Date: Thu, 4 Aug 2022 16:32:42 +0800
+Subject: [PATCH] cleaned up
+
+---
+ service/core/iptables/tproxy.go | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/core/iptables/tproxy.go
++++ b/core/iptables/tproxy.go
+@@ -124,7 +124,6 @@ ip6tables -w 2 -t mangle -A TP_PRE -p ud
+
+ ip6tables -w 2 -t mangle -A TP_RULE -j CONNMARK --restore-mark
+ ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
+-ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i br+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
+@@ -159,7 +158,7 @@ ip6tables -w 2 -t mangle -A TP_MARK -j C
+
+ func (t *tproxy) GetCleanCommands() Setter {
+ commands := `
+-ip rule del fwmark 0x40/0xc0 table 100
++ip rule del fwmark 0x40/0xc0 table 100
+ ip route del local 0.0.0.0/0 dev lo table 100
+
+ iptables -w 2 -t mangle -F TP_OUT
+@@ -175,7 +174,7 @@ iptables -w 2 -t mangle -X TP_MARK
+ `
+ if IsIPv6Supported() {
+ commands += `
+-ip -6 rule del fwmark 0x40/0xc0 table 100
++ip -6 rule del fwmark 0x40/0xc0 table 100
+ ip -6 route del local ::/0 dev lo table 100
+
+ ip6tables -w 2 -t mangle -F TP_OUT
--- /dev/null
+From 4a87a6fc9a17939cc0fc54058b2128b1f688045a Mon Sep 17 00:00:00 2001
+From: Xiaoxu Guo <ftiasch0@gmail.com>
+Date: Thu, 4 Aug 2022 22:56:46 +0800
+Subject: [PATCH] improved
+
+---
+ service/core/iptables/tproxy.go | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/core/iptables/tproxy.go
++++ b/core/iptables/tproxy.go
+@@ -16,7 +16,7 @@ var Tproxy tproxy
+ func (t *tproxy) AddIPWhitelist(cidr string) {
+ // avoid duplication
+ t.RemoveIPWhitelist(cidr)
+- pos := 5
++ pos := 6
+ if configure.GetSettingNotNil().AntiPollution != configure.AntipollutionClosed {
+ pos += 3
+ }
+@@ -65,7 +65,7 @@ iptables -w 2 -t mangle -A TP_PRE -p udp
+
+ iptables -w 2 -t mangle -A TP_RULE -j CONNMARK --restore-mark
+ iptables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
+-iptables -w 2 -t mangle -A TP_RULE -i br+ -j RETURN
++iptables -w 2 -t mangle -A TP_RULE -i br-+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
+ `
+@@ -124,7 +124,7 @@ ip6tables -w 2 -t mangle -A TP_PRE -p ud
+
+ ip6tables -w 2 -t mangle -A TP_RULE -j CONNMARK --restore-mark
+ ip6tables -w 2 -t mangle -A TP_RULE -m mark --mark 0x40/0xc0 -j RETURN
+-ip6tables -w 2 -t mangle -A TP_RULE -i br+ -j RETURN
++ip6tables -w 2 -t mangle -A TP_RULE -i br-+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
+ `
--- /dev/null
+From ca6a05273284daa04856a840e64f3936f700b7c3 Mon Sep 17 00:00:00 2001
+From: mzz2017 <mzz@tuta.io>
+Date: Fri, 16 Sep 2022 15:13:11 +0800
+Subject: [PATCH] fix: we should skip interface ppp+ to avoid to break net
+
+---
+ service/core/iptables/tproxy.go | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/core/iptables/tproxy.go
++++ b/core/iptables/tproxy.go
+@@ -16,7 +16,7 @@ var Tproxy tproxy
+ func (t *tproxy) AddIPWhitelist(cidr string) {
+ // avoid duplication
+ t.RemoveIPWhitelist(cidr)
+- pos := 6
++ pos := 8
+ if configure.GetSettingNotNil().AntiPollution != configure.AntipollutionClosed {
+ pos += 3
+ }
+@@ -68,6 +68,8 @@ iptables -w 2 -t mangle -A TP_RULE -m ma
+ iptables -w 2 -t mangle -A TP_RULE -i br-+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ iptables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
++iptables -w 2 -t mangle -A TP_RULE -i ppp+ -j RETURN
++iptables -w 2 -t mangle -A TP_RULE -i dn42-+ -j RETURN
+ `
+ if configure.GetSettingNotNil().AntiPollution != configure.AntipollutionClosed {
+ commands += `
+@@ -127,6 +129,8 @@ ip6tables -w 2 -t mangle -A TP_RULE -m m
+ ip6tables -w 2 -t mangle -A TP_RULE -i br-+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i docker+ -j RETURN
+ ip6tables -w 2 -t mangle -A TP_RULE -i veth+ -j RETURN
++ip6tables -w 2 -t mangle -A TP_RULE -i ppp+ -j RETURN
++ip6tables -w 2 -t mangle -A TP_RULE -i dn42-+ -j RETURN
+ `
+ if configure.GetSettingNotNil().AntiPollution != configure.AntipollutionClosed {
+ commands += `
--- /dev/null
+From 5db722b22b39642280572a62b149d4e1efa21ce3 Mon Sep 17 00:00:00 2001
+From: mzz2017 <mzz@tuta.io>
+Date: Mon, 8 Aug 2022 22:30:36 +0800
+Subject: [PATCH] fix: seed cannot be read from vless sharing-link and add
+ missing sni field. #616
+
+---
+ service/core/serverObj/v2ray.go | 24 +++++++++++-------------
+ 1 file changed, 11 insertions(+), 13 deletions(-)
+
+--- a/core/serverObj/v2ray.go
++++ b/core/serverObj/v2ray.go
+@@ -12,7 +12,6 @@ import (
+ "time"
+
+ jsoniter "github.com/json-iterator/go"
+- "github.com/tidwall/gjson"
+ "github.com/v2rayA/v2rayA/common"
+ "github.com/v2rayA/v2rayA/core/coreObj"
+ "github.com/v2rayA/v2rayA/core/v2ray/service"
+@@ -39,6 +38,7 @@ type V2Ray struct {
+ Net string `json:"net"`
+ Type string `json:"type"`
+ Host string `json:"host"`
++ SNI string `json:"sni"`
+ Path string `json:"path"`
+ TLS string `json:"tls"`
+ Flow string `json:"flow,omitempty"`
+@@ -69,7 +69,8 @@ func ParseVlessURL(vless string) (data *
+ ID: u.User.String(),
+ Net: u.Query().Get("type"),
+ Type: u.Query().Get("headerType"),
+- Host: u.Query().Get("sni"),
++ Host: u.Query().Get("host"),
++ SNI: u.Query().Get("sni"),
+ Path: u.Query().Get("path"),
+ TLS: u.Query().Get("security"),
+ Flow: u.Query().Get("flow"),
+@@ -86,16 +87,13 @@ func ParseVlessURL(vless string) (data *
+ if data.Type == "" {
+ data.Type = "none"
+ }
+- if data.Host == "" {
+- data.Host = u.Query().Get("host")
+- }
+ if data.TLS == "" {
+ data.TLS = "none"
+ }
+ if data.Flow == "" {
+ data.Flow = "xtls-rprx-direct"
+ }
+- if data.Type == "mkcp" || data.Type == "kcp" {
++ if data.Net == "mkcp" || data.Net == "kcp" {
+ data.Path = u.Query().Get("seed")
+ }
+ return data, nil
+@@ -145,6 +143,7 @@ func ParseVmessURL(vmess string) (data *
+ if aid == "" {
+ aid = q.Get("aid")
+ }
++ sni := q.Get("sni")
+ info = V2Ray{
+ ID: subMatch[1],
+ Add: subMatch[2],
+@@ -152,6 +151,7 @@ func ParseVmessURL(vmess string) (data *
+ Ps: ps,
+ Host: obfsParam,
+ Path: path,
++ SNI: sni,
+ Net: obfs,
+ Aid: aid,
+ TLS: map[string]string{"1": "tls"}[q.Get("tls")],
+@@ -165,12 +165,6 @@ func ParseVmessURL(vmess string) (data *
+ if err != nil {
+ return
+ }
+- if info.Host == "" {
+- sni := gjson.Get(raw, "sni")
+- if sni.Exists() {
+- info.Host = sni.String()
+- }
+- }
+ }
+ // correct the wrong vmess as much as possible
+ if strings.HasPrefix(info.Host, "/") && info.Path == "" {
+@@ -328,7 +322,9 @@ func (v *V2Ray) Configuration(info Prior
+ core.StreamSettings.TLSSettings.AllowInsecure = true
+ }
+ // SNI
+- if v.Host != "" {
++ if v.SNI != "" {
++ core.StreamSettings.TLSSettings.ServerName = v.SNI
++ } else if v.Host != "" {
+ core.StreamSettings.TLSSettings.ServerName = v.Host
+ }
+ // Alpn
+@@ -345,6 +341,8 @@ func (v *V2Ray) Configuration(info Prior
+ // SNI
+ if v.Host != "" {
+ core.StreamSettings.XTLSSettings.ServerName = v.Host
++ } else if v.Host != "" {
++ core.StreamSettings.TLSSettings.ServerName = v.Host
+ }
+ if v.AllowInsecure {
+ core.StreamSettings.XTLSSettings.AllowInsecure = true
--- /dev/null
+From 3f78422f81f3abc2668fc3938b31d213bfe4dfff Mon Sep 17 00:00:00 2001
+From: mzz2017 <mzz@tuta.io>
+Date: Sun, 28 Aug 2022 17:54:36 +0800
+Subject: [PATCH] fix: a problem that supervisor cannot exit normally
+
+---
+ service/core/specialMode/infra/handle.go | 11 ++++++----
+ service/core/specialMode/infra/supervisor.go | 22 ++++++++------------
+ 2 files changed, 16 insertions(+), 17 deletions(-)
+
+--- a/core/specialMode/infra/handle.go
++++ b/core/specialMode/infra/handle.go
+@@ -127,10 +127,13 @@ func (interfaceHandle *handle) handleRec
+ return results, msg
+ }
+
+-func packetFilter(portCache *portCache, pPacket *gopacket.Packet, whitelistDnsServers *v2router.GeoIPMatcher) (m *dnsmessage.Message, pSAddr, pSPort, pDAddr, pDPort *gopacket.Endpoint) {
+- packet := *pPacket
+- trans := packet.TransportLayer()
++func packetFilter(portCache *portCache, packet gopacket.Packet, whitelistDnsServers *v2router.GeoIPMatcher) (m *dnsmessage.Message, pSAddr, pSPort, pDAddr, pDPort *gopacket.Endpoint) {
++ //跳过非网络层的包
++ if packet.NetworkLayer() == nil {
++ return
++ }
+ //跳过非传输层的包
++ trans := packet.TransportLayer()
+ if trans == nil {
+ return
+ }
+@@ -180,7 +183,7 @@ func packetFilter(portCache *portCache,
+ }
+
+ func (interfaceHandle *handle) handlePacket(packet gopacket.Packet, ifname string, whitelistDnsServers *v2router.GeoIPMatcher, whitelistDomains *strmatcher.MatcherGroup) {
+- m, sAddr, sPort, dAddr, dPort := packetFilter(interfaceHandle.portCache, &packet, whitelistDnsServers)
++ m, sAddr, sPort, dAddr, dPort := packetFilter(interfaceHandle.portCache, packet, whitelistDnsServers)
+ if m == nil {
+ return
+ }
+--- a/core/specialMode/infra/supervisor.go
++++ b/core/specialMode/infra/supervisor.go
+@@ -9,7 +9,6 @@ import (
+ v2router "github.com/v2rayA/v2ray-lib/router"
+ "github.com/v2rayA/v2rayA/pkg/util/log"
+ "sync"
+- "time"
+ )
+
+ type DnsSupervisor struct {
+@@ -70,7 +69,7 @@ func (d *DnsSupervisor) DeleteHandles(if
+ }
+ close(d.handles[ifname].done)
+ delete(d.handles, ifname)
+- log.Trace("DnsSupervisor:%v closed", ifname)
++ log.Trace("DnsSupervisor:%v deleted", ifname)
+ return
+ }
+
+@@ -81,28 +80,24 @@ func (d *DnsSupervisor) Run(ifname strin
+ d.inner.Lock()
+ handle, ok := d.handles[ifname]
+ if !ok {
++ d.inner.Unlock()
+ return fmt.Errorf("Run: %v not exsits", ifname)
+ }
+ if handle.running {
++ d.inner.Unlock()
+ return fmt.Errorf("Run: %v is running", ifname)
+ }
+ handle.running = true
+ log.Trace("[DnsSupervisor] " + ifname + ": running")
+- pkgsrc := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
++ // we only decode UDP packets
++ pkgsrc := gopacket.NewPacketSource(handle, layers.LayerTypeDNS)
+ pkgsrc.NoCopy = true
++ //pkgsrc.Lazy = true
+ d.inner.Unlock()
+ packets := pkgsrc.Packets()
+ go func() {
+- for {
+- //心跳包,防止内存泄漏
+- packets <- gopacket.NewPacket(nil, layers.LinkTypeEthernet, gopacket.DecodeOptions{})
+- select {
+- case <-handle.done:
+- return
+- default:
+- time.Sleep(2 * time.Second)
+- }
+- }
++ <-handle.done
++ packets <- gopacket.NewPacket(nil, layers.LinkTypeEthernet, pkgsrc.DecodeOptions)
+ }()
+ out:
+ for packet := range packets {
+@@ -113,5 +108,6 @@ out:
+ }
+ go handle.handlePacket(packet, ifname, whitelistDnsServers, whitelistDomains)
+ }
++ log.Trace("DnsSupervisor:%v closed", ifname)
+ return
+ }
--- /dev/null
+From 153b72ed623876ad73b731c2ec2344e9057d3c35 Mon Sep 17 00:00:00 2001
+From: mzz2017 <mzz@tuta.io>
+Date: Wed, 21 Sep 2022 16:50:24 +0800
+Subject: [PATCH] fix: unexpected exit does not apply stop steps
+
+---
+ service/core/v2ray/process.go | 4 ++--
+ service/core/v2ray/processManager.go | 8 +++-----
+ 2 files changed, 5 insertions(+), 7 deletions(-)
+
+--- a/core/v2ray/process.go
++++ b/core/v2ray/process.go
+@@ -35,7 +35,7 @@ type Process struct {
+ tag2WhichIndex map[string]int
+ }
+
+-func NewProcess(tmpl *Template, prestart func() error, poststart func() error) (process *Process, err error) {
++func NewProcess(tmpl *Template, prestart func() error, poststart func() error, stopfunc func(p *Process)) (process *Process, err error) {
+ process = &Process{
+ template: tmpl,
+ }
+@@ -111,7 +111,7 @@ func NewProcess(tmpl *Template, prestart
+ // canceled by v2rayA
+ return
+ }
+- defer ProcessManager.Stop(false)
++ defer stopfunc(process)
+ var t []string
+ if p != nil {
+ if p.Success() {
+--- a/core/v2ray/processManager.go
++++ b/core/v2ray/processManager.go
+@@ -245,16 +245,14 @@ func (m *CoreProcessManager) Start(t *Te
+ return m.beforeStart(t)
+ }, func() error {
+ return m.afterStart(t)
++ }, func(p *Process) {
++ m.p = p
++ ProcessManager.Stop(false)
+ })
+ if err != nil {
+ return err
+ }
+ m.p = process
+- defer func() {
+- if err != nil {
+- m.stop(true)
+- }
+- }()
+
+ configure.SetRunning(true)
+ return nil
--- /dev/null
+From 00366b224b2e28861b80f677e8aa604c5d08dae3 Mon Sep 17 00:00:00 2001
+From: Kelo <meetkelo@outlook.com>
+Date: Sat, 29 Oct 2022 16:27:26 +0800
+Subject: [PATCH] optimize: reduce disk writes
+
+---
+ service/db/boltdb.go | 43 +++++++++++++++++++++++++++++++----
+ service/db/listOp.go | 48 +++++++++++++++++++++------------------
+ service/db/plainOp.go | 52 ++++++++++++++++++++++++-------------------
+ service/db/setOp.go | 20 +++++++++--------
+ 4 files changed, 105 insertions(+), 58 deletions(-)
+
+--- a/db/boltdb.go
++++ b/db/boltdb.go
+@@ -1,13 +1,14 @@
+ package db
+
+ import (
+- "go.etcd.io/bbolt"
+- "github.com/v2rayA/v2rayA/conf"
+- "github.com/v2rayA/v2rayA/pkg/util/copyfile"
+- "github.com/v2rayA/v2rayA/pkg/util/log"
+ "os"
+ "path/filepath"
+ "sync"
++
++ "github.com/v2rayA/v2rayA/conf"
++ "github.com/v2rayA/v2rayA/pkg/util/copyfile"
++ "github.com/v2rayA/v2rayA/pkg/util/log"
++ "go.etcd.io/bbolt"
+ )
+
+ var once sync.Once
+@@ -46,3 +47,37 @@ func DB() *bbolt.DB {
+ once.Do(initDB)
+ return db
+ }
++
++// The function should return a dirty flag.
++// If the dirty flag is true and there is no error then the transaction is commited.
++// Otherwise, the transaction is rolled back.
++func Transaction(db *bbolt.DB, fn func(*bbolt.Tx) (bool, error)) error {
++ tx, err := db.Begin(true)
++ if err != nil {
++ return err
++ }
++ defer tx.Rollback()
++ dirty, err := fn(tx)
++ if err != nil {
++ _ = tx.Rollback()
++ return err
++ }
++ if !dirty {
++ return nil
++ }
++ return tx.Commit()
++}
++
++// If the bucket does not exist, the dirty flag is setted
++func CreateBucketIfNotExists(tx *bbolt.Tx, name []byte, dirty *bool) (*bbolt.Bucket, error) {
++ bkt := tx.Bucket(name)
++ if bkt != nil {
++ return bkt, nil
++ }
++ bkt, err := tx.CreateBucket(name)
++ if err != nil {
++ return nil, err
++ }
++ *dirty = true
++ return bkt, nil
++}
+--- a/db/listOp.go
++++ b/db/listOp.go
+@@ -2,13 +2,14 @@ package db
+
+ import (
+ "fmt"
+- "go.etcd.io/bbolt"
+- jsoniter "github.com/json-iterator/go"
+- "github.com/tidwall/gjson"
+- "github.com/tidwall/sjson"
+ "reflect"
+ "sort"
+ "strconv"
++
++ jsoniter "github.com/json-iterator/go"
++ "github.com/tidwall/gjson"
++ "github.com/tidwall/sjson"
++ "go.etcd.io/bbolt"
+ )
+
+ func ListSet(bucket string, key string, index int, val interface{}) (err error) {
+@@ -31,20 +32,21 @@ func ListSet(bucket string, key string,
+ }
+
+ func ListGet(bucket string, key string, index int) (b []byte, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ v := bkt.Get([]byte(key))
+ if v == nil {
+- return fmt.Errorf("ListGet: can't get element from an empty list")
++ return dirty, fmt.Errorf("ListGet: can't get element from an empty list")
+ }
+ r := gjson.GetBytes(v, strconv.Itoa(index))
+ if r.Exists() {
+ b = []byte(r.Raw)
+- return nil
++ return dirty, nil
+ } else {
+- return fmt.Errorf("ListGet: no such element")
++ return dirty, fmt.Errorf("ListGet: no such element")
+ }
+ }
+ })
+@@ -79,24 +81,25 @@ func ListAppend(bucket string, key strin
+ }
+
+ func ListGetAll(bucket string, key string) (list [][]byte, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ b := bkt.Get([]byte(key))
+ if b == nil {
+- return nil
++ return dirty, nil
+ }
+ parsed := gjson.ParseBytes(b)
+ if !parsed.IsArray() {
+- return fmt.Errorf("ListGetAll: is not array")
++ return dirty, fmt.Errorf("ListGetAll: is not array")
+ }
+ results := parsed.Array()
+ for _, r := range results {
+ list = append(list, []byte(r.Raw))
+ }
+ }
+- return nil
++ return dirty, nil
+ })
+ return list, err
+ }
+@@ -143,21 +146,22 @@ func ListRemove(bucket, key string, inde
+ }
+
+ func ListLen(bucket string, key string) (length int, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ b := bkt.Get([]byte(key))
+ if b == nil {
+- return nil
++ return dirty, nil
+ }
+ parsed := gjson.ParseBytes(b)
+ if !parsed.IsArray() {
+- return fmt.Errorf("ListLen: is not array")
++ return dirty, fmt.Errorf("ListLen: is not array")
+ }
+ length = len(parsed.Array())
+ }
+- return nil
++ return dirty, nil
+ })
+ return length, err
+ }
+--- a/db/plainOp.go
++++ b/db/plainOp.go
+@@ -2,50 +2,54 @@ package db
+
+ import (
+ "fmt"
+- "go.etcd.io/bbolt"
++
+ jsoniter "github.com/json-iterator/go"
+ "github.com/v2rayA/v2rayA/common"
+ "github.com/v2rayA/v2rayA/pkg/util/log"
++ "go.etcd.io/bbolt"
+ )
+
+ func Get(bucket string, key string, val interface{}) (err error) {
+- return DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ return Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ if v := bkt.Get([]byte(key)); v == nil {
+- return fmt.Errorf("Get: key is not found")
++ return dirty, fmt.Errorf("Get: key is not found")
+ } else {
+- return jsoniter.Unmarshal(v, val)
++ return dirty, jsoniter.Unmarshal(v, val)
+ }
+ }
+ })
+ }
+
+ func GetRaw(bucket string, key string) (b []byte, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ v := bkt.Get([]byte(key))
+ if v == nil {
+- return fmt.Errorf("GetRaw: key is not found")
++ return dirty, fmt.Errorf("GetRaw: key is not found")
+ }
+ b = common.BytesCopy(v)
+- return nil
++ return dirty, nil
+ }
+ })
+ return b, err
+ }
+
+ func Exists(bucket string, key string) (exists bool) {
+- if err := DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ if err := Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ v := bkt.Get([]byte(key))
+ exists = v != nil
+- return nil
++ return dirty, nil
+ }
+ }); err != nil {
+ log.Warn("%v", err)
+@@ -55,23 +59,25 @@ func Exists(bucket string, key string) (
+ }
+
+ func GetBucketLen(bucket string) (length int, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ length = bkt.Stats().KeyN
+ }
+- return nil
++ return dirty, nil
+ })
+ return length, err
+ }
+
+ func GetBucketKeys(bucket string) (keys []string, err error) {
+- err = DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ err = Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+- return bkt.ForEach(func(k, v []byte) error {
++ return dirty, bkt.ForEach(func(k, v []byte) error {
+ keys = append(keys, string(k))
+ return nil
+ })
+--- a/db/setOp.go
++++ b/db/setOp.go
+@@ -4,8 +4,9 @@ import (
+ "bytes"
+ "crypto/sha256"
+ "encoding/gob"
+- "go.etcd.io/bbolt"
++
+ "github.com/v2rayA/v2rayA/common"
++ "go.etcd.io/bbolt"
+ )
+
+ type set map[[32]byte]interface{}
+@@ -28,26 +29,27 @@ func toSha256(val interface{}) (hash [32
+ }
+
+ func setOp(bucket string, key string, f func(m set) (readonly bool, err error)) (err error) {
+- return DB().Update(func(tx *bbolt.Tx) error {
+- if bkt, err := tx.CreateBucketIfNotExists([]byte(bucket)); err != nil {
+- return err
++ return Transaction(DB(), func(tx *bbolt.Tx) (bool, error) {
++ dirty := false
++ if bkt, err := CreateBucketIfNotExists(tx, []byte(bucket), &dirty); err != nil {
++ return dirty, err
+ } else {
+ var m set
+ v := bkt.Get([]byte(key))
+ if v == nil {
+ m = make(set)
+ } else if err := gob.NewDecoder(bytes.NewReader(v)).Decode(&m); err != nil {
+- return err
++ return dirty, err
+ }
+ if readonly, err := f(m); err != nil {
+- return err
++ return dirty, err
+ } else if readonly {
+- return nil
++ return dirty, nil
+ }
+ if b, err := common.ToBytes(m); err != nil {
+- return err
++ return dirty, err
+ } else {
+- return bkt.Put([]byte(key), b)
++ return true, bkt.Put([]byte(key), b)
+ }
+ }
+ })
--- /dev/null
+From 451912074ba1ba4000c66874876bc0a6b64cb5da Mon Sep 17 00:00:00 2001
+From: Kelo <meetkelo@outlook.com>
+Date: Sun, 30 Oct 2022 16:49:22 +0800
+Subject: [PATCH] fix: do not rollback closed transaction
+
+---
+ service/db/boltdb.go | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/db/boltdb.go
++++ b/db/boltdb.go
+@@ -56,14 +56,13 @@ func Transaction(db *bbolt.DB, fn func(*
+ if err != nil {
+ return err
+ }
+- defer tx.Rollback()
+ dirty, err := fn(tx)
+ if err != nil {
+ _ = tx.Rollback()
+ return err
+ }
+ if !dirty {
+- return nil
++ return tx.Rollback()
+ }
+ return tx.Commit()
+ }
include $(TOPDIR)/rules.mk
PKG_NAME:=xray-core
-PKG_VERSION:=1.6.4
+PKG_VERSION:=1.6.5
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=8f81aecb5c28585c98ea95e563d2f03a7d21daa333778f9c4f0aeed27afacef4
+PKG_HASH:=61956d8d72d086fbf83e6a3aff191d010401aca34f30015f839f8a73bf50914c
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=MPL-2.0
include $(TOPDIR)/rules.mk
PKG_NAME:=yq
-PKG_VERSION:=4.30.4
+PKG_VERSION:=4.30.5
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/mikefarah/yq/tar.gz/v$(PKG_VERSION)?
-PKG_HASH:=d46e4f5176d6115107909623bd89ceb7ae991acc0980112ba9b0159811229c0c
+PKG_HASH:=54706926e44ca8f28c74c0165c4746f372daafd4db885b709fdaf5e8f2e4502c
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=MIT