mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
Update On Wed Nov 19 19:40:07 CET 2025
This commit is contained in:
@@ -1186,3 +1186,4 @@ Update On Sat Nov 15 19:34:45 CET 2025
|
||||
Update On Sun Nov 16 19:35:35 CET 2025
|
||||
Update On Mon Nov 17 19:42:18 CET 2025
|
||||
Update On Tue Nov 18 19:40:59 CET 2025
|
||||
Update On Wed Nov 19 19:39:59 CET 2025
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.25.1
|
||||
go-version: 1.25.4
|
||||
id: go
|
||||
|
||||
- name: Check out repository
|
||||
|
||||
@@ -7,14 +7,14 @@ require (
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
github.com/infobloxopen/go-trees v0.0.0-20221216143356-66ceba885ebc
|
||||
github.com/miekg/dns v1.1.68
|
||||
golang.org/x/net v0.44.0
|
||||
golang.org/x/net v0.47.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
)
|
||||
|
||||
+12
-12
@@ -12,18 +12,18 @@ github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
|
||||
Generated
+8
-8
@@ -116,7 +116,7 @@ importers:
|
||||
version: 7.2.1(terser@5.44.1)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.9.3))
|
||||
version: 6.0.2(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.9.3))
|
||||
'@vue/eslint-config-prettier':
|
||||
specifier: ^10.2.0
|
||||
version: 10.2.0(eslint@9.39.1)(prettier@3.6.2)
|
||||
@@ -965,8 +965,8 @@ packages:
|
||||
resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
|
||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.29':
|
||||
resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==}
|
||||
'@rolldown/pluginutils@1.0.0-beta.50':
|
||||
resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==}
|
||||
|
||||
'@rollup/pluginutils@5.3.0':
|
||||
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
|
||||
@@ -1276,8 +1276,8 @@ packages:
|
||||
terser: ^5.16.0
|
||||
vite: ^7.0.0
|
||||
|
||||
'@vitejs/plugin-vue@6.0.1':
|
||||
resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==}
|
||||
'@vitejs/plugin-vue@6.0.2':
|
||||
resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
peerDependencies:
|
||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||
@@ -3452,7 +3452,7 @@ snapshots:
|
||||
|
||||
'@pkgr/core@0.2.9': {}
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.29': {}
|
||||
'@rolldown/pluginutils@1.0.0-beta.50': {}
|
||||
|
||||
'@rollup/pluginutils@5.3.0(rollup@4.52.5)':
|
||||
dependencies:
|
||||
@@ -3809,9 +3809,9 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@vitejs/plugin-vue@6.0.1(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.9.3))':
|
||||
'@vitejs/plugin-vue@6.0.2(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-beta.29
|
||||
'@rolldown/pluginutils': 1.0.0-beta.50
|
||||
vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1)(yaml@2.7.0)
|
||||
vue: 3.5.24(typescript@5.9.3)
|
||||
|
||||
|
||||
@@ -15,10 +15,8 @@ export default {
|
||||
data() {
|
||||
const dataObj = {};
|
||||
const locales = {
|
||||
he: "עברית",
|
||||
hr: "Hrvatski",
|
||||
hu: "Magyar",
|
||||
ar: "العربية",
|
||||
bg: "български език",
|
||||
ca: "Català",
|
||||
cs: "Čeština",
|
||||
de: "Deutsch",
|
||||
@@ -26,15 +24,18 @@ export default {
|
||||
en: "English",
|
||||
es: "Español",
|
||||
fr: "Français",
|
||||
he: "עברית",
|
||||
hr: "Hrvatski",
|
||||
hu: "Magyar",
|
||||
is: "Icelandic",
|
||||
it: "Italiano",
|
||||
ja: "日本語",
|
||||
ko: "한국어",
|
||||
"nl-be": "Dutch (Belgium)",
|
||||
no: "Norsk",
|
||||
"nl-be": "Dutch (Belgium)",
|
||||
pl: "Polski",
|
||||
"pt-br": "Português",
|
||||
pt: "Português (Brasil)",
|
||||
"pt-br": "Português (Brasil)",
|
||||
pt: "Português (Portugal)",
|
||||
ro: "Romanian",
|
||||
ru: "Русский",
|
||||
sk: "Slovenčina",
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
{
|
||||
"buttons": {
|
||||
"cancel": "Отмени",
|
||||
"clear": "Изчисти",
|
||||
"close": "Затвори",
|
||||
"continue": "Продължи",
|
||||
"copy": "Копирай",
|
||||
"copyFile": "Копирай файл",
|
||||
"copyToClipboard": "Копирай в клипборда",
|
||||
"copyDownloadLinkToClipboard": "Копирай линк за сваляне в клипборда",
|
||||
"create": "Създай",
|
||||
"delete": "Изтрий",
|
||||
"download": "Свали",
|
||||
"file": "Файл",
|
||||
"folder": "Папка",
|
||||
"fullScreen": "Превключване на цял екран",
|
||||
"hideDotfiles": "Скрий файлове започващи с точка",
|
||||
"info": "Информация",
|
||||
"more": "Повече",
|
||||
"move": "Премести",
|
||||
"moveFile": "Премести файл",
|
||||
"new": "Нов",
|
||||
"next": "Следващ",
|
||||
"ok": "Потвърди",
|
||||
"permalink": "Вземи постоянен линк",
|
||||
"previous": "Предишен",
|
||||
"preview": "Преглед",
|
||||
"publish": "Публикуване",
|
||||
"rename": "Преименуване",
|
||||
"replace": "Замяна",
|
||||
"reportIssue": "Докладвай проблем",
|
||||
"save": "Запис",
|
||||
"schedule": "График",
|
||||
"search": "Търсене",
|
||||
"select": "Избери",
|
||||
"selectMultiple": "Избери няколко",
|
||||
"share": "Сподели",
|
||||
"shell": "Превключване на терминала",
|
||||
"submit": "Изпрати",
|
||||
"switchView": "Смени изгледа",
|
||||
"toggleSidebar": "Превключване на страничен панел",
|
||||
"update": "Обнови",
|
||||
"upload": "Качи",
|
||||
"openFile": "Отвори файл",
|
||||
"discardChanges": "Изчисти",
|
||||
"saveChanges": "Запиши промените"
|
||||
},
|
||||
"download": {
|
||||
"downloadFile": "Свали файл",
|
||||
"downloadFolder": "Свали папка",
|
||||
"downloadSelected": "Свали избраното"
|
||||
},
|
||||
"upload": {
|
||||
"abortUpload": "Сигурни ли сте, че искате да прекратите?"
|
||||
},
|
||||
"errors": {
|
||||
"forbidden": "Нямате право на достъп.",
|
||||
"internal": "Взникна грешка.",
|
||||
"notFound": "Локацията не може да бъде достигната.",
|
||||
"connection": "Сървъра не може да бъде достигнат."
|
||||
},
|
||||
"files": {
|
||||
"body": "Тяло",
|
||||
"closePreview": "Затвори прегледа",
|
||||
"files": "Файлове",
|
||||
"folders": "Папки",
|
||||
"home": "Начало",
|
||||
"lastModified": "Последна промяна",
|
||||
"loading": "Зареждане ...",
|
||||
"lonely": "Тук е самотно ...",
|
||||
"metadata": "Метаданни",
|
||||
"multipleSelectionEnabled": "Множествения избор е разрешен",
|
||||
"name": "Име",
|
||||
"size": "Размер",
|
||||
"sortByLastModified": "Подредба по последна промяна",
|
||||
"sortByName": "Подредба по име",
|
||||
"sortBySize": "Подредба по размер",
|
||||
"noPreview": "За този файл не е наличен преглед."
|
||||
},
|
||||
"help": {
|
||||
"click": "избери файл или директория",
|
||||
"ctrl": {
|
||||
"click": "избери файлове или директории",
|
||||
"f": "отваря търсене",
|
||||
"s": "запиши файл или свари директория тук"
|
||||
},
|
||||
"del": "изтрий избраните",
|
||||
"doubleClick": "отвори файл или директория",
|
||||
"esc": "изтрий избраното и/или затвори",
|
||||
"f1": "тази информация",
|
||||
"f2": "преименувай файл",
|
||||
"help": "Помощ"
|
||||
},
|
||||
"login": {
|
||||
"createAnAccount": "Създай акаунт",
|
||||
"loginInstead": "Вече имаш акаунт",
|
||||
"password": "Парола",
|
||||
"passwordConfirm": "Парола Потвърждение",
|
||||
"passwordsDontMatch": "Паролите не съвпадат",
|
||||
"signup": "Абониране",
|
||||
"submit": "Вход",
|
||||
"username": "Потребителско име",
|
||||
"usernameTaken": "Потребителското име вече се използва",
|
||||
"wrongCredentials": "Грешни потребителско име и/или парола",
|
||||
"logout_reasons": {
|
||||
"inactivity": "Бяхте разлогнати поради неактивност"
|
||||
}
|
||||
},
|
||||
"permanent": "Постоянен",
|
||||
"prompts": {
|
||||
"copy": "Копирай",
|
||||
"copyMessage": "Избери къде да копираш файловете си:",
|
||||
"currentlyNavigating": "В момента навигира към:",
|
||||
"deleteMessageMultiple": "Сигурни ли сте, че искате да изтриете {count} файл(а)?",
|
||||
"deleteMessageSingle": "Сигурни ли сте, че искате да изтриете този файл/папка?",
|
||||
"deleteMessageShare": "Сигурни ли сте, че искате на изтриете това споделяне({path})?",
|
||||
"deleteUser": "Сигурни ли сте, че искате да изтриете този потребител?",
|
||||
"deleteTitle": "Изтрий файлове",
|
||||
"displayName": "Име за показване:",
|
||||
"download": "Свали файлове",
|
||||
"downloadMessage": "Изберете формата, в който искате да свалите.",
|
||||
"error": "Възникна грешка",
|
||||
"fileInfo": "Информация за файла",
|
||||
"filesSelected": "Избрани са {count} файла.",
|
||||
"lastModified": "Последна промяна",
|
||||
"move": "Премести",
|
||||
"moveMessage": "Избери ново място за вашите файл(ове)/папк(а/и):",
|
||||
"newArchetype": "Създай нова публикация базирана на шаблон. Вашия файл ще бъде създаден в папката за съдържание.",
|
||||
"newDir": "Нова директория",
|
||||
"newDirMessage": "Именувайте вашата нова директория.",
|
||||
"newFile": "Нов файл",
|
||||
"newFileMessage": "Именувайте вашия нов файл.",
|
||||
"numberDirs": "Брой на директорийте",
|
||||
"numberFiles": "Брой на файловете",
|
||||
"rename": "Преименувай",
|
||||
"renameMessage": "Вмъкни ново име за",
|
||||
"replace": "Замени",
|
||||
"replaceMessage": "Файл, които се опитвате да качите има конфликтно име. Искате ли да го пропуснете и да продължите качването или да замените съществуващия файл?\n",
|
||||
"schedule": "График",
|
||||
"scheduleMessage": "Изберете дата и час за публикуване на тази публикация.",
|
||||
"show": "Покажи",
|
||||
"size": "Размер",
|
||||
"upload": "Качване",
|
||||
"uploadFiles": "Качване на {files} файла...",
|
||||
"uploadMessage": "Изберете опция за качване.",
|
||||
"optionalPassword": "Опционална парола",
|
||||
"resolution": "Резолюция",
|
||||
"discardEditorChanges": "Сигурни ли сте, че искате да откажете направените промени?"
|
||||
},
|
||||
"search": {
|
||||
"images": "Изображения",
|
||||
"music": "Музика",
|
||||
"pdf": "PDF",
|
||||
"pressToSearch": "За търсене, натиснете Enter ...",
|
||||
"search": "Търсене ...",
|
||||
"typeToSearch": "Пишете за търсене ...",
|
||||
"types": "Типове",
|
||||
"video": "Видео"
|
||||
},
|
||||
"settings": {
|
||||
"aceEditorTheme": "Тема на \"Ace редактор\"",
|
||||
"admin": "Админ",
|
||||
"administrator": "Администратор",
|
||||
"allowCommands": "Изпълни команди",
|
||||
"allowEdit": "Редактира, преименува и изтрива файлове и директории",
|
||||
"allowNew": "Създава нови файлове и директорий",
|
||||
"allowPublish": "Публикува нови публикации и страници",
|
||||
"allowSignup": "Разреши потребителите да се абонират",
|
||||
"hideLoginButton": "Скрий логин бутона от публичните страници",
|
||||
"avoidChanges": "(остави празно за да избегнеш промени)",
|
||||
"branding": "Брандиране",
|
||||
"brandingDirectoryPath": "Брандиране - път до директория",
|
||||
"brandingHelp": "Можете да настроите как изглежда вашия File Browser, като промените името и логото му, да добавите стилове и дори да забраните външни линкове към GitHub.\nЗа повече информация за бандиране се обърнете към {0}",
|
||||
"changePassword": "Промени парола",
|
||||
"commandRunner": "Изпълнение на команди",
|
||||
"commandRunnerHelp": "Тук можете да зададете команди, които да се изпълнят при определени събития. Пишете по една команда на ред. Системните променливите {0} и {1} ще са на разположение, като {0} е релативна на {1}. За повече информация относно тази възможност и наличните системни променливи, моля прочетете {2}.",
|
||||
"commandsUpdated": "Командите са запаметени!",
|
||||
"createUserDir": "Създай автоматично собствена директория на потребителя, когато го добавяш.",
|
||||
"minimumPasswordLength": "Минимална дължина на паролата",
|
||||
"tusUploads": "Качване на части",
|
||||
"tusUploadsHelp": "File Browser поддържа качване на части, което позволява съзадавнето на ефективно, надеждно, и възобновяемо качване на части дори и при ненадеждна мрежа.",
|
||||
"tusUploadsChunkSize": "Максимален размер на заявката (за малки качвания ще бъдат използвано директо качване). Можете да въведете цяло число, което означава размера на данните в байтове, или пък текст от вида на 10MB, 1GB и т.н..",
|
||||
"tusUploadsRetryCount": "Брой повторения, когато част от файл не се качи успешно.",
|
||||
"userHomeBasePath": "Основен път до личните директории на потребителите",
|
||||
"userScopeGenerationPlaceholder": "Обхватът ще бъде автоматично генериран",
|
||||
"createUserHomeDirectory": "Създай лична директория на потребителя",
|
||||
"customStylesheet": "Потребителски Стилове",
|
||||
"defaultUserDescription": "Настройки по подразбиране за нови потребители.",
|
||||
"disableExternalLinks": "Забрани външните връзки (с изключение на документацията)",
|
||||
"disableUsedDiskPercentage": "Забрани графиката за използване на диска",
|
||||
"documentation": "документация",
|
||||
"examples": "Примери",
|
||||
"executeOnShell": "Изпълни в шела",
|
||||
"executeOnShellDescription": "По подразбиране, File Browser изпълнява командите директно. Ако искате да ги изпълните в сесия (като Bash или PowerShell), можете да я дефинирате тук заедно с необходимите аргументи и флагове. Ако това е зададено, командата която изпълните ще бъде добавена като аргумент. Това се отнася както за потребителски команди, така и за обработка на събития.",
|
||||
"globalRules": "Това е общия списък от правила за разрешения или забрани. Те са приложими за всеки потребител. Можете да дефинирате специфични правила в настройките на всеки потребител, които ще имат приоритет над общите.",
|
||||
"globalSettings": "Глобални Настройки",
|
||||
"hideDotfiles": "Скрий фаловете започващи с точка",
|
||||
"insertPath": "Вмъкни пътя",
|
||||
"insertRegex": "Вмъкни регулярен израз",
|
||||
"instanceName": "Име на инстанцията",
|
||||
"language": "Език",
|
||||
"lockPassword": "Забрани на потребителя да променя паролата",
|
||||
"newPassword": "Вашата нова парола",
|
||||
"newPasswordConfirm": "Потвърди вашата нова парола",
|
||||
"newUser": "Нов потребител",
|
||||
"password": "Парола",
|
||||
"passwordUpdated": "Паролата е променена!",
|
||||
"path": "Път",
|
||||
"perm": {
|
||||
"create": "Създаване на файлове и директорий",
|
||||
"delete": "Изтриване на файлове и директорий",
|
||||
"download": "Сваляне",
|
||||
"execute": "Изпълни команди",
|
||||
"modify": "Редактирай файлове",
|
||||
"rename": "Преименувай или премести файлове и директорий",
|
||||
"share": "Сподели файлове"
|
||||
},
|
||||
"permissions": "Разрешения",
|
||||
"permissionsHelp": "Можете да зададете потребител да бъде администратор или да изберете разрешения индивидуално. Ако изберете \"Администратор\" всички други опции ще бъдат автоматично отметнати. Управлението на потребителите е привилегия на администратор.\n",
|
||||
"profileSettings": "Настройки на Профила",
|
||||
"ruleExample1": "предотвратете достъпа до всеки файл започващ с точка (като .git, .gitignore) във всяка папка.\n",
|
||||
"ruleExample2": "блокира достъпа до файл именуван Caddyfile поставен в началото за обхвата.",
|
||||
"rules": "Правила",
|
||||
"rulesHelp": "Тук можете да дефинирате списък от правила за разрешаване и забрана за точно този потребител. Блокираните файлове няма да се покажат в списъците и няма да са достъпни за потребителя. Поддържаме регулярни изрази и пътища релативни на обхвата.\n",
|
||||
"scope": "Обхват",
|
||||
"setDateFormat": "Задайте точен формат на дата",
|
||||
"settingsUpdated": "Настройките са обновени!",
|
||||
"shareDuration": "Продължителност на споделянето",
|
||||
"shareManagement": "Управление на споделянето",
|
||||
"shareDeleted": "Споделянето е премахнато!",
|
||||
"singleClick": "Използвайте единичен клик за да отворите файлове или директорий",
|
||||
"themes": {
|
||||
"default": "Настройки по подразбиране",
|
||||
"dark": "Тъмна",
|
||||
"light": "Светла",
|
||||
"title": "Тема"
|
||||
},
|
||||
"user": "Потребител",
|
||||
"userCommands": "Команди",
|
||||
"userCommandsHelp": "Списък разделен с интервал от наличните команди за този потребител.\n",
|
||||
"userCreated": "Потребителя е създаден!",
|
||||
"userDefaults": "Настройки по подразбиране на потребителя",
|
||||
"userDeleted": "Потребителя е изтрит!",
|
||||
"userManagement": "Управление на потребители",
|
||||
"userUpdated": "Потребителя е обновен!",
|
||||
"username": "Потребителско име",
|
||||
"users": "Потребители"
|
||||
},
|
||||
"sidebar": {
|
||||
"help": "Помощ",
|
||||
"hugoNew": "Hugo New",
|
||||
"login": "Вход",
|
||||
"logout": "Изход",
|
||||
"myFiles": "Моите файлове",
|
||||
"newFile": "Нов файл",
|
||||
"newFolder": "Нова папка",
|
||||
"preview": "Преглед",
|
||||
"settings": "Настройки",
|
||||
"signup": "Абониране",
|
||||
"siteSettings": "Настройки на сървъра"
|
||||
},
|
||||
"success": {
|
||||
"linkCopied": "Връзката е копирана!"
|
||||
},
|
||||
"time": {
|
||||
"days": "Дни",
|
||||
"hours": "Часове",
|
||||
"minutes": "Минути",
|
||||
"seconds": "Секунди",
|
||||
"unit": "Единица за време"
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,7 @@
|
||||
"username": "Username",
|
||||
"usernameTaken": "Username already taken",
|
||||
"wrongCredentials": "Wrong credentials",
|
||||
"passwordTooShort": "Password must be at least {min} characters",
|
||||
"logout_reasons": {
|
||||
"inactivity": "You have been logged out due to inactivity."
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import dayjs from "dayjs";
|
||||
import { createI18n } from "vue-i18n";
|
||||
|
||||
import("dayjs/locale/ar");
|
||||
import("dayjs/locale/bg");
|
||||
import("dayjs/locale/cs");
|
||||
import("dayjs/locale/de");
|
||||
import("dayjs/locale/el");
|
||||
import("dayjs/locale/en");
|
||||
@@ -14,6 +16,7 @@ import("dayjs/locale/is");
|
||||
import("dayjs/locale/it");
|
||||
import("dayjs/locale/ja");
|
||||
import("dayjs/locale/ko");
|
||||
import("dayjs/locale/nb");
|
||||
import("dayjs/locale/nl-be");
|
||||
import("dayjs/locale/pl");
|
||||
import("dayjs/locale/pt-br");
|
||||
@@ -27,8 +30,6 @@ import("dayjs/locale/uk");
|
||||
import("dayjs/locale/vi");
|
||||
import("dayjs/locale/zh-cn");
|
||||
import("dayjs/locale/zh-tw");
|
||||
import("dayjs/locale/cs");
|
||||
import("dayjs/locale/nb");
|
||||
|
||||
// All i18n resources specified in the plugin `include` option can be loaded
|
||||
// at once using the import syntax
|
||||
@@ -109,6 +110,7 @@ export function detectLocale() {
|
||||
case /^uk\b/.test(locale):
|
||||
locale = "uk";
|
||||
break;
|
||||
|
||||
case /^vi\b/.test(locale):
|
||||
locale = "vi";
|
||||
break;
|
||||
@@ -123,6 +125,9 @@ export function detectLocale() {
|
||||
case /^no\b/.test(locale):
|
||||
locale = "no";
|
||||
break;
|
||||
case /^bg\b/.test(locale):
|
||||
locale = "bg";
|
||||
break;
|
||||
default:
|
||||
locale = "en";
|
||||
}
|
||||
|
||||
@@ -101,7 +101,11 @@ export async function signup(username: string, password: string) {
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new StatusError(`${res.status} ${res.statusText}`, res.status);
|
||||
const body = await res.text();
|
||||
throw new StatusError(
|
||||
body || `${res.status} ${res.statusText}`,
|
||||
res.status
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,13 @@ const submit = async (event: Event) => {
|
||||
error.value = t("login.usernameTaken");
|
||||
} else if (e.status === 403) {
|
||||
error.value = t("login.wrongCredentials");
|
||||
} else if (e.status === 400) {
|
||||
const match = e.message.match(/minimum length is (\d+)/);
|
||||
if (match) {
|
||||
error.value = t("login.passwordTooShort", { min: match[1] });
|
||||
} else {
|
||||
error.value = e.message;
|
||||
}
|
||||
} else {
|
||||
$showError(e);
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=intel-microcode
|
||||
PKG_VERSION:=20250512
|
||||
PKG_VERSION:=20251111
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=intel-microcode_3.$(PKG_VERSION).1.tar.xz
|
||||
PKG_SOURCE_URL:=@DEBIAN/pool/non-free-firmware/i/intel-microcode/
|
||||
PKG_HASH:=5773cf59867d90f4f5479bae973ac85f1cce2f7ae407645ec29c4ec1ba60f8e2
|
||||
PKG_HASH:=9b6d11cf851dbe483d3afe73e93049263f06b2f93c78a5f7b0068fb2f7ea3411
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/intel-microcode-3.$(PKG_VERSION).1
|
||||
PKG_CPE_ID:=cpe:/a:intel:microcode
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for quickstart
|
||||
LUCI_DEPENDS:=+quickstart +luci-app-store
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_VERSION:=0.12.3-r1
|
||||
PKG_VERSION:=0.12.4-r1
|
||||
# PKG_RELEASE MUST be empty for luci.mk
|
||||
PKG_RELEASE:=
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -10,11 +10,11 @@ include $(TOPDIR)/rules.mk
|
||||
PKG_ARCH_quickstart:=$(ARCH)
|
||||
|
||||
PKG_NAME:=quickstart
|
||||
PKG_VERSION:=0.11.11
|
||||
PKG_VERSION:=0.11.12
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/
|
||||
PKG_HASH:=69e857f6adcd9018f90670a24b0a96ef44412969662b89f62a1a20c62ed5213b
|
||||
PKG_HASH:=9d1a31b8bf365af79c0fe6048ccc66a7ab7f3c60e4e18796ea68db4427eb0a01
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ end
|
||||
function get_node()
|
||||
local id = http.formvalue("id")
|
||||
local result = {}
|
||||
local show_node_info = api.uci_get_type("@global_other[0]", "show_node_info", "0")
|
||||
local show_node_info = api.uci_get_type("global_other", "show_node_info", "0")
|
||||
|
||||
function add_is_ipv6_key(o)
|
||||
if o and o.address and show_node_info == "1" then
|
||||
|
||||
@@ -504,7 +504,7 @@ function get_domain_from_url(url)
|
||||
end
|
||||
|
||||
function get_valid_nodes()
|
||||
local show_node_info = uci_get_type("@global_other[0]", "show_node_info", "0")
|
||||
local show_node_info = uci_get_type("global_other", "show_node_info", "0")
|
||||
local nodes = {}
|
||||
uci:foreach(appname, "nodes", function(e)
|
||||
e.id = e[".name"]
|
||||
@@ -628,7 +628,15 @@ function gen_short_uuid()
|
||||
end
|
||||
|
||||
function uci_get_type(type, config, default)
|
||||
local value = uci:get(appname, type, config) or default
|
||||
local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")")
|
||||
if (value == nil or value == "") and (default and default ~= "") then
|
||||
value = default
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function uci_get_type_id(id, config, default)
|
||||
local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")")
|
||||
if (value == nil or value == "") and (default and default ~= "") then
|
||||
value = default
|
||||
end
|
||||
@@ -644,7 +652,7 @@ local function chmod_755(file)
|
||||
end
|
||||
|
||||
function get_customed_path(e)
|
||||
return uci_get_type("@global_app[0]", e .. "_file")
|
||||
return uci_get_type("global_app", e .. "_file")
|
||||
end
|
||||
|
||||
function finded_com(e)
|
||||
@@ -703,7 +711,7 @@ end
|
||||
function get_app_path(app_name)
|
||||
if com[app_name] then
|
||||
local def_path = com[app_name].default_path
|
||||
local path = uci_get_type("@global_app[0]", app_name:gsub("%-","_") .. "_file")
|
||||
local path = uci_get_type("global_app", app_name:gsub("%-","_") .. "_file")
|
||||
path = path and (#path>0 and path or def_path) or def_path
|
||||
return path
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%
|
||||
local api = require "luci.passwall.api"
|
||||
local haproxy_enable = api.uci_get_type("@global_haproxy[0]", "balancing_enable", "0")
|
||||
local console_port = api.uci_get_type("@global_haproxy[0]", "console_port", "")
|
||||
local haproxy_enable = api.uci_get_type("global_haproxy", "balancing_enable", "0")
|
||||
local console_port = api.uci_get_type("global_haproxy", "console_port", "")
|
||||
-%>
|
||||
<p id="_status"></p>
|
||||
|
||||
|
||||
@@ -127,8 +127,8 @@ table td, .table .td {
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
let auto_detection_time = "<%=api.uci_get_type("@global_other[0]", "auto_detection_time", "0")%>"
|
||||
let show_node_info = "<%=api.uci_get_type("@global_other[0]", "show_node_info", "0")%>"
|
||||
let auto_detection_time = "<%=api.uci_get_type("global_other", "auto_detection_time", "0")%>"
|
||||
let show_node_info = "<%=api.uci_get_type("global_other", "show_node_info", "0")%>"
|
||||
|
||||
var node_list = [];
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ end
|
||||
function get_node()
|
||||
local id = http.formvalue("id")
|
||||
local result = {}
|
||||
local show_node_info = api.uci_get_type("@global_other[0]", "show_node_info", "0")
|
||||
local show_node_info = api.uci_get_type("global_other", "show_node_info", "0")
|
||||
|
||||
function add_is_ipv6_key(o)
|
||||
if o and o.address and show_node_info == "1" then
|
||||
|
||||
@@ -504,7 +504,7 @@ function get_domain_from_url(url)
|
||||
end
|
||||
|
||||
function get_valid_nodes()
|
||||
local show_node_info = uci_get_type("@global_other[0]", "show_node_info", "0")
|
||||
local show_node_info = uci_get_type("global_other", "show_node_info", "0")
|
||||
local nodes = {}
|
||||
uci:foreach(appname, "nodes", function(e)
|
||||
e.id = e[".name"]
|
||||
@@ -628,7 +628,15 @@ function gen_short_uuid()
|
||||
end
|
||||
|
||||
function uci_get_type(type, config, default)
|
||||
local value = uci:get(appname, type, config) or default
|
||||
local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")")
|
||||
if (value == nil or value == "") and (default and default ~= "") then
|
||||
value = default
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function uci_get_type_id(id, config, default)
|
||||
local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")")
|
||||
if (value == nil or value == "") and (default and default ~= "") then
|
||||
value = default
|
||||
end
|
||||
@@ -644,7 +652,7 @@ local function chmod_755(file)
|
||||
end
|
||||
|
||||
function get_customed_path(e)
|
||||
return uci_get_type("@global_app[0]", e .. "_file")
|
||||
return uci_get_type("global_app", e .. "_file")
|
||||
end
|
||||
|
||||
function finded_com(e)
|
||||
@@ -703,7 +711,7 @@ end
|
||||
function get_app_path(app_name)
|
||||
if com[app_name] then
|
||||
local def_path = com[app_name].default_path
|
||||
local path = uci_get_type("@global_app[0]", app_name:gsub("%-","_") .. "_file")
|
||||
local path = uci_get_type("global_app", app_name:gsub("%-","_") .. "_file")
|
||||
path = path and (#path>0 and path or def_path) or def_path
|
||||
return path
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%
|
||||
local api = require "luci.passwall.api"
|
||||
local haproxy_enable = api.uci_get_type("@global_haproxy[0]", "balancing_enable", "0")
|
||||
local console_port = api.uci_get_type("@global_haproxy[0]", "console_port", "")
|
||||
local haproxy_enable = api.uci_get_type("global_haproxy", "balancing_enable", "0")
|
||||
local console_port = api.uci_get_type("global_haproxy", "console_port", "")
|
||||
-%>
|
||||
<p id="_status"></p>
|
||||
|
||||
|
||||
@@ -127,8 +127,8 @@ table td, .table .td {
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
let auto_detection_time = "<%=api.uci_get_type("@global_other[0]", "auto_detection_time", "0")%>"
|
||||
let show_node_info = "<%=api.uci_get_type("@global_other[0]", "show_node_info", "0")%>"
|
||||
let auto_detection_time = "<%=api.uci_get_type("global_other", "auto_detection_time", "0")%>"
|
||||
let show_node_info = "<%=api.uci_get_type("global_other", "show_node_info", "0")%>"
|
||||
|
||||
var node_list = [];
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=2445b44d9ae3ab9a867c9d1e0e244646c4c378622e14b9afaf3658ecf46a40b9
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20251115145809
|
||||
GEOSITE_VER:=20251119044456
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=c41cd987bdd3dda6df67bbf15790713c833e59c619e289e7673bcec178db90c0
|
||||
HASH:=9f1d68cacb68baf5b6a71988d3913f951d4aeff846043ab3b64408be199e8f95
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202511170041
|
||||
|
||||
@@ -28,7 +28,7 @@ Package: v2rayN
|
||||
Version: $Version
|
||||
Architecture: $Arch2
|
||||
Maintainer: https://github.com/2dust/v2rayN
|
||||
Depends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1)
|
||||
Depends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11)
|
||||
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
|
||||
EOF
|
||||
|
||||
|
||||
@@ -631,13 +631,14 @@ ExclusiveArch: aarch64 x86_64
|
||||
Source0: __PKGROOT__.tar.gz
|
||||
|
||||
# Runtime dependencies (Avalonia / X11 / Fonts / GL)
|
||||
Requires: freetype, cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||
Requires: cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||
Requires: glibc >= 2.34
|
||||
Requires: fontconfig >= 2.13.1
|
||||
Requires: desktop-file-utils >= 0.26
|
||||
Requires: xdg-utils >= 1.1.3
|
||||
Requires: coreutils >= 8.32
|
||||
Requires: bash >= 5.1
|
||||
Requires: freetype >= 2.10
|
||||
|
||||
%description
|
||||
v2rayN Linux for Red Hat Enterprise Linux
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>7.16.2</Version>
|
||||
<Version>7.16.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace v2rayN.Desktop.Common;
|
||||
|
||||
public static class AppBuilderExtension
|
||||
{
|
||||
public static AppBuilder WithFontByDefault(this AppBuilder appBuilder)
|
||||
{
|
||||
var uri = Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC");
|
||||
return appBuilder.With(new FontManagerOptions()
|
||||
var fallbacks = new List<FontFallback>();
|
||||
|
||||
var notoSansSc = new FontFamily(Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC"));
|
||||
fallbacks.Add(new FontFallback { FontFamily = notoSansSc });
|
||||
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
//DefaultFamilyName = uri,
|
||||
FontFallbacks = new[] { new FontFallback { FontFamily = new FontFamily(uri) } }
|
||||
fallbacks.Add(new FontFallback
|
||||
{
|
||||
FontFamily = new FontFamily("Noto Color Emoji")
|
||||
});
|
||||
}
|
||||
|
||||
return appBuilder.With(new FontManagerOptions
|
||||
{
|
||||
FontFallbacks = fallbacks.ToArray()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
[submodule "hev-socks5-tunnel"]
|
||||
path = hev-socks5-tunnel
|
||||
url = https://github.com/heiher/hev-socks5-tunnel
|
||||
branch = master
|
||||
|
||||
+11
-5
@@ -3,7 +3,7 @@ name: "Build"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
release:
|
||||
types:
|
||||
@@ -77,8 +77,14 @@ jobs:
|
||||
tool: mips-unknown-linux-musl
|
||||
- name: mips32sf
|
||||
tool: mips-unknown-linux-muslsf
|
||||
- name: or1k
|
||||
tool: or1k-unknown-linux-musl
|
||||
- name: powerpc64le
|
||||
tool: powerpc64le-unknown-linux-musl
|
||||
- name: powerpc64
|
||||
tool: powerpc64-unknown-linux-musl
|
||||
- name: powerpcle
|
||||
tool: powerpcle-unknown-linux-musl
|
||||
- name: powerpc
|
||||
tool: powerpc-unknown-linux-musl
|
||||
- name: riscv32
|
||||
@@ -100,7 +106,7 @@ jobs:
|
||||
- name: Build ${{ matrix.name }}
|
||||
run: |
|
||||
sudo mkdir -p /opt/x-tools
|
||||
wget https://github.com/cross-tools/musl-cross/releases/download/20250804/${{ matrix.tool }}.tar.xz
|
||||
wget https://github.com/cross-tools/musl-cross/releases/download/20250929/${{ matrix.tool }}.tar.xz
|
||||
sudo tar xf ${{ matrix.tool }}.tar.xz -C /opt/x-tools
|
||||
make CROSS_PREFIX=/opt/x-tools/${{ matrix.tool }}/bin/${{ matrix.tool }}- CFLAGS=${{ matrix.env.CFLAGS }} ENABLE_STATIC=1 -j`nproc`
|
||||
cp bin/hev-socks5-tunnel hev-socks5-tunnel-linux-${{ matrix.name }}
|
||||
@@ -264,12 +270,12 @@ jobs:
|
||||
submodules: true
|
||||
- name: Prepare
|
||||
run: |
|
||||
wget https://dl.google.com/android/repository/android-ndk-r27b-linux.zip
|
||||
unzip android-ndk-r27b-linux.zip
|
||||
wget https://dl.google.com/android/repository/android-ndk-r27d-linux.zip
|
||||
unzip android-ndk-r27d-linux.zip
|
||||
ln -sf . jni
|
||||
- name: Build
|
||||
run: |
|
||||
./android-ndk-r27b/ndk-build
|
||||
./android-ndk-r27d/ndk-build
|
||||
|
||||
llvm:
|
||||
name: LLVM
|
||||
|
||||
@@ -3,7 +3,7 @@ name: "Check code formatting"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#
|
||||
|
||||
APP_OPTIM := release
|
||||
APP_PLATFORM := android-21
|
||||
APP_ABI := armeabi-v7a arm64-v8a
|
||||
APP_PLATFORM := android-29
|
||||
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
|
||||
APP_CFLAGS := -O3
|
||||
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
|
||||
NDK_TOOLCHAIN_VERSION := clang
|
||||
|
||||
@@ -29,6 +29,7 @@ ENV TUN=tun0 \
|
||||
SOCKS5_USERNAME='' \
|
||||
SOCKS5_PASSWORD='' \
|
||||
SOCKS5_UDP_MODE=udp \
|
||||
SOCKS5_UDP_ADDR='' \
|
||||
CONFIG_ROUTES=1 \
|
||||
IPV4_INCLUDED_ROUTES=0.0.0.0/0 \
|
||||
IPV4_EXCLUDED_ROUTES='' \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# HevSocks5Tunnel
|
||||
|
||||
[](https://github.com/heiher/hev-socks5-tunnel)
|
||||
[](https://github.com/heiher/hev-socks5-tunnel)
|
||||
|
||||
A simple, lightweight tunnel over Socks5 proxy (tun2socks).
|
||||
|
||||
@@ -107,6 +107,8 @@ socks5:
|
||||
address: 127.0.0.1
|
||||
# Socks5 UDP relay mode (tcp|udp)
|
||||
udp: 'udp'
|
||||
# Override the UDP address provided by the Socks5 server (ipv4/ipv6)
|
||||
# udp-address: ''
|
||||
# Socks5 handshake using pipeline mode
|
||||
# pipeline: false
|
||||
# Socks5 server username
|
||||
@@ -133,10 +135,18 @@ socks5:
|
||||
# task-stack-size: 86016
|
||||
# tcp buffer size (bytes)
|
||||
# tcp-buffer-size: 65536
|
||||
# udp socket recv buffer (SO_RCVBUF) size (bytes)
|
||||
# udp-recv-buffer-size: 524288
|
||||
# number of udp buffers in splice, 1500 bytes per buffer.
|
||||
# udp-copy-buffer-nums: 10
|
||||
# maximum session count (0: unlimited)
|
||||
# max-session-count: 0
|
||||
# connect timeout (ms)
|
||||
# connect-timeout: 5000
|
||||
# read-write timeout (ms)
|
||||
# read-write-timeout: 60000
|
||||
# connect-timeout: 10000
|
||||
# TCP read-write timeout (ms)
|
||||
# tcp-read-write-timeout: 300000
|
||||
# UDP read-write timeout (ms)
|
||||
# udp-read-write-timeout: 60000
|
||||
# stdout, stderr or file-path
|
||||
# log-file: stderr
|
||||
# debug, info, warn or error
|
||||
@@ -188,8 +198,8 @@ sudo route change -inet6 default -interface tun0
|
||||
route add 10.0.0.1/32 10.0.2.2
|
||||
|
||||
# Route others
|
||||
route change 0.0.0.0/0 0.0.0.0 if tun0
|
||||
route change ::/0 :: if tun0
|
||||
route change 0.0.0.0/0 0.0.0.0 if tun-index
|
||||
route change ::/0 :: if tun-index
|
||||
```
|
||||
|
||||
#### OpenWrt 24.10+
|
||||
@@ -208,8 +218,9 @@ opkg install hev-socks5-tunnel
|
||||
|
||||
#### Low memory usage
|
||||
|
||||
On low-memory systems like iOS, reducing the size of the TCP buffer
|
||||
and task stack can help prevent out-of-memory issues.
|
||||
On low-memory systems like iOS, reducing the size of the TCP buffer and
|
||||
task stack, as well as limiting the maximum session count, can help prevent
|
||||
out-of-memory issues.
|
||||
|
||||
```yaml
|
||||
misc:
|
||||
@@ -217,6 +228,8 @@ misc:
|
||||
task-stack-size: 24576 # 20480 + tcp-buffer-size
|
||||
# tcp buffer size (bytes)
|
||||
tcp-buffer-size: 4096
|
||||
# maximum session count
|
||||
max-session-count: 1200
|
||||
```
|
||||
|
||||
#### Docker Compose
|
||||
@@ -250,6 +263,7 @@ services:
|
||||
SOCKS5_USERNAME: user # optional, socks5 proxy username, only set when need to auth
|
||||
SOCKS5_PASSWORD: pass # optional, socks5 proxy password, only set when need to auth
|
||||
SOCKS5_UDP_MODE: udp # optional, UDP relay mode, default `udp`, other option `tcp`
|
||||
SOCKS5_UDP_ADDR: a.b.c.d # optional, override the UDP address provided by the Socks5 server
|
||||
CONFIG_ROUTES: 1 # optional, set 0 to ignore TABLE, IPV4_INCLUDED_ROUTES and IPV4_EXCLUDED_ROUTES, with MARK defaults to 0
|
||||
IPV4_INCLUDED_ROUTES: 0.0.0.0/0 # optional, demo means proxy all traffic. for multiple network segments, join with `,` or `\n`
|
||||
IPV4_EXCLUDED_ROUTES: a.b.c.d # optional, demo means exclude traffic from the proxy itself. for multiple network segments, join with `,` or `\n`
|
||||
@@ -371,4 +385,4 @@ void hev_socks5_tunnel_stats (size_t *tx_packets, size_t *tx_bytes,
|
||||
|
||||
MIT
|
||||
|
||||
[^1]: See [protocol specification](https://github.com/heiher/hev-socks5-core/tree/master?tab=readme-ov-file#udp-in-tcp). The [hev-socks5-server](https://github.com/heiher/hev-socks5-server) supports UDP relay over TCP.
|
||||
[^1]: See [protocol specification](https://github.com/heiher/hev-socks5-core/tree/main?tab=readme-ov-file#udp-in-tcp). The [hev-socks5-server](https://github.com/heiher/hev-socks5-server) supports UDP relay over TCP.
|
||||
|
||||
@@ -23,6 +23,8 @@ socks5:
|
||||
address: 127.0.0.1
|
||||
# Socks5 UDP relay mode (tcp|udp)
|
||||
udp: 'udp'
|
||||
# Override the UDP address provided by the Socks5 server (ipv4/ipv6)
|
||||
# udp-address: ''
|
||||
# Socks5 handshake using pipeline mode
|
||||
# pipeline: false
|
||||
# Socks5 server username
|
||||
@@ -49,10 +51,18 @@ socks5:
|
||||
# task-stack-size: 86016
|
||||
# tcp buffer size (bytes)
|
||||
# tcp-buffer-size: 65536
|
||||
# udp socket recv buffer (SO_RCVBUF) size (bytes)
|
||||
# udp-recv-buffer-size: 524288
|
||||
# number of udp buffers in splice, 1500 bytes per buffer.
|
||||
# udp-copy-buffer-nums: 10
|
||||
# maximum session count (0: unlimited)
|
||||
# max-session-count: 0
|
||||
# connect timeout (ms)
|
||||
# connect-timeout: 5000
|
||||
# read-write timeout (ms)
|
||||
# read-write-timeout: 60000
|
||||
# connect-timeout: 10000
|
||||
# TCP read-write timeout (ms)
|
||||
# tcp-read-write-timeout: 300000
|
||||
# UDP read-write timeout (ms)
|
||||
# udp-read-write-timeout: 60000
|
||||
# stdout, stderr or file-path
|
||||
# log-file: stderr
|
||||
# debug, info, warn or error
|
||||
|
||||
@@ -19,6 +19,7 @@ SOCKS5_PORT="${SOCKS5_PORT:-1080}"
|
||||
SOCKS5_USERNAME="${SOCKS5_USERNAME:-}"
|
||||
SOCKS5_PASSWORD="${SOCKS5_PASSWORD:-}"
|
||||
SOCKS5_UDP_MODE="${SOCKS5_UDP_MODE:-udp}"
|
||||
SOCKS5_UDP_ADDR="${SOCKS5_UDP_ADDR:-}"
|
||||
|
||||
IPV4_INCLUDED_ROUTES="${IPV4_INCLUDED_ROUTES:-0.0.0.0/0}"
|
||||
IPV4_EXCLUDED_ROUTES="${IPV4_EXCLUDED_ROUTES:-}"
|
||||
@@ -49,6 +50,10 @@ EOF
|
||||
if [ -n "${SOCKS5_PASSWORD}" ]; then
|
||||
echo " password: '${SOCKS5_PASSWORD}'" >> /hs5t.yml
|
||||
fi
|
||||
|
||||
if [ -n "${SOCKS5_UDP_ADDR}" ]; then
|
||||
echo " udp-address: '${SOCKS5_UDP_ADDR}'" >> /hs5t.yml
|
||||
fi
|
||||
}
|
||||
|
||||
config_route() {
|
||||
|
||||
@@ -3,7 +3,7 @@ name: "Check code formatting"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -124,13 +124,13 @@ udp_client_entry (void *data)
|
||||
hev_socks5_client_handshake (HEV_SOCKS5_CLIENT (udp));
|
||||
|
||||
/*
|
||||
* HevSocks5Addr addr;
|
||||
* HevSocks5UDPMsg msgv[num];
|
||||
*
|
||||
* send udp packet:
|
||||
* hev_socks5_udp_sendto (HEV_SOCKS5_UDP (udp), data, len, &addr);
|
||||
* send udp packets:
|
||||
* hev_socks5_udp_sendmmsg (HEV_SOCKS5_UDP (udp), msgv, num);
|
||||
*
|
||||
* recv udp packet:
|
||||
* hev_socks5_udp_recvfrom (HEV_SOCKS5_UDP (udp), data, len, &addr);
|
||||
* recv udp packets:
|
||||
* hev_socks5_udp_recvmmsg (HEV_SOCKS5_UDP (udp), msgv, num, 0);
|
||||
*/
|
||||
|
||||
hev_object_unref (HEV_OBJECT (udp));
|
||||
|
||||
@@ -22,57 +22,6 @@
|
||||
|
||||
#define task_io_yielder hev_socks5_task_io_yielder
|
||||
|
||||
static int
|
||||
hev_socks5_client_connect_server (HevSocks5Client *self, const char *addr,
|
||||
int port)
|
||||
{
|
||||
HevSocks5Class *klass;
|
||||
struct sockaddr_in6 saddr;
|
||||
struct sockaddr *sap;
|
||||
int addr_family;
|
||||
int fd, res;
|
||||
|
||||
LOG_D ("%p socks5 client connect server", self);
|
||||
|
||||
addr_family = hev_socks5_get_addr_family (HEV_SOCKS5 (self));
|
||||
res = hev_socks5_name_into_sockaddr6 (addr, port, &saddr, &addr_family);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client resolve [%s]:%d", self, addr, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = hev_socks5_socket (SOCK_STREAM);
|
||||
if (fd < 0) {
|
||||
LOG_E ("%p socks5 client socket", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sap = (struct sockaddr *)&saddr;
|
||||
klass = HEV_OBJECT_GET_CLASS (self);
|
||||
res = klass->binder (HEV_SOCKS5 (self), fd, sap);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client bind", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_connect (fd, sap, sizeof (saddr), task_io_yielder,
|
||||
self);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client connect", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HEV_SOCKS5 (self)->fd = fd;
|
||||
hev_socks5_set_addr_family (HEV_SOCKS5 (self), addr_family);
|
||||
LOG_D ("%p socks5 client connect server fd %d", self, fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_client_write_auth_methods (HevSocks5Client *self)
|
||||
{
|
||||
@@ -213,7 +162,7 @@ hev_socks5_client_read_auth_method (HevSocks5Client *self)
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &auth, 2, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != 2) {
|
||||
LOG_E ("%p socks5 client read auth", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -236,7 +185,7 @@ hev_socks5_client_read_auth_creds (HevSocks5Client *self)
|
||||
|
||||
ret = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &res, 2, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (ret <= 0) {
|
||||
if (ret != 2) {
|
||||
LOG_E ("%p socks5 client read auth creds", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -268,7 +217,7 @@ hev_socks5_client_read_response (HevSocks5Client *self)
|
||||
|
||||
ret = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &res, 4, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (ret <= 0) {
|
||||
if (ret != 4) {
|
||||
LOG_E ("%p socks5 client read response", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -297,7 +246,7 @@ hev_socks5_client_read_response (HevSocks5Client *self)
|
||||
|
||||
ret = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &res.addr.ipv4,
|
||||
addrlen, MSG_WAITALL, task_io_yielder, self);
|
||||
if (ret <= 0) {
|
||||
if (ret != addrlen) {
|
||||
LOG_E ("%p socks5 client read addr", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -315,16 +264,54 @@ hev_socks5_client_read_response (HevSocks5Client *self)
|
||||
int
|
||||
hev_socks5_client_connect (HevSocks5Client *self, const char *addr, int port)
|
||||
{
|
||||
int res;
|
||||
HevSocks5Class *klass;
|
||||
struct sockaddr_in6 saddr;
|
||||
struct sockaddr *sap;
|
||||
int addr_family;
|
||||
int timeout;
|
||||
int fd, res;
|
||||
|
||||
LOG_D ("%p socks5 client connect [%s]:%d", self, addr, port);
|
||||
|
||||
res = hev_socks5_client_connect_server (self, addr, port);
|
||||
timeout = hev_socks5_get_connect_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
|
||||
addr_family = hev_socks5_get_addr_family (HEV_SOCKS5 (self));
|
||||
res = hev_socks5_name_into_sockaddr6 (addr, port, &saddr, &addr_family);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client connect", self);
|
||||
LOG_E ("%p socks5 client resolve [%s]:%d", self, addr, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = hev_socks5_socket (SOCK_STREAM);
|
||||
if (fd < 0) {
|
||||
LOG_E ("%p socks5 client socket", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sap = (struct sockaddr *)&saddr;
|
||||
klass = HEV_OBJECT_GET_CLASS (self);
|
||||
res = klass->binder (HEV_SOCKS5 (self), fd, sap);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client bind", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_connect (fd, sap, sizeof (saddr), task_io_yielder,
|
||||
self);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 client connect", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HEV_SOCKS5 (self)->fd = fd;
|
||||
hev_socks5_set_addr_family (HEV_SOCKS5 (self), addr_family);
|
||||
LOG_D ("%p socks5 client connect server fd %d", self, fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -409,10 +396,28 @@ hev_socks5_client_handshake_pipeline (HevSocks5Client *self)
|
||||
int
|
||||
hev_socks5_client_handshake (HevSocks5Client *self, int pipeline)
|
||||
{
|
||||
if (pipeline)
|
||||
return hev_socks5_client_handshake_pipeline (self);
|
||||
int timeout;
|
||||
int res;
|
||||
|
||||
return hev_socks5_client_handshake_standard (self);
|
||||
timeout = hev_socks5_get_tcp_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
|
||||
if (pipeline)
|
||||
res = hev_socks5_client_handshake_pipeline (self);
|
||||
else
|
||||
res = hev_socks5_client_handshake_standard (self);
|
||||
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
timeout = hev_socks5_get_udp_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -49,7 +49,7 @@ hev_socks5_logger_fini (void)
|
||||
int
|
||||
hev_socks5_logger_enabled (HevSocks5LoggerLevel level)
|
||||
{
|
||||
if (fd >= 0 && level >= req_level)
|
||||
if (level >= req_level && fd >= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -67,7 +67,7 @@ hev_socks5_logger_log (HevSocks5LoggerLevel level, const char *fmt, ...)
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
if (fd < 0 || level < req_level)
|
||||
if (level < req_level || fd < 0)
|
||||
return;
|
||||
|
||||
time (&now);
|
||||
|
||||
@@ -27,7 +27,12 @@ int hev_socks5_socket (int type);
|
||||
const char *hev_socks5_addr_into_str (const HevSocks5Addr *addr, char *buf,
|
||||
int len);
|
||||
|
||||
int hev_socks5_get_connect_timeout (void);
|
||||
int hev_socks5_get_tcp_timeout (void);
|
||||
int hev_socks5_get_udp_timeout (void);
|
||||
|
||||
int hev_socks5_get_task_stack_size (void);
|
||||
int hev_socks5_get_udp_copy_buffer_nums (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -24,8 +24,13 @@
|
||||
#include "hev-socks5-misc.h"
|
||||
#include "hev-socks5-misc-priv.h"
|
||||
|
||||
static int connect_timeout = 10000;
|
||||
static int tcp_timeout = 300000;
|
||||
static int udp_timeout = 60000;
|
||||
|
||||
static int task_stack_size = 8192;
|
||||
static int udp_recv_buffer_size = 512 * 1024;
|
||||
static int udp_copy_buffer_nums = 10;
|
||||
|
||||
int
|
||||
hev_socks5_task_io_yielder (HevTaskYieldType type, void *data)
|
||||
@@ -313,6 +318,42 @@ hev_socks5_name_into_sockaddr6 (const char *name, int port,
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_set_connect_timeout (int timeout)
|
||||
{
|
||||
connect_timeout = timeout;
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_get_connect_timeout (void)
|
||||
{
|
||||
return connect_timeout;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_set_tcp_timeout (int timeout)
|
||||
{
|
||||
tcp_timeout = timeout;
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_get_tcp_timeout (void)
|
||||
{
|
||||
return tcp_timeout;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_set_udp_timeout (int timeout)
|
||||
{
|
||||
udp_timeout = timeout;
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_get_udp_timeout (void)
|
||||
{
|
||||
return udp_timeout;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_set_task_stack_size (int stack_size)
|
||||
{
|
||||
@@ -330,3 +371,15 @@ hev_socks5_set_udp_recv_buffer_size (int buffer_size)
|
||||
{
|
||||
udp_recv_buffer_size = buffer_size;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_set_udp_copy_buffer_nums (int nums)
|
||||
{
|
||||
udp_copy_buffer_nums = nums;
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_get_udp_copy_buffer_nums (void)
|
||||
{
|
||||
return udp_copy_buffer_nums;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,13 @@ extern "C" {
|
||||
|
||||
int hev_socks5_task_io_yielder (HevTaskYieldType type, void *data);
|
||||
|
||||
void hev_socks5_set_connect_timeout (int timeout);
|
||||
void hev_socks5_set_tcp_timeout (int timeout);
|
||||
void hev_socks5_set_udp_timeout (int timeout);
|
||||
|
||||
void hev_socks5_set_task_stack_size (int stack_size);
|
||||
void hev_socks5_set_udp_recv_buffer_size (int buffer_size);
|
||||
void hev_socks5_set_udp_copy_buffer_nums (int nums);
|
||||
|
||||
int hev_socks5_addr_len (const HevSocks5Addr *addr);
|
||||
int hev_socks5_addr_from_name (HevSocks5Addr *addr, const char *name, int port);
|
||||
|
||||
@@ -54,12 +54,6 @@ hev_socks5_server_set_auth (HevSocks5Server *self, HevSocks5Authenticator *auth)
|
||||
self->auth = auth;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_server_set_connect_timeout (HevSocks5Server *self, int timeout)
|
||||
{
|
||||
self->timeout = timeout;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_server_read_auth_method (HevSocks5Server *self)
|
||||
{
|
||||
@@ -72,7 +66,7 @@ hev_socks5_server_read_auth_method (HevSocks5Server *self)
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &auth, 2, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != 2) {
|
||||
LOG_E ("%p socks5 server read auth method", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -85,7 +79,7 @@ hev_socks5_server_read_auth_method (HevSocks5Server *self)
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &auth.methods,
|
||||
auth.method_len, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != auth.method_len) {
|
||||
LOG_E ("%p socks5 server read auth methods", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -141,7 +135,7 @@ hev_socks5_server_read_auth_user (HevSocks5Server *self)
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, head, 2, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != 2) {
|
||||
LOG_E ("%p socks5 server read auth user.ver", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -159,7 +153,7 @@ hev_socks5_server_read_auth_user (HevSocks5Server *self)
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, name, nlen + 1,
|
||||
MSG_WAITALL, task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != (nlen + 1)) {
|
||||
LOG_E ("%p socks5 server read auth user.name", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -172,7 +166,7 @@ hev_socks5_server_read_auth_user (HevSocks5Server *self)
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, pass, plen,
|
||||
MSG_WAITALL, task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != plen) {
|
||||
LOG_E ("%p socks5 server read auth user.pass", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -257,7 +251,7 @@ hev_socks5_server_read_request (HevSocks5Server *self, int *cmd, int *rep,
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, &req, 5, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != 5) {
|
||||
LOG_E ("%p socks5 server read request", self);
|
||||
return -1;
|
||||
}
|
||||
@@ -286,7 +280,7 @@ hev_socks5_server_read_request (HevSocks5Server *self, int *cmd, int *rep,
|
||||
|
||||
res = hev_task_io_socket_recv (HEV_SOCKS5 (self)->fd, req.addr.domain.addr,
|
||||
addrlen, MSG_WAITALL, task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
if (res != addrlen) {
|
||||
*rep = HEV_SOCKS5_RES_REP_ADDR;
|
||||
LOG_E ("%p socks5 server read addr", self);
|
||||
return 0;
|
||||
@@ -377,12 +371,11 @@ hev_socks5_server_connect (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = hev_socks5_get_timeout (HEV_SOCKS5 (self));
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), self->timeout);
|
||||
res = hev_task_io_socket_connect (fd, (struct sockaddr *)addr,
|
||||
sizeof (*addr), task_io_yielder, self);
|
||||
timeout = hev_socks5_get_connect_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
|
||||
res = hev_task_io_socket_connect (fd, (struct sockaddr *)addr,
|
||||
sizeof (*addr), task_io_yielder, self);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server connect", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
@@ -390,6 +383,9 @@ hev_socks5_server_connect (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = hev_socks5_get_tcp_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
|
||||
self->fds[0] = fd;
|
||||
|
||||
return 0;
|
||||
@@ -399,7 +395,6 @@ static int
|
||||
hev_socks5_server_bind (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
{
|
||||
HevSocks5ServerClass *sskptr = HEV_OBJECT_GET_CLASS (self);
|
||||
socklen_t alen;
|
||||
int one = 1;
|
||||
int res;
|
||||
int fd;
|
||||
@@ -431,7 +426,7 @@ hev_socks5_server_bind (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = sskptr->binder (self, fd, (struct sockaddr *)addr);
|
||||
res = sskptr->binder (self, fd, addr);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server bind", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
@@ -439,15 +434,6 @@ hev_socks5_server_bind (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
alen = sizeof (struct sockaddr_in6);
|
||||
res = getsockname (fd, (struct sockaddr *)addr, &alen);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server socket name", self);
|
||||
hev_task_del_fd (hev_task_self (), fd);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->fds[1] = fd;
|
||||
|
||||
return 0;
|
||||
@@ -455,28 +441,33 @@ hev_socks5_server_bind (HevSocks5Server *self, struct sockaddr_in6 *addr)
|
||||
|
||||
static int
|
||||
hev_socks5_server_udp_bind (HevSocks5Server *self, int sock,
|
||||
const struct sockaddr *src)
|
||||
struct sockaddr_in6 *src)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t alen;
|
||||
int res;
|
||||
|
||||
LOG_D ("%p socks5 server udp bind", self);
|
||||
|
||||
alen = sizeof (struct sockaddr_in6);
|
||||
res = getsockname (HEV_SOCKS5 (self)->fd, (struct sockaddr *)&addr, &alen);
|
||||
res = getsockname (HEV_SOCKS5 (self)->fd, (struct sockaddr *)src, &alen);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server socket name", self);
|
||||
LOG_E ("%p socks5 server tcp socket name", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sin6_port = 0;
|
||||
res = bind (sock, (struct sockaddr *)&addr, alen);
|
||||
src->sin6_port = 0;
|
||||
res = bind (sock, (struct sockaddr *)src, alen);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server socket bind", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = getsockname (sock, (struct sockaddr *)src, &alen);
|
||||
if (res < 0) {
|
||||
LOG_E ("%p socks5 server udp socket name", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -484,12 +475,16 @@ static int
|
||||
hev_socks5_server_handshake (HevSocks5Server *self)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
int timeout;
|
||||
int cmd;
|
||||
int rep;
|
||||
int res;
|
||||
|
||||
LOG_D ("%p socks5 server handshake", self);
|
||||
|
||||
timeout = hev_socks5_get_tcp_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
|
||||
res = hev_socks5_server_auth (self);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
@@ -535,6 +530,8 @@ hev_socks5_server_handshake (HevSocks5Server *self)
|
||||
static int
|
||||
hev_socks5_server_service (HevSocks5Server *self)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
LOG_D ("%p socks5 server service", self);
|
||||
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
@@ -542,9 +539,9 @@ hev_socks5_server_service (HevSocks5Server *self)
|
||||
hev_socks5_tcp_splice (HEV_SOCKS5_TCP (self), self->fds[0]);
|
||||
break;
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
hev_socks5_udp_splice (HEV_SOCKS5_UDP (self), self->fds[0]);
|
||||
break;
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
timeout = hev_socks5_get_udp_timeout ();
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), timeout);
|
||||
hev_socks5_udp_splice (HEV_SOCKS5_UDP (self), self->fds[0]);
|
||||
break;
|
||||
default:
|
||||
@@ -615,7 +612,6 @@ hev_socks5_server_construct (HevSocks5Server *self, int fd)
|
||||
|
||||
self->fds[0] = -1;
|
||||
self->fds[1] = -1;
|
||||
self->timeout = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ struct _HevSocks5Server
|
||||
HevSocks5 base;
|
||||
|
||||
int fds[2];
|
||||
int timeout;
|
||||
|
||||
union
|
||||
{
|
||||
@@ -48,7 +47,7 @@ struct _HevSocks5ServerClass
|
||||
{
|
||||
HevSocks5Class base;
|
||||
|
||||
int (*binder) (HevSocks5Server *self, int sock, const struct sockaddr *src);
|
||||
int (*binder) (HevSocks5Server *self, int sock, struct sockaddr_in6 *src);
|
||||
|
||||
HevSocks5TCPIface tcp;
|
||||
HevSocks5UDPIface udp;
|
||||
@@ -62,7 +61,6 @@ HevSocks5Server *hev_socks5_server_new (int fd);
|
||||
|
||||
void hev_socks5_server_set_auth (HevSocks5Server *self,
|
||||
HevSocks5Authenticator *auth);
|
||||
void hev_socks5_server_set_connect_timeout (HevSocks5Server *self, int timeout);
|
||||
|
||||
int hev_socks5_server_run (HevSocks5Server *self);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <hev-task.h>
|
||||
#include <hev-task-io.h>
|
||||
#include <hev-task-io-socket.h>
|
||||
#include <hev-memory-allocator.h>
|
||||
|
||||
#include "hev-socks5.h"
|
||||
#include "hev-socks5-misc-priv.h"
|
||||
@@ -21,22 +23,7 @@
|
||||
|
||||
#include "hev-socks5-udp.h"
|
||||
|
||||
typedef enum _HevSocks5UDPAlive HevSocks5UDPAlive;
|
||||
typedef struct _HevSocks5UDPSplice HevSocks5UDPSplice;
|
||||
|
||||
enum _HevSocks5UDPAlive
|
||||
{
|
||||
HEV_SOCKS5_UDP_ALIVE_F = (1 << 0),
|
||||
HEV_SOCKS5_UDP_ALIVE_B = (1 << 1),
|
||||
};
|
||||
|
||||
struct _HevSocks5UDPSplice
|
||||
{
|
||||
HevSocks5UDP *udp;
|
||||
HevSocks5UDPAlive alive;
|
||||
int bind;
|
||||
int fd;
|
||||
};
|
||||
#define UDP_BUF_SIZE 1500
|
||||
|
||||
static int
|
||||
task_io_yielder (HevTaskYieldType type, void *data)
|
||||
@@ -66,336 +53,437 @@ hev_socks5_udp_get_fd (HevSocks5UDP *self)
|
||||
return iface->get_fd (self);
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_udp_sendto (HevSocks5UDP *self, const void *buf, size_t len,
|
||||
const HevSocks5Addr *addr)
|
||||
static int
|
||||
hev_socks5_udp_sendmmsg_tcp (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num)
|
||||
{
|
||||
HevSocks5UDPHdr udp;
|
||||
struct iovec iov[3];
|
||||
struct iovec iov[num * 3];
|
||||
HevSocks5UDPHdr udp[num];
|
||||
struct msghdr mh;
|
||||
int addrlen;
|
||||
int res;
|
||||
int i, res;
|
||||
|
||||
LOG_D ("%p socks5 udp sendto", self);
|
||||
|
||||
addrlen = hev_socks5_addr_len (addr);
|
||||
if (addrlen <= 0) {
|
||||
LOG_D ("%p socks5 udp addr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
udp.datlen = htons (len);
|
||||
udp.hdrlen = 3 + addrlen;
|
||||
break;
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
udp.datlen = 0;
|
||||
udp.hdrlen = 0;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (&mh, 0, sizeof (mh));
|
||||
mh.msg_name = NULL;
|
||||
mh.msg_namelen = 0;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
mh.msg_iov = iov;
|
||||
mh.msg_iovlen = 3;
|
||||
mh.msg_iovlen = num * 3;
|
||||
|
||||
iov[0].iov_base = &udp;
|
||||
iov[0].iov_len = 3;
|
||||
iov[1].iov_base = (void *)addr;
|
||||
iov[1].iov_len = addrlen;
|
||||
iov[2].iov_base = (void *)buf;
|
||||
iov[2].iov_len = len;
|
||||
for (i = 0; i < num; i++) {
|
||||
int addrlen;
|
||||
|
||||
addrlen = hev_socks5_addr_len (msgv[i].addr);
|
||||
if (addrlen <= 0) {
|
||||
LOG_D ("%p socks5 udp addr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
udp[i].datlen = htons (msgv[i].len);
|
||||
udp[i].hdrlen = 3 + addrlen;
|
||||
|
||||
iov[i * 3].iov_base = &udp[i];
|
||||
iov[i * 3].iov_len = 3;
|
||||
iov[i * 3 + 1].iov_base = msgv[i].addr;
|
||||
iov[i * 3 + 1].iov_len = addrlen;
|
||||
iov[i * 3 + 2].iov_base = msgv[i].buf;
|
||||
iov[i * 3 + 2].iov_len = msgv[i].len;
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_sendmsg (hev_socks5_udp_get_fd (self), &mh,
|
||||
MSG_WAITALL, task_io_yielder, self);
|
||||
if (res <= 0) {
|
||||
LOG_D ("%p socks5 udp write tcp", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_sendmmsg_udp (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num)
|
||||
{
|
||||
struct iovec iov[num * 3];
|
||||
struct mmsghdr mvec[num];
|
||||
HevSocks5UDPHdr udp[num];
|
||||
int i, res;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
int addrlen;
|
||||
|
||||
addrlen = hev_socks5_addr_len (msgv[i].addr);
|
||||
if (addrlen <= 0) {
|
||||
LOG_D ("%p socks5 udp addr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
udp[i].datlen = 0;
|
||||
udp[i].hdrlen = 0;
|
||||
|
||||
iov[i * 3].iov_base = &udp[i];
|
||||
iov[i * 3].iov_len = 3;
|
||||
iov[i * 3 + 1].iov_base = msgv[i].addr;
|
||||
iov[i * 3 + 1].iov_len = addrlen;
|
||||
iov[i * 3 + 2].iov_base = msgv[i].buf;
|
||||
iov[i * 3 + 2].iov_len = msgv[i].len;
|
||||
|
||||
mvec[i].msg_hdr.msg_name = NULL;
|
||||
mvec[i].msg_hdr.msg_namelen = 0;
|
||||
mvec[i].msg_hdr.msg_control = NULL;
|
||||
mvec[i].msg_hdr.msg_controllen = 0;
|
||||
mvec[i].msg_hdr.msg_iov = &iov[i * 3];
|
||||
mvec[i].msg_hdr.msg_iovlen = 3;
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_sendmmsg (hev_socks5_udp_get_fd (self), mvec, num,
|
||||
MSG_WAITALL, task_io_yielder, self);
|
||||
if (res <= 0)
|
||||
LOG_D ("%p socks5 udp write udp", self);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_recvfrom_tcp (HevSocks5UDP *self, void *buf, size_t len,
|
||||
HevSocks5Addr *addr)
|
||||
int
|
||||
hev_socks5_udp_sendmmsg (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num)
|
||||
{
|
||||
HevSocks5UDPHdr udp;
|
||||
struct iovec iov[2];
|
||||
struct msghdr mh;
|
||||
int res;
|
||||
int fd;
|
||||
|
||||
LOG_D ("%p socks5 udp recvfrom tcp", self);
|
||||
|
||||
fd = hev_socks5_udp_get_fd (self);
|
||||
res = hev_task_io_socket_recv (fd, &udp, 5, MSG_WAITALL, task_io_yielder,
|
||||
self);
|
||||
if (res <= 0) {
|
||||
LOG_D ("%p socks5 udp read udp head", self);
|
||||
return res;
|
||||
}
|
||||
|
||||
udp.datlen = ntohs (udp.datlen);
|
||||
if (udp.datlen > len) {
|
||||
LOG_D ("%p socks5 udp data len", self);
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
return hev_socks5_udp_sendmmsg_tcp (self, msgv, num);
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
return hev_socks5_udp_sendmmsg_udp (self, msgv, num);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (&mh, 0, sizeof (mh));
|
||||
mh.msg_iov = iov;
|
||||
mh.msg_iovlen = 2;
|
||||
|
||||
iov[0].iov_base = &addr->domain.addr;
|
||||
iov[0].iov_len = udp.hdrlen - 5;
|
||||
iov[1].iov_base = buf;
|
||||
iov[1].iov_len = udp.datlen;
|
||||
|
||||
res = hev_task_io_socket_recvmsg (fd, &mh, MSG_WAITALL, task_io_yielder,
|
||||
self);
|
||||
if (res <= 0) {
|
||||
LOG_D ("%p socks5 udp read udp data", self);
|
||||
return res;
|
||||
}
|
||||
|
||||
addr->atype = udp.addr.atype;
|
||||
addr->domain.len = udp.addr.domain.len;
|
||||
|
||||
return udp.datlen;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_recvfrom_udp (HevSocks5UDP *self, void *buf, size_t len,
|
||||
HevSocks5Addr *addr)
|
||||
hev_socks5_udp_recvmmsg_tcp (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num, int nonblock)
|
||||
{
|
||||
struct sockaddr *saddr = NULL;
|
||||
struct sockaddr_in6 taddr;
|
||||
HevSocks5UDPHdr *udp;
|
||||
uint8_t rbuf[1500];
|
||||
socklen_t alen = 0;
|
||||
ssize_t rlen;
|
||||
int addrlen;
|
||||
int doff;
|
||||
int res;
|
||||
int fd;
|
||||
|
||||
LOG_D ("%p socks5 udp recvfrom udp", self);
|
||||
|
||||
if (!HEV_SOCKS5 (self)->udp_associated) {
|
||||
saddr = (struct sockaddr *)&taddr;
|
||||
alen = sizeof (struct sockaddr_in6);
|
||||
HEV_SOCKS5 (self)->udp_associated = 1;
|
||||
}
|
||||
int i, fd, rlen = 0;
|
||||
|
||||
fd = hev_socks5_udp_get_fd (self);
|
||||
rlen = hev_task_io_socket_recvfrom (fd, rbuf, sizeof (rbuf), 0, saddr,
|
||||
&alen, task_io_yielder, self);
|
||||
if (rlen < 4) {
|
||||
LOG_D ("%p socks5 udp read", self);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
if (saddr) {
|
||||
res = connect (fd, saddr, alen);
|
||||
if (res < 0)
|
||||
if (nonblock)
|
||||
nonblock = MSG_DONTWAIT;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
HevSocks5UDPHdr udp;
|
||||
struct iovec iov[2];
|
||||
struct msghdr mh;
|
||||
int addrlen;
|
||||
int res;
|
||||
|
||||
res = hev_task_io_socket_recv (fd, &udp, 5, nonblock, task_io_yielder,
|
||||
self);
|
||||
if (res > 0 && res < 5)
|
||||
res += hev_task_io_socket_recv (fd, (void *)&udp + res, 5 - res,
|
||||
MSG_WAITALL, task_io_yielder, self);
|
||||
if (res != 5) {
|
||||
if (rlen > 0)
|
||||
break;
|
||||
if (res != -1 || errno != EAGAIN)
|
||||
LOG_D ("%p socks5 udp read udp head", self);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (udp.hdrlen < 5) {
|
||||
LOG_D ("%p socks5 udp head len", self);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
udp = (HevSocks5UDPHdr *)rbuf;
|
||||
addrlen = hev_socks5_addr_len (&udp->addr);
|
||||
if (addrlen <= 0) {
|
||||
LOG_D ("%p socks5 udp addr", self);
|
||||
return -1;
|
||||
}
|
||||
addrlen = udp.hdrlen - 3;
|
||||
udp.datlen = ntohs (udp.datlen);
|
||||
if (udp.datlen > (msgv[i].len - addrlen)) {
|
||||
LOG_D ("%p socks5 udp data len", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
doff = 3 + addrlen;
|
||||
if (doff > rlen) {
|
||||
LOG_D ("%p socks5 udp data len", self);
|
||||
return -1;
|
||||
}
|
||||
mh.msg_name = NULL;
|
||||
mh.msg_namelen = 0;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
mh.msg_iov = iov;
|
||||
mh.msg_iovlen = 2;
|
||||
|
||||
rlen -= doff;
|
||||
if (len < rlen)
|
||||
rlen = len;
|
||||
memcpy (buf, rbuf + doff, rlen);
|
||||
memcpy (addr, &udp->addr, addrlen);
|
||||
iov[0].iov_base = msgv[i].buf + 2;
|
||||
iov[0].iov_len = addrlen - 2;
|
||||
iov[1].iov_base = msgv[i].buf + addrlen;
|
||||
iov[1].iov_len = udp.datlen;
|
||||
|
||||
res = hev_task_io_socket_recvmsg (fd, &mh, MSG_WAITALL, task_io_yielder,
|
||||
self);
|
||||
if (res != (addrlen - 2 + udp.datlen)) {
|
||||
LOG_D ("%p socks5 udp read udp data", self);
|
||||
return res;
|
||||
}
|
||||
|
||||
msgv[i].addr = msgv[i].buf;
|
||||
msgv[i].buf = iov[1].iov_base;
|
||||
msgv[i].len = udp.datlen;
|
||||
msgv[i].addr->atype = udp.addr.atype;
|
||||
msgv[i].addr->domain.len = udp.addr.domain.len;
|
||||
|
||||
rlen++;
|
||||
}
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
int
|
||||
hev_socks5_udp_recvfrom (HevSocks5UDP *self, void *buf, size_t len,
|
||||
HevSocks5Addr *addr)
|
||||
static int
|
||||
hev_socks5_udp_recvmmsg_udp (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num, int nonblock)
|
||||
{
|
||||
int res;
|
||||
struct sockaddr_in6 taddr;
|
||||
struct mmsghdr mvec[num];
|
||||
struct iovec iov[num];
|
||||
int i, fd, res;
|
||||
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
res = hev_socks5_udp_recvfrom_tcp (self, buf, len, addr);
|
||||
break;
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
res = hev_socks5_udp_recvfrom_udp (self, buf, len, addr);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
fd = hev_socks5_udp_get_fd (self);
|
||||
|
||||
if (nonblock)
|
||||
nonblock = MSG_DONTWAIT;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
mvec[i].msg_hdr.msg_name = NULL;
|
||||
mvec[i].msg_hdr.msg_namelen = 0;
|
||||
mvec[i].msg_hdr.msg_control = NULL;
|
||||
mvec[i].msg_hdr.msg_controllen = 0;
|
||||
mvec[i].msg_hdr.msg_iov = &iov[i];
|
||||
mvec[i].msg_hdr.msg_iovlen = 1;
|
||||
|
||||
iov[i].iov_base = msgv[i].buf;
|
||||
iov[i].iov_len = msgv[i].len;
|
||||
}
|
||||
|
||||
if (!HEV_SOCKS5 (self)->udp_associated) {
|
||||
mvec[0].msg_hdr.msg_name = &taddr;
|
||||
mvec[0].msg_hdr.msg_namelen = sizeof (taddr);
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_recvmmsg (fd, mvec, num, nonblock, task_io_yielder,
|
||||
self);
|
||||
if (res <= 0) {
|
||||
if (res != -1 || errno != EAGAIN)
|
||||
LOG_D ("%p socks5 udp read udp", self);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!HEV_SOCKS5 (self)->udp_associated) {
|
||||
struct sockaddr *saddr = mvec[0].msg_hdr.msg_name;
|
||||
socklen_t alen = mvec[0].msg_hdr.msg_namelen;
|
||||
if (connect (fd, saddr, alen) < 0)
|
||||
return -1;
|
||||
HEV_SOCKS5 (self)->udp_associated = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
HevSocks5UDPHdr *udp = msgv[i].buf;
|
||||
int addrlen = hev_socks5_addr_len (&udp->addr);
|
||||
int doff;
|
||||
|
||||
msgv[i].len = mvec[i].msg_len;
|
||||
if (msgv[i].len < 4) {
|
||||
msgv[i].addr = NULL;
|
||||
msgv[i].len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addrlen <= 0) {
|
||||
LOG_D ("%p socks5 udp addr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
doff = 3 + addrlen;
|
||||
if (doff > msgv[i].len) {
|
||||
LOG_D ("%p socks5 udp data len", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msgv[i].addr = &udp->addr;
|
||||
msgv[i].buf += doff;
|
||||
msgv[i].len -= doff;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_fwd_f (HevSocks5UDP *self, HevSocks5UDPSplice *splice)
|
||||
int
|
||||
hev_socks5_udp_recvmmsg (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num, int nonblock)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
struct sockaddr *saddr;
|
||||
HevSocks5Addr taddr;
|
||||
uint8_t buf[1500];
|
||||
int addr_family;
|
||||
ssize_t res;
|
||||
int ret;
|
||||
|
||||
LOG_D ("%p socks5 udp fwd f", self);
|
||||
|
||||
res = hev_socks5_udp_recvfrom (self, buf, sizeof (buf), &taddr);
|
||||
if (res <= 0) {
|
||||
if (res < -1) {
|
||||
splice->alive &= ~HEV_SOCKS5_UDP_ALIVE_F;
|
||||
if (splice->alive && hev_socks5_get_timeout (HEV_SOCKS5 (self)))
|
||||
return 0;
|
||||
}
|
||||
if (HEV_SOCKS5 (self)->type == HEV_SOCKS5_TYPE_UDP_IN_TCP)
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), 0);
|
||||
LOG_D ("%p socks5 udp fwd f recv", self);
|
||||
switch (HEV_SOCKS5 (self)->type) {
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_TCP:
|
||||
return hev_socks5_udp_recvmmsg_tcp (self, msgv, num, nonblock);
|
||||
case HEV_SOCKS5_TYPE_UDP_IN_UDP:
|
||||
return hev_socks5_udp_recvmmsg_udp (self, msgv, num, nonblock);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
saddr = (struct sockaddr *)&addr;
|
||||
addr_family = hev_socks5_get_addr_family (HEV_SOCKS5 (self));
|
||||
ret = hev_socks5_addr_into_sockaddr6 (&taddr, &addr, &addr_family);
|
||||
if (ret < 0) {
|
||||
LOG_D ("%p socks5 udp to sockaddr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!splice->bind) {
|
||||
HevSocks5Class *skptr = HEV_OBJECT_GET_CLASS (self);
|
||||
ret = skptr->binder (HEV_SOCKS5 (self), splice->fd, saddr);
|
||||
if (ret < 0) {
|
||||
LOG_E ("%p socks5 udp bind", self);
|
||||
return -1;
|
||||
}
|
||||
splice->bind = 1;
|
||||
}
|
||||
|
||||
res = sendto (splice->fd, buf, res, 0, saddr, sizeof (addr));
|
||||
if (res <= 0) {
|
||||
if ((res < 0) && (errno == EAGAIN))
|
||||
return 0;
|
||||
LOG_D ("%p socks5 udp fwd f send", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
splice->alive |= HEV_SOCKS5_UDP_ALIVE_F;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_fwd_b (HevSocks5UDP *self, HevSocks5UDPSplice *splice)
|
||||
hev_socks5_udp_fwd_f (HevSocks5UDP *self, int fd, void *buf, unsigned int num,
|
||||
int *bind)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t addrlen;
|
||||
uint8_t buf[1500];
|
||||
ssize_t res;
|
||||
HevSocks5UDPMsg svec[num];
|
||||
int i, res;
|
||||
|
||||
LOG_D ("%p socks5 udp fwd b", self);
|
||||
for (i = 0; i < num; i++) {
|
||||
svec[i].buf = buf + UDP_BUF_SIZE * i;
|
||||
svec[i].len = UDP_BUF_SIZE;
|
||||
}
|
||||
|
||||
addrlen = sizeof (addr);
|
||||
res = hev_task_io_socket_recvfrom (splice->fd, buf, sizeof (buf), 0,
|
||||
(struct sockaddr *)&addr, &addrlen,
|
||||
task_io_yielder, self);
|
||||
res = hev_socks5_udp_recvmmsg (self, svec, num, 1);
|
||||
if (res > 0) {
|
||||
HevSocks5Addr taddr;
|
||||
hev_socks5_addr_from_sockaddr6 (&taddr, &addr);
|
||||
res = hev_socks5_udp_sendto (self, buf, res, &taddr);
|
||||
struct sockaddr_in6 addr[res];
|
||||
struct mmsghdr dvec[res];
|
||||
struct iovec iov[res];
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int family;
|
||||
|
||||
if (!svec[i].len || !svec[i].addr) {
|
||||
LOG_D ("%p socks5 udp invalid", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
family = hev_socks5_get_addr_family (HEV_SOCKS5 (self));
|
||||
ret = hev_socks5_addr_into_sockaddr6 (svec[i].addr, &addr[i],
|
||||
&family);
|
||||
if (ret < 0) {
|
||||
LOG_D ("%p socks5 udp sockaddr", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dvec[i].msg_hdr.msg_name = (struct sockaddr *)&addr[i];
|
||||
dvec[i].msg_hdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
dvec[i].msg_hdr.msg_control = NULL;
|
||||
dvec[i].msg_hdr.msg_controllen = 0;
|
||||
dvec[i].msg_hdr.msg_iov = &iov[i];
|
||||
dvec[i].msg_hdr.msg_iovlen = 1;
|
||||
iov[i].iov_base = svec[i].buf;
|
||||
iov[i].iov_len = svec[i].len;
|
||||
}
|
||||
|
||||
if (!*bind) {
|
||||
HevSocks5Class *skptr = HEV_OBJECT_GET_CLASS (self);
|
||||
struct sockaddr *addr = dvec[0].msg_hdr.msg_name;
|
||||
ret = skptr->binder (HEV_SOCKS5 (self), fd, addr);
|
||||
if (ret < 0) {
|
||||
LOG_E ("%p socks5 udp bind", self);
|
||||
return -1;
|
||||
}
|
||||
*bind = 1;
|
||||
}
|
||||
|
||||
res = hev_task_io_socket_sendmmsg (fd, dvec, res, MSG_WAITALL,
|
||||
task_io_yielder, self);
|
||||
}
|
||||
if (res <= 0) {
|
||||
if (res < -1) {
|
||||
splice->alive &= ~HEV_SOCKS5_UDP_ALIVE_B;
|
||||
if (splice->alive && hev_socks5_get_timeout (HEV_SOCKS5 (self)))
|
||||
return 0;
|
||||
if (res == -1 && errno == EAGAIN)
|
||||
return 0;
|
||||
LOG_D ("%p socks5 udp fwd f recv send", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_fwd_b (HevSocks5UDP *self, int fd, struct mmsghdr *svec,
|
||||
unsigned int num)
|
||||
{
|
||||
int i, res;
|
||||
|
||||
res = hev_task_io_socket_recvmmsg (fd, svec, num, MSG_DONTWAIT,
|
||||
task_io_yielder, self);
|
||||
if (res > 0) {
|
||||
HevSocks5UDPMsg dvec[res];
|
||||
char saddr[res][19];
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
dvec[i].buf = svec[i].msg_hdr.msg_iov->iov_base;
|
||||
dvec[i].len = svec[i].msg_len;
|
||||
dvec[i].addr = (HevSocks5Addr *)&saddr[i];
|
||||
hev_socks5_addr_from_sockaddr6 (dvec[i].addr,
|
||||
svec[i].msg_hdr.msg_name);
|
||||
}
|
||||
if (HEV_SOCKS5 (self)->type == HEV_SOCKS5_TYPE_UDP_IN_TCP)
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), 0);
|
||||
res = hev_socks5_udp_sendmmsg (self, dvec, res);
|
||||
}
|
||||
if (res <= 0) {
|
||||
if (res == -1 && errno == EAGAIN)
|
||||
return 0;
|
||||
LOG_D ("%p socks5 udp fwd b recv send", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
splice->alive |= HEV_SOCKS5_UDP_ALIVE_B;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
splice_task_entry (void *data)
|
||||
{
|
||||
HevSocks5UDPSplice *splice = data;
|
||||
HevSocks5UDP *self = splice->udp;
|
||||
HevTask *task = hev_task_self ();
|
||||
int fd;
|
||||
|
||||
fd = hev_task_io_dup (hev_socks5_udp_get_fd (self));
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (hev_task_add_fd (task, fd, POLLIN) < 0)
|
||||
hev_task_mod_fd (task, fd, POLLIN);
|
||||
|
||||
for (;;) {
|
||||
if (hev_socks5_udp_fwd_f (self, splice) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
splice->alive &= ~HEV_SOCKS5_UDP_ALIVE_F;
|
||||
hev_task_del_fd (task, fd);
|
||||
close (fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_udp_splicer (HevSocks5UDP *self, int fd)
|
||||
hev_socks5_udp_splicer (HevSocks5UDP *self, int fd_b)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
HevSocks5UDPSplice splice;
|
||||
int stack_size;
|
||||
int ufd;
|
||||
int res_f = 1, res_b = 1;
|
||||
int bind = 0;
|
||||
void *buf;
|
||||
int fd_a;
|
||||
int num;
|
||||
|
||||
LOG_D ("%p socks5 udp splicer", self);
|
||||
|
||||
splice.udp = self;
|
||||
splice.alive = HEV_SOCKS5_UDP_ALIVE_F | HEV_SOCKS5_UDP_ALIVE_B;
|
||||
splice.bind = 0;
|
||||
splice.fd = fd;
|
||||
num = hev_socks5_get_udp_copy_buffer_nums ();
|
||||
buf = hev_malloc (UDP_BUF_SIZE * num * 2);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
if (hev_task_add_fd (task, fd, POLLIN) < 0)
|
||||
hev_task_mod_fd (task, fd, POLLIN);
|
||||
fd_a = hev_socks5_udp_get_fd (self);
|
||||
if (hev_task_mod_fd (task, fd_a, POLLIN | POLLOUT) < 0)
|
||||
hev_task_add_fd (task, fd_a, POLLIN | POLLOUT);
|
||||
if (hev_task_add_fd (task, fd_b, POLLIN | POLLOUT) < 0)
|
||||
hev_task_mod_fd (task, fd_b, POLLIN | POLLOUT);
|
||||
|
||||
ufd = hev_socks5_udp_get_fd (self);
|
||||
if (hev_task_mod_fd (task, ufd, POLLOUT) < 0)
|
||||
hev_task_add_fd (task, ufd, POLLOUT);
|
||||
{
|
||||
struct mmsghdr vec[num];
|
||||
struct sockaddr_in6 addr[num];
|
||||
struct iovec iov[num];
|
||||
int i;
|
||||
|
||||
stack_size = hev_socks5_get_task_stack_size ();
|
||||
task = hev_task_new (stack_size);
|
||||
hev_task_ref (task);
|
||||
hev_task_run (task, splice_task_entry, &splice);
|
||||
for (i = 0; i < num; i++) {
|
||||
vec[i].msg_hdr.msg_name = (struct sockaddr *)&addr[i];
|
||||
vec[i].msg_hdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
vec[i].msg_hdr.msg_control = NULL;
|
||||
vec[i].msg_hdr.msg_controllen = 0;
|
||||
vec[i].msg_hdr.msg_iov = &iov[i];
|
||||
vec[i].msg_hdr.msg_iovlen = 1;
|
||||
iov[i].iov_base = buf + UDP_BUF_SIZE * (num + i);
|
||||
iov[i].iov_len = UDP_BUF_SIZE;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (hev_socks5_udp_fwd_b (self, &splice) < 0)
|
||||
break;
|
||||
for (;;) {
|
||||
HevTaskYieldType type;
|
||||
|
||||
if (res_f >= 0)
|
||||
res_f = hev_socks5_udp_fwd_f (self, fd_b, buf, num, &bind);
|
||||
if (res_b >= 0)
|
||||
res_b = hev_socks5_udp_fwd_b (self, fd_b, vec, num);
|
||||
|
||||
if (res_f > 0 || res_b > 0)
|
||||
type = HEV_TASK_YIELD;
|
||||
else if ((res_f & res_b) == 0)
|
||||
type = HEV_TASK_WAITIO;
|
||||
else
|
||||
break;
|
||||
|
||||
if (task_io_yielder (type, self))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
splice.alive &= ~HEV_SOCKS5_UDP_ALIVE_B;
|
||||
hev_task_join (task);
|
||||
hev_task_unref (task);
|
||||
hev_free (buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,16 @@ extern "C" {
|
||||
#define HEV_SOCKS5_UDP_TYPE (hev_socks5_udp_iface ())
|
||||
|
||||
typedef void HevSocks5UDP;
|
||||
typedef struct _HevSocks5UDPMsg HevSocks5UDPMsg;
|
||||
typedef struct _HevSocks5UDPIface HevSocks5UDPIface;
|
||||
|
||||
struct _HevSocks5UDPMsg
|
||||
{
|
||||
HevSocks5Addr *addr;
|
||||
void *buf;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct _HevSocks5UDPIface
|
||||
{
|
||||
int (*get_fd) (HevSocks5UDP *self);
|
||||
@@ -33,11 +41,10 @@ void *hev_socks5_udp_iface (void);
|
||||
|
||||
int hev_socks5_udp_get_fd (HevSocks5UDP *self);
|
||||
|
||||
int hev_socks5_udp_sendto (HevSocks5UDP *self, const void *buf, size_t len,
|
||||
const HevSocks5Addr *addr);
|
||||
|
||||
int hev_socks5_udp_recvfrom (HevSocks5UDP *self, void *buf, size_t len,
|
||||
HevSocks5Addr *addr);
|
||||
int hev_socks5_udp_sendmmsg (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num);
|
||||
int hev_socks5_udp_recvmmsg (HevSocks5UDP *self, HevSocks5UDPMsg *msgv,
|
||||
unsigned int num, int nonblock);
|
||||
|
||||
int hev_socks5_udp_splice (HevSocks5UDP *self, int fd);
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#define __HEV_CONFIG_CONST_H__
|
||||
|
||||
#define MAJOR_VERSION (2)
|
||||
#define MINOR_VERSION (13)
|
||||
#define MICRO_VERSION (0)
|
||||
#define MINOR_VERSION (14)
|
||||
#define MICRO_VERSION (1)
|
||||
|
||||
static const int UDP_BUF_SIZE = 1500;
|
||||
static const int UDP_POOL_SIZE = 512;
|
||||
|
||||
@@ -37,10 +37,14 @@ static int mapdns_cache_size;
|
||||
|
||||
static char log_file[1024];
|
||||
static char pid_file[1024];
|
||||
static int max_session_count;
|
||||
static int task_stack_size = 86016;
|
||||
static int tcp_buffer_size = 65536;
|
||||
static int connect_timeout = 5000;
|
||||
static int read_write_timeout = 60000;
|
||||
static int udp_recv_buffer_size = 524288;
|
||||
static int udp_copy_buffer_nums = 10;
|
||||
static int connect_timeout = 10000;
|
||||
static int tcp_read_write_timeout = 300000;
|
||||
static int udp_read_write_timeout = 60000;
|
||||
static int limit_nofile = 65535;
|
||||
static int log_level = HEV_LOGGER_WARN;
|
||||
|
||||
@@ -172,6 +176,7 @@ hev_config_parse_socks5 (yaml_document_t *doc, yaml_node_t *base)
|
||||
const char *addr = NULL;
|
||||
const char *port = NULL;
|
||||
const char *udpm = NULL;
|
||||
const char *udpa = NULL;
|
||||
const char *user = NULL;
|
||||
const char *pass = NULL;
|
||||
const char *mark = NULL;
|
||||
@@ -204,6 +209,8 @@ hev_config_parse_socks5 (yaml_document_t *doc, yaml_node_t *base)
|
||||
addr = value;
|
||||
else if (0 == strcmp (key, "udp"))
|
||||
udpm = value;
|
||||
else if (0 == strcmp (key, "udp-address"))
|
||||
udpa = value;
|
||||
else if (0 == strcmp (key, "pipeline"))
|
||||
pipe = value;
|
||||
else if (0 == strcmp (key, "username"))
|
||||
@@ -238,6 +245,9 @@ hev_config_parse_socks5 (yaml_document_t *doc, yaml_node_t *base)
|
||||
if (udpm && (strcasecmp (udpm, "udp") == 0))
|
||||
srv.udp_in_udp = 1;
|
||||
|
||||
if (udpa)
|
||||
strncpy (srv.udp_addr, udpa, 256 - 1);
|
||||
|
||||
if (user && pass) {
|
||||
strncpy (_user, user, 256 - 1);
|
||||
strncpy (_pass, pass, 256 - 1);
|
||||
@@ -312,6 +322,9 @@ static int
|
||||
hev_config_parse_misc (yaml_document_t *doc, yaml_node_t *base)
|
||||
{
|
||||
yaml_node_pair_t *pair;
|
||||
int tcp_rw_timeout = -1;
|
||||
int udp_rw_timeout = -1;
|
||||
int rw_timeout = -1;
|
||||
|
||||
if (!base || YAML_MAPPING_NODE != base->type)
|
||||
return -1;
|
||||
@@ -338,10 +351,20 @@ hev_config_parse_misc (yaml_document_t *doc, yaml_node_t *base)
|
||||
task_stack_size = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "tcp-buffer-size"))
|
||||
tcp_buffer_size = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "udp-recv-buffer-size"))
|
||||
udp_recv_buffer_size = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "udp-copy-buffer-nums"))
|
||||
udp_copy_buffer_nums = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "max-session-count"))
|
||||
max_session_count = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "connect-timeout"))
|
||||
connect_timeout = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "read-write-timeout"))
|
||||
read_write_timeout = strtoul (value, NULL, 10);
|
||||
rw_timeout = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "tcp-read-write-timeout"))
|
||||
tcp_rw_timeout = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "udp-read-write-timeout"))
|
||||
udp_rw_timeout = strtoul (value, NULL, 10);
|
||||
else if (0 == strcmp (key, "pid-file"))
|
||||
strncpy (pid_file, value, 1024 - 1);
|
||||
else if (0 == strcmp (key, "log-file"))
|
||||
@@ -352,6 +375,16 @@ hev_config_parse_misc (yaml_document_t *doc, yaml_node_t *base)
|
||||
limit_nofile = strtol (value, NULL, 10);
|
||||
}
|
||||
|
||||
if (tcp_rw_timeout <= 0)
|
||||
tcp_rw_timeout = rw_timeout;
|
||||
if (udp_rw_timeout <= 0)
|
||||
udp_rw_timeout = rw_timeout;
|
||||
|
||||
if (tcp_rw_timeout > 0)
|
||||
tcp_read_write_timeout = tcp_rw_timeout;
|
||||
if (udp_rw_timeout > 0)
|
||||
udp_read_write_timeout = udp_rw_timeout;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -361,6 +394,7 @@ hev_config_parse_doc (yaml_document_t *doc)
|
||||
yaml_node_t *root;
|
||||
yaml_node_pair_t *pair;
|
||||
int min_task_stack_size;
|
||||
int udp_buffer_size;
|
||||
|
||||
root = yaml_document_get_root_node (doc);
|
||||
if (!root || YAML_MAPPING_NODE != root->type)
|
||||
@@ -398,7 +432,13 @@ hev_config_parse_doc (yaml_document_t *doc)
|
||||
if (tcp_buffer_size > TCP_SND_BUF)
|
||||
tcp_buffer_size = TCP_SND_BUF;
|
||||
|
||||
min_task_stack_size = TASK_STACK_SIZE + tcp_buffer_size;
|
||||
udp_buffer_size = UDP_BUF_SIZE * udp_copy_buffer_nums;
|
||||
|
||||
if (tcp_buffer_size > udp_buffer_size)
|
||||
min_task_stack_size = TASK_STACK_SIZE + tcp_buffer_size;
|
||||
else
|
||||
min_task_stack_size = TASK_STACK_SIZE + udp_buffer_size;
|
||||
|
||||
if (task_stack_size < min_task_stack_size)
|
||||
task_stack_size = min_task_stack_size;
|
||||
|
||||
@@ -575,6 +615,24 @@ hev_config_get_misc_tcp_buffer_size (void)
|
||||
return tcp_buffer_size;
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_udp_recv_buffer_size (void)
|
||||
{
|
||||
return udp_recv_buffer_size;
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_udp_copy_buffer_nums (void)
|
||||
{
|
||||
return udp_copy_buffer_nums;
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_max_session_count (void)
|
||||
{
|
||||
return max_session_count;
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_connect_timeout (void)
|
||||
{
|
||||
@@ -582,9 +640,15 @@ hev_config_get_misc_connect_timeout (void)
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_read_write_timeout (void)
|
||||
hev_config_get_misc_tcp_read_write_timeout (void)
|
||||
{
|
||||
return read_write_timeout;
|
||||
return tcp_read_write_timeout;
|
||||
}
|
||||
|
||||
int
|
||||
hev_config_get_misc_udp_read_write_timeout (void)
|
||||
{
|
||||
return udp_read_write_timeout;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -20,6 +20,7 @@ struct _HevConfigServer
|
||||
short udp_in_udp;
|
||||
unsigned short port;
|
||||
unsigned char pipeline;
|
||||
char udp_addr[256];
|
||||
char addr[256];
|
||||
};
|
||||
|
||||
@@ -48,8 +49,12 @@ int hev_config_get_mapdns_cache_size (void);
|
||||
|
||||
int hev_config_get_misc_task_stack_size (void);
|
||||
int hev_config_get_misc_tcp_buffer_size (void);
|
||||
int hev_config_get_misc_udp_recv_buffer_size (void);
|
||||
int hev_config_get_misc_udp_copy_buffer_nums (void);
|
||||
int hev_config_get_misc_max_session_count (void);
|
||||
int hev_config_get_misc_connect_timeout (void);
|
||||
int hev_config_get_misc_read_write_timeout (void);
|
||||
int hev_config_get_misc_tcp_read_write_timeout (void);
|
||||
int hev_config_get_misc_udp_read_write_timeout (void);
|
||||
int hev_config_get_misc_limit_nofile (void);
|
||||
const char *hev_config_get_misc_pid_file (void);
|
||||
const char *hev_config_get_misc_log_file (void);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <hev-task.h>
|
||||
#include <hev-task-system.h>
|
||||
#include <hev-socks5-misc.h>
|
||||
|
||||
#include "hev-utils.h"
|
||||
#include "hev-config.h"
|
||||
@@ -37,6 +38,16 @@ hev_socks5_tunnel_main_inner (int tun_fd)
|
||||
log_file = hev_config_get_misc_log_file ();
|
||||
log_level = hev_config_get_misc_log_level ();
|
||||
|
||||
res = hev_config_get_misc_connect_timeout ();
|
||||
hev_socks5_set_connect_timeout (res);
|
||||
res = hev_config_get_misc_tcp_read_write_timeout ();
|
||||
hev_socks5_set_tcp_timeout (res);
|
||||
res = hev_config_get_misc_udp_read_write_timeout ();
|
||||
hev_socks5_set_udp_timeout (res);
|
||||
|
||||
res = hev_config_get_misc_udp_recv_buffer_size ();
|
||||
hev_socks5_set_udp_recv_buffer_size (res);
|
||||
|
||||
res = hev_logger_init (log_level, log_file);
|
||||
if (res < 0)
|
||||
return -2;
|
||||
|
||||
@@ -23,10 +23,23 @@
|
||||
#include "hev-config.h"
|
||||
#include "hev-logger.h"
|
||||
#include "hev-config-const.h"
|
||||
#include "hev-socks5-tunnel.h"
|
||||
|
||||
#include "hev-socks5-session-tcp.h"
|
||||
|
||||
#define task_io_yielder hev_socks5_task_io_yielder
|
||||
static int
|
||||
task_io_yielder (HevTaskYieldType type, void *data)
|
||||
{
|
||||
HevSocks5Session *self = data;
|
||||
HevListNode *node;
|
||||
int res;
|
||||
|
||||
res = hev_socks5_task_io_yielder (type, data);
|
||||
node = hev_socks5_session_get_node (self);
|
||||
hev_socks5_tunnel_update_session (node);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
tcp_splice_f (HevSocks5SessionTCP *self)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "hev-logger.h"
|
||||
#include "hev-compiler.h"
|
||||
#include "hev-config-const.h"
|
||||
#include "hev-socks5-tunnel.h"
|
||||
|
||||
#include "hev-socks5-session-udp.h"
|
||||
|
||||
@@ -41,6 +42,8 @@ static int
|
||||
task_io_yielder (HevTaskYieldType type, void *data)
|
||||
{
|
||||
HevSocks5 *self = data;
|
||||
HevListNode *node;
|
||||
int res;
|
||||
|
||||
if (self->type == HEV_SOCKS5_TYPE_UDP_IN_UDP) {
|
||||
ssize_t res;
|
||||
@@ -53,119 +56,114 @@ task_io_yielder (HevTaskYieldType type, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
return hev_socks5_task_io_yielder (type, data);
|
||||
res = hev_socks5_task_io_yielder (type, data);
|
||||
node = hev_socks5_session_get_node (HEV_SOCKS5_SESSION (self));
|
||||
hev_socks5_tunnel_update_session (node);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_session_udp_fwd_f (HevSocks5SessionUDP *self)
|
||||
hev_socks5_session_udp_fwd_f (HevSocks5SessionUDP *self, unsigned int num)
|
||||
{
|
||||
HevSocks5UDPMsg msgv[num];
|
||||
HevSocks5UDPFrame *frame;
|
||||
HevListNode *node;
|
||||
HevSocks5UDP *udp;
|
||||
struct pbuf *buf;
|
||||
int res;
|
||||
int i, res;
|
||||
|
||||
for (;;) {
|
||||
node = hev_list_first (&self->frame_list);
|
||||
if (node)
|
||||
break;
|
||||
res = self->frames;
|
||||
if (res <= 0)
|
||||
return 0;
|
||||
|
||||
res = task_io_yielder (HEV_TASK_WAITIO, self);
|
||||
if (res < 0) {
|
||||
self->alive &= ~HEV_SOCKS5_SESSION_UDP_ALIVE_F;
|
||||
if (self->alive && hev_socks5_get_timeout (HEV_SOCKS5 (self)))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
res = (res > num) ? num : res;
|
||||
node = hev_list_first (&self->frame_list);
|
||||
for (i = 0; i < res; i++) {
|
||||
frame = container_of (node, HevSocks5UDPFrame, node);
|
||||
node = hev_list_node_next (node);
|
||||
buf = frame->data;
|
||||
|
||||
msgv[i].buf = buf->payload;
|
||||
msgv[i].len = buf->len;
|
||||
msgv[i].addr = &frame->addr;
|
||||
}
|
||||
|
||||
frame = container_of (node, HevSocks5UDPFrame, node);
|
||||
buf = frame->data;
|
||||
|
||||
udp = HEV_SOCKS5_UDP (self);
|
||||
res = hev_socks5_udp_sendto (udp, buf->payload, buf->len, &frame->addr);
|
||||
hev_list_del (&self->frame_list, node);
|
||||
hev_free (frame);
|
||||
pbuf_free (buf);
|
||||
self->frames--;
|
||||
res = hev_socks5_udp_sendmmsg (HEV_SOCKS5_UDP (self), msgv, res);
|
||||
if (res <= 0) {
|
||||
if (res < -1) {
|
||||
self->alive &= ~HEV_SOCKS5_SESSION_UDP_ALIVE_F;
|
||||
if (self->alive && hev_socks5_get_timeout (HEV_SOCKS5 (self)))
|
||||
return 0;
|
||||
}
|
||||
if (HEV_SOCKS5 (self)->type == HEV_SOCKS5_TYPE_UDP_IN_TCP)
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), 0);
|
||||
LOG_D ("%p socks5 session udp fwd f send", self);
|
||||
res = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->alive |= HEV_SOCKS5_SESSION_UDP_ALIVE_F;
|
||||
for (i = 0; i < res; i++) {
|
||||
node = hev_list_first (&self->frame_list);
|
||||
frame = container_of (node, HevSocks5UDPFrame, node);
|
||||
buf = frame->data;
|
||||
|
||||
return 0;
|
||||
hev_list_del (&self->frame_list, node);
|
||||
hev_free (frame);
|
||||
pbuf_free (buf);
|
||||
self->frames--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_session_udp_fwd_b (HevSocks5SessionUDP *self)
|
||||
hev_socks5_session_udp_fwd_b (HevSocks5SessionUDP *self, unsigned int num)
|
||||
{
|
||||
HevSocks5UDP *udp = HEV_SOCKS5_UDP (self);
|
||||
HevSocks5Addr addr;
|
||||
err_t err = ERR_OK;
|
||||
struct pbuf *buf;
|
||||
ip_addr_t saddr;
|
||||
uint16_t port;
|
||||
int res;
|
||||
char buf[UDP_BUF_SIZE * num];
|
||||
HevSocks5UDPMsg msgv[num];
|
||||
int i, res;
|
||||
|
||||
buf = pbuf_alloc (PBUF_TRANSPORT, UDP_BUF_SIZE, PBUF_RAM);
|
||||
if (!buf) {
|
||||
LOG_D ("%p socks5 session udp fwd b buf", self);
|
||||
for (i = 0; i < num; i++) {
|
||||
msgv[i].buf = buf + UDP_BUF_SIZE * i;
|
||||
msgv[i].len = UDP_BUF_SIZE;
|
||||
}
|
||||
|
||||
res = hev_socks5_udp_recvmmsg (HEV_SOCKS5_UDP (self), msgv, num, 1);
|
||||
if (res <= 0) {
|
||||
if (res == -1 && errno == EAGAIN)
|
||||
return 0;
|
||||
LOG_D ("%p socks5 session udp fwd b recv", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = hev_socks5_udp_recvfrom (udp, buf->payload, buf->len, &addr);
|
||||
if (res <= 0) {
|
||||
if (res < -1) {
|
||||
self->alive &= ~HEV_SOCKS5_SESSION_UDP_ALIVE_B;
|
||||
if (self->alive && hev_socks5_get_timeout (HEV_SOCKS5 (self))) {
|
||||
pbuf_free (buf);
|
||||
return 0;
|
||||
for (i = 0; i < res; i++) {
|
||||
ip_addr_t saddr;
|
||||
struct pbuf *b;
|
||||
uint16_t port;
|
||||
err_t err;
|
||||
int ret;
|
||||
|
||||
if (self->addr && self->port) {
|
||||
ip_2_ip4 (&saddr)->addr = self->addr;
|
||||
port = self->port;
|
||||
} else {
|
||||
ret = hev_socks5_addr_into_lwip (msgv[i].addr, &saddr, &port);
|
||||
if (ret < 0) {
|
||||
LOG_D ("%p socks5 session udp fwd b addr", self);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (HEV_SOCKS5 (self)->type == HEV_SOCKS5_TYPE_UDP_IN_TCP)
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), 0);
|
||||
LOG_D ("%p socks5 session udp fwd b recv", self);
|
||||
pbuf_free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf->len = res;
|
||||
buf->tot_len = res;
|
||||
b = pbuf_alloc_reference (msgv[i].buf, msgv[i].len, PBUF_REF);
|
||||
if (!b) {
|
||||
LOG_D ("%p socks5 session udp fwd b buf", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (self->addr && self->port) {
|
||||
ip_2_ip4 (&saddr)->addr = self->addr;
|
||||
port = self->port;
|
||||
} else {
|
||||
res = hev_socks5_addr_into_lwip (&addr, &saddr, &port);
|
||||
if (res < 0) {
|
||||
LOG_D ("%p socks5 session udp fwd b addr", self);
|
||||
pbuf_free (buf);
|
||||
hev_task_mutex_lock (self->mutex);
|
||||
err = udp_sendfrom (self->pcb, b, &saddr, port);
|
||||
hev_task_mutex_unlock (self->mutex);
|
||||
|
||||
pbuf_free (b);
|
||||
if (err != ERR_OK) {
|
||||
LOG_D ("%p socks5 session udp fwd b send", self);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hev_task_mutex_lock (self->mutex);
|
||||
err = udp_sendfrom (self->pcb, buf, &saddr, port);
|
||||
hev_task_mutex_unlock (self->mutex);
|
||||
pbuf_free (buf);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
LOG_D ("%p socks5 session udp fwd b send", self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->alive |= HEV_SOCKS5_SESSION_UDP_ALIVE_B;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -249,28 +247,39 @@ hev_socks5_session_udp_bind (HevSocks5 *self, int fd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
splice_task_entry (void *data)
|
||||
static uint16_t
|
||||
hev_socks5_addr_get_port (const HevSocks5Addr *addr)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
HevSocks5SessionUDP *self = data;
|
||||
int fd;
|
||||
uint16_t port = 0;
|
||||
|
||||
fd = hev_task_io_dup (hev_socks5_udp_get_fd (HEV_SOCKS5_UDP (self)));
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (hev_task_add_fd (task, fd, POLLIN) < 0)
|
||||
hev_task_mod_fd (task, fd, POLLIN);
|
||||
|
||||
for (;;) {
|
||||
if (hev_socks5_session_udp_fwd_b (self) < 0)
|
||||
break;
|
||||
switch (addr->atype) {
|
||||
case HEV_SOCKS5_ADDR_TYPE_IPV4:
|
||||
port = addr->ipv4.port;
|
||||
break;
|
||||
case HEV_SOCKS5_ADDR_TYPE_IPV6:
|
||||
port = addr->ipv6.port;
|
||||
break;
|
||||
case HEV_SOCKS5_ADDR_TYPE_NAME:
|
||||
memcpy (&port, addr->domain.addr + addr->domain.len, 2);
|
||||
}
|
||||
|
||||
self->alive &= ~HEV_SOCKS5_SESSION_UDP_ALIVE_B;
|
||||
hev_task_del_fd (task, fd);
|
||||
close (fd);
|
||||
return port;
|
||||
}
|
||||
|
||||
static int
|
||||
hev_socks5_session_udp_set_upstream_addr (HevSocks5Client *base,
|
||||
HevSocks5Addr *addr)
|
||||
{
|
||||
HevConfigServer *srv = hev_config_get_socks5_server ();
|
||||
HevSocks5ClientClass *ckptr;
|
||||
|
||||
if (srv->udp_in_udp && srv->udp_addr[0]) {
|
||||
uint16_t port = hev_socks5_addr_get_port (addr);
|
||||
hev_socks5_addr_from_name (addr, srv->udp_addr, port);
|
||||
}
|
||||
|
||||
ckptr = HEV_SOCKS5_CLIENT_CLASS (HEV_SOCKS5_CLIENT_UDP_TYPE);
|
||||
return ckptr->set_upstream_addr (base, addr);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -278,30 +287,35 @@ hev_socks5_session_udp_splice (HevSocks5Session *base)
|
||||
{
|
||||
HevSocks5SessionUDP *self = HEV_SOCKS5_SESSION_UDP (base);
|
||||
HevTask *task = hev_task_self ();
|
||||
int stack_size;
|
||||
int res_f = 1, res_b = 1;
|
||||
int num;
|
||||
int fd;
|
||||
|
||||
LOG_D ("%p socks5 session udp splice", self);
|
||||
|
||||
self->alive = HEV_SOCKS5_SESSION_UDP_ALIVE_F |
|
||||
HEV_SOCKS5_SESSION_UDP_ALIVE_B;
|
||||
num = hev_config_get_misc_udp_copy_buffer_nums ();
|
||||
fd = hev_socks5_udp_get_fd (HEV_SOCKS5_UDP (self));
|
||||
if (hev_task_mod_fd (task, fd, POLLOUT) < 0)
|
||||
hev_task_add_fd (task, fd, POLLOUT);
|
||||
|
||||
stack_size = hev_config_get_misc_task_stack_size ();
|
||||
task = hev_task_new (stack_size);
|
||||
hev_task_ref (task);
|
||||
hev_task_run (task, splice_task_entry, self);
|
||||
if (hev_task_mod_fd (task, fd, POLLIN | POLLOUT) < 0)
|
||||
hev_task_add_fd (task, fd, POLLIN | POLLOUT);
|
||||
|
||||
for (;;) {
|
||||
if (hev_socks5_session_udp_fwd_f (self) < 0)
|
||||
HevTaskYieldType type;
|
||||
|
||||
if (res_f >= 0)
|
||||
res_f = hev_socks5_session_udp_fwd_f (self, num);
|
||||
if (res_b >= 0)
|
||||
res_b = hev_socks5_session_udp_fwd_b (self, num);
|
||||
|
||||
if (res_f > 0 || res_b > 0)
|
||||
type = HEV_TASK_YIELD;
|
||||
else if ((res_f & res_b) == 0)
|
||||
type = HEV_TASK_WAITIO;
|
||||
else
|
||||
break;
|
||||
|
||||
if (task_io_yielder (type, self))
|
||||
break;
|
||||
}
|
||||
|
||||
self->alive &= ~HEV_SOCKS5_SESSION_UDP_ALIVE_F;
|
||||
hev_task_join (task);
|
||||
hev_task_unref (task);
|
||||
}
|
||||
|
||||
static HevTask *
|
||||
@@ -406,6 +420,7 @@ hev_socks5_session_udp_class (void)
|
||||
|
||||
if (!okptr->name) {
|
||||
HevSocks5Class *skptr;
|
||||
HevSocks5ClientClass *ckptr;
|
||||
HevSocks5SessionIface *siptr;
|
||||
void *ptr;
|
||||
|
||||
@@ -419,6 +434,9 @@ hev_socks5_session_udp_class (void)
|
||||
skptr = HEV_SOCKS5_CLASS (kptr);
|
||||
skptr->binder = hev_socks5_session_udp_bind;
|
||||
|
||||
ckptr = HEV_SOCKS5_CLIENT_CLASS (kptr);
|
||||
ckptr->set_upstream_addr = hev_socks5_session_udp_set_upstream_addr;
|
||||
|
||||
siptr = &kptr->session;
|
||||
siptr->splicer = hev_socks5_session_udp_splice;
|
||||
siptr->get_task = hev_socks5_session_udp_get_task;
|
||||
|
||||
@@ -18,23 +18,15 @@
|
||||
#define HEV_SOCKS5_SESSION_UDP_CLASS(p) ((HevSocks5SessionUDPClass *)p)
|
||||
#define HEV_SOCKS5_SESSION_UDP_TYPE (hev_socks5_session_udp_class ())
|
||||
|
||||
typedef enum _HevSocks5SessionUDPAlive HevSocks5SessionUDPAlive;
|
||||
typedef struct _HevSocks5SessionUDP HevSocks5SessionUDP;
|
||||
typedef struct _HevSocks5SessionUDPClass HevSocks5SessionUDPClass;
|
||||
|
||||
enum _HevSocks5SessionUDPAlive
|
||||
{
|
||||
HEV_SOCKS5_SESSION_UDP_ALIVE_F = (1 << 0),
|
||||
HEV_SOCKS5_SESSION_UDP_ALIVE_B = (1 << 1),
|
||||
};
|
||||
|
||||
struct _HevSocks5SessionUDP
|
||||
{
|
||||
HevSocks5ClientUDP base;
|
||||
|
||||
HevSocks5SessionData data;
|
||||
|
||||
HevSocks5SessionUDPAlive alive;
|
||||
HevList frame_list;
|
||||
struct udp_pcb *pcb;
|
||||
HevTaskMutex *mutex;
|
||||
|
||||
@@ -20,17 +20,11 @@ hev_socks5_session_run (HevSocks5Session *self)
|
||||
{
|
||||
HevSocks5SessionIface *iface;
|
||||
HevConfigServer *srv;
|
||||
int read_write_timeout;
|
||||
int connect_timeout;
|
||||
int res;
|
||||
|
||||
LOG_D ("%p socks5 session run", self);
|
||||
|
||||
srv = hev_config_get_socks5_server ();
|
||||
connect_timeout = hev_config_get_misc_connect_timeout ();
|
||||
read_write_timeout = hev_config_get_misc_read_write_timeout ();
|
||||
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), connect_timeout);
|
||||
|
||||
res = hev_socks5_client_connect (HEV_SOCKS5_CLIENT (self), srv->addr,
|
||||
srv->port);
|
||||
@@ -39,8 +33,6 @@ hev_socks5_session_run (HevSocks5Session *self)
|
||||
return;
|
||||
}
|
||||
|
||||
hev_socks5_set_timeout (HEV_SOCKS5 (self), read_write_timeout);
|
||||
|
||||
if (srv->user && srv->pass) {
|
||||
hev_socks5_client_set_auth (HEV_SOCKS5_CLIENT (self), srv->user,
|
||||
srv->pass);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <hev-memory-allocator.h>
|
||||
|
||||
#include "hev-exec.h"
|
||||
#include "hev-list.h"
|
||||
#include "hev-config.h"
|
||||
#include "hev-logger.h"
|
||||
#include "hev-tunnel.h"
|
||||
@@ -43,6 +42,7 @@
|
||||
static int run;
|
||||
static int tun_fd = -1;
|
||||
static int tun_fd_local;
|
||||
static int session_count;
|
||||
static int event_fds[2] = { -1, -1 };
|
||||
|
||||
static size_t stat_tx_packets;
|
||||
@@ -110,6 +110,44 @@ netif_init_handler (struct netif *netif)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
hev_socks5_tunnel_insert_session (HevListNode *node)
|
||||
{
|
||||
HevSocks5SessionData *sd;
|
||||
int max_session_count;
|
||||
|
||||
hev_list_add_tail (&session_set, node);
|
||||
session_count++;
|
||||
|
||||
max_session_count = hev_config_get_misc_max_session_count ();
|
||||
if (!max_session_count || session_count < max_session_count)
|
||||
return;
|
||||
|
||||
node = hev_list_first (&session_set);
|
||||
sd = container_of (node, HevSocks5SessionData, node);
|
||||
hev_socks5_session_terminate (sd->self);
|
||||
}
|
||||
|
||||
static void
|
||||
hev_socks5_tunnel_delete_session (HevListNode *node)
|
||||
{
|
||||
hev_list_del (&session_set, node);
|
||||
session_count--;
|
||||
}
|
||||
|
||||
void
|
||||
hev_socks5_tunnel_update_session (HevListNode *node)
|
||||
{
|
||||
int max_session_count;
|
||||
|
||||
max_session_count = hev_config_get_misc_max_session_count ();
|
||||
if (!max_session_count)
|
||||
return;
|
||||
|
||||
hev_list_del (&session_set, node);
|
||||
hev_list_add_tail (&session_set, node);
|
||||
}
|
||||
|
||||
static void
|
||||
hev_socks5_session_task_entry (void *data)
|
||||
{
|
||||
@@ -117,7 +155,7 @@ hev_socks5_session_task_entry (void *data)
|
||||
|
||||
hev_socks5_session_run (s);
|
||||
|
||||
hev_list_del (&session_set, hev_socks5_session_get_node (s));
|
||||
hev_socks5_tunnel_delete_session (hev_socks5_session_get_node (s));
|
||||
hev_object_unref (HEV_OBJECT (s));
|
||||
}
|
||||
|
||||
@@ -148,7 +186,7 @@ tcp_accept_handler (void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
|
||||
hev_socks5_session_set_task (HEV_SOCKS5_SESSION (tcp), task);
|
||||
node = hev_socks5_session_get_node (HEV_SOCKS5_SESSION (tcp));
|
||||
hev_list_add_tail (&session_set, node);
|
||||
hev_socks5_tunnel_insert_session (node);
|
||||
hev_task_run (task, hev_socks5_session_task_entry, tcp);
|
||||
hev_task_wakeup (task_lwip_timer);
|
||||
|
||||
@@ -225,7 +263,7 @@ udp_recv_handler (void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
|
||||
hev_socks5_session_set_task (HEV_SOCKS5_SESSION (udp), task);
|
||||
node = hev_socks5_session_get_node (HEV_SOCKS5_SESSION (udp));
|
||||
hev_list_add_tail (&session_set, node);
|
||||
hev_socks5_tunnel_insert_session (node);
|
||||
hev_task_run (task, hev_socks5_session_task_entry, udp);
|
||||
hev_task_wakeup (task_lwip_timer);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef __HEV_SOCKS5_TUNNEL_H__
|
||||
#define __HEV_SOCKS5_TUNNEL_H__
|
||||
|
||||
#include "hev-list.h"
|
||||
|
||||
int hev_socks5_tunnel_init (int tun_fd);
|
||||
void hev_socks5_tunnel_fini (void);
|
||||
|
||||
@@ -19,4 +21,6 @@ void hev_socks5_tunnel_stop (void);
|
||||
void hev_socks5_tunnel_stats (size_t *tx_packets, size_t *tx_bytes,
|
||||
size_t *rx_packets, size_t *rx_bytes);
|
||||
|
||||
void hev_socks5_tunnel_update_session (HevListNode *node);
|
||||
|
||||
#endif /* __HEV_SOCKS5_TUNNEL_H__ */
|
||||
|
||||
@@ -48,7 +48,7 @@ hev_logger_fini (void)
|
||||
int
|
||||
hev_logger_enabled (HevLoggerLevel level)
|
||||
{
|
||||
if (fd >= 0 && level >= req_level)
|
||||
if (level >= req_level && fd >= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -66,7 +66,7 @@ hev_logger_log (HevLoggerLevel level, const char *fmt, ...)
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
if (fd < 0 || level < req_level)
|
||||
if (level < req_level || fd < 0)
|
||||
return;
|
||||
|
||||
time (&now);
|
||||
|
||||
+11
-5
@@ -3,7 +3,7 @@ name: "Build"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -48,8 +48,14 @@ jobs:
|
||||
tool: mips-unknown-linux-musl
|
||||
- name: mips32sf
|
||||
tool: mips-unknown-linux-muslsf
|
||||
- name: or1k
|
||||
tool: or1k-unknown-linux-musl
|
||||
- name: powerpc64le
|
||||
tool: powerpc64le-unknown-linux-musl
|
||||
- name: powerpc64
|
||||
tool: powerpc64-unknown-linux-musl
|
||||
- name: powerpcle
|
||||
tool: powerpcle-unknown-linux-musl
|
||||
- name: powerpc
|
||||
tool: powerpc-unknown-linux-musl
|
||||
- name: riscv32
|
||||
@@ -71,7 +77,7 @@ jobs:
|
||||
- name: Build ${{ matrix.name }}
|
||||
run: |
|
||||
sudo mkdir -p /opt/x-tools
|
||||
wget https://github.com/cross-tools/musl-cross/releases/download/20250520/${{ matrix.tool }}.tar.xz
|
||||
wget https://github.com/cross-tools/musl-cross/releases/download/20250929/${{ matrix.tool }}.tar.xz
|
||||
sudo tar xf ${{ matrix.tool }}.tar.xz -C /opt/x-tools
|
||||
make CROSS_PREFIX=/opt/x-tools/${{ matrix.tool }}/bin/${{ matrix.tool }}- CFLAGS=${{ matrix.env.CFLAGS }} -j`nproc`
|
||||
|
||||
@@ -119,12 +125,12 @@ jobs:
|
||||
submodules: true
|
||||
- name: Prepare
|
||||
run: |
|
||||
wget https://dl.google.com/android/repository/android-ndk-r27b-linux.zip
|
||||
unzip android-ndk-r27b-linux.zip
|
||||
wget https://dl.google.com/android/repository/android-ndk-r27d-linux.zip
|
||||
unzip android-ndk-r27d-linux.zip
|
||||
ln -sf . jni
|
||||
- name: Build
|
||||
run: |
|
||||
./android-ndk-r27b/ndk-build
|
||||
./android-ndk-r27d/ndk-build
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ name: "Check code formatting"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# HevTaskSystem
|
||||
|
||||
[](https://github.com/heiher/hev-task-system)
|
||||
[](https://github.com/heiher/hev-task-system)
|
||||
|
||||
HevTaskSystem is a simple, lightweight multi-task system (coroutines).
|
||||
|
||||
@@ -85,14 +85,14 @@ make
|
||||
|
||||
## Demos
|
||||
|
||||
1. [simple](https://gitlab.com/hev/hev-task-system/blob/master/apps/simple.c)
|
||||
1. [channel](https://gitlab.com/hev/hev-task-system/blob/master/apps/channel.c)
|
||||
1. [timeout](https://gitlab.com/hev/hev-task-system/blob/master/apps/timeout.c)
|
||||
1. [wakeup](https://gitlab.com/hev/hev-task-system/blob/master/apps/wakeup.c)
|
||||
1. [echo-server](https://gitlab.com/hev/hev-task-system/blob/master/apps/echo-server.c)
|
||||
1. [call](https://gitlab.com/hev/hev-task-system/blob/master/apps/call.c)
|
||||
1. [gtk](https://gitlab.com/hev/hev-task-system/blob/master/apps/gtk.c)
|
||||
1. [curl](https://gitlab.com/hev/hev-task-system/blob/master/apps/curl.c)
|
||||
1. [simple](https://gitlab.com/hev/hev-task-system/blob/main/apps/simple.c)
|
||||
1. [channel](https://gitlab.com/hev/hev-task-system/blob/main/apps/channel.c)
|
||||
1. [timeout](https://gitlab.com/hev/hev-task-system/blob/main/apps/timeout.c)
|
||||
1. [wakeup](https://gitlab.com/hev/hev-task-system/blob/main/apps/wakeup.c)
|
||||
1. [echo-server](https://gitlab.com/hev/hev-task-system/blob/main/apps/echo-server.c)
|
||||
1. [call](https://gitlab.com/hev/hev-task-system/blob/main/apps/call.c)
|
||||
1. [gtk](https://gitlab.com/hev/hev-task-system/blob/main/apps/gtk.c)
|
||||
1. [curl](https://gitlab.com/hev/hev-task-system/blob/main/apps/curl.c)
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
============================================================================
|
||||
Name : hev-task-execute-or1k.s
|
||||
Author : Heiher <r@hev.cc>
|
||||
Copyright : Copyright (c) 2025 everyone.
|
||||
Description :
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
.globl hev_task_execute
|
||||
.type hev_task_execute, @function
|
||||
|
||||
hev_task_execute:
|
||||
l.lwz r11, 0(r3)
|
||||
l.sw -4(r11), r1
|
||||
l.sw -8(r11), r9
|
||||
l.addi r1, r11, -8
|
||||
|
||||
l.jalr r4
|
||||
l.nop
|
||||
|
||||
l.lwz r9, 0(r1)
|
||||
l.lwz r1, 4(r1)
|
||||
l.jr r9
|
||||
l.nop
|
||||
|
||||
.end hev_task_execute
|
||||
.size hev_task_execute, . - hev_task_execute
|
||||
+2
-2
@@ -15,8 +15,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define HEV_TASK_SYSTEM_MAJOR_VERSION (5)
|
||||
#define HEV_TASK_SYSTEM_MINOR_VERSION (8)
|
||||
#define HEV_TASK_SYSTEM_MICRO_VERSION (1)
|
||||
#define HEV_TASK_SYSTEM_MINOR_VERSION (10)
|
||||
#define HEV_TASK_SYSTEM_MICRO_VERSION (0)
|
||||
|
||||
/**
|
||||
* hev_task_system_init:
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
|
||||
# include "arch/sh/hev-task-execute-sh.s"
|
||||
|
||||
#elif defined(__or1k__)
|
||||
|
||||
# include "arch/openrisc/hev-task-execute-or1k.s"
|
||||
|
||||
#else
|
||||
|
||||
# error "Unsupported platform!"
|
||||
|
||||
+118
-55
@@ -82,10 +82,11 @@ hev_task_io_socket_connect (int fd, const struct sockaddr *addr,
|
||||
socklen_t addr_len, HevTaskIOYielder yielder,
|
||||
void *yielder_data)
|
||||
{
|
||||
int ret;
|
||||
int res;
|
||||
|
||||
retry:
|
||||
ret = connect (fd, addr, addr_len);
|
||||
if (ret < 0) {
|
||||
res = connect (fd, addr, addr_len);
|
||||
if (res < 0) {
|
||||
if (errno == EINPROGRESS || errno == EALREADY) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
@@ -95,11 +96,11 @@ retry:
|
||||
}
|
||||
goto retry;
|
||||
} else if (errno == EISCONN) {
|
||||
ret = 0;
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return res;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL int
|
||||
@@ -142,15 +143,15 @@ EXPORT_SYMBOL ssize_t
|
||||
hev_task_io_socket_recv (int fd, void *buf, size_t len, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
size_t size = 0;
|
||||
ssize_t s;
|
||||
|
||||
retry:
|
||||
s = recv (fd, buf + size, len - size, flags & ~MSG_WAITALL);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -160,11 +161,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len)
|
||||
@@ -177,15 +175,15 @@ EXPORT_SYMBOL ssize_t
|
||||
hev_task_io_socket_send (int fd, const void *buf, size_t len, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
size_t size = 0;
|
||||
ssize_t s;
|
||||
|
||||
retry:
|
||||
s = send (fd, buf + size, len - size, flags & ~MSG_WAITALL);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -195,11 +193,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len)
|
||||
@@ -213,16 +208,16 @@ hev_task_io_socket_recvfrom (int fd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *addr, socklen_t *addr_len,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
size_t size = 0;
|
||||
ssize_t s;
|
||||
|
||||
retry:
|
||||
s = recvfrom (fd, buf + size, len - size, flags & ~MSG_WAITALL, addr,
|
||||
addr_len);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -232,11 +227,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len)
|
||||
@@ -250,16 +242,16 @@ hev_task_io_socket_sendto (int fd, const void *buf, size_t len, int flags,
|
||||
const struct sockaddr *addr, socklen_t addr_len,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
size_t size = 0;
|
||||
ssize_t s;
|
||||
|
||||
retry:
|
||||
s = sendto (fd, buf + size, len - size, flags & ~MSG_WAITALL, addr,
|
||||
addr_len);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -269,11 +261,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len)
|
||||
@@ -286,10 +275,10 @@ EXPORT_SYMBOL ssize_t
|
||||
hev_task_io_socket_recvmsg (int fd, struct msghdr *msg, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
struct iovec iov[msg->msg_iovlen];
|
||||
size_t i, size = 0, len = 0;
|
||||
struct msghdr mh;
|
||||
struct iovec iov[msg->msg_iovlen];
|
||||
ssize_t s;
|
||||
|
||||
mh.msg_name = msg->msg_name;
|
||||
mh.msg_namelen = msg->msg_namelen;
|
||||
@@ -306,10 +295,10 @@ hev_task_io_socket_recvmsg (int fd, struct msghdr *msg, int flags,
|
||||
|
||||
retry:
|
||||
s = recvmsg (fd, &mh, flags & ~MSG_WAITALL);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -319,11 +308,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len) {
|
||||
@@ -350,10 +336,10 @@ EXPORT_SYMBOL ssize_t
|
||||
hev_task_io_socket_sendmsg (int fd, const struct msghdr *msg, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
ssize_t s;
|
||||
struct iovec iov[msg->msg_iovlen];
|
||||
size_t i, size = 0, len = 0;
|
||||
struct msghdr mh;
|
||||
struct iovec iov[msg->msg_iovlen];
|
||||
ssize_t s;
|
||||
|
||||
mh.msg_name = msg->msg_name;
|
||||
mh.msg_namelen = msg->msg_namelen;
|
||||
@@ -370,10 +356,10 @@ hev_task_io_socket_sendmsg (int fd, const struct msghdr *msg, int flags,
|
||||
|
||||
retry:
|
||||
s = sendmsg (fd, &mh, flags & ~MSG_WAITALL);
|
||||
if (s < 0 && errno == EAGAIN) {
|
||||
if (s < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return -2;
|
||||
return size ? size : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
@@ -383,11 +369,8 @@ retry:
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return s;
|
||||
|
||||
if (s <= 0) {
|
||||
if (size)
|
||||
return size;
|
||||
return s;
|
||||
}
|
||||
if (s <= 0)
|
||||
return size ? size : s;
|
||||
|
||||
size += s;
|
||||
if (size < len) {
|
||||
@@ -409,3 +392,83 @@ retry:
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL int
|
||||
hev_task_io_socket_recvmmsg (int fd, void *_msgv, unsigned int n, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
struct mmsghdr *msgv = _msgv;
|
||||
int r, c = 0;
|
||||
|
||||
retry:
|
||||
#ifdef MSG_WAITFORONE
|
||||
r = recvmmsg (fd, &msgv[c], n - c, flags & ~MSG_WAITALL, NULL);
|
||||
#else
|
||||
r = recvmsg (fd, &msgv[c].msg_hdr, flags & ~MSG_WAITALL);
|
||||
if (r >= 0) {
|
||||
msgv[c].msg_len = r;
|
||||
r = 1;
|
||||
}
|
||||
#endif
|
||||
if (r < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return c ? c : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return r;
|
||||
|
||||
if (r <= 0)
|
||||
return c ? c : r;
|
||||
|
||||
c += r;
|
||||
if (c < n)
|
||||
goto retry;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL int
|
||||
hev_task_io_socket_sendmmsg (int fd, void *_msgv, unsigned int n, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data)
|
||||
{
|
||||
struct mmsghdr *msgv = _msgv;
|
||||
int r, c = 0;
|
||||
|
||||
retry:
|
||||
#ifdef MSG_WAITFORONE
|
||||
r = sendmmsg (fd, &msgv[c], n - c, flags & ~MSG_WAITALL);
|
||||
#else
|
||||
r = sendmsg (fd, &msgv[c].msg_hdr, flags & ~MSG_WAITALL);
|
||||
if (r >= 0) {
|
||||
msgv[c].msg_len = r;
|
||||
r = 1;
|
||||
}
|
||||
#endif
|
||||
if (r < 0 && errno == EAGAIN && !(flags & MSG_DONTWAIT)) {
|
||||
if (yielder) {
|
||||
if (yielder (HEV_TASK_WAITIO, yielder_data))
|
||||
return c ? c : -2;
|
||||
} else {
|
||||
hev_task_yield (HEV_TASK_WAITIO);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!(flags & MSG_WAITALL))
|
||||
return r;
|
||||
|
||||
if (r <= 0)
|
||||
return c ? c : r;
|
||||
|
||||
c += r;
|
||||
if (c < n)
|
||||
goto retry;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
+50
@@ -16,6 +16,14 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MSG_WAITFORONE
|
||||
struct mmsghdr
|
||||
{
|
||||
struct msghdr msg_hdr;
|
||||
unsigned int msg_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hev_task_io_socket_socket:
|
||||
* @domain: the communications domain
|
||||
@@ -224,6 +232,48 @@ ssize_t hev_task_io_socket_sendmsg (int fd, const struct msghdr *msg, int flags,
|
||||
HevTaskIOYielder yielder,
|
||||
void *yielder_data);
|
||||
|
||||
/**
|
||||
* hev_task_io_socket_recvmmsg:
|
||||
* @fd: a file descriptor
|
||||
* @msgv: an array of mmsghdr structures
|
||||
* @n: size of mmsghdr array
|
||||
* @flags: flags
|
||||
* @yielder: a #HevTaskIOYielder
|
||||
* @yielder_data: user data
|
||||
*
|
||||
* The recvmmsg function that allows the caller to receive multiple messages
|
||||
* from a socket using a single system call.
|
||||
*
|
||||
* The recvmmsg is not supported for stream sockets.
|
||||
*
|
||||
* Returns: the number of messages received in msgv
|
||||
*
|
||||
* Since: 5.10
|
||||
*/
|
||||
int hev_task_io_socket_recvmmsg (int fd, void *msgv, unsigned int n, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data);
|
||||
|
||||
/**
|
||||
* hev_task_io_socket_sendmmsg:
|
||||
* @fd: a file descriptor
|
||||
* @msgv: an array of mmsghdr structures
|
||||
* @n: size of mmsghdr array
|
||||
* @flags: flags
|
||||
* @yielder: a #HevTaskIOYielder
|
||||
* @yielder_data: user data
|
||||
*
|
||||
* The sendmmsg that allows the caller to transmit multiple messages on a
|
||||
* socket using a single system call.
|
||||
*
|
||||
* The sendmmsg is not supported for stream sockets.
|
||||
*
|
||||
* Returns: the number of messages sent from msgv
|
||||
*
|
||||
* Since: 5.10
|
||||
*/
|
||||
int hev_task_io_socket_sendmmsg (int fd, void *msgv, unsigned int n, int flags,
|
||||
HevTaskIOYielder yielder, void *yielder_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
@@ -21,10 +22,11 @@
|
||||
#include <hev-task-io-socket.h>
|
||||
|
||||
static int port;
|
||||
static int fds[2];
|
||||
static const char *msg = "Hello!";
|
||||
|
||||
static void
|
||||
task_server_entry (void *data)
|
||||
task_tcp_server_entry (void *data)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
int fd, cfd;
|
||||
@@ -88,7 +90,7 @@ task_server_entry (void *data)
|
||||
}
|
||||
|
||||
static void
|
||||
task_client_entry (void *data)
|
||||
task_tcp_client_entry (void *data)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
int fd;
|
||||
@@ -140,6 +142,80 @@ task_client_entry (void *data)
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
task_udp_server_entry (void *data)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
struct mmsghdr msgv[10];
|
||||
struct iovec iov[10];
|
||||
char bufs[128][10];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
msgv[i].msg_hdr.msg_name = NULL;
|
||||
msgv[i].msg_hdr.msg_namelen = 0;
|
||||
msgv[i].msg_hdr.msg_control = NULL;
|
||||
msgv[i].msg_hdr.msg_controllen = 0;
|
||||
msgv[i].msg_hdr.msg_flags = 0;
|
||||
msgv[i].msg_hdr.msg_iov = &iov[i];
|
||||
msgv[i].msg_hdr.msg_iovlen = 1;
|
||||
msgv[i].msg_len = 0;
|
||||
|
||||
iov[i].iov_base = bufs[i];
|
||||
iov[i].iov_len = 128;
|
||||
}
|
||||
|
||||
assert (hev_task_add_fd (task, fds[0], POLLIN) == 0);
|
||||
|
||||
i = hev_task_io_socket_recvmmsg (fds[0], msgv, 10, MSG_WAITALL, NULL, NULL);
|
||||
assert (i == 10);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
int res;
|
||||
|
||||
assert (msgv[i].msg_len == strlen (msg));
|
||||
res = memcmp (msgv[i].msg_hdr.msg_iov[0].iov_base, msg, strlen (msg));
|
||||
assert (res == 0);
|
||||
}
|
||||
|
||||
assert (hev_task_del_fd (task, fds[0]) == 0);
|
||||
close (fds[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
task_udp_client_entry (void *data)
|
||||
{
|
||||
HevTask *task = hev_task_self ();
|
||||
struct mmsghdr msgv[10];
|
||||
struct iovec iov[10];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
msgv[i].msg_hdr.msg_name = NULL;
|
||||
msgv[i].msg_hdr.msg_namelen = 0;
|
||||
msgv[i].msg_hdr.msg_control = NULL;
|
||||
msgv[i].msg_hdr.msg_controllen = 0;
|
||||
msgv[i].msg_hdr.msg_flags = 0;
|
||||
msgv[i].msg_hdr.msg_iov = &iov[i];
|
||||
msgv[i].msg_hdr.msg_iovlen = 1;
|
||||
msgv[i].msg_len = 0;
|
||||
|
||||
iov[i].iov_base = (void *)msg;
|
||||
iov[i].iov_len = strlen (msg);
|
||||
}
|
||||
|
||||
assert (hev_task_add_fd (task, fds[1], POLLOUT) == 0);
|
||||
|
||||
i = hev_task_io_socket_sendmmsg (fds[1], msgv, 10, MSG_WAITALL, NULL, NULL);
|
||||
assert (i == 10);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
assert (msgv[i].msg_len == strlen (msg));
|
||||
|
||||
assert (hev_task_del_fd (task, fds[1]) == 0);
|
||||
close (fds[1]);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -150,12 +226,24 @@ main (int argc, char *argv[])
|
||||
task = hev_task_new (-1);
|
||||
assert (task);
|
||||
hev_task_set_priority (task, 1);
|
||||
hev_task_run (task, task_server_entry, NULL);
|
||||
hev_task_run (task, task_tcp_server_entry, NULL);
|
||||
|
||||
task = hev_task_new (-1);
|
||||
assert (task);
|
||||
hev_task_set_priority (task, 2);
|
||||
hev_task_run (task, task_client_entry, NULL);
|
||||
hev_task_run (task, task_tcp_client_entry, NULL);
|
||||
|
||||
assert (hev_task_io_socket_socketpair (PF_LOCAL, SOCK_DGRAM, 0, fds) == 0);
|
||||
|
||||
task = hev_task_new (-1);
|
||||
assert (task);
|
||||
hev_task_set_priority (task, 1);
|
||||
hev_task_run (task, task_udp_server_entry, NULL);
|
||||
|
||||
task = hev_task_new (-1);
|
||||
assert (task);
|
||||
hev_task_set_priority (task, 2);
|
||||
hev_task_run (task, task_udp_client_entry, NULL);
|
||||
|
||||
hev_task_system_run ();
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.24"
|
||||
go-version: "1.25"
|
||||
|
||||
- name: Setup Python # This is for the build script
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.24"
|
||||
go-version: "1.25"
|
||||
|
||||
- name: Setup Python # This is for the build script
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
@@ -467,4 +467,6 @@ $RECYCLE.BIN/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/goland+all,intellij+all,go,windows,linux,macos,python,pycharm+all
|
||||
# End of https://www.toptal.com/developers/gitignore/api/goland+all,intellij+all,go,windows,linux,macos,python,pycharm+all
|
||||
|
||||
test-configs/
|
||||
|
||||
@@ -2,6 +2,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
@@ -96,10 +97,12 @@ type clientConfigObfs struct {
|
||||
}
|
||||
|
||||
type clientConfigTLS struct {
|
||||
SNI string `mapstructure:"sni"`
|
||||
Insecure bool `mapstructure:"insecure"`
|
||||
PinSHA256 string `mapstructure:"pinSHA256"`
|
||||
CA string `mapstructure:"ca"`
|
||||
SNI string `mapstructure:"sni"`
|
||||
Insecure bool `mapstructure:"insecure"`
|
||||
PinSHA256 string `mapstructure:"pinSHA256"`
|
||||
CA string `mapstructure:"ca"`
|
||||
ClientCertificate string `mapstructure:"clientCertificate"`
|
||||
ClientKey string `mapstructure:"clientKey"`
|
||||
}
|
||||
|
||||
type clientConfigQUIC struct {
|
||||
@@ -272,12 +275,11 @@ func (c *clientConfig) fillTLSConfig(hyConfig *client.Config) error {
|
||||
if c.TLS.PinSHA256 != "" {
|
||||
nHash := normalizeCertHash(c.TLS.PinSHA256)
|
||||
hyConfig.TLSConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||
for _, cert := range rawCerts {
|
||||
hash := sha256.Sum256(cert)
|
||||
hashHex := hex.EncodeToString(hash[:])
|
||||
if hashHex == nHash {
|
||||
return nil
|
||||
}
|
||||
cert := rawCerts[0] // only check the end-entity cert hash in the chain of trust
|
||||
hash := sha256.Sum256(cert)
|
||||
hashHex := hex.EncodeToString(hash[:])
|
||||
if hashHex == nHash {
|
||||
return nil
|
||||
}
|
||||
// No match
|
||||
return errors.New("no certificate matches the pinned hash")
|
||||
@@ -294,6 +296,31 @@ func (c *clientConfig) fillTLSConfig(hyConfig *client.Config) error {
|
||||
}
|
||||
hyConfig.TLSConfig.RootCAs = cPool
|
||||
}
|
||||
if c.TLS.ClientCertificate != "" && c.TLS.ClientKey != "" {
|
||||
certLoader := &utils.LocalCertificateLoader{
|
||||
CertFile: c.TLS.ClientCertificate,
|
||||
KeyFile: c.TLS.ClientKey,
|
||||
}
|
||||
// Try loading the cert-key pair here to catch errors early
|
||||
err := certLoader.InitializeCache()
|
||||
if err != nil {
|
||||
var pathErr *os.PathError
|
||||
if errors.As(err, &pathErr) {
|
||||
if pathErr.Path == c.TLS.ClientCertificate {
|
||||
return configError{Field: "tls.clientCertificate", Err: pathErr}
|
||||
}
|
||||
if pathErr.Path == c.TLS.ClientKey {
|
||||
return configError{Field: "tls.clientKey", Err: pathErr}
|
||||
}
|
||||
}
|
||||
return configError{Field: "tls.clientCertificate", Err: err}
|
||||
}
|
||||
// Use GetClientCertificates so that users can update the cert without restarting the client.
|
||||
hyConfig.TLSConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
// For simplicity, always respond with the configured client certs, regardless of server requests.
|
||||
return certLoader.GetCertificate(nil)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,12 @@ func TestClientConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
TLS: clientConfigTLS{
|
||||
SNI: "another.example.com",
|
||||
Insecure: true,
|
||||
PinSHA256: "114515DEADBEEF",
|
||||
CA: "custom_ca.crt",
|
||||
SNI: "another.example.com",
|
||||
Insecure: true,
|
||||
PinSHA256: "114515DEADBEEF",
|
||||
CA: "custom_ca.crt",
|
||||
ClientCertificate: "client.crt",
|
||||
ClientKey: "client.key",
|
||||
},
|
||||
QUIC: clientConfigQUIC{
|
||||
InitStreamReceiveWindow: 1145141,
|
||||
|
||||
@@ -17,6 +17,8 @@ tls:
|
||||
insecure: true
|
||||
pinSHA256: 114515DEADBEEF
|
||||
ca: custom_ca.crt
|
||||
clientCertificate: client.crt
|
||||
clientKey: client.key
|
||||
|
||||
quic:
|
||||
initStreamReceiveWindow: 1145141
|
||||
|
||||
@@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -86,6 +87,7 @@ type serverConfigTLS struct {
|
||||
Cert string `mapstructure:"cert"`
|
||||
Key string `mapstructure:"key"`
|
||||
SNIGuard string `mapstructure:"sniGuard"` // "disable", "dns-san", "strict"
|
||||
ClientCA string `mapstructure:"clientCA"`
|
||||
}
|
||||
|
||||
type serverConfigACME struct {
|
||||
@@ -333,6 +335,18 @@ func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
|
||||
// Use GetCertificate instead of Certificates so that
|
||||
// users can update the cert without restarting the server.
|
||||
hyConfig.TLSConfig.GetCertificate = certLoader.GetCertificate
|
||||
// Client CA
|
||||
if c.TLS.ClientCA != "" {
|
||||
ca, err := os.ReadFile(c.TLS.ClientCA)
|
||||
if err != nil {
|
||||
return configError{Field: "tls.clientCA", Err: err}
|
||||
}
|
||||
cPool := x509.NewCertPool()
|
||||
if !cPool.AppendCertsFromPEM(ca) {
|
||||
return configError{Field: "tls.clientCA", Err: errors.New("failed to parse client CA certificate")}
|
||||
}
|
||||
hyConfig.TLSConfig.ClientCAs = cPool
|
||||
}
|
||||
} else {
|
||||
// ACME
|
||||
dataDir := c.ACME.Dir
|
||||
|
||||
@@ -29,6 +29,7 @@ func TestServerConfig(t *testing.T) {
|
||||
Cert: "some.crt",
|
||||
Key: "some.key",
|
||||
SNIGuard: "strict",
|
||||
ClientCA: "some_ca.crt",
|
||||
},
|
||||
ACME: &serverConfigACME{
|
||||
Domains: []string{
|
||||
|
||||
@@ -9,6 +9,7 @@ tls:
|
||||
cert: some.crt
|
||||
key: some.key
|
||||
sniGuard: strict
|
||||
clientCA: some_ca.crt
|
||||
|
||||
acme:
|
||||
domains:
|
||||
|
||||
@@ -2,13 +2,13 @@ module github.com/apernet/hysteria/app/v2
|
||||
|
||||
go 1.23
|
||||
|
||||
toolchain go1.24.2
|
||||
toolchain go1.25.1
|
||||
|
||||
require (
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f
|
||||
github.com/apernet/hysteria/core/v2 v2.0.0-00010101000000-000000000000
|
||||
github.com/apernet/hysteria/extras/v2 v2.0.0-00010101000000-000000000000
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250726070404-c99085f9af13
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250920121535-299f04629986
|
||||
github.com/caddyserver/certmagic v0.17.2
|
||||
github.com/libdns/cloudflare v0.1.1
|
||||
github.com/libdns/duckdns v0.2.0
|
||||
@@ -30,17 +30,14 @@ require (
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431 // indirect
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 // indirect
|
||||
github.com/cloudflare/circl v1.3.9 // indirect
|
||||
github.com/database64128/netx-go v0.0.0-20240905055117-62795b8b054a // indirect
|
||||
github.com/database64128/tfo-go/v2 v2.2.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.6 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
|
||||
@@ -52,7 +49,6 @@ require (
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/miekg/dns v1.1.59 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
||||
@@ -42,12 +42,10 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM=
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431 h1:9/jM7e+kVALd7Jfu1c27dcEpT/Fd/Gzq2OsQjKjakKI=
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431/go.mod h1:I/47OIGG5H/IfAm+nz2c6hm6b/NkEhpvptAoiPcY7jQ=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250726070404-c99085f9af13 h1:gzets97c/u5iMj1zjanMBVkIYOdaVw+RXPzTT1xQoyM=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250726070404-c99085f9af13/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 h1:WgFl2esvC7FnVhhBvA+BJUgxyheiTAhJ4CIbRlaK22I=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250920121535-299f04629986 h1:w62V0oOO2Do0vXeZkx7mgZ2YFuUaRcO6rNZewI3xzuE=
|
||||
github.com/apernet/sing-tun v0.2.6-0.20250920121535-299f04629986/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/caddyserver/certmagic v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
|
||||
@@ -85,12 +83,8 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -116,8 +110,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -146,8 +138,6 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
@@ -215,10 +205,6 @@ github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||
@@ -265,7 +251,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.43.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.5. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
@@ -23,7 +23,7 @@ func (_m *MockConn) EXPECT() *MockConn_Expecter {
|
||||
return &MockConn_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
// Close provides a mock function with no fields
|
||||
func (_m *MockConn) Close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -68,7 +68,7 @@ func (_c *MockConn_Close_Call) RunAndReturn(run func() error) *MockConn_Close_Ca
|
||||
return _c
|
||||
}
|
||||
|
||||
// LocalAddr provides a mock function with given fields:
|
||||
// LocalAddr provides a mock function with no fields
|
||||
func (_m *MockConn) LocalAddr() net.Addr {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -171,7 +171,7 @@ func (_c *MockConn_Read_Call) RunAndReturn(run func([]byte) (int, error)) *MockC
|
||||
return _c
|
||||
}
|
||||
|
||||
// RemoteAddr provides a mock function with given fields:
|
||||
// RemoteAddr provides a mock function with no fields
|
||||
func (_m *MockConn) RemoteAddr() net.Addr {
|
||||
ret := _m.Called()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.43.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.5. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
@@ -21,7 +21,7 @@ func (_m *MockListener) EXPECT() *MockListener_Expecter {
|
||||
return &MockListener_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Accept provides a mock function with given fields:
|
||||
// Accept provides a mock function with no fields
|
||||
func (_m *MockListener) Accept() (net.Conn, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -78,7 +78,7 @@ func (_c *MockListener_Accept_Call) RunAndReturn(run func() (net.Conn, error)) *
|
||||
return _c
|
||||
}
|
||||
|
||||
// Addr provides a mock function with given fields:
|
||||
// Addr provides a mock function with no fields
|
||||
func (_m *MockListener) Addr() net.Addr {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -125,7 +125,7 @@ func (_c *MockListener_Addr_Call) RunAndReturn(run func() net.Addr) *MockListene
|
||||
return _c
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields:
|
||||
// Close provides a mock function with no fields
|
||||
func (_m *MockListener) Close() error {
|
||||
ret := _m.Called()
|
||||
|
||||
|
||||
@@ -13,5 +13,5 @@ func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint32) (err
|
||||
if e != 0 {
|
||||
err = e
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ func getsockopt(s, level, name uintptr, val unsafe.Pointer, vallen *uint32) (err
|
||||
if e != 0 {
|
||||
err = e
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -42,15 +42,15 @@ func (e *UnsupportedError) Error() string {
|
||||
func (o *SocketOptions) ListenUDP() (uconn net.PacketConn, err error) {
|
||||
uconn, err = net.ListenUDP("udp", nil)
|
||||
if err != nil {
|
||||
return
|
||||
return uconn, err
|
||||
}
|
||||
err = o.applyToUDPConn(uconn.(*net.UDPConn))
|
||||
if err != nil {
|
||||
uconn.Close()
|
||||
uconn = nil
|
||||
return
|
||||
return uconn, err
|
||||
}
|
||||
return
|
||||
return uconn, err
|
||||
}
|
||||
|
||||
func (o *SocketOptions) applyToUDPConn(c *net.UDPConn) error {
|
||||
|
||||
@@ -24,19 +24,19 @@ func init() {
|
||||
func controlUDPConn(c *net.UDPConn, cb func(fd int) error) (err error) {
|
||||
rconn, err := c.SyscallConn()
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
cerr := rconn.Control(func(fd uintptr) {
|
||||
err = cb(int(fd))
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if cerr != nil {
|
||||
err = fmt.Errorf("failed to control fd: %w", cerr)
|
||||
return
|
||||
return err
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
func bindInterfaceImpl(c *net.UDPConn, device string) error {
|
||||
|
||||
@@ -42,12 +42,12 @@ func Test_fdControlUnixSocketImpl(t *testing.T) {
|
||||
err = controlUDPConn(conn.(*net.UDPConn), func(fd int) (err error) {
|
||||
rcvbuf, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_RCVBUF)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
// The test server called setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 2500),
|
||||
// and kernel will double this value for getsockopt().
|
||||
assert.Equal(t, 5000, rcvbuf)
|
||||
return
|
||||
return err
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -1173,7 +1173,7 @@ func splitHostPort(hostPort string) (host, port string) {
|
||||
host = host[1 : len(host)-1]
|
||||
}
|
||||
|
||||
return
|
||||
return host, port
|
||||
}
|
||||
|
||||
// Marshaling interface implementations.
|
||||
@@ -1263,8 +1263,8 @@ func stringContainsCTLByte(s string) bool {
|
||||
func JoinPath(base string, elem ...string) (result string, err error) {
|
||||
url, err := Parse(base)
|
||||
if err != nil {
|
||||
return
|
||||
return result, err
|
||||
}
|
||||
result = url.JoinPath(elem...).String()
|
||||
return
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -68,17 +68,17 @@ func (l *LocalCertificateLoader) checkModTime() (certModTime, keyModTime time.Ti
|
||||
fi, err := os.Stat(l.CertFile)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to stat certificate file: %w", err)
|
||||
return
|
||||
return certModTime, keyModTime, err
|
||||
}
|
||||
certModTime = fi.ModTime()
|
||||
|
||||
fi, err = os.Stat(l.KeyFile)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to stat key file: %w", err)
|
||||
return
|
||||
return certModTime, keyModTime, err
|
||||
}
|
||||
keyModTime = fi.ModTime()
|
||||
return
|
||||
return certModTime, keyModTime, err
|
||||
}
|
||||
|
||||
func (l *LocalCertificateLoader) makeCache() (cache *localCertificateCache, err error) {
|
||||
@@ -86,24 +86,24 @@ func (l *LocalCertificateLoader) makeCache() (cache *localCertificateCache, err
|
||||
|
||||
c.certModTime, c.keyModTime, err = l.checkModTime()
|
||||
if err != nil {
|
||||
return
|
||||
return cache, err
|
||||
}
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(l.CertFile, l.KeyFile)
|
||||
if err != nil {
|
||||
return
|
||||
return cache, err
|
||||
}
|
||||
c.certificate = &cert
|
||||
if c.certificate.Leaf == nil {
|
||||
// certificate.Leaf was left nil by tls.LoadX509KeyPair before Go 1.23
|
||||
c.certificate.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
return
|
||||
return cache, err
|
||||
}
|
||||
}
|
||||
|
||||
cache = c
|
||||
return
|
||||
return cache, err
|
||||
}
|
||||
|
||||
func (l *LocalCertificateLoader) getCertificateWithCache() (*tls.Certificate, error) {
|
||||
|
||||
@@ -58,7 +58,7 @@ type clientImpl struct {
|
||||
config *Config
|
||||
|
||||
pktConn net.PacketConn
|
||||
conn quic.Connection
|
||||
conn *quic.Conn
|
||||
|
||||
udpSM *udpSessionManager
|
||||
}
|
||||
@@ -74,6 +74,7 @@ func (c *clientImpl) connect() (*HandshakeInfo, error) {
|
||||
InsecureSkipVerify: c.config.TLSConfig.InsecureSkipVerify,
|
||||
VerifyPeerCertificate: c.config.TLSConfig.VerifyPeerCertificate,
|
||||
RootCAs: c.config.TLSConfig.RootCAs,
|
||||
GetClientCertificate: c.config.TLSConfig.GetClientCertificate,
|
||||
}
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: c.config.QUICConfig.InitialStreamReceiveWindow,
|
||||
@@ -84,14 +85,15 @@ func (c *clientImpl) connect() (*HandshakeInfo, error) {
|
||||
KeepAlivePeriod: c.config.QUICConfig.KeepAlivePeriod,
|
||||
DisablePathMTUDiscovery: c.config.QUICConfig.DisablePathMTUDiscovery,
|
||||
EnableDatagrams: true,
|
||||
MaxDatagramFrameSize: protocol.MaxDatagramFrameSize,
|
||||
DisablePathManager: true,
|
||||
}
|
||||
// Prepare RoundTripper
|
||||
var conn quic.EarlyConnection
|
||||
rt := &http3.RoundTripper{
|
||||
var conn *quic.Conn
|
||||
rt := &http3.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
QUICConfig: quicConfig,
|
||||
Dial: func(ctx context.Context, _ string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||
Dial: func(ctx context.Context, _ string, tlsCfg *tls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||
qc, err := quic.DialEarly(ctx, pktConn, c.config.ServerAddr, tlsCfg, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -162,7 +164,7 @@ func (c *clientImpl) connect() (*HandshakeInfo, error) {
|
||||
}
|
||||
|
||||
// openStream wraps the stream with QStream, which handles Close() properly
|
||||
func (c *clientImpl) openStream() (quic.Stream, error) {
|
||||
func (c *clientImpl) openStream() (*utils.QStream, error) {
|
||||
stream, err := c.conn.OpenStream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -241,7 +243,7 @@ func wrapIfConnectionClosed(err error) error {
|
||||
}
|
||||
|
||||
type tcpConn struct {
|
||||
Orig quic.Stream
|
||||
Orig *utils.QStream
|
||||
PseudoLocalAddr net.Addr
|
||||
PseudoRemoteAddr net.Addr
|
||||
Established bool
|
||||
@@ -291,7 +293,7 @@ func (c *tcpConn) SetWriteDeadline(t time.Time) error {
|
||||
}
|
||||
|
||||
type udpIOImpl struct {
|
||||
Conn quic.Connection
|
||||
Conn *quic.Conn
|
||||
}
|
||||
|
||||
func (io *udpIOImpl) ReceiveMessage() (*protocol.UDPMessage, error) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"time"
|
||||
@@ -92,6 +93,7 @@ type TLSConfig struct {
|
||||
InsecureSkipVerify bool
|
||||
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
||||
RootCAs *x509.CertPool
|
||||
GetClientCertificate func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
|
||||
}
|
||||
|
||||
// QUICConfig contains the QUIC configuration fields that we want to expose to the user.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.43.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.5. DO NOT EDIT.
|
||||
|
||||
package client
|
||||
|
||||
@@ -20,7 +20,7 @@ func (_m *mockUDPIO) EXPECT() *mockUDPIO_Expecter {
|
||||
return &mockUDPIO_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// ReceiveMessage provides a mock function with given fields:
|
||||
// ReceiveMessage provides a mock function with no fields
|
||||
func (_m *mockUDPIO) ReceiveMessage() (*protocol.UDPMessage, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ func (u *udpConn) Send(data []byte, addr string) error {
|
||||
if errors.As(err, &errTooLarge) {
|
||||
// Message too large, try fragmentation
|
||||
msg.PacketID = uint16(rand.Intn(0xFFFF)) + 1
|
||||
fMsgs := frag.FragUDPMessage(msg, int(errTooLarge.MaxDataLen))
|
||||
fMsgs := frag.FragUDPMessage(msg, int(errTooLarge.MaxDatagramPayloadSize))
|
||||
for _, fMsg := range fMsgs {
|
||||
err := u.SendFunc(u.SendBuf, &fMsg)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,10 +2,10 @@ module github.com/apernet/hysteria/core/v2
|
||||
|
||||
go 1.23
|
||||
|
||||
toolchain go1.24.2
|
||||
toolchain go1.25.1
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.uber.org/goleak v1.2.1
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||
@@ -14,11 +14,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
@@ -31,7 +27,6 @@ require (
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431 h1:9/jM7e+kVALd7Jfu1c27dcEpT/Fd/Gzq2OsQjKjakKI=
|
||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431/go.mod h1:I/47OIGG5H/IfAm+nz2c6hm6b/NkEhpvptAoiPcY7jQ=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079 h1:WgFl2esvC7FnVhhBvA+BJUgxyheiTAhJ4CIbRlaK22I=
|
||||
github.com/apernet/quic-go v0.54.1-0.20251024023933-5e0818a71079/go.mod h1:Y4cCWi64O51TRUKDPy0ShA2/pevlWiWJJnlNo2fO2ds=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
@@ -25,10 +10,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -37,10 +18,8 @@ github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
@@ -57,7 +36,6 @@ golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
@@ -66,11 +44,8 @@ golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -31,7 +31,7 @@ const (
|
||||
// Constants based on TCP defaults.
|
||||
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
||||
// Does not inflate the pacing rate.
|
||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSizeIPv4)
|
||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize)
|
||||
|
||||
// The gain used for the STARTUP, equal to 2/ln(2).
|
||||
defaultHighGain = 2.885
|
||||
@@ -961,12 +961,8 @@ func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.B
|
||||
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
|
||||
// If this is not a UDP address, we don't know anything about the MTU.
|
||||
// Use the minimum size of an Initial packet as the max packet size.
|
||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
if udpAddr.IP.To4() != nil {
|
||||
return congestion.InitialPacketSizeIPv4
|
||||
} else {
|
||||
return congestion.InitialPacketSizeIPv6
|
||||
}
|
||||
if _, ok := addr.(*net.UDPAddr); ok {
|
||||
return congestion.InitialPacketSize
|
||||
} else {
|
||||
return congestion.MinInitialPacketSize
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func NewBrutalSender(bps uint64) *BrutalSender {
|
||||
debug, _ := strconv.ParseBool(os.Getenv(debugEnv))
|
||||
bs := &BrutalSender{
|
||||
bps: congestion.ByteCount(bps),
|
||||
maxDatagramSize: congestion.InitialPacketSizeIPv4,
|
||||
maxDatagramSize: congestion.InitialPacketSize,
|
||||
ackRate: 1,
|
||||
debug: debug,
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ type Pacer struct {
|
||||
|
||||
func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
|
||||
p := &Pacer{
|
||||
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSizeIPv4,
|
||||
maxDatagramSize: congestion.InitialPacketSizeIPv4,
|
||||
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSize,
|
||||
maxDatagramSize: congestion.InitialPacketSize,
|
||||
getBandwidth: getBandwidth,
|
||||
}
|
||||
return p
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user