mirror of
https://github.com/MetaCubeX/metacubexd.git
synced 2024-11-13 06:05:34 +08:00
fix: latency test for selector and ipv6 test (#860)
This commit is contained in:
parent
e84b348a6e
commit
5da350d08e
@ -1,14 +1,16 @@
|
|||||||
import { useProxies } from '~/signals'
|
import { useProxies } from '~/signals'
|
||||||
|
import { proxyIPv6SupportMap } from '~/signals/ipv6'
|
||||||
|
|
||||||
export const IPv6Support = (props: { name?: string }) => {
|
export const IPv6Support = (props: { name?: string; class?: string }) => {
|
||||||
const { proxyIPv6SupportMap } = useProxies()
|
const { getNowProxyNodeName } = useProxies()
|
||||||
const support = createMemo(() => proxyIPv6SupportMap()[props.name!] === true)
|
|
||||||
|
const support = createMemo(() => {
|
||||||
|
return proxyIPv6SupportMap()[getNowProxyNodeName(props.name || '')]
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show when={support()}>
|
<Show when={support()}>
|
||||||
<span class="badge badge-sm p-px">
|
<span class={`scale-75 ${props.class}`}>IPv6</span>
|
||||||
<span class="scale-75">IPv6</span>
|
|
||||||
</span>
|
|
||||||
</Show>
|
</Show>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@ import { latencyQualityMap, useProxies } from '~/signals'
|
|||||||
|
|
||||||
export const Latency = (props: { name?: string; class?: string }) => {
|
export const Latency = (props: { name?: string; class?: string }) => {
|
||||||
const [t] = useI18n()
|
const [t] = useI18n()
|
||||||
const { latencyMap } = useProxies()
|
const { getNowProxyNodeName, latencyMap } = useProxies()
|
||||||
const [textClassName, setTextClassName] = createSignal('')
|
const [textClassName, setTextClassName] = createSignal('')
|
||||||
const latency = createMemo(() => latencyMap()[props.name!])
|
const latency = createMemo(() => {
|
||||||
|
return latencyMap()[getNowProxyNodeName(props.name || '')]
|
||||||
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
setTextClassName('text-success')
|
setTextClassName('text-success')
|
||||||
|
@ -9,8 +9,10 @@ export type WsMsg = {
|
|||||||
downloadTotal: number
|
downloadTotal: number
|
||||||
} | null
|
} | null
|
||||||
|
|
||||||
|
// DIRECT is from clash
|
||||||
|
// direct and dns-out is from the example of sing-box official site
|
||||||
export const [quickFilterRegex, setQuickFilterRegex] = makePersisted(
|
export const [quickFilterRegex, setQuickFilterRegex] = makePersisted(
|
||||||
createSignal<string>('Direct|direct|dns-out'),
|
createSignal<string>('DIRECT|direct|dns-out'),
|
||||||
{
|
{
|
||||||
name: 'quickFilterRegex',
|
name: 'quickFilterRegex',
|
||||||
storage: localStorage,
|
storage: localStorage,
|
||||||
|
66
src/signals/ipv6.ts
Normal file
66
src/signals/ipv6.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { proxyGroupLatencyTestAPI, proxyLatencyTestAPI } from '~/apis'
|
||||||
|
import {
|
||||||
|
latencyQualityMap,
|
||||||
|
latencyTestTimeoutDuration,
|
||||||
|
urlForIPv6SupportTest,
|
||||||
|
} from './config'
|
||||||
|
|
||||||
|
export const [proxyIPv6SupportMap, setProxyIPv6SupportMap] = createSignal<
|
||||||
|
Record<string, boolean>
|
||||||
|
>({})
|
||||||
|
|
||||||
|
export const proxyIPv6SupportTest = async (
|
||||||
|
proxyName: string,
|
||||||
|
provider: string,
|
||||||
|
) => {
|
||||||
|
const urlForTest = urlForIPv6SupportTest()
|
||||||
|
|
||||||
|
if (!urlForTest || urlForTest.length === 0) {
|
||||||
|
setProxyIPv6SupportMap({})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let support = false
|
||||||
|
try {
|
||||||
|
const { delay } = await proxyLatencyTestAPI(
|
||||||
|
proxyName,
|
||||||
|
provider,
|
||||||
|
urlForTest,
|
||||||
|
latencyTestTimeoutDuration(),
|
||||||
|
)
|
||||||
|
support = delay > latencyQualityMap().NOT_CONNECTED
|
||||||
|
} catch {
|
||||||
|
support = false
|
||||||
|
}
|
||||||
|
setProxyIPv6SupportMap((supportMap) => ({
|
||||||
|
...supportMap,
|
||||||
|
[proxyName]: support,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const proxyGroupIPv6SupportTest = async (proxyGroupName: string) => {
|
||||||
|
const urlForTest = urlForIPv6SupportTest()
|
||||||
|
|
||||||
|
if (!urlForTest || urlForTest.length === 0) {
|
||||||
|
setProxyIPv6SupportMap({})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const newLatencyMap = await proxyGroupLatencyTestAPI(
|
||||||
|
proxyGroupName,
|
||||||
|
urlForTest,
|
||||||
|
latencyTestTimeoutDuration(),
|
||||||
|
)
|
||||||
|
const newSupportMap = Object.fromEntries(
|
||||||
|
Object.entries(newLatencyMap).map(([k, v]) => [
|
||||||
|
k,
|
||||||
|
v > latencyQualityMap().NOT_CONNECTED,
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
setProxyIPv6SupportMap((supportMap) => ({
|
||||||
|
...supportMap,
|
||||||
|
...newSupportMap,
|
||||||
|
}))
|
||||||
|
}
|
@ -19,6 +19,12 @@ import {
|
|||||||
urlForLatencyTest,
|
urlForLatencyTest,
|
||||||
} from '~/signals'
|
} from '~/signals'
|
||||||
import type { Proxy, ProxyNode, ProxyProvider } from '~/types'
|
import type { Proxy, ProxyNode, ProxyProvider } from '~/types'
|
||||||
|
import {
|
||||||
|
proxyGroupIPv6SupportTest,
|
||||||
|
proxyIPv6SupportMap,
|
||||||
|
proxyIPv6SupportTest,
|
||||||
|
setProxyIPv6SupportMap,
|
||||||
|
} from './ipv6'
|
||||||
|
|
||||||
type ProxyInfo = {
|
type ProxyInfo = {
|
||||||
name: string
|
name: string
|
||||||
@ -58,13 +64,32 @@ const [proxyProviders, setProxyProviders] = createSignal<
|
|||||||
>([])
|
>([])
|
||||||
|
|
||||||
const [latencyMap, setLatencyMap] = createSignal<Record<string, number>>({})
|
const [latencyMap, setLatencyMap] = createSignal<Record<string, number>>({})
|
||||||
const [proxyIPv6SupportMap, setProxyIPv6SupportMap] = createSignal<
|
|
||||||
Record<string, boolean>
|
|
||||||
>({})
|
|
||||||
const [proxyNodeMap, setProxyNodeMap] = createSignal<Record<string, ProxyInfo>>(
|
const [proxyNodeMap, setProxyNodeMap] = createSignal<Record<string, ProxyInfo>>(
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const getLatencyFromProxy = (
|
||||||
|
proxy: Pick<Proxy, 'extra' | 'history'>,
|
||||||
|
url: string,
|
||||||
|
fallbackDefault = true,
|
||||||
|
) => {
|
||||||
|
const extra = proxy.extra?.[url] as Proxy['history'] | undefined
|
||||||
|
|
||||||
|
if (Array.isArray(extra)) {
|
||||||
|
const delay = extra.at(-1)?.delay
|
||||||
|
|
||||||
|
if (delay) {
|
||||||
|
return delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fallbackDefault) {
|
||||||
|
return latencyQualityMap().NOT_CONNECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxy.history?.at(-1)?.delay ?? latencyQualityMap().NOT_CONNECTED
|
||||||
|
}
|
||||||
|
|
||||||
const setProxiesInfo = (
|
const setProxiesInfo = (
|
||||||
proxies: (ProxyWithProvider | ProxyNodeWithProvider)[],
|
proxies: (ProxyWithProvider | ProxyNodeWithProvider)[],
|
||||||
) => {
|
) => {
|
||||||
@ -72,68 +97,21 @@ const setProxiesInfo = (
|
|||||||
const newLatencyMap = { ...latencyMap() }
|
const newLatencyMap = { ...latencyMap() }
|
||||||
const newProxyIPv6SupportMap = { ...proxyIPv6SupportMap() }
|
const newProxyIPv6SupportMap = { ...proxyIPv6SupportMap() }
|
||||||
|
|
||||||
const lastDelay = (
|
|
||||||
proxy: Pick<Proxy, 'extra' | 'history'>,
|
|
||||||
url: string,
|
|
||||||
fallbackDefault = true,
|
|
||||||
) => {
|
|
||||||
const extra = proxy.extra?.[url] as Proxy['history'] | undefined
|
|
||||||
|
|
||||||
if (Array.isArray(extra)) {
|
|
||||||
const delay = extra.at(-1)?.delay
|
|
||||||
|
|
||||||
if (delay) {
|
|
||||||
return delay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fallbackDefault) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxy.history?.at(-1)?.delay
|
|
||||||
}
|
|
||||||
|
|
||||||
const dependedLatencyProxies = {} as Record<string, Set<string>>
|
|
||||||
|
|
||||||
proxies.forEach((proxy) => {
|
proxies.forEach((proxy) => {
|
||||||
const { udp, xudp, type, now, name, provider = '' } = proxy
|
const { udp, xudp, type, now, name, provider = '' } = proxy
|
||||||
|
|
||||||
newProxyNodeMap[proxy.name] = { udp, xudp, type, now, name, provider }
|
newProxyNodeMap[proxy.name] = { udp, xudp, type, now, name, provider }
|
||||||
|
newLatencyMap[proxy.name] = getLatencyFromProxy(proxy, urlForLatencyTest())
|
||||||
|
|
||||||
// to solve the problem of the ProxyGroup cannot obtain the latency of the currently used proxy node
|
// we don't set it when false because sing-box didn't have "extra" so it will always be false
|
||||||
// it seems that only clash.core and clash.premium have issues
|
if (
|
||||||
if (!now) {
|
getLatencyFromProxy(proxy, urlForIPv6SupportTest(), false) >
|
||||||
newLatencyMap[proxy.name] =
|
latencyQualityMap().NOT_CONNECTED
|
||||||
lastDelay(proxy, urlForLatencyTest()) ||
|
) {
|
||||||
latencyQualityMap().NOT_CONNECTED
|
newProxyIPv6SupportMap[proxy.name] = true
|
||||||
} else if (newLatencyMap[now] !== undefined) {
|
|
||||||
newLatencyMap[proxy.name] = newLatencyMap[now]
|
|
||||||
} else {
|
|
||||||
const dependencies = dependedLatencyProxies[now] ?? new Set()
|
|
||||||
dependencies.add(proxy.name)
|
|
||||||
dependedLatencyProxies[now] = dependencies
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyIPv6Support =
|
|
||||||
(lastDelay(proxy, urlForIPv6SupportTest(), false) ?? 0) > 0
|
|
||||||
newProxyIPv6SupportMap[proxy.name] = proxyIPv6Support
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const independencies = Object.keys(dependedLatencyProxies).filter(
|
|
||||||
(now) => newLatencyMap[now] !== undefined,
|
|
||||||
)
|
|
||||||
|
|
||||||
// maybe we should use Union-Find to implement this
|
|
||||||
while (independencies.length > 0) {
|
|
||||||
const now = independencies.shift()!
|
|
||||||
const delay = newLatencyMap[now]!
|
|
||||||
|
|
||||||
for (const name of dependedLatencyProxies[now]?.values() ?? []) {
|
|
||||||
newLatencyMap[name] = delay
|
|
||||||
independencies.push(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
batch(() => {
|
batch(() => {
|
||||||
setProxyNodeMap(newProxyNodeMap)
|
setProxyNodeMap(newProxyNodeMap)
|
||||||
setLatencyMap(newLatencyMap)
|
setLatencyMap(newLatencyMap)
|
||||||
@ -206,58 +184,9 @@ export const useProxies = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyIPv6SupportTest = async (proxyName: string, provider: string) => {
|
|
||||||
const urlForTest = urlForIPv6SupportTest()
|
|
||||||
|
|
||||||
if (!urlForTest || urlForTest.length === 0) {
|
|
||||||
setProxyIPv6SupportMap({})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let support = false
|
|
||||||
try {
|
|
||||||
const { delay } = await proxyLatencyTestAPI(
|
|
||||||
proxyName,
|
|
||||||
provider,
|
|
||||||
urlForTest,
|
|
||||||
latencyTestTimeoutDuration(),
|
|
||||||
)
|
|
||||||
support = delay > 0
|
|
||||||
} catch {
|
|
||||||
support = false
|
|
||||||
}
|
|
||||||
setProxyIPv6SupportMap((supportMap) => ({
|
|
||||||
...supportMap,
|
|
||||||
[proxyName]: support,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
const proxyGroupIPv6SupportTest = async (proxyGroupName: string) => {
|
|
||||||
const urlForTest = urlForIPv6SupportTest()
|
|
||||||
|
|
||||||
if (!urlForTest || urlForTest.length === 0) {
|
|
||||||
setProxyIPv6SupportMap({})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const newLatencyMap = await proxyGroupLatencyTestAPI(
|
|
||||||
proxyGroupName,
|
|
||||||
urlForTest,
|
|
||||||
latencyTestTimeoutDuration(),
|
|
||||||
)
|
|
||||||
const newSupportMap = Object.fromEntries(
|
|
||||||
Object.entries(newLatencyMap).map(([k, v]) => [k, v > 0]),
|
|
||||||
)
|
|
||||||
setProxyIPv6SupportMap((supportMap) => ({
|
|
||||||
...supportMap,
|
|
||||||
...newSupportMap,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
const proxyLatencyTest = async (proxyName: string, provider: string) => {
|
const proxyLatencyTest = async (proxyName: string, provider: string) => {
|
||||||
await proxyIPv6SupportTest(proxyName, provider)
|
|
||||||
setProxyLatencyTestingMap(proxyName, async () => {
|
setProxyLatencyTestingMap(proxyName, async () => {
|
||||||
|
await proxyIPv6SupportTest(proxyName, provider)
|
||||||
const { delay } = await proxyLatencyTestAPI(
|
const { delay } = await proxyLatencyTestAPI(
|
||||||
proxyName,
|
proxyName,
|
||||||
provider,
|
provider,
|
||||||
@ -273,19 +202,13 @@ export const useProxies = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const proxyGroupLatencyTest = async (proxyGroupName: string) => {
|
const proxyGroupLatencyTest = async (proxyGroupName: string) => {
|
||||||
await proxyGroupIPv6SupportTest(proxyGroupName)
|
|
||||||
setProxyGroupLatencyTestingMap(proxyGroupName, async () => {
|
setProxyGroupLatencyTestingMap(proxyGroupName, async () => {
|
||||||
const newLatencyMap = await proxyGroupLatencyTestAPI(
|
await proxyGroupIPv6SupportTest(proxyGroupName)
|
||||||
|
await proxyGroupLatencyTestAPI(
|
||||||
proxyGroupName,
|
proxyGroupName,
|
||||||
urlForLatencyTest(),
|
urlForLatencyTest(),
|
||||||
latencyTestTimeoutDuration(),
|
latencyTestTimeoutDuration(),
|
||||||
)
|
)
|
||||||
|
|
||||||
setLatencyMap((latencyMap) => ({
|
|
||||||
...latencyMap,
|
|
||||||
...newLatencyMap,
|
|
||||||
}))
|
|
||||||
|
|
||||||
await fetchProxies()
|
await fetchProxies()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -320,8 +243,21 @@ export const useProxies = () => {
|
|||||||
await fetchProxies()
|
await fetchProxies()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const getNowProxyNodeName = (name: string) => {
|
||||||
|
let node = proxyNodeMap()[name]
|
||||||
|
|
||||||
|
if (!name || !node) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node.now && node.now !== node.name) {
|
||||||
|
node = proxyNodeMap()[node.now]
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.name
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
proxyIPv6SupportMap,
|
|
||||||
proxyLatencyTestingMap,
|
proxyLatencyTestingMap,
|
||||||
proxyGroupLatencyTestingMap,
|
proxyGroupLatencyTestingMap,
|
||||||
proxyProviderLatencyTestingMap,
|
proxyProviderLatencyTestingMap,
|
||||||
@ -339,5 +275,6 @@ export const useProxies = () => {
|
|||||||
updateProviderByProviderName,
|
updateProviderByProviderName,
|
||||||
updateAllProvider,
|
updateAllProvider,
|
||||||
proxyProviderLatencyTest,
|
proxyProviderLatencyTest,
|
||||||
|
getNowProxyNodeName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user