Update On Wed Nov 19 19:40:07 CET 2025

This commit is contained in:
github-action[bot]
2025-11-19 19:40:07 +01:00
parent accb772624
commit 7a658aedda
142 changed files with 2240 additions and 1163 deletions
+1
View File
@@ -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
View File
@@ -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
+6 -6
View File
@@ -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
View File
@@ -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=
+8 -8
View File
@@ -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",
+272
View File
@@ -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": "Единица за време"
}
}
+1
View File
@@ -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."
}
+7 -2
View File
@@ -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";
}
+5 -1
View File
@@ -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
);
}
}
+7
View File
@@ -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
+2 -2
View File
@@ -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 = [];
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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 -1
View File
@@ -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()
});
}
}
-1
View File
@@ -13,4 +13,3 @@
[submodule "hev-socks5-tunnel"]
path = hev-socks5-tunnel
url = https://github.com/heiher/hev-socks5-tunnel
branch = master
+11 -5
View File
@@ -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:
+2 -2
View File
@@ -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
+1
View File
@@ -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='' \
+23 -9
View File
@@ -1,6 +1,6 @@
# HevSocks5Tunnel
[![status](https://github.com/heiher/hev-socks5-tunnel/actions/workflows/build.yaml/badge.svg?branch=master&event=push)](https://github.com/heiher/hev-socks5-tunnel)
[![status](https://github.com/heiher/hev-socks5-tunnel/actions/workflows/build.yaml/badge.svg?branch=main&event=push)](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.
+13 -3
View File
@@ -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:
+5 -5
View File
@@ -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;
+70 -6
View File
@@ -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
+6 -1
View File
@@ -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);
+11
View File
@@ -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);
@@ -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
@@ -3,7 +3,7 @@ name: "Check code formatting"
on:
push:
branches:
- master
- main
pull_request:
jobs:
@@ -1,6 +1,6 @@
# HevTaskSystem
[![status](https://github.com/heiher/hev-task-system/actions/workflows/build.yaml/badge.svg?branch=master&event=push)](https://github.com/heiher/hev-task-system)
[![status](https://github.com/heiher/hev-task-system/actions/workflows/build.yaml/badge.svg?branch=main&event=push)](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
@@ -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
@@ -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!"
@@ -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;
}
@@ -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
View File
@@ -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
View File
@@ -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
+3 -1
View File
@@ -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/
+37 -10
View File
@@ -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
}
+6 -4
View File
@@ -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
+14
View File
@@ -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
+1
View File
@@ -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:
+3 -7
View File
@@ -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
+4 -19
View File
@@ -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)
}
+3 -3
View File
@@ -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) {
+9 -7
View File
@@ -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) {
+2
View File
@@ -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.
+2 -2
View File
@@ -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()
+1 -1
View File
@@ -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 -7
View File
@@ -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
)
+2 -27
View File
@@ -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