mirror of
https://github.com/bolucat/Archive.git
synced 2025-10-16 13:11:02 +08:00
Update On Mon Apr 7 20:36:19 CEST 2025
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -965,3 +965,4 @@ Update On Thu Apr 3 20:36:49 CEST 2025
|
|||||||
Update On Fri Apr 4 20:36:13 CEST 2025
|
Update On Fri Apr 4 20:36:13 CEST 2025
|
||||||
Update On Sat Apr 5 20:32:49 CEST 2025
|
Update On Sat Apr 5 20:32:49 CEST 2025
|
||||||
Update On Sun Apr 6 20:34:52 CEST 2025
|
Update On Sun Apr 6 20:34:52 CEST 2025
|
||||||
|
Update On Mon Apr 7 20:36:09 CEST 2025
|
||||||
|
4
clash-nyanpasu/backend/Cargo.lock
generated
4
clash-nyanpasu/backend/Cargo.lock
generated
@@ -2980,9 +2980,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.0"
|
version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
|
@@ -53,7 +53,7 @@
|
|||||||
"@csstools/normalize.css": "12.1.1",
|
"@csstools/normalize.css": "12.1.1",
|
||||||
"@emotion/babel-plugin": "11.13.5",
|
"@emotion/babel-plugin": "11.13.5",
|
||||||
"@emotion/react": "11.14.0",
|
"@emotion/react": "11.14.0",
|
||||||
"@iconify/json": "2.2.323",
|
"@iconify/json": "2.2.324",
|
||||||
"@monaco-editor/react": "4.7.0",
|
"@monaco-editor/react": "4.7.0",
|
||||||
"@tanstack/react-query": "5.71.10",
|
"@tanstack/react-query": "5.71.10",
|
||||||
"@tanstack/react-router": "1.114.34",
|
"@tanstack/react-router": "1.114.34",
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 1,
|
"manifest_version": 1,
|
||||||
"latest": {
|
"latest": {
|
||||||
"mihomo": "v1.19.4",
|
"mihomo": "v1.19.4",
|
||||||
"mihomo_alpha": "alpha-2a08c44",
|
"mihomo_alpha": "alpha-9e8f4ad",
|
||||||
"clash_rs": "v0.7.6",
|
"clash_rs": "v0.7.6",
|
||||||
"clash_premium": "2023-09-05-gdcc8d87",
|
"clash_premium": "2023-09-05-gdcc8d87",
|
||||||
"clash_rs_alpha": "0.7.6-alpha+sha.5af4aa5"
|
"clash_rs_alpha": "0.7.6-alpha+sha.5af4aa5"
|
||||||
@@ -69,5 +69,5 @@
|
|||||||
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"updated_at": "2025-04-05T22:20:47.286Z"
|
"updated_at": "2025-04-06T22:20:38.947Z"
|
||||||
}
|
}
|
||||||
|
12
clash-nyanpasu/pnpm-lock.yaml
generated
12
clash-nyanpasu/pnpm-lock.yaml
generated
@@ -333,8 +333,8 @@ importers:
|
|||||||
specifier: 11.14.0
|
specifier: 11.14.0
|
||||||
version: 11.14.0(@types/react@19.0.12)(react@19.1.0)
|
version: 11.14.0(@types/react@19.0.12)(react@19.1.0)
|
||||||
'@iconify/json':
|
'@iconify/json':
|
||||||
specifier: 2.2.323
|
specifier: 2.2.324
|
||||||
version: 2.2.323
|
version: 2.2.324
|
||||||
'@monaco-editor/react':
|
'@monaco-editor/react':
|
||||||
specifier: 4.7.0
|
specifier: 4.7.0
|
||||||
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
@@ -1680,8 +1680,8 @@ packages:
|
|||||||
'@vue/compiler-sfc':
|
'@vue/compiler-sfc':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@iconify/json@2.2.323':
|
'@iconify/json@2.2.324':
|
||||||
resolution: {integrity: sha512-PtRN4hK9OkT2nlEa76A5QT54E6/SOukceKQkOZv9mk44UOlaS/9fhJFNUEA+FBAXEPcnnCQb2nVui+IAn7xTSw==}
|
resolution: {integrity: sha512-7rx2pY2NH4zn/7q04zFiiD3o7eQ8ZV0F0nf7Rkn2DyI272OWzDMw5goSULOyDdiW9sdfBLeZod/TRxEilaNNsA==}
|
||||||
|
|
||||||
'@iconify/types@2.0.0':
|
'@iconify/types@2.0.0':
|
||||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||||
@@ -9551,7 +9551,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@iconify/json@2.2.323':
|
'@iconify/json@2.2.324':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
@@ -9679,7 +9679,7 @@ snapshots:
|
|||||||
'@babel/runtime': 7.26.10
|
'@babel/runtime': 7.26.10
|
||||||
'@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
'@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
'@mui/types': 7.2.24(@types/react@19.0.12)
|
'@mui/types': 7.2.24(@types/react@19.0.12)
|
||||||
'@mui/utils': 6.4.8(@types/react@19.0.12)(react@19.1.0)
|
'@mui/utils': 6.4.9(@types/react@19.0.12)(react@19.1.0)
|
||||||
'@popperjs/core': 2.11.8
|
'@popperjs/core': 2.11.8
|
||||||
clsx: 2.1.1
|
clsx: 2.1.1
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
|
@@ -3,13 +3,9 @@ import { getClashInfo } from "./cmds";
|
|||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
|
|
||||||
let axiosIns: AxiosInstance = null!;
|
let instancePromise: Promise<AxiosInstance> = null!;
|
||||||
|
|
||||||
/// initialize some information
|
|
||||||
/// enable force update axiosIns
|
|
||||||
export const getAxios = async (force: boolean = false) => {
|
|
||||||
if (axiosIns && !force) return axiosIns;
|
|
||||||
|
|
||||||
|
async function getInstancePromise() {
|
||||||
let server = "";
|
let server = "";
|
||||||
let secret = "";
|
let secret = "";
|
||||||
|
|
||||||
@@ -26,13 +22,22 @@ export const getAxios = async (force: boolean = false) => {
|
|||||||
if (info?.secret) secret = info?.secret;
|
if (info?.secret) secret = info?.secret;
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
axiosIns = axios.create({
|
const axiosIns = axios.create({
|
||||||
baseURL: `http://${server}`,
|
baseURL: `http://${server}`,
|
||||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
});
|
});
|
||||||
axiosIns.interceptors.response.use((r) => r.data);
|
axiosIns.interceptors.response.use((r) => r.data);
|
||||||
return axiosIns;
|
return axiosIns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialize some information
|
||||||
|
/// enable force update axiosIns
|
||||||
|
export const getAxios = async (force: boolean = false) => {
|
||||||
|
if (!instancePromise || force) {
|
||||||
|
instancePromise = getInstancePromise();
|
||||||
|
}
|
||||||
|
return instancePromise;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Get Version
|
/// Get Version
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||||
|
|
||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
@@ -43,38 +43,21 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
leds {
|
gpio-leds {
|
||||||
compatible = "gpio-leds";
|
compatible = "gpio-leds";
|
||||||
|
|
||||||
led_sys_red: led-0 {
|
led_sys_red: led-0 {
|
||||||
function = LED_FUNCTION_STATUS;
|
|
||||||
color = <LED_COLOR_ID_RED>;
|
color = <LED_COLOR_ID_RED>;
|
||||||
|
function = LED_FUNCTION_STATUS;
|
||||||
gpios = <&pio 11 GPIO_ACTIVE_LOW>;
|
gpios = <&pio 11 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
|
|
||||||
led_sys_green: led-1 {
|
led_sys_green: led-1 {
|
||||||
function = LED_FUNCTION_STATUS;
|
|
||||||
color = <LED_COLOR_ID_GREEN>;
|
color = <LED_COLOR_ID_GREEN>;
|
||||||
|
function = LED_FUNCTION_STATUS;
|
||||||
gpios = <&pio 10 GPIO_ACTIVE_LOW>;
|
gpios = <&pio 10 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
usb_vbus: regulator-usb {
|
|
||||||
compatible = "regulator-fixed";
|
|
||||||
regulator-name = "usb-vbus";
|
|
||||||
regulator-min-microvolt = <5000000>;
|
|
||||||
regulator-max-microvolt = <5000000>;
|
|
||||||
gpios = <&pio 9 GPIO_ACTIVE_LOW>;
|
|
||||||
regulator-boot-on;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&uart0 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&watchdog {
|
|
||||||
status = "okay";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ð {
|
ð {
|
||||||
@@ -87,6 +70,9 @@
|
|||||||
reg = <0>;
|
reg = <0>;
|
||||||
phy-mode = "2500base-x";
|
phy-mode = "2500base-x";
|
||||||
phy-handle = <&phy1>;
|
phy-handle = <&phy1>;
|
||||||
|
|
||||||
|
nvmem-cells = <&macaddr_factory_4 2>;
|
||||||
|
nvmem-cell-names = "mac-address";
|
||||||
};
|
};
|
||||||
|
|
||||||
gmac1: mac@1 {
|
gmac1: mac@1 {
|
||||||
@@ -94,11 +80,14 @@
|
|||||||
reg = <1>;
|
reg = <1>;
|
||||||
phy-mode = "gmii";
|
phy-mode = "gmii";
|
||||||
phy-handle = <&int_gbe_phy>;
|
phy-handle = <&int_gbe_phy>;
|
||||||
|
|
||||||
|
nvmem-cells = <&macaddr_factory_4 3>;
|
||||||
|
nvmem-cell-names = "mac-address";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&mdio_bus {
|
&mdio_bus {
|
||||||
phy1: phy@1 {
|
phy1: ethernet-phy@1 {
|
||||||
compatible = "ethernet-phy-ieee802.3-c45";
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
reset-assert-us = <100000>;
|
reset-assert-us = <100000>;
|
||||||
@@ -110,6 +99,49 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&mmc0 {
|
||||||
|
bus-width = <8>;
|
||||||
|
cap-mmc-highspeed;
|
||||||
|
max-frequency = <52000000>;
|
||||||
|
non-removable;
|
||||||
|
pinctrl-names = "default", "state_uhs";
|
||||||
|
pinctrl-0 = <&mmc0_pins_default>;
|
||||||
|
pinctrl-1 = <&mmc0_pins_uhs>;
|
||||||
|
vmmc-supply = <®_3p3v>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
card@0 {
|
||||||
|
compatible = "mmc-card";
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
block {
|
||||||
|
compatible = "block-device";
|
||||||
|
|
||||||
|
partitions {
|
||||||
|
block-partition-factory {
|
||||||
|
partname = "factory";
|
||||||
|
|
||||||
|
nvmem-layout {
|
||||||
|
compatible = "fixed-layout";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
eeprom_factory_0: eeprom@0 {
|
||||||
|
reg = <0x0 0x1000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
macaddr_factory_4: macaddr@4 {
|
||||||
|
compatible = "mac-base";
|
||||||
|
reg = <0x4 0x6>;
|
||||||
|
#nvmem-cell-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
&pio {
|
&pio {
|
||||||
mmc0_pins_default: mmc0-pins-default {
|
mmc0_pins_default: mmc0-pins-default {
|
||||||
mux {
|
mux {
|
||||||
@@ -125,27 +157,24 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&uart0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
&usb_phy {
|
&usb_phy {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&watchdog {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&wifi {
|
||||||
|
nvmem-cells = <&eeprom_factory_0>;
|
||||||
|
nvmem-cell-names = "eeprom";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
&xhci {
|
&xhci {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
vbus-supply = <&usb_vbus>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&wifi {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&mmc0 {
|
|
||||||
pinctrl-names = "default", "state_uhs";
|
|
||||||
pinctrl-0 = <&mmc0_pins_default>;
|
|
||||||
pinctrl-1 = <&mmc0_pins_uhs>;
|
|
||||||
bus-width = <8>;
|
|
||||||
cap-mmc-highspeed;
|
|
||||||
max-frequency = <52000000>;
|
|
||||||
vmmc-supply = <®_3p3v>;
|
|
||||||
non-removable;
|
|
||||||
status = "okay";
|
|
||||||
};
|
};
|
||||||
|
@@ -128,11 +128,6 @@ mediatek_setup_macs()
|
|||||||
lan_mac=$(macaddr_add "$wan_mac" 1)
|
lan_mac=$(macaddr_add "$wan_mac" 1)
|
||||||
label_mac=$wan_mac
|
label_mac=$wan_mac
|
||||||
;;
|
;;
|
||||||
huasifei,wh3000-emmc)
|
|
||||||
label_mac=$(mmc_get_mac_binary factory 0x4)
|
|
||||||
lan_mac="$(macaddr_add $label_mac 2)"
|
|
||||||
wan_mac="$(macaddr_add $label_mac 3)"
|
|
||||||
;;
|
|
||||||
imou,lc-hx3001)
|
imou,lc-hx3001)
|
||||||
lan_mac=$(mtd_get_mac_ascii u-boot-env mac)
|
lan_mac=$(mtd_get_mac_ascii u-boot-env mac)
|
||||||
wan_mac=$(macaddr_add "$lan_mac" 2)
|
wan_mac=$(macaddr_add "$lan_mac" 2)
|
||||||
|
@@ -351,7 +351,7 @@ define Device/cmcc_xr30-nand
|
|||||||
DEVICE_VARIANT := (U-Boot mod)
|
DEVICE_VARIANT := (U-Boot mod)
|
||||||
DEVICE_DTS := mt7981b-cmcc-xr30-nand
|
DEVICE_DTS := mt7981b-cmcc-xr30-nand
|
||||||
DEVICE_DTS_DIR := ../dts
|
DEVICE_DTS_DIR := ../dts
|
||||||
DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3
|
DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3
|
||||||
UBINIZE_OPTS := -E 5
|
UBINIZE_OPTS := -E 5
|
||||||
BLOCKSIZE := 128k
|
BLOCKSIZE := 128k
|
||||||
PAGESIZE := 2048
|
PAGESIZE := 2048
|
||||||
@@ -499,6 +499,7 @@ define Device/huasifei_wh3000-emmc
|
|||||||
KERNEL_INITRAMFS := kernel-bin | lzma | \
|
KERNEL_INITRAMFS := kernel-bin | lzma | \
|
||||||
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k
|
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k
|
||||||
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
||||||
|
SUPPORTED_DEVICES += huasifei,wh3000
|
||||||
endef
|
endef
|
||||||
TARGET_DEVICES += huasifei_wh3000-emmc
|
TARGET_DEVICES += huasifei_wh3000-emmc
|
||||||
|
|
||||||
@@ -508,11 +509,11 @@ define Device/hf_m7986r1-emmc
|
|||||||
DEVICE_DTS := mt7986a-hf-m7986r1-emmc
|
DEVICE_DTS := mt7986a-hf-m7986r1-emmc
|
||||||
DEVICE_DTS_DIR := ../dts
|
DEVICE_DTS_DIR := ../dts
|
||||||
DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-net-rndis kmod-usb-serial-option f2fsck mkf2fs
|
DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-net-rndis kmod-usb-serial-option f2fsck mkf2fs
|
||||||
SUPPORTED_DEVICES += HF-M7986R1
|
|
||||||
KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
|
KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb
|
||||||
KERNEL_INITRAMFS := kernel-bin | lzma | \
|
KERNEL_INITRAMFS := kernel-bin | lzma | \
|
||||||
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k
|
fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k
|
||||||
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
||||||
|
SUPPORTED_DEVICES += HF-M7986R1
|
||||||
endef
|
endef
|
||||||
TARGET_DEVICES += hf_m7986r1-emmc
|
TARGET_DEVICES += hf_m7986r1-emmc
|
||||||
|
|
||||||
@@ -526,8 +527,8 @@ define Device/hf_m7986r1-nand
|
|||||||
PAGESIZE := 2048
|
PAGESIZE := 2048
|
||||||
KERNEL_IN_UBI := 1
|
KERNEL_IN_UBI := 1
|
||||||
DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-net-rndis kmod-usb-serial-option
|
DEVICE_PACKAGES := kmod-usb3 kmod-mt7921e kmod-usb-net-rndis kmod-usb-serial-option
|
||||||
SUPPORTED_DEVICES += HF-M7986R1
|
|
||||||
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
|
||||||
|
SUPPORTED_DEVICES += HF-M7986R1
|
||||||
endef
|
endef
|
||||||
TARGET_DEVICES += hf_m7986r1-nand
|
TARGET_DEVICES += hf_m7986r1-nand
|
||||||
|
|
||||||
|
8
naiveproxy/.github/workflows/build.yml
vendored
8
naiveproxy/.github/workflows/build.yml
vendored
@@ -144,7 +144,7 @@ jobs:
|
|||||||
- run: ./get-clang.sh
|
- run: ./get-clang.sh
|
||||||
- run: ccache -z
|
- run: ccache -z
|
||||||
- run: ./build.sh
|
- run: ./build.sh
|
||||||
- run: ccache -s
|
- run: ccache -s && ccache --evict-older-than 1d
|
||||||
- run: ../tests/basic.sh out/Release/naive
|
- run: ../tests/basic.sh out/Release/naive
|
||||||
- name: Pack naiveproxy assets
|
- name: Pack naiveproxy assets
|
||||||
run: |
|
run: |
|
||||||
@@ -228,7 +228,7 @@ jobs:
|
|||||||
- run: ./get-clang.sh
|
- run: ./get-clang.sh
|
||||||
- run: ccache -z
|
- run: ccache -z
|
||||||
- run: ./build.sh
|
- run: ./build.sh
|
||||||
- run: ccache -s
|
- run: ccache -s && ccache --evict-older-than 1d
|
||||||
- run: ./get-android-sys.sh
|
- run: ./get-android-sys.sh
|
||||||
- run: ../tests/basic.sh out/Release/naive
|
- run: ../tests/basic.sh out/Release/naive
|
||||||
- name: Gradle cache
|
- name: Gradle cache
|
||||||
@@ -355,7 +355,7 @@ jobs:
|
|||||||
- run: ./get-clang.sh
|
- run: ./get-clang.sh
|
||||||
- run: ccache -z
|
- run: ccache -z
|
||||||
- run: ./build.sh
|
- run: ./build.sh
|
||||||
- run: ccache -s
|
- run: ccache -s && ccache --evict-older-than 1d
|
||||||
- run: ../tests/basic.sh out/Release/naive
|
- run: ../tests/basic.sh out/Release/naive
|
||||||
# No real or emulated environment is available to test this.
|
# No real or emulated environment is available to test this.
|
||||||
if: ${{ matrix.arch != 'arm64' }}
|
if: ${{ matrix.arch != 'arm64' }}
|
||||||
@@ -558,7 +558,7 @@ jobs:
|
|||||||
- run: ./get-clang.sh
|
- run: ./get-clang.sh
|
||||||
- run: ccache -z
|
- run: ccache -z
|
||||||
- run: ./build.sh
|
- run: ./build.sh
|
||||||
- run: ccache -s
|
- run: ccache -s && ccache --evict-older-than 1d
|
||||||
- run: ../tests/basic.sh out/Release/naive
|
- run: ../tests/basic.sh out/Release/naive
|
||||||
- name: Pack naiveproxy assets
|
- name: Pack naiveproxy assets
|
||||||
run: |
|
run: |
|
||||||
|
@@ -368,7 +368,7 @@ declare_args() {
|
|||||||
|
|
||||||
stack_scan_supported =
|
stack_scan_supported =
|
||||||
current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" ||
|
current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" ||
|
||||||
current_cpu == "arm64" || current_cpu == "riscv64" || current_cpu == "loong64"
|
current_cpu == "arm64" || current_cpu == "riscv64"
|
||||||
|
|
||||||
# We want to provide assertions that guard against inconsistent build
|
# We want to provide assertions that guard against inconsistent build
|
||||||
# args, but there is no point in having them fire if we're not building
|
# args, but there is no point in having them fire if we're not building
|
||||||
|
@@ -521,9 +521,6 @@ if (is_clang_or_gcc) {
|
|||||||
} else if (current_cpu == "riscv64") {
|
} else if (current_cpu == "riscv64") {
|
||||||
assert(stack_scan_supported)
|
assert(stack_scan_supported)
|
||||||
sources += [ "stack/asm/riscv64/push_registers_asm.cc" ]
|
sources += [ "stack/asm/riscv64/push_registers_asm.cc" ]
|
||||||
} else if (current_cpu == "loong64") {
|
|
||||||
assert(stack_scan_supported)
|
|
||||||
sources += [ "stack/asm/loong64/push_registers_asm.cc" ]
|
|
||||||
} else {
|
} else {
|
||||||
# To support a trampoline for another arch, please refer to v8/src/heap/base.
|
# To support a trampoline for another arch, please refer to v8/src/heap/base.
|
||||||
assert(!stack_scan_supported)
|
assert(!stack_scan_supported)
|
||||||
|
@@ -1,49 +0,0 @@
|
|||||||
// Copyright 2023 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// Push all callee-saved registers to get them on the stack for conservative
|
|
||||||
// stack scanning.
|
|
||||||
//
|
|
||||||
// See asm/x64/push_registers_asm.cc for why the function is not generated
|
|
||||||
// using clang.
|
|
||||||
//
|
|
||||||
// Calling convention source:
|
|
||||||
// https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
|
|
||||||
asm(".global PAPushAllRegistersAndIterateStack \n"
|
|
||||||
".type PAPushAllRegistersAndIterateStack, %function \n"
|
|
||||||
".hidden PAPushAllRegistersAndIterateStack \n"
|
|
||||||
"PAPushAllRegistersAndIterateStack: \n"
|
|
||||||
// Push all callee-saved registers and save return address.
|
|
||||||
" addi.d $sp, $sp, -96 \n"
|
|
||||||
// Save return address.
|
|
||||||
" st.d $ra, $sp, 88 \n"
|
|
||||||
// sp is callee-saved.
|
|
||||||
" st.d $sp, $sp, 80 \n"
|
|
||||||
// s0-s9(fp) are callee-saved.
|
|
||||||
" st.d $fp, $sp, 72 \n"
|
|
||||||
" st.d $s8, $sp, 64 \n"
|
|
||||||
" st.d $s7, $sp, 56 \n"
|
|
||||||
" st.d $s6, $sp, 48 \n"
|
|
||||||
" st.d $s5, $sp, 40 \n"
|
|
||||||
" st.d $s4, $sp, 32 \n"
|
|
||||||
" st.d $s3, $sp, 24 \n"
|
|
||||||
" st.d $s2, $sp, 16 \n"
|
|
||||||
" st.d $s1, $sp, 8 \n"
|
|
||||||
" st.d $s0, $sp, 0 \n"
|
|
||||||
// Maintain frame pointer(fp is s9).
|
|
||||||
" move $fp, $sp \n"
|
|
||||||
// Pass 1st parameter (a0) unchanged (Stack*).
|
|
||||||
// Pass 2nd parameter (a1) unchanged (StackVisitor*).
|
|
||||||
// Save 3rd parameter (a2; IterateStackCallback) to a3.
|
|
||||||
" move $a3, $a2 \n"
|
|
||||||
// Pass 3rd parameter as sp (stack pointer).
|
|
||||||
" move $a2, $sp \n"
|
|
||||||
// Call the callback.
|
|
||||||
" jirl $ra, $a3, 0 \n"
|
|
||||||
// Load return address.
|
|
||||||
" ld.d $ra, $sp, 88 \n"
|
|
||||||
// Restore frame pointer.
|
|
||||||
" ld.d $fp, $sp, 72 \n"
|
|
||||||
" addi.d $sp, $sp, 96 \n"
|
|
||||||
" jr $ra \n");
|
|
@@ -55,7 +55,7 @@ namespace base {
|
|||||||
// defined as a constant.
|
// defined as a constant.
|
||||||
|
|
||||||
// These constants are borrowed from glibc’s (arch)/bits/pthread_stack_min.h.
|
// These constants are borrowed from glibc’s (arch)/bits/pthread_stack_min.h.
|
||||||
#if defined(ARCH_CPU_ARM64) || defined(ARCH_CPU_LOONGARCH64)
|
#if defined(ARCH_CPU_ARM64)
|
||||||
#define PTHREAD_STACK_MIN_CONST \
|
#define PTHREAD_STACK_MIN_CONST \
|
||||||
(__builtin_constant_p(PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : 131072)
|
(__builtin_constant_p(PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : 131072)
|
||||||
#else
|
#else
|
||||||
|
@@ -216,14 +216,11 @@ config("default_libs") {
|
|||||||
# linking can have run-time side effects, nothing should be listed here.
|
# linking can have run-time side effects, nothing should be listed here.
|
||||||
libs = []
|
libs = []
|
||||||
} else if (is_linux || is_chromeos) {
|
} else if (is_linux || is_chromeos) {
|
||||||
# loong64 uses newer libc that subsumes libdl.so etc.
|
libs = [
|
||||||
if (current_cpu != "loong64") {
|
"dl",
|
||||||
libs = [
|
"pthread",
|
||||||
"dl",
|
"rt",
|
||||||
"pthread",
|
]
|
||||||
"rt",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -488,6 +488,11 @@ def removing_unnecessary_files(install_root, arch):
|
|||||||
ALLOWLIST = {
|
ALLOWLIST = {
|
||||||
f"usr/lib/gcc/{gcc_triple}/{GCC_VERSION}/libgcc.a",
|
f"usr/lib/gcc/{gcc_triple}/{GCC_VERSION}/libgcc.a",
|
||||||
f"usr/lib/{TRIPLES[arch]}/libc_nonshared.a",
|
f"usr/lib/{TRIPLES[arch]}/libc_nonshared.a",
|
||||||
|
|
||||||
|
# https://developers.redhat.com/articles/2021/12/17/why-glibc-234-removed-libpthread
|
||||||
|
f"usr/lib/{TRIPLES[arch]}/libdl.a",
|
||||||
|
f"usr/lib/{TRIPLES[arch]}/libpthread.a",
|
||||||
|
f"usr/lib/{TRIPLES[arch]}/librt.a",
|
||||||
}
|
}
|
||||||
|
|
||||||
for file in ALLOWLIST:
|
for file in ALLOWLIST:
|
||||||
|
@@ -195,6 +195,12 @@ def test_naive_once(proxy, *args, **kwargs):
|
|||||||
def test_naive(label, proxy, *args, **kwargs):
|
def test_naive(label, proxy, *args, **kwargs):
|
||||||
RETRIES = 5
|
RETRIES = 5
|
||||||
result = None
|
result = None
|
||||||
|
if argv.target_cpu == 'arm' and not label.startswith('Default'):
|
||||||
|
# Arm tests are too slow in qemu-user
|
||||||
|
# due to https://www.openwall.com/lists/musl/2017/06/15/9
|
||||||
|
print('** SKIP TEST:', label, end='\n\n')
|
||||||
|
return
|
||||||
|
|
||||||
for i in range(RETRIES):
|
for i in range(RETRIES):
|
||||||
result = test_naive_once(proxy, *args, **kwargs)
|
result = test_naive_once(proxy, *args, **kwargs)
|
||||||
if result == 'Failed to listen':
|
if result == 'Failed to listen':
|
||||||
|
6
shadowsocks-rust/Cargo.lock
generated
6
shadowsocks-rust/Cargo.lock
generated
@@ -2019,7 +2019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3900,9 +3900,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.44.1"
|
version = "1.44.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
|
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@@ -654,7 +654,7 @@ if (!isEmpty(main_node)) {
|
|||||||
urltest_nodes = [...urltest_nodes, ...filter(main_udp_urltest_nodes, (l) => !~index(urltest_nodes, l))];
|
urltest_nodes = [...urltest_nodes, ...filter(main_udp_urltest_nodes, (l) => !~index(urltest_nodes, l))];
|
||||||
} else if (dedicated_udp_node) {
|
} else if (dedicated_udp_node) {
|
||||||
const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {};
|
const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {};
|
||||||
if (main_node_cfg.type === 'wireguard') {
|
if (main_udp_node_cfg.type === 'wireguard') {
|
||||||
push(config.endpoints, generate_endpoint(main_udp_node_cfg));
|
push(config.endpoints, generate_endpoint(main_udp_node_cfg));
|
||||||
config.endpoints[length(config.endpoints)-1].tag = 'main-udp-out';
|
config.endpoints[length(config.endpoints)-1].tag = 'main-udp-out';
|
||||||
} else {
|
} else {
|
||||||
|
@@ -30,7 +30,7 @@ local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url',
|
|||||||
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
|
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
|
||||||
local save_words = ucic:get_first(name, 'server_subscribe', 'save_words', '')
|
local save_words = ucic:get_first(name, 'server_subscribe', 'save_words', '')
|
||||||
-- 读取 ss_type 设置
|
-- 读取 ss_type 设置
|
||||||
local ss_type = ucic:get_first(name, 'server_subscribe', 'ss_type')
|
local ss_type = ucic:get_first(name, 'server_subscribe', 'ss_type', 'ss-rust')
|
||||||
-- 根据 ss_type 选择对应的程序
|
-- 根据 ss_type 选择对应的程序
|
||||||
local ss_program = ""
|
local ss_program = ""
|
||||||
if ss_type == "ss-rust" then
|
if ss_type == "ss-rust" then
|
||||||
@@ -180,6 +180,7 @@ local function processData(szType, content)
|
|||||||
if not isCompleteJSON(content) then
|
if not isCompleteJSON(content) then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if szType == "hysteria2" or szType == "hy2" then
|
if szType == "hysteria2" or szType == "hy2" then
|
||||||
local url = URL.parse("http://" .. content)
|
local url = URL.parse("http://" .. content)
|
||||||
local params = url.query
|
local params = url.query
|
||||||
@@ -788,7 +789,7 @@ local execute = function()
|
|||||||
if result then
|
if result then
|
||||||
-- 中文做地址的 也没有人拿中文域名搞,就算中文域也有Puny Code SB 机场
|
-- 中文做地址的 也没有人拿中文域名搞,就算中文域也有Puny Code SB 机场
|
||||||
if not result.server or not result.server_port or result.alias == "NULL" or check_filer(result) or result.server:match("[^0-9a-zA-Z%-_%.%s]") or cache[groupHash][result.hashkey] then
|
if not result.server or not result.server_port or result.alias == "NULL" or check_filer(result) or result.server:match("[^0-9a-zA-Z%-_%.%s]") or cache[groupHash][result.hashkey] then
|
||||||
log('丢弃无效节点: ' .. result.type .. ' 节点, ' .. result.alias)
|
log('丢弃无效节点: ' .. result.alias)
|
||||||
else
|
else
|
||||||
-- log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
|
-- log('成功解析: ' .. result.type ..' 节点, ' .. result.alias)
|
||||||
result.grouphashkey = groupHash
|
result.grouphashkey = groupHash
|
||||||
|
@@ -5,12 +5,12 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=v2ray-core
|
PKG_NAME:=v2ray-core
|
||||||
PKG_VERSION:=5.29.3
|
PKG_VERSION:=5.30.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=f2a2eb4c835a99339746eaadbb1c88b4dcd022aa6d801ca44936be36f3ed027a
|
PKG_HASH:=8b10fc864289cb73e328d07b6d25b5e064d95e13fc5621ad4b5deb10137482b2
|
||||||
|
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
PKG_LICENSE_FILES:=LICENSE
|
PKG_LICENSE_FILES:=LICENSE
|
||||||
|
@@ -21,22 +21,22 @@ define Download/geoip
|
|||||||
HASH:=735786c00694313090c5d525516463836167422b132ce293873443613b496e92
|
HASH:=735786c00694313090c5d525516463836167422b132ce293873443613b496e92
|
||||||
endef
|
endef
|
||||||
|
|
||||||
GEOSITE_VER:=20250405160157
|
GEOSITE_VER:=20250407044718
|
||||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||||
define Download/geosite
|
define Download/geosite
|
||||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||||
URL_FILE:=dlc.dat
|
URL_FILE:=dlc.dat
|
||||||
FILE:=$(GEOSITE_FILE)
|
FILE:=$(GEOSITE_FILE)
|
||||||
HASH:=bf18a50193c260b5913af089394e49ca92967a1bb416d1e8e651667985e018bc
|
HASH:=a35d248bdf7892fbf747d94e656e45339c1d90c6b656b5c1311d62c1f2cbaadf
|
||||||
endef
|
endef
|
||||||
|
|
||||||
GEOSITE_IRAN_VER:=202503310039
|
GEOSITE_IRAN_VER:=202504070038
|
||||||
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
|
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
|
||||||
define Download/geosite-ir
|
define Download/geosite-ir
|
||||||
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
|
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
|
||||||
URL_FILE:=iran.dat
|
URL_FILE:=iran.dat
|
||||||
FILE:=$(GEOSITE_IRAN_FILE)
|
FILE:=$(GEOSITE_IRAN_FILE)
|
||||||
HASH:=1eb78f2dee6952b43dde65f72af44c1a064c97572ed0d72ad36fcf47ac4feafd
|
HASH:=ea5ed940fee6d7c872a143d160486e5d576124fc5167dfc6a8d55708281276ec
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/v2ray-geodata/template
|
define Package/v2ray-geodata/template
|
||||||
|
@@ -1023,14 +1023,21 @@ public class ConfigHandler
|
|||||||
|
|
||||||
var profileItem = await AppHandler.Instance.GetProfileItem(indexId) ?? new();
|
var profileItem = await AppHandler.Instance.GetProfileItem(indexId) ?? new();
|
||||||
profileItem.IndexId = indexId;
|
profileItem.IndexId = indexId;
|
||||||
profileItem.Remarks = multipleLoad switch
|
if (coreType == ECoreType.Xray)
|
||||||
{
|
{
|
||||||
EMultipleLoad.Random => ResUI.menuSetDefaultMultipleServerXrayRandom,
|
profileItem.Remarks = multipleLoad switch
|
||||||
EMultipleLoad.RoundRobin => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
|
{
|
||||||
EMultipleLoad.LeastPing => ResUI.menuSetDefaultMultipleServerXrayLeastPing,
|
EMultipleLoad.Random => ResUI.menuSetDefaultMultipleServerXrayRandom,
|
||||||
EMultipleLoad.LeastLoad => ResUI.menuSetDefaultMultipleServerXrayLeastLoad,
|
EMultipleLoad.RoundRobin => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
|
||||||
_ => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
|
EMultipleLoad.LeastPing => ResUI.menuSetDefaultMultipleServerXrayLeastPing,
|
||||||
};
|
EMultipleLoad.LeastLoad => ResUI.menuSetDefaultMultipleServerXrayLeastLoad,
|
||||||
|
_ => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (coreType == ECoreType.sing_box)
|
||||||
|
{
|
||||||
|
profileItem.Remarks = ResUI.menuSetDefaultMultipleServerSingBoxLeastPing;
|
||||||
|
}
|
||||||
profileItem.Address = Global.CoreMultipleLoadConfigFileName;
|
profileItem.Address = Global.CoreMultipleLoadConfigFileName;
|
||||||
profileItem.ConfigType = EConfigType.Custom;
|
profileItem.ConfigType = EConfigType.Custom;
|
||||||
profileItem.CoreType = coreType;
|
profileItem.CoreType = coreType;
|
||||||
|
@@ -172,14 +172,6 @@ object AppConfig {
|
|||||||
const val DNS_QUAD9_DOMAIN = "dns.quad9.net"
|
const val DNS_QUAD9_DOMAIN = "dns.quad9.net"
|
||||||
const val DNS_YANDEX_DOMAIN = "common.dot.dns.yandex.net"
|
const val DNS_YANDEX_DOMAIN = "common.dot.dns.yandex.net"
|
||||||
|
|
||||||
|
|
||||||
val DNS_ALIDNS_ADDRESSES = arrayListOf("223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1")
|
|
||||||
val DNS_CLOUDFLARE_ADDRESSES = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001")
|
|
||||||
val DNS_DNSPOD_ADDRESSES = arrayListOf("1.12.12.12", "120.53.53.53")
|
|
||||||
val DNS_GOOGLE_ADDRESSES = arrayListOf("8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844")
|
|
||||||
val DNS_QUAD9_ADDRESSES = arrayListOf("9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9")
|
|
||||||
val DNS_YANDEX_ADDRESSES = arrayListOf("77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff")
|
|
||||||
|
|
||||||
const val DEFAULT_PORT = 443
|
const val DEFAULT_PORT = 443
|
||||||
const val DEFAULT_SECURITY = "auto"
|
const val DEFAULT_SECURITY = "auto"
|
||||||
const val DEFAULT_LEVEL = 8
|
const val DEFAULT_LEVEL = 8
|
||||||
@@ -188,4 +180,27 @@ object AppConfig {
|
|||||||
const val REALITY = "reality"
|
const val REALITY = "reality"
|
||||||
const val HEADER_TYPE_HTTP = "http"
|
const val HEADER_TYPE_HTTP = "http"
|
||||||
|
|
||||||
|
val DNS_ALIDNS_ADDRESSES = arrayListOf("223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1")
|
||||||
|
val DNS_CLOUDFLARE_ADDRESSES = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001")
|
||||||
|
val DNS_DNSPOD_ADDRESSES = arrayListOf("1.12.12.12", "120.53.53.53")
|
||||||
|
val DNS_GOOGLE_ADDRESSES = arrayListOf("8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844")
|
||||||
|
val DNS_QUAD9_ADDRESSES = arrayListOf("9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9")
|
||||||
|
val DNS_YANDEX_ADDRESSES = arrayListOf("77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff")
|
||||||
|
|
||||||
|
val PRIVATE_IP_LIST = arrayListOf(
|
||||||
|
"0.0.0.0/8",
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"169.254.0.0/16",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
"192.0.0.0/24",
|
||||||
|
"192.0.2.0/24",
|
||||||
|
"192.88.99.0/24",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
"198.18.0.0/15",
|
||||||
|
"198.51.100.0/24",
|
||||||
|
"203.0.113.0/24",
|
||||||
|
"224.0.0.0/4",
|
||||||
|
"240.0.0.0/4"
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -417,6 +417,9 @@ object AngConfigManager {
|
|||||||
if (!Utils.isValidUrl(url)) {
|
if (!Utils.isValidUrl(url)) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if (!Utils.isValidSubUrl(url)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
Log.i(AppConfig.TAG, url)
|
Log.i(AppConfig.TAG, url)
|
||||||
|
|
||||||
var configText = try {
|
var configText = try {
|
||||||
@@ -430,7 +433,7 @@ object AngConfigManager {
|
|||||||
configText = try {
|
configText = try {
|
||||||
HttpUtil.getUrlContentWithUserAgent(url)
|
HttpUtil.getUrlContentWithUserAgent(url)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(AppConfig.TAG, "Failed to get URL content with user agent", e)
|
Log.e(AppConfig.TAG, "Update subscription: Failed to get URL content with user agent", e)
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -166,7 +166,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
//builder.addDnsServer(PRIVATE_VLAN4_ROUTER)
|
//builder.addDnsServer(PRIVATE_VLAN4_ROUTER)
|
||||||
val bypassLan = SettingsManager.routingRulesetsBypassLan()
|
val bypassLan = SettingsManager.routingRulesetsBypassLan()
|
||||||
if (bypassLan) {
|
if (bypassLan) {
|
||||||
resources.getStringArray(R.array.bypass_private_ip_address).forEach {
|
AppConfig.PRIVATE_IP_LIST.forEach {
|
||||||
val addr = it.split('/')
|
val addr = it.split('/')
|
||||||
builder.addRoute(addr[0], addr[1].toInt())
|
builder.addRoute(addr[0], addr[1].toInt())
|
||||||
}
|
}
|
||||||
|
@@ -90,7 +90,7 @@ class SubEditActivity : BaseActivity() {
|
|||||||
|
|
||||||
if (!Utils.isValidSubUrl(subItem.url)) {
|
if (!Utils.isValidSubUrl(subItem.url)) {
|
||||||
toast(R.string.toast_insecure_url_protocol)
|
toast(R.string.toast_insecure_url_protocol)
|
||||||
//return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,8 +7,11 @@ import com.v2ray.ang.BuildConfig
|
|||||||
import com.v2ray.ang.util.Utils.encode
|
import com.v2ray.ang.util.Utils.encode
|
||||||
import com.v2ray.ang.util.Utils.urlDecode
|
import com.v2ray.ang.util.Utils.urlDecode
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.*
|
import java.net.HttpURLConnection
|
||||||
import java.util.*
|
import java.net.IDN
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.net.Proxy
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
object HttpUtil {
|
object HttpUtil {
|
||||||
|
|
||||||
@@ -20,7 +23,7 @@ object HttpUtil {
|
|||||||
* @return The ASCII representation of the URL.
|
* @return The ASCII representation of the URL.
|
||||||
*/
|
*/
|
||||||
fun idnToASCII(str: String): String {
|
fun idnToASCII(str: String): String {
|
||||||
val url = URI(str)
|
val url = URL(str)
|
||||||
val host = url.host
|
val host = url.host
|
||||||
val asciiHost = IDN.toASCII(url.host, IDN.ALLOW_UNASSIGNED)
|
val asciiHost = IDN.toASCII(url.host, IDN.ALLOW_UNASSIGNED)
|
||||||
if (host != asciiHost) {
|
if (host != asciiHost) {
|
||||||
|
@@ -20,7 +20,9 @@ import com.v2ray.ang.AppConfig
|
|||||||
import com.v2ray.ang.AppConfig.LOOPBACK
|
import com.v2ray.ang.AppConfig.LOOPBACK
|
||||||
import com.v2ray.ang.BuildConfig
|
import com.v2ray.ang.BuildConfig
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.net.InetAddress
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
|
import java.net.URI
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@@ -461,13 +463,23 @@ object Utils {
|
|||||||
fun isValidSubUrl(value: String?): Boolean {
|
fun isValidSubUrl(value: String?): Boolean {
|
||||||
if (value.isNullOrEmpty()) return false
|
if (value.isNullOrEmpty()) return false
|
||||||
|
|
||||||
return try {
|
try {
|
||||||
URLUtil.isHttpsUrl(value) ||
|
if (URLUtil.isHttpsUrl(value)) return true
|
||||||
(URLUtil.isHttpUrl(value) && value.contains(LOOPBACK))
|
if (URLUtil.isHttpUrl(value)) {
|
||||||
|
if (value.contains(LOOPBACK)) return true
|
||||||
|
|
||||||
|
//Check private ip address
|
||||||
|
val uri = URI(fixIllegalUrl(value))
|
||||||
|
if (isIpAddress(uri.host)) {
|
||||||
|
AppConfig.PRIVATE_IP_LIST.forEach {
|
||||||
|
if (isIpInCidr(uri.host, it)) return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(AppConfig.TAG, "Failed to validate subscription URL", e)
|
Log.e(AppConfig.TAG, "Failed to validate subscription URL", e)
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -495,5 +507,49 @@ object Utils {
|
|||||||
*/
|
*/
|
||||||
fun isGoogleFlavor(): Boolean = BuildConfig.FLAVOR == "playstore"
|
fun isGoogleFlavor(): Boolean = BuildConfig.FLAVOR == "playstore"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an InetAddress to its long representation
|
||||||
|
*
|
||||||
|
* @param ip The InetAddress to convert
|
||||||
|
* @return The long representation of the IP address
|
||||||
|
*/
|
||||||
|
private fun inetAddressToLong(ip: InetAddress): Long {
|
||||||
|
val bytes = ip.address
|
||||||
|
var result: Long = 0
|
||||||
|
for (i in bytes.indices) {
|
||||||
|
result = result shl 8 or (bytes[i].toInt() and 0xff).toLong()
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an IP address is within a CIDR range
|
||||||
|
*
|
||||||
|
* @param ip The IP address to check
|
||||||
|
* @param cidr The CIDR notation range (e.g., "192.168.1.0/24")
|
||||||
|
* @return True if the IP is within the CIDR range, false otherwise
|
||||||
|
*/
|
||||||
|
fun isIpInCidr(ip: String, cidr: String): Boolean {
|
||||||
|
try {
|
||||||
|
if (!isIpAddress(ip)) return false
|
||||||
|
|
||||||
|
// Parse CIDR (e.g., "192.168.1.0/24")
|
||||||
|
val (cidrIp, prefixLen) = cidr.split("/")
|
||||||
|
val prefixLength = prefixLen.toInt()
|
||||||
|
|
||||||
|
// Convert IP and CIDR's IP portion to Long
|
||||||
|
val ipLong = inetAddressToLong(InetAddress.getByName(ip))
|
||||||
|
val cidrIpLong = inetAddressToLong(InetAddress.getByName(cidrIp))
|
||||||
|
|
||||||
|
// Calculate subnet mask (e.g., /24 → 0xFFFFFF00)
|
||||||
|
val mask = if (prefixLength == 0) 0L else (-1L shl (32 - prefixLength))
|
||||||
|
|
||||||
|
// Check if they're in the same subnet
|
||||||
|
return (ipLong and mask) == (cidrIpLong and mask)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(AppConfig.TAG, "Failed to check if IP is in CIDR", e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -124,43 +124,6 @@
|
|||||||
<item>xtls-rprx-vision-udp443</item>
|
<item>xtls-rprx-vision-udp443</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
<!-- minimum list https://serverfault.com/a/304791 -->
|
|
||||||
<string-array name="bypass_private_ip_address" translatable="false">
|
|
||||||
<item>0.0.0.0/5</item>
|
|
||||||
<item>8.0.0.0/7</item>
|
|
||||||
<item>11.0.0.0/8</item>
|
|
||||||
<item>12.0.0.0/6</item>
|
|
||||||
<item>16.0.0.0/4</item>
|
|
||||||
<item>32.0.0.0/3</item>
|
|
||||||
<item>64.0.0.0/2</item>
|
|
||||||
<item>128.0.0.0/3</item>
|
|
||||||
<item>160.0.0.0/5</item>
|
|
||||||
<item>168.0.0.0/6</item>
|
|
||||||
<item>172.0.0.0/12</item>
|
|
||||||
<item>172.32.0.0/11</item>
|
|
||||||
<item>172.64.0.0/10</item>
|
|
||||||
<item>172.128.0.0/9</item>
|
|
||||||
<item>173.0.0.0/8</item>
|
|
||||||
<item>174.0.0.0/7</item>
|
|
||||||
<item>176.0.0.0/4</item>
|
|
||||||
<item>192.0.0.0/9</item>
|
|
||||||
<item>192.128.0.0/11</item>
|
|
||||||
<item>192.160.0.0/13</item>
|
|
||||||
<item>192.169.0.0/16</item>
|
|
||||||
<item>192.170.0.0/15</item>
|
|
||||||
<item>192.172.0.0/14</item>
|
|
||||||
<item>192.176.0.0/12</item>
|
|
||||||
<item>192.192.0.0/10</item>
|
|
||||||
<item>193.0.0.0/8</item>
|
|
||||||
<item>194.0.0.0/7</item>
|
|
||||||
<item>196.0.0.0/6</item>
|
|
||||||
<item>200.0.0.0/5</item>
|
|
||||||
<item>208.0.0.0/4</item>
|
|
||||||
<item>240.0.0.0/4</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
|
|
||||||
<string-array name="language_select" translatable="false">
|
<string-array name="language_select" translatable="false">
|
||||||
<item>auto</item>
|
<item>auto</item>
|
||||||
<item>English</item>
|
<item>English</item>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
||||||
<base-config>
|
<base-config cleartextTrafficPermitted="true">
|
||||||
<trust-anchors>
|
<trust-anchors>
|
||||||
<certificates src="system" />
|
<certificates src="system" />
|
||||||
<certificates
|
<certificates
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
package com.v2ray.ang
|
||||||
|
|
||||||
|
import com.v2ray.ang.util.HttpUtil
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class HttpUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIdnToASCII() {
|
||||||
|
// Regular URL remains unchanged
|
||||||
|
val regularUrl = "https://example.com/path"
|
||||||
|
assertEquals(regularUrl, HttpUtil.idnToASCII(regularUrl))
|
||||||
|
|
||||||
|
// Non-ASCII URL converts to ASCII (Punycode)
|
||||||
|
val nonAsciiUrl = "https://例子.测试/path"
|
||||||
|
val expectedNonAscii = "https://xn--fsqu00a.xn--0zwm56d/path"
|
||||||
|
assertEquals(expectedNonAscii, HttpUtil.idnToASCII(nonAsciiUrl))
|
||||||
|
|
||||||
|
// Mixed URL only converts the host part
|
||||||
|
val mixedUrl = "https://例子.com/测试"
|
||||||
|
val expectedMixed = "https://xn--fsqu00a.com/测试"
|
||||||
|
assertEquals(expectedMixed, HttpUtil.idnToASCII(mixedUrl))
|
||||||
|
|
||||||
|
// URL with Basic Authentication using regular domain
|
||||||
|
val basicAuthUrl = "https://user:password@example.com/path"
|
||||||
|
assertEquals(basicAuthUrl, HttpUtil.idnToASCII(basicAuthUrl))
|
||||||
|
|
||||||
|
// URL with Basic Authentication using non-ASCII domain
|
||||||
|
val basicAuthNonAscii = "https://user:password@例子.测试/path"
|
||||||
|
val expectedBasicAuthNonAscii = "https://user:password@xn--fsqu00a.xn--0zwm56d/path"
|
||||||
|
assertEquals(expectedBasicAuthNonAscii, HttpUtil.idnToASCII(basicAuthNonAscii))
|
||||||
|
|
||||||
|
// URL with non-ASCII username and password
|
||||||
|
val nonAsciiAuth = "https://用户:密码@example.com/path"
|
||||||
|
// Basic auth credentials should remain unchanged as they're percent-encoded separately
|
||||||
|
assertEquals(nonAsciiAuth, HttpUtil.idnToASCII(nonAsciiAuth))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -11,7 +11,7 @@ import org.junit.Test
|
|||||||
*
|
*
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
*/
|
*/
|
||||||
class AngUnitTest {
|
class UtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_parseInt() {
|
fun test_parseInt() {
|
||||||
@@ -45,4 +45,18 @@ class AngUnitTest {
|
|||||||
assertTrue(Utils.isIpAddress("240e:1234:abcd:12::/64"))
|
assertTrue(Utils.isIpAddress("240e:1234:abcd:12::/64"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_IsIpInCidr() {
|
||||||
|
assertTrue(Utils.isIpInCidr("192.168.1.1", "192.168.1.0/24"))
|
||||||
|
assertTrue(Utils.isIpInCidr("192.168.1.254", "192.168.1.0/24"))
|
||||||
|
assertFalse(Utils.isIpInCidr("192.168.2.1", "192.168.1.0/24"))
|
||||||
|
|
||||||
|
assertTrue(Utils.isIpInCidr("10.0.0.0", "10.0.0.0/8"))
|
||||||
|
assertTrue(Utils.isIpInCidr("10.255.255.255", "10.0.0.0/8"))
|
||||||
|
assertFalse(Utils.isIpInCidr("11.0.0.0", "10.0.0.0/8"))
|
||||||
|
|
||||||
|
assertFalse(Utils.isIpInCidr("invalid-ip", "192.168.1.0/24"))
|
||||||
|
assertFalse(Utils.isIpInCidr("192.168.1.1", "invalid-cidr"))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -9,7 +9,7 @@ require (
|
|||||||
github.com/golang/mock v1.7.0-rc.1
|
github.com/golang/mock v1.7.0-rc.1
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/miekg/dns v1.1.64
|
github.com/miekg/dns v1.1.65
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.8.0
|
github.com/pires/go-proxyproto v0.8.0
|
||||||
github.com/quic-go/quic-go v0.50.1
|
github.com/quic-go/quic-go v0.50.1
|
||||||
@@ -22,12 +22,12 @@ require (
|
|||||||
github.com/vishvananda/netlink v1.3.0
|
github.com/vishvananda/netlink v1.3.0
|
||||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
|
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.36.0
|
golang.org/x/crypto v0.37.0
|
||||||
golang.org/x/net v0.38.0
|
golang.org/x/net v0.38.0
|
||||||
golang.org/x/sync v0.12.0
|
golang.org/x/sync v0.13.0
|
||||||
golang.org/x/sys v0.31.0
|
golang.org/x/sys v0.32.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
google.golang.org/grpc v1.71.0
|
google.golang.org/grpc v1.71.1
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
|
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
@@ -51,7 +51,7 @@ require (
|
|||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
||||||
golang.org/x/mod v0.23.0 // indirect
|
golang.org/x/mod v0.23.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.24.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.30.0 // indirect
|
golang.org/x/tools v0.30.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
|
@@ -38,8 +38,8 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N
|
|||||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
|
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||||
github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||||
@@ -97,8 +97,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
||||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
@@ -111,8 +111,8 @@ golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
|||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -121,14 +121,14 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -145,8 +145,8 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
|
|||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
|
||||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
@@ -8,11 +8,13 @@ import (
|
|||||||
|
|
||||||
type Duration int64
|
type Duration int64
|
||||||
|
|
||||||
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
func (d *Duration) MarshalJSON() ([]byte, error) {
|
func (d *Duration) MarshalJSON() ([]byte, error) {
|
||||||
dr := time.Duration(*d)
|
dr := time.Duration(*d)
|
||||||
return json.Marshal(dr.String())
|
return json.Marshal(dr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
if err := json.Unmarshal(b, &v); err != nil {
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
@@ -23,6 +23,7 @@ func (v StringList) Len() int {
|
|||||||
return len(v)
|
return len(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *StringList) UnmarshalJSON(data []byte) error {
|
func (v *StringList) UnmarshalJSON(data []byte) error {
|
||||||
var strarray []string
|
var strarray []string
|
||||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||||
@@ -43,10 +44,12 @@ type Address struct {
|
|||||||
net.Address
|
net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Address) MarshalJSON() ([]byte, error) {
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (v *Address) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(v.Address.String())
|
return json.Marshal(v.Address.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *Address) UnmarshalJSON(data []byte) error {
|
func (v *Address) UnmarshalJSON(data []byte) error {
|
||||||
var rawStr string
|
var rawStr string
|
||||||
if err := json.Unmarshal(data, &rawStr); err != nil {
|
if err := json.Unmarshal(data, &rawStr); err != nil {
|
||||||
@@ -81,6 +84,7 @@ func (v Network) Build() net.Network {
|
|||||||
|
|
||||||
type NetworkList []Network
|
type NetworkList []Network
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
||||||
var strarray []Network
|
var strarray []Network
|
||||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||||
@@ -169,6 +173,19 @@ func (v *PortRange) Build() *net.PortRange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (v *PortRange) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(v.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (port *PortRange) String() string {
|
||||||
|
if port.From == port.To {
|
||||||
|
return strconv.Itoa(int(port.From))
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%d-%d", port.From, port.To)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *PortRange) UnmarshalJSON(data []byte) error {
|
func (v *PortRange) UnmarshalJSON(data []byte) error {
|
||||||
port, err := parseIntPort(data)
|
port, err := parseIntPort(data)
|
||||||
@@ -203,20 +220,21 @@ func (list *PortList) Build() *net.PortList {
|
|||||||
return portList
|
return portList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PortList) MarshalJSON() ([]byte, error) {
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
return json.Marshal(v.String())
|
func (v *PortList) MarshalJSON() ([]byte, error) {
|
||||||
|
portStr := v.String()
|
||||||
|
port, err := strconv.Atoi(portStr)
|
||||||
|
if err == nil {
|
||||||
|
return json.Marshal(port)
|
||||||
|
} else {
|
||||||
|
return json.Marshal(portStr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PortList) String() string {
|
func (v PortList) String() string {
|
||||||
ports := []string{}
|
ports := []string{}
|
||||||
for _, port := range v.Range {
|
for _, port := range v.Range {
|
||||||
if port.From == port.To {
|
ports = append(ports, port.String())
|
||||||
p := strconv.Itoa(int(port.From))
|
|
||||||
ports = append(ports, p)
|
|
||||||
} else {
|
|
||||||
p := fmt.Sprintf("%d-%d", port.From, port.To)
|
|
||||||
ports = append(ports, p)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return strings.Join(ports, ",")
|
return strings.Join(ports, ",")
|
||||||
}
|
}
|
||||||
@@ -277,7 +295,8 @@ type Int32Range struct {
|
|||||||
To int32
|
To int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Int32Range) MarshalJSON() ([]byte, error) {
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (v *Int32Range) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(v.String())
|
return json.Marshal(v.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,6 +308,7 @@ func (v Int32Range) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *Int32Range) UnmarshalJSON(data []byte) error {
|
func (v *Int32Range) UnmarshalJSON(data []byte) error {
|
||||||
defer v.ensureOrder()
|
defer v.ensureOrder()
|
||||||
var str string
|
var str string
|
||||||
|
@@ -25,6 +25,7 @@ type NameServerConfig struct {
|
|||||||
TimeoutMs uint64 `json:"timeoutMs"`
|
TimeoutMs uint64 `json:"timeoutMs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
||||||
var address Address
|
var address Address
|
||||||
if err := json.Unmarshal(data, &address); err == nil {
|
if err := json.Unmarshal(data, &address); err == nil {
|
||||||
@@ -163,6 +164,18 @@ type HostAddress struct {
|
|||||||
addrs []*Address
|
addrs []*Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (h *HostAddress) MarshalJSON() ([]byte, error) {
|
||||||
|
if (h.addr != nil) != (h.addrs != nil) {
|
||||||
|
if h.addr != nil {
|
||||||
|
return json.Marshal(h.addr)
|
||||||
|
} else if h.addrs != nil {
|
||||||
|
return json.Marshal(h.addrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.New("unexpected config state")
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (h *HostAddress) UnmarshalJSON(data []byte) error {
|
func (h *HostAddress) UnmarshalJSON(data []byte) error {
|
||||||
addr := new(Address)
|
addr := new(Address)
|
||||||
@@ -208,6 +221,11 @@ func getHostMapping(ha *HostAddress) *dns.Config_HostMapping {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (m *HostsWrapper) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(m.Hosts)
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
|
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
|
||||||
hosts := make(map[string]*HostAddress)
|
hosts := make(map[string]*HostAddress)
|
||||||
|
@@ -20,6 +20,18 @@ type FakeDNSConfig struct {
|
|||||||
pools []*FakeDNSPoolElementConfig
|
pools []*FakeDNSPoolElementConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||||
|
func (f *FakeDNSConfig) MarshalJSON() ([]byte, error) {
|
||||||
|
if (f.pool != nil) != (f.pools != nil) {
|
||||||
|
if f.pool != nil {
|
||||||
|
return json.Marshal(f.pool)
|
||||||
|
} else if f.pools != nil {
|
||||||
|
return json.Marshal(f.pools)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errors.New("unexpected config state")
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
|
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
|
||||||
var pool FakeDNSPoolElementConfig
|
var pool FakeDNSPoolElementConfig
|
||||||
|
@@ -13,9 +13,6 @@ const (
|
|||||||
TCP_FASTOPEN = 15
|
TCP_FASTOPEN = 15
|
||||||
IP_UNICAST_IF = 31
|
IP_UNICAST_IF = 31
|
||||||
IPV6_UNICAST_IF = 31
|
IPV6_UNICAST_IF = 31
|
||||||
IP_MULTICAST_IF = 9
|
|
||||||
IPV6_MULTICAST_IF = 9
|
|
||||||
IPV6_V6ONLY = 27
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func setTFO(fd syscall.Handle, tfo int) error {
|
func setTFO(fd syscall.Handle, tfo int) error {
|
||||||
@@ -44,14 +41,14 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_UNICAST_IF, int(idx)); err != nil {
|
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_UNICAST_IF, int(idx)); err != nil {
|
||||||
return errors.New("failed to set IP_UNICAST_IF").Base(err)
|
return errors.New("failed to set IP_UNICAST_IF").Base(err)
|
||||||
}
|
}
|
||||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_MULTICAST_IF, int(idx)); err != nil {
|
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, int(idx)); err != nil {
|
||||||
return errors.New("failed to set IP_MULTICAST_IF").Base(err)
|
return errors.New("failed to set IP_MULTICAST_IF").Base(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, inf.Index); err != nil {
|
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, inf.Index); err != nil {
|
||||||
return errors.New("failed to set IPV6_UNICAST_IF").Base(err)
|
return errors.New("failed to set IPV6_UNICAST_IF").Base(err)
|
||||||
}
|
}
|
||||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_MULTICAST_IF, inf.Index); err != nil {
|
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, inf.Index); err != nil {
|
||||||
return errors.New("failed to set IPV6_MULTICAST_IF").Base(err)
|
return errors.New("failed to set IPV6_MULTICAST_IF").Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +89,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.V6Only {
|
if config.V6Only {
|
||||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_V6ONLY, 1); err != nil {
|
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1); err != nil {
|
||||||
return errors.New("failed to set IPV6_V6ONLY").Base(err)
|
return errors.New("failed to set IPV6_V6ONLY").Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -659,6 +659,8 @@ class TestUtil(unittest.TestCase):
|
|||||||
self.assertEqual(url_or_none('mms://foo.de'), 'mms://foo.de')
|
self.assertEqual(url_or_none('mms://foo.de'), 'mms://foo.de')
|
||||||
self.assertEqual(url_or_none('rtspu://foo.de'), 'rtspu://foo.de')
|
self.assertEqual(url_or_none('rtspu://foo.de'), 'rtspu://foo.de')
|
||||||
self.assertEqual(url_or_none('ftps://foo.de'), 'ftps://foo.de')
|
self.assertEqual(url_or_none('ftps://foo.de'), 'ftps://foo.de')
|
||||||
|
self.assertEqual(url_or_none('ws://foo.de'), 'ws://foo.de')
|
||||||
|
self.assertEqual(url_or_none('wss://foo.de'), 'wss://foo.de')
|
||||||
|
|
||||||
def test_parse_age_limit(self):
|
def test_parse_age_limit(self):
|
||||||
self.assertEqual(parse_age_limit(None), None)
|
self.assertEqual(parse_age_limit(None), None)
|
||||||
|
@@ -85,6 +85,7 @@ class NiconicoLiveFD(FileDownloader):
|
|||||||
'quality': live_quality,
|
'quality': live_quality,
|
||||||
'protocol': 'hls+fmp4',
|
'protocol': 'hls+fmp4',
|
||||||
'latency': live_latency,
|
'latency': live_latency,
|
||||||
|
'accessRightMethod': 'single_cookie',
|
||||||
'chasePlay': False,
|
'chasePlay': False,
|
||||||
},
|
},
|
||||||
'room': {
|
'room': {
|
||||||
|
@@ -903,6 +903,7 @@ from .ivi import (
|
|||||||
IviIE,
|
IviIE,
|
||||||
)
|
)
|
||||||
from .ivideon import IvideonIE
|
from .ivideon import IvideonIE
|
||||||
|
from .ivoox import IvooxIE
|
||||||
from .iwara import (
|
from .iwara import (
|
||||||
IwaraIE,
|
IwaraIE,
|
||||||
IwaraPlaylistIE,
|
IwaraPlaylistIE,
|
||||||
@@ -960,7 +961,10 @@ from .kick import (
|
|||||||
)
|
)
|
||||||
from .kicker import KickerIE
|
from .kicker import KickerIE
|
||||||
from .kickstarter import KickStarterIE
|
from .kickstarter import KickStarterIE
|
||||||
from .kika import KikaIE
|
from .kika import (
|
||||||
|
KikaIE,
|
||||||
|
KikaPlaylistIE,
|
||||||
|
)
|
||||||
from .kinja import KinjaEmbedIE
|
from .kinja import KinjaEmbedIE
|
||||||
from .kinopoisk import KinoPoiskIE
|
from .kinopoisk import KinoPoiskIE
|
||||||
from .kommunetv import KommunetvIE
|
from .kommunetv import KommunetvIE
|
||||||
@@ -1061,6 +1065,7 @@ from .loom import (
|
|||||||
from .lovehomeporn import LoveHomePornIE
|
from .lovehomeporn import LoveHomePornIE
|
||||||
from .lrt import (
|
from .lrt import (
|
||||||
LRTVODIE,
|
LRTVODIE,
|
||||||
|
LRTRadioIE,
|
||||||
LRTStreamIE,
|
LRTStreamIE,
|
||||||
)
|
)
|
||||||
from .lsm import (
|
from .lsm import (
|
||||||
|
78
yt-dlp/yt_dlp/extractor/ivoox.py
Normal file
78
yt-dlp/yt_dlp/extractor/ivoox.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import int_or_none, parse_iso8601, url_or_none, urljoin
|
||||||
|
from ..utils.traversal import traverse_obj
|
||||||
|
|
||||||
|
|
||||||
|
class IvooxIE(InfoExtractor):
|
||||||
|
_VALID_URL = (
|
||||||
|
r'https?://(?:www\.)?ivoox\.com/(?:\w{2}/)?[^/?#]+_rf_(?P<id>[0-9]+)_1\.html',
|
||||||
|
r'https?://go\.ivoox\.com/rf/(?P<id>[0-9]+)',
|
||||||
|
)
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.ivoox.com/dex-08x30-rostros-del-mal-los-asesinos-en-audios-mp3_rf_143594959_1.html',
|
||||||
|
'md5': '993f712de5b7d552459fc66aa3726885',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '143594959',
|
||||||
|
'ext': 'mp3',
|
||||||
|
'timestamp': 1742731200,
|
||||||
|
'channel': 'DIAS EXTRAÑOS con Santiago Camacho',
|
||||||
|
'title': 'DEx 08x30 Rostros del mal: Los asesinos en serie que aterrorizaron España',
|
||||||
|
'description': 'md5:eae8b4b9740d0216d3871390b056bb08',
|
||||||
|
'uploader': 'Santiago Camacho',
|
||||||
|
'thumbnail': 'https://static-1.ivoox.com/audios/c/d/5/2/cd52f46783fe735000c33a803dce2554_XXL.jpg',
|
||||||
|
'upload_date': '20250323',
|
||||||
|
'episode': 'DEx 08x30 Rostros del mal: Los asesinos en serie que aterrorizaron España',
|
||||||
|
'duration': 11837,
|
||||||
|
'tags': ['españa', 'asesinos en serie', 'arropiero', 'historia criminal', 'mataviejas'],
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'https://go.ivoox.com/rf/143594959',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.ivoox.com/en/campodelgas-28-03-2025-audios-mp3_rf_144036942_1.html',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
media_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, media_id, fatal=False)
|
||||||
|
|
||||||
|
data = self._search_nuxt_data(
|
||||||
|
webpage, media_id, fatal=False, traverse=('data', 0, 'data', 'audio'))
|
||||||
|
|
||||||
|
direct_download = self._download_json(
|
||||||
|
f'https://vcore-web.ivoox.com/v1/public/audios/{media_id}/download-url', media_id, fatal=False,
|
||||||
|
note='Fetching direct download link', headers={'Referer': url})
|
||||||
|
|
||||||
|
download_paths = {
|
||||||
|
*traverse_obj(direct_download, ('data', 'downloadUrl', {str}, filter, all)),
|
||||||
|
*traverse_obj(data, (('downloadUrl', 'mediaUrl'), {str}, filter)),
|
||||||
|
}
|
||||||
|
|
||||||
|
formats = []
|
||||||
|
for path in download_paths:
|
||||||
|
formats.append({
|
||||||
|
'url': urljoin('https://ivoox.com', path),
|
||||||
|
'http_headers': {'Referer': url},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': media_id,
|
||||||
|
'formats': formats,
|
||||||
|
'uploader': self._html_search_regex(r'data-prm-author="([^"]+)"', webpage, 'author', default=None),
|
||||||
|
'timestamp': parse_iso8601(
|
||||||
|
self._html_search_regex(r'data-prm-pubdate="([^"]+)"', webpage, 'timestamp', default=None)),
|
||||||
|
'channel': self._html_search_regex(r'data-prm-podname="([^"]+)"', webpage, 'channel', default=None),
|
||||||
|
'title': self._html_search_regex(r'data-prm-title="([^"]+)"', webpage, 'title', default=None),
|
||||||
|
'thumbnail': self._og_search_thumbnail(webpage, default=None),
|
||||||
|
'description': self._og_search_description(webpage, default=None),
|
||||||
|
**self._search_json_ld(webpage, media_id, default={}),
|
||||||
|
**traverse_obj(data, {
|
||||||
|
'title': ('title', {str}),
|
||||||
|
'description': ('description', {str}),
|
||||||
|
'thumbnail': ('image', {url_or_none}),
|
||||||
|
'timestamp': ('uploadDate', {parse_iso8601(delimiter=' ')}),
|
||||||
|
'duration': ('duration', {int_or_none}),
|
||||||
|
'tags': ('tags', ..., 'name', {str}),
|
||||||
|
}),
|
||||||
|
}
|
@@ -1,3 +1,5 @@
|
|||||||
|
import itertools
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
determine_ext,
|
determine_ext,
|
||||||
@@ -124,3 +126,43 @@ class KikaIE(InfoExtractor):
|
|||||||
'vbr': ('bitrateVideo', {int_or_none}, {lambda x: None if x == -1 else x}),
|
'vbr': ('bitrateVideo', {int_or_none}, {lambda x: None if x == -1 else x}),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class KikaPlaylistIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?kika\.de/[\w-]+/(?P<id>[a-z-]+\d+)'
|
||||||
|
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.kika.de/logo/logo-die-welt-und-ich-562',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'logo-die-welt-und-ich-562',
|
||||||
|
'title': 'logo!',
|
||||||
|
'description': 'md5:7b9d7f65561b82fa512f2cfb553c397d',
|
||||||
|
},
|
||||||
|
'playlist_count': 100,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _entries(self, playlist_url, playlist_id):
|
||||||
|
for page in itertools.count(1):
|
||||||
|
data = self._download_json(playlist_url, playlist_id, note=f'Downloading page {page}')
|
||||||
|
for item in traverse_obj(data, ('content', lambda _, v: url_or_none(v['api']['url']))):
|
||||||
|
yield self.url_result(
|
||||||
|
item['api']['url'], ie=KikaIE,
|
||||||
|
**traverse_obj(item, {
|
||||||
|
'id': ('id', {str}),
|
||||||
|
'title': ('title', {str}),
|
||||||
|
'duration': ('duration', {int_or_none}),
|
||||||
|
'timestamp': ('date', {parse_iso8601}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
playlist_url = traverse_obj(data, ('links', 'next', {url_or_none}))
|
||||||
|
if not playlist_url:
|
||||||
|
break
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
playlist_id = self._match_id(url)
|
||||||
|
brand_data = self._download_json(
|
||||||
|
f'https://www.kika.de/_next-api/proxy/v1/brands/{playlist_id}', playlist_id)
|
||||||
|
|
||||||
|
return self.playlist_result(
|
||||||
|
self._entries(brand_data['videoSubchannel']['videosPageUrl'], playlist_id),
|
||||||
|
playlist_id, title=brand_data.get('title'), description=brand_data.get('description'))
|
||||||
|
@@ -2,8 +2,11 @@ from .common import InfoExtractor
|
|||||||
from ..utils import (
|
from ..utils import (
|
||||||
clean_html,
|
clean_html,
|
||||||
merge_dicts,
|
merge_dicts,
|
||||||
|
str_or_none,
|
||||||
traverse_obj,
|
traverse_obj,
|
||||||
|
unified_timestamp,
|
||||||
url_or_none,
|
url_or_none,
|
||||||
|
urljoin,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +83,7 @@ class LRTVODIE(LRTBaseIE):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
path, video_id = self._match_valid_url(url).groups()
|
path, video_id = self._match_valid_url(url).group('path', 'id')
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
media_url = self._extract_js_var(webpage, 'main_url', path)
|
media_url = self._extract_js_var(webpage, 'main_url', path)
|
||||||
@@ -106,3 +109,42 @@ class LRTVODIE(LRTBaseIE):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return merge_dicts(clean_info, jw_data, json_ld_data)
|
return merge_dicts(clean_info, jw_data, json_ld_data)
|
||||||
|
|
||||||
|
|
||||||
|
class LRTRadioIE(LRTBaseIE):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?lrt\.lt/radioteka/irasas/(?P<id>\d+)/(?P<path>[^?#/]+)'
|
||||||
|
_TESTS = [{
|
||||||
|
# m3u8 download
|
||||||
|
'url': 'https://www.lrt.lt/radioteka/irasas/2000359728/nemarios-eiles-apie-pragarus-ir-skaistyklas-su-aiste-kiltinaviciute',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '2000359728',
|
||||||
|
'ext': 'm4a',
|
||||||
|
'title': 'Nemarios eilės: apie pragarus ir skaistyklas su Aiste Kiltinavičiūte',
|
||||||
|
'description': 'md5:5eee9a0e86a55bf547bd67596204625d',
|
||||||
|
'timestamp': 1726143120,
|
||||||
|
'upload_date': '20240912',
|
||||||
|
'tags': 'count:5',
|
||||||
|
'thumbnail': r're:https?://.+/.+\.jpe?g',
|
||||||
|
'categories': ['Daiktiniai įrodymai'],
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.lrt.lt/radioteka/irasas/2000304654/vakaras-su-knyga-svetlana-aleksijevic-cernobylio-malda-v-dalis?season=%2Fmediateka%2Faudio%2Fvakaras-su-knyga%2F2023',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id, path = self._match_valid_url(url).group('id', 'path')
|
||||||
|
media = self._download_json(
|
||||||
|
'https://www.lrt.lt/radioteka/api/media', video_id,
|
||||||
|
query={'url': f'/mediateka/irasas/{video_id}/{path}'})
|
||||||
|
|
||||||
|
return traverse_obj(media, {
|
||||||
|
'id': ('id', {int}, {str_or_none}),
|
||||||
|
'title': ('title', {str}),
|
||||||
|
'tags': ('tags', ..., 'name', {str}),
|
||||||
|
'categories': ('playlist_item', 'category', {str}, filter, all, filter),
|
||||||
|
'description': ('content', {clean_html}, {str}),
|
||||||
|
'timestamp': ('date', {lambda x: x.replace('.', '/')}, {unified_timestamp}),
|
||||||
|
'thumbnail': ('playlist_item', 'image', {urljoin('https://www.lrt.lt')}),
|
||||||
|
'formats': ('playlist_item', 'file', {lambda x: self._extract_m3u8_formats(x, video_id)}),
|
||||||
|
})
|
||||||
|
@@ -27,6 +27,7 @@ from ..utils import (
|
|||||||
traverse_obj,
|
traverse_obj,
|
||||||
try_get,
|
try_get,
|
||||||
unescapeHTML,
|
unescapeHTML,
|
||||||
|
unified_timestamp,
|
||||||
update_url_query,
|
update_url_query,
|
||||||
url_basename,
|
url_basename,
|
||||||
url_or_none,
|
url_or_none,
|
||||||
@@ -985,6 +986,7 @@ class NiconicoLiveIE(InfoExtractor):
|
|||||||
'quality': 'abr',
|
'quality': 'abr',
|
||||||
'protocol': 'hls+fmp4',
|
'protocol': 'hls+fmp4',
|
||||||
'latency': latency,
|
'latency': latency,
|
||||||
|
'accessRightMethod': 'single_cookie',
|
||||||
'chasePlay': False,
|
'chasePlay': False,
|
||||||
},
|
},
|
||||||
'room': {
|
'room': {
|
||||||
@@ -1005,6 +1007,7 @@ class NiconicoLiveIE(InfoExtractor):
|
|||||||
if data.get('type') == 'stream':
|
if data.get('type') == 'stream':
|
||||||
m3u8_url = data['data']['uri']
|
m3u8_url = data['data']['uri']
|
||||||
qualities = data['data']['availableQualities']
|
qualities = data['data']['availableQualities']
|
||||||
|
cookies = data['data']['cookies']
|
||||||
break
|
break
|
||||||
elif data.get('type') == 'disconnect':
|
elif data.get('type') == 'disconnect':
|
||||||
self.write_debug(recv)
|
self.write_debug(recv)
|
||||||
@@ -1043,6 +1046,11 @@ class NiconicoLiveIE(InfoExtractor):
|
|||||||
**res,
|
**res,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for cookie in cookies:
|
||||||
|
self._set_cookie(
|
||||||
|
cookie['domain'], cookie['name'], cookie['value'],
|
||||||
|
expire_time=unified_timestamp(cookie['expires']), path=cookie['path'], secure=cookie['secure'])
|
||||||
|
|
||||||
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4', live=True)
|
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4', live=True)
|
||||||
for fmt, q in zip(formats, reversed(qualities[1:])):
|
for fmt, q in zip(formats, reversed(qualities[1:])):
|
||||||
fmt.update({
|
fmt.update({
|
||||||
|
@@ -2044,7 +2044,7 @@ def url_or_none(url):
|
|||||||
if not url or not isinstance(url, str):
|
if not url or not isinstance(url, str):
|
||||||
return None
|
return None
|
||||||
url = url.strip()
|
url = url.strip()
|
||||||
return url if re.match(r'(?:(?:https?|rt(?:m(?:pt?[es]?|fp)|sp[su]?)|mms|ftps?):)?//', url) else None
|
return url if re.match(r'(?:(?:https?|rt(?:m(?:pt?[es]?|fp)|sp[su]?)|mms|ftps?|wss?):)?//', url) else None
|
||||||
|
|
||||||
|
|
||||||
def strftime_or_none(timestamp, date_format='%Y%m%d', default=None):
|
def strftime_or_none(timestamp, date_format='%Y%m%d', default=None):
|
||||||
|
Reference in New Issue
Block a user