Update On Tue Mar 17 20:16:43 CET 2026

This commit is contained in:
github-action[bot]
2026-03-17 20:16:44 +01:00
parent 3888600a40
commit 775b612ecc
72 changed files with 1601 additions and 1470 deletions
+1
View File
@@ -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 Sat Mar 14 19:52:58 CET 2026
Update On Sun Mar 15 19:54:13 CET 2026 Update On Sun Mar 15 19:54:13 CET 2026
Update On Mon Mar 16 20:17:53 CET 2026 Update On Mon Mar 16 20:17:53 CET 2026
Update On Tue Mar 17 20:16:34 CET 2026
+3 -3
View File
@@ -63,7 +63,7 @@ jobs:
workspaces: 'backend' workspaces: 'backend'
save-if: ${{ github.event_name == 'push' }} save-if: ${{ github.event_name == 'push' }}
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@@ -155,7 +155,7 @@ jobs:
workspaces: 'backend' workspaces: 'backend'
save-if: ${{ github.event_name == 'push' }} save-if: ${{ github.event_name == 'push' }}
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@@ -247,7 +247,7 @@ jobs:
workspaces: 'backend' workspaces: 'backend'
save-if: ${{ github.event_name == 'push' }} save-if: ${{ github.event_name == 'push' }}
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+2 -2
View File
@@ -18,7 +18,7 @@ jobs:
with: with:
node-version: '24' node-version: '24'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@@ -63,7 +63,7 @@ jobs:
with: with:
node-version: '24' node-version: '24'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+1 -1
View File
@@ -84,7 +84,7 @@ jobs:
with: with:
node-version: 24 node-version: 24
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+1 -1
View File
@@ -73,7 +73,7 @@ jobs:
with: with:
deno-version: v2.x deno-version: v2.x
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@@ -90,7 +90,7 @@ jobs:
with: with:
node-version: 24 node-version: 24
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
with: with:
node-version: 24 node-version: 24
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
with: with:
node-version: '24' node-version: '24'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version: 24 node-version: 24
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v5
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@@ -194,6 +194,15 @@
"connections_empty_message": "No connections found", "connections_empty_message": "No connections found",
"connections_close_connection": "Close Connection", "connections_close_connection": "Close Connection",
"connections_view_details": "Details", "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_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_validate_error_message": "Please fix the error before saving content",
"editor_read_only_chip": "Read Only", "editor_read_only_chip": "Read Only",
@@ -194,6 +194,15 @@
"connections_empty_message": "Не найдено ни одного соединения", "connections_empty_message": "Не найдено ни одного соединения",
"connections_close_connection": "Закрыть соединение", "connections_close_connection": "Закрыть соединение",
"connections_view_details": "Просмотреть детали", "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_before_close_message": "Вы не сохранили измененное содержимое, вы уверены, что хотите закрыть редактор?",
"editor_validate_error_message": "Пожалуйста, исправьте ошибки перед сохранением содержимого", "editor_validate_error_message": "Пожалуйста, исправьте ошибки перед сохранением содержимого",
"editor_read_only_chip": "Только для чтения", "editor_read_only_chip": "Только для чтения",
@@ -194,6 +194,15 @@
"connections_empty_message": "没有找到任何连接", "connections_empty_message": "没有找到任何连接",
"connections_close_connection": "关闭连接", "connections_close_connection": "关闭连接",
"connections_view_details": "查看详情", "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_before_close_message": "你尚未保存编辑的内容,确定要关闭编辑器吗?",
"editor_validate_error_message": "请修复错误后再保存内容", "editor_validate_error_message": "请修复错误后再保存内容",
"editor_read_only_chip": "只读", "editor_read_only_chip": "只读",
@@ -194,6 +194,15 @@
"connections_empty_message": "沒有找到任何連接", "connections_empty_message": "沒有找到任何連接",
"connections_close_connection": "關閉連接", "connections_close_connection": "關閉連接",
"connections_view_details": "查看詳情", "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_before_close_message": "你尚未儲存編輯的內容,確定要關閉編輯器嗎?",
"editor_validate_error_message": "請修正錯誤後再儲存內容", "editor_validate_error_message": "請修正錯誤後再儲存內容",
"editor_read_only_chip": "只讀", "editor_read_only_chip": "只讀",
@@ -42,7 +42,7 @@
"country-code-emoji": "2.3.0", "country-code-emoji": "2.3.0",
"country-emoji": "1.5.6", "country-emoji": "1.5.6",
"dayjs": "1.11.20", "dayjs": "1.11.20",
"framer-motion": "12.36.0", "framer-motion": "12.38.0",
"i18next": "25.8.18", "i18next": "25.8.18",
"jotai": "2.18.1", "jotai": "2.18.1",
"json-schema": "0.4.0", "json-schema": "0.4.0",
@@ -69,12 +69,12 @@
"@csstools/normalize.css": "12.1.1", "@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.13.5", "@emotion/babel-plugin": "11.13.5",
"@emotion/react": "11.14.0", "@emotion/react": "11.14.0",
"@iconify/json": "2.2.450", "@iconify/json": "2.2.451",
"@monaco-editor/react": "4.7.0", "@monaco-editor/react": "4.7.0",
"@tanstack/react-query": "5.90.21", "@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/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-clipboard-manager": "2.3.2",
"@tauri-apps/plugin-dialog": "2.6.0", "@tauri-apps/plugin-dialog": "2.6.0",
"@tauri-apps/plugin-fs": "2.4.5", "@tauri-apps/plugin-fs": "2.4.5",
@@ -91,7 +91,7 @@
"@vitejs/plugin-react-swc": "4.3.0", "@vitejs/plugin-react-swc": "4.3.0",
"change-case": "5.4.4", "change-case": "5.4.4",
"clsx": "2.1.1", "clsx": "2.1.1",
"core-js": "3.48.0", "core-js": "3.49.0",
"filesize": "11.0.13", "filesize": "11.0.13",
"meta-json-schema": "1.19.21", "meta-json-schema": "1.19.21",
"monaco-yaml": "5.4.1", "monaco-yaml": "5.4.1",
@@ -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>
</>
)
}
@@ -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
}
@@ -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])
}
@@ -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>
</>
)
}
@@ -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>
)
}
@@ -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')({ export const Route = createFileRoute('/(main)/main/providers')({
component: RouteComponent, component: RouteComponent,
}) })
function RouteComponent() { const NavigateButton = ({
return <div>Hello "/(main)/main/providers"!</div> 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>
</>
)
}
@@ -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 mainMainSettingsIndexRouteImport } from './pages/(main)/main/settings/index'
import { Route as mainMainRulesIndexRouteImport } from './pages/(main)/main/rules/index' import { Route as mainMainRulesIndexRouteImport } from './pages/(main)/main/rules/index'
import { Route as mainMainProxiesIndexRouteImport } from './pages/(main)/main/proxies/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 mainMainProfilesIndexRouteImport } from './pages/(main)/main/profiles/index'
import { Route as mainMainLogsIndexRouteImport } from './pages/(main)/main/logs/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 mainMainSettingsWebUiRouteRouteImport } from './pages/(main)/main/settings/web-ui/route'
import { Route as mainMainSettingsUserInterfaceRouteRouteImport } from './pages/(main)/main/settings/user-interface/route' import { Route as mainMainSettingsUserInterfaceRouteRouteImport } from './pages/(main)/main/settings/user-interface/route'
import { Route as mainMainSettingsSystemRouteRouteImport } from './pages/(main)/main/settings/system/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 mainMainSettingsDebugIndexRouteImport } from './pages/(main)/main/settings/debug/index'
import { Route as mainMainProfilesTypeIndexRouteImport } from './pages/(main)/main/profiles/$type/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 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' import { Route as mainMainProfilesTypeDetailUidRouteImport } from './pages/(main)/main/profiles/$type/detail/$uid'
const mainRouteRoute = mainRouteRouteImport.update({ const mainRouteRoute = mainRouteRouteImport.update({
@@ -173,6 +177,11 @@ const mainMainProxiesIndexRoute = mainMainProxiesIndexRouteImport.update({
path: '/', path: '/',
getParentRoute: () => mainMainProxiesRouteRoute, getParentRoute: () => mainMainProxiesRouteRoute,
} as any) } as any)
const mainMainProvidersIndexRoute = mainMainProvidersIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => mainMainProvidersRouteRoute,
} as any)
const mainMainProfilesIndexRoute = mainMainProfilesIndexRouteImport.update({ const mainMainProfilesIndexRoute = mainMainProfilesIndexRouteImport.update({
id: '/', id: '/',
path: '/', path: '/',
@@ -183,6 +192,12 @@ const mainMainLogsIndexRoute = mainMainLogsIndexRouteImport.update({
path: '/', path: '/',
getParentRoute: () => mainMainLogsRouteRoute, getParentRoute: () => mainMainLogsRouteRoute,
} as any) } as any)
const mainMainConnectionsIndexRoute =
mainMainConnectionsIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => mainMainConnectionsRouteRoute,
} as any)
const mainMainSettingsWebUiRouteRoute = const mainMainSettingsWebUiRouteRoute =
mainMainSettingsWebUiRouteRouteImport.update({ mainMainSettingsWebUiRouteRouteImport.update({
id: '/web-ui', id: '/web-ui',
@@ -249,6 +264,18 @@ const mainMainProxiesGroupNameRoute =
path: '/group/$name', path: '/group/$name',
getParentRoute: () => mainMainProxiesRouteRoute, getParentRoute: () => mainMainProxiesRouteRoute,
} as any) } 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 = const mainMainProfilesTypeDetailUidRoute =
mainMainProfilesTypeDetailUidRouteImport.update({ mainMainProfilesTypeDetailUidRouteImport.update({
id: '/$type/detail/$uid', id: '/$type/detail/$uid',
@@ -267,11 +294,11 @@ export interface FileRoutesByFullPath {
'/rules': typeof legacyRulesRoute '/rules': typeof legacyRulesRoute
'/settings': typeof legacySettingsRoute '/settings': typeof legacySettingsRoute
'/': typeof legacyIndexRoute '/': typeof legacyIndexRoute
'/main/connections': typeof mainMainConnectionsRouteRoute '/main/connections': typeof mainMainConnectionsRouteRouteWithChildren
'/main/dashboard': typeof mainMainDashboardRouteRoute '/main/dashboard': typeof mainMainDashboardRouteRoute
'/main/logs': typeof mainMainLogsRouteRouteWithChildren '/main/logs': typeof mainMainLogsRouteRouteWithChildren
'/main/profiles': typeof mainMainProfilesRouteRouteWithChildren '/main/profiles': typeof mainMainProfilesRouteRouteWithChildren
'/main/providers': typeof mainMainProvidersRouteRoute '/main/providers': typeof mainMainProvidersRouteRouteWithChildren
'/main/proxies': typeof mainMainProxiesRouteRouteWithChildren '/main/proxies': typeof mainMainProxiesRouteRouteWithChildren
'/main/rules': typeof mainMainRulesRouteRouteWithChildren '/main/rules': typeof mainMainRulesRouteRouteWithChildren
'/main/settings': typeof mainMainSettingsRouteRouteWithChildren '/main/settings': typeof mainMainSettingsRouteRouteWithChildren
@@ -285,11 +312,15 @@ export interface FileRoutesByFullPath {
'/main/settings/system': typeof mainMainSettingsSystemRouteRoute '/main/settings/system': typeof mainMainSettingsSystemRouteRoute
'/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute '/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
'/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute '/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
'/main/connections/': typeof mainMainConnectionsIndexRoute
'/main/logs/': typeof mainMainLogsIndexRoute '/main/logs/': typeof mainMainLogsIndexRoute
'/main/profiles/': typeof mainMainProfilesIndexRoute '/main/profiles/': typeof mainMainProfilesIndexRoute
'/main/providers/': typeof mainMainProvidersIndexRoute
'/main/proxies/': typeof mainMainProxiesIndexRoute '/main/proxies/': typeof mainMainProxiesIndexRoute
'/main/rules/': typeof mainMainRulesIndexRoute '/main/rules/': typeof mainMainRulesIndexRoute
'/main/settings/': typeof mainMainSettingsIndexRoute '/main/settings/': typeof mainMainSettingsIndexRoute
'/main/providers/proxies/$key': typeof mainMainProvidersProxiesKeyRoute
'/main/providers/rules/$key': typeof mainMainProvidersRulesKeyRoute
'/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute '/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
'/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute '/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute
'/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute '/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute
@@ -305,9 +336,7 @@ export interface FileRoutesByTo {
'/rules': typeof legacyRulesRoute '/rules': typeof legacyRulesRoute
'/settings': typeof legacySettingsRoute '/settings': typeof legacySettingsRoute
'/': typeof legacyIndexRoute '/': typeof legacyIndexRoute
'/main/connections': typeof mainMainConnectionsRouteRoute
'/main/dashboard': typeof mainMainDashboardRouteRoute '/main/dashboard': typeof mainMainDashboardRouteRoute
'/main/providers': typeof mainMainProvidersRouteRoute
'/editor': typeof editorEditorIndexRoute '/editor': typeof editorEditorIndexRoute
'/main': typeof mainMainIndexRoute '/main': typeof mainMainIndexRoute
'/main/profiles/inspect': typeof mainMainProfilesInspectRouteRoute '/main/profiles/inspect': typeof mainMainProfilesInspectRouteRoute
@@ -317,11 +346,15 @@ export interface FileRoutesByTo {
'/main/settings/system': typeof mainMainSettingsSystemRouteRoute '/main/settings/system': typeof mainMainSettingsSystemRouteRoute
'/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute '/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
'/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute '/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
'/main/connections': typeof mainMainConnectionsIndexRoute
'/main/logs': typeof mainMainLogsIndexRoute '/main/logs': typeof mainMainLogsIndexRoute
'/main/profiles': typeof mainMainProfilesIndexRoute '/main/profiles': typeof mainMainProfilesIndexRoute
'/main/providers': typeof mainMainProvidersIndexRoute
'/main/proxies': typeof mainMainProxiesIndexRoute '/main/proxies': typeof mainMainProxiesIndexRoute
'/main/rules': typeof mainMainRulesIndexRoute '/main/rules': typeof mainMainRulesIndexRoute
'/main/settings': typeof mainMainSettingsIndexRoute '/main/settings': typeof mainMainSettingsIndexRoute
'/main/providers/proxies/$key': typeof mainMainProvidersProxiesKeyRoute
'/main/providers/rules/$key': typeof mainMainProvidersRulesKeyRoute
'/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute '/main/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
'/main/profiles/$type': typeof mainMainProfilesTypeIndexRoute '/main/profiles/$type': typeof mainMainProfilesTypeIndexRoute
'/main/settings/debug': typeof mainMainSettingsDebugIndexRoute '/main/settings/debug': typeof mainMainSettingsDebugIndexRoute
@@ -341,11 +374,11 @@ export interface FileRoutesById {
'/(legacy)/rules': typeof legacyRulesRoute '/(legacy)/rules': typeof legacyRulesRoute
'/(legacy)/settings': typeof legacySettingsRoute '/(legacy)/settings': typeof legacySettingsRoute
'/(legacy)/': typeof legacyIndexRoute '/(legacy)/': typeof legacyIndexRoute
'/(main)/main/connections': typeof mainMainConnectionsRouteRoute '/(main)/main/connections': typeof mainMainConnectionsRouteRouteWithChildren
'/(main)/main/dashboard': typeof mainMainDashboardRouteRoute '/(main)/main/dashboard': typeof mainMainDashboardRouteRoute
'/(main)/main/logs': typeof mainMainLogsRouteRouteWithChildren '/(main)/main/logs': typeof mainMainLogsRouteRouteWithChildren
'/(main)/main/profiles': typeof mainMainProfilesRouteRouteWithChildren '/(main)/main/profiles': typeof mainMainProfilesRouteRouteWithChildren
'/(main)/main/providers': typeof mainMainProvidersRouteRoute '/(main)/main/providers': typeof mainMainProvidersRouteRouteWithChildren
'/(main)/main/proxies': typeof mainMainProxiesRouteRouteWithChildren '/(main)/main/proxies': typeof mainMainProxiesRouteRouteWithChildren
'/(main)/main/rules': typeof mainMainRulesRouteRouteWithChildren '/(main)/main/rules': typeof mainMainRulesRouteRouteWithChildren
'/(main)/main/settings': typeof mainMainSettingsRouteRouteWithChildren '/(main)/main/settings': typeof mainMainSettingsRouteRouteWithChildren
@@ -359,11 +392,15 @@ export interface FileRoutesById {
'/(main)/main/settings/system': typeof mainMainSettingsSystemRouteRoute '/(main)/main/settings/system': typeof mainMainSettingsSystemRouteRoute
'/(main)/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute '/(main)/main/settings/user-interface': typeof mainMainSettingsUserInterfaceRouteRoute
'/(main)/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute '/(main)/main/settings/web-ui': typeof mainMainSettingsWebUiRouteRoute
'/(main)/main/connections/': typeof mainMainConnectionsIndexRoute
'/(main)/main/logs/': typeof mainMainLogsIndexRoute '/(main)/main/logs/': typeof mainMainLogsIndexRoute
'/(main)/main/profiles/': typeof mainMainProfilesIndexRoute '/(main)/main/profiles/': typeof mainMainProfilesIndexRoute
'/(main)/main/providers/': typeof mainMainProvidersIndexRoute
'/(main)/main/proxies/': typeof mainMainProxiesIndexRoute '/(main)/main/proxies/': typeof mainMainProxiesIndexRoute
'/(main)/main/rules/': typeof mainMainRulesIndexRoute '/(main)/main/rules/': typeof mainMainRulesIndexRoute
'/(main)/main/settings/': typeof mainMainSettingsIndexRoute '/(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/proxies/group/$name': typeof mainMainProxiesGroupNameRoute
'/(main)/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute '/(main)/main/profiles/$type/': typeof mainMainProfilesTypeIndexRoute
'/(main)/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute '/(main)/main/settings/debug/': typeof mainMainSettingsDebugIndexRoute
@@ -400,11 +437,15 @@ export interface FileRouteTypes {
| '/main/settings/system' | '/main/settings/system'
| '/main/settings/user-interface' | '/main/settings/user-interface'
| '/main/settings/web-ui' | '/main/settings/web-ui'
| '/main/connections/'
| '/main/logs/' | '/main/logs/'
| '/main/profiles/' | '/main/profiles/'
| '/main/providers/'
| '/main/proxies/' | '/main/proxies/'
| '/main/rules/' | '/main/rules/'
| '/main/settings/' | '/main/settings/'
| '/main/providers/proxies/$key'
| '/main/providers/rules/$key'
| '/main/proxies/group/$name' | '/main/proxies/group/$name'
| '/main/profiles/$type/' | '/main/profiles/$type/'
| '/main/settings/debug/' | '/main/settings/debug/'
@@ -420,9 +461,7 @@ export interface FileRouteTypes {
| '/rules' | '/rules'
| '/settings' | '/settings'
| '/' | '/'
| '/main/connections'
| '/main/dashboard' | '/main/dashboard'
| '/main/providers'
| '/editor' | '/editor'
| '/main' | '/main'
| '/main/profiles/inspect' | '/main/profiles/inspect'
@@ -432,11 +471,15 @@ export interface FileRouteTypes {
| '/main/settings/system' | '/main/settings/system'
| '/main/settings/user-interface' | '/main/settings/user-interface'
| '/main/settings/web-ui' | '/main/settings/web-ui'
| '/main/connections'
| '/main/logs' | '/main/logs'
| '/main/profiles' | '/main/profiles'
| '/main/providers'
| '/main/proxies' | '/main/proxies'
| '/main/rules' | '/main/rules'
| '/main/settings' | '/main/settings'
| '/main/providers/proxies/$key'
| '/main/providers/rules/$key'
| '/main/proxies/group/$name' | '/main/proxies/group/$name'
| '/main/profiles/$type' | '/main/profiles/$type'
| '/main/settings/debug' | '/main/settings/debug'
@@ -473,11 +516,15 @@ export interface FileRouteTypes {
| '/(main)/main/settings/system' | '/(main)/main/settings/system'
| '/(main)/main/settings/user-interface' | '/(main)/main/settings/user-interface'
| '/(main)/main/settings/web-ui' | '/(main)/main/settings/web-ui'
| '/(main)/main/connections/'
| '/(main)/main/logs/' | '/(main)/main/logs/'
| '/(main)/main/profiles/' | '/(main)/main/profiles/'
| '/(main)/main/providers/'
| '/(main)/main/proxies/' | '/(main)/main/proxies/'
| '/(main)/main/rules/' | '/(main)/main/rules/'
| '/(main)/main/settings/' | '/(main)/main/settings/'
| '/(main)/main/providers/proxies/$key'
| '/(main)/main/providers/rules/$key'
| '/(main)/main/proxies/group/$name' | '/(main)/main/proxies/group/$name'
| '/(main)/main/profiles/$type/' | '/(main)/main/profiles/$type/'
| '/(main)/main/settings/debug/' | '/(main)/main/settings/debug/'
@@ -667,6 +714,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof mainMainProxiesIndexRouteImport preLoaderRoute: typeof mainMainProxiesIndexRouteImport
parentRoute: typeof mainMainProxiesRouteRoute parentRoute: typeof mainMainProxiesRouteRoute
} }
'/(main)/main/providers/': {
id: '/(main)/main/providers/'
path: '/'
fullPath: '/main/providers/'
preLoaderRoute: typeof mainMainProvidersIndexRouteImport
parentRoute: typeof mainMainProvidersRouteRoute
}
'/(main)/main/profiles/': { '/(main)/main/profiles/': {
id: '/(main)/main/profiles/' id: '/(main)/main/profiles/'
path: '/' path: '/'
@@ -681,6 +735,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof mainMainLogsIndexRouteImport preLoaderRoute: typeof mainMainLogsIndexRouteImport
parentRoute: typeof mainMainLogsRouteRoute 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': { '/(main)/main/settings/web-ui': {
id: '/(main)/main/settings/web-ui' id: '/(main)/main/settings/web-ui'
path: '/web-ui' path: '/web-ui'
@@ -758,6 +819,20 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof mainMainProxiesGroupNameRouteImport preLoaderRoute: typeof mainMainProxiesGroupNameRouteImport
parentRoute: typeof mainMainProxiesRouteRoute 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': { '/(main)/main/profiles/$type/detail/$uid': {
id: '/(main)/main/profiles/$type/detail/$uid' id: '/(main)/main/profiles/$type/detail/$uid'
path: '/$type/detail/$uid' path: '/$type/detail/$uid'
@@ -796,6 +871,20 @@ const legacyRouteRouteWithChildren = legacyRouteRoute._addFileChildren(
legacyRouteRouteChildren, legacyRouteRouteChildren,
) )
interface mainMainConnectionsRouteRouteChildren {
mainMainConnectionsIndexRoute: typeof mainMainConnectionsIndexRoute
}
const mainMainConnectionsRouteRouteChildren: mainMainConnectionsRouteRouteChildren =
{
mainMainConnectionsIndexRoute: mainMainConnectionsIndexRoute,
}
const mainMainConnectionsRouteRouteWithChildren =
mainMainConnectionsRouteRoute._addFileChildren(
mainMainConnectionsRouteRouteChildren,
)
interface mainMainLogsRouteRouteChildren { interface mainMainLogsRouteRouteChildren {
mainMainLogsIndexRoute: typeof mainMainLogsIndexRoute mainMainLogsIndexRoute: typeof mainMainLogsIndexRoute
} }
@@ -826,6 +915,24 @@ const mainMainProfilesRouteRouteWithChildren =
mainMainProfilesRouteRouteChildren, 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 { interface mainMainProxiesRouteRouteChildren {
mainMainProxiesIndexRoute: typeof mainMainProxiesIndexRoute mainMainProxiesIndexRoute: typeof mainMainProxiesIndexRoute
mainMainProxiesGroupNameRoute: typeof mainMainProxiesGroupNameRoute mainMainProxiesGroupNameRoute: typeof mainMainProxiesGroupNameRoute
@@ -893,11 +1000,11 @@ const mainMainSettingsRouteRouteWithChildren =
) )
interface mainRouteRouteChildren { interface mainRouteRouteChildren {
mainMainConnectionsRouteRoute: typeof mainMainConnectionsRouteRoute mainMainConnectionsRouteRoute: typeof mainMainConnectionsRouteRouteWithChildren
mainMainDashboardRouteRoute: typeof mainMainDashboardRouteRoute mainMainDashboardRouteRoute: typeof mainMainDashboardRouteRoute
mainMainLogsRouteRoute: typeof mainMainLogsRouteRouteWithChildren mainMainLogsRouteRoute: typeof mainMainLogsRouteRouteWithChildren
mainMainProfilesRouteRoute: typeof mainMainProfilesRouteRouteWithChildren mainMainProfilesRouteRoute: typeof mainMainProfilesRouteRouteWithChildren
mainMainProvidersRouteRoute: typeof mainMainProvidersRouteRoute mainMainProvidersRouteRoute: typeof mainMainProvidersRouteRouteWithChildren
mainMainProxiesRouteRoute: typeof mainMainProxiesRouteRouteWithChildren mainMainProxiesRouteRoute: typeof mainMainProxiesRouteRouteWithChildren
mainMainRulesRouteRoute: typeof mainMainRulesRouteRouteWithChildren mainMainRulesRouteRoute: typeof mainMainRulesRouteRouteWithChildren
mainMainSettingsRouteRoute: typeof mainMainSettingsRouteRouteWithChildren mainMainSettingsRouteRoute: typeof mainMainSettingsRouteRouteWithChildren
@@ -905,11 +1012,11 @@ interface mainRouteRouteChildren {
} }
const mainRouteRouteChildren: mainRouteRouteChildren = { const mainRouteRouteChildren: mainRouteRouteChildren = {
mainMainConnectionsRouteRoute: mainMainConnectionsRouteRoute, mainMainConnectionsRouteRoute: mainMainConnectionsRouteRouteWithChildren,
mainMainDashboardRouteRoute: mainMainDashboardRouteRoute, mainMainDashboardRouteRoute: mainMainDashboardRouteRoute,
mainMainLogsRouteRoute: mainMainLogsRouteRouteWithChildren, mainMainLogsRouteRoute: mainMainLogsRouteRouteWithChildren,
mainMainProfilesRouteRoute: mainMainProfilesRouteRouteWithChildren, mainMainProfilesRouteRoute: mainMainProfilesRouteRouteWithChildren,
mainMainProvidersRouteRoute: mainMainProvidersRouteRoute, mainMainProvidersRouteRoute: mainMainProvidersRouteRouteWithChildren,
mainMainProxiesRouteRoute: mainMainProxiesRouteRouteWithChildren, mainMainProxiesRouteRoute: mainMainProxiesRouteRouteWithChildren,
mainMainRulesRouteRoute: mainMainRulesRouteRouteWithChildren, mainMainRulesRouteRoute: mainMainRulesRouteRouteWithChildren,
mainMainSettingsRouteRoute: mainMainSettingsRouteRouteWithChildren, mainMainSettingsRouteRoute: mainMainSettingsRouteRouteWithChildren,
+1 -1
View File
@@ -23,7 +23,7 @@
"@vitejs/plugin-react": "5.2.0", "@vitejs/plugin-react": "5.2.0",
"ahooks": "3.9.6", "ahooks": "3.9.6",
"d3": "7.9.0", "d3": "7.9.0",
"framer-motion": "12.36.0", "framer-motion": "12.38.0",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4", "react-dom": "19.2.4",
"react-error-boundary": "6.0.0", "react-error-boundary": "6.0.0",
+2 -2
View File
@@ -5,7 +5,7 @@
"mihomo_alpha": "alpha-dd4eb63", "mihomo_alpha": "alpha-dd4eb63",
"clash_rs": "v0.9.6", "clash_rs": "v0.9.6",
"clash_premium": "2023-09-05-gdcc8d87", "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": { "arch_template": {
"mihomo": { "mihomo": {
@@ -69,5 +69,5 @@
"linux-armv7hf": "clash-rs-armv7-unknown-linux-gnueabihf" "linux-armv7hf": "clash-rs-armv7-unknown-linux-gnueabihf"
} }
}, },
"updated_at": "2026-03-15T17:40:58.103Z" "updated_at": "2026-03-16T22:28:20.426Z"
} }
+62 -59
View File
@@ -226,7 +226,7 @@ importers:
version: 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-zod-adapter': '@tanstack/router-zod-adapter':
specifier: 1.81.5 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': '@tauri-apps/api':
specifier: 2.10.1 specifier: 2.10.1
version: 2.10.1 version: 2.10.1
@@ -258,8 +258,8 @@ importers:
specifier: 1.11.20 specifier: 1.11.20
version: 1.11.20 version: 1.11.20
framer-motion: framer-motion:
specifier: 12.36.0 specifier: 12.38.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) 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: i18next:
specifier: 25.8.18 specifier: 25.8.18
version: 25.8.18(typescript@5.9.3) version: 25.8.18(typescript@5.9.3)
@@ -334,8 +334,8 @@ importers:
specifier: 11.14.0 specifier: 11.14.0
version: 11.14.0(@types/react@19.2.14)(react@19.2.4) version: 11.14.0(@types/react@19.2.14)(react@19.2.4)
'@iconify/json': '@iconify/json':
specifier: 2.2.450 specifier: 2.2.451
version: 2.2.450 version: 2.2.451
'@monaco-editor/react': '@monaco-editor/react':
specifier: 4.7.0 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) 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 specifier: 5.90.21
version: 5.90.21(react@19.2.4) version: 5.90.21(react@19.2.4)
'@tanstack/react-router': '@tanstack/react-router':
specifier: 1.167.3 specifier: 1.167.4
version: 1.167.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/react-router-devtools': '@tanstack/react-router-devtools':
specifier: 1.166.9 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': '@tanstack/router-plugin':
specifier: 1.166.12 specifier: 1.166.13
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)) 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': '@tauri-apps/plugin-clipboard-manager':
specifier: 2.3.2 specifier: 2.3.2
version: 2.3.2 version: 2.3.2
@@ -400,8 +400,8 @@ importers:
specifier: 2.1.1 specifier: 2.1.1
version: 2.1.1 version: 2.1.1
core-js: core-js:
specifier: 3.48.0 specifier: 3.49.0
version: 3.48.0 version: 3.49.0
filesize: filesize:
specifier: 11.0.13 specifier: 11.0.13
version: 11.0.13 version: 11.0.13
@@ -487,8 +487,8 @@ importers:
specifier: 7.9.0 specifier: 7.9.0
version: 7.9.0 version: 7.9.0
framer-motion: framer-motion:
specifier: 12.36.0 specifier: 12.38.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) 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: react:
specifier: 19.2.4 specifier: 19.2.4
version: 19.2.4 version: 19.2.4
@@ -1704,8 +1704,8 @@ packages:
prettier-plugin-ember-template-tag: prettier-plugin-ember-template-tag:
optional: true optional: true
'@iconify/json@2.2.450': '@iconify/json@2.2.451':
resolution: {integrity: sha512-dltwhGrVC1guhfqIiFJ+jH21aO1C9RRvIOsAYdmsqKOr3vfMkKnwji4pYpxPEEEg3YQCvVDFpyKCKbfI8Gl/ow==} resolution: {integrity: sha512-dDAPVdlpXdjtqYReacSWtwa3Mix0Cg4ezZ5SORLjLqyPSQttaHn03sjndnqgXfeY1zckOuLUgYUMLiZfIoD2oQ==}
'@iconify/types@2.0.0': '@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -3869,8 +3869,8 @@ packages:
'@tanstack/router-core': '@tanstack/router-core':
optional: true optional: true
'@tanstack/react-router@1.167.3': '@tanstack/react-router@1.167.4':
resolution: {integrity: sha512-1qbSy4r+O7IBdmPLlcKsjB041Gq2MMnIEAYSGIjaMZIL4duUIQnOWLw4jTfjKil/IJz/9rO5JcvrbxOG5UTSdg==} resolution: {integrity: sha512-VpbZh382zX3WF4+X2Z+EUyd8eJhJyjg9C6ByYwrVZiWbhgbMK4+zQQIG2+lCAlIlDi7SV8fDcGL09NA8Z2kpGQ==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
peerDependencies: peerDependencies:
react: '>=18.0.0 || >=19.0.0' 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: ^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 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
'@tanstack/router-core@1.167.3': '@tanstack/router-core@1.167.4':
resolution: {integrity: sha512-M/CxrTGKk1fsySJjd+Pzpbi3YLDz+cJSutDjSTMy12owWlOgHV/I6kzR0UxyaBlHraM6XgMHNA0XdgsS1fa4Nw==} resolution: {integrity: sha512-Gk5V9Zr5JFJ4SbLyCheQLJ3MnXddccENPA+DJRz+9g3QxtN8DJB8w8KCUCgDeYlWp4LvmO4nX3fy3tupqVP2Pw==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
hasBin: true
'@tanstack/router-devtools-core@1.166.9': '@tanstack/router-devtools-core@1.166.9':
resolution: {integrity: sha512-PNlA7GmOUX9wY7LUG709Pk3Lg33dfHBztQwzjzrOiOsuf4ggp2R6bwarF8nYGNjG79z/MaB5PN+5yvkCVk8jGw==} resolution: {integrity: sha512-PNlA7GmOUX9wY7LUG709Pk3Lg33dfHBztQwzjzrOiOsuf4ggp2R6bwarF8nYGNjG79z/MaB5PN+5yvkCVk8jGw==}
@@ -3915,16 +3916,17 @@ packages:
csstype: csstype:
optional: true optional: true
'@tanstack/router-generator@1.166.11': '@tanstack/router-generator@1.166.12':
resolution: {integrity: sha512-Q/49wxURbft1oNOvo/eVAWZq/lNLK3nBGlavqhLToAYXY6LCzfMtRlE/y3XPHzYC9pZc09u5jvBR1k1E4hyGDQ==} resolution: {integrity: sha512-2HdxSTbCkbU9JeYogKVigIlXoLtIJE1x5rbEov+ZLTPjGCO9kicNQuljqg9Js+u2/ahtWewNrE5u1QCAyxmpIg==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
'@tanstack/router-plugin@1.166.12': '@tanstack/router-plugin@1.166.13':
resolution: {integrity: sha512-PYsnN6goK6zBaVo63UVKjofv69+HHMKRQXymwN55JYKguNnNR8OZ6E12icPb0Olc5uIpPiGz1YI2+rbpmNKGHA==} resolution: {integrity: sha512-xG3ND3AlMe6DN9PihJAYUbQJevqJvVdzN1QpZbfU1/jkHurL97ynP2yXfmMTh8Qgi1K+SWRko4bi7iZlYP9SUw==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
hasBin: true
peerDependencies: peerDependencies:
'@rsbuild/core': '>=1.0.2' '@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: '>=5.0.0 || >=6.0.0 || >=7.0.0'
vite-plugin-solid: ^2.11.10 vite-plugin-solid: ^2.11.10
webpack: '>=5.92.0' webpack: '>=5.92.0'
@@ -3964,9 +3966,10 @@ packages:
'@tanstack/virtual-core@3.13.9': '@tanstack/virtual-core@3.13.9':
resolution: {integrity: sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==} resolution: {integrity: sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==}
'@tanstack/virtual-file-routes@1.161.6': '@tanstack/virtual-file-routes@1.161.7':
resolution: {integrity: sha512-EGWs9yvJA821pUkwkiZLQW89CzUumHyJy8NKq229BubyoWXfDw1oWnTJYSS/hhbLiwP9+KpopjeF5wWwnCCyeQ==} resolution: {integrity: sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
hasBin: true
'@taplo/core@0.2.0': '@taplo/core@0.2.0':
resolution: {integrity: sha512-r8bl54Zj1In3QLkiW/ex694bVzpPJ9EhwqT9xkcUVODnVUGirdB1JTsmiIv0o1uwqZiwhi8xNnTOQBRQCpizrQ==} resolution: {integrity: sha512-r8bl54Zj1In3QLkiW/ex694bVzpPJ9EhwqT9xkcUVODnVUGirdB1JTsmiIv0o1uwqZiwhi8xNnTOQBRQCpizrQ==}
@@ -4929,8 +4932,8 @@ packages:
core-js-compat@3.44.0: core-js-compat@3.44.0:
resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==} resolution: {integrity: sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==}
core-js@3.48.0: core-js@3.49.0:
resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
core-util-is@1.0.3: core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -5476,8 +5479,8 @@ packages:
fraction.js@5.3.4: fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
framer-motion@12.36.0: framer-motion@12.38.0:
resolution: {integrity: sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==} resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==}
peerDependencies: peerDependencies:
'@emotion/is-prop-valid': '*' '@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0
@@ -6320,8 +6323,8 @@ packages:
peerDependencies: peerDependencies:
monaco-editor: '>=0.36' monaco-editor: '>=0.36'
motion-dom@12.36.0: motion-dom@12.38.0:
resolution: {integrity: sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA==} resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==}
motion-utils@12.36.0: motion-utils@12.36.0:
resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==} resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==}
@@ -9339,7 +9342,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@iconify/json@2.2.450': '@iconify/json@2.2.451':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
pathe: 2.0.3 pathe: 2.0.3
@@ -11364,22 +11367,22 @@ snapshots:
'@tanstack/query-core': 5.90.20 '@tanstack/query-core': 5.90.20
react: 19.2.4 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: 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)
'@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)
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
optionalDependencies: optionalDependencies:
'@tanstack/router-core': 1.167.3 '@tanstack/router-core': 1.167.4
transitivePeerDependencies: transitivePeerDependencies:
- csstype - 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: dependencies:
'@tanstack/history': 1.161.6 '@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/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 isbot: 5.1.28
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
@@ -11411,7 +11414,7 @@ snapshots:
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(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: dependencies:
'@tanstack/history': 1.161.6 '@tanstack/history': 1.161.6
'@tanstack/store': 0.9.1 '@tanstack/store': 0.9.1
@@ -11421,20 +11424,20 @@ snapshots:
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
tiny-warning: 1.0.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: dependencies:
'@tanstack/router-core': 1.167.3 '@tanstack/router-core': 1.167.4
clsx: 2.1.1 clsx: 2.1.1
goober: 2.1.16(csstype@3.2.3) goober: 2.1.16(csstype@3.2.3)
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
optionalDependencies: optionalDependencies:
csstype: 3.2.3 csstype: 3.2.3
'@tanstack/router-generator@1.166.11': '@tanstack/router-generator@1.166.12':
dependencies: dependencies:
'@tanstack/router-core': 1.167.3 '@tanstack/router-core': 1.167.4
'@tanstack/router-utils': 1.161.6 '@tanstack/router-utils': 1.161.6
'@tanstack/virtual-file-routes': 1.161.6 '@tanstack/virtual-file-routes': 1.161.7
prettier: 3.8.1 prettier: 3.8.1
recast: 0.23.11 recast: 0.23.11
source-map: 0.7.4 source-map: 0.7.4
@@ -11443,7 +11446,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - 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: dependencies:
'@babel/core': 7.29.0 '@babel/core': 7.29.0
'@babel/plugin-syntax-jsx': 7.27.1(@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/template': 7.28.6
'@babel/traverse': 7.29.0 '@babel/traverse': 7.29.0
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@tanstack/router-core': 1.167.3 '@tanstack/router-core': 1.167.4
'@tanstack/router-generator': 1.166.11 '@tanstack/router-generator': 1.166.12
'@tanstack/router-utils': 1.161.6 '@tanstack/router-utils': 1.161.6
'@tanstack/virtual-file-routes': 1.161.6 '@tanstack/virtual-file-routes': 1.161.7
chokidar: 3.6.0 chokidar: 3.6.0
unplugin: 2.3.11 unplugin: 2.3.11
zod: 3.25.76 zod: 3.25.76
optionalDependencies: 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) 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: transitivePeerDependencies:
- supports-color - supports-color
@@ -11478,9 +11481,9 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - 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: 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 zod: 4.3.6
'@tanstack/store@0.9.1': {} '@tanstack/store@0.9.1': {}
@@ -11491,7 +11494,7 @@ snapshots:
'@tanstack/virtual-core@3.13.9': {} '@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': {} '@taplo/core@0.2.0': {}
@@ -12053,7 +12056,7 @@ snapshots:
babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0)
browserslist: 4.25.1 browserslist: 4.25.1
browserslist-to-esbuild: 2.1.1(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 magic-string: 0.30.17
regenerator-runtime: 0.14.1 regenerator-runtime: 0.14.1
systemjs: 6.15.1 systemjs: 6.15.1
@@ -12534,7 +12537,7 @@ snapshots:
dependencies: dependencies:
browserslist: 4.28.1 browserslist: 4.28.1
core-js@3.48.0: {} core-js@3.49.0: {}
core-util-is@1.0.3: {} core-util-is@1.0.3: {}
@@ -13094,9 +13097,9 @@ snapshots:
fraction.js@5.3.4: {} 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: dependencies:
motion-dom: 12.36.0 motion-dom: 12.38.0
motion-utils: 12.36.0 motion-utils: 12.36.0
tslib: 2.8.1 tslib: 2.8.1
optionalDependencies: optionalDependencies:
@@ -14013,7 +14016,7 @@ snapshots:
vscode-uri: 3.0.8 vscode-uri: 3.0.8
yaml: 2.8.1 yaml: 2.8.1
motion-dom@12.36.0: motion-dom@12.38.0:
dependencies: dependencies:
motion-utils: 12.36.0 motion-utils: 12.36.0
+157 -6
View File
@@ -90,6 +90,29 @@ func NewClient(conf *config.Config) (c *Client, err error) {
Net: "tcp", Net: "tcp",
Timeout: time.Duration(conf.Other.Timeout) * time.Second, 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 { for _, addr := range conf.Listen {
c.udpServers = append(c.udpServers, &dns.Server{ c.udpServers = append(c.udpServers, &dns.Server{
Addr: addr, Addr: addr,
@@ -120,6 +143,38 @@ func NewClient(conf *config.Config) (c *Client, err error) {
PreferGo: true, PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
var d net.Dialer 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) numServers := len(c.bootstrap)
bootstrap := c.bootstrap[rand.Intn(numServers)] bootstrap := c.bootstrap[rand.Intn(numServers)]
conn, err := d.DialContext(ctx, network, bootstrap) conn, err := d.DialContext(ctx, network, bootstrap)
@@ -235,14 +290,72 @@ func (c *Client) newHTTPClient() error {
if c.httpTransport != nil { if c.httpTransport != nil {
c.httpTransport.CloseIdleConnections() 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, Timeout: time.Duration(c.conf.Other.Timeout) * time.Second,
KeepAlive: 30 * time.Second, KeepAlive: 30 * time.Second,
// DualStack: true, Resolver: c.bootstrapResolver,
Resolver: c.bootstrapResolver,
} }
c.httpTransport = &http.Transport{ 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, ExpectContinueTimeout: 1 * time.Second,
IdleConnTimeout: 90 * time.Second, IdleConnTimeout: 90 * time.Second,
MaxIdleConns: 100, MaxIdleConns: 100,
@@ -251,15 +364,18 @@ func (c *Client) newHTTPClient() error {
TLSHandshakeTimeout: time.Duration(c.conf.Other.Timeout) * time.Second, TLSHandshakeTimeout: time.Duration(c.conf.Other.Timeout) * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: c.conf.Other.TLSInsecureSkipVerify}, TLSClientConfig: &tls.Config{InsecureSkipVerify: c.conf.Other.TLSInsecureSkipVerify},
} }
if c.conf.Other.NoIPv6 { if c.conf.Other.NoIPv6 {
originalDial := c.httpTransport.DialContext
c.httpTransport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { c.httpTransport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
if strings.HasPrefix(network, "tcp") { if strings.HasPrefix(network, "tcp") {
network = "tcp4" 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 { if err != nil {
return err return err
} }
@@ -485,3 +601,38 @@ func (c *Client) findClientIP(w dns.ResponseWriter, r *dns.Msg) (ednsClientAddre
} }
return 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"` Bootstrap []string `toml:"bootstrap"`
Passthrough []string `toml:"passthrough"` Passthrough []string `toml:"passthrough"`
Timeout uint `toml:"timeout"` Timeout uint `toml:"timeout"`
Interface string `toml:"interface"`
NoCookies bool `toml:"no_cookies"` NoCookies bool `toml:"no_cookies"`
NoECS bool `toml:"no_ecs"` NoECS bool `toml:"no_ecs"`
NoIPv6 bool `toml:"no_ipv6"` NoIPv6 bool `toml:"no_ipv6"`
@@ -97,6 +97,11 @@ passthrough = [
# Timeout for upstream request in seconds # Timeout for upstream request in seconds
timeout = 30 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 # Disable HTTP Cookies
# #
# Cookies may be useful if your upstream resolver is protected by some # Cookies may be useful if your upstream resolver is protected by some
@@ -1,4 +1,39 @@
# luci-app-argone-config # 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
```
+20 -121
View File
@@ -1,128 +1,27 @@
<!-- markdownlint-configure-file { #### argon 原作者是jerrykuku
"MD013": { #### 改argone是为了编译方便
"code_blocks": false,
"tables": false,
"line_length":200
},
"MD033": false,
"MD041": false
} -->
[license]: /LICENSE + main 分支支持 luci-18.06
[license-badge]: https://img.shields.io/github/license/jerrykuku/luci-theme-argon?style=flat-square&a=1 ```bash
[prs]: https://github.com/jerrykuku/luci-theme-argone/pulls git clone https://github.com/kenzok78/luci-theme-argone
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square ```
[issues]: https://github.com/jerrykuku/luci-theme-argone/issues/new + 23 分支支持最新 luci
[issues-badge]: https://img.shields.io/badge/Issues-welcome-brightgreen.svg?style=flat-square ```bash
[release]: https://github.com/jerrykuku/luci-theme-argone/releases git clone -b 23 https://github.com/kenzok78/luci-theme-argone
[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"> ### 一键安装 (18.06 / main)
<img src="https://raw.githubusercontent.com/jerrykuku/staff/master/argon_title4.svg">
# A brand new OpenWrt LuCI theme ```sh
### • This branch only matches [Lean's LEDE ( LuCI 18.06 )][lede] / [OpenWrt LuCI 18.06][official-luci-18.06] • 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
Argon is **a clean and tidy OpenWrt LuCI theme** that allows<br/> opkg install luci-theme-argone_1.8.4_all.ipk
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 )
```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
``` ```
### Install for LuCI 18.06 ( Lean's LEDE ) ### 一键安装 (23 branch / 最新 luci)
```bash ```sh
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 wget --no-check-certificate -O luci-theme-argone_2.4.3_all.ipk \
opkg install luci-theme-argon*.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
``` ```
### Install the settings plugin with extensions - 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
opkg install luci-app-argone-config*.ipk
```
## Screenshots
![desktop](/Screenshots/screenshot_pc.jpg)
![mobile](/Screenshots/screenshot_phone.jpg)
## 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
```
## 屏幕截图
![desktop](/Screenshots/screenshot_pc.jpg)
![mobile](/Screenshots/screenshot_phone.jpg)
## 贡献者
<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> Copyright 2020 Jerrykuku <jerrykuku@qq.com>
Have a bug? Please create an issue here on GitHub! 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: luci-theme-bootstrap:
Copyright 2008 Steven Barth <steven@midlink.org> Copyright 2008 Steven Barth <steven@midlink.org>
@@ -43,7 +43,7 @@
<div class="ftc"> <div class="ftc">
<a class="luci-link" href="https://github.com/openwrt/luci" target="_blank">Powered by <%= ver.luciname %> <a class="luci-link" href="https://github.com/openwrt/luci" target="_blank">Powered by <%= ver.luciname %>
(<%= ver.luciversion %>)</a> / (<%= 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 %> <%= ver.distversion %>
<% if #categories > 1 then %> <% if #categories > 1 then %>
<ul class="breadcrumb pull-right" id="modemenu"> <ul class="breadcrumb pull-right" id="modemenu">
@@ -5,7 +5,7 @@
Copyright 2020 Jerryk <jerrykuku@gmail.com> Copyright 2020 Jerryk <jerrykuku@gmail.com>
Have a bug? Please create an issue here on GitHub! 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: luci-theme-bootstrap:
Copyright 2008 Steven Barth <steven@midlink.org> Copyright 2008 Steven Barth <steven@midlink.org>
@@ -5,7 +5,7 @@
Copyright 2020 Jerrykuku <jerrykuku@qq.com> Copyright 2020 Jerrykuku <jerrykuku@qq.com>
Have a bug? Please create an issue here on GitHub! 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: luci-theme-bootstrap:
Copyright 2008 Steven Barth <steven@midlink.org> Copyright 2008 Steven Barth <steven@midlink.org>
@@ -5,7 +5,7 @@
Copyright 2021 Jerryk <jerrykuku@gmail.com> Copyright 2021 Jerryk <jerrykuku@gmail.com>
Have a bug? Please create an issue here on GitHub! 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: luci-theme-bootstrap:
Copyright 2008 Steven Barth <steven@midlink.org> Copyright 2008 Steven Barth <steven@midlink.org>
@@ -4,8 +4,8 @@
# the script will be excuted when `argone.@global[0].bing_background == '1'` # the script will be excuted when `argone.@global[0].bing_background == '1'`
# defaults to 'bing' to be compatible with old config # defaults to 'bing' to be compatible with old config
WEB_PIC_SRC=$(uci -q get argone.@global[0].online_wallpaper || echo 'bing') WEB_PIC_SRC=$(uci -q get argone.@global[0].online_wallpaper || echo 'bing')
CACHE=/var/run/argon_${WEB_PIC_SRC}.url CACHE=/var/run/argone_${WEB_PIC_SRC}.url
WRLOCK=/var/lock/argon_${WEB_PIC_SRC}.lock WRLOCK=/var/lock/argone_${WEB_PIC_SRC}.lock
fetch_pic_url() { fetch_pic_url() {
case $WEB_PIC_SRC in case $WEB_PIC_SRC in
+1 -1
View File
@@ -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 menuconfig # choose LUCI->Theme->Luci-theme-design
make V=s make V=s
``` ```
+4 -4
View File
@@ -17,20 +17,20 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Setup Docker Buildx - name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v4
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata - name: Docker metadata
id: metadata id: metadata
uses: docker/metadata-action@v5 uses: docker/metadata-action@v6
with: with:
images: ghcr.io/${{ github.repository_owner }}/${{ matrix.bin }}-rust images: ghcr.io/${{ github.repository_owner }}/${{ matrix.bin }}-rust
- name: Build and release Docker images - name: Build and release Docker images
uses: docker/build-push-action@v6 uses: docker/build-push-action@v7
with: with:
platforms: linux/386,linux/amd64,linux/arm64/v8 platforms: linux/386,linux/amd64,linux/arm64/v8
target: ${{ matrix.bin }} target: ${{ matrix.bin }}
+44 -32
View File
@@ -111,7 +111,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [ dependencies = [
"anstyle", "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-query",
"anstyle-wincon", "anstyle-wincon",
"colorchoice", "colorchoice",
@@ -134,6 +149,15 @@ dependencies = [
"utf8parse", "utf8parse",
] ]
[[package]]
name = "anstyle-parse"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.1.5" version = "1.1.5"
@@ -585,20 +609,20 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.60" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.60" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [ dependencies = [
"anstream", "anstream 1.0.0",
"anstyle", "anstyle",
"clap_lex", "clap_lex",
"strsim", "strsim",
@@ -976,7 +1000,7 @@ version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d"
dependencies = [ dependencies = [
"anstream", "anstream 0.6.21",
"anstyle", "anstyle",
"env_filter", "env_filter",
"jiff", "jiff",
@@ -996,7 +1020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -1749,9 +1773,9 @@ dependencies = [
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.11.0" version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]] [[package]]
name = "iprange" name = "iprange"
@@ -2194,18 +2218,6 @@ dependencies = [
"tempfile", "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]] [[package]]
name = "nix" name = "nix"
version = "0.31.2" version = "0.31.2"
@@ -2639,7 +2651,7 @@ dependencies = [
"once_cell", "once_cell",
"socket2 0.5.10", "socket2 0.5.10",
"tracing", "tracing",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -2916,7 +2928,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -2975,7 +2987,7 @@ dependencies = [
"security-framework 3.5.1", "security-framework 3.5.1",
"security-framework-sys", "security-framework-sys",
"webpki-root-certs", "webpki-root-certs",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -3332,7 +3344,7 @@ dependencies = [
"lru_time_cache", "lru_time_cache",
"mime", "mime",
"native-tls", "native-tls",
"nix 0.31.2", "nix",
"pin-project", "pin-project",
"rand 0.10.0", "rand 0.10.0",
"regex", "regex",
@@ -3621,7 +3633,7 @@ dependencies = [
"getrandom 0.3.4", "getrandom 0.3.4",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -3753,9 +3765,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.49.0" version = "1.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
@@ -3968,9 +3980,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]] [[package]]
name = "tun" name = "tun"
version = "0.8.5" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35f176015650e3bd849e85808d809e5b54da2ba7df983c5c3b601a2a8f1095e" checksum = "87dce40a7bfb165d8eb8e96f7463230f3d91b56aae21e0f1e56db60161962e1a"
dependencies = [ dependencies = [
"bytes", "bytes",
"cfg-if", "cfg-if",
@@ -3979,7 +3991,7 @@ dependencies = [
"ipnet", "ipnet",
"libc", "libc",
"log", "log",
"nix 0.30.1", "nix",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"tokio-util", "tokio-util",
+1 -1
View File
@@ -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 ARG TARGETARCH
+1 -1
View File
@@ -10,7 +10,7 @@ PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/pdnsd/tar.gz/$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/pdnsd/tar.gz/$(PKG_VERSION)?
PKG_HASH:=a40243e2eedc9645316e0e5055f71495dc7ec821d1ced393834dbf93cb7fc3a3 PKG_HASH:=28929bfd7874fd86872dc1bf4cd01103d7ebbdad6a457ccd9a8947a2819440be
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1 PKG_INSTALL:=1
+4 -4
View File
@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=redsocks2 PKG_NAME:=redsocks2
PKG_VERSION:=0.71 PKG_VERSION:=0.73
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=redsocks-$(PKG_VERSION).tar.gz PKG_SOURCE:=redsocks-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/semigodking/redsocks/tar.gz/release-$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/redsocks/tar.gz/release-$(PKG_VERSION)?
PKG_HASH:=4ec470f47461ce5accffbefd56ead019ecd19b207ab8599461481c3d7e083bef PKG_HASH:=0c9a50b6039cd9fe078a3da5fb5317e38fe52ec59fba7fa9abdf3b002471ebfd
PKG_BUILD_DIR:=$(BUILD_DIR)/redsocks-release-$(PKG_VERSION) PKG_BUILD_DIR:=$(BUILD_DIR)/redsocks-release-$(PKG_VERSION)
PKG_MAINTAINER:=semigodking <semigodking@gmail.com> PKG_MAINTAINER:=semigodking <semigodking@gmail.com>
@@ -27,7 +27,7 @@ define Package/redsocks2
CATEGORY:=Network CATEGORY:=Network
SUBMENU:=Web Servers/Proxies SUBMENU:=Web Servers/Proxies
TITLE:=Redirect TCP connection to proxy server TITLE:=Redirect TCP connection to proxy server
URL:=https://github.com/semigodking/redsocks URL:=https://github.com/kenzok8/redsocks
DEPENDS:=+libevent2 +libopenssl DEPENDS:=+libevent2 +libopenssl
endef endef
+21 -6
View File
@@ -1,20 +1,20 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=shadowsocksr-libev PKG_NAME:=shadowsocksr-libev
PKG_VERSION:=2.5.8 PKG_VERSION:=2.5.9
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/shadowsocksr-libev/tar.gz/v$(PKG_VERSION)? 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:=GPL-3.0
PKG_LICENSE_FILES:=LICENSE PKG_LICENSE_FILES:=LICENSE
PKG_FIXUP:=autoreconf
PKG_USE_MIPS16:=0 PKG_USE_MIPS16:=0
PKG_BUILD_FLAGS:=no-mips16 PKG_BUILD_FLAGS:=no-mips16
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1 PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@@ -35,7 +35,7 @@ define Package/shadowsocksr-libev/Default
endef endef
endef endef
SHADOWSOCKSR_COMPONENTS:=check local nat redir server SHADOWSOCKSR_COMPONENTS:=local nat redir server
define shadowsocksr-libev/templates define shadowsocksr-libev/templates
$(foreach component,$(SHADOWSOCKSR_COMPONENTS), $(foreach component,$(SHADOWSOCKSR_COMPONENTS),
$(call Package/shadowsocksr-libev/Default,$(component)) $(call Package/shadowsocksr-libev/Default,$(component))
@@ -43,16 +43,31 @@ define shadowsocksr-libev/templates
endef endef
$(eval $(call shadowsocksr-libev/templates)) $(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 += \ CONFIGURE_ARGS += \
--disable-documentation \ --disable-documentation \
--disable-ssp \ --disable-ssp \
--disable-assert \ --disable-assert \
--enable-system-shared-lib --enable-system-shared-lib \
--with-pcre=$(STAGING_DIR)/usr
TARGET_CFLAGS += -flto TARGET_CFLAGS += -flto
TARGET_CFLAGS += -Wno-error=use-after-free TARGET_CFLAGS += -Wno-error=use-after-free
TARGET_CPPFLAGS += -DPCRE2_CODE_UNIT_WIDTH=8
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
$(foreach component,$(SHADOWSOCKSR_COMPONENTS), \ $(foreach component,$(SHADOWSOCKSR_COMPONENTS), \
$(eval $(call BuildPackage,shadowsocksr-libev-ssr-$(component))) \ $(eval $(call BuildPackage,shadowsocksr-libev-ssr-$(component))) \
) )
@@ -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@:>@.])])
@@ -4,17 +4,17 @@
plugin->client_decode = tls12_ticket_auth_client_decode; plugin->client_decode = tls12_ticket_auth_client_decode;
return plugin; return plugin;
- /*} else if (strcmp(plugin_name, "verify_simple") == 0) { - /*} else if (strcmp(plugin_name, "verify_simple") == 0) {
+ } else if (strcmp(plugin_name, "verify_simple") == 0) { + } else if (strcmp(plugin_name, "verify_simple") == 0) {
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class));
plugin->init_data = init_data; plugin->init_data = init_data;
plugin->new_obfs = verify_simple_new_obfs; plugin->new_obfs = verify_simple_new_obfs;
@@ -115,7 +115,7 @@ obfs_class *new_obfs_class(const char *p @@ -115,7 +115,7 @@ obfs_class *new_obfs_class(const char *p
plugin->client_udp_pre_encrypt = NULL; plugin->client_udp_pre_encrypt = NULL;
plugin->client_udp_post_decrypt = NULL; plugin->client_udp_post_decrypt = NULL;
- return plugin;*/ - return plugin;*/
+ return plugin; + return plugin;
} else if (strcmp(plugin_name, "auth_sha1") == 0) { } else if (strcmp(plugin_name, "auth_sha1") == 0) {
obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class));
plugin->init_data = auth_simple_init_data; plugin->init_data = auth_simple_init_data;
@@ -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 "includeobfs.h" // I don't want to modify makefile
#include "jconf.h" #include "jconf.h"
@@ -101,18 +109,28 @@ static struct cork_dllist inactive_profi @@ -114,21 +114,23 @@
static listen_ctx_t *current_profile; static listen_ctx_t *current_profile;
static struct cork_dllist all_connections; static struct cork_dllist all_connections;
@@ -65,28 +65,26 @@
- error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen); - error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
- if (error) { // Didn't find a proper way to detect IP version. - 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); - error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
-#endif
- if (error) { - if (error) {
- return -1; - return -1;
- } + if (tcp_tproxy) {
+ if (tcp_tproxy) {
+ error = getsockname(fd, (void *)destaddr, &socklen); + error = getsockname(fd, (void *)destaddr, &socklen);
+ } else { + } else {
+ error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen); + error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
+ if (error) { // Didn't find a proper way to detect IP version. + if (error) { // Didn't find a proper way to detect IP version.
+ error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen); + error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
+ if (error) { + if (error) {
+ return -1; + return -1;
+ } + }
+ } }
+ }
+
+ if (error) {
+ return -1;
} }
return 0; return 0;
} @@ -164,6 +174,23 @@ create_and_bind(const char *addr, const
@@ -164,6 +182,23 @@ create_and_bind(const char *addr, const
if (err == 0) { if (err == 0) {
LOGI("tcp port reuse enabled"); LOGI("tcp port reuse enabled");
} }
@@ -110,7 +108,7 @@
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) { if (s == 0) {
@@ -1094,7 +1129,7 @@ main(int argc, char **argv) @@ -1094,7 +1121,7 @@ main(int argc, char **argv)
USE_TTY(); USE_TTY();
@@ -119,7 +117,7 @@
"O:o:G:g:", "O:o:G:g:",
long_options, &option_index)) != -1) { long_options, &option_index)) != -1) {
switch (c) { switch (c) {
@@ -1169,6 +1204,9 @@ main(int argc, char **argv) @@ -1169,6 +1196,9 @@ main(int argc, char **argv)
case 'U': case 'U':
mode = UDP_ONLY; mode = UDP_ONLY;
break; break;
@@ -129,7 +127,7 @@
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
@@ -1255,6 +1293,9 @@ main(int argc, char **argv) @@ -1255,6 +1285,9 @@ main(int argc, char **argv)
if (mode == TCP_ONLY) { if (mode == TCP_ONLY) {
mode = conf->mode; 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
+2 -2
View File
@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=simple-obfs PKG_NAME:=simple-obfs
PKG_VERSION:=0.0.9 PKG_VERSION:=0.0.10
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/simple-obfs/tar.gz/v$(PKG_VERSION)? 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:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE PKG_LICENSE_FILES:=LICENSE
+2 -2
View File
@@ -7,12 +7,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=v2dat PKG_NAME:=v2dat
PKG_VERSION:=0.1.1 PKG_VERSION:=0.1.2
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/v2dat/tar.gz/v$(PKG_VERSION)? 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_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_LICENSE:=GPL-3.0 PKG_LICENSE:=GPL-3.0
+1 -1
View File
@@ -39,7 +39,7 @@ require (
go.starlark.net v0.0.0-20230612165344-9532f5667272 go.starlark.net v0.0.0-20230612165344-9532f5667272
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
golang.org/x/crypto v0.49.0 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/sync v0.20.0
golang.org/x/sys v0.42.0 golang.org/x/sys v0.42.0
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb
+2 -2
View File
@@ -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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= 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.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.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= 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-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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+21 -2
View File
@@ -7,9 +7,28 @@ import (
) )
type GunConfig struct { type GunConfig struct {
ServiceName string `json:"serviceName"` 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) { 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
} }
-1
View File
@@ -213,7 +213,6 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
rawConn.Close() rawConn.Close()
return nil, nil, err return nil, nil, err
} }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
rawConn.Close() 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)), rxReplayDetector: replaydetector.New(1024, ^uint64(0)),
} }
c.trackedServerSessionID[string(resp.SessionID[:])] = state 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.sessionMapAlias[string(resp.SessionID[:])] = string(resp.ClientSessionID[:])
c.parent.locker.RUnlock() c.parent.locker.Unlock()
trackedState = state trackedState = state
} else { } else {
trackedState = trackedStateReceived 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 package grpc
import ( import (
@@ -17,11 +23,15 @@ const (
) )
type Config struct { type Config struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` 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"` ServiceName string `protobuf:"bytes,2,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"`
unknownFields protoimpl.UnknownFields IdleTimeout int32 `protobuf:"varint,3,opt,name=idle_timeout,json=idleTimeout,proto3" json:"idle_timeout,omitempty"`
sizeCache protoimpl.SizeCache 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
} }
func (x *Config) Reset() { func (x *Config) Reset() {
@@ -68,14 +78,46 @@ func (x *Config) GetServiceName() string {
return "" 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 var File_transport_internet_grpc_config_proto protoreflect.FileDescriptor
const file_transport_internet_grpc_config_proto_rawDesc = "" + const file_transport_internet_grpc_config_proto_rawDesc = "" +
"\n" + "\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" + "\x06Config\x12\x12\n" +
"\x04host\x18\x01 \x01(\tR\x04host\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" + "\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" "&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 host = 1;
string service_name = 2; string service_name = 2;
int32 idle_timeout = 3;
int32 health_check_timeout = 4;
bool permit_without_stream = 5;
int32 initial_windows_size = 6;
} }
+49 -37
View File
@@ -14,6 +14,7 @@ import (
"google.golang.org/grpc/connectivity" "google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
core "github.com/v2fly/v2ray-core/v5" core "github.com/v2fly/v2ray-core/v5"
"github.com/v2fly/v2ray-core/v5/common" "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) { func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
grpcSettings := streamSettings.ProtocolSettings.(*Config) grpcSettings := streamSettings.ProtocolSettings.(*Config)
config := tls.ConfigFromStreamSettings(streamSettings) conn, canceller, err := getGrpcClient(ctx, dest, 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)
if err != nil { if err != nil {
return nil, newError("Cannot dial grpc").Base(err) 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 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) transportEnvironment := envctx.EnvironmentFromContext(ctx).(environment.TransportEnvironment)
state, err := transportEnvironment.TransientStorage().Get(ctx, "grpc-transport-connection-state") 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 { if err != nil {
state = &transportConnectionState{} state = &transportConnectionState{}
transportEnvironment.TransientStorage().Put(ctx, "grpc-transport-connection-state", state) 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( conn, err := grpc.NewClient(
dest.Address.String()+":"+dest.Port.String(), dest.Address.String()+":"+dest.Port.String(),
dialOption, dialOptions...,
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(),
) )
canceller = func() { canceller = func() {
stateTyped.scopedDialerAccess.Lock() stateTyped.scopedDialerAccess.Lock()
+7 -7
View File
@@ -231,7 +231,7 @@ jobs:
[[ "${version}" != "${downgraded_version}" ]] [[ "${version}" != "${downgraded_version}" ]]
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: build-bin-${{ github.job }} name: build-bin-${{ github.job }}
path: | path: |
@@ -267,7 +267,7 @@ jobs:
- name: Set up QEMU - name: Set up QEMU
if: matrix.qemu_platform if: matrix.qemu_platform
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
with: with:
image: tonistiigi/binfmt:qemu-v10.0.4-56@sha256:30cc9a4d03765acac9be2ed0afc23af1ad018aed2c28ea4be8c2eb9afe03fbd1 image: tonistiigi/binfmt:qemu-v10.0.4-56@sha256:30cc9a4d03765acac9be2ed0afc23af1ad018aed2c28ea4be8c2eb9afe03fbd1
cache-image: false cache-image: false
@@ -294,7 +294,7 @@ jobs:
docker compose up --build --exit-code-from "${SERVICE}" "${SERVICE}" docker compose up --build --exit-code-from "${SERVICE}" "${SERVICE}"
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: build-bin-${{ matrix.os }}_${{ matrix.arch }} name: build-bin-${{ matrix.os }}_${{ matrix.arch }}
path: | path: |
@@ -384,7 +384,7 @@ jobs:
[[ "$version" != "$downgraded_version" ]] [[ "$version" != "$downgraded_version" ]]
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: build-bin-${{ github.job }} name: build-bin-${{ github.job }}
path: | path: |
@@ -501,7 +501,7 @@ jobs:
} }
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: build-bin-${{ github.job }}-${{ matrix.arch }} name: build-bin-${{ github.job }}-${{ matrix.arch }}
path: | path: |
@@ -521,7 +521,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
path: artifact path: artifact
pattern: build-bin-* pattern: build-bin-*
@@ -590,7 +590,7 @@ jobs:
done done
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: build-${{ github.job }} name: build-${{ github.job }}
path: | path: |
+2 -2
View File
@@ -50,13 +50,13 @@ jobs:
with: with:
deno-version: '2.0.0' # minimum supported version deno-version: '2.0.0' # minimum supported version
- name: Install Bun - name: Install Bun
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with: with:
# minimum supported version is 1.0.31 but earliest available Windows version is 1.1.0 # 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' }} bun-version: ${{ (matrix.os == 'windows-latest' && '1.1.0') || '1.0.31' }}
no-cache: true no-cache: true
- name: Install Node - name: Install Node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: '20.0' # minimum supported version node-version: '20.0' # minimum supported version
- name: Install QuickJS (Linux) - name: Install QuickJS (Linux)
+2 -2
View File
@@ -36,12 +36,12 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
build-mode: none build-mode: none
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0
with: with:
category: "/language:${{matrix.language}}" category: "/language:${{matrix.language}}"
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
path: dist path: dist
name: build-pypi name: build-pypi
+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
run: echo "head=$(git rev-parse HEAD)" | tee -a "${GITHUB_OUTPUT}" run: echo "head=$(git rev-parse HEAD)" | tee -a "${GITHUB_OUTPUT}"
- name: Cache nightly commit hash - name: Cache nightly commit hash
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
env: env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1 SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
with: with:
@@ -94,7 +94,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
path: dist path: dist
name: build-pypi name: build-pypi
+2 -2
View File
@@ -214,7 +214,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
if: github.event.workflow != '.github/workflows/release.yml' # Reusable workflow_call 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: with:
name: build-pypi name: build-pypi
path: | path: |
@@ -243,7 +243,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
path: artifact path: artifact
pattern: build-* pattern: build-*
+4 -4
View File
@@ -26,8 +26,8 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }} cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env: env:
ACTIONLINT_VERSION: "1.7.9" ACTIONLINT_VERSION: "1.7.11"
ACTIONLINT_SHA256SUM: 233b280d05e100837f4af1433c7b40a5dcb306e3aa68fb4f17f8a7f45a7df7b4 ACTIONLINT_SHA256SUM: 900919a84f2229bac68ca9cd4103ea297abc35e9689ebb842c6e34a3d1b01b0a
ACTIONLINT_REPO: https://github.com/rhysd/actionlint ACTIONLINT_REPO: https://github.com/rhysd/actionlint
jobs: jobs:
@@ -76,8 +76,8 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Run zizmor - name: Run zizmor
uses: zizmorcore/zizmor-action@135698455da5c3b3e55f73f4419e481ab68cdd95 # v0.4.1 uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
with: with:
advanced-security: false advanced-security: false
persona: pedantic persona: pedantic
version: v1.22.0 version: v1.23.1
+4
View File
@@ -9,6 +9,10 @@ rules:
obfuscation: obfuscation:
ignore: ignore:
- release.yml # Not actual obfuscation - release.yml # Not actual obfuscation
secrets-outside-env:
ignore:
- build.yml
- release.yml
unpinned-uses: unpinned-uses:
config: config:
policies: policies: