mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
Update On Tue Mar 17 20:16:43 CET 2026
This commit is contained in:
@@ -1301,3 +1301,4 @@ Update On Fri Mar 13 19:57:31 CET 2026
|
||||
Update On Sat Mar 14 19:52:58 CET 2026
|
||||
Update On Sun Mar 15 19:54:13 CET 2026
|
||||
Update On Mon Mar 16 20:17:53 CET 2026
|
||||
Update On Tue Mar 17 20:16:34 CET 2026
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ jobs:
|
||||
workspaces: 'backend'
|
||||
save-if: ${{ github.event_name == 'push' }}
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
@@ -155,7 +155,7 @@ jobs:
|
||||
workspaces: 'backend'
|
||||
save-if: ${{ github.event_name == 'push' }}
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
@@ -247,7 +247,7 @@ jobs:
|
||||
workspaces: 'backend'
|
||||
save-if: ${{ github.event_name == 'push' }}
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ jobs:
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ jobs:
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ jobs:
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ jobs:
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v5
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
@@ -194,6 +194,15 @@
|
||||
"connections_empty_message": "No connections found",
|
||||
"connections_close_connection": "Close Connection",
|
||||
"connections_view_details": "Details",
|
||||
"providers_proxies_title": "Proxy Groups",
|
||||
"providers_rules_title": "Rule Sets",
|
||||
"providers_no_proxies_message": "Current profile does not have any proxy groups",
|
||||
"providers_no_rules_message": "Current profile does not have any rule sets",
|
||||
"providers_proxies_proxy_count_label": "{count} Proxies",
|
||||
"providers_rules_rule_count_label": "{count} Rules",
|
||||
"providers_info_title": "Resource Info",
|
||||
"providers_subscription_title": "Subscription Info",
|
||||
"providers_update_provider": "Update",
|
||||
"editor_before_close_message": "You have not saved the edited content, are you sure you want to close the editor?",
|
||||
"editor_validate_error_message": "Please fix the error before saving content",
|
||||
"editor_read_only_chip": "Read Only",
|
||||
|
||||
@@ -194,6 +194,15 @@
|
||||
"connections_empty_message": "Не найдено ни одного соединения",
|
||||
"connections_close_connection": "Закрыть соединение",
|
||||
"connections_view_details": "Просмотреть детали",
|
||||
"providers_proxies_title": "Группы прокси",
|
||||
"providers_rules_title": "Наборы правил",
|
||||
"providers_no_proxies_message": "Текущий профиль не имеет групп прокси",
|
||||
"providers_no_rules_message": "Текущий профиль не имеет наборов правил",
|
||||
"providers_proxies_proxy_count_label": "{count} прокси",
|
||||
"providers_rules_rule_count_label": "{count} правил",
|
||||
"providers_info_title": "Информация о ресурсах",
|
||||
"providers_subscription_title": "Информация о подписке",
|
||||
"providers_update_provider": "Обновить ресурсы",
|
||||
"editor_before_close_message": "Вы не сохранили измененное содержимое, вы уверены, что хотите закрыть редактор?",
|
||||
"editor_validate_error_message": "Пожалуйста, исправьте ошибки перед сохранением содержимого",
|
||||
"editor_read_only_chip": "Только для чтения",
|
||||
|
||||
@@ -194,6 +194,15 @@
|
||||
"connections_empty_message": "没有找到任何连接",
|
||||
"connections_close_connection": "关闭连接",
|
||||
"connections_view_details": "查看详情",
|
||||
"providers_proxies_title": "代理集",
|
||||
"providers_rules_title": "规则集",
|
||||
"providers_no_proxies_message": "当前配置没有任何代理集",
|
||||
"providers_no_rules_message": "当前配置没有任何规则集",
|
||||
"providers_proxies_proxy_count_label": "{count}个节点",
|
||||
"providers_rules_rule_count_label": "{count}个规则",
|
||||
"providers_info_title": "资源信息",
|
||||
"providers_subscription_title": "订阅信息",
|
||||
"providers_update_provider": "更新资源",
|
||||
"editor_before_close_message": "你尚未保存编辑的内容,确定要关闭编辑器吗?",
|
||||
"editor_validate_error_message": "请修复错误后再保存内容",
|
||||
"editor_read_only_chip": "只读",
|
||||
|
||||
@@ -194,6 +194,15 @@
|
||||
"connections_empty_message": "沒有找到任何連接",
|
||||
"connections_close_connection": "關閉連接",
|
||||
"connections_view_details": "查看詳情",
|
||||
"providers_proxies_title": "代理集",
|
||||
"providers_rules_title": "規則集",
|
||||
"providers_no_proxies_message": "當前配置沒有任何代理集",
|
||||
"providers_no_rules_message": "當前配置沒有任何規則集",
|
||||
"providers_proxies_proxy_count_label": "{count}個節點",
|
||||
"providers_rules_rule_count_label": "{count}個規則",
|
||||
"providers_info_title": "資源信息",
|
||||
"providers_subscription_title": "訂閱信息",
|
||||
"providers_update_provider": "更新資源",
|
||||
"editor_before_close_message": "你尚未儲存編輯的內容,確定要關閉編輯器嗎?",
|
||||
"editor_validate_error_message": "請修正錯誤後再儲存內容",
|
||||
"editor_read_only_chip": "只讀",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"country-code-emoji": "2.3.0",
|
||||
"country-emoji": "1.5.6",
|
||||
"dayjs": "1.11.20",
|
||||
"framer-motion": "12.36.0",
|
||||
"framer-motion": "12.38.0",
|
||||
"i18next": "25.8.18",
|
||||
"jotai": "2.18.1",
|
||||
"json-schema": "0.4.0",
|
||||
@@ -69,12 +69,12 @@
|
||||
"@csstools/normalize.css": "12.1.1",
|
||||
"@emotion/babel-plugin": "11.13.5",
|
||||
"@emotion/react": "11.14.0",
|
||||
"@iconify/json": "2.2.450",
|
||||
"@iconify/json": "2.2.451",
|
||||
"@monaco-editor/react": "4.7.0",
|
||||
"@tanstack/react-query": "5.90.21",
|
||||
"@tanstack/react-router": "1.167.3",
|
||||
"@tanstack/react-router": "1.167.4",
|
||||
"@tanstack/react-router-devtools": "1.166.9",
|
||||
"@tanstack/router-plugin": "1.166.12",
|
||||
"@tanstack/router-plugin": "1.166.13",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.3.2",
|
||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||
"@tauri-apps/plugin-fs": "2.4.5",
|
||||
@@ -91,7 +91,7 @@
|
||||
"@vitejs/plugin-react-swc": "4.3.0",
|
||||
"change-case": "5.4.4",
|
||||
"clsx": "2.1.1",
|
||||
"core-js": "3.48.0",
|
||||
"core-js": "3.49.0",
|
||||
"filesize": "11.0.13",
|
||||
"meta-json-schema": "1.19.21",
|
||||
"monaco-yaml": "5.4.1",
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import ArrowBackIosNewRounded from '~icons/material-symbols/arrow-back-ios-new-rounded'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { ComponentProps, useId } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useScrollArea } from '@/components/ui/scroll-area'
|
||||
import { cn } from '@nyanpasu/ui'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
|
||||
const BackButton = () => {
|
||||
return (
|
||||
<Button
|
||||
icon
|
||||
variant="raised"
|
||||
className="flex items-center justify-center"
|
||||
asChild
|
||||
>
|
||||
<Link to="/main/providers">
|
||||
<ArrowBackIosNewRounded className="size-4" />
|
||||
</Link>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
const Title = (props: ComponentProps<typeof motion.div>) => {
|
||||
return (
|
||||
<motion.div
|
||||
layout
|
||||
transition={{
|
||||
layout: {
|
||||
duration: 0.5,
|
||||
ease: [0.32, 0.72, 0, 1],
|
||||
},
|
||||
opacity: {
|
||||
duration: 0.16,
|
||||
},
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function ProvidersTitle({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: ComponentProps<'div'>) {
|
||||
const { offset } = useScrollArea()
|
||||
|
||||
const id = useId()
|
||||
|
||||
const showTopTitle = offset.top > 40
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
'group sticky top-0 z-10',
|
||||
'bg-mixed-background',
|
||||
'flex items-center gap-4',
|
||||
'h-16 px-4',
|
||||
className,
|
||||
)}
|
||||
data-show-title={showTopTitle}
|
||||
data-slot="providers-title"
|
||||
{...props}
|
||||
>
|
||||
<BackButton />
|
||||
|
||||
<AnimatePresence initial={false}>
|
||||
{showTopTitle && (
|
||||
<Title
|
||||
key="providers-title-top"
|
||||
layoutId={id}
|
||||
className="text-xl font-bold"
|
||||
>
|
||||
{children}
|
||||
</Title>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="group flex h-24 px-6 pt-10 pb-4"
|
||||
data-slot="providers-title"
|
||||
data-show-title={!showTopTitle}
|
||||
>
|
||||
<AnimatePresence initial={false}>
|
||||
{!showTopTitle && (
|
||||
<Title
|
||||
key="providers-title-main"
|
||||
layoutId={id}
|
||||
className="text-3xl font-bold"
|
||||
>
|
||||
{children}
|
||||
</Title>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { useBlockTask } from '@/components/providers/block-task-provider'
|
||||
import { formatError } from '@/utils'
|
||||
import { message } from '@/utils/notification'
|
||||
import { ClashProxiesProviderQueryItem } from '@nyanpasu/interface'
|
||||
|
||||
export const useProxiesProviderUpdate = (
|
||||
data: ClashProxiesProviderQueryItem,
|
||||
) => {
|
||||
const blockTask = useBlockTask(
|
||||
`update-proxies-provider-${data.name}`,
|
||||
async () => {
|
||||
try {
|
||||
await data.mutate()
|
||||
} catch (error) {
|
||||
console.error('Failed to update proxies provider', error)
|
||||
message(`Update provider failed: \n ${formatError(error)}`, {
|
||||
title: 'Error',
|
||||
kind: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return blockTask
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { useMemo } from 'react'
|
||||
import { ClashProviderProxies } from '@nyanpasu/interface'
|
||||
|
||||
export const useProxiesSubscription = (data: ClashProviderProxies) => {
|
||||
return useMemo(() => {
|
||||
let progress = 0
|
||||
let total = 0
|
||||
let used = 0
|
||||
|
||||
const hasSubscriptionInfo =
|
||||
'subscriptionInfo' in data && data.subscriptionInfo !== undefined
|
||||
|
||||
if (hasSubscriptionInfo) {
|
||||
const subscriptionInfo = data.subscriptionInfo as Record<
|
||||
string,
|
||||
number | undefined
|
||||
>
|
||||
|
||||
const download =
|
||||
subscriptionInfo.download ?? subscriptionInfo.Download ?? 0
|
||||
const upload = subscriptionInfo.upload ?? subscriptionInfo.Upload ?? 0
|
||||
const t = subscriptionInfo.total ?? subscriptionInfo.Total ?? 0
|
||||
|
||||
total = t
|
||||
|
||||
used = download + upload
|
||||
|
||||
progress = (used / (total || 1)) * 100
|
||||
}
|
||||
|
||||
return {
|
||||
progress,
|
||||
total,
|
||||
used,
|
||||
hasSubscriptionInfo,
|
||||
}
|
||||
}, [data])
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { useBlockTask } from '@/components/providers/block-task-provider'
|
||||
import { formatError } from '@/utils'
|
||||
import { message } from '@/utils/notification'
|
||||
import { ClashRulesProviderQueryItem } from '@nyanpasu/interface'
|
||||
|
||||
export const useRulesProviderUpdate = (data: ClashRulesProviderQueryItem) => {
|
||||
const blockTask = useBlockTask(
|
||||
`update-rules-provider-${data.name}`,
|
||||
async () => {
|
||||
try {
|
||||
await data.mutate()
|
||||
} catch (error) {
|
||||
console.error('Failed to update rules provider', error)
|
||||
message(`Update provider failed: \n ${formatError(error)}`, {
|
||||
title: 'Error',
|
||||
kind: 'error',
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return blockTask
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
import AllInboxRounded from '~icons/material-symbols/all-inbox-outline-rounded'
|
||||
import RefreshRounded from '~icons/material-symbols/refresh-rounded'
|
||||
import dayjs from 'dayjs'
|
||||
import { filesize } from 'filesize'
|
||||
import { ComponentProps, PropsWithChildren } from 'react'
|
||||
import { useBlockTask } from '@/components/providers/block-task-provider'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { LinearProgress } from '@/components/ui/progress'
|
||||
import TextMarquee from '@/components/ui/text-marquee'
|
||||
import { useLockFn } from '@/hooks/use-lock-fn'
|
||||
import { m } from '@/paraglide/messages'
|
||||
import { formatError } from '@/utils'
|
||||
import { message } from '@/utils/notification'
|
||||
import {
|
||||
ClashProxiesProviderQueryItem,
|
||||
ClashRulesProviderQueryItem,
|
||||
useClashProxiesProvider,
|
||||
useClashRulesProvider,
|
||||
} from '@nyanpasu/interface'
|
||||
import { cn } from '@nyanpasu/ui'
|
||||
import { createFileRoute, Link } from '@tanstack/react-router'
|
||||
import { useProxiesProviderUpdate } from './_modules/use-proxies-provider-update'
|
||||
import { useProxiesSubscription } from './_modules/use-proxies-subscription'
|
||||
import { useRulesProviderUpdate } from './_modules/use-rules-provider-update'
|
||||
|
||||
export const Route = createFileRoute('/(main)/main/providers/')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
const NavigateButton = ({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Button>) => {
|
||||
return (
|
||||
<Button
|
||||
variant="fab"
|
||||
className={cn(
|
||||
'flex h-auto w-full flex-col justify-center gap-1 p-3 text-left',
|
||||
'bg-on-background/3!',
|
||||
'dark:bg-surface!',
|
||||
'shadow-none',
|
||||
'hover:shadow-none',
|
||||
'hover:bg-surface-variant/30',
|
||||
className,
|
||||
)}
|
||||
asChild
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const Group = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-1" data-slot="providers-group">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const GroupTitle = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'sticky top-0 z-10 pl-1 text-lg font-semibold',
|
||||
'text-secondary bg-mixed-background flex h-16 items-center justify-between',
|
||||
)}
|
||||
data-slot="providers-group-title"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const GroupContent = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<div
|
||||
className="grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4"
|
||||
data-slot="providers-group-content"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Empty = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<Card variant="outline">
|
||||
<CardContent className="min-h-40 items-center justify-center text-sm">
|
||||
<AllInboxRounded className="size-10" />
|
||||
|
||||
{children}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const Proxies = ({ data }: { data: ClashProxiesProviderQueryItem }) => {
|
||||
const { progress, total, used, hasSubscriptionInfo } =
|
||||
useProxiesSubscription(data)
|
||||
|
||||
const blockTask = useProxiesProviderUpdate(data)
|
||||
|
||||
const handleClick = useLockFn(blockTask.execute)
|
||||
|
||||
return (
|
||||
<NavigateButton className="flex flex-col gap-2">
|
||||
<Link
|
||||
to="/main/providers/proxies/$key"
|
||||
params={{
|
||||
key: data.name,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<TextMarquee className="text-sm font-medium">{data.name}</TextMarquee>
|
||||
|
||||
<div className="text-xs text-nowrap text-zinc-700 dark:text-zinc-300">
|
||||
{dayjs(data.updatedAt).fromNow()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-zinc-500">
|
||||
{data.vehicleType}/{data.type}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 flex-col gap-2 text-xs text-zinc-500">
|
||||
{hasSubscriptionInfo && (
|
||||
<>
|
||||
<LinearProgress value={progress} />
|
||||
|
||||
<TextMarquee>
|
||||
<div className="flex items-center justify-between gap-2 text-xs font-bold">
|
||||
<div>{progress.toFixed(2)}%</div>
|
||||
|
||||
<div>
|
||||
{filesize(used)} / {filesize(total)}
|
||||
</div>
|
||||
</div>
|
||||
</TextMarquee>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="bg-surface-variant text-secondary rounded-full px-2 py-1 text-[10px]">
|
||||
{m.providers_proxies_proxy_count_label({
|
||||
count: data.proxies.length,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="size-6"
|
||||
icon
|
||||
loading={blockTask.isPending}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
handleClick()
|
||||
}}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</Button>
|
||||
</div>
|
||||
</Link>
|
||||
</NavigateButton>
|
||||
)
|
||||
}
|
||||
|
||||
const Rules = ({ data }: { data: ClashRulesProviderQueryItem }) => {
|
||||
const blockTask = useRulesProviderUpdate(data)
|
||||
|
||||
const handleClick = useLockFn(blockTask.execute)
|
||||
|
||||
return (
|
||||
<NavigateButton className="flex flex-col gap-2">
|
||||
<Link
|
||||
to="/main/providers/rules/$key"
|
||||
params={{
|
||||
key: data.name,
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<TextMarquee className="text-sm font-medium">{data.name}</TextMarquee>
|
||||
|
||||
<div className="text-xs text-nowrap text-zinc-700 dark:text-zinc-300">
|
||||
{dayjs(data.updatedAt).fromNow()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-zinc-500">
|
||||
{data.vehicleType}/{data.type}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="bg-surface-variant text-secondary rounded-full px-2 py-1 text-[10px]">
|
||||
{m.providers_rules_rule_count_label({
|
||||
count: data.ruleCount,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="size-6"
|
||||
icon
|
||||
loading={blockTask.isPending}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
handleClick()
|
||||
}}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</Button>
|
||||
</div>
|
||||
</Link>
|
||||
</NavigateButton>
|
||||
)
|
||||
}
|
||||
|
||||
function RouteComponent() {
|
||||
const proxiesProvider = useClashProxiesProvider()
|
||||
|
||||
const proxies = proxiesProvider.data
|
||||
? Object.entries(proxiesProvider.data)
|
||||
: null
|
||||
|
||||
const proxiesBlockTask = useBlockTask('update-proxies-provider', async () => {
|
||||
if (!proxies) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all(proxies.map(([_, data]) => data.mutate()))
|
||||
} catch (error) {
|
||||
console.error('Failed to update proxies provider', error)
|
||||
message(`Update provider failed: \n ${formatError(error)}`, {
|
||||
title: 'Error',
|
||||
kind: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const handleUpdateProxies = useLockFn(proxiesBlockTask.execute)
|
||||
|
||||
const rulesProvider = useClashRulesProvider()
|
||||
|
||||
const rules = rulesProvider.data ? Object.entries(rulesProvider.data) : null
|
||||
|
||||
const rulesBlockTask = useBlockTask('update-rules-provider', async () => {
|
||||
if (!rules) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all(rules.map(([_, data]) => data.mutate()))
|
||||
} catch (error) {
|
||||
console.error('Failed to update rules provider', error)
|
||||
message(`Update provider failed: \n ${formatError(error)}`, {
|
||||
title: 'Error',
|
||||
kind: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const handleUpdateRules = useLockFn(rulesBlockTask.execute)
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 p-4 pt-0">
|
||||
<Group>
|
||||
<GroupTitle>
|
||||
<span>{m.providers_proxies_title()}</span>
|
||||
|
||||
<Button
|
||||
icon
|
||||
onClick={handleUpdateProxies}
|
||||
loading={proxiesBlockTask.isPending}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</Button>
|
||||
</GroupTitle>
|
||||
|
||||
{proxies && proxies.length ? (
|
||||
<GroupContent>
|
||||
{proxies.map(([key, data]) => (
|
||||
<Proxies key={key} data={data} />
|
||||
))}
|
||||
</GroupContent>
|
||||
) : (
|
||||
<Empty>
|
||||
<p>{m.providers_no_proxies_message()}</p>
|
||||
</Empty>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
<GroupTitle>
|
||||
<span>{m.providers_rules_title()}</span>
|
||||
|
||||
<Button
|
||||
icon
|
||||
onClick={handleUpdateRules}
|
||||
loading={rulesBlockTask.isPending}
|
||||
>
|
||||
<RefreshRounded />
|
||||
</Button>
|
||||
</GroupTitle>
|
||||
|
||||
{rules && rules.length ? (
|
||||
<GroupContent>
|
||||
{rules.map(([key, data]) => (
|
||||
<Rules key={key} data={data} />
|
||||
))}
|
||||
</GroupContent>
|
||||
) : (
|
||||
<Empty>
|
||||
<p>{m.providers_no_rules_message()}</p>
|
||||
</Empty>
|
||||
)}
|
||||
</Group>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { useClashProxiesProvider } from '@nyanpasu/interface'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { ProvidersTitle } from '../_modules/providers-title'
|
||||
import { InfoCard } from './_modules/info-card'
|
||||
import { SubscriptionCard } from './_modules/subscription-card'
|
||||
|
||||
export const Route = createFileRoute('/(main)/main/providers/proxies/$key')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
const { key } = Route.useParams()
|
||||
|
||||
const proxiesProvider = useClashProxiesProvider()
|
||||
|
||||
const currentProxy = proxiesProvider.data?.[key]
|
||||
|
||||
if (!currentProxy) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProvidersTitle>{key}</ProvidersTitle>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 p-4 md:grid-cols-4">
|
||||
<SubscriptionCard data={currentProxy} />
|
||||
|
||||
<InfoCard data={currentProxy} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import RefreshRounded from '~icons/material-symbols/refresh-rounded'
|
||||
import dayjs from 'dayjs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
|
||||
import { useLockFn } from '@/hooks/use-lock-fn'
|
||||
import { m } from '@/paraglide/messages'
|
||||
import { ClashProxiesProviderQueryItem } from '@nyanpasu/interface'
|
||||
import { useProxiesProviderUpdate } from '../../_modules/use-proxies-provider-update'
|
||||
|
||||
export const InfoCard = ({ data }: { data: ClashProxiesProviderQueryItem }) => {
|
||||
const blockTask = useProxiesProviderUpdate(data)
|
||||
|
||||
const handleRefreshClick = useLockFn(async () => {
|
||||
await blockTask.execute()
|
||||
})
|
||||
|
||||
return (
|
||||
<Card className="col-span-2 flex flex-col justify-between">
|
||||
<CardHeader>{m.providers_info_title()}</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<div className="flex items-center justify-between px-1">
|
||||
<div className="text-secondary text-sm">
|
||||
{m.providers_proxies_proxy_count_label({
|
||||
count: data.proxies.length,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-zinc-500">
|
||||
{data.vehicleType}/{data.type}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
<CardFooter>
|
||||
<Button
|
||||
className="flex items-center gap-2"
|
||||
onClick={handleRefreshClick}
|
||||
loading={blockTask.isPending}
|
||||
>
|
||||
<RefreshRounded />
|
||||
<span>{m.providers_update_provider()}</span>
|
||||
</Button>
|
||||
|
||||
<div className="flex-1" />
|
||||
|
||||
<div className="hover:bg-surface-variant text-secondary rounded-full px-3 py-2 text-xs font-semibold">
|
||||
{m.profile_subscription_updated_at({
|
||||
updated: dayjs(data.updatedAt).fromNow(),
|
||||
})}
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { filesize } from 'filesize'
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card'
|
||||
import { LinearProgress } from '@/components/ui/progress'
|
||||
import { m } from '@/paraglide/messages'
|
||||
import { ClashProxiesProviderQueryItem } from '@nyanpasu/interface'
|
||||
import { useProxiesSubscription } from '../../_modules/use-proxies-subscription'
|
||||
|
||||
export const SubscriptionCard = ({
|
||||
data,
|
||||
}: {
|
||||
data: ClashProxiesProviderQueryItem
|
||||
}) => {
|
||||
const { progress, total, used, hasSubscriptionInfo } =
|
||||
useProxiesSubscription(data)
|
||||
|
||||
if (!hasSubscriptionInfo) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="col-span-2 flex flex-col justify-between">
|
||||
<CardHeader>{m.providers_subscription_title()}</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<LinearProgress value={progress} />
|
||||
|
||||
<div className="flex items-center justify-between pb-2">
|
||||
<div className="text-sm font-bold">{progress.toFixed(2)}%</div>
|
||||
|
||||
<div className="text-sm font-bold">
|
||||
{filesize(used)} / {filesize(total)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,166 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { motion } from 'framer-motion'
|
||||
import { ComponentProps } from 'react'
|
||||
import { AnimatedOutletPreset } from '@/components/router/animated-outlet'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { AppContentScrollArea } from '@/components/ui/scroll-area'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Sidebar, SidebarContent } from '@/components/ui/sidebar'
|
||||
import TextMarquee from '@/components/ui/text-marquee'
|
||||
import useIsMobile from '@/hooks/use-is-moblie'
|
||||
import {
|
||||
useClashProxiesProvider,
|
||||
useClashRulesProvider,
|
||||
} from '@nyanpasu/interface'
|
||||
import { cn } from '@nyanpasu/ui'
|
||||
import { createFileRoute, Link, useLocation } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/(main)/main/providers')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
return <div>Hello "/(main)/main/providers"!</div>
|
||||
const NavigateButton = ({
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<typeof Button>) => {
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
'h-16 w-full rounded-2xl',
|
||||
'flex flex-col items-start justify-center gap-2',
|
||||
'data-[active=true]:bg-surface-variant/80',
|
||||
'data-[active=false]:bg-transparent',
|
||||
'data-[active=false]:shadow-none',
|
||||
'data-[active=false]:hover:shadow-none',
|
||||
'data-[active=false]:hover:bg-surface-variant/30',
|
||||
className,
|
||||
)}
|
||||
asChild
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const SidebarNavigate = () => {
|
||||
const proxiesProvider = useClashProxiesProvider()
|
||||
|
||||
const proxies = proxiesProvider.data
|
||||
? Object.entries(proxiesProvider.data)
|
||||
: null
|
||||
|
||||
const rulesProvider = useClashRulesProvider()
|
||||
|
||||
const rules = rulesProvider.data ? Object.entries(rulesProvider.data) : null
|
||||
|
||||
const { pathname } = useLocation()
|
||||
|
||||
return (
|
||||
<>
|
||||
{proxies && proxies.length ? (
|
||||
<>
|
||||
<div className="flex flex-col gap-2 p-2">
|
||||
{proxies.map(([key, data]) => (
|
||||
<NavigateButton
|
||||
key={key}
|
||||
data-active={String(pathname.endsWith(`/proxies/${key}`))}
|
||||
>
|
||||
<Link
|
||||
to="/main/providers/proxies/$key"
|
||||
params={{
|
||||
key,
|
||||
}}
|
||||
>
|
||||
<div className="text-sm font-medium">{data.name}</div>
|
||||
|
||||
<TextMarquee className="text-xs text-zinc-500">
|
||||
{data.type}
|
||||
</TextMarquee>
|
||||
</Link>
|
||||
</NavigateButton>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{rules && rules.length ? (
|
||||
<div className="flex flex-col gap-2 p-2">
|
||||
{rules.map(([key, data]) => (
|
||||
<NavigateButton
|
||||
key={key}
|
||||
data-active={String(pathname.endsWith(`/rules/${key}`))}
|
||||
>
|
||||
<Link
|
||||
to="/main/providers/rules/$key"
|
||||
params={{
|
||||
key,
|
||||
}}
|
||||
>
|
||||
<div className="text-sm font-medium">{data.name}</div>
|
||||
|
||||
<TextMarquee className="text-xs text-zinc-500">
|
||||
{data.type}
|
||||
</TextMarquee>
|
||||
</Link>
|
||||
</NavigateButton>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function RouteComponent() {
|
||||
const { pathname } = useLocation()
|
||||
|
||||
const isCurrent = pathname === Route.fullPath
|
||||
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
return (
|
||||
<Sidebar data-slot="providers-container">
|
||||
{!isCurrent && !isMobile && (
|
||||
<motion.div
|
||||
animate={{
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
}}
|
||||
initial={{
|
||||
opacity: 0,
|
||||
x: -24,
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.28,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
>
|
||||
<SidebarContent
|
||||
className="bg-surface-variant/10 [&>div>div]:block!"
|
||||
data-slot="providers-sidebar-scroll-area"
|
||||
>
|
||||
<SidebarNavigate />
|
||||
</SidebarContent>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<AppContentScrollArea
|
||||
className={cn(
|
||||
'group/providers-content flex-[3_1_auto]',
|
||||
'overflow-clip',
|
||||
)}
|
||||
data-slot="providers-content-scroll-area"
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'container mx-auto w-full max-w-7xl',
|
||||
'min-h-[calc(100vh-40px-64px)]',
|
||||
'sm:min-h-[calc(100vh-40px-48px)]',
|
||||
)}
|
||||
data-slot="providers-content"
|
||||
>
|
||||
<AnimatedOutletPreset />
|
||||
</div>
|
||||
</AppContentScrollArea>
|
||||
</Sidebar>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useClashRulesProvider } from '@nyanpasu/interface'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { ProvidersTitle } from '../_modules/providers-title'
|
||||
import { InfoCard } from './_modules/info-card'
|
||||
|
||||
export const Route = createFileRoute('/(main)/main/providers/rules/$key')({
|
||||
component: RouteComponent,
|
||||
})
|
||||
|
||||
function RouteComponent() {
|
||||
const { key } = Route.useParams()
|
||||
|
||||
const rulesProvider = useClashRulesProvider()
|
||||
|
||||
const currentRule = rulesProvider.data?.[key]
|
||||
|
||||
if (!currentRule) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProvidersTitle>{key}</ProvidersTitle>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 p-4 md:grid-cols-4">
|
||||
<InfoCard data={currentRule} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import RefreshRounded from '~icons/material-symbols/refresh-rounded'
|
||||
import dayjs from 'dayjs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
|
||||
import { useLockFn } from '@/hooks/use-lock-fn'
|
||||
import { m } from '@/paraglide/messages'
|
||||
import { ClashRulesProviderQueryItem } from '@nyanpasu/interface'
|
||||
import { useRulesProviderUpdate } from '../../_modules/use-rules-provider-update'
|
||||
|
||||
export const InfoCard = ({ data }: { data: ClashRulesProviderQueryItem }) => {
|
||||
const blockTask = useRulesProviderUpdate(data)
|
||||
|
||||
const handleRefreshClick = useLockFn(async () => {
|
||||
await blockTask.execute()
|
||||
})
|
||||
|
||||
return (
|
||||
<Card className="col-span-2 flex flex-col justify-between">
|
||||
<CardHeader>{m.providers_info_title()}</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<div className="flex items-center justify-between px-1">
|
||||
<div className="text-secondary text-sm">
|
||||
{m.providers_rules_rule_count_label({
|
||||
count: data.ruleCount,
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-zinc-500">
|
||||
{data.vehicleType}/{data.type}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
<CardFooter>
|
||||
<Button
|
||||
className="flex items-center gap-2"
|
||||
onClick={handleRefreshClick}
|
||||
loading={blockTask.isPending}
|
||||
>
|
||||
<RefreshRounded />
|
||||
<span>{m.providers_update_provider()}</span>
|
||||
</Button>
|
||||
|
||||
<div className="flex-1" />
|
||||
|
||||
<div className="hover:bg-surface-variant text-secondary rounded-full px-3 py-2 text-xs font-semibold">
|
||||
{m.profile_subscription_updated_at({
|
||||
updated: dayjs(data.updatedAt).fromNow(),
|
||||
})}
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -34,8 +34,10 @@ import { Route as mainMainConnectionsRouteRouteImport } from './pages/(main)/mai
|
||||
import { Route as mainMainSettingsIndexRouteImport } from './pages/(main)/main/settings/index'
|
||||
import { Route as mainMainRulesIndexRouteImport } from './pages/(main)/main/rules/index'
|
||||
import { Route as mainMainProxiesIndexRouteImport } from './pages/(main)/main/proxies/index'
|
||||
import { Route as mainMainProvidersIndexRouteImport } from './pages/(main)/main/providers/index'
|
||||
import { Route as mainMainProfilesIndexRouteImport } from './pages/(main)/main/profiles/index'
|
||||
import { Route as mainMainLogsIndexRouteImport } from './pages/(main)/main/logs/index'
|
||||
import { Route as mainMainConnectionsIndexRouteImport } from './pages/(main)/main/connections/index'
|
||||
import { Route as mainMainSettingsWebUiRouteRouteImport } from './pages/(main)/main/settings/web-ui/route'
|
||||
import { Route as mainMainSettingsUserInterfaceRouteRouteImport } from './pages/(main)/main/settings/user-interface/route'
|
||||
import { Route as mainMainSettingsSystemRouteRouteImport } from './pages/(main)/main/settings/system/route'
|
||||
@@ -47,6 +49,8 @@ import { Route as mainMainProfilesInspectRouteRouteImport } from './pages/(main)
|
||||
import { Route as mainMainSettingsDebugIndexRouteImport } from './pages/(main)/main/settings/debug/index'
|
||||
import { Route as mainMainProfilesTypeIndexRouteImport } from './pages/(main)/main/profiles/$type/index'
|
||||
import { Route as mainMainProxiesGroupNameRouteImport } from './pages/(main)/main/proxies/group/$name'
|
||||
import { Route as mainMainProvidersRulesKeyRouteImport } from './pages/(main)/main/providers/rules/$key'
|
||||
import { Route as mainMainProvidersProxiesKeyRouteImport } from './pages/(main)/main/providers/proxies/$key'
|
||||
import { Route as mainMainProfilesTypeDetailUidRouteImport } from './pages/(main)/main/profiles/$type/detail/$uid'
|
||||
|
||||
const mainRouteRoute = mainRouteRouteImport.update({
|
||||
@@ -173,6 +177,11 @@ const mainMainProxiesIndexRoute = mainMainProxiesIndexRouteImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => mainMainProxiesRouteRoute,
|
||||
} as any)
|
||||
const mainMainProvidersIndexRoute = mainMainProvidersIndexRouteImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => mainMainProvidersRouteRoute,
|
||||
} as any)
|
||||
const mainMainProfilesIndexRoute = mainMainProfilesIndexRouteImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
@@ -183,6 +192,12 @@ const mainMainLogsIndexRoute = mainMainLogsIndexRouteImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => mainMainLogsRouteRoute,
|
||||
} as any)
|
||||
const mainMainConnectionsIndexRoute =
|
||||
mainMainConnectionsIndexRouteImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => mainMainConnectionsRouteRoute,
|
||||
} as any)
|
||||
const mainMainSettingsWebUiRouteRoute =
|
||||
mainMainSettingsWebUiRouteRouteImport.update({
|
||||
id: '/web-ui',
|
||||
@@ -249,6 +264,18 @@ const mainMainProxiesGroupNameRoute =
|
||||
path: '/group/$name',
|
||||
getParentRoute: () => mainMainProxiesRouteRoute,
|
||||
} as any)
|
||||
const mainMainProvidersRulesKeyRoute =
|
||||
mainMainProvidersRulesKeyRouteImport.update({
|
||||
id: '/rules/$key',
|
||||
path: '/rules/$key',
|
||||
getParentRoute: () => mainMainProvidersRouteRoute,
|
||||
} as any)
|
||||
const mainMainProvidersProxiesKeyRoute =
|
||||
mainMainProvidersProxiesKeyRouteImport.update({
|
||||
id: '/proxies/$key',
|
||||
path: '/proxies/$key',
|
||||
getParentRoute: () => mainMainProvidersRouteRoute,
|
||||
} as any)
|
||||
const mainMainProfilesTypeDetailUidRoute =
|
||||
mainMainProfilesTypeDetailUidRouteImport.update({
|
||||
id: '/$type/detail/$uid',
|
||||
@@ -267,11 +294,11 @@ export interface FileRoutesByFullPath {
|
||||
'/rules': typeof legacyRulesRoute
|
||||
'/settings': typeof legacySettingsRoute
|
||||
'/': typeof legacyIndexRoute
|
||||
'/main/connections': typeof mainMainConnectionsRouteRoute
|
||||
'/main/connections': typeof mainMainConnectionsRouteRouteWithChildren
|
||||
'/main/dashboard': typeof mainMainDashboardRouteRoute
|
||||
'/main/logs': typeof mainMainLogsRouteRouteWithChildren
|
||||
'/main/profiles': typeof mainMainProfilesRouteRouteWithChildren
|
||||
'/main/providers': typeof mainMainProvidersRouteRoute
|
||||
'/main/providers': typeof mainMainProvidersRouteRouteWithChildren
|
||||
'/main/proxies': typeof mainMainProxiesRouteRouteWithChildren
|
||||
'/main/rules': typeof mainMainRulesRouteRouteWithChildren
|
||||
'/main/settings': typeof mainMainSettingsRouteRouteWithChildren
|
||||
@@ -285,11 +312,15 @@ export interface FileRoutesByFullPath {
|
||||
'/main/settings/system': typeof mainMainSettingsSystemRouteRoute
|
||||
'/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
|
||||
'/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
|
||||
'/main/connections/': typeof mainMainConnectionsIndexRoute
|
||||
'/main/logs/': typeof mainMainLogsIndexRoute
|
||||
'/main/profiles/': typeof mainMainProfilesIndexRoute
|
||||
'/main/providers/': typeof mainMainProvidersIndexRoute
|
||||
'/main/proxies/': typeof mainMainProxiesIndexRoute
|
||||
'/main/rules/': typeof mainMainRulesIndexRoute
|
||||
'/main/settings/': typeof mainMainSettingsIndexRoute
|
||||
'/main/providers/proxies/$key': typeof mainMainProvidersProxiesKeyRoute
|
||||
'/main/providers/rules/$key': typeof mainMainProvidersRulesKeyRoute
|
||||
'/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
|
||||
'/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute
|
||||
'/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute
|
||||
@@ -305,9 +336,7 @@ export interface FileRoutesByTo {
|
||||
'/rules': typeof legacyRulesRoute
|
||||
'/settings': typeof legacySettingsRoute
|
||||
'/': typeof legacyIndexRoute
|
||||
'/main/connections': typeof mainMainConnectionsRouteRoute
|
||||
'/main/dashboard': typeof mainMainDashboardRouteRoute
|
||||
'/main/providers': typeof mainMainProvidersRouteRoute
|
||||
'/editor': typeof editorEditorIndexRoute
|
||||
'/main': typeof mainMainIndexRoute
|
||||
'/main/profiles/inspect': typeof mainMainProfilesInspectRouteRoute
|
||||
@@ -317,11 +346,15 @@ export interface FileRoutesByTo {
|
||||
'/main/settings/system': typeof mainMainSettingsSystemRouteRoute
|
||||
'/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
|
||||
'/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
|
||||
'/main/connections': typeof mainMainConnectionsIndexRoute
|
||||
'/main/logs': typeof mainMainLogsIndexRoute
|
||||
'/main/profiles': typeof mainMainProfilesIndexRoute
|
||||
'/main/providers': typeof mainMainProvidersIndexRoute
|
||||
'/main/proxies': typeof mainMainProxiesIndexRoute
|
||||
'/main/rules': typeof mainMainRulesIndexRoute
|
||||
'/main/settings': typeof mainMainSettingsIndexRoute
|
||||
'/main/providers/proxies/$key': typeof mainMainProvidersProxiesKeyRoute
|
||||
'/main/providers/rules/$key': typeof mainMainProvidersRulesKeyRoute
|
||||
'/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
|
||||
'/main/profiles/$type': typeof mainMainProfilesTypeIndexRoute
|
||||
'/main/settings/debug': typeof mainMainSettingsDebugIndexRoute
|
||||
@@ -341,11 +374,11 @@ export interface FileRoutesById {
|
||||
'/(legacy)/rules': typeof legacyRulesRoute
|
||||
'/(legacy)/settings': typeof legacySettingsRoute
|
||||
'/(legacy)/': typeof legacyIndexRoute
|
||||
'/(main)/main/connections': typeof mainMainConnectionsRouteRoute
|
||||
'/(main)/main/connections': typeof mainMainConnectionsRouteRouteWithChildren
|
||||
'/(main)/main/dashboard': typeof mainMainDashboardRouteRoute
|
||||
'/(main)/main/logs': typeof mainMainLogsRouteRouteWithChildren
|
||||
'/(main)/main/profiles': typeof mainMainProfilesRouteRouteWithChildren
|
||||
'/(main)/main/providers': typeof mainMainProvidersRouteRoute
|
||||
'/(main)/main/providers': typeof mainMainProvidersRouteRouteWithChildren
|
||||
'/(main)/main/proxies': typeof mainMainProxiesRouteRouteWithChildren
|
||||
'/(main)/main/rules': typeof mainMainRulesRouteRouteWithChildren
|
||||
'/(main)/main/settings': typeof mainMainSettingsRouteRouteWithChildren
|
||||
@@ -359,11 +392,15 @@ export interface FileRoutesById {
|
||||
'/(main)/main/settings/system': typeof mainMainSettingsSystemRouteRoute
|
||||
'/(main)/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
|
||||
'/(main)/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
|
||||
'/(main)/main/connections/': typeof mainMainConnectionsIndexRoute
|
||||
'/(main)/main/logs/': typeof mainMainLogsIndexRoute
|
||||
'/(main)/main/profiles/': typeof mainMainProfilesIndexRoute
|
||||
'/(main)/main/providers/': typeof mainMainProvidersIndexRoute
|
||||
'/(main)/main/proxies/': typeof mainMainProxiesIndexRoute
|
||||
'/(main)/main/rules/': typeof mainMainRulesIndexRoute
|
||||
'/(main)/main/settings/': typeof mainMainSettingsIndexRoute
|
||||
'/(main)/main/providers/proxies/$key': typeof mainMainProvidersProxiesKeyRoute
|
||||
'/(main)/main/providers/rules/$key': typeof mainMainProvidersRulesKeyRoute
|
||||
'/(main)/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
|
||||
'/(main)/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute
|
||||
'/(main)/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute
|
||||
@@ -400,11 +437,15 @@ export interface FileRouteTypes {
|
||||
| '/main/settings/system'
|
||||
| '/main/settings/user-interface'
|
||||
| '/main/settings/web-ui'
|
||||
| '/main/connections/'
|
||||
| '/main/logs/'
|
||||
| '/main/profiles/'
|
||||
| '/main/providers/'
|
||||
| '/main/proxies/'
|
||||
| '/main/rules/'
|
||||
| '/main/settings/'
|
||||
| '/main/providers/proxies/$key'
|
||||
| '/main/providers/rules/$key'
|
||||
| '/main/proxies/group/$name'
|
||||
| '/main/profiles/$type/'
|
||||
| '/main/settings/debug/'
|
||||
@@ -420,9 +461,7 @@ export interface FileRouteTypes {
|
||||
| '/rules'
|
||||
| '/settings'
|
||||
| '/'
|
||||
| '/main/connections'
|
||||
| '/main/dashboard'
|
||||
| '/main/providers'
|
||||
| '/editor'
|
||||
| '/main'
|
||||
| '/main/profiles/inspect'
|
||||
@@ -432,11 +471,15 @@ export interface FileRouteTypes {
|
||||
| '/main/settings/system'
|
||||
| '/main/settings/user-interface'
|
||||
| '/main/settings/web-ui'
|
||||
| '/main/connections'
|
||||
| '/main/logs'
|
||||
| '/main/profiles'
|
||||
| '/main/providers'
|
||||
| '/main/proxies'
|
||||
| '/main/rules'
|
||||
| '/main/settings'
|
||||
| '/main/providers/proxies/$key'
|
||||
| '/main/providers/rules/$key'
|
||||
| '/main/proxies/group/$name'
|
||||
| '/main/profiles/$type'
|
||||
| '/main/settings/debug'
|
||||
@@ -473,11 +516,15 @@ export interface FileRouteTypes {
|
||||
| '/(main)/main/settings/system'
|
||||
| '/(main)/main/settings/user-interface'
|
||||
| '/(main)/main/settings/web-ui'
|
||||
| '/(main)/main/connections/'
|
||||
| '/(main)/main/logs/'
|
||||
| '/(main)/main/profiles/'
|
||||
| '/(main)/main/providers/'
|
||||
| '/(main)/main/proxies/'
|
||||
| '/(main)/main/rules/'
|
||||
| '/(main)/main/settings/'
|
||||
| '/(main)/main/providers/proxies/$key'
|
||||
| '/(main)/main/providers/rules/$key'
|
||||
| '/(main)/main/proxies/group/$name'
|
||||
| '/(main)/main/profiles/$type/'
|
||||
| '/(main)/main/settings/debug/'
|
||||
@@ -667,6 +714,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof mainMainProxiesIndexRouteImport
|
||||
parentRoute: typeof mainMainProxiesRouteRoute
|
||||
}
|
||||
'/(main)/main/providers/': {
|
||||
id: '/(main)/main/providers/'
|
||||
path: '/'
|
||||
fullPath: '/main/providers/'
|
||||
preLoaderRoute: typeof mainMainProvidersIndexRouteImport
|
||||
parentRoute: typeof mainMainProvidersRouteRoute
|
||||
}
|
||||
'/(main)/main/profiles/': {
|
||||
id: '/(main)/main/profiles/'
|
||||
path: '/'
|
||||
@@ -681,6 +735,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof mainMainLogsIndexRouteImport
|
||||
parentRoute: typeof mainMainLogsRouteRoute
|
||||
}
|
||||
'/(main)/main/connections/': {
|
||||
id: '/(main)/main/connections/'
|
||||
path: '/'
|
||||
fullPath: '/main/connections/'
|
||||
preLoaderRoute: typeof mainMainConnectionsIndexRouteImport
|
||||
parentRoute: typeof mainMainConnectionsRouteRoute
|
||||
}
|
||||
'/(main)/main/settings/web-ui': {
|
||||
id: '/(main)/main/settings/web-ui'
|
||||
path: '/web-ui'
|
||||
@@ -758,6 +819,20 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof mainMainProxiesGroupNameRouteImport
|
||||
parentRoute: typeof mainMainProxiesRouteRoute
|
||||
}
|
||||
'/(main)/main/providers/rules/$key': {
|
||||
id: '/(main)/main/providers/rules/$key'
|
||||
path: '/rules/$key'
|
||||
fullPath: '/main/providers/rules/$key'
|
||||
preLoaderRoute: typeof mainMainProvidersRulesKeyRouteImport
|
||||
parentRoute: typeof mainMainProvidersRouteRoute
|
||||
}
|
||||
'/(main)/main/providers/proxies/$key': {
|
||||
id: '/(main)/main/providers/proxies/$key'
|
||||
path: '/proxies/$key'
|
||||
fullPath: '/main/providers/proxies/$key'
|
||||
preLoaderRoute: typeof mainMainProvidersProxiesKeyRouteImport
|
||||
parentRoute: typeof mainMainProvidersRouteRoute
|
||||
}
|
||||
'/(main)/main/profiles/$type/detail/$uid': {
|
||||
id: '/(main)/main/profiles/$type/detail/$uid'
|
||||
path: '/$type/detail/$uid'
|
||||
@@ -796,6 +871,20 @@ const legacyRouteRouteWithChildren = legacyRouteRoute._addFileChildren(
|
||||
legacyRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface mainMainConnectionsRouteRouteChildren {
|
||||
mainMainConnectionsIndexRoute: typeof mainMainConnectionsIndexRoute
|
||||
}
|
||||
|
||||
const mainMainConnectionsRouteRouteChildren: mainMainConnectionsRouteRouteChildren =
|
||||
{
|
||||
mainMainConnectionsIndexRoute: mainMainConnectionsIndexRoute,
|
||||
}
|
||||
|
||||
const mainMainConnectionsRouteRouteWithChildren =
|
||||
mainMainConnectionsRouteRoute._addFileChildren(
|
||||
mainMainConnectionsRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface mainMainLogsRouteRouteChildren {
|
||||
mainMainLogsIndexRoute: typeof mainMainLogsIndexRoute
|
||||
}
|
||||
@@ -826,6 +915,24 @@ const mainMainProfilesRouteRouteWithChildren =
|
||||
mainMainProfilesRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface mainMainProvidersRouteRouteChildren {
|
||||
mainMainProvidersIndexRoute: typeof mainMainProvidersIndexRoute
|
||||
mainMainProvidersProxiesKeyRoute: typeof mainMainProvidersProxiesKeyRoute
|
||||
mainMainProvidersRulesKeyRoute: typeof mainMainProvidersRulesKeyRoute
|
||||
}
|
||||
|
||||
const mainMainProvidersRouteRouteChildren: mainMainProvidersRouteRouteChildren =
|
||||
{
|
||||
mainMainProvidersIndexRoute: mainMainProvidersIndexRoute,
|
||||
mainMainProvidersProxiesKeyRoute: mainMainProvidersProxiesKeyRoute,
|
||||
mainMainProvidersRulesKeyRoute: mainMainProvidersRulesKeyRoute,
|
||||
}
|
||||
|
||||
const mainMainProvidersRouteRouteWithChildren =
|
||||
mainMainProvidersRouteRoute._addFileChildren(
|
||||
mainMainProvidersRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface mainMainProxiesRouteRouteChildren {
|
||||
mainMainProxiesIndexRoute: typeof mainMainProxiesIndexRoute
|
||||
mainMainProxiesGroupNameRoute: typeof mainMainProxiesGroupNameRoute
|
||||
@@ -893,11 +1000,11 @@ const mainMainSettingsRouteRouteWithChildren =
|
||||
)
|
||||
|
||||
interface mainRouteRouteChildren {
|
||||
mainMainConnectionsRouteRoute: typeof mainMainConnectionsRouteRoute
|
||||
mainMainConnectionsRouteRoute: typeof mainMainConnectionsRouteRouteWithChildren
|
||||
mainMainDashboardRouteRoute: typeof mainMainDashboardRouteRoute
|
||||
mainMainLogsRouteRoute: typeof mainMainLogsRouteRouteWithChildren
|
||||
mainMainProfilesRouteRoute: typeof mainMainProfilesRouteRouteWithChildren
|
||||
mainMainProvidersRouteRoute: typeof mainMainProvidersRouteRoute
|
||||
mainMainProvidersRouteRoute: typeof mainMainProvidersRouteRouteWithChildren
|
||||
mainMainProxiesRouteRoute: typeof mainMainProxiesRouteRouteWithChildren
|
||||
mainMainRulesRouteRoute: typeof mainMainRulesRouteRouteWithChildren
|
||||
mainMainSettingsRouteRoute: typeof mainMainSettingsRouteRouteWithChildren
|
||||
@@ -905,11 +1012,11 @@ interface mainRouteRouteChildren {
|
||||
}
|
||||
|
||||
const mainRouteRouteChildren: mainRouteRouteChildren = {
|
||||
mainMainConnectionsRouteRoute: mainMainConnectionsRouteRoute,
|
||||
mainMainConnectionsRouteRoute: mainMainConnectionsRouteRouteWithChildren,
|
||||
mainMainDashboardRouteRoute: mainMainDashboardRouteRoute,
|
||||
mainMainLogsRouteRoute: mainMainLogsRouteRouteWithChildren,
|
||||
mainMainProfilesRouteRoute: mainMainProfilesRouteRouteWithChildren,
|
||||
mainMainProvidersRouteRoute: mainMainProvidersRouteRoute,
|
||||
mainMainProvidersRouteRoute: mainMainProvidersRouteRouteWithChildren,
|
||||
mainMainProxiesRouteRoute: mainMainProxiesRouteRouteWithChildren,
|
||||
mainMainRulesRouteRoute: mainMainRulesRouteRouteWithChildren,
|
||||
mainMainSettingsRouteRoute: mainMainSettingsRouteRouteWithChildren,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"@vitejs/plugin-react": "5.2.0",
|
||||
"ahooks": "3.9.6",
|
||||
"d3": "7.9.0",
|
||||
"framer-motion": "12.36.0",
|
||||
"framer-motion": "12.38.0",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"react-error-boundary": "6.0.0",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"mihomo_alpha": "alpha-dd4eb63",
|
||||
"clash_rs": "v0.9.6",
|
||||
"clash_premium": "2023-09-05-gdcc8d87",
|
||||
"clash_rs_alpha": "0.9.6-alpha+sha.301cd95"
|
||||
"clash_rs_alpha": "0.9.6-alpha+sha.c5a0da5"
|
||||
},
|
||||
"arch_template": {
|
||||
"mihomo": {
|
||||
@@ -69,5 +69,5 @@
|
||||
"linux-armv7hf": "clash-rs-armv7-unknown-linux-gnueabihf"
|
||||
}
|
||||
},
|
||||
"updated_at": "2026-03-15T17:40:58.103Z"
|
||||
"updated_at": "2026-03-16T22:28:20.426Z"
|
||||
}
|
||||
|
||||
Generated
+62
-59
@@ -226,7 +226,7 @@ importers:
|
||||
version: 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-zod-adapter':
|
||||
specifier: 1.81.5
|
||||
version: 1.81.5(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)
|
||||
version: 1.81.5(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)
|
||||
'@tauri-apps/api':
|
||||
specifier: 2.10.1
|
||||
version: 2.10.1
|
||||
@@ -258,8 +258,8 @@ importers:
|
||||
specifier: 1.11.20
|
||||
version: 1.11.20
|
||||
framer-motion:
|
||||
specifier: 12.36.0
|
||||
version: 12.36.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
specifier: 12.38.0
|
||||
version: 12.38.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
i18next:
|
||||
specifier: 25.8.18
|
||||
version: 25.8.18(typescript@5.9.3)
|
||||
@@ -334,8 +334,8 @@ importers:
|
||||
specifier: 11.14.0
|
||||
version: 11.14.0(@types/react@19.2.14)(react@19.2.4)
|
||||
'@iconify/json':
|
||||
specifier: 2.2.450
|
||||
version: 2.2.450
|
||||
specifier: 2.2.451
|
||||
version: 2.2.451
|
||||
'@monaco-editor/react':
|
||||
specifier: 4.7.0
|
||||
version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -343,14 +343,14 @@ importers:
|
||||
specifier: 5.90.21
|
||||
version: 5.90.21(react@19.2.4)
|
||||
'@tanstack/react-router':
|
||||
specifier: 1.167.3
|
||||
version: 1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
specifier: 1.167.4
|
||||
version: 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/react-router-devtools':
|
||||
specifier: 1.166.9
|
||||
version: 1.166.9(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.167.3)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
version: 1.166.9(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.167.4)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-plugin':
|
||||
specifier: 1.166.12
|
||||
version: 1.166.12(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@24.11.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.31.1)(sass-embedded@1.98.0)(sass@1.98.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
specifier: 1.166.13
|
||||
version: 1.166.13(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@24.11.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.31.1)(sass-embedded@1.98.0)(sass@1.98.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
'@tauri-apps/plugin-clipboard-manager':
|
||||
specifier: 2.3.2
|
||||
version: 2.3.2
|
||||
@@ -400,8 +400,8 @@ importers:
|
||||
specifier: 2.1.1
|
||||
version: 2.1.1
|
||||
core-js:
|
||||
specifier: 3.48.0
|
||||
version: 3.48.0
|
||||
specifier: 3.49.0
|
||||
version: 3.49.0
|
||||
filesize:
|
||||
specifier: 11.0.13
|
||||
version: 11.0.13
|
||||
@@ -487,8 +487,8 @@ importers:
|
||||
specifier: 7.9.0
|
||||
version: 7.9.0
|
||||
framer-motion:
|
||||
specifier: 12.36.0
|
||||
version: 12.36.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
specifier: 12.38.0
|
||||
version: 12.38.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
react:
|
||||
specifier: 19.2.4
|
||||
version: 19.2.4
|
||||
@@ -1704,8 +1704,8 @@ packages:
|
||||
prettier-plugin-ember-template-tag:
|
||||
optional: true
|
||||
|
||||
'@iconify/json@2.2.450':
|
||||
resolution: {integrity: sha512-dltwhGrVC1guhfqIiFJ+jH21aO1C9RRvIOsAYdmsqKOr3vfMkKnwji4pYpxPEEEg3YQCvVDFpyKCKbfI8Gl/ow==}
|
||||
'@iconify/json@2.2.451':
|
||||
resolution: {integrity: sha512-dDAPVdlpXdjtqYReacSWtwa3Mix0Cg4ezZ5SORLjLqyPSQttaHn03sjndnqgXfeY1zckOuLUgYUMLiZfIoD2oQ==}
|
||||
|
||||
'@iconify/types@2.0.0':
|
||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||
@@ -3869,8 +3869,8 @@ packages:
|
||||
'@tanstack/router-core':
|
||||
optional: true
|
||||
|
||||
'@tanstack/react-router@1.167.3':
|
||||
resolution: {integrity: sha512-1qbSy4r+O7IBdmPLlcKsjB041Gq2MMnIEAYSGIjaMZIL4duUIQnOWLw4jTfjKil/IJz/9rO5JcvrbxOG5UTSdg==}
|
||||
'@tanstack/react-router@1.167.4':
|
||||
resolution: {integrity: sha512-VpbZh382zX3WF4+X2Z+EUyd8eJhJyjg9C6ByYwrVZiWbhgbMK4+zQQIG2+lCAlIlDi7SV8fDcGL09NA8Z2kpGQ==}
|
||||
engines: {node: '>=20.19'}
|
||||
peerDependencies:
|
||||
react: '>=18.0.0 || >=19.0.0'
|
||||
@@ -3901,9 +3901,10 @@ packages:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
'@tanstack/router-core@1.167.3':
|
||||
resolution: {integrity: sha512-M/CxrTGKk1fsySJjd+Pzpbi3YLDz+cJSutDjSTMy12owWlOgHV/I6kzR0UxyaBlHraM6XgMHNA0XdgsS1fa4Nw==}
|
||||
'@tanstack/router-core@1.167.4':
|
||||
resolution: {integrity: sha512-Gk5V9Zr5JFJ4SbLyCheQLJ3MnXddccENPA+DJRz+9g3QxtN8DJB8w8KCUCgDeYlWp4LvmO4nX3fy3tupqVP2Pw==}
|
||||
engines: {node: '>=20.19'}
|
||||
hasBin: true
|
||||
|
||||
'@tanstack/router-devtools-core@1.166.9':
|
||||
resolution: {integrity: sha512-PNlA7GmOUX9wY7LUG709Pk3Lg33dfHBztQwzjzrOiOsuf4ggp2R6bwarF8nYGNjG79z/MaB5PN+5yvkCVk8jGw==}
|
||||
@@ -3915,16 +3916,17 @@ packages:
|
||||
csstype:
|
||||
optional: true
|
||||
|
||||
'@tanstack/router-generator@1.166.11':
|
||||
resolution: {integrity: sha512-Q/49wxURbft1oNOvo/eVAWZq/lNLK3nBGlavqhLToAYXY6LCzfMtRlE/y3XPHzYC9pZc09u5jvBR1k1E4hyGDQ==}
|
||||
'@tanstack/router-generator@1.166.12':
|
||||
resolution: {integrity: sha512-2HdxSTbCkbU9JeYogKVigIlXoLtIJE1x5rbEov+ZLTPjGCO9kicNQuljqg9Js+u2/ahtWewNrE5u1QCAyxmpIg==}
|
||||
engines: {node: '>=20.19'}
|
||||
|
||||
'@tanstack/router-plugin@1.166.12':
|
||||
resolution: {integrity: sha512-PYsnN6goK6zBaVo63UVKjofv69+HHMKRQXymwN55JYKguNnNR8OZ6E12icPb0Olc5uIpPiGz1YI2+rbpmNKGHA==}
|
||||
'@tanstack/router-plugin@1.166.13':
|
||||
resolution: {integrity: sha512-xG3ND3AlMe6DN9PihJAYUbQJevqJvVdzN1QpZbfU1/jkHurL97ynP2yXfmMTh8Qgi1K+SWRko4bi7iZlYP9SUw==}
|
||||
engines: {node: '>=20.19'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@rsbuild/core': '>=1.0.2'
|
||||
'@tanstack/react-router': ^1.167.3
|
||||
'@tanstack/react-router': ^1.167.4
|
||||
vite: '>=5.0.0 || >=6.0.0 || >=7.0.0'
|
||||
vite-plugin-solid: ^2.11.10
|
||||
webpack: '>=5.92.0'
|
||||
@@ -3964,9 +3966,10 @@ packages:
|
||||
'@tanstack/virtual-core@3.13.9':
|
||||
resolution: {integrity: sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==}
|
||||
|
||||
'@tanstack/virtual-file-routes@1.161.6':
|
||||
resolution: {integrity: sha512-EGWs9yvJA821pUkwkiZLQW89CzUumHyJy8NKq229BubyoWXfDw1oWnTJYSS/hhbLiwP9+KpopjeF5wWwnCCyeQ==}
|
||||
'@tanstack/virtual-file-routes@1.161.7':
|
||||
resolution: {integrity: sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ==}
|
||||
engines: {node: '>=20.19'}
|
||||
hasBin: true
|
||||
|
||||
'@taplo/core@0.2.0':
|
||||
resolution: {integrity: sha512-r8bl54Zj1In3QLkiW/ex694bVzpPJ9EhwqT9xkcUVODnVUGirdB1JTsmiIv0o1uwqZiwhi8xNnTOQBRQCpizrQ==}
|
||||
@@ -4929,8 +4932,8 @@ packages:
|
||||
core-js-compat@3.44.0:
|
||||
resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==}
|
||||
|
||||
core-js@3.48.0:
|
||||
resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==}
|
||||
core-js@3.49.0:
|
||||
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
|
||||
|
||||
core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
@@ -5476,8 +5479,8 @@ packages:
|
||||
fraction.js@5.3.4:
|
||||
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
||||
|
||||
framer-motion@12.36.0:
|
||||
resolution: {integrity: sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==}
|
||||
framer-motion@12.38.0:
|
||||
resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==}
|
||||
peerDependencies:
|
||||
'@emotion/is-prop-valid': '*'
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
@@ -6320,8 +6323,8 @@ packages:
|
||||
peerDependencies:
|
||||
monaco-editor: '>=0.36'
|
||||
|
||||
motion-dom@12.36.0:
|
||||
resolution: {integrity: sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA==}
|
||||
motion-dom@12.38.0:
|
||||
resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==}
|
||||
|
||||
motion-utils@12.36.0:
|
||||
resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==}
|
||||
@@ -9339,7 +9342,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@iconify/json@2.2.450':
|
||||
'@iconify/json@2.2.451':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
pathe: 2.0.3
|
||||
@@ -11364,22 +11367,22 @@ snapshots:
|
||||
'@tanstack/query-core': 5.90.20
|
||||
react: 19.2.4
|
||||
|
||||
'@tanstack/react-router-devtools@1.166.9(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.167.3)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
'@tanstack/react-router-devtools@1.166.9(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.167.4)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
dependencies:
|
||||
'@tanstack/react-router': 1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-devtools-core': 1.166.9(@tanstack/router-core@1.167.3)(csstype@3.2.3)
|
||||
'@tanstack/react-router': 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-devtools-core': 1.166.9(@tanstack/router-core@1.167.4)(csstype@3.2.3)
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
optionalDependencies:
|
||||
'@tanstack/router-core': 1.167.3
|
||||
'@tanstack/router-core': 1.167.4
|
||||
transitivePeerDependencies:
|
||||
- csstype
|
||||
|
||||
'@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
'@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
dependencies:
|
||||
'@tanstack/history': 1.161.6
|
||||
'@tanstack/react-store': 0.9.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-core': 1.167.3
|
||||
'@tanstack/router-core': 1.167.4
|
||||
isbot: 5.1.28
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
@@ -11411,7 +11414,7 @@ snapshots:
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
|
||||
'@tanstack/router-core@1.167.3':
|
||||
'@tanstack/router-core@1.167.4':
|
||||
dependencies:
|
||||
'@tanstack/history': 1.161.6
|
||||
'@tanstack/store': 0.9.1
|
||||
@@ -11421,20 +11424,20 @@ snapshots:
|
||||
tiny-invariant: 1.3.3
|
||||
tiny-warning: 1.0.3
|
||||
|
||||
'@tanstack/router-devtools-core@1.166.9(@tanstack/router-core@1.167.3)(csstype@3.2.3)':
|
||||
'@tanstack/router-devtools-core@1.166.9(@tanstack/router-core@1.167.4)(csstype@3.2.3)':
|
||||
dependencies:
|
||||
'@tanstack/router-core': 1.167.3
|
||||
'@tanstack/router-core': 1.167.4
|
||||
clsx: 2.1.1
|
||||
goober: 2.1.16(csstype@3.2.3)
|
||||
tiny-invariant: 1.3.3
|
||||
optionalDependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@tanstack/router-generator@1.166.11':
|
||||
'@tanstack/router-generator@1.166.12':
|
||||
dependencies:
|
||||
'@tanstack/router-core': 1.167.3
|
||||
'@tanstack/router-core': 1.167.4
|
||||
'@tanstack/router-utils': 1.161.6
|
||||
'@tanstack/virtual-file-routes': 1.161.6
|
||||
'@tanstack/virtual-file-routes': 1.161.7
|
||||
prettier: 3.8.1
|
||||
recast: 0.23.11
|
||||
source-map: 0.7.4
|
||||
@@ -11443,7 +11446,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tanstack/router-plugin@1.166.12(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@24.11.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.31.1)(sass-embedded@1.98.0)(sass@1.98.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
'@tanstack/router-plugin@1.166.13(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@24.11.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.31.1)(sass-embedded@1.98.0)(sass@1.98.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.21.0)(yaml@2.8.2))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.29.0)
|
||||
@@ -11451,15 +11454,15 @@ snapshots:
|
||||
'@babel/template': 7.28.6
|
||||
'@babel/traverse': 7.29.0
|
||||
'@babel/types': 7.29.0
|
||||
'@tanstack/router-core': 1.167.3
|
||||
'@tanstack/router-generator': 1.166.11
|
||||
'@tanstack/router-core': 1.167.4
|
||||
'@tanstack/router-generator': 1.166.12
|
||||
'@tanstack/router-utils': 1.161.6
|
||||
'@tanstack/virtual-file-routes': 1.161.6
|
||||
'@tanstack/virtual-file-routes': 1.161.7
|
||||
chokidar: 3.6.0
|
||||
unplugin: 2.3.11
|
||||
zod: 3.25.76
|
||||
optionalDependencies:
|
||||
'@tanstack/react-router': 1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/react-router': 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
vite: 7.3.1(@types/node@24.11.0)(jiti@2.6.1)(less@4.2.0)(lightningcss@1.31.1)(sass-embedded@1.98.0)(sass@1.98.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -11478,9 +11481,9 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)':
|
||||
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@tanstack/react-router': 1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/react-router': 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
zod: 4.3.6
|
||||
|
||||
'@tanstack/store@0.9.1': {}
|
||||
@@ -11491,7 +11494,7 @@ snapshots:
|
||||
|
||||
'@tanstack/virtual-core@3.13.9': {}
|
||||
|
||||
'@tanstack/virtual-file-routes@1.161.6': {}
|
||||
'@tanstack/virtual-file-routes@1.161.7': {}
|
||||
|
||||
'@taplo/core@0.2.0': {}
|
||||
|
||||
@@ -12053,7 +12056,7 @@ snapshots:
|
||||
babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0)
|
||||
browserslist: 4.25.1
|
||||
browserslist-to-esbuild: 2.1.1(browserslist@4.25.1)
|
||||
core-js: 3.48.0
|
||||
core-js: 3.49.0
|
||||
magic-string: 0.30.17
|
||||
regenerator-runtime: 0.14.1
|
||||
systemjs: 6.15.1
|
||||
@@ -12534,7 +12537,7 @@ snapshots:
|
||||
dependencies:
|
||||
browserslist: 4.28.1
|
||||
|
||||
core-js@3.48.0: {}
|
||||
core-js@3.49.0: {}
|
||||
|
||||
core-util-is@1.0.3: {}
|
||||
|
||||
@@ -13094,9 +13097,9 @@ snapshots:
|
||||
|
||||
fraction.js@5.3.4: {}
|
||||
|
||||
framer-motion@12.36.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
framer-motion@12.38.0(@emotion/is-prop-valid@1.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
dependencies:
|
||||
motion-dom: 12.36.0
|
||||
motion-dom: 12.38.0
|
||||
motion-utils: 12.36.0
|
||||
tslib: 2.8.1
|
||||
optionalDependencies:
|
||||
@@ -14013,7 +14016,7 @@ snapshots:
|
||||
vscode-uri: 3.0.8
|
||||
yaml: 2.8.1
|
||||
|
||||
motion-dom@12.36.0:
|
||||
motion-dom@12.38.0:
|
||||
dependencies:
|
||||
motion-utils: 12.36.0
|
||||
|
||||
|
||||
@@ -90,6 +90,29 @@ func NewClient(conf *config.Config) (c *Client, err error) {
|
||||
Net: "tcp",
|
||||
Timeout: time.Duration(conf.Other.Timeout) * time.Second,
|
||||
}
|
||||
|
||||
if c.conf.Other.Interface != "" {
|
||||
localV4, localV6, err := c.getInterfaceIPs()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get interface IPs for %s: %v", c.conf.Other.Interface, err)
|
||||
}
|
||||
var localAddr net.IP
|
||||
if localV4 != nil {
|
||||
localAddr = localV4
|
||||
} else {
|
||||
localAddr = localV6
|
||||
}
|
||||
|
||||
c.udpClient.Dialer = &net.Dialer{
|
||||
Timeout: time.Duration(conf.Other.Timeout) * time.Second,
|
||||
LocalAddr: &net.UDPAddr{IP: localAddr},
|
||||
}
|
||||
c.tcpClient.Dialer = &net.Dialer{
|
||||
Timeout: time.Duration(conf.Other.Timeout) * time.Second,
|
||||
LocalAddr: &net.TCPAddr{IP: localAddr},
|
||||
}
|
||||
}
|
||||
|
||||
for _, addr := range conf.Listen {
|
||||
c.udpServers = append(c.udpServers, &dns.Server{
|
||||
Addr: addr,
|
||||
@@ -120,6 +143,38 @@ func NewClient(conf *config.Config) (c *Client, err error) {
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
var d net.Dialer
|
||||
if c.conf.Other.Interface != "" {
|
||||
localV4, localV6, err := c.getInterfaceIPs()
|
||||
if err != nil {
|
||||
log.Printf("Bootstrap dial warning: %v", err)
|
||||
} else {
|
||||
numServers := len(c.bootstrap)
|
||||
bootstrap := c.bootstrap[rand.Intn(numServers)]
|
||||
host, _, _ := net.SplitHostPort(bootstrap)
|
||||
ip := net.ParseIP(host)
|
||||
if ip != nil {
|
||||
if ip.To4() != nil {
|
||||
if localV4 != nil {
|
||||
if strings.HasPrefix(network, "udp") {
|
||||
d.LocalAddr = &net.UDPAddr{IP: localV4}
|
||||
} else {
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV4}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if localV6 != nil {
|
||||
if strings.HasPrefix(network, "udp") {
|
||||
d.LocalAddr = &net.UDPAddr{IP: localV6}
|
||||
} else {
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV6}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
conn, err := d.DialContext(ctx, network, bootstrap)
|
||||
return conn, err
|
||||
}
|
||||
}
|
||||
numServers := len(c.bootstrap)
|
||||
bootstrap := c.bootstrap[rand.Intn(numServers)]
|
||||
conn, err := d.DialContext(ctx, network, bootstrap)
|
||||
@@ -235,14 +290,72 @@ func (c *Client) newHTTPClient() error {
|
||||
if c.httpTransport != nil {
|
||||
c.httpTransport.CloseIdleConnections()
|
||||
}
|
||||
dialer := &net.Dialer{
|
||||
|
||||
localV4, localV6, err := c.getInterfaceIPs()
|
||||
if err != nil {
|
||||
log.Printf("Interface binding error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
baseDialer := &net.Dialer{
|
||||
Timeout: time.Duration(c.conf.Other.Timeout) * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
// DualStack: true,
|
||||
Resolver: c.bootstrapResolver,
|
||||
}
|
||||
|
||||
c.httpTransport = &http.Transport{
|
||||
DialContext: dialer.DialContext,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
if c.conf.Other.Interface == "" {
|
||||
return baseDialer.DialContext(ctx, network, addr)
|
||||
}
|
||||
|
||||
if network == "tcp4" && localV4 != nil {
|
||||
d := *baseDialer
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV4}
|
||||
return d.DialContext(ctx, network, addr)
|
||||
}
|
||||
if network == "tcp6" && localV6 != nil {
|
||||
d := *baseDialer
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV6}
|
||||
return d.DialContext(ctx, network, addr)
|
||||
}
|
||||
|
||||
// Manual Dual-Stack: Resolve host and try compatible families sequentially
|
||||
host, port, _ := net.SplitHostPort(addr)
|
||||
ips, err := c.bootstrapResolver.LookupIPAddr(ctx, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for _, ip := range ips {
|
||||
d := *baseDialer
|
||||
targetAddr := net.JoinHostPort(ip.String(), port)
|
||||
|
||||
if ip.IP.To4() != nil {
|
||||
if localV4 == nil {
|
||||
continue
|
||||
}
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV4}
|
||||
} else {
|
||||
if localV6 == nil {
|
||||
continue
|
||||
}
|
||||
d.LocalAddr = &net.TCPAddr{IP: localV6}
|
||||
}
|
||||
|
||||
conn, err := d.DialContext(ctx, "tcp", targetAddr)
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
lastErr = err
|
||||
}
|
||||
|
||||
if lastErr != nil {
|
||||
return nil, lastErr
|
||||
}
|
||||
return nil, fmt.Errorf("connection to %s failed: no matching local/remote IP families on interface %s", addr, c.conf.Other.Interface)
|
||||
},
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
MaxIdleConns: 100,
|
||||
@@ -251,15 +364,18 @@ func (c *Client) newHTTPClient() error {
|
||||
TLSHandshakeTimeout: time.Duration(c.conf.Other.Timeout) * time.Second,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: c.conf.Other.TLSInsecureSkipVerify},
|
||||
}
|
||||
|
||||
if c.conf.Other.NoIPv6 {
|
||||
originalDial := c.httpTransport.DialContext
|
||||
c.httpTransport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if strings.HasPrefix(network, "tcp") {
|
||||
network = "tcp4"
|
||||
}
|
||||
return dialer.DialContext(ctx, network, address)
|
||||
return originalDial(ctx, network, address)
|
||||
}
|
||||
}
|
||||
err := http2.ConfigureTransport(c.httpTransport)
|
||||
|
||||
err = http2.ConfigureTransport(c.httpTransport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -485,3 +601,38 @@ func (c *Client) findClientIP(w dns.ResponseWriter, r *dns.Msg) (ednsClientAddre
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getInterfaceIPs returns the first valid IPv4 and IPv6 addresses found on the interface
|
||||
func (c *Client) getInterfaceIPs() (v4, v6 net.IP, err error) {
|
||||
if c.conf.Other.Interface == "" {
|
||||
return nil, nil, nil
|
||||
}
|
||||
ifi, err := net.InterfaceByName(c.conf.Other.Interface)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
addrs, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
ip, _, err := net.ParseCIDR(addr.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
if v4 == nil {
|
||||
v4 = ip4
|
||||
}
|
||||
} else {
|
||||
if v6 == nil && !c.conf.Other.NoIPv6 {
|
||||
v6 = ip
|
||||
}
|
||||
}
|
||||
}
|
||||
if v4 == nil && v6 == nil {
|
||||
return nil, nil, fmt.Errorf("no valid IP addresses found on interface %s", c.conf.Other.Interface)
|
||||
}
|
||||
return v4, v6, nil
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ type others struct {
|
||||
Bootstrap []string `toml:"bootstrap"`
|
||||
Passthrough []string `toml:"passthrough"`
|
||||
Timeout uint `toml:"timeout"`
|
||||
Interface string `toml:"interface"`
|
||||
NoCookies bool `toml:"no_cookies"`
|
||||
NoECS bool `toml:"no_ecs"`
|
||||
NoIPv6 bool `toml:"no_ipv6"`
|
||||
|
||||
@@ -97,6 +97,11 @@ passthrough = [
|
||||
# Timeout for upstream request in seconds
|
||||
timeout = 30
|
||||
|
||||
# Interface to bind to for outgoing connections.
|
||||
# If empty, the system default route is used (usually eth0 or wlan0).
|
||||
# Example: "eth1", "wlan0"
|
||||
interface = ""
|
||||
|
||||
# Disable HTTP Cookies
|
||||
#
|
||||
# Cookies may be useful if your upstream resolver is protected by some
|
||||
|
||||
@@ -1,4 +1,39 @@
|
||||
# luci-app-argone-config
|
||||
Argon Theme Config Plugin
|
||||
|
||||
You can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.
|
||||
> argon 原作者是jerry;改argone是为了编译方便
|
||||
|
||||
Argon Theme Config Plugin for OpenWrt LuCI
|
||||
|
||||
### Install (18.06 / main)
|
||||
|
||||
```sh
|
||||
wget --no-check-certificate -O luci-app-argone-config_0.9_all.ipk \
|
||||
https://github.com/kenzok78/luci-app-argone-config/releases/download/v0.9/luci-app-argone-config_0.9_all.ipk
|
||||
opkg install luci-app-argone-config_0.9_all.ipk
|
||||
```
|
||||
|
||||
Optional Chinese translation:
|
||||
```sh
|
||||
wget --no-check-certificate -O luci-i18n-argone-config-zh-cn.ipk \
|
||||
https://github.com/kenzok78/luci-app-argone-config/releases/download/v0.9/luci-i18n-argone-config-zh-cn_git-22.114.24542-d1474ba_all.ipk
|
||||
opkg install luci-i18n-argone-config-zh-cn.ipk
|
||||
```
|
||||
|
||||
### Install (23 branch / latest luci)
|
||||
|
||||
```sh
|
||||
wget --no-check-certificate -O luci-app-argone-config_1.0_all.ipk \
|
||||
https://github.com/kenzok78/luci-app-argone-config/releases/download/v1.0/luci-app-argone-config_1.0_all.ipk
|
||||
opkg install luci-app-argone-config_1.0_all.ipk
|
||||
```
|
||||
|
||||
### Source
|
||||
|
||||
- main 分支\uff08luci-18.06\uff09\uff1a
|
||||
```
|
||||
git clone https://github.com/kenzok78/luci-app-argone-config
|
||||
```
|
||||
- 23 分支\uff08最新 luci\uff09\uff1a
|
||||
```
|
||||
git clone -b 23 https://github.com/kenzok78/luci-app-argone-config
|
||||
```
|
||||
|
||||
@@ -1,128 +1,27 @@
|
||||
<!-- markdownlint-configure-file {
|
||||
"MD013": {
|
||||
"code_blocks": false,
|
||||
"tables": false,
|
||||
"line_length":200
|
||||
},
|
||||
"MD033": false,
|
||||
"MD041": false
|
||||
} -->
|
||||
|
||||
[license]: /LICENSE
|
||||
[license-badge]: https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1
|
||||
[prs]: https://github.com/jerrykuku/luci-theme-argone/pulls
|
||||
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
||||
[issues]: https://github.com/jerrykuku/luci-theme-argone/issues/new
|
||||
[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square
|
||||
[release]: https://github.com/jerrykuku/luci-theme-argone/releases
|
||||
[release-badge]: https://img.shields.io/badge/release-v1.8.4-blue.svg?
|
||||
[download]: https://github.com/jerrykuku/luci-theme-argone/releases
|
||||
[download-badge]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argone/total?style=flat-square
|
||||
[contact]: https://t.me/jerryk6
|
||||
[contact-badge]: https://img.shields.io/badge/Contact-telegram-blue?style=flat-square
|
||||
[en-us-link]: /README.md
|
||||
[zh-cn-link]: /README_ZH.md
|
||||
[en-us-release-log]: /RELEASE.md
|
||||
[zh-cn-release-log]: /RELEASE_ZH.md
|
||||
[config-link]: https://github.com/jerrykuku/luci-app-argone-config/releases
|
||||
[lede]: https://github.com/coolsnowwolf/lede
|
||||
[official-luci-18.06]: https://github.com/openwrt/luci/tree/openwrt-18.06
|
||||
[immortalwrt]: https://github.com/immortalwrt/immortalwrt
|
||||
|
||||
<div align="center">
|
||||
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon_title4.svg">
|
||||
|
||||
# A brand new OpenWrt LuCI theme
|
||||
### • This branch only matches [Lean's LEDE ( LuCI 18.06 )][lede] / [OpenWrt LuCI 18.06][official-luci-18.06] •
|
||||
|
||||
Argon is **a clean and tidy OpenWrt LuCI theme** that allows<br/>
|
||||
users to customize their login interface with images or videos.
|
||||
It also supports automatic and manual switching between light and dark modes.
|
||||
|
||||
[![license][license-badge]][license]
|
||||
[![prs][prs-badge]][prs]
|
||||
[![issues][issues-badge]][issues]
|
||||
[![release][release-badge]][release]
|
||||
[![download][download-badge]][download]
|
||||
[![contact][contact-badge]][contact]
|
||||
|
||||
**English** |
|
||||
[简体中文][zh-cn-link]
|
||||
|
||||
[Key Features](#key-features) •
|
||||
[Getting started](#getting-started) •
|
||||
[Screenshots](#screenshots) •
|
||||
[Contributors](#contributors) •
|
||||
[Credits](#credits)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon2.gif">
|
||||
</div>
|
||||
|
||||
## Key Features
|
||||
|
||||
- Clean Layout.
|
||||
- Adapted to mobile display.
|
||||
- Customizable theme colors.
|
||||
- Support for using Bing images as login background.
|
||||
- Support for custom uploading of images or videos as login background.
|
||||
- Automatically switch between light 和 dark modes with the system, 和 can also be set to a fixed mode.
|
||||
- Settings plugin with extensions [luci-app-argone-config][config-link]
|
||||
|
||||
## Notice
|
||||
- Chrome & Edge browser is highly recommended. There are some new css3 features used in this theme, currently only Chrome & Edge has the best compatibility.
|
||||
- FireFox does not enable the backdrop-filter by default, [see here](https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter) for the opening method.
|
||||
- __LEDE has upgraded LuCI to 23.05 since 10/17/2024. The 18.06 branch of this repository is no longer compatible with it. If you still need to compile or install the theme for the 18.06 branch, please modify the [feeds.conf.default](https://github.com/coolsnowwolf/lede/blob/master/feeds.conf.default) file in the LEDE before compiling the firmware. Revert it back to the previous 18.06 LuCI.__
|
||||
|
||||
## Getting started
|
||||
|
||||
### Build for Lean's LEDE ( LuCI 18.06 )
|
||||
#### argon 原作者是jerrykuku
|
||||
#### 改argone是为了编译方便
|
||||
|
||||
+ main 分支支持 luci-18.06
|
||||
```bash
|
||||
cd lede
|
||||
sed -i '/^#src-git luci https:\/\/github.com\/coolsnowwolf\/luci$/s/^#//' feeds.conf.default && sed -i '/^src-git luci https:\/\/github.com\/coolsnowwolf\/luci\.git;openwrt-23\.05$/s/^/#/' feeds.conf.default
|
||||
./scripts/feeds clean
|
||||
./scripts/feeds update -a
|
||||
rm -rf feeds/luci/themes/luci-theme-argone
|
||||
git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git package/downloads/luci-theme-argone
|
||||
./scripts/feeds install -a
|
||||
make menuconfig #choose LuCI->Themes->luci-theme-argone
|
||||
make -j1 V=s
|
||||
git clone https://github.com/kenzok78/luci-theme-argone
|
||||
```
|
||||
+ 23 分支支持最新 luci
|
||||
```bash
|
||||
git clone -b 23 https://github.com/kenzok78/luci-theme-argone
|
||||
```
|
||||
|
||||
### Install for LuCI 18.06 ( Lean's LEDE )
|
||||
### 一键安装 (18.06 / main)
|
||||
|
||||
```bash
|
||||
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argone/releases/download/v1.8.4/luci-theme-argon_1.8.4-20241221_all.ipk
|
||||
opkg install luci-theme-argon*.ipk
|
||||
```sh
|
||||
wget --no-check-certificate -O luci-theme-argone_1.8.4_all.ipk \
|
||||
https://github.com/kenzok78/luci-theme-argone/releases/download/v1.8.4/luci-theme-argone_1.8.4_all.ipk
|
||||
opkg install luci-theme-argone_1.8.4_all.ipk
|
||||
```
|
||||
|
||||
### Install the settings plugin with extensions - luci-app-argone-config
|
||||
### 一键安装 (23 branch / 最新 luci)
|
||||
|
||||
```bash
|
||||
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argone/releases/download/v1.8.3/luci-app-argone-config_0.9-20220424_all.ipk
|
||||
opkg install luci-app-argone-config*.ipk
|
||||
```sh
|
||||
wget --no-check-certificate -O luci-theme-argone_2.4.3_all.ipk \
|
||||
https://github.com/kenzok78/luci-theme-argone/releases/download/v2.4.3/luci-theme-argone_2.4.3_all.ipk
|
||||
opkg install luci-theme-argone_2.4.3_all.ipk
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/jerrykuku/luci-theme-argone/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=jerrykuku/luci-theme-argone" />
|
||||
</a>
|
||||
|
||||
Made with [contrib.rocks](https://contrib.rocks).
|
||||
|
||||
## Related Projects
|
||||
|
||||
- [luci-app-argone-config](https://github.com/jerrykuku/luci-app-argone-config): Argon theme config plugin
|
||||
- [luci-app-vssr](https://github.com/jerrykuku/luci-app-vssr): An OpenWrt internet surfing plugin
|
||||
- [openwrt-package](https://github.com/jerrykuku/openwrt-package): My OpenWrt package
|
||||
- [CasaOS](https://github.com/IceWhaleTech/CasaOS): A simple, easy-to-use, elegant open-source Personal Cloud system (My current main project)
|
||||
|
||||
## Credits
|
||||
|
||||
[luci-theme-material](https://github.com/LuttyYang/luci-theme-material/)
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
<!-- markdownlint-configure-file {
|
||||
"MD013": {
|
||||
"code_blocks": false,
|
||||
"tables": false,
|
||||
"line_length":200
|
||||
},
|
||||
"MD033": false,
|
||||
"MD041": false
|
||||
} -->
|
||||
|
||||
[license]: /LICENSE
|
||||
[license-badge]: https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1
|
||||
[prs]: https://github.com/jerrykuku/luci-theme-argone/pulls
|
||||
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
||||
[issues]: https://github.com/jerrykuku/luci-theme-argone/issues/new
|
||||
[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square
|
||||
[release]: https://github.com/jerrykuku/luci-theme-argone/releases
|
||||
[release-badge]: https://img.shields.io/badge/release-v1.8.4-blue.svg?
|
||||
[download]: https://github.com/jerrykuku/luci-theme-argone/releases
|
||||
[download-badge]: https://img.shields.io/github/downloads/jerrykuku/luci-theme-argone/total?style=flat-square
|
||||
[contact]: https://t.me/jerryk6
|
||||
[contact-badge]: https://img.shields.io/badge/Contact-telegram-blue?style=flat-square
|
||||
[en-us-link]: /README.md
|
||||
[zh-cn-link]: /README_ZH.md
|
||||
[en-us-release-log]: /RELEASE.md
|
||||
[zh-cn-release-log]: /RELEASE_ZH.md
|
||||
[config-link]: https://github.com/jerrykuku/luci-app-argone-config/releases
|
||||
[lede]: https://github.com/coolsnowwolf/lede
|
||||
[official-luci-18.06]: https://github.com/openwrt/luci/tree/openwrt-18.06
|
||||
[immortalwrt]: https://github.com/immortalwrt/immortalwrt
|
||||
|
||||
<div align="center">
|
||||
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon_title4.svg">
|
||||
|
||||
# 一个全新的 OpenWrt 主题
|
||||
### • 该分支只适配 [Lean's LEDE ( LuCI 18.06 )][lede] / [OpenWrt LuCI 18.06][official-luci-18.06] •
|
||||
|
||||
Argon 是**一款干净整洁的 OpenWrt LuCI 主题**,
|
||||
允许用户使用图片或视频自定义其登录界面。
|
||||
它还支持在浅色模式和深色模式之间自动或手动切换。
|
||||
|
||||
[![license][license-badge]][license]
|
||||
[![prs][prs-badge]][prs]
|
||||
[![issues][issues-badge]][issues]
|
||||
[![release][release-badge]][release]
|
||||
[![download][download-badge]][download]
|
||||
[![contact][contact-badge]][contact]
|
||||
|
||||
[English][en-us-link] |
|
||||
**简体中文**
|
||||
|
||||
[特色](#特色) •
|
||||
[快速开始](#快速开始) •
|
||||
[屏幕截图](#屏幕截图) •
|
||||
[贡献者](#贡献者) •
|
||||
[鸣谢](#鸣谢)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon2.gif">
|
||||
</div>
|
||||
|
||||
## 特色
|
||||
|
||||
- 干净整洁的布局。
|
||||
- 适配移动端显示。
|
||||
- 可自定义主题颜色。
|
||||
- 支持使用 Bing 图片作为登录背景。
|
||||
- 支持自定义上传图片或视频作为登录背景。
|
||||
- 通过系统自动在明暗模式之间切换,也可设置为固定模式。
|
||||
- 带有扩展功能的设置插件 [luci-app-argone-config][config-link]
|
||||
|
||||
## 注意
|
||||
|
||||
- 强烈建议使用 Chrome 和 Edge 浏览器。该主题中使用了一些新的 css3 功能,目前只有 Chrome 和 Edge 浏览器有最好的兼容性。
|
||||
- FireFox 默认不启用 backdrop-filter,[见这里](https://developer.mozilla.org/zh-CN/docs/Web/CSS/backdrop-filter)的打开方法。
|
||||
- __LEDE 自 2024-10-17,已将LuCI升级为23.05,本项目18.06分支的主题已不再兼容;如果你还需要继续编译或安装18.06分支的主题,请在编译LEDE固件前修改LEDE源码中的[feeds.conf.default](https://github.com/coolsnowwolf/lede/blob/master/feeds.conf.default),将其更改回以前的18.06 LuCI,详见:[#428 (comment)](https://github.com/jerrykuku/luci-theme-argone/issues/428#issuecomment-2425167489)__
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 使用 Lean's LEDE ( LuCI 18.06 ) 构建
|
||||
|
||||
```bash
|
||||
cd lede
|
||||
sed -i '/^#src-git luci https:\/\/github.com\/coolsnowwolf\/luci$/s/^#//' feeds.conf.default && sed -i '/^src-git luci https:\/\/github.com\/coolsnowwolf\/luci\.git;openwrt-23\.05$/s/^/#/' feeds.conf.default
|
||||
./scripts/feeds clean
|
||||
./scripts/feeds update -a
|
||||
rm -rf feeds/luci/themes/luci-theme-argone
|
||||
git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git package/downloads/luci-theme-argone
|
||||
./scripts/feeds install -a
|
||||
make menuconfig #选择 LuCI->Themes->luci-theme-argone
|
||||
make -j1 V=s
|
||||
```
|
||||
|
||||
### 在 18.06 的 LuCI 上安装 ( Lean's LEDE )
|
||||
|
||||
```bash
|
||||
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argone/releases/download/v1.8.4/luci-theme-argon_1.8.4-20241221_all.ipk
|
||||
opkg install luci-theme-argon*.ipk
|
||||
```
|
||||
|
||||
### 安装扩展功能的设置插件 - luci-app-argone-config
|
||||
|
||||
```bash
|
||||
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argone/releases/download/v1.8.3/luci-app-argone-config_0.9-20220424_all.ipk
|
||||
wget --no-check-certificate https://github.com/jerrykuku/luci-theme-argone/releases/download/v1.8.3/luci-i18n-argon-config-zh-cn_0.9-20220424_all.ipk
|
||||
opkg install luci-app-argone-config*.ipk
|
||||
opkg install luci-i18n-argon-config*.ipk
|
||||
```
|
||||
|
||||
## 屏幕截图
|
||||
|
||||

|
||||

|
||||
|
||||
## 贡献者
|
||||
|
||||
<a href="https://github.com/jerrykuku/luci-theme-argone/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=jerrykuku/luci-theme-argone" />
|
||||
</a>
|
||||
|
||||
Made with [contrib.rocks](https://contrib.rocks).
|
||||
|
||||
## 相关项目
|
||||
|
||||
- [luci-app-argone-config](https://github.com/jerrykuku/luci-app-argone-config): Argon 主题的设置插件
|
||||
- [luci-app-vssr](https://github.com/jerrykuku/luci-app-vssr): 一个 OpenWrt 的互联网冲浪插件
|
||||
- [openwrt-package](https://github.com/jerrykuku/openwrt-package): 我的 OpenWrt Package
|
||||
- [CasaOS](https://github.com/IceWhaleTech/CasaOS): 一个简单、易用且优雅的开源个人家庭云系统(我目前主要开发的项目)
|
||||
|
||||
## 鸣谢
|
||||
|
||||
[luci-theme-material](https://github.com/LuttyYang/luci-theme-material/)
|
||||
@@ -5,7 +5,7 @@
|
||||
Copyright 2020 Jerrykuku <jerrykuku@qq.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/jerrykuku/luci-theme-argone/issues
|
||||
https://github.com/kenzok78/luci-theme-argone/issues
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="ftc">
|
||||
<a class="luci-link" href="https://github.com/openwrt/luci" target="_blank">Powered by <%= ver.luciname %>
|
||||
(<%= ver.luciversion %>)</a> /
|
||||
<a href="https://github.com/jerrykuku/luci-theme-argone" target="_blank">ArgonTheme <%# vPKG_VERSION %></a> /
|
||||
<a href="https://github.com/kenzok78/luci-theme-argone" target="_blank">ArgonTheme <%# vPKG_VERSION %></a> /
|
||||
<%= ver.distversion %>
|
||||
<% if #categories > 1 then %>
|
||||
<ul class="breadcrumb pull-right" id="modemenu">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Copyright 2020 Jerryk <jerrykuku@gmail.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/jerrykuku/luci-theme-argone/issues
|
||||
https://github.com/kenzok78/luci-theme-argone/issues
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Copyright 2020 Jerrykuku <jerrykuku@qq.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/jerrykuku/luci-theme-argone/issues
|
||||
https://github.com/kenzok78/luci-theme-argone/issues
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Copyright 2021 Jerryk <jerrykuku@gmail.com>
|
||||
|
||||
Have a bug? Please create an issue here on GitHub!
|
||||
https://github.com/jerrykuku/luci-theme-argone/issues
|
||||
https://github.com/kenzok78/luci-theme-argone/issues
|
||||
|
||||
luci-theme-bootstrap:
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
# the script will be excuted when `argone.@global[0].bing_background == '1'`
|
||||
# defaults to 'bing' to be compatible with old config
|
||||
WEB_PIC_SRC=$(uci -q get argone.@global[0].online_wallpaper || echo 'bing')
|
||||
CACHE=/var/run/argon_${WEB_PIC_SRC}.url
|
||||
WRLOCK=/var/lock/argon_${WEB_PIC_SRC}.lock
|
||||
CACHE=/var/run/argone_${WEB_PIC_SRC}.url
|
||||
WRLOCK=/var/lock/argone_${WEB_PIC_SRC}.lock
|
||||
|
||||
fetch_pic_url() {
|
||||
case $WEB_PIC_SRC in
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
### 编译
|
||||
|
||||
```
|
||||
git clone https://github.com/gngpp/luci-theme-design.git package/luci-theme-design
|
||||
git clone https://github.com/kenzok78/luci-theme-design.git package/luci-theme-design
|
||||
make menuconfig # choose LUCI->Theme->Luci-theme-design
|
||||
make V=s
|
||||
```
|
||||
|
||||
@@ -17,20 +17,20 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Docker metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository_owner }}/${{ matrix.bin }}-rust
|
||||
- name: Build and release Docker images
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
platforms: linux/386,linux/amd64,linux/arm64/v8
|
||||
target: ${{ matrix.bin }}
|
||||
|
||||
Generated
+44
-32
@@ -111,7 +111,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-parse 0.2.7",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse 1.0.0",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
@@ -134,6 +149,15 @@ dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
@@ -585,20 +609,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.60"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
|
||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.60"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstream 1.0.0",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
@@ -976,7 +1000,7 @@ version = "0.11.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstream 0.6.21",
|
||||
"anstyle",
|
||||
"env_filter",
|
||||
"jiff",
|
||||
@@ -996,7 +1020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1749,9 +1773,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
version = "2.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
|
||||
|
||||
[[package]]
|
||||
name = "iprange"
|
||||
@@ -2194,18 +2218,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.2"
|
||||
@@ -2639,7 +2651,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2916,7 +2928,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2975,7 +2987,7 @@ dependencies = [
|
||||
"security-framework 3.5.1",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3332,7 +3344,7 @@ dependencies = [
|
||||
"lru_time_cache",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"nix 0.31.2",
|
||||
"nix",
|
||||
"pin-project",
|
||||
"rand 0.10.0",
|
||||
"regex",
|
||||
@@ -3621,7 +3633,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3753,9 +3765,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.49.0"
|
||||
version = "1.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -3968,9 +3980,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "tun"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b35f176015650e3bd849e85808d809e5b54da2ba7df983c5c3b601a2a8f1095e"
|
||||
checksum = "87dce40a7bfb165d8eb8e96f7463230f3d91b56aae21e0f1e56db60161962e1a"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
@@ -3979,7 +3991,7 @@ dependencies = [
|
||||
"ipnet",
|
||||
"libc",
|
||||
"log",
|
||||
"nix 0.30.1",
|
||||
"nix",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM rust:1.93.1-alpine3.22 AS builder
|
||||
FROM --platform=$BUILDPLATFORM rust:1.94.0-alpine3.22 AS builder
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/pdnsd/tar.gz/$(PKG_VERSION)?
|
||||
PKG_HASH:=a40243e2eedc9645316e0e5055f71495dc7ec821d1ced393834dbf93cb7fc3a3
|
||||
PKG_HASH:=28929bfd7874fd86872dc1bf4cd01103d7ebbdad6a457ccd9a8947a2819440be
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=redsocks2
|
||||
PKG_VERSION:=0.71
|
||||
PKG_VERSION:=0.73
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=redsocks-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/semigodking/redsocks/tar.gz/release-$(PKG_VERSION)?
|
||||
PKG_HASH:=4ec470f47461ce5accffbefd56ead019ecd19b207ab8599461481c3d7e083bef
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/redsocks/tar.gz/release-$(PKG_VERSION)?
|
||||
PKG_HASH:=0c9a50b6039cd9fe078a3da5fb5317e38fe52ec59fba7fa9abdf3b002471ebfd
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/redsocks-release-$(PKG_VERSION)
|
||||
|
||||
PKG_MAINTAINER:=semigodking <semigodking@gmail.com>
|
||||
@@ -27,7 +27,7 @@ define Package/redsocks2
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=Redirect TCP connection to proxy server
|
||||
URL:=https://github.com/semigodking/redsocks
|
||||
URL:=https://github.com/kenzok8/redsocks
|
||||
DEPENDS:=+libevent2 +libopenssl
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=shadowsocksr-libev
|
||||
PKG_VERSION:=2.5.8
|
||||
PKG_VERSION:=2.5.9
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/shadowsocksr-libev/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=22dc6df12a60425fbae24f39d35c4068c212725608647a331a56d2012cefe970
|
||||
PKG_HASH:=2dd06d4591ac46f1afd26bf9054488193143d31121e31ae914f67535a8e2cd22
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@@ -35,7 +35,7 @@ define Package/shadowsocksr-libev/Default
|
||||
endef
|
||||
endef
|
||||
|
||||
SHADOWSOCKSR_COMPONENTS:=check local nat redir server
|
||||
SHADOWSOCKSR_COMPONENTS:=local nat redir server
|
||||
define shadowsocksr-libev/templates
|
||||
$(foreach component,$(SHADOWSOCKSR_COMPONENTS),
|
||||
$(call Package/shadowsocksr-libev/Default,$(component))
|
||||
@@ -43,14 +43,29 @@ define shadowsocksr-libev/templates
|
||||
endef
|
||||
$(eval $(call shadowsocksr-libev/templates))
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
# Patch configure: use pcre2 instead of pcre1 (OpenWrt 24.10 only provides pcre2)
|
||||
sed -i \
|
||||
-e 's/pcre-config/pcre2-config/g' \
|
||||
-e 's/PCRE_CONFIG --libs/PCRE_CONFIG --libs8/g' \
|
||||
-e 's/pcre_exec/pcre2_match_8/g' \
|
||||
-e '/for ac_lib in/{s/ pcre;/ pcre2-8;/}' \
|
||||
-e 's/pcre\.h/pcre2.h/g' \
|
||||
-e 's/pcre\/pcre\.h/pcre2\/pcre2.h/g' \
|
||||
$(PKG_BUILD_DIR)/configure
|
||||
endef
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--disable-documentation \
|
||||
--disable-ssp \
|
||||
--disable-assert \
|
||||
--enable-system-shared-lib
|
||||
--enable-system-shared-lib \
|
||||
--with-pcre=$(STAGING_DIR)/usr
|
||||
|
||||
TARGET_CFLAGS += -flto
|
||||
TARGET_CFLAGS += -Wno-error=use-after-free
|
||||
TARGET_CPPFLAGS += -DPCRE2_CODE_UNIT_WIDTH=8
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||
|
||||
$(foreach component,$(SHADOWSOCKSR_COMPONENTS), \
|
||||
|
||||
@@ -1,397 +0,0 @@
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -2,6 +2,7 @@ build/
|
||||
.deps/
|
||||
/Makefile
|
||||
src/Makefile
|
||||
+server/Makefile
|
||||
libev/Makefile
|
||||
libudns/Makefile
|
||||
libcork/Makefile
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -1,7 +1,7 @@
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
-SUBDIRS = libcork libipset src
|
||||
+SUBDIRS = libcork libipset src server
|
||||
else
|
||||
-SUBDIRS = libsodium libcork libipset libudns libev src
|
||||
+SUBDIRS = libsodium libcork libipset libudns libev src server
|
||||
endif
|
||||
|
||||
if ENABLE_DOCUMENTATION
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -195,7 +195,7 @@ am__define_uniq_tagged_files = \
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
CSCOPE = cscope
|
||||
-DIST_SUBDIRS = libsodium libcork libipset libudns libev src doc
|
||||
+DIST_SUBDIRS = libsodium libcork libipset libudns libev src server doc
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(srcdir)/shadowsocks-libev.pc.in $(top_srcdir)/auto/ar-lib \
|
||||
$(top_srcdir)/auto/compile $(top_srcdir)/auto/config.guess \
|
||||
@@ -377,8 +377,9 @@ top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@SUBDIRS = libsodium libcork libipset \
|
||||
-@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src $(am__append_1)
|
||||
-@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src \
|
||||
+@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src server \
|
||||
+@USE_SYSTEM_SHARED_LIB_FALSE@ $(am__append_1)
|
||||
+@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src server \
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@ $(am__append_1)
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
pkgconfiglibdir = $(libdir)/pkgconfig
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -649,7 +649,6 @@ PTHREAD_CC
|
||||
ax_pthread_config
|
||||
INET_NTOP_LIB
|
||||
MV
|
||||
-RM
|
||||
GZIP
|
||||
XMLTO
|
||||
ASCIIDOC
|
||||
@@ -757,6 +756,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
+runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -857,6 +857,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
+runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1109,6 +1110,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
+ | --runstate | --runstat | --runsta | --runst | --runs \
|
||||
+ | --run | --ru | --r)
|
||||
+ ac_prev=runstatedir ;;
|
||||
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
+ | --run=* | --ru=* | --r=*)
|
||||
+ runstatedir=$ac_optarg ;;
|
||||
+
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1246,7 +1256,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
- libdir localedir mandir
|
||||
+ libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1399,6 +1409,7 @@ Fine tuning of the installation director
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -2472,8 +2483,8 @@ ac_configure="$SHELL $ac_aux_dir/configu
|
||||
|
||||
|
||||
|
||||
-# expand $ac_aux_dir to an absolute path
|
||||
-am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
+# Expand $ac_aux_dir to an absolute path.
|
||||
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
@@ -3783,7 +3794,7 @@ $as_echo "$ac_cv_safe_to_define___extens
|
||||
|
||||
|
||||
|
||||
-am__api_version='1.14'
|
||||
+am__api_version='1.15'
|
||||
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
@@ -3972,7 +3983,7 @@ else
|
||||
$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
|
||||
fi
|
||||
|
||||
-if test x"${install_sh}" != xset; then
|
||||
+if test x"${install_sh+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
|
||||
@@ -4363,8 +4374,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}ma
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
mkdir_p='$(MKDIR_P)'
|
||||
|
||||
-# We need awk for the "check" target. The system "awk" is bad on
|
||||
-# some platforms.
|
||||
+# We need awk for the "check" target (and possibly the TAP driver). The
|
||||
+# system "awk" is bad on some platforms.
|
||||
# Always define AMTAR for backward compatibility. Yes, it's still used
|
||||
# in the wild :-( We should find a proper way to deprecate it ...
|
||||
AMTAR='$${TAR-tar}'
|
||||
@@ -4549,6 +4560,7 @@ END
|
||||
as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
+
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
for ac_prog in ar lib "link -lib"
|
||||
do
|
||||
@@ -12494,47 +12506,6 @@ $as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
- # Extract the first word of "rm", so it can be a program name with args.
|
||||
-set dummy rm; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if ${ac_cv_path_RM+:} false; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $RM in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_RM="$RM" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
- ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm"
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-RM=$ac_cv_path_RM
|
||||
-if test -n "$RM"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
|
||||
-$as_echo "$RM" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
# Extract the first word of "mv", so it can be a program name with args.
|
||||
set dummy mv; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
@@ -16204,15 +16175,162 @@ $as_echo "#define HAVE_IPv6 1" >>confdef
|
||||
|
||||
|
||||
if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then :
|
||||
- else
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sodium_init in -lsodium" >&5
|
||||
+$as_echo_n "checking for sodium_init in -lsodium... " >&6; }
|
||||
+if ${ac_cv_lib_sodium_sodium_init+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-lsodium $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char sodium_init ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return sodium_init ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_sodium_sodium_init=yes
|
||||
+else
|
||||
+ ac_cv_lib_sodium_sodium_init=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sodium_sodium_init" >&5
|
||||
+$as_echo "$ac_cv_lib_sodium_sodium_init" >&6; }
|
||||
+if test "x$ac_cv_lib_sodium_sodium_init" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBSODIUM 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-lsodium $LIBS"
|
||||
+
|
||||
+else
|
||||
+
|
||||
+ as_fn_error $? "Couldn't find libsodium. Try installing libsodium-dev[el]." "$LINENO" 5
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+else
|
||||
subdirs="$subdirs libsodium"
|
||||
|
||||
fi
|
||||
|
||||
-ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile"
|
||||
+ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile server/Makefile"
|
||||
|
||||
if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then :
|
||||
- else
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dns_dnlen in -ludns" >&5
|
||||
+$as_echo_n "checking for dns_dnlen in -ludns... " >&6; }
|
||||
+if ${ac_cv_lib_udns_dns_dnlen+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-ludns $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char dns_dnlen ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return dns_dnlen ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_udns_dns_dnlen=yes
|
||||
+else
|
||||
+ ac_cv_lib_udns_dns_dnlen=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_udns_dns_dnlen" >&5
|
||||
+$as_echo "$ac_cv_lib_udns_dns_dnlen" >&6; }
|
||||
+if test "x$ac_cv_lib_udns_dns_dnlen" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBUDNS 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-ludns $LIBS"
|
||||
+
|
||||
+else
|
||||
+ as_fn_error $? "Couldn't find libudns. Try installing libudns-dev or udns-devel." "$LINENO" 5
|
||||
+fi
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_loop_destroy in -lev" >&5
|
||||
+$as_echo_n "checking for ev_loop_destroy in -lev... " >&6; }
|
||||
+if ${ac_cv_lib_ev_ev_loop_destroy+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-lev $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char ev_loop_destroy ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return ev_loop_destroy ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_ev_ev_loop_destroy=yes
|
||||
+else
|
||||
+ ac_cv_lib_ev_ev_loop_destroy=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_loop_destroy" >&5
|
||||
+$as_echo "$ac_cv_lib_ev_ev_loop_destroy" >&6; }
|
||||
+if test "x$ac_cv_lib_ev_ev_loop_destroy" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBEV 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-lev $LIBS"
|
||||
+
|
||||
+else
|
||||
+ as_fn_error $? "Couldn't find libev. Try installing libev-dev[el]." "$LINENO" 5
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+else
|
||||
ac_config_files="$ac_config_files libudns/Makefile libev/Makefile"
|
||||
|
||||
fi
|
||||
@@ -17258,6 +17376,7 @@ do
|
||||
"libcork/Makefile") CONFIG_FILES="$CONFIG_FILES libcork/Makefile" ;;
|
||||
"libipset/Makefile") CONFIG_FILES="$CONFIG_FILES libipset/Makefile" ;;
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
+ "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;;
|
||||
"libudns/Makefile") CONFIG_FILES="$CONFIG_FILES libudns/Makefile" ;;
|
||||
"libev/Makefile") CONFIG_FILES="$CONFIG_FILES libev/Makefile" ;;
|
||||
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||
@@ -17958,8 +18077,8 @@ $as_echo X"$file" |
|
||||
fi
|
||||
|
||||
cfgfile="${ofile}T"
|
||||
- trap "$RM -f \"$cfgfile\"; exit 1" 1 2 15
|
||||
- $RM -f "$cfgfile"
|
||||
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
|
||||
+ $RM "$cfgfile"
|
||||
|
||||
cat <<_LT_EOF >> "$cfgfile"
|
||||
#! $SHELL
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -315,7 +315,8 @@ AC_CONFIG_FILES([ shadowsocks-libev.pc
|
||||
Makefile
|
||||
libcork/Makefile
|
||||
libipset/Makefile
|
||||
- src/Makefile])
|
||||
+ src/Makefile
|
||||
+ server/Makefile])
|
||||
AM_COND_IF([USE_SYSTEM_SHARED_LIB],[
|
||||
AC_CHECK_LIB([udns], [dns_dnlen], ,[AC_MSG_ERROR([Couldn't find libudns. Try installing libudns-dev or udns-devel.])])
|
||||
AC_CHECK_LIB([ev], [ev_loop_destroy], ,[AC_MSG_ERROR([Couldn't find libev. Try installing libev-dev@<:@el@:>@.])])
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/src/http.h
|
||||
+++ b/src/http.h
|
||||
@@ -29,6 +29,6 @@
|
||||
#include <stdio.h>
|
||||
#include "protocol.h"
|
||||
|
||||
-const protocol_t *const http_protocol;
|
||||
+extern const protocol_t *const http_protocol;
|
||||
|
||||
#endif
|
||||
--- a/src/tls.h
|
||||
+++ b/src/tls.h
|
||||
@@ -28,6 +28,6 @@
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
-const protocol_t *const tls_protocol;
|
||||
+extern const protocol_t *const tls_protocol;
|
||||
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/src/local.c
|
||||
+++ b/src/local.c
|
||||
@@ -718,7 +718,7 @@ server_recv_cb(EV_P_ ev_io *w, int reven
|
||||
|
||||
ss_free(hostname);
|
||||
} else {
|
||||
- strncpy(host, ip, sizeof(ip));
|
||||
+ strncpy(host, ip, INET6_ADDRSTRLEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
--- a/src/jconf.c
|
||||
+++ b/src/jconf.c
|
||||
@@ -259,6 +259,19 @@ read_jconf(const char *file)
|
||||
conf.server_legacy.obfs = to_string(value);
|
||||
} else if (strcmp(name, "obfs_param") == 0) { // SSR
|
||||
conf.server_legacy.obfs_param = to_string(value);
|
||||
+ } else if (strcmp(name, "mode") == 0) {
|
||||
+ char *mode_str = to_string(value);
|
||||
+
|
||||
+ if (strcmp(mode_str, "tcp_only") == 0)
|
||||
+ conf.mode = TCP_ONLY;
|
||||
+ else if (strcmp(mode_str, "tcp_and_udp") == 0)
|
||||
+ conf.mode = TCP_AND_UDP;
|
||||
+ else if (strcmp(mode_str, "udp_only") == 0)
|
||||
+ conf.mode = UDP_ONLY;
|
||||
+ else
|
||||
+ LOGI("ignore unknown mode: %s, use tcp_only as fallback",
|
||||
+ mode_str);
|
||||
+ ss_free(mode_str);
|
||||
} else {
|
||||
match = 0;
|
||||
}
|
||||
--- a/src/redir.c
|
||||
+++ b/src/redir.c
|
||||
@@ -1252,6 +1252,9 @@ main(int argc, char **argv)
|
||||
if (user == NULL) {
|
||||
user = conf->user;
|
||||
}
|
||||
+ if (mode == TCP_ONLY) {
|
||||
+ mode = conf->mode;
|
||||
+ }
|
||||
if (mtu == 0) {
|
||||
mtu = conf->mtu;
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "includeobfs.h" // I don't want to modify makefile
|
||||
#include "jconf.h"
|
||||
|
||||
@@ -101,18 +109,28 @@ static struct cork_dllist inactive_profi
|
||||
@@ -114,21 +114,23 @@
|
||||
static listen_ctx_t *current_profile;
|
||||
static struct cork_dllist all_connections;
|
||||
|
||||
@@ -65,10 +65,13 @@
|
||||
|
||||
- error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
- if (error) { // Didn't find a proper way to detect IP version.
|
||||
-#if defined(__FreeBSD__)
|
||||
- error = getsockname(fd, (struct sockaddr *)destaddr, &socklen);
|
||||
-#else
|
||||
- error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
-#endif
|
||||
- if (error) {
|
||||
- return -1;
|
||||
- }
|
||||
+ if (tcp_tproxy) {
|
||||
+ error = getsockname(fd, (void *)destaddr, &socklen);
|
||||
+ } else {
|
||||
@@ -78,15 +81,10 @@
|
||||
+ if (error) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (error) {
|
||||
+ return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -164,6 +182,23 @@ create_and_bind(const char *addr, const
|
||||
@@ -164,6 +174,23 @@ create_and_bind(const char *addr, const
|
||||
if (err == 0) {
|
||||
LOGI("tcp port reuse enabled");
|
||||
}
|
||||
@@ -110,7 +108,7 @@
|
||||
|
||||
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
|
||||
if (s == 0) {
|
||||
@@ -1094,7 +1129,7 @@ main(int argc, char **argv)
|
||||
@@ -1094,7 +1121,7 @@ main(int argc, char **argv)
|
||||
|
||||
USE_TTY();
|
||||
|
||||
@@ -119,7 +117,7 @@
|
||||
"O:o:G:g:",
|
||||
long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
@@ -1169,6 +1204,9 @@ main(int argc, char **argv)
|
||||
@@ -1169,6 +1196,9 @@ main(int argc, char **argv)
|
||||
case 'U':
|
||||
mode = UDP_ONLY;
|
||||
break;
|
||||
@@ -129,7 +127,7 @@
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
@@ -1255,6 +1293,9 @@ main(int argc, char **argv)
|
||||
@@ -1255,6 +1285,9 @@ main(int argc, char **argv)
|
||||
if (mode == TCP_ONLY) {
|
||||
mode = conf->mode;
|
||||
}
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
From 32f944b9a06fb2be4cd50da2434f2fd4b4decede Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <984419930@qq.com>
|
||||
Date: Thu, 1 Feb 2024 21:21:56 +0800
|
||||
Subject: [PATCH] Upgrade PCRE to PCRE2
|
||||
|
||||
Signed-off-by: sbwml <984419930@qq.com>
|
||||
---
|
||||
configure.ac | 8 +--
|
||||
m4/pcre.m4 | 152 ------------------------------------------
|
||||
m4/pcre2.m4 | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/rule.c | 47 ++++++++++---
|
||||
src/rule.h | 22 +++++--
|
||||
5 files changed, 238 insertions(+), 172 deletions(-)
|
||||
delete mode 100644 m4/pcre.m4
|
||||
create mode 100644 m4/pcre2.m4
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index f9c51ab..0513db0 100755
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -20,10 +20,10 @@ AC_DISABLE_STATIC
|
||||
AC_DISABLE_SHARED
|
||||
LT_INIT([dlopen])
|
||||
|
||||
-dnl Check for pcre library
|
||||
-TS_CHECK_PCRE
|
||||
-if test "x${enable_pcre}" != "xyes"; then
|
||||
- AC_MSG_ERROR([Cannot find pcre library. Configure --with-pcre=DIR])
|
||||
+dnl Check for pcre2 library
|
||||
+TS_CHECK_PCRE2
|
||||
+if test "x${enable_pcre2}" != "xyes"; then
|
||||
+ AC_MSG_ERROR([Cannot find pcre2 library. Configure --with-pcre2=DIR])
|
||||
fi
|
||||
|
||||
dnl Checks for using shared libraries from system
|
||||
diff --git a/m4/pcre.m4 b/m4/pcre.m4
|
||||
deleted file mode 100644
|
||||
index 4d965bc..0000000
|
||||
--- a/m4/pcre.m4
|
||||
+++ /dev/null
|
||||
@@ -1,152 +0,0 @@
|
||||
-dnl -------------------------------------------------------- -*- autoconf -*-
|
||||
-dnl Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
-dnl contributor license agreements. See the NOTICE file distributed with
|
||||
-dnl this work for additional information regarding copyright ownership.
|
||||
-dnl The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
-dnl (the "License"); you may not use this file except in compliance with
|
||||
-dnl the License. You may obtain a copy of the License at
|
||||
-dnl
|
||||
-dnl http://www.apache.org/licenses/LICENSE-2.0
|
||||
-dnl
|
||||
-dnl Unless required by applicable law or agreed to in writing, software
|
||||
-dnl distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-dnl See the License for the specific language governing permissions and
|
||||
-dnl limitations under the License.
|
||||
-
|
||||
-dnl
|
||||
-dnl TS_ADDTO(variable, value)
|
||||
-dnl
|
||||
-dnl Add value to variable
|
||||
-dnl
|
||||
-AC_DEFUN([TS_ADDTO], [
|
||||
- if test "x$$1" = "x"; then
|
||||
- test "x$verbose" = "xyes" && echo " setting $1 to \"$2\""
|
||||
- $1="$2"
|
||||
- else
|
||||
- ats_addto_bugger="$2"
|
||||
- for i in $ats_addto_bugger; do
|
||||
- ats_addto_duplicate="0"
|
||||
- for j in $$1; do
|
||||
- if test "x$i" = "x$j"; then
|
||||
- ats_addto_duplicate="1"
|
||||
- break
|
||||
- fi
|
||||
- done
|
||||
- if test $ats_addto_duplicate = "0"; then
|
||||
- test "x$verbose" = "xyes" && echo " adding \"$i\" to $1"
|
||||
- $1="$$1 $i"
|
||||
- fi
|
||||
- done
|
||||
- fi
|
||||
-])dnl
|
||||
-
|
||||
-dnl
|
||||
-dnl TS_ADDTO_RPATH(path)
|
||||
-dnl
|
||||
-dnl Adds path to variable with the '-rpath' directive.
|
||||
-dnl
|
||||
-AC_DEFUN([TS_ADDTO_RPATH], [
|
||||
- AC_MSG_NOTICE([adding $1 to RPATH])
|
||||
- TS_ADDTO(LIBTOOL_LINK_FLAGS, [-R$1])
|
||||
-])dnl
|
||||
-
|
||||
-dnl
|
||||
-dnl pcre.m4: Trafficserver's pcre autoconf macros
|
||||
-dnl
|
||||
-
|
||||
-dnl
|
||||
-dnl TS_CHECK_PCRE: look for pcre libraries and headers
|
||||
-dnl
|
||||
-AC_DEFUN([TS_CHECK_PCRE], [
|
||||
-enable_pcre=no
|
||||
-AC_ARG_WITH(pcre, [AC_HELP_STRING([--with-pcre=DIR],[use a specific pcre library])],
|
||||
-[
|
||||
- if test "x$withval" != "xyes" && test "x$withval" != "x"; then
|
||||
- pcre_base_dir="$withval"
|
||||
- if test "$withval" != "no"; then
|
||||
- enable_pcre=yes
|
||||
- case "$withval" in
|
||||
- *":"*)
|
||||
- pcre_include="`echo $withval |sed -e 's/:.*$//'`"
|
||||
- pcre_ldflags="`echo $withval |sed -e 's/^.*://'`"
|
||||
- AC_MSG_CHECKING(checking for pcre includes in $pcre_include libs in $pcre_ldflags )
|
||||
- ;;
|
||||
- *)
|
||||
- pcre_include="$withval/include"
|
||||
- pcre_ldflags="$withval/lib"
|
||||
- AC_MSG_CHECKING(checking for pcre includes in $withval)
|
||||
- ;;
|
||||
- esac
|
||||
- fi
|
||||
- fi
|
||||
-],
|
||||
-[
|
||||
- AC_CHECK_PROG(PCRE_CONFIG, pcre-config, pcre-config)
|
||||
- if test "x$PCRE_CONFIG" != "x"; then
|
||||
- enable_pcre=yes
|
||||
- pcre_base_dir="`$PCRE_CONFIG --prefix`"
|
||||
- pcre_include="`$PCRE_CONFIG --cflags | sed -es/-I//`"
|
||||
- pcre_ldflags="`$PCRE_CONFIG --libs | sed -es/-lpcre// -es/-L//`"
|
||||
- fi
|
||||
-])
|
||||
-
|
||||
-if test "x$pcre_base_dir" = "x"; then
|
||||
- AC_MSG_CHECKING([for pcre location])
|
||||
- AC_CACHE_VAL(ats_cv_pcre_dir,[
|
||||
- for dir in /usr/local /usr ; do
|
||||
- if test -d $dir && ( test -f $dir/include/pcre.h || test -f $dir/include/pcre/pcre.h ); then
|
||||
- ats_cv_pcre_dir=$dir
|
||||
- break
|
||||
- fi
|
||||
- done
|
||||
- ])
|
||||
- pcre_base_dir=$ats_cv_pcre_dir
|
||||
- if test "x$pcre_base_dir" = "x"; then
|
||||
- enable_pcre=no
|
||||
- AC_MSG_RESULT([not found])
|
||||
- else
|
||||
- enable_pcre=yes
|
||||
- pcre_include="$pcre_base_dir/include"
|
||||
- pcre_ldflags="$pcre_base_dir/lib"
|
||||
- AC_MSG_RESULT([$pcre_base_dir])
|
||||
- fi
|
||||
-else
|
||||
- AC_MSG_CHECKING(for pcre headers in $pcre_include)
|
||||
- if test -d $pcre_include && test -d $pcre_ldflags && ( test -f $pcre_include/pcre.h || test -f $pcre_include/pcre/pcre.h ); then
|
||||
- AC_MSG_RESULT([ok])
|
||||
- else
|
||||
- AC_MSG_RESULT([not found])
|
||||
- fi
|
||||
-fi
|
||||
-
|
||||
-pcreh=0
|
||||
-pcre_pcreh=0
|
||||
-if test "$enable_pcre" != "no"; then
|
||||
- saved_ldflags=$LDFLAGS
|
||||
- saved_cppflags=$CFLAGS
|
||||
- pcre_have_headers=0
|
||||
- pcre_have_libs=0
|
||||
- if test "$pcre_base_dir" != "/usr"; then
|
||||
- TS_ADDTO(CFLAGS, [-I${pcre_include}])
|
||||
- TS_ADDTO(CFLAGS, [-DPCRE_STATIC])
|
||||
- TS_ADDTO(LDFLAGS, [-L${pcre_ldflags}])
|
||||
- TS_ADDTO_RPATH(${pcre_ldflags})
|
||||
- fi
|
||||
- AC_SEARCH_LIBS([pcre_exec], [pcre], [pcre_have_libs=1])
|
||||
- if test "$pcre_have_libs" != "0"; then
|
||||
- AC_CHECK_HEADERS(pcre.h, [pcre_have_headers=1])
|
||||
- AC_CHECK_HEADERS(pcre/pcre.h, [pcre_have_headers=1])
|
||||
- fi
|
||||
- if test "$pcre_have_headers" != "0"; then
|
||||
- AC_DEFINE(HAVE_LIBPCRE,1,[Compiling with pcre support])
|
||||
- AC_SUBST(LIBPCRE, [-lpcre])
|
||||
- else
|
||||
- enable_pcre=no
|
||||
- CFLAGS=$saved_cppflags
|
||||
- LDFLAGS=$saved_ldflags
|
||||
- fi
|
||||
-fi
|
||||
-AC_SUBST(pcreh)
|
||||
-AC_SUBST(pcre_pcreh)
|
||||
-])
|
||||
diff --git a/m4/pcre2.m4 b/m4/pcre2.m4
|
||||
new file mode 100644
|
||||
index 0000000..fcec4b7
|
||||
--- /dev/null
|
||||
+++ b/m4/pcre2.m4
|
||||
@@ -0,0 +1,181 @@
|
||||
+dnl -------------------------------------------------------- -*- autoconf -*-
|
||||
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
+dnl contributor license agreements. See the NOTICE file distributed with
|
||||
+dnl this work for additional information regarding copyright ownership.
|
||||
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
+dnl (the "License"); you may not use this file except in compliance with
|
||||
+dnl the License. You may obtain a copy of the License at
|
||||
+dnl
|
||||
+dnl http://www.apache.org/licenses/LICENSE-2.0
|
||||
+dnl
|
||||
+dnl Unless required by applicable law or agreed to in writing, software
|
||||
+dnl distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+dnl See the License for the specific language governing permissions and
|
||||
+dnl limitations under the License.
|
||||
+
|
||||
+dnl Modified by Syrone Wong <wong.syrone@gmail.com> to support pcre2 8bit variant only
|
||||
+
|
||||
+dnl
|
||||
+dnl TS_ADDTO(variable, value)
|
||||
+dnl
|
||||
+dnl Add value to variable
|
||||
+dnl
|
||||
+AC_DEFUN([TS_ADDTO], [
|
||||
+ if test "x$$1" = "x"; then
|
||||
+ test "x$verbose" = "xyes" && echo " setting $1 to \"$2\""
|
||||
+ $1="$2"
|
||||
+ else
|
||||
+ ats_addto_bugger="$2"
|
||||
+ for i in $ats_addto_bugger; do
|
||||
+ ats_addto_duplicate="0"
|
||||
+ for j in $$1; do
|
||||
+ if test "x$i" = "x$j"; then
|
||||
+ ats_addto_duplicate="1"
|
||||
+ break
|
||||
+ fi
|
||||
+ done
|
||||
+ if test $ats_addto_duplicate = "0"; then
|
||||
+ test "x$verbose" = "xyes" && echo " adding \"$i\" to $1"
|
||||
+ $1="$$1 $i"
|
||||
+ fi
|
||||
+ done
|
||||
+ fi
|
||||
+])dnl
|
||||
+
|
||||
+dnl
|
||||
+dnl TS_ADDTO_RPATH(path)
|
||||
+dnl
|
||||
+dnl Adds path to variable with the '-rpath' directive.
|
||||
+dnl
|
||||
+AC_DEFUN([TS_ADDTO_RPATH], [
|
||||
+ AC_MSG_NOTICE([adding $1 to RPATH])
|
||||
+ TS_ADDTO(LIBTOOL_LINK_FLAGS, [-R$1])
|
||||
+])dnl
|
||||
+
|
||||
+dnl
|
||||
+dnl pcre2.m4: Trafficserver's pcre2 autoconf macros
|
||||
+dnl
|
||||
+
|
||||
+dnl
|
||||
+dnl TS_CHECK_PCRE2: look for pcre2 libraries and headers
|
||||
+dnl
|
||||
+AC_DEFUN([TS_CHECK_PCRE2], [
|
||||
+enable_pcre2=no
|
||||
+AC_ARG_WITH(pcre2, [AC_HELP_STRING([--with-pcre2=DIR],[use a specific pcre2 library])],
|
||||
+[
|
||||
+ if test "x$withval" != "xyes" && test "x$withval" != "x"; then
|
||||
+ pcre2_base_dir="$withval"
|
||||
+ if test "$withval" != "no"; then
|
||||
+ enable_pcre2=yes
|
||||
+ case "$withval" in
|
||||
+ *":"*)
|
||||
+ pcre2_include="`echo $withval |sed -e 's/:.*$//'`"
|
||||
+ pcre2_ldflags="`echo $withval |sed -e 's/^.*://'`"
|
||||
+ AC_MSG_CHECKING(checking for pcre2 includes in $pcre2_include libs in $pcre2_ldflags )
|
||||
+ ;;
|
||||
+ *)
|
||||
+ pcre2_include="$withval/include"
|
||||
+ pcre2_ldflags="$withval/lib"
|
||||
+ AC_MSG_CHECKING(checking for pcre2 includes in $withval)
|
||||
+ ;;
|
||||
+ esac
|
||||
+ fi
|
||||
+ fi
|
||||
+],
|
||||
+[
|
||||
+ AC_CHECK_PROG(PCRE2_CONFIG, pcre2-config, pcre2-config)
|
||||
+ if test "x$PCRE2_CONFIG" != "x"; then
|
||||
+ enable_pcre2=yes
|
||||
+ pcre2_base_dir="`$PCRE2_CONFIG --prefix`"
|
||||
+ pcre2_include="`$PCRE2_CONFIG --cflags | sed -es/-I//`"
|
||||
+ pcre2_ldflags="`$PCRE2_CONFIG --libs8 | sed -es/-lpcre2-8// -es/-L//`"
|
||||
+ fi
|
||||
+])
|
||||
+
|
||||
+if test "x$pcre2_base_dir" = "x"; then
|
||||
+ AC_MSG_CHECKING([for pcre2 location])
|
||||
+ AC_CACHE_VAL(ats_cv_pcre2_dir,[
|
||||
+ for dir in /usr/local /usr ; do
|
||||
+ if test -d $dir && ( test -f $dir/include/pcre2.h || test -f $dir/include/pcre2/pcre2.h ); then
|
||||
+ ats_cv_pcre2_dir=$dir
|
||||
+ break
|
||||
+ fi
|
||||
+ done
|
||||
+ ])
|
||||
+ pcre2_base_dir=$ats_cv_pcre2_dir
|
||||
+ if test "x$pcre2_base_dir" = "x"; then
|
||||
+ enable_pcre2=no
|
||||
+ AC_MSG_RESULT([not found])
|
||||
+ else
|
||||
+ enable_pcre2=yes
|
||||
+ pcre2_include="$pcre2_base_dir/include"
|
||||
+ pcre2_ldflags="$pcre2_base_dir/lib"
|
||||
+ AC_MSG_RESULT([$pcre2_base_dir])
|
||||
+ fi
|
||||
+else
|
||||
+ AC_MSG_CHECKING(for pcre2 headers in $pcre2_include)
|
||||
+ if test -d $pcre2_include && test -d $pcre2_ldflags && ( test -f $pcre2_include/pcre2.h || test -f $pcre2_include/pcre2/pcre2.h ); then
|
||||
+ AC_MSG_RESULT([ok])
|
||||
+ else
|
||||
+ AC_MSG_RESULT([not found])
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+pcre2h=0
|
||||
+pcre2_pcre2h=0
|
||||
+if test "$enable_pcre2" != "no"; then
|
||||
+ saved_ldflags=$LDFLAGS
|
||||
+ saved_cppflags=$CFLAGS
|
||||
+ pcre2_have_headers=0
|
||||
+ pcre2_have_libs=0
|
||||
+ if test "$pcre2_base_dir" != "/usr"; then
|
||||
+ TS_ADDTO(CFLAGS, [-I${pcre2_include}])
|
||||
+ TS_ADDTO(CFLAGS, [-DPCRE2_STATIC])
|
||||
+ TS_ADDTO(LDFLAGS, [-L${pcre2_ldflags}])
|
||||
+ TS_ADDTO_RPATH(${pcre2_ldflags})
|
||||
+ fi
|
||||
+ AC_SEARCH_LIBS([pcre2_match_8], [pcre2-8], [pcre2_have_libs=1])
|
||||
+ if test "$pcre2_have_libs" != "0"; then
|
||||
+ AC_MSG_CHECKING([pcre2.h])
|
||||
+ AC_COMPILE_IFELSE(
|
||||
+ [AC_LANG_PROGRAM(
|
||||
+ [[
|
||||
+#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
+#include <pcre2.h>
|
||||
+ ]],
|
||||
+ [[
|
||||
+ ]]
|
||||
+ )],
|
||||
+ [pcre2_have_headers=1
|
||||
+ AC_MSG_RESULT([ok])],
|
||||
+ [AC_MSG_RESULT([not found])]
|
||||
+ )
|
||||
+
|
||||
+ AC_MSG_CHECKING([pcre2/pcre2.h])
|
||||
+ AC_COMPILE_IFELSE(
|
||||
+ [AC_LANG_PROGRAM(
|
||||
+ [[
|
||||
+#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
+#include <pcre2/pcre2.h>
|
||||
+ ]],
|
||||
+ [[
|
||||
+ ]]
|
||||
+ )],
|
||||
+ [pcre2_have_headers=1
|
||||
+ AC_MSG_RESULT([ok])],
|
||||
+ [AC_MSG_RESULT([not found])]
|
||||
+ )
|
||||
+ fi
|
||||
+ if test "$pcre2_have_headers" != "0"; then
|
||||
+ AC_DEFINE(HAVE_LIBPCRE2,1,[Compiling with pcre2 support])
|
||||
+ AC_SUBST(LIBPCRE2, [-lpcre2-8])
|
||||
+ else
|
||||
+ enable_pcre2=no
|
||||
+ CFLAGS=$saved_cppflags
|
||||
+ LDFLAGS=$saved_ldflags
|
||||
+ fi
|
||||
+fi
|
||||
+AC_SUBST(pcre2h)
|
||||
+AC_SUBST(pcre2_pcre2h)
|
||||
+])
|
||||
diff --git a/src/rule.c b/src/rule.c
|
||||
index 8aae04e..41ba5e7 100644
|
||||
--- a/src/rule.c
|
||||
+++ b/src/rule.c
|
||||
@@ -82,14 +82,28 @@ int
|
||||
init_rule(rule_t *rule)
|
||||
{
|
||||
if (rule->pattern_re == NULL) {
|
||||
- const char *reerr;
|
||||
- int reerroffset;
|
||||
+ int errornumber;
|
||||
+ PCRE2_SIZE erroroffset;
|
||||
+ rule->pattern_re = pcre2_compile(
|
||||
+ (PCRE2_SPTR)rule->pattern, /* the pattern */
|
||||
+ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
|
||||
+ 0, /* default options */
|
||||
+ &errornumber, /* for error number */
|
||||
+ &erroroffset, /* for error offset */
|
||||
+ NULL); /* use default compile context */
|
||||
|
||||
- rule->pattern_re =
|
||||
- pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL);
|
||||
if (rule->pattern_re == NULL) {
|
||||
- LOGE("Regex compilation of \"%s\" failed: %s, offset %d",
|
||||
- rule->pattern, reerr, reerroffset);
|
||||
+ PCRE2_UCHAR errbuffer[512];
|
||||
+ pcre2_get_error_message(errornumber, errbuffer, sizeof(errbuffer));
|
||||
+ LOGE("PCRE2 regex compilation failed at offset %d: %s\n", (int)erroroffset,
|
||||
+ errbuffer);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ rule->pattern_re_match_data = pcre2_match_data_create_from_pattern(rule->pattern_re, NULL);
|
||||
+
|
||||
+ if (rule->pattern_re_match_data == NULL) {
|
||||
+ ERROR("PCRE2: the memory for the block could not be obtained");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -109,8 +123,15 @@ lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len)
|
||||
|
||||
cork_dllist_foreach_void(rules, curr, next) {
|
||||
rule_t *rule = cork_container_of(curr, rule_t, entries);
|
||||
- if (pcre_exec(rule->pattern_re, NULL,
|
||||
- name, name_len, 0, 0, NULL, 0) >= 0)
|
||||
+ if (pcre2_match(
|
||||
+ rule->pattern_re, /* the compiled pattern */
|
||||
+ (PCRE2_SPTR)name, /* the subject string */
|
||||
+ name_len, /* the length of the subject */
|
||||
+ 0, /* start at offset 0 in the subject */
|
||||
+ 0, /* default options */
|
||||
+ rule->pattern_re_match_data, /* block for storing the result */
|
||||
+ NULL /* use default match context */
|
||||
+ ) >= 0)
|
||||
return rule;
|
||||
}
|
||||
|
||||
@@ -131,7 +152,13 @@ free_rule(rule_t *rule)
|
||||
return;
|
||||
|
||||
ss_free(rule->pattern);
|
||||
- if (rule->pattern_re != NULL)
|
||||
- pcre_free(rule->pattern_re);
|
||||
+ if (rule->pattern_re != NULL) {
|
||||
+ pcre2_code_free(rule->pattern_re); /* data and the compiled pattern. */
|
||||
+ rule->pattern_re = NULL;
|
||||
+ }
|
||||
+ if (rule->pattern_re_match_data != NULL) {
|
||||
+ pcre2_match_data_free(rule->pattern_re_match_data); /* Release memory used for the match */
|
||||
+ rule->pattern_re_match_data = NULL;
|
||||
+ }
|
||||
ss_free(rule);
|
||||
}
|
||||
diff --git a/src/rule.h b/src/rule.h
|
||||
index 015bc42..84a89af 100644
|
||||
--- a/src/rule.h
|
||||
+++ b/src/rule.h
|
||||
@@ -33,17 +33,27 @@
|
||||
|
||||
#include <libcork/ds.h>
|
||||
|
||||
-#ifdef HAVE_PCRE_H
|
||||
-#include <pcre.h>
|
||||
-#elif HAVE_PCRE_PCRE_H
|
||||
-#include <pcre/pcre.h>
|
||||
-#endif
|
||||
+/*
|
||||
+ * The PCRE2_CODE_UNIT_WIDTH macro must be defined before including pcre2.h.
|
||||
+ * For a program that uses only one code unit width, setting it to 8, 16, or 32
|
||||
+ * makes it possible to use generic function names such as pcre2_compile(). Note
|
||||
+ * that just changing 8 to 16 (for example) is not sufficient to convert this
|
||||
+ * program to process 16-bit characters. Even in a fully 16-bit environment, where
|
||||
+ * string-handling functions such as strcmp() and printf() work with 16-bit
|
||||
+ * characters, the code for handling the table of named substrings will still need
|
||||
+ * to be modified.
|
||||
+ */
|
||||
+/* we only need to support ASCII chartable, thus set it to 8 */
|
||||
+#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
+
|
||||
+#include <pcre2.h>
|
||||
|
||||
typedef struct rule {
|
||||
char *pattern;
|
||||
|
||||
/* Runtime fields */
|
||||
- pcre *pattern_re;
|
||||
+ pcre2_code *pattern_re;
|
||||
+ pcre2_match_data *pattern_re_match_data;
|
||||
|
||||
struct cork_dllist_item entries;
|
||||
} rule_t;
|
||||
--
|
||||
2.42.0
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=simple-obfs
|
||||
PKG_VERSION:=0.0.9
|
||||
PKG_VERSION:=0.0.10
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/simple-obfs/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=d0f7a1ec6b13ade944ab43d551ba04b0a48b58d7ebfefec5607ce33e7d4bf2d7
|
||||
PKG_HASH:=f64eb9f9013fe0798e5159e3cd108909eb4ac949d78d51804d96945af82d363e
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=v2dat
|
||||
PKG_VERSION:=0.1.1
|
||||
PKG_VERSION:=0.1.2
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/v2dat/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=8c5ca5ffec48034527de09281ed4cb7fb6004fc693e09baf7d874549ad7e49c0
|
||||
PKG_HASH:=a85229fa6b0c9fbb4cb14c3e4734f5c6b743a779e6337bba09e144720451e1ac
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ require (
|
||||
go.starlark.net v0.0.0-20230612165344-9532f5667272
|
||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
|
||||
golang.org/x/crypto v0.49.0
|
||||
golang.org/x/net v0.51.0
|
||||
golang.org/x/net v0.52.0
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/sys v0.42.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb
|
||||
|
||||
+2
-2
@@ -661,8 +661,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
||||
@@ -8,8 +8,27 @@ import (
|
||||
|
||||
type GunConfig struct {
|
||||
ServiceName string `json:"serviceName"`
|
||||
IdleTimeout int32 `json:"idle_timeout"`
|
||||
HealthCheckTimeout int32 `json:"health_check_timeout"`
|
||||
PermitWithoutStream bool `json:"permit_without_stream"`
|
||||
InitialWindowsSize int32 `json:"initial_windows_size"`
|
||||
}
|
||||
|
||||
func (g GunConfig) Build() (proto.Message, error) {
|
||||
return &grpc.Config{ServiceName: g.ServiceName}, nil
|
||||
if g.IdleTimeout <= 0 {
|
||||
g.IdleTimeout = 0
|
||||
}
|
||||
if g.HealthCheckTimeout <= 0 {
|
||||
g.HealthCheckTimeout = 0
|
||||
}
|
||||
if g.InitialWindowsSize < 0 {
|
||||
g.InitialWindowsSize = 0
|
||||
}
|
||||
return &grpc.Config{
|
||||
ServiceName: g.ServiceName,
|
||||
IdleTimeout: g.IdleTimeout,
|
||||
HealthCheckTimeout: g.HealthCheckTimeout,
|
||||
PermitWithoutStream: g.PermitWithoutStream,
|
||||
InitialWindowsSize: g.InitialWindowsSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -213,7 +213,6 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
|
||||
rawConn.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
rawConn.Close()
|
||||
|
||||
@@ -269,9 +269,9 @@ func (c *ClientUDPSessionConn) ReadFrom(p []byte) (n int, addr net.Addr, err err
|
||||
rxReplayDetector: replaydetector.New(1024, ^uint64(0)),
|
||||
}
|
||||
c.trackedServerSessionID[string(resp.SessionID[:])] = state
|
||||
c.parent.locker.RLock()
|
||||
c.parent.locker.Lock()
|
||||
c.parent.sessionMapAlias[string(resp.SessionID[:])] = string(resp.ClientSessionID[:])
|
||||
c.parent.locker.RUnlock()
|
||||
c.parent.locker.Unlock()
|
||||
trackedState = state
|
||||
} else {
|
||||
trackedState = trackedStateReceived
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc v6.33.1
|
||||
// source: transport/internet/grpc/config.proto
|
||||
|
||||
package grpc
|
||||
|
||||
import (
|
||||
@@ -20,6 +26,10 @@ type Config struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"`
|
||||
ServiceName string `protobuf:"bytes,2,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"`
|
||||
IdleTimeout int32 `protobuf:"varint,3,opt,name=idle_timeout,json=idleTimeout,proto3" json:"idle_timeout,omitempty"`
|
||||
HealthCheckTimeout int32 `protobuf:"varint,4,opt,name=health_check_timeout,json=healthCheckTimeout,proto3" json:"health_check_timeout,omitempty"`
|
||||
PermitWithoutStream bool `protobuf:"varint,5,opt,name=permit_without_stream,json=permitWithoutStream,proto3" json:"permit_without_stream,omitempty"`
|
||||
InitialWindowsSize int32 `protobuf:"varint,6,opt,name=initial_windows_size,json=initialWindowsSize,proto3" json:"initial_windows_size,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -68,14 +78,46 @@ func (x *Config) GetServiceName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetIdleTimeout() int32 {
|
||||
if x != nil {
|
||||
return x.IdleTimeout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetHealthCheckTimeout() int32 {
|
||||
if x != nil {
|
||||
return x.HealthCheckTimeout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetPermitWithoutStream() bool {
|
||||
if x != nil {
|
||||
return x.PermitWithoutStream
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetInitialWindowsSize() int32 {
|
||||
if x != nil {
|
||||
return x.InitialWindowsSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_transport_internet_grpc_config_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_transport_internet_grpc_config_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"$transport/internet/grpc/config.proto\x12+v2ray.core.transport.internet.grpc.encoding\x1a common/protoext/extensions.proto\"a\n" +
|
||||
"$transport/internet/grpc/config.proto\x12+v2ray.core.transport.internet.grpc.encoding\x1a common/protoext/extensions.proto\"\x9c\x02\n" +
|
||||
"\x06Config\x12\x12\n" +
|
||||
"\x04host\x18\x01 \x01(\tR\x04host\x12!\n" +
|
||||
"\fservice_name\x18\x02 \x01(\tR\vserviceName: \x82\xb5\x18\x1c\n" +
|
||||
"\fservice_name\x18\x02 \x01(\tR\vserviceName\x12!\n" +
|
||||
"\fidle_timeout\x18\x03 \x01(\x05R\vidleTimeout\x120\n" +
|
||||
"\x14health_check_timeout\x18\x04 \x01(\x05R\x12healthCheckTimeout\x122\n" +
|
||||
"\x15permit_without_stream\x18\x05 \x01(\bR\x13permitWithoutStream\x120\n" +
|
||||
"\x14initial_windows_size\x18\x06 \x01(\x05R\x12initialWindowsSize: \x82\xb5\x18\x1c\n" +
|
||||
"\ttransport\x12\x04grpc\x8a\xff)\x03gun\x90\xff)\x01B\x85\x01\n" +
|
||||
"&com.v2ray.core.transport.internet.grpcZ6github.com/v2fly/v2ray-core/v5/transport/internet/grpc\xaa\x02\"V2Ray.Core.Transport.Internet.Grpcb\x06proto3"
|
||||
|
||||
|
||||
@@ -16,4 +16,8 @@ message Config {
|
||||
|
||||
string host = 1;
|
||||
string service_name = 2;
|
||||
int32 idle_timeout = 3;
|
||||
int32 health_check_timeout = 4;
|
||||
bool permit_without_stream = 5;
|
||||
int32 initial_windows_size = 6;
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
@@ -63,15 +64,7 @@ type dialerCanceller func()
|
||||
func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
|
||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
|
||||
transportCredentials := insecure.NewCredentials()
|
||||
if config != nil {
|
||||
transportCredentials = credentials.NewTLS(config.GetTLSConfig(tls.WithDestination(dest)))
|
||||
}
|
||||
dialOption := grpc.WithTransportCredentials(transportCredentials)
|
||||
|
||||
conn, canceller, err := getGrpcClient(ctx, dest, dialOption, streamSettings)
|
||||
conn, canceller, err := getGrpcClient(ctx, dest, streamSettings)
|
||||
if err != nil {
|
||||
return nil, newError("Cannot dial grpc").Base(err)
|
||||
}
|
||||
@@ -84,9 +77,54 @@ func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *interne
|
||||
return encoding.NewGunConn(gunService, nil), nil
|
||||
}
|
||||
|
||||
func getGrpcClient(ctx context.Context, dest net.Destination, dialOption grpc.DialOption, streamSettings *internet.MemoryStreamConfig) (*grpc.ClientConn, dialerCanceller, error) {
|
||||
func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (*grpc.ClientConn, dialerCanceller, error) {
|
||||
transportEnvironment := envctx.EnvironmentFromContext(ctx).(environment.TransportEnvironment)
|
||||
state, err := transportEnvironment.TransientStorage().Get(ctx, "grpc-transport-connection-state")
|
||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
transportCredentials := insecure.NewCredentials()
|
||||
if tlsConfig != nil {
|
||||
transportCredentials = credentials.NewTLS(tlsConfig.GetTLSConfig(tls.WithDestination(dest)))
|
||||
}
|
||||
dialOptions := []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(transportCredentials),
|
||||
grpc.WithConnectParams(grpc.ConnectParams{
|
||||
Backoff: backoff.Config{
|
||||
BaseDelay: 500 * time.Millisecond,
|
||||
Multiplier: 1.5,
|
||||
Jitter: 0.2,
|
||||
MaxDelay: 19 * time.Second,
|
||||
},
|
||||
MinConnectTimeout: 5 * time.Second,
|
||||
}),
|
||||
grpc.WithContextDialer(func(ctxGrpc context.Context, s string) (gonet.Conn, error) {
|
||||
rawHost, rawPort, err := net.SplitHostPort(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rawPort) == 0 {
|
||||
rawPort = "443"
|
||||
}
|
||||
port, err := net.PortFromString(rawPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
address := net.ParseAddress(rawHost)
|
||||
detachedContext := core.ToBackgroundDetachedContext(ctx)
|
||||
return internet.DialSystem(detachedContext, net.TCPDestination(address, port), streamSettings.SocketSettings)
|
||||
}),
|
||||
grpc.WithDisableServiceConfig(),
|
||||
}
|
||||
if grpcSettings.IdleTimeout > 0 || grpcSettings.HealthCheckTimeout > 0 || grpcSettings.PermitWithoutStream {
|
||||
dialOptions = append(dialOptions, grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: time.Second * time.Duration(grpcSettings.IdleTimeout),
|
||||
Timeout: time.Second * time.Duration(grpcSettings.HealthCheckTimeout),
|
||||
PermitWithoutStream: grpcSettings.PermitWithoutStream,
|
||||
}))
|
||||
}
|
||||
if grpcSettings.InitialWindowsSize > 0 {
|
||||
dialOptions = append(dialOptions, grpc.WithInitialWindowSize(grpcSettings.InitialWindowsSize))
|
||||
}
|
||||
if err != nil {
|
||||
state = &transportConnectionState{}
|
||||
transportEnvironment.TransientStorage().Put(ctx, "grpc-transport-connection-state", state)
|
||||
@@ -116,33 +154,7 @@ func getGrpcClient(ctx context.Context, dest net.Destination, dialOption grpc.Di
|
||||
|
||||
conn, err := grpc.NewClient(
|
||||
dest.Address.String()+":"+dest.Port.String(),
|
||||
dialOption,
|
||||
grpc.WithConnectParams(grpc.ConnectParams{
|
||||
Backoff: backoff.Config{
|
||||
BaseDelay: 500 * time.Millisecond,
|
||||
Multiplier: 1.5,
|
||||
Jitter: 0.2,
|
||||
MaxDelay: 19 * time.Second,
|
||||
},
|
||||
MinConnectTimeout: 5 * time.Second,
|
||||
}),
|
||||
grpc.WithContextDialer(func(ctxGrpc context.Context, s string) (gonet.Conn, error) {
|
||||
rawHost, rawPort, err := net.SplitHostPort(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rawPort) == 0 {
|
||||
rawPort = "443"
|
||||
}
|
||||
port, err := net.PortFromString(rawPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
address := net.ParseAddress(rawHost)
|
||||
detachedContext := core.ToBackgroundDetachedContext(ctx)
|
||||
return internet.DialSystem(detachedContext, net.TCPDestination(address, port), streamSettings.SocketSettings)
|
||||
}),
|
||||
grpc.WithDisableServiceConfig(),
|
||||
dialOptions...,
|
||||
)
|
||||
canceller = func() {
|
||||
stateTyped.scopedDialerAccess.Lock()
|
||||
|
||||
Vendored
+7
-7
@@ -231,7 +231,7 @@ jobs:
|
||||
[[ "${version}" != "${downgraded_version}" ]]
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-bin-${{ github.job }}
|
||||
path: |
|
||||
@@ -267,7 +267,7 @@ jobs:
|
||||
|
||||
- name: Set up QEMU
|
||||
if: matrix.qemu_platform
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||
with:
|
||||
image: tonistiigi/binfmt:qemu-v10.0.4-56@sha256:30cc9a4d03765acac9be2ed0afc23af1ad018aed2c28ea4be8c2eb9afe03fbd1
|
||||
cache-image: false
|
||||
@@ -294,7 +294,7 @@ jobs:
|
||||
docker compose up --build --exit-code-from "${SERVICE}" "${SERVICE}"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-bin-${{ matrix.os }}_${{ matrix.arch }}
|
||||
path: |
|
||||
@@ -384,7 +384,7 @@ jobs:
|
||||
[[ "$version" != "$downgraded_version" ]]
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-bin-${{ github.job }}
|
||||
path: |
|
||||
@@ -501,7 +501,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-bin-${{ github.job }}-${{ matrix.arch }}
|
||||
path: |
|
||||
@@ -521,7 +521,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: artifact
|
||||
pattern: build-bin-*
|
||||
@@ -590,7 +590,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-${{ github.job }}
|
||||
path: |
|
||||
|
||||
+2
-2
@@ -50,13 +50,13 @@ jobs:
|
||||
with:
|
||||
deno-version: '2.0.0' # minimum supported version
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
with:
|
||||
# minimum supported version is 1.0.31 but earliest available Windows version is 1.1.0
|
||||
bun-version: ${{ (matrix.os == 'windows-latest' && '1.1.0') || '1.0.31' }}
|
||||
no-cache: true
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.0' # minimum supported version
|
||||
- name: Install QuickJS (Linux)
|
||||
|
||||
Vendored
+2
-2
@@ -36,12 +36,12 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: none
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: build-pypi
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ jobs:
|
||||
run: echo "head=$(git rev-parse HEAD)" | tee -a "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Cache nightly commit hash
|
||||
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
with:
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: build-pypi
|
||||
|
||||
Vendored
+2
-2
@@ -214,7 +214,7 @@ jobs:
|
||||
|
||||
- name: Upload artifacts
|
||||
if: github.event.workflow != '.github/workflows/release.yml' # Reusable workflow_call
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: build-pypi
|
||||
path: |
|
||||
@@ -243,7 +243,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: artifact
|
||||
pattern: build-*
|
||||
|
||||
+4
-4
@@ -26,8 +26,8 @@ concurrency:
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
ACTIONLINT_VERSION: "1.7.9"
|
||||
ACTIONLINT_SHA256SUM: 233b280d05e100837f4af1433c7b40a5dcb306e3aa68fb4f17f8a7f45a7df7b4
|
||||
ACTIONLINT_VERSION: "1.7.11"
|
||||
ACTIONLINT_SHA256SUM: 900919a84f2229bac68ca9cd4103ea297abc35e9689ebb842c6e34a3d1b01b0a
|
||||
ACTIONLINT_REPO: https://github.com/rhysd/actionlint
|
||||
|
||||
jobs:
|
||||
@@ -76,8 +76,8 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@135698455da5c3b3e55f73f4419e481ab68cdd95 # v0.4.1
|
||||
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
|
||||
with:
|
||||
advanced-security: false
|
||||
persona: pedantic
|
||||
version: v1.22.0
|
||||
version: v1.23.1
|
||||
|
||||
Vendored
+4
@@ -9,6 +9,10 @@ rules:
|
||||
obfuscation:
|
||||
ignore:
|
||||
- release.yml # Not actual obfuscation
|
||||
secrets-outside-env:
|
||||
ignore:
|
||||
- build.yml
|
||||
- release.yml
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
|
||||
Reference in New Issue
Block a user