mirror of
https://github.com/nestriness/nestri.git
synced 2026-03-17 03:43:07 +02:00
feat: WIP s6-overlay and friends
This commit is contained in:
1
packages/configs/s6-overlay/application/notification-fd
Normal file
1
packages/configs/s6-overlay/application/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
25
packages/configs/s6-overlay/application/run
Normal file
25
packages/configs/s6-overlay/application/run
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check if NESTRI_LAUNCH_CMD is unset or empty
|
||||
if [[ -z "${NESTRI_LAUNCH_CMD:-}" ]]; then
|
||||
# exit with 0 so s6 doesn't think the service failed and try to restart it repeatedly
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export LD_PRELOAD="/usr/lib64/libvimputti_shim.so:/usr/lib32/libvimputti_shim.so"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} ${NESTRI_LAUNCH_CMD} &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/application/type
Normal file
1
packages/configs/s6-overlay/application/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
1
packages/configs/s6-overlay/compositor/notification-fd
Normal file
1
packages/configs/s6-overlay/compositor/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
44
packages/configs/s6-overlay/compositor/run
Normal file
44
packages/configs/s6-overlay/compositor/run
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check if NESTRI_LAUNCH_COMPOSITOR is unset or empty
|
||||
if [[ -z "${NESTRI_LAUNCH_COMPOSITOR:-}" ]]; then
|
||||
# exit with 0 so s6 doesn't think the service failed and try to restart it repeatedly
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export LD_PRELOAD="/usr/lib64/libvimputti_shim.so:/usr/lib32/libvimputti_shim.so"
|
||||
|
||||
# Set socket based on compositor type
|
||||
COMPOSITOR_SOCKET="${NESTRI_XDG_RUNTIME_DIR}/wayland-0"
|
||||
|
||||
# Check if this is gamescope
|
||||
if [[ "${NESTRI_LAUNCH_COMPOSITOR}" == *"gamescope"* ]]; then
|
||||
COMPOSITOR_SOCKET="${NESTRI_XDG_RUNTIME_DIR}/gamescope-0"
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "${COMPOSITOR_SOCKET}"
|
||||
|
||||
# expand internal variables
|
||||
FINAL_LAUNCH_COMPOSITOR=$(echo "${NESTRI_LAUNCH_COMPOSITOR}" | envsubst)
|
||||
|
||||
WAYLAND_DISPLAY=wayland-1 s6-setuidgid ${NESTRI_USER} $FINAL_LAUNCH_COMPOSITOR &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "${COMPOSITOR_SOCKET}"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/compositor/type
Normal file
1
packages/configs/s6-overlay/compositor/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
1
packages/configs/s6-overlay/dbus-session/notification-fd
Normal file
1
packages/configs/s6-overlay/dbus-session/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
25
packages/configs/s6-overlay/dbus-session/run
Normal file
25
packages/configs/s6-overlay/dbus-session/run
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "${NESTRI_XDG_RUNTIME_DIR}/bus"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} dbus-daemon --session --address=unix:path="${NESTRI_XDG_RUNTIME_DIR}/bus" --nofork --nopidfile &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "${NESTRI_XDG_RUNTIME_DIR}/bus"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/dbus-session/type
Normal file
1
packages/configs/s6-overlay/dbus-session/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
1
packages/configs/s6-overlay/dbus-system/notification-fd
Normal file
1
packages/configs/s6-overlay/dbus-system/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
25
packages/configs/s6-overlay/dbus-system/run
Normal file
25
packages/configs/s6-overlay/dbus-system/run
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "/run/dbus/system_bus_socket"
|
||||
|
||||
dbus-daemon --system --address=unix:path="/run/dbus/system_bus_socket" --nofork --nopidfile &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "/run/dbus/system_bus_socket"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/dbus-system/type
Normal file
1
packages/configs/s6-overlay/dbus-system/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
238
packages/configs/s6-overlay/init/run
Normal file
238
packages/configs/s6-overlay/init/run
Normal file
@@ -0,0 +1,238 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
# Common helpers as requirement
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
echo "Error: Common script not found at /etc/nestri/common.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configuration
|
||||
CACHE_DIR="${NESTRI_HOME}/.cache/nestri"
|
||||
NVIDIA_INSTALLER_DIR="/tmp"
|
||||
|
||||
|
||||
# Methods #
|
||||
|
||||
# Ensures user ownership across directories
|
||||
handle_user_permissions() {
|
||||
if ! chown "${NESTRI_USER}:${NESTRI_USER}" "${NESTRI_HOME}" 2>/dev/null; then
|
||||
echo "Error: Failed to change ownership of ${NESTRI_HOME} to ${NESTRI_USER}:${NESTRI_USER}" >&2
|
||||
return 1
|
||||
fi
|
||||
# Also apply to .cache
|
||||
if [[ -d "${NESTRI_HOME}/.cache" ]]; then
|
||||
if ! chown "${NESTRI_USER}:${NESTRI_USER}" "${NESTRI_HOME}/.cache" 2>/dev/null; then
|
||||
echo "Error: Failed to change ownership of ${NESTRI_HOME}/.cache to ${NESTRI_USER}:${NESTRI_USER}" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Prepares environment for namespace-less applications (like Steam)
|
||||
setup_namespaceless() {
|
||||
rm -f /run/systemd/container || true
|
||||
mkdir -p /run/pressure-vessel || true
|
||||
}
|
||||
|
||||
# Ensures cache directory exists
|
||||
setup_cache() {
|
||||
log "Setting up cache directory at $CACHE_DIR..."
|
||||
mkdir -p "$CACHE_DIR" || {
|
||||
log "Warning: Failed to create cache directory, continuing.."
|
||||
return 1
|
||||
}
|
||||
chown "${NESTRI_USER}:${NESTRI_USER}" "$CACHE_DIR" 2>/dev/null || {
|
||||
log "Warning: Failed to set cache directory ownership, continuing.."
|
||||
}
|
||||
}
|
||||
|
||||
# Grabs NVIDIA driver installer
|
||||
get_nvidia_installer() {
|
||||
local driver_version="$1"
|
||||
local arch="$2"
|
||||
local filename="NVIDIA-Linux-${arch}-${driver_version}.run"
|
||||
local cached_file="${CACHE_DIR}/${filename}"
|
||||
local tmp_file="${NVIDIA_INSTALLER_DIR}/${filename}"
|
||||
|
||||
# Check cache
|
||||
if [[ -f "$cached_file" ]]; then
|
||||
log "Found cached NVIDIA installer at $cached_file."
|
||||
cp "$cached_file" "$tmp_file" || {
|
||||
log "Warning: Failed to copy cached installer, proceeding with download."
|
||||
rm -f "$cached_file" 2>/dev/null
|
||||
}
|
||||
fi
|
||||
|
||||
# Download if not in tmp
|
||||
if [[ ! -f "$tmp_file" ]]; then
|
||||
log "Downloading NVIDIA driver installer ($filename)..."
|
||||
local urls=(
|
||||
"https://international.download.nvidia.com/XFree86/Linux-${arch}/${driver_version}/${filename}"
|
||||
"https://international.download.nvidia.com/tesla/${driver_version}/${filename}"
|
||||
)
|
||||
local success=0
|
||||
for url in "${urls[@]}"; do
|
||||
if wget -q --show-progress "$url" -O "$tmp_file"; then
|
||||
success=1
|
||||
break
|
||||
fi
|
||||
log "Failed to download from $url, trying next source..."
|
||||
done
|
||||
|
||||
if [[ "$success" -eq 0 ]]; then
|
||||
log "Error: Failed to download NVIDIA driver from all sources."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Cache the downloaded file
|
||||
cp "$tmp_file" "$cached_file" 2>/dev/null && \
|
||||
chown "${NESTRI_USER}:${NESTRI_USER}" "$cached_file" 2>/dev/null || \
|
||||
log "Warning: Failed to cache NVIDIA driver, continuing..."
|
||||
fi
|
||||
|
||||
chmod +x "$tmp_file" || {
|
||||
log "Error: Failed to make NVIDIA installer executable."
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
# Installs the NVIDIA driver
|
||||
install_nvidia_driver() {
|
||||
local filename="$1"
|
||||
log "Installing NVIDIA driver components from $filename..."
|
||||
bash ./"$filename" \
|
||||
--silent \
|
||||
--skip-depmod \
|
||||
--skip-module-unload \
|
||||
--no-kernel-module \
|
||||
--install-compat32-libs \
|
||||
--no-nouveau-check \
|
||||
--no-nvidia-modprobe \
|
||||
--no-systemd \
|
||||
--no-rpms \
|
||||
--no-backup \
|
||||
--no-distro-scripts \
|
||||
--no-libglx-indirect \
|
||||
--no-install-libglvnd \
|
||||
--no-check-for-alternate-installs || {
|
||||
log "Error: NVIDIA driver installation failed."
|
||||
return 1
|
||||
}
|
||||
|
||||
log "NVIDIA driver installation completed."
|
||||
return 0
|
||||
}
|
||||
|
||||
log_container_info() {
|
||||
if ! declare -p container_runtime &>/dev/null; then
|
||||
log "Warning: container_runtime is not defined"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "${container_runtime:-none}" != "none" ]]; then
|
||||
log "Detected container:"
|
||||
log "> ${container_runtime}"
|
||||
else
|
||||
log "No container runtime detected"
|
||||
fi
|
||||
}
|
||||
|
||||
log_gpu_info() {
|
||||
if ! declare -p vendor_devices &>/dev/null; then
|
||||
log "Warning: vendor_devices array is not defined"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Detected GPUs:"
|
||||
for vendor in "${!vendor_devices[@]}"; do
|
||||
log "> $vendor: ${vendor_devices[$vendor]}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Main #
|
||||
|
||||
# Start by getting the container we are running under
|
||||
get_container_info || {
|
||||
log "Warning: Failed to detect container information"
|
||||
}
|
||||
log_container_info
|
||||
|
||||
# Setup cache now
|
||||
setup_cache
|
||||
|
||||
# Get and detect GPU(s)
|
||||
get_gpu_info || {
|
||||
log "Error: Failed to detect GPU information"
|
||||
exit 1
|
||||
}
|
||||
log_gpu_info
|
||||
|
||||
# Handle NVIDIA GPU
|
||||
if [[ -n "${vendor_devices[nvidia]:-}" ]]; then
|
||||
log "NVIDIA GPU(s) detected, applying driver fix.."
|
||||
|
||||
# Determine NVIDIA driver version
|
||||
nvidia_driver_version=""
|
||||
if [[ -f "/proc/driver/nvidia/version" ]]; then
|
||||
nvidia_driver_version=$(awk '/NVIDIA/ {for(i=1;i<=NF;i++) if ($i ~ /^[0-9]+\.[0-9\.]+/) {print $i; exit}}' /proc/driver/nvidia/version | head -n1)
|
||||
elif command -v nvidia-smi >/dev/null 2>&1; then
|
||||
nvidia_driver_version=$(nvidia-smi --version | grep -i 'driver version' | cut -d: -f2 | tr -d ' ')
|
||||
fi
|
||||
|
||||
if [[ -z "$nvidia_driver_version" ]]; then
|
||||
log "Error: Failed to determine NVIDIA driver version."
|
||||
# Check for other GPU vendors before exiting
|
||||
if [[ -n "${vendor_devices[amd]:-}" || -n "${vendor_devices[intel]:-}" ]]; then
|
||||
log "Other GPUs (AMD or Intel) detected, continuing without NVIDIA driver"
|
||||
else
|
||||
log "No other GPUs detected, exiting due to NVIDIA driver version failure"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "Detected NVIDIA driver version: $nvidia_driver_version"
|
||||
|
||||
# Get installer
|
||||
arch=$(uname -m)
|
||||
filename="NVIDIA-Linux-${arch}-${nvidia_driver_version}.run"
|
||||
cd "$NVIDIA_INSTALLER_DIR" || {
|
||||
log "Error: Failed to change to $NVIDIA_INSTALLER_DIR."
|
||||
exit 1
|
||||
}
|
||||
get_nvidia_installer "$nvidia_driver_version" "$arch" || {
|
||||
# Check for other GPU vendors before exiting
|
||||
if [[ -n "${vendor_devices[amd]:-}" || -n "${vendor_devices[intel]:-}" ]]; then
|
||||
log "Other GPUs (AMD or Intel) detected, continuing without NVIDIA driver"
|
||||
else
|
||||
log "No other GPUs detected, exiting due to NVIDIA installer failure"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Install driver
|
||||
install_nvidia_driver "$filename" || {
|
||||
# Check for other GPU vendors before exiting
|
||||
if [[ -n "${vendor_devices[amd]:-}" || -n "${vendor_devices[intel]:-}" ]]; then
|
||||
log "Other GPUs (AMD or Intel) detected, continuing without NVIDIA driver"
|
||||
else
|
||||
log "No other GPUs detected, exiting due to NVIDIA driver installation failure"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle user permissions
|
||||
log "Ensuring user permissions..."
|
||||
handle_user_permissions || exit 1
|
||||
|
||||
# Setup namespaceless env if needed for container runtime
|
||||
if [[ "$container_runtime" != "podman" ]]; then
|
||||
log "Applying namespace-less configuration"
|
||||
setup_namespaceless
|
||||
fi
|
||||
1
packages/configs/s6-overlay/init/type
Normal file
1
packages/configs/s6-overlay/init/type
Normal file
@@ -0,0 +1 @@
|
||||
oneshot
|
||||
1
packages/configs/s6-overlay/init/up
Normal file
1
packages/configs/s6-overlay/init/up
Normal file
@@ -0,0 +1 @@
|
||||
/etc/s6-overlay/s6-rc.d/init/run
|
||||
@@ -0,0 +1 @@
|
||||
3
|
||||
25
packages/configs/s6-overlay/nestri-server/run
Normal file
25
packages/configs/s6-overlay/nestri-server/run
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "${NESTRI_XDG_RUNTIME_DIR}/wayland-1"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} nestri-server $NESTRI_PARAMS &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "${NESTRI_XDG_RUNTIME_DIR}/wayland-1"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exists
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/nestri-server/type
Normal file
1
packages/configs/s6-overlay/nestri-server/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
@@ -0,0 +1 @@
|
||||
3
|
||||
26
packages/configs/s6-overlay/pipewire-pulse/run
Normal file
26
packages/configs/s6-overlay/pipewire-pulse/run
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -rf "${NESTRI_XDG_RUNTIME_DIR}/pulse"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} pipewire-pulse &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "${NESTRI_XDG_RUNTIME_DIR}/pulse/native"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
|
||||
1
packages/configs/s6-overlay/pipewire-pulse/type
Normal file
1
packages/configs/s6-overlay/pipewire-pulse/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
1
packages/configs/s6-overlay/pipewire/notification-fd
Normal file
1
packages/configs/s6-overlay/pipewire/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
26
packages/configs/s6-overlay/pipewire/run
Normal file
26
packages/configs/s6-overlay/pipewire/run
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "${NESTRI_XDG_RUNTIME_DIR}/pipewire-0"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} pipewire &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "${NESTRI_XDG_RUNTIME_DIR}/pipewire-0"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
|
||||
1
packages/configs/s6-overlay/pipewire/type
Normal file
1
packages/configs/s6-overlay/pipewire/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
@@ -0,0 +1 @@
|
||||
3
|
||||
27
packages/configs/s6-overlay/vimputti-manager/run
Normal file
27
packages/configs/s6-overlay/vimputti-manager/run
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export VIMPUTTI_PATH="${NESTRI_VIMPUTTI_PATH}"
|
||||
|
||||
# remove possibly stale socket
|
||||
rm -f "/tmp/vimputti-0"
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} vimputti-manager &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# wait for socket
|
||||
while ! test -S "/tmp/vimputti-0"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exists
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/vimputti-manager/type
Normal file
1
packages/configs/s6-overlay/vimputti-manager/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
1
packages/configs/s6-overlay/wireplumber/notification-fd
Normal file
1
packages/configs/s6-overlay/wireplumber/notification-fd
Normal file
@@ -0,0 +1 @@
|
||||
3
|
||||
20
packages/configs/s6-overlay/wireplumber/run
Normal file
20
packages/configs/s6-overlay/wireplumber/run
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/command/with-contenv bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -f /etc/nestri/common.sh ]]; then
|
||||
source /etc/nestri/common.sh
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
s6-setuidgid ${NESTRI_USER} wireplumber &
|
||||
PROCESS_PID=$!
|
||||
|
||||
# safety sleep for wireplumber
|
||||
sleep 0.5
|
||||
|
||||
# notify
|
||||
printf 'ready\n' >&3
|
||||
|
||||
# wait till process exits
|
||||
wait "${PROCESS_PID}"
|
||||
1
packages/configs/s6-overlay/wireplumber/type
Normal file
1
packages/configs/s6-overlay/wireplumber/type
Normal file
@@ -0,0 +1 @@
|
||||
longrun
|
||||
@@ -7,22 +7,22 @@
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bufbuild/buf": "^1.59.0",
|
||||
"@bufbuild/protoc-gen-es": "^2.10.0"
|
||||
"@bufbuild/buf": "^1.61.0",
|
||||
"@bufbuild/protoc-gen-es": "^2.10.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.10.0",
|
||||
"@bufbuild/protobuf": "^2.10.2",
|
||||
"@chainsafe/libp2p-noise": "^17.0.0",
|
||||
"@chainsafe/libp2p-quic": "^1.1.3",
|
||||
"@chainsafe/libp2p-quic": "^1.1.8",
|
||||
"@chainsafe/libp2p-yamux": "^8.0.1",
|
||||
"@libp2p/identify": "^4.0.5",
|
||||
"@libp2p/interface": "^3.0.2",
|
||||
"@libp2p/ping": "^3.0.5",
|
||||
"@libp2p/websockets": "^10.0.6",
|
||||
"@libp2p/webtransport": "^6.0.7",
|
||||
"@libp2p/utils": "^7.0.5",
|
||||
"@libp2p/identify": "^4.0.9",
|
||||
"@libp2p/interface": "^3.1.0",
|
||||
"@libp2p/ping": "^3.0.9",
|
||||
"@libp2p/websockets": "^10.1.2",
|
||||
"@libp2p/webtransport": "^6.0.11",
|
||||
"@libp2p/utils": "^7.0.9",
|
||||
"@multiformats/multiaddr": "^13.0.1",
|
||||
"libp2p": "^3.0.6",
|
||||
"libp2p": "^3.1.2",
|
||||
"uint8arraylist": "^2.4.8"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
import { keyCodeToLinuxEventCode } from "./codes";
|
||||
import { WebRTCStream } from "./webrtc-stream";
|
||||
import { ProtoKeyDownSchema, ProtoKeyUpSchema } from "./proto/types_pb";
|
||||
import { create, toBinary } from "@bufbuild/protobuf";
|
||||
import {
|
||||
ProtoKeyDownSchema,
|
||||
ProtoKeyUpSchema,
|
||||
//ProtoClipboardSchema,
|
||||
} from "./proto/types_pb";
|
||||
import { create, Message, toBinary } from "@bufbuild/protobuf";
|
||||
import { createMessage } from "./utils";
|
||||
import { ProtoMessageSchema } from "./proto/messages_pb";
|
||||
|
||||
@@ -13,21 +17,40 @@ export class Keyboard {
|
||||
protected wrtc: WebRTCStream;
|
||||
protected connected!: boolean;
|
||||
|
||||
private onEscapeCallback?: () => void;
|
||||
|
||||
// Store references to event listeners
|
||||
private readonly keydownListener: (e: KeyboardEvent) => void;
|
||||
private readonly keyupListener: (e: KeyboardEvent) => void;
|
||||
|
||||
constructor({ webrtc }: Props) {
|
||||
this.wrtc = webrtc;
|
||||
this.keydownListener = this.createKeyboardListener((e: any) =>
|
||||
create(ProtoKeyDownSchema, {
|
||||
key: this.keyToVirtualKeyCode(e.code),
|
||||
}),
|
||||
this.keydownListener = this.createKeyboardListener(
|
||||
async (e: KeyboardEvent) => {
|
||||
let rets = [];
|
||||
if (e.shiftKey && e.code === "Escape" && this.onEscapeCallback !== undefined) {
|
||||
this.onEscapeCallback();
|
||||
return rets;
|
||||
}
|
||||
/*if (e.ctrlKey && e.key === "v" && navigator.clipboard) {
|
||||
rets.push(create(ProtoClipboardSchema, {
|
||||
content: await navigator.clipboard.readText(),
|
||||
}));
|
||||
}*/
|
||||
rets.push(
|
||||
create(ProtoKeyDownSchema, {
|
||||
key: this.keyToVirtualKeyCode(e.code),
|
||||
}),
|
||||
);
|
||||
return rets;
|
||||
},
|
||||
);
|
||||
this.keyupListener = this.createKeyboardListener((e: any) =>
|
||||
create(ProtoKeyUpSchema, {
|
||||
key: this.keyToVirtualKeyCode(e.code),
|
||||
}),
|
||||
this.keyupListener = this.createKeyboardListener(
|
||||
async (e: KeyboardEvent) => [
|
||||
create(ProtoKeyUpSchema, {
|
||||
key: this.keyToVirtualKeyCode(e.code),
|
||||
}),
|
||||
],
|
||||
);
|
||||
this.run();
|
||||
}
|
||||
@@ -56,10 +79,12 @@ export class Keyboard {
|
||||
// Prevent repeated key events from being sent (important for games)
|
||||
if ((e as any).repeat) return;
|
||||
|
||||
const data = dataCreator(e as any);
|
||||
|
||||
const message = createMessage(data, "input");
|
||||
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, message));
|
||||
dataCreator(e as any).then((datas: Message[]) => {
|
||||
datas.forEach((data) => {
|
||||
const message = createMessage(data, "input");
|
||||
this.wrtc.sendBinary(toBinary(ProtoMessageSchema, message));
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,6 +93,10 @@ export class Keyboard {
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
public setOnEscape(cb: () => void) {
|
||||
this.onEscapeCallback = cb;
|
||||
}
|
||||
|
||||
private keyToVirtualKeyCode(code: string) {
|
||||
// Treat Home key as Escape - TODO: Make user-configurable
|
||||
if (code === "Home") return 1;
|
||||
|
||||
@@ -76,9 +76,15 @@ export class Mouse {
|
||||
if (document.pointerLockElement == this.canvas) {
|
||||
this.connected = true;
|
||||
this.canvas.addEventListener("mousemove", this.mousemoveListener);
|
||||
this.canvas.addEventListener("mousedown", this.mousedownListener);
|
||||
this.canvas.addEventListener("mouseup", this.mouseupListener);
|
||||
this.canvas.addEventListener("wheel", this.mousewheelListener);
|
||||
this.canvas.addEventListener("mousedown", this.mousedownListener, {
|
||||
passive: true,
|
||||
});
|
||||
this.canvas.addEventListener("mouseup", this.mouseupListener, {
|
||||
passive: true,
|
||||
});
|
||||
this.canvas.addEventListener("wheel", this.mousewheelListener, {
|
||||
passive: true,
|
||||
});
|
||||
} else {
|
||||
if (this.connected) {
|
||||
this.stop();
|
||||
@@ -119,7 +125,6 @@ export class Mouse {
|
||||
dataCreator: (e: Event) => any,
|
||||
): (e: Event) => void {
|
||||
return (e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const data = dataCreator(e as any);
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "9.5.0",
|
||||
"@astrojs/node": "9.5.1",
|
||||
"@nestri/input": "*",
|
||||
"astro": "5.15.1"
|
||||
"astro": "5.16.5"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
153
packages/play-standalone/src/components/NerdStats.astro
Normal file
153
packages/play-standalone/src/components/NerdStats.astro
Normal file
@@ -0,0 +1,153 @@
|
||||
---
|
||||
interface Props {
|
||||
audioCodec?: string;
|
||||
audioBitrate?: number;
|
||||
fps?: number;
|
||||
resolution?: { width: number; height: number };
|
||||
videoCodec?: string;
|
||||
videoBitrate?: number;
|
||||
}
|
||||
const {
|
||||
audioCodec,
|
||||
audioBitrate,
|
||||
fps,
|
||||
resolution,
|
||||
videoCodec,
|
||||
videoBitrate
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
|
||||
<button id="nerdStatsBtnOpen">
|
||||
{"|>"}
|
||||
</button>
|
||||
|
||||
<div id="nerdStatsBox" class="statsBox">
|
||||
<button id="nerdStatsBtnClose">
|
||||
{"<|"}
|
||||
</button>
|
||||
<span>Nerd Stats</span>
|
||||
<div class="h-line"></div>
|
||||
<div id="audioStatsList" class="statsList">
|
||||
<span>Audio Stream</span>
|
||||
<div class="h-line"></div>
|
||||
<ul>
|
||||
<li>Codec: {audioCodec}</li>
|
||||
<li>Bitrate: {audioBitrate}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="videoStatsList" class="statsList">
|
||||
<span>Video Stream</span>
|
||||
<div class="h-line"></div>
|
||||
<ul>
|
||||
<li>FPS: {fps}</li>
|
||||
<li>WxH: {resolution ? resolution?.width + "x" + resolution?.height : ""}</li>
|
||||
<li>Codec: {videoCodec}</li>
|
||||
<li>Bitrate: {videoBitrate}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
const openBtn = document.getElementById("nerdStatsBtnOpen")! as HTMLButtonElement;
|
||||
const closeBtn = document.getElementById("nerdStatsBtnClose")! as HTMLButtonElement;
|
||||
const box = document.getElementById("nerdStatsBox")! as HTMLDivElement;
|
||||
|
||||
openBtn.style.display = "flex";
|
||||
box.style.display = "none";
|
||||
|
||||
openBtn.addEventListener("click", () => {
|
||||
openBtn.style.display = "none";
|
||||
box.style.display = "flex";
|
||||
});
|
||||
|
||||
closeBtn.addEventListener("click", () => {
|
||||
openBtn.style.display = "flex";
|
||||
box.style.display = "none";
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
#nerdStatsBtnOpen {
|
||||
font-family: "Geist Mono", sans-serif;
|
||||
font-size: 1em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
display: flex;
|
||||
color: #d1d1d1;
|
||||
background-color: #fe500f;
|
||||
padding: 0.25rem;
|
||||
transform: translateY(-50%);
|
||||
border: #fe500f 2px solid;
|
||||
|
||||
&:hover {
|
||||
background-color: #cc3f0c;
|
||||
}
|
||||
&:active {
|
||||
background-color: #993009;
|
||||
}
|
||||
}
|
||||
|
||||
.statsBox {
|
||||
font-family: "Geist Mono", sans-serif;
|
||||
font-size: 1em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
color: #d1d1d1;
|
||||
background-color: #993009;
|
||||
min-width: 10rem;
|
||||
padding: 0.5rem;
|
||||
text-align: center;
|
||||
transform: translateY(-50%);
|
||||
border: #fe500f 2px solid;
|
||||
|
||||
button {
|
||||
font-family: "Geist Mono", sans-serif;
|
||||
font-size: 1em;
|
||||
position: absolute;
|
||||
color: #d1d1d1;
|
||||
background-color: #fe500f;
|
||||
padding: 0.25rem;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translateY(-50%) translateX(100%);
|
||||
border: #fe500f 2px solid;
|
||||
|
||||
&:hover {
|
||||
background-color: #cc3f0c;
|
||||
}
|
||||
&:active {
|
||||
background-color: #993009;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.h-line {
|
||||
margin: 0.25rem 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: #cc3f0c;
|
||||
}
|
||||
|
||||
.statsList {
|
||||
margin: 0.25rem 0 0 0;
|
||||
padding: 0.5rem;
|
||||
border: #cc3f0c 2px solid;
|
||||
background-color: #802808;
|
||||
text-align: center;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -20,11 +20,25 @@
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Geist Mono";
|
||||
src: url("/fonts/GeistMono-VariableFont_wght.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Basement Grotesque", sans-serif;
|
||||
}
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
import DefaultLayout from "../layouts/DefaultLayout.astro";
|
||||
import NerdStats from "../components/NerdStats.astro";
|
||||
const { room } = Astro.params;
|
||||
|
||||
// Passing of environment variables to the client side
|
||||
@@ -16,13 +17,22 @@ if (envs_map.size > 0) {
|
||||
}
|
||||
---
|
||||
|
||||
|
||||
<DefaultLayout>
|
||||
<h1 id="offlineText" class="offline">Offline</h1>
|
||||
<h1 id="loadingText" class="loading">Warming up the GPU...</h1>
|
||||
<div id="playOverlay">
|
||||
<button id="playBtn">Start</button>
|
||||
<div id="darkener"></div>
|
||||
</div>
|
||||
<h1 id="offlineText" class="statusText">Offline</h1>
|
||||
<h1 id="loadingText" class="statusText">Loading..</h1>
|
||||
<div id="nerdStats">
|
||||
<NerdStats></NerdStats>
|
||||
</div>
|
||||
<canvas id="playCanvas" class="playCanvas" data-room={room}></canvas>
|
||||
<div id="ENVS" data-envs={envs}></div>
|
||||
</DefaultLayout>
|
||||
|
||||
|
||||
<script>
|
||||
import { Mouse, Keyboard, Controller, WebRTCStream } from "@nestri/input";
|
||||
const ENVS = document.getElementById("ENVS")!.dataset.envs as string;
|
||||
@@ -38,18 +48,18 @@ if (envs_map.size > 0) {
|
||||
};
|
||||
|
||||
// Elements
|
||||
const playOverlay = document.getElementById("playOverlay")! as HTMLDivElement;
|
||||
const playBtn = document.getElementById("playBtn")! as HTMLButtonElement;
|
||||
const nerdStats = document.getElementById("nerdStats")! as HTMLDivElement;
|
||||
const canvas = document.getElementById("playCanvas")! as HTMLCanvasElement;
|
||||
const offlineText = document.getElementById("offlineText")! as HTMLHeadingElement;
|
||||
const loadingText = document.getElementById("loadingText")! as HTMLHeadingElement;
|
||||
const loadingText = document.getElementById("loadingText")! as HTMLHeadingElement;
|
||||
|
||||
const room = canvas.dataset.room;
|
||||
if (!room || room.length <= 0) {
|
||||
throw new Error("Room parameter is required");
|
||||
}
|
||||
|
||||
offlineText.style.display = "flex";
|
||||
loadingText.style.display = "none";
|
||||
|
||||
// Get query parameter "peerURL" from the URL
|
||||
let peerURL = new URLSearchParams(window.location.search).get("peerURL");
|
||||
if (!peerURL || peerURL.length <= 0) {
|
||||
@@ -58,32 +68,60 @@ if (envs_map.size > 0) {
|
||||
|
||||
console.debug("Using Peer URL:", peerURL);
|
||||
|
||||
loadingText.style.display = "flex";
|
||||
|
||||
// Stream
|
||||
const stream = new WebRTCStream(peerURL, room, async (mediaStream) => {
|
||||
const stream = new WebRTCStream(peerURL, room, (mediaStream) => {
|
||||
if (mediaStream && video.srcObject === null) {
|
||||
video.srcObject = mediaStream;
|
||||
offlineText.style.display = "none";
|
||||
loadingText.style.display = "flex";
|
||||
|
||||
await video.play().catch((e) => {
|
||||
console.error("Failed to play video:", e);
|
||||
});
|
||||
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
const ctx = canvas.getContext("2d");
|
||||
const renderer = () => {
|
||||
if (ctx && video.srcObject) {
|
||||
ctx.drawImage(video, 0, 0);
|
||||
video.requestVideoFrameCallback(renderer);
|
||||
}
|
||||
};
|
||||
video.requestVideoFrameCallback(renderer);
|
||||
loadingText.style.display = "none";
|
||||
}
|
||||
loadingText.style.display = "none";
|
||||
offlineText.style.display = "none";
|
||||
playOverlay.style.display = "flex";
|
||||
} else if (!mediaStream && video.srcObject === null) {
|
||||
offlineText.style.display = "flex";
|
||||
loadingText.style.display = "none";
|
||||
}
|
||||
});
|
||||
const video = document.createElement("video") as HTMLVideoElement;
|
||||
|
||||
const lockPlay = async function () {
|
||||
if (document.fullscreenElement)
|
||||
return;
|
||||
|
||||
await canvas.requestFullscreen();
|
||||
if (!isMobile())
|
||||
await canvas.requestPointerLock();
|
||||
};
|
||||
|
||||
const streamStart = async function () {
|
||||
playBtn.style.display = "none";
|
||||
loadingText.style.display = "flex";
|
||||
await video.play().catch((e) => {
|
||||
console.error("Failed to play video:", e);
|
||||
});
|
||||
|
||||
canvas.style.display = "flex";
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
const ctx = canvas.getContext("2d");
|
||||
const renderer = () => {
|
||||
if (ctx && video.srcObject) {
|
||||
ctx.drawImage(video, 0, 0);
|
||||
video.requestVideoFrameCallback(renderer);
|
||||
}
|
||||
};
|
||||
video.requestVideoFrameCallback(renderer);
|
||||
|
||||
nerdStats.style.display = "flex";
|
||||
loadingText.style.display = "none";
|
||||
playBtn.style.display = "flex"
|
||||
|
||||
playBtn.innerText = "Play";
|
||||
playBtn.removeEventListener("click", streamStart);
|
||||
playBtn.addEventListener("click", lockPlay);
|
||||
};
|
||||
playBtn.addEventListener("click", streamStart);
|
||||
|
||||
// Input
|
||||
let nestriMouse: Mouse | null = null;
|
||||
let nestriKeyboard: Keyboard | null = null;
|
||||
@@ -132,6 +170,12 @@ if (envs_map.size > 0) {
|
||||
webrtc: stream,
|
||||
});
|
||||
|
||||
nestriKeyboard.setOnEscape(async () => {
|
||||
await document.exitFullscreen();
|
||||
if (!isMobile())
|
||||
await document.exitPointerLock();
|
||||
});
|
||||
|
||||
nestriControllers.forEach((c) => c.run());
|
||||
|
||||
if ("keyboard" in navigator && "lock" in (navigator.keyboard as any)) {
|
||||
@@ -152,38 +196,77 @@ if (envs_map.size > 0) {
|
||||
nestriKeyboard = null;
|
||||
}
|
||||
nestriControllers.forEach((c) => c.stop());
|
||||
|
||||
playOverlay.style.display = "flex";
|
||||
playBtn.style.display = "flex";
|
||||
}
|
||||
})
|
||||
|
||||
const lockPlay = async function () {
|
||||
if (document.fullscreenElement)
|
||||
return;
|
||||
|
||||
await canvas.requestFullscreen();
|
||||
if (!isMobile())
|
||||
await canvas.requestPointerLock();
|
||||
};
|
||||
|
||||
canvas.addEventListener("click", lockPlay);
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
#nerdStats {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#playOverlay {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
button {
|
||||
font-size: 1.5em;
|
||||
line-height: 2rem;
|
||||
font-weight: 600;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
color: lightgray;
|
||||
background-color: #fe500f;
|
||||
padding: 0.5rem 1rem;
|
||||
transform: translateY(-50%) translateX(-50%);
|
||||
border: none;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
&:hover {
|
||||
background-color: #cc3f0c;
|
||||
}
|
||||
&:active {
|
||||
background-color: #993009;
|
||||
}
|
||||
}
|
||||
|
||||
#darkener {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0.5rem;
|
||||
padding: 0;
|
||||
border-radius: 1rem;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.playCanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100vh;
|
||||
display: none;
|
||||
object-fit: contain;
|
||||
aspect-ratio: 16 / 9;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.offline, .loading {
|
||||
.statusText {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
color: lightgray;
|
||||
font-size: 1.5rem;
|
||||
|
||||
@@ -3,17 +3,17 @@ module relay
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/libp2p/go-libp2p v0.44.0
|
||||
github.com/libp2p/go-libp2p v0.46.0
|
||||
github.com/libp2p/go-libp2p-pubsub v0.15.0
|
||||
github.com/libp2p/go-reuseport v0.4.0
|
||||
github.com/multiformats/go-multiaddr v0.16.1
|
||||
github.com/oklog/ulid/v2 v2.1.1
|
||||
github.com/pion/ice/v4 v4.0.10
|
||||
github.com/pion/interceptor v0.1.41
|
||||
github.com/pion/rtp v1.8.25
|
||||
github.com/pion/webrtc/v4 v4.1.6
|
||||
github.com/pion/ice/v4 v4.1.0
|
||||
github.com/pion/interceptor v0.1.42
|
||||
github.com/pion/rtp v1.9.0
|
||||
github.com/pion/webrtc/v4 v4.2.1
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
google.golang.org/protobuf v1.36.10
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -24,7 +24,6 @@ require (
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||
github.com/filecoin-project/go-clock v0.1.0 // indirect
|
||||
github.com/flynn/noise v1.1.0 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
@@ -33,7 +32,7 @@ require (
|
||||
github.com/ipfs/go-cid v0.6.0 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
|
||||
github.com/klauspost/compress v1.18.1 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/koron/go-ssdp v0.1.0 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
@@ -44,7 +43,7 @@ require (
|
||||
github.com/libp2p/go-yamux/v5 v5.1.0 // indirect
|
||||
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
|
||||
github.com/miekg/dns v1.1.68 // indirect
|
||||
github.com/miekg/dns v1.1.69 // indirect
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
|
||||
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
@@ -62,24 +61,24 @@ require (
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pion/datachannel v1.5.10 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.12 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.7 // indirect
|
||||
github.com/pion/dtls/v3 v3.0.9 // indirect
|
||||
github.com/pion/logging v0.2.4 // indirect
|
||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||
github.com/pion/mdns/v2 v2.1.0 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/rtcp v1.2.16 // indirect
|
||||
github.com/pion/sctp v1.8.40 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.16 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.8 // indirect
|
||||
github.com/pion/sctp v1.9.0 // indirect
|
||||
github.com/pion/sdp/v3 v3.0.17 // indirect
|
||||
github.com/pion/srtp/v3 v3.0.9 // indirect
|
||||
github.com/pion/stun v0.6.1 // indirect
|
||||
github.com/pion/stun/v3 v3.0.1 // indirect
|
||||
github.com/pion/stun/v3 v3.0.2 // indirect
|
||||
github.com/pion/transport/v2 v2.2.10 // indirect
|
||||
github.com/pion/transport/v3 v3.0.8 // indirect
|
||||
github.com/pion/turn/v4 v4.1.2 // indirect
|
||||
github.com/pion/transport/v3 v3.1.1 // indirect
|
||||
github.com/pion/turn/v4 v4.1.3 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.2 // indirect
|
||||
github.com/prometheus/common v0.67.4 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.55.0 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.58.0 // indirect
|
||||
github.com/quic-go/webtransport-go v0.9.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
@@ -88,17 +87,17 @@ require (
|
||||
go.uber.org/fx v1.24.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/net v0.46.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/crypto v0.46.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20251222180846-3f2a21fb04ff // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.org/x/tools v0.40.0 // indirect
|
||||
lukechampine.com/blake3 v1.4.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,25 +1,9 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
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=
|
||||
@@ -29,44 +13,18 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U
|
||||
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
|
||||
github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
|
||||
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||
@@ -77,23 +35,18 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/koron/go-ssdp v0.1.0 h1:ckl5x5H6qSNFmi+wCuROvvGUu2FQnMbQrU95IHCcv3Y=
|
||||
github.com/koron/go-ssdp v0.1.0/go.mod h1:GltaDBjtK1kemZOusWYLGotV0kBeEf59Bp0wtSB0uyU=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/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=
|
||||
@@ -103,8 +56,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6
|
||||
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
|
||||
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
|
||||
github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs=
|
||||
github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc=
|
||||
github.com/libp2p/go-libp2p v0.46.0 h1:0T2yvIKpZ3DVYCuPOFxPD1layhRU486pj9rSlGWYnDM=
|
||||
github.com/libp2p/go-libp2p v0.46.0/go.mod h1:TbIDnpDjBLa7isdgYpbxozIVPBTmM/7qKOJP4SFySrQ=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
|
||||
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.15.0 h1:cG7Cng2BT82WttmPFMi50gDNV+58K626m/wR00vGL1o=
|
||||
@@ -121,17 +74,13 @@ github.com/libp2p/go-yamux/v5 v5.1.0 h1:8Qlxj4E9JGJAQVW6+uj2o7mqkqsIVlSUGmTWhlXz
|
||||
github.com/libp2p/go-yamux/v5 v5.1.0/go.mod h1:tgIQ07ObtRR/I0IWsFOyQIL9/dR5UXgc2s8xKmNZv1o=
|
||||
github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q=
|
||||
github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marcopolo/simnet v0.0.1 h1:rSMslhPz6q9IvJeFWDoMGxMIrlsbXau3NkuIXHGJxfg=
|
||||
github.com/marcopolo/simnet v0.0.1/go.mod h1:WDaQkgLAjqDUEBAOXz22+1j6wXKfGlC5sD5XWt3ddOs=
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
|
||||
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/miekg/dns v1.1.69 h1:Kb7Y/1Jo+SG+a2GtfoFUfDkG//csdRPwRLkCsxDG9Sc=
|
||||
github.com/miekg/dns v1.1.69/go.mod h1:7OyjD9nEba5OkqQ/hB4fy3PIoxafSZJtducccIelz3g=
|
||||
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
|
||||
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
|
||||
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
|
||||
@@ -142,8 +91,6 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8Rv
|
||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
@@ -171,11 +118,8 @@ github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOo
|
||||
github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
@@ -184,114 +128,78 @@ github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oL
|
||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
|
||||
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
|
||||
github.com/pion/dtls/v3 v3.0.7 h1:bItXtTYYhZwkPFk4t1n3Kkf5TDrfj6+4wG+CZR8uI9Q=
|
||||
github.com/pion/dtls/v3 v3.0.7/go.mod h1:uDlH5VPrgOQIw59irKYkMudSFprY9IEFCqz/eTz16f8=
|
||||
github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
|
||||
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||
github.com/pion/interceptor v0.1.41 h1:NpvX3HgWIukTf2yTBVjVGFXtpSpWgXjqz7IIpu7NsOw=
|
||||
github.com/pion/interceptor v0.1.41/go.mod h1:nEt4187unvRXJFyjiw00GKo+kIuXMWQI9K89fsosDLY=
|
||||
github.com/pion/dtls/v3 v3.0.9 h1:4AijfFRm8mAjd1gfdlB1wzJF3fjjR/VPIpJgkEtvYmM=
|
||||
github.com/pion/dtls/v3 v3.0.9/go.mod h1:abApPjgadS/ra1wvUzHLc3o2HvoxppAh+NZkyApL4Os=
|
||||
github.com/pion/ice/v4 v4.1.0 h1:YlxIii2bTPWyC08/4hdmtYq4srbrY0T9xcTsTjldGqU=
|
||||
github.com/pion/ice/v4 v4.1.0/go.mod h1:5gPbzYxqenvn05k7zKPIZFuSAufolygiy6P1U9HzvZ4=
|
||||
github.com/pion/interceptor v0.1.42 h1:0/4tvNtruXflBxLfApMVoMubUMik57VZ+94U0J7cmkQ=
|
||||
github.com/pion/interceptor v0.1.42/go.mod h1:g6XYTChs9XyolIQFhRHOOUS+bGVGLRfgTCUzH29EfVU=
|
||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||
github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8=
|
||||
github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so=
|
||||
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||
github.com/pion/mdns/v2 v2.1.0 h1:3IJ9+Xio6tWYjhN6WwuY142P/1jA0D5ERaIqawg/fOY=
|
||||
github.com/pion/mdns/v2 v2.1.0/go.mod h1:pcez23GdynwcfRU1977qKU0mDxSeucttSHbCSfFOd9A=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo=
|
||||
github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo=
|
||||
github.com/pion/rtp v1.8.25 h1:b8+y44GNbwOJTYWuVan7SglX/hMlicVCAtL50ztyZHw=
|
||||
github.com/pion/rtp v1.8.25/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
|
||||
github.com/pion/sctp v1.8.40 h1:bqbgWYOrUhsYItEnRObUYZuzvOMsVplS3oNgzedBlG8=
|
||||
github.com/pion/sctp v1.8.40/go.mod h1:SPBBUENXE6ThkEksN5ZavfAhFYll+h+66ZiG6IZQuzo=
|
||||
github.com/pion/sdp/v3 v3.0.16 h1:0dKzYO6gTAvuLaAKQkC02eCPjMIi4NuAr/ibAwrGDCo=
|
||||
github.com/pion/sdp/v3 v3.0.16/go.mod h1:9tyKzznud3qiweZcD86kS0ff1pGYB3VX+Bcsmkx6IXo=
|
||||
github.com/pion/srtp/v3 v3.0.8 h1:RjRrjcIeQsilPzxvdaElN0CpuQZdMvcl9VZ5UY9suUM=
|
||||
github.com/pion/srtp/v3 v3.0.8/go.mod h1:2Sq6YnDH7/UDCvkSoHSDNDeyBcFgWL0sAVycVbAsXFg=
|
||||
github.com/pion/rtp v1.9.0 h1:NL2nGZPXhjnTQGRgsDZRv0ZTo0Or5fkjCy9o9PtBHBU=
|
||||
github.com/pion/rtp v1.9.0/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
|
||||
github.com/pion/sctp v1.9.0 h1:vajCA6G+1/SEi4vpPmDnpRNXwDNBmAXFBvJx0Le9HrI=
|
||||
github.com/pion/sctp v1.9.0/go.mod h1:2wO6HBycUH7iCssuGyc2e9+0giXVW0pyCv3ZuL8LiyY=
|
||||
github.com/pion/sdp/v3 v3.0.17 h1:9SfLAW/fF1XC8yRqQ3iWGzxkySxup4k4V7yN8Fs8nuo=
|
||||
github.com/pion/sdp/v3 v3.0.17/go.mod h1:9tyKzznud3qiweZcD86kS0ff1pGYB3VX+Bcsmkx6IXo=
|
||||
github.com/pion/srtp/v3 v3.0.9 h1:lRGF4G61xxj+m/YluB3ZnBpiALSri2lTzba0kGZMrQY=
|
||||
github.com/pion/srtp/v3 v3.0.9/go.mod h1:E+AuWd7Ug2Fp5u38MKnhduvpVkveXJX6J4Lq4rxUYt8=
|
||||
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
||||
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
||||
github.com/pion/stun/v3 v3.0.1 h1:jx1uUq6BdPihF0yF33Jj2mh+C9p0atY94IkdnW174kA=
|
||||
github.com/pion/stun/v3 v3.0.1/go.mod h1:RHnvlKFg+qHgoKIqtQWMOJF52wsImCAf/Jh5GjX+4Tw=
|
||||
github.com/pion/stun/v3 v3.0.2 h1:BJuGEN2oLrJisiNEJtUTJC4BGbzbfp37LizfqswblFU=
|
||||
github.com/pion/stun/v3 v3.0.2/go.mod h1:JFJKfIWvt178MCF5H/YIgZ4VX3LYE77vca4b9HP60SA=
|
||||
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
|
||||
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
|
||||
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
|
||||
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
|
||||
github.com/pion/transport/v3 v3.0.8 h1:oI3myyYnTKUSTthu/NZZ8eu2I5sHbxbUNNFW62olaYc=
|
||||
github.com/pion/transport/v3 v3.0.8/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
|
||||
github.com/pion/turn/v4 v4.1.2 h1:Em2svpl6aBFa88dLhxypMUzaLjC79kWZWx8FIov01cc=
|
||||
github.com/pion/turn/v4 v4.1.2/go.mod h1:ISYWfZYy0Z3tXzRpyYZHTL+U23yFQIspfxogdQ8pn9Y=
|
||||
github.com/pion/webrtc/v4 v4.1.6 h1:srHH2HwvCGwPba25EYJgUzgLqCQoXl1VCUnrGQMSzUw=
|
||||
github.com/pion/webrtc/v4 v4.1.6/go.mod h1:wKecGRlkl3ox/As/MYghJL+b/cVXMEhoPMJWPuGQFhU=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pion/transport/v3 v3.1.1 h1:Tr684+fnnKlhPceU+ICdrw6KKkTms+5qHMgw6bIkYOM=
|
||||
github.com/pion/transport/v3 v3.1.1/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
|
||||
github.com/pion/turn/v4 v4.1.3 h1:jVNW0iR05AS94ysEtvzsrk3gKs9Zqxf6HmnsLfRvlzA=
|
||||
github.com/pion/turn/v4 v4.1.3/go.mod h1:TD/eiBUf5f5LwXbCJa35T7dPtTpCHRJ9oJWmyPLVT3A=
|
||||
github.com/pion/webrtc/v4 v4.2.1 h1:QgIfJeXf9dg++35y4z8GK3oXHcxWf0y2tUstCry0/V8=
|
||||
github.com/pion/webrtc/v4 v4.2.1/go.mod h1:YDcAacHK1DZkkn1vwFn3yiXbixCBsEDaCNzg9PPAACk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
|
||||
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc=
|
||||
github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.58.0 h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug=
|
||||
github.com/quic-go/quic-go v0.58.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70=
|
||||
github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
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=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
|
||||
go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
|
||||
go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg=
|
||||
@@ -302,15 +210,11 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@@ -320,28 +224,16 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -355,30 +247,17 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -394,10 +273,10 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8 h1:DwMAzqwLj2rVin75cRFh1kfhwQY3hyHrU1oCEDZXPmQ=
|
||||
golang.org/x/telemetry v0.0.0-20251028164327-d7a2859f34e8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20251222180846-3f2a21fb04ff h1:1QaeZGjxSnF1KOGnUYQmI1YpaBe0FvBE1K2rRDuxawc=
|
||||
golang.org/x/telemetry v0.0.0-20251222180846-3f2a21fb04ff/go.mod h1:ArQvPJS723nJQietgilmZA+shuB3CZxH1n2iXq9VSfs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -406,7 +285,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
@@ -414,60 +292,29 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
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/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
||||
@@ -131,6 +131,13 @@ func InitWebRTCAPI() error {
|
||||
// Interceptor registry
|
||||
interceptorRegistry := &interceptor.Registry{}
|
||||
|
||||
// FlexFEC
|
||||
if flags.FlexFEC {
|
||||
if err = webrtc.ConfigureFlexFEC03(118, mediaEngine, interceptorRegistry); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Register our interceptors..
|
||||
nackGenFactory, err := nack.NewGeneratorInterceptor()
|
||||
if err != nil {
|
||||
@@ -153,11 +160,11 @@ func InitWebRTCAPI() error {
|
||||
// New in v4, reduces CPU usage and latency when enabled
|
||||
settingEngine.EnableSCTPZeroChecksum(true)
|
||||
|
||||
nat11IP := GetFlags().NAT11IP
|
||||
/*nat11IP := GetFlags().NAT11IP
|
||||
if len(nat11IP) > 0 {
|
||||
settingEngine.SetNAT1To1IPs([]string{nat11IP}, webrtc.ICECandidateTypeHost)
|
||||
slog.Info("Using NAT 1:1 IP for WebRTC", "nat11_ip", nat11IP)
|
||||
}
|
||||
}*/
|
||||
|
||||
muxPort := GetFlags().UDPMuxPort
|
||||
if muxPort > 0 {
|
||||
@@ -186,6 +193,11 @@ func InitWebRTCAPI() error {
|
||||
// Improves speed when sending offers to browsers (https://github.com/pion/webrtc/issues/3174)
|
||||
settingEngine.SetIncludeLoopbackCandidate(true)
|
||||
|
||||
// Enable ICE Renomination for network recovery
|
||||
if err = settingEngine.SetICERenomination(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a new API object with our customized settings
|
||||
globalWebRTCAPI = webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine), webrtc.WithSettingEngine(settingEngine), webrtc.WithInterceptorRegistry(interceptorRegistry))
|
||||
|
||||
|
||||
@@ -13,19 +13,22 @@ import (
|
||||
var globalFlags *Flags
|
||||
|
||||
type Flags struct {
|
||||
RegenIdentity bool // Remove old identity on startup and regenerate it
|
||||
Verbose bool // Log everything to console
|
||||
Debug bool // Enable debug mode, implies Verbose
|
||||
EndpointPort int // Port for HTTP/S and WS/S endpoint (TCP)
|
||||
WebRTCUDPStart int // WebRTC UDP port range start - ignored if UDPMuxPort is set
|
||||
WebRTCUDPEnd int // WebRTC UDP port range end - ignored if UDPMuxPort is set
|
||||
STUNServer string // WebRTC STUN server
|
||||
UDPMuxPort int // WebRTC UDP mux port - if set, overrides UDP port range
|
||||
AutoAddLocalIP bool // Automatically add local IP to NAT 1 to 1 IPs
|
||||
NAT11IP string // WebRTC NAT 1 to 1 IP - allows specifying IP of relay if behind NAT
|
||||
PersistDir string // Directory to save persistent data to
|
||||
Metrics bool // Enable metrics endpoint
|
||||
MetricsPort int // Port for metrics endpoint
|
||||
RegenIdentity bool // Remove old identity on startup and regenerate it
|
||||
Verbose bool // Log everything to console
|
||||
Debug bool // Enable debug mode, implies Verbose
|
||||
EndpointPort int // Port for HTTP/S and WS/S endpoint (TCP)
|
||||
WebRTCUDPStart int // WebRTC UDP port range start - ignored if UDPMuxPort is set
|
||||
WebRTCUDPEnd int // WebRTC UDP port range end - ignored if UDPMuxPort is set
|
||||
STUNServer string // WebRTC STUN server
|
||||
UDPMuxPort int // WebRTC UDP mux port - if set, overrides UDP port range
|
||||
AutoAddLocalIP bool // Automatically add local IP to NAT 1 to 1 IPs
|
||||
NAT11IP string // WebRTC NAT 1 to 1 IP - allows specifying IP of relay if behind NAT
|
||||
PersistDir string // Directory to save persistent data to
|
||||
Metrics bool // Enable metrics endpoint
|
||||
MetricsPort int // Port for metrics endpoint
|
||||
PlayoutDelayMin int // UNSTABLE: Minimum playout latency
|
||||
PlayoutDelayMax int // UNSTABLE: Maximum playout latency
|
||||
FlexFEC bool // UNSTABLE: Enable/disable FlexFEC for video streams
|
||||
}
|
||||
|
||||
func (flags *Flags) DebugLog() {
|
||||
@@ -43,6 +46,9 @@ func (flags *Flags) DebugLog() {
|
||||
"persistDir", flags.PersistDir,
|
||||
"metrics", flags.Metrics,
|
||||
"metricsPort", flags.MetricsPort,
|
||||
"playoutDelayMin", flags.PlayoutDelayMin,
|
||||
"playoutDelayMax", flags.PlayoutDelayMax,
|
||||
"flexFEC", flags.FlexFEC,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,6 +97,9 @@ func InitFlags() {
|
||||
flag.StringVar(&globalFlags.PersistDir, "persistDir", getEnvAsString("PERSIST_DIR", "./persist-data"), "Directory to save persistent data to")
|
||||
flag.BoolVar(&globalFlags.Metrics, "metrics", getEnvAsBool("METRICS", false), "Enable metrics endpoint")
|
||||
flag.IntVar(&globalFlags.MetricsPort, "metricsPort", getEnvAsInt("METRICS_PORT", 3030), "Port for metrics endpoint")
|
||||
flag.IntVar(&globalFlags.PlayoutDelayMin, "playoutDelayMin", getEnvAsInt("PLAYOUTDELAY_MIN", 0), "Minimum playout delay")
|
||||
flag.IntVar(&globalFlags.PlayoutDelayMin, "playoutDelayMax", getEnvAsInt("PLAYOUTDELAY_MAX", 0), "Maximum playout delay")
|
||||
flag.BoolVar(&globalFlags.FlexFEC, "flexFEC", getEnvAsBool("FLEXFEC", true), "Enable FlexFEC for video streams")
|
||||
// Parse flags
|
||||
flag.Parse()
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
@@ -181,7 +180,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
|
||||
// Add audio/video tracks
|
||||
{
|
||||
localTrack, err := webrtc.NewTrackLocalStaticRTP(
|
||||
room.AudioCodec,
|
||||
room.GetAudioCodec(),
|
||||
"participant-"+participant.ID.String(),
|
||||
"participant-"+participant.ID.String()+"-audio",
|
||||
)
|
||||
@@ -194,7 +193,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
|
||||
}
|
||||
{
|
||||
localTrack, err := webrtc.NewTrackLocalStaticRTP(
|
||||
room.VideoCodec,
|
||||
room.GetVideoCodec(),
|
||||
"participant-"+participant.ID.String(),
|
||||
"participant-"+participant.ID.String()+"-video",
|
||||
)
|
||||
@@ -296,7 +295,7 @@ func (sp *StreamProtocol) handleStreamRequest(stream network.Stream) {
|
||||
})
|
||||
|
||||
// Create offer
|
||||
offer, err := pc.CreateOffer(nil)
|
||||
offer, err := pc.CreateOffer(&webrtc.OfferOptions{OfferAnswerOptions: webrtc.OfferAnswerOptions{ICETricklingSupported: true}})
|
||||
if err != nil {
|
||||
slog.Error("Failed to create offer for requested stream", "room", reqMsg.RoomName, "err", err)
|
||||
continue
|
||||
@@ -571,21 +570,10 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
|
||||
})
|
||||
|
||||
pc.OnTrack(func(remoteTrack *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||
// Prepare PlayoutDelayExtension so we don't need to recreate it for each packet
|
||||
playoutExt := &rtp.PlayoutDelayExtension{
|
||||
MinDelay: 0,
|
||||
MaxDelay: 0,
|
||||
}
|
||||
playoutPayload, err := playoutExt.Marshal()
|
||||
if err != nil {
|
||||
slog.Error("Failed to marshal PlayoutDelayExtension for room", "room", room.Name, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if remoteTrack.Kind() == webrtc.RTPCodecTypeAudio {
|
||||
room.AudioCodec = remoteTrack.Codec().RTPCodecCapability
|
||||
room.SetAudioCodec(remoteTrack.Codec().RTPCodecCapability)
|
||||
} else if remoteTrack.Kind() == webrtc.RTPCodecTypeVideo {
|
||||
room.VideoCodec = remoteTrack.Codec().RTPCodecCapability
|
||||
room.SetVideoCodec(remoteTrack.Codec().RTPCodecCapability)
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -597,14 +585,6 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
|
||||
break
|
||||
}
|
||||
|
||||
// Use PlayoutDelayExtension for low latency, if set for this track kind
|
||||
if extID, ok := common.GetExtension(remoteTrack.Kind(), common.ExtensionPlayoutDelay); ok {
|
||||
if err = rtpPacket.SetExtension(extID, playoutPayload); err != nil {
|
||||
slog.Error("Failed to set PlayoutDelayExtension for room", "room", room.Name, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast
|
||||
room.BroadcastPacket(remoteTrack.Kind(), rtpPacket)
|
||||
}
|
||||
@@ -622,7 +602,7 @@ func (sp *StreamProtocol) handleStreamPush(stream network.Stream) {
|
||||
iceHelper.FlushHeldCandidates()
|
||||
|
||||
// Create an answer
|
||||
answer, err := pc.CreateAnswer(nil)
|
||||
answer, err := pc.CreateAnswer(&webrtc.AnswerOptions{OfferAnswerOptions: webrtc.OfferAnswerOptions{ICETricklingSupported: true}})
|
||||
if err != nil {
|
||||
slog.Error("Failed to create answer for pushed stream", "room", room.Name, "err", err)
|
||||
continue
|
||||
|
||||
@@ -23,12 +23,15 @@ func (r *Relay) GetRoomByID(id ulid.ULID) *shared.Room {
|
||||
|
||||
// GetRoomByName retrieves a local Room struct by its name
|
||||
func (r *Relay) GetRoomByName(name string) *shared.Room {
|
||||
for _, room := range r.LocalRooms.Copy() {
|
||||
if room.Name == name {
|
||||
return room
|
||||
}
|
||||
}
|
||||
return nil
|
||||
var found *shared.Room
|
||||
r.LocalRooms.Range(func(id ulid.ULID, room *shared.Room) bool {
|
||||
if room.Name == name {
|
||||
found = room
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
// CreateRoom creates a new local Room struct with the given name
|
||||
|
||||
@@ -327,7 +327,7 @@ type ProtoMessage_KeyDown struct {
|
||||
}
|
||||
|
||||
type ProtoMessage_KeyUp struct {
|
||||
KeyUp *ProtoKeyUp `protobuf:"bytes,8,opt,name=key_up,json=keyUp,proto3,oneof"`
|
||||
KeyUp *ProtoKeyUp `protobuf:"bytes,8,opt,name=key_up,json=keyUp,proto3,oneof"` //ProtoClipboard clipboard = 9;
|
||||
}
|
||||
|
||||
type ProtoMessage_ControllerAttach struct {
|
||||
|
||||
@@ -3,6 +3,7 @@ package shared
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/pion/rtp"
|
||||
"io"
|
||||
"log/slog"
|
||||
"relay/internal/common"
|
||||
@@ -104,6 +105,17 @@ func (p *Participant) Close() {
|
||||
}
|
||||
|
||||
func (p *Participant) packetWriter() {
|
||||
flags := common.GetFlags()
|
||||
playoutExt := &rtp.PlayoutDelayExtension{
|
||||
MinDelay: uint16(flags.PlayoutDelayMin),
|
||||
MaxDelay: uint16(flags.PlayoutDelayMax),
|
||||
}
|
||||
playoutPayload, err := playoutExt.Marshal()
|
||||
if err != nil {
|
||||
slog.Error("Failed to marshal PlayoutDelayExtension for participant", "participant", p.ID, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
for pkt := range p.packetQueue {
|
||||
var track *webrtc.TrackLocalStaticRTP
|
||||
|
||||
@@ -114,6 +126,14 @@ func (p *Participant) packetWriter() {
|
||||
track = p.VideoTrack
|
||||
}
|
||||
|
||||
// Use PlayoutDelayExtension for low latency, if set for this track kind
|
||||
if extID, ok := common.GetExtension(track.Kind(), common.ExtensionPlayoutDelay); ok {
|
||||
if err = pkt.packet.SetExtension(extID, playoutPayload); err != nil {
|
||||
slog.Error("Failed to set PlayoutDelayExtension for participant", "participant", p.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if track != nil {
|
||||
if err := track.WriteRTP(pkt.packet); err != nil && !errors.Is(err, io.ErrClosedPipe) {
|
||||
slog.Error("WriteRTP failed", "participant", p.ID, "kind", pkt.kind, "err", err)
|
||||
|
||||
@@ -19,8 +19,8 @@ var participantPacketPool = sync.Pool{
|
||||
}
|
||||
|
||||
type participantPacket struct {
|
||||
kind webrtc.RTPCodecType
|
||||
packet *rtp.Packet
|
||||
kind webrtc.RTPCodecType
|
||||
packet *rtp.Packet
|
||||
}
|
||||
|
||||
type RoomInfo struct {
|
||||
@@ -31,11 +31,13 @@ type RoomInfo struct {
|
||||
|
||||
type Room struct {
|
||||
RoomInfo
|
||||
AudioCodec webrtc.RTPCodecCapability
|
||||
VideoCodec webrtc.RTPCodecCapability
|
||||
PeerConnection *webrtc.PeerConnection
|
||||
DataChannel *connections.NestriDataChannel
|
||||
|
||||
codecMu sync.RWMutex
|
||||
audioCodec webrtc.RTPCodecCapability
|
||||
videoCodec webrtc.RTPCodecCapability
|
||||
|
||||
// Atomic pointer to slice of participant channels
|
||||
participantChannels atomic.Pointer[[]chan<- *participantPacket]
|
||||
participantsMtx sync.Mutex // Use only for add/remove
|
||||
@@ -90,7 +92,6 @@ func (r *Room) Close() {
|
||||
}
|
||||
}
|
||||
|
||||
// AddParticipant adds a Participant to a Room
|
||||
func (r *Room) AddParticipant(participant *Participant) {
|
||||
r.participantsMtx.Lock()
|
||||
defer r.participantsMtx.Unlock()
|
||||
@@ -108,7 +109,6 @@ func (r *Room) AddParticipant(participant *Participant) {
|
||||
slog.Debug("Added participant", "participant", participant.ID, "room", r.Name)
|
||||
}
|
||||
|
||||
// RemoveParticipantByID removes a Participant from a Room by participant's ID
|
||||
func (r *Room) RemoveParticipantByID(pID ulid.ULID) {
|
||||
r.participantsMtx.Lock()
|
||||
defer r.participantsMtx.Unlock()
|
||||
@@ -134,7 +134,6 @@ func (r *Room) RemoveParticipantByID(pID ulid.ULID) {
|
||||
slog.Debug("Removed participant", "participant", pID, "room", r.Name)
|
||||
}
|
||||
|
||||
// IsOnline checks if the room is online
|
||||
func (r *Room) IsOnline() bool {
|
||||
return r.PeerConnection != nil
|
||||
}
|
||||
@@ -153,7 +152,7 @@ func (r *Room) BroadcastPacket(kind webrtc.RTPCodecType, pkt *rtp.Packet) {
|
||||
// Get packet struct from pool
|
||||
pp := participantPacketPool.Get().(*participantPacket)
|
||||
pp.kind = kind
|
||||
pp.packet = pkt
|
||||
pp.packet = pkt.Clone()
|
||||
|
||||
select {
|
||||
case ch <- pp:
|
||||
@@ -165,3 +164,27 @@ func (r *Room) BroadcastPacket(kind webrtc.RTPCodecType, pkt *rtp.Packet) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Room) SetAudioCodec(c webrtc.RTPCodecCapability) {
|
||||
r.codecMu.Lock()
|
||||
defer r.codecMu.Unlock()
|
||||
r.audioCodec = c
|
||||
}
|
||||
|
||||
func (r *Room) GetAudioCodec() webrtc.RTPCodecCapability {
|
||||
r.codecMu.RLock()
|
||||
defer r.codecMu.RUnlock()
|
||||
return r.audioCodec
|
||||
}
|
||||
|
||||
func (r *Room) SetVideoCodec(c webrtc.RTPCodecCapability) {
|
||||
r.codecMu.Lock()
|
||||
defer r.codecMu.Unlock()
|
||||
r.videoCodec = c
|
||||
}
|
||||
|
||||
func (r *Room) GetVideoCodec() webrtc.RTPCodecCapability {
|
||||
r.codecMu.RLock()
|
||||
defer r.codecMu.RUnlock()
|
||||
return r.videoCodec
|
||||
}
|
||||
|
||||
35
packages/scripts/cloud/upcloud-rocky10.sh
Normal file
35
packages/scripts/cloud/upcloud-rocky10.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Setup package repos #
|
||||
dnf install epel-release -y
|
||||
dnf config-manager --enable crb
|
||||
|
||||
# Install dev packages #
|
||||
dnf groupinstall "Development Tools" -y
|
||||
dnf install kernel-devel-matched kernel-headers -y
|
||||
|
||||
# NVIDIA repo and driver install #
|
||||
dnf config-manager --add-repo http://developer.download.nvidia.com/compute/cuda/repos/rhel10/$(uname -m)/cuda-rhel10.repo
|
||||
dnf clean expire-cache
|
||||
dnf install nvidia-open -y
|
||||
|
||||
# Update to be safe #
|
||||
dnf update -y
|
||||
|
||||
# Install NVIDIA container toolkit and podman + SELinux helper #
|
||||
dnf install nvidia-container-toolkit podman container-selinux -y
|
||||
|
||||
# Setup required boot flags #
|
||||
grubby --args="nouveau.modeset=0 rd.driver.blacklist=nouveau nvidia-drm.modeset=1" --update-kernel=ALL
|
||||
|
||||
# ENSURE we have required packages, had a weird case where it didn't have kernel and caused modeset to fail??? #
|
||||
dnf update -y
|
||||
|
||||
# Reboot! #
|
||||
reboot now
|
||||
|
||||
# Make sure modeset is available #
|
||||
nvidia-modprobe -c 0 -u -m
|
||||
|
||||
# And make sure CDI devices are listed #
|
||||
systemctl restart nvidia-cdi-refresh.service
|
||||
@@ -21,3 +21,23 @@ if [[ ! -f /etc/nestri/gpu_helpers.sh ]]; then
|
||||
exit 1
|
||||
fi
|
||||
source /etc/nestri/gpu_helpers.sh || { log "Error: Failed to source /etc/nestri/gpu_helpers.sh"; exit 1; }
|
||||
|
||||
# Parses resolution string
|
||||
parse_resolution() {
|
||||
local resolution="$1"
|
||||
if [[ -z "$resolution" ]]; then
|
||||
log "Error: No resolution provided"
|
||||
return 1
|
||||
fi
|
||||
|
||||
IFS='x' read -r width height <<< "$resolution"
|
||||
if ! [[ "$width" =~ ^[0-9]+$ ]] || ! [[ "$height" =~ ^[0-9]+$ ]]; then
|
||||
log "Error: Invalid resolution format. Expected: WIDTHxHEIGHT (e.g., 1920x1080), got: $resolution"
|
||||
return 1
|
||||
fi
|
||||
|
||||
export WIDTH="$width"
|
||||
export HEIGHT="$height"
|
||||
return 0
|
||||
}
|
||||
parse_resolution "${RESOLUTION:-1280x720}" || exit 1
|
||||
|
||||
@@ -225,7 +225,7 @@ configure_ssh() {
|
||||
|
||||
main() {
|
||||
# Wait for required sockets
|
||||
wait_for_socket "${NESTRI_XDG_RUNTIME_DIR}/dbus-1" "DBus" || exit 1
|
||||
wait_for_socket "${NESTRI_XDG_RUNTIME_DIR}/bus" "DBus" || exit 1
|
||||
wait_for_socket "${NESTRI_XDG_RUNTIME_DIR}/pipewire-0" "PipeWire" || exit 1
|
||||
|
||||
# Start by getting the container we are running under
|
||||
|
||||
@@ -74,16 +74,9 @@ start_nestri_server() {
|
||||
|
||||
# Start nestri-server
|
||||
log "Starting nestri-server.."
|
||||
# Try with realtime scheduling first (chrt -f 80), if fails, launch normally
|
||||
if $ENTCMD_PREFIX chrt -f 80 true 2>/dev/null; then
|
||||
$ENTCMD_PREFIX chrt -f 80 nestri-server $NESTRI_PARAMS &
|
||||
NESTRI_PID=$!
|
||||
log "Started nestri-server with realtime scheduling"
|
||||
else
|
||||
$ENTCMD_PREFIX nestri-server $NESTRI_PARAMS &
|
||||
NESTRI_PID=$!
|
||||
log "Started nestri-server"
|
||||
fi
|
||||
$ENTCMD_PREFIX nestri-server $NESTRI_PARAMS &
|
||||
NESTRI_PID=$!
|
||||
log "Started nestri-server"
|
||||
|
||||
log "Waiting for Wayland display $WAYLAND_SOCKET.."
|
||||
for ((i=1; i<=15; i++)); do
|
||||
@@ -108,7 +101,7 @@ start_compositor() {
|
||||
|
||||
# Set default compositor if unset
|
||||
if [[ -z "${NESTRI_LAUNCH_COMPOSITOR+x}" ]]; then
|
||||
NESTRI_LAUNCH_COMPOSITOR="gamescope --backend wayland -g -f --rt -W ${WIDTH} -H ${HEIGHT} -r ${FRAMERATE:-60}"
|
||||
NESTRI_LAUNCH_COMPOSITOR="gamescope --backend wayland --force-grab-cursor -g -f --rt -W ${WIDTH} -H ${HEIGHT} -r ${FRAMERATE:-60}"
|
||||
fi
|
||||
|
||||
# If PRELOAD_SHIM_arch's are set and exist, set LD_PRELOAD for 32/64-bit apps
|
||||
@@ -118,13 +111,13 @@ start_compositor() {
|
||||
log "Using LD_PRELOAD shim(s)"
|
||||
fi
|
||||
|
||||
# Configure launch cmd with dbus if set
|
||||
# Configure launch cmd if set
|
||||
local launch_cmd=""
|
||||
if [[ -n "${NESTRI_LAUNCH_CMD+x}" ]]; then
|
||||
if $do_ld_preload; then
|
||||
launch_cmd="LD_PRELOAD='/usr/\$LIB/libvimputti_shim.so' dbus-launch $NESTRI_LAUNCH_CMD"
|
||||
launch_cmd="LD_PRELOAD='/usr/\$LIB/libvimputti_shim.so' $NESTRI_LAUNCH_CMD"
|
||||
else
|
||||
launch_cmd="dbus-launch $NESTRI_LAUNCH_CMD"
|
||||
launch_cmd="$NESTRI_LAUNCH_CMD"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ export XDG_RUNTIME_DIR=${NESTRI_XDG_RUNTIME_DIR}
|
||||
# Causes some setups to break
|
||||
export PROTON_NO_FSYNC=1
|
||||
|
||||
# Skip first core automatically, to allow nestri-server to work as best as it can
|
||||
export PROTON_CPU_TOPOLOGY=$(nproc | awk '{print $1-1 ":"}')$({ seq 1 $(($(nproc) - 1)) | paste -sd, -; })
|
||||
export WINE_CPU_TOPOLOGY=$(nproc | awk '{print $1-1 ":"}')$({ seq 1 $(($(nproc) - 1)) | paste -sd, -; })
|
||||
|
||||
# Make gstreamer GL elements work without display output (NVIDIA issue..)
|
||||
export GST_GL_API=gles2
|
||||
export GST_GL_WINDOW=surfaceless
|
||||
|
||||
54
packages/scripts/pressure-vent.sh
Normal file
54
packages/scripts/pressure-vent.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Steam "Pressure Vessel" runtime eliminator.
|
||||
#
|
||||
# Valve ships various pre-packaged runtime environments for games to use.
|
||||
# They are cool, in a way: Most games "just work" with them.
|
||||
# However, such convenience comes at the cost of performance and sometimes reliability.
|
||||
#
|
||||
# Normally, I disable any and all such runtimes and install all the required dependencies myself.
|
||||
# However, running Windows games using Proton enforces use of a runtime.
|
||||
# That runtime is shipped in a "Pressure Vessel" container, which is more isolated.
|
||||
# The worst part is, user-supplied LD_PRELOAD and LD_LIBRARY_PATH are ignored due to that.
|
||||
# That means no primusrun/pvkrun/whatever for Windows games, which sucks.
|
||||
#
|
||||
# This little script's purpose is to cut "Pressure Vessel" out of game's command line.
|
||||
# Be warned that that gives you the ability *and responsibility* to manage the dependencies.
|
||||
# Place pressure-vent.sh after all " -- " in game's launch options, if any.
|
||||
# Placing e.g. "xterm -e" at the start of launch options is an easy way to see logs.
|
||||
# Examples:
|
||||
# primusrun ~/pressure-vent.sh %command%
|
||||
# xterm -e /full/path/to/pressure-vent.sh pvkrun %command%
|
||||
|
||||
|
||||
# Functions
|
||||
cmdprn() {
|
||||
printf '%s:\n%q' "$1" "$2"
|
||||
printf ' %q' "${@:3}"
|
||||
printf '\n\n'
|
||||
}
|
||||
err() {
|
||||
printf '%s\nPress Enter to quit.\n' "$1"
|
||||
read
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Debug
|
||||
cmdprn "Original command line" "$@"
|
||||
printf "LD_PRELOAD:\n%q\n\n" "$LD_PRELOAD"
|
||||
printf "LD_LIBRARY_PATH:\n%q\n\n" "$LD_LIBRARY_PATH"
|
||||
|
||||
# Find Pressure Vessel arguments (between two first "--")
|
||||
((left=1))
|
||||
while [[ left -le $# && "${!left}" != "--" ]]; do
|
||||
((left++))
|
||||
done
|
||||
((right=left+1))
|
||||
while [[ right -le $# && "${!right}" != "--" ]]; do
|
||||
((right++))
|
||||
done
|
||||
[[ right -gt $# ]] && err 'Error processing command line.'
|
||||
# Cut them out
|
||||
set -- "${@:1:left}" "${@:right+1}"
|
||||
cmdprn "Processed command line" "$@" # Debug
|
||||
|
||||
exec "$@" || err "Game terminated with code $?."
|
||||
1131
packages/server/Cargo.lock
generated
1131
packages/server/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -12,17 +12,17 @@ gstreamer = { version = "0.24", features = ["v1_26"] }
|
||||
gstreamer-webrtc = { version = "0.24", features = ["v1_26"] }
|
||||
gst-plugin-webrtc = { version = "0.14" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.48", features = ["full"] }
|
||||
tokio = { version = "1.49", features = ["full"] }
|
||||
tokio-stream = { version = "0.1", features = ["full"] }
|
||||
clap = { version = "4.5", features = ["env", "derive"] }
|
||||
serde_json = "1.0"
|
||||
webrtc = "0.14"
|
||||
regex = "1.11"
|
||||
rand = "0.9"
|
||||
webrtc = "0.17"
|
||||
regex = "1.12"
|
||||
rand = "0.10"
|
||||
rustls = { version = "0.23", features = ["ring"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
vimputti = "0.1.7"
|
||||
vimputti = "0.1"
|
||||
chrono = "0.4"
|
||||
prost = "0.14"
|
||||
prost-types = "0.14"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "1.91"
|
||||
channel = "1.93"
|
||||
@@ -301,7 +301,7 @@ pub fn encoder_low_latency_params(
|
||||
}
|
||||
"svtav1enc" => {
|
||||
encoder_optz.set_parameter("preset", "11");
|
||||
encoder_optz.set_parameter("parameters-string", "lookahead=0");
|
||||
encoder_optz.set_parameter("parameters-string", "lookahead=0:fast-decode=2");
|
||||
}
|
||||
"av1enc" => {
|
||||
encoder_optz.set_parameter("usage-profile", "realtime");
|
||||
@@ -351,7 +351,7 @@ pub fn encoder_high_quality_params(
|
||||
}
|
||||
"svtav1enc" => {
|
||||
encoder_optz.set_parameter("preset", "8");
|
||||
encoder_optz.set_parameter("parameters-string", "lookahead=3");
|
||||
encoder_optz.set_parameter("parameters-string", "lookahead=0:fast-decode=1");
|
||||
}
|
||||
"av1enc" => {
|
||||
encoder_optz.set_parameter("usage-profile", "realtime");
|
||||
|
||||
@@ -209,19 +209,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
gstreamer::init()?;
|
||||
let _ = gstrswebrtc::plugin_register_static(); // Might be already registered, so we'll pass..
|
||||
|
||||
if args.app.zero_copy {
|
||||
if args.encoding.video.encoder_type != EncoderType::HARDWARE {
|
||||
tracing::warn!(
|
||||
"zero-copy is only supported with hardware encoders, disabling zero-copy.."
|
||||
);
|
||||
args.app.zero_copy = false;
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"zero-copy is experimental, it may or may not improve performance, or even work at all."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle GPU selection
|
||||
let gpus = match handle_gpus(&args) {
|
||||
Ok(gpu) => gpu,
|
||||
@@ -243,6 +230,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
// Handle video encoder settings
|
||||
video_encoder_info = handle_encoder_video_settings(&args, &video_encoder_info);
|
||||
|
||||
// Deal with zero-copy mismatches
|
||||
if args.app.zero_copy {
|
||||
if video_encoder_info.encoder_type != EncoderType::HARDWARE {
|
||||
tracing::warn!(
|
||||
"zero-copy is only supported with hardware encoders, disabling zero-copy.."
|
||||
);
|
||||
args.app.zero_copy = false;
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"zero-copy is experimental, it may or may not improve performance, or even work at all."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle audio encoder selection
|
||||
let audio_encoder = handle_encoder_audio(&args);
|
||||
|
||||
@@ -338,6 +339,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
video_source.set_property_from_str("render-node", gpu_info.render_path());
|
||||
}
|
||||
|
||||
// videorate to enforce constant framerate during static scenes
|
||||
let video_rate = gstreamer::ElementFactory::make("videorate")
|
||||
.property("drop-only", false) // ensure it duplicates frames, not just drops
|
||||
.property("skip-to-first", true) // helps startup latency sometimes
|
||||
.build()?;
|
||||
|
||||
// Caps Filter Element (resolution, fps)
|
||||
let caps_filter = gstreamer::ElementFactory::make("capsfilter").build()?;
|
||||
let caps = gstreamer::Caps::from_str(&format!(
|
||||
@@ -417,6 +424,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
.build()?,
|
||||
);
|
||||
}
|
||||
enc_helper::VideoCodec::AV1 if video_encoder_info.encoder_type == EncoderType::SOFTWARE => {
|
||||
video_parser = Some(gstreamer::ElementFactory::make("av1parse").build()?);
|
||||
}
|
||||
_ => {
|
||||
video_parser = None;
|
||||
}
|
||||
@@ -461,8 +471,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
&video_sink_queue,
|
||||
&audio_sink_queue,
|
||||
&video_encoder,
|
||||
&caps_filter,
|
||||
&video_source_queue,
|
||||
&caps_filter,
|
||||
&video_rate,
|
||||
&video_source,
|
||||
&audio_encoder,
|
||||
&audio_capsfilter,
|
||||
@@ -524,6 +535,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
if let (Some(vapostproc), Some(va_caps_filter)) = (&vapostproc, &va_caps_filter) {
|
||||
gstreamer::Element::link_many(&[
|
||||
&video_source,
|
||||
&video_rate,
|
||||
&caps_filter,
|
||||
&video_source_queue,
|
||||
&vapostproc,
|
||||
@@ -532,11 +544,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
])?;
|
||||
} else if video_encoder_info.encoder_api == EncoderAPI::NVENC {
|
||||
// NVENC pipeline
|
||||
gstreamer::Element::link_many(&[&video_source, &caps_filter, &video_encoder])?;
|
||||
gstreamer::Element::link_many(&[
|
||||
&video_source,
|
||||
&video_rate,
|
||||
&caps_filter,
|
||||
&video_source_queue,
|
||||
&video_encoder,
|
||||
])?;
|
||||
}
|
||||
} else {
|
||||
gstreamer::Element::link_many(&[
|
||||
&video_source,
|
||||
&video_rate,
|
||||
&caps_filter,
|
||||
&video_source_queue,
|
||||
&video_converter.unwrap(),
|
||||
@@ -560,9 +579,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
])?;
|
||||
}
|
||||
|
||||
video_source.set_property("do-timestamp", &false);
|
||||
audio_source.set_property("do-timestamp", &false);
|
||||
|
||||
// Optimize latency of pipeline
|
||||
pipeline.set_property("latency", &0u64);
|
||||
pipeline.set_property("async-handling", true);
|
||||
|
||||
@@ -398,9 +398,20 @@ fn setup_data_channel(
|
||||
if let Some(message_base) = msg_wrapper.message_base {
|
||||
if message_base.payload_type == "input" {
|
||||
if let Some(input_data) = msg_wrapper.payload {
|
||||
if let Some(event) = handle_input_message(input_data) {
|
||||
// Send the event to wayland source, result bool is ignored
|
||||
let _ = wayland_src.send_event(event);
|
||||
/*if let Payload::Clipboard(data) = &input_data {
|
||||
tracing::info!("CLIPBOARD: {:?}", data.content);
|
||||
// Make sure Ctrl is unpressed before handling clipboard
|
||||
let structure = gstreamer::Structure::builder("SetClipboard")
|
||||
.field("content", data.content.clone())
|
||||
.build();
|
||||
|
||||
let _ = wayland_src.send_event(gstreamer::event::CustomUpstream::new(structure));
|
||||
} else*/
|
||||
{
|
||||
if let Some(event) = handle_input_message(input_data) {
|
||||
// Send the event to wayland source, result bool is ignored
|
||||
let _ = wayland_src.send_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if message_base.payload_type == "controllerInput" {
|
||||
|
||||
@@ -8,7 +8,8 @@ use std::sync::Arc;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
// Cloneable callback type
|
||||
pub type CallbackInner = dyn Fn(crate::proto::proto::ProtoMessage) -> Result<()> + Send + Sync + 'static;
|
||||
pub type CallbackInner =
|
||||
dyn Fn(crate::proto::proto::ProtoMessage) -> Result<()> + Send + Sync + 'static;
|
||||
pub struct Callback(Arc<CallbackInner>);
|
||||
impl Callback {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
|
||||
@@ -2,68 +2,68 @@
|
||||
// This file is @generated by prost-build.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoTimestampEntry {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub stage: ::prost::alloc::string::String,
|
||||
#[prost(message, optional, tag="2")]
|
||||
#[prost(message, optional, tag = "2")]
|
||||
pub time: ::core::option::Option<::prost_types::Timestamp>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ProtoLatencyTracker {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub sequence_id: ::prost::alloc::string::String,
|
||||
#[prost(message, repeated, tag="2")]
|
||||
#[prost(message, repeated, tag = "2")]
|
||||
pub timestamps: ::prost::alloc::vec::Vec<ProtoTimestampEntry>,
|
||||
}
|
||||
// Mouse messages
|
||||
// Mouse messages
|
||||
|
||||
/// MouseMove message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoMouseMove {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub x: i32,
|
||||
#[prost(int32, tag="2")]
|
||||
#[prost(int32, tag = "2")]
|
||||
pub y: i32,
|
||||
}
|
||||
/// MouseMoveAbs message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoMouseMoveAbs {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub x: i32,
|
||||
#[prost(int32, tag="2")]
|
||||
#[prost(int32, tag = "2")]
|
||||
pub y: i32,
|
||||
}
|
||||
/// MouseWheel message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoMouseWheel {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub x: i32,
|
||||
#[prost(int32, tag="2")]
|
||||
#[prost(int32, tag = "2")]
|
||||
pub y: i32,
|
||||
}
|
||||
/// MouseKeyDown message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoMouseKeyDown {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub key: i32,
|
||||
}
|
||||
/// MouseKeyUp message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoMouseKeyUp {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub key: i32,
|
||||
}
|
||||
// Keyboard messages
|
||||
// Keyboard messages
|
||||
|
||||
/// KeyDown message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoKeyDown {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub key: i32,
|
||||
}
|
||||
/// KeyUp message
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoKeyUp {
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub key: i32,
|
||||
}
|
||||
// Clipboard message
|
||||
@@ -71,96 +71,96 @@ pub struct ProtoKeyUp {
|
||||
// string content = 1; // Clipboard content
|
||||
// }
|
||||
|
||||
// Controller messages
|
||||
// Controller messages
|
||||
|
||||
/// ControllerAttach message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoControllerAttach {
|
||||
/// One of the following enums: "ps", "xbox" or "switch"
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub id: ::prost::alloc::string::String,
|
||||
/// Session specific slot number (0-3)
|
||||
#[prost(int32, tag="2")]
|
||||
#[prost(int32, tag = "2")]
|
||||
pub session_slot: i32,
|
||||
/// Session ID of the client
|
||||
#[prost(string, tag="3")]
|
||||
#[prost(string, tag = "3")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
}
|
||||
/// ControllerDetach message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoControllerDetach {
|
||||
/// Session specific slot number (0-3)
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub session_slot: i32,
|
||||
/// Session ID of the client
|
||||
#[prost(string, tag="2")]
|
||||
#[prost(string, tag = "2")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
}
|
||||
/// ControllerRumble message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoControllerRumble {
|
||||
/// Session specific slot number (0-3)
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub session_slot: i32,
|
||||
/// Session ID of the client
|
||||
#[prost(string, tag="2")]
|
||||
#[prost(string, tag = "2")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
/// Low frequency rumble (0-65535)
|
||||
#[prost(int32, tag="3")]
|
||||
#[prost(int32, tag = "3")]
|
||||
pub low_frequency: i32,
|
||||
/// High frequency rumble (0-65535)
|
||||
#[prost(int32, tag="4")]
|
||||
#[prost(int32, tag = "4")]
|
||||
pub high_frequency: i32,
|
||||
/// Duration in milliseconds
|
||||
#[prost(int32, tag="5")]
|
||||
#[prost(int32, tag = "5")]
|
||||
pub duration: i32,
|
||||
}
|
||||
/// ControllerStateBatch - single message containing full or partial controller state
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ProtoControllerStateBatch {
|
||||
/// Session specific slot number (0-3)
|
||||
#[prost(int32, tag="1")]
|
||||
#[prost(int32, tag = "1")]
|
||||
pub session_slot: i32,
|
||||
/// Session ID of the client
|
||||
#[prost(string, tag="2")]
|
||||
#[prost(string, tag = "2")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
#[prost(enumeration="proto_controller_state_batch::UpdateType", tag="3")]
|
||||
#[prost(enumeration = "proto_controller_state_batch::UpdateType", tag = "3")]
|
||||
pub update_type: i32,
|
||||
/// Sequence number for packet loss detection
|
||||
#[prost(uint32, tag="4")]
|
||||
#[prost(uint32, tag = "4")]
|
||||
pub sequence: u32,
|
||||
/// Button state map (Linux event codes)
|
||||
#[prost(map="int32, bool", tag="5")]
|
||||
#[prost(map = "int32, bool", tag = "5")]
|
||||
pub button_changed_mask: ::std::collections::HashMap<i32, bool>,
|
||||
/// Analog inputs
|
||||
///
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="6")]
|
||||
#[prost(int32, optional, tag = "6")]
|
||||
pub left_stick_x: ::core::option::Option<i32>,
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="7")]
|
||||
#[prost(int32, optional, tag = "7")]
|
||||
pub left_stick_y: ::core::option::Option<i32>,
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="8")]
|
||||
#[prost(int32, optional, tag = "8")]
|
||||
pub right_stick_x: ::core::option::Option<i32>,
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="9")]
|
||||
#[prost(int32, optional, tag = "9")]
|
||||
pub right_stick_y: ::core::option::Option<i32>,
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="10")]
|
||||
#[prost(int32, optional, tag = "10")]
|
||||
pub left_trigger: ::core::option::Option<i32>,
|
||||
/// -32768 to 32767
|
||||
#[prost(int32, optional, tag="11")]
|
||||
#[prost(int32, optional, tag = "11")]
|
||||
pub right_trigger: ::core::option::Option<i32>,
|
||||
/// -1, 0, or 1
|
||||
#[prost(int32, optional, tag="12")]
|
||||
#[prost(int32, optional, tag = "12")]
|
||||
pub dpad_x: ::core::option::Option<i32>,
|
||||
/// -1, 0, or 1
|
||||
#[prost(int32, optional, tag="13")]
|
||||
#[prost(int32, optional, tag = "13")]
|
||||
pub dpad_y: ::core::option::Option<i32>,
|
||||
/// Bitmask indicating which fields have changed
|
||||
/// Bit 0: button_changed_mask, Bit 1: left_stick_x, Bit 2: left_stick_y, etc.
|
||||
#[prost(uint32, optional, tag="14")]
|
||||
#[prost(uint32, optional, tag = "14")]
|
||||
pub changed_fields: ::core::option::Option<u32>,
|
||||
}
|
||||
/// Nested message and enum types in `ProtoControllerStateBatch`.
|
||||
@@ -194,78 +194,81 @@ pub mod proto_controller_state_batch {
|
||||
}
|
||||
}
|
||||
}
|
||||
// WebRTC + signaling
|
||||
// WebRTC + signaling
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct RtcIceCandidateInit {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub candidate: ::prost::alloc::string::String,
|
||||
#[prost(uint32, optional, tag="2")]
|
||||
#[prost(uint32, optional, tag = "2")]
|
||||
pub sdp_m_line_index: ::core::option::Option<u32>,
|
||||
#[prost(string, optional, tag="3")]
|
||||
#[prost(string, optional, tag = "3")]
|
||||
pub sdp_mid: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(string, optional, tag="4")]
|
||||
#[prost(string, optional, tag = "4")]
|
||||
pub username_fragment: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct RtcSessionDescriptionInit {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub sdp: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
#[prost(string, tag = "2")]
|
||||
pub r#type: ::prost::alloc::string::String,
|
||||
}
|
||||
/// ProtoICE message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoIce {
|
||||
#[prost(message, optional, tag="1")]
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub candidate: ::core::option::Option<RtcIceCandidateInit>,
|
||||
}
|
||||
/// ProtoSDP message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoSdp {
|
||||
#[prost(message, optional, tag="1")]
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub sdp: ::core::option::Option<RtcSessionDescriptionInit>,
|
||||
}
|
||||
/// ProtoRaw message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoRaw {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub data: ::prost::alloc::string::String,
|
||||
}
|
||||
/// ProtoClientRequestRoomStream message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoClientRequestRoomStream {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub room_name: ::prost::alloc::string::String,
|
||||
#[prost(string, tag="2")]
|
||||
#[prost(string, tag = "2")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
}
|
||||
/// ProtoClientDisconnected message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoClientDisconnected {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub session_id: ::prost::alloc::string::String,
|
||||
#[prost(int32, repeated, tag="2")]
|
||||
#[prost(int32, repeated, tag = "2")]
|
||||
pub controller_slots: ::prost::alloc::vec::Vec<i32>,
|
||||
}
|
||||
/// ProtoServerPushStream message
|
||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||
pub struct ProtoServerPushStream {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub room_name: ::prost::alloc::string::String,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ProtoMessageBase {
|
||||
#[prost(string, tag="1")]
|
||||
#[prost(string, tag = "1")]
|
||||
pub payload_type: ::prost::alloc::string::String,
|
||||
#[prost(message, optional, tag="2")]
|
||||
#[prost(message, optional, tag = "2")]
|
||||
pub latency: ::core::option::Option<ProtoLatencyTracker>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ProtoMessage {
|
||||
#[prost(message, optional, tag="1")]
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub message_base: ::core::option::Option<ProtoMessageBase>,
|
||||
#[prost(oneof="proto_message::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25")]
|
||||
#[prost(
|
||||
oneof = "proto_message::Payload",
|
||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25"
|
||||
)]
|
||||
pub payload: ::core::option::Option<proto_message::Payload>,
|
||||
}
|
||||
/// Nested message and enum types in `ProtoMessage`.
|
||||
@@ -273,42 +276,42 @@ pub mod proto_message {
|
||||
#[derive(Clone, PartialEq, ::prost::Oneof)]
|
||||
pub enum Payload {
|
||||
/// Input types
|
||||
#[prost(message, tag="2")]
|
||||
#[prost(message, tag = "2")]
|
||||
MouseMove(super::ProtoMouseMove),
|
||||
#[prost(message, tag="3")]
|
||||
#[prost(message, tag = "3")]
|
||||
MouseMoveAbs(super::ProtoMouseMoveAbs),
|
||||
#[prost(message, tag="4")]
|
||||
#[prost(message, tag = "4")]
|
||||
MouseWheel(super::ProtoMouseWheel),
|
||||
#[prost(message, tag="5")]
|
||||
#[prost(message, tag = "5")]
|
||||
MouseKeyDown(super::ProtoMouseKeyDown),
|
||||
#[prost(message, tag="6")]
|
||||
#[prost(message, tag = "6")]
|
||||
MouseKeyUp(super::ProtoMouseKeyUp),
|
||||
#[prost(message, tag="7")]
|
||||
#[prost(message, tag = "7")]
|
||||
KeyDown(super::ProtoKeyDown),
|
||||
/// ProtoClipboard clipboard = 9;
|
||||
#[prost(message, tag="8")]
|
||||
#[prost(message, tag = "8")]
|
||||
KeyUp(super::ProtoKeyUp),
|
||||
/// Controller input types
|
||||
#[prost(message, tag="9")]
|
||||
#[prost(message, tag = "9")]
|
||||
ControllerAttach(super::ProtoControllerAttach),
|
||||
#[prost(message, tag="10")]
|
||||
#[prost(message, tag = "10")]
|
||||
ControllerDetach(super::ProtoControllerDetach),
|
||||
#[prost(message, tag="11")]
|
||||
#[prost(message, tag = "11")]
|
||||
ControllerRumble(super::ProtoControllerRumble),
|
||||
#[prost(message, tag="12")]
|
||||
#[prost(message, tag = "12")]
|
||||
ControllerStateBatch(super::ProtoControllerStateBatch),
|
||||
/// Signaling types
|
||||
#[prost(message, tag="20")]
|
||||
#[prost(message, tag = "20")]
|
||||
Ice(super::ProtoIce),
|
||||
#[prost(message, tag="21")]
|
||||
#[prost(message, tag = "21")]
|
||||
Sdp(super::ProtoSdp),
|
||||
#[prost(message, tag="22")]
|
||||
#[prost(message, tag = "22")]
|
||||
Raw(super::ProtoRaw),
|
||||
#[prost(message, tag="23")]
|
||||
#[prost(message, tag = "23")]
|
||||
ClientRequestRoomStream(super::ProtoClientRequestRoomStream),
|
||||
#[prost(message, tag="24")]
|
||||
#[prost(message, tag = "24")]
|
||||
ClientDisconnected(super::ProtoClientDisconnected),
|
||||
#[prost(message, tag="25")]
|
||||
#[prost(message, tag = "25")]
|
||||
ServerPushStream(super::ProtoServerPushStream),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user