This commit is contained in:
Mateusz Gruszczyński committed 2026-10-20 11:19:55 +02:00
1 parent 8c0de520d7
commit 8f41b39c26
32 files changed
+934 -128

No files matched your search

+21 -5
View File
@@ -1,6 +1,4 @@
"use strict";
// Shared controls for named listeners, HTTP/2/HTTP/3 and the certificate inventory.
// All labels are resolved from discovered language packs.
(() => {
let uploadBusy = false;
const label = (tag, key, cls) => { const node = el(tag, t(key), cls); node.dataset.i18n = key; return node; };
@@ -10,7 +8,7 @@
if (type === "select") for (const [value, key] of options.values || []) { const option = label("option", key); option.value = value; input.append(option); }
else if (type !== "textarea") input.type = type;
if (type === "checkbox") input.checked = !!value; else input.value = value ?? "";
for (const key of ["min", "max", "maxLength", "required", "pattern", "rows"]) if (Object.hasOwn(options, key)) input[key] = options[key];
for (const key of ["min", "max", "maxLength", "required", "pattern", "rows", "step"]) if (Object.hasOwn(options, key)) input[key] = options[key];
if (type === "checkbox") wrapper.append(input, label("span", key)); else wrapper.append(label("span", key), input);
parent.append(wrapper); return input;
}
@@ -87,15 +85,33 @@
};
return { read, sync };
}
const h3Defaults = { alt_svc_max_age: 3600, max_concurrent_connections: 512, max_concurrent_bidistream: 100, max_concurrent_unistream: 100, max_idle_timeout: 10 };
const h3Defaults = { alt_svc_max_age: 3600, max_concurrent_connections: 512, max_concurrent_bidistream: 100, max_concurrent_unistream: 100, max_idle_timeout: 10, udp_receive_buffer_bytes: 4194304, udp_send_buffer_bytes: 4194304 };
function http3SettingsControls(parent, binding) {
const box = el("div", undefined, "h3-editor vh-wide"); parent.append(box);
const grid = el("div", undefined, "vh-grid"); box.append(grid); const inputs = {};
for (const [name, min, max] of [["alt_svc_max_age", 0, 604800], ["max_concurrent_connections", 1, 4096], ["max_concurrent_bidistream", 1, 1024], ["max_concurrent_unistream", 3, 1024], ["max_idle_timeout", 0, 86400]]) inputs[name] = field(grid, name, `h3_${name}`, binding.http3?.[name] ?? h3Defaults[name], "number", { min, max, required: true });
for (const direction of ["receive", "send"]) {
const name = `udp_${direction}_buffer_bytes`;
const mib = (binding.http3?.[name] ?? h3Defaults[name]) / 1048576;
inputs[name] = field(grid, name, `h3_udp_${direction}_buffer_mib`, mib, "number", { min: 0, max: 16, step: "any", required: true });
}
box.append(label("p", "h3TuningHelp", "fine"));
const sync = (blocked = false) => { for (const input of Object.values(inputs)) input.disabled = blocked; };
sync(false);
const read = () => { const value = {}; for (const [name, input] of Object.entries(inputs)) { value[name] = Number(input.value); if (!Number.isSafeInteger(value[name])) throw fieldError(input, t("vhJsonInvalid")); } return value; };
const read = () => {
const value = {};
for (const [name, input] of Object.entries(inputs)) {
let number = Number(input.value);
if (!input.value.trim() || !Number.isFinite(number)) throw fieldError(input, t("vhJsonInvalid"));
if (name.startsWith("udp_") && name.endsWith("_buffer_bytes")) {
number = Math.round(number * 1048576);
if (number !== 0 && (number < 65536 || number > 16777216)) throw fieldError(input, t("vhJsonInvalid"));
}
if (!Number.isSafeInteger(number)) throw fieldError(input, t("vhJsonInvalid"));
value[name] = number;
}
return value;
};
return { read, sync };
}
function addRow(item = { id: `listener-${$("named-listener-rows").children.length + 1}`, name: "", scope: "internal", enabled: true, binding: { address: "127.0.0.1:8181", tls: false, http2: false, http2_settings: null, h2c: false, http3: null } }) {