From f7a69ac92deef63a044be0701a0939b58ff07d63 Mon Sep 17 00:00:00 2001
From: "CanbiZ (MickLesk)" <47820557+MickLesk@users.noreply.github.com>
Date: Sun, 17 May 2026 14:01:56 +0200
Subject: [PATCH] tools.func: replace max-time with speed-limit stall detection
in curl_download (#14545)
* tools.func: replace max-time with speed-limit stall detection in curl_download
* Refactor curl_download function for improved readability and remove unnecessary whitespace
---
ct/apache-guacamole.sh | 16 ++++++++--------
ct/checkmk.sh | 2 +-
ct/kasm.sh | 14 +++++++-------
install/apache-guacamole-install.sh | 6 +++---
install/apache-tomcat-install.sh | 2 +-
install/checkmk-install.sh | 2 +-
install/frigate-install.sh | 10 +++++-----
install/kasm-install.sh | 4 ++--
install/nextpvr-install.sh | 2 +-
install/omada-install.sh | 4 ++--
install/tasmocompiler-install.sh | 2 +-
misc/tools.func | 26 +++++++++++++++++---------
12 files changed, 49 insertions(+), 41 deletions(-)
diff --git a/ct/apache-guacamole.sh b/ct/apache-guacamole.sh
index 7bbe57580..3e577aaa1 100644
--- a/ct/apache-guacamole.sh
+++ b/ct/apache-guacamole.sh
@@ -89,7 +89,7 @@ function update_script() {
# Auth JDBC follows server version
msg_info "Updating Guacamole Auth JDBC"
rm -f /etc/guacamole/extensions/guacamole-auth-jdbc-mysql-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-jdbc-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-jdbc.tar.gz"
+ curl_download "/tmp/guacamole-auth-jdbc.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-jdbc-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-auth-jdbc.tar.gz -C /tmp
mv /tmp/guacamole-auth-jdbc-"${LATEST_SERVER}"/mysql/guacamole-auth-jdbc-mysql-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
echo "${LATEST_SERVER}" >~/.guacamole_auth_jdbc
@@ -101,7 +101,7 @@ function update_script() {
# Update Guacamole Client
if [[ "$CURRENT_CLIENT" != "$LATEST_CLIENT" ]]; then
msg_info "Updating Guacamole Client (${CURRENT_CLIENT} → ${LATEST_CLIENT})"
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_CLIENT}/binary/guacamole-${LATEST_CLIENT}.war" -o "/opt/apache-guacamole/tomcat9/webapps/guacamole.war"
+ curl_download "/opt/apache-guacamole/tomcat9/webapps/guacamole.war" "https://downloads.apache.org/guacamole/${LATEST_CLIENT}/binary/guacamole-${LATEST_CLIENT}.war"
echo "${LATEST_CLIENT}" >~/.guacamole_client
msg_ok "Updated Guacamole Client"
else
@@ -111,7 +111,7 @@ function update_script() {
# Update MySQL Connector
if [[ "$CURRENT_MYSQL_CONNECTOR" != "$LATEST_MYSQL_CONNECTOR" ]]; then
msg_info "Updating MySQL Connector (${CURRENT_MYSQL_CONNECTOR} → ${LATEST_MYSQL_CONNECTOR})"
- curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${LATEST_MYSQL_CONNECTOR}/mysql-connector-j-${LATEST_MYSQL_CONNECTOR}.jar" -o "/etc/guacamole/lib/mysql-connector-j.jar"
+ curl_download "/etc/guacamole/lib/mysql-connector-j.jar" "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${LATEST_MYSQL_CONNECTOR}/mysql-connector-j-${LATEST_MYSQL_CONNECTOR}.jar"
echo "${LATEST_MYSQL_CONNECTOR}" >~/.guacamole_mysql_connector
msg_ok "Updated MySQL Connector"
else
@@ -148,7 +148,7 @@ function update_script() {
if [[ -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar ]]; then
msg_info "Updating TOTP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-totp-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-totp.tar.gz"
+ curl_download "/tmp/guacamole-auth-totp.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-totp-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-auth-totp.tar.gz -C /tmp
mv /tmp/guacamole-auth-totp-"${LATEST_SERVER}"/guacamole-auth-totp-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-totp-"${LATEST_SERVER}".jar
@@ -160,7 +160,7 @@ function update_script() {
if [[ -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar ]]; then
msg_info "Updating DUO Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-duo-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-duo.tar.gz"
+ curl_download "/tmp/guacamole-auth-duo.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-duo-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-auth-duo.tar.gz -C /tmp
mv /tmp/guacamole-auth-duo-"${LATEST_SERVER}"/guacamole-auth-duo-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-duo-"${LATEST_SERVER}".jar
@@ -172,7 +172,7 @@ function update_script() {
if [[ -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar ]]; then
msg_info "Updating LDAP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-ldap-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-ldap.tar.gz"
+ curl_download "/tmp/guacamole-auth-ldap.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-ldap-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-auth-ldap.tar.gz -C /tmp
mv /tmp/guacamole-auth-ldap-"${LATEST_SERVER}"/guacamole-auth-ldap-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-ldap-"${LATEST_SERVER}".jar
@@ -184,7 +184,7 @@ function update_script() {
if [[ -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar ]]; then
msg_info "Updating Quick Connect Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-quickconnect-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-quickconnect.tar.gz"
+ curl_download "/tmp/guacamole-auth-quickconnect.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-quickconnect-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-auth-quickconnect.tar.gz -C /tmp
mv /tmp/guacamole-auth-quickconnect-"${LATEST_SERVER}"/guacamole-auth-quickconnect-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-quickconnect-"${LATEST_SERVER}".jar
@@ -196,7 +196,7 @@ function update_script() {
if [[ -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar ]]; then
msg_info "Updating History Recording Storage Extension"
rm -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar
- curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-history-recording-storage-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-history-recording-storage.tar.gz"
+ curl_download "/tmp/guacamole-history-recording-storage.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-history-recording-storage-${LATEST_SERVER}.tar.gz"
$STD tar -xf /tmp/guacamole-history-recording-storage.tar.gz -C /tmp
mv /tmp/guacamole-history-recording-storage-"${LATEST_SERVER}"/guacamole-history-recording-storage-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-history-recording-storage-"${LATEST_SERVER}".jar
diff --git a/ct/checkmk.sh b/ct/checkmk.sh
index 83cf4c226..998a7d933 100644
--- a/ct/checkmk.sh
+++ b/ct/checkmk.sh
@@ -33,7 +33,7 @@ function update_script() {
msg_info "Updating checkmk"
$STD omd stop monitoring
$STD omd cp monitoring monitoringbackup
- curl_with_retry "https://download.checkmk.com/checkmk/${RELEASE}/check-mk-community-${RELEASE}_0.$(get_os_info codename)_amd64.deb" "/opt/checkmk.deb"
+ curl_download "/opt/checkmk.deb" "https://download.checkmk.com/checkmk/${RELEASE}/check-mk-community-${RELEASE}_0.$(get_os_info codename)_amd64.deb"
$STD apt install -y /opt/checkmk.deb
OMD_VERSION=$(omd versions 2>/dev/null | grep "^${RELEASE}" | awk '{print $1}')
if [[ -z "${OMD_VERSION}" ]]; then
diff --git a/ct/kasm.sh b/ct/kasm.sh
index 2542c52d6..9d1be38c8 100644
--- a/ct/kasm.sh
+++ b/ct/kasm.sh
@@ -35,7 +35,7 @@ function update_script() {
CURRENT_VERSION=$(readlink -f /opt/kasm/current | awk -F'/' '{print $4}')
KASM_VERSION=$(curl -s https://kasm.com/downloads | grep -oP '
]*>.*?
' | sed -E 's/<\/?h1[^>]*>//g' | grep -oP '\d+\.\d+\.\d+')
KASM_URL="https://kasm-static-content.s3.amazonaws.com/kasm_release_${KASM_VERSION:-var_kasm_version}.tar.gz"
-
+
# KASM_URL=$(curl -fsSL "https://www.kasm.com/downloads" | tr '\n' ' ' | grep -oE 'https://kasm-static-content[^"]*kasm_release_[0-9]+\.[0-9]+\.[0-9]+\.[a-z0-9]+\.tar\.gz' | head -n 1)
# if [[ -z "$KASM_URL" ]]; then
# SERVICE_IMAGE_URL=$(curl -fsSL "https://www.kasm.com/downloads" | tr '\n' ' ' | grep -oE 'https://kasm-static-content[^"]*kasm_release_service_images_amd64_[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz' | head -n 1)
@@ -46,7 +46,7 @@ function update_script() {
# else
# KASM_VERSION=$(echo "$KASM_URL" | sed -E 's/.*kasm_release_([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
# fi
-
+
if [[ -z "$KASM_VERSION" ]] || [[ -z "$KASM_URL" ]]; then
msg_error "Unable to detect latest Kasm release URL."
exit 250
@@ -56,10 +56,10 @@ function update_script() {
msg_info "Removing outdated docker-compose plugin"
[ -f ~/.docker/cli-plugins/docker-compose ] && rm -rf ~/.docker/cli-plugins/docker-compose
msg_ok "Removed outdated docker-compose plugin"
-
+
if [[ -z "$CURRENT_VERSION" ]] || [[ "$KASM_VERSION" != "$CURRENT_VERSION" ]]; then
msg_info "Updating Kasm"
- cd /tmp
+ cd /tmp
msg_warn "WARNING: This script will run an external installer from a third-party source (https://www.kasmweb.com/)."
msg_warn "The following code is NOT maintained or audited by our repository."
@@ -71,17 +71,17 @@ function update_script() {
msg_error "Aborted by user. No changes have been made."
exit 10
fi
- curl -fsSL -o "/tmp/kasm_release_${KASM_VERSION}.tar.gz" "$KASM_URL"
+ curl_download "/tmp/kasm_release_${KASM_VERSION}.tar.gz" "$KASM_URL"
tar -xf "kasm_release_${KASM_VERSION}.tar.gz"
chmod +x /tmp/kasm_release/install.sh
rm -f /tmp/kasm_release_"${KASM_VERSION}".tar.gz
-
+
bash /tmp/kasm_release/upgrade.sh --proxy-port 443
rm -rf /tmp/kasm_release
msg_ok "Updated successfully!"
else
msg_ok "No update required. Kasm is already at v${KASM_VERSION}"
-
+
fi
exit
}
diff --git a/install/apache-guacamole-install.sh b/install/apache-guacamole-install.sh
index 632b2aa0c..17dfe4537 100644
--- a/install/apache-guacamole-install.sh
+++ b/install/apache-guacamole-install.sh
@@ -65,12 +65,12 @@ $STD make
$STD make install
$STD ldconfig
echo "${GUAC_SERVER_VERSION}" >~/.guacamole_server
-curl -fsSL "https://downloads.apache.org/guacamole/${GUAC_CLIENT_VERSION}/binary/guacamole-${GUAC_CLIENT_VERSION}.war" -o "/opt/apache-guacamole/tomcat9/webapps/guacamole.war"
+curl_download "/opt/apache-guacamole/tomcat9/webapps/guacamole.war" "https://downloads.apache.org/guacamole/${GUAC_CLIENT_VERSION}/binary/guacamole-${GUAC_CLIENT_VERSION}.war"
echo "${GUAC_CLIENT_VERSION}" >~/.guacamole_client
-curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${MYSQL_CONNECTOR_VERSION}/mysql-connector-j-${MYSQL_CONNECTOR_VERSION}.jar" -o "/etc/guacamole/lib/mysql-connector-j.jar"
+curl_download "/etc/guacamole/lib/mysql-connector-j.jar" "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${MYSQL_CONNECTOR_VERSION}/mysql-connector-j-${MYSQL_CONNECTOR_VERSION}.jar"
echo "${MYSQL_CONNECTOR_VERSION}" >~/.guacamole_mysql_connector
cd /root
-curl -fsSL "https://downloads.apache.org/guacamole/${GUAC_SERVER_VERSION}/binary/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz" -o "/root/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz"
+curl_download "/root/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz" "https://downloads.apache.org/guacamole/${GUAC_SERVER_VERSION}/binary/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz"
$STD tar -xf ~/guacamole-auth-jdbc-"$GUAC_SERVER_VERSION".tar.gz
mv ~/guacamole-auth-jdbc-"$GUAC_SERVER_VERSION"/mysql/guacamole-auth-jdbc-mysql-"$GUAC_SERVER_VERSION".jar /etc/guacamole/extensions/
echo "${GUAC_SERVER_VERSION}" >~/.guacamole_auth_jdbc
diff --git a/install/apache-tomcat-install.sh b/install/apache-tomcat-install.sh
index b342f6b37..c6d8843ba 100644
--- a/install/apache-tomcat-install.sh
+++ b/install/apache-tomcat-install.sh
@@ -66,7 +66,7 @@ esac
msg_info "Installing Tomcat $TOMCAT_VERSION"
LATEST_VERSION=$(curl -fsSL "https://dlcdn.apache.org/tomcat/tomcat-$TOMCAT_VERSION/" | grep -oP 'v[0-9]+\.[0-9]+\.[0-9]+(-M[0-9]+)?/' | sort -V | tail -n 1 | sed 's/\/$//; s/v//')
TOMCAT_URL="https://dlcdn.apache.org/tomcat/tomcat-$TOMCAT_VERSION/v$LATEST_VERSION/bin/apache-tomcat-$LATEST_VERSION.tar.gz"
-curl -fsSL "$TOMCAT_URL" -o "/tmp/tomcat.tar.gz"
+curl_download "/tmp/tomcat.tar.gz" "$TOMCAT_URL"
mkdir -p /opt/tomcat-$TOMCAT_VERSION
tar --strip-components=1 -xzf /tmp/tomcat.tar.gz -C /opt/tomcat-$TOMCAT_VERSION
chown -R root:root /opt/tomcat-$TOMCAT_VERSION
diff --git a/install/checkmk-install.sh b/install/checkmk-install.sh
index fac46aa90..c9b35ef4b 100644
--- a/install/checkmk-install.sh
+++ b/install/checkmk-install.sh
@@ -16,7 +16,7 @@ update_os
msg_info "Install Checkmk"
RELEASE=$(curl_with_retry "https://api.github.com/repos/checkmk/checkmk/tags" "-" | grep "name" | awk '{print substr($2, 3, length($2)-4) }' | tr ' ' '\n' | grep -Ev 'rc|b' | sort -V | tail -n 1)
RELEASE="${RELEASE%%+*}"
-curl_with_retry "https://download.checkmk.com/checkmk/${RELEASE}/check-mk-community-${RELEASE}_0.$(get_os_info codename)_amd64.deb" "/opt/checkmk.deb"
+curl_download "/opt/checkmk.deb" "https://download.checkmk.com/checkmk/${RELEASE}/check-mk-community-${RELEASE}_0.$(get_os_info codename)_amd64.deb"
$STD apt install -y /opt/checkmk.deb
rm -rf /opt/checkmk.deb
echo "${RELEASE}" >"/opt/checkmk_version.txt"
diff --git a/install/frigate-install.sh b/install/frigate-install.sh
index 777ea893c..89a1630fa 100644
--- a/install/frigate-install.sh
+++ b/install/frigate-install.sh
@@ -169,13 +169,13 @@ NODE_VERSION="20" setup_nodejs
msg_info "Downloading Inference Models"
mkdir -p /models /openvino-model
-curl_with_retry "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite" "/edgetpu_model.tflite"
-curl_with_retry "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite" "/models/cpu_model.tflite"
+curl_download "/edgetpu_model.tflite" "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite"
+curl_download "/models/cpu_model.tflite" "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite"
cp /opt/frigate/labelmap.txt /labelmap.txt
msg_ok "Downloaded Inference Models"
msg_info "Downloading Audio Model"
-curl_with_retry "https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download" "/tmp/yamnet.tar.gz"
+curl_download "/tmp/yamnet.tar.gz" "https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download"
$STD tar xzf /tmp/yamnet.tar.gz -C /
mv /1.tflite /cpu_audio_model.tflite
cp /opt/frigate/audio-labelmap.txt /audio-labelmap.txt
@@ -188,7 +188,7 @@ msg_ok "Installed OpenVino"
msg_info "Building OpenVino Model"
cd /models
-curl_with_retry "http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz" "ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz"
+curl_download "ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz" "http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz"
$STD tar -zxf ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz --no-same-owner
if python3 /opt/frigate/docker/main/build_ov_model.py &>/dev/null; then
mkdir -p /openvino-model
@@ -246,7 +246,7 @@ msg_info "Configuring Frigate"
mkdir -p /config /media/frigate
cp -r /opt/frigate/config/. /config
-curl_with_retry "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4" "/media/frigate/person-bicycle-car-detection.mp4"
+curl_download "/media/frigate/person-bicycle-car-detection.mp4" "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4"
echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab
diff --git a/install/kasm-install.sh b/install/kasm-install.sh
index 340a6ae11..3b9bafa10 100644
--- a/install/kasm-install.sh
+++ b/install/kasm-install.sh
@@ -20,7 +20,7 @@ msg_ok "Installed Docker"
msg_info "Detecting latest Kasm Workspaces release"
KASM_VERSION=$(curl -s https://kasm.com/downloads | grep -oP ']*>.*?
' | sed -E 's/<\/?h1[^>]*>//g' | grep -oP '\d+\.\d+\.\d+')
KASM_URL="https://kasm-static-content.s3.amazonaws.com/kasm_release_${KASM_VERSION:-var_kasm_version}.tar.gz"
-
+
# KASM_URL=$(curl -fsSL "https://www.kasm.com/downloads" | tr '\n' ' ' | grep -oE 'https://kasm-static-content[^"]*kasm_release_[0-9]+\.[0-9]+\.[0-9]+\.[a-z0-9]+\.tar\.gz' | head -n 1)
# if [[ -z "$KASM_URL" ]]; then
# SERVICE_IMAGE_URL=$(curl -fsSL "https://www.kasm.com/downloads" | tr '\n' ' ' | grep -oE 'https://kasm-static-content[^"]*kasm_release_service_images_amd64_[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz' | head -n 1)
@@ -50,7 +50,7 @@ if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
fi
msg_info "Installing Kasm Workspaces"
-curl -fsSL -o "/opt/kasm_release_${KASM_VERSION}.tar.gz" "$KASM_URL"
+curl_download "/opt/kasm_release_${KASM_VERSION}.tar.gz" "$KASM_URL"
cd /opt
tar -xf "kasm_release_${KASM_VERSION}.tar.gz"
chmod +x /opt/kasm_release/install.sh
diff --git a/install/nextpvr-install.sh b/install/nextpvr-install.sh
index 05c24100e..ec77f2cbc 100644
--- a/install/nextpvr-install.sh
+++ b/install/nextpvr-install.sh
@@ -30,7 +30,7 @@ msg_ok "Installed Dependencies"
msg_info "Setup NextPVR (Patience)"
cd /opt
-curl -fsSL "https://nextpvr.com/nextpvr-helper.deb" -o "/opt/nextpvr-helper.deb"
+curl_download "/opt/nextpvr-helper.deb" "https://nextpvr.com/nextpvr-helper.deb"
$STD dpkg -i nextpvr-helper.deb
rm -rf /opt/nextpvr-helper.deb
msg_ok "Installed NextPVR"
diff --git a/install/omada-install.sh b/install/omada-install.sh
index de9e47792..bfc51e092 100644
--- a/install/omada-install.sh
+++ b/install/omada-install.sh
@@ -28,7 +28,7 @@ fi
if ! dpkg -l | grep -q 'libssl1.1'; then
msg_info "Installing libssl (if needed)"
- curl -fsSL "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u5_amd64.deb" -o "/tmp/libssl.deb"
+ curl_download "/tmp/libssl.deb" "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u5_amd64.deb"
$STD dpkg -i /tmp/libssl.deb
rm -f /tmp/libssl.deb
msg_ok "Installed libssl1.1"
@@ -39,7 +39,7 @@ OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/o
grep -o 'https://static\.tp-link\.com/upload/software/[^"]*linux_x64[^"]*\.deb' |
head -n1)
OMADA_PKG=$(basename "${OMADA_URL}")
-curl -fsSL "${OMADA_URL}" -o "${OMADA_PKG}"
+curl_download "${OMADA_PKG}" "${OMADA_URL}"
$STD dpkg -i "${OMADA_PKG}"
rm -rf "${OMADA_PKG}"
VERSION=$(sed -n 's/.*_v\([0-9.]*\)_.*_\([0-9]\{14\}\)\.deb$/\1-\2/p' <<<"${OMADA_PKG}")
diff --git a/install/tasmocompiler-install.sh b/install/tasmocompiler-install.sh
index 9114de279..ece36657b 100644
--- a/install/tasmocompiler-install.sh
+++ b/install/tasmocompiler-install.sh
@@ -29,7 +29,7 @@ msg_ok "Setup Platformio"
msg_info "Setup TasmoCompiler"
mkdir /tmp/Tasmota
RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
-curl -fsSL "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz" -o "/tmp/v${RELEASE}.tar.gz"
+curl_download "/tmp/v${RELEASE}.tar.gz" "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz"
cd /tmp
tar xzf /tmp/v${RELEASE}.tar.gz
mv tasmocompiler-${RELEASE}/ /opt/tasmocompiler/
diff --git a/misc/tools.func b/misc/tools.func
index 2fcd6749e..2166f703f 100644
--- a/misc/tools.func
+++ b/misc/tools.func
@@ -2524,7 +2524,6 @@ check_for_gh_release() {
if [[ "$current" =~ ^v[0-9] ]]; then
current="${current:1}"
fi
-
# Pinned version handling
if [[ -n "$pinned_version_in" ]]; then
@@ -2796,25 +2795,34 @@ function ensure_usr_local_bin_persist() {
}
# ------------------------------------------------------------------------------
-# curl_download - Downloads a file with automatic retry and exponential backoff.
+# curl_download - Downloads a file with stall detection and retry.
#
# Usage: curl_download
#
-# Retries up to 5 times with increasing --max-time (60/120/240/480/960s).
-# Returns 0 on success, 1 if all attempts fail.
+# Uses --speed-limit / --speed-time instead of a hard --max-time cap so that
+# slow but progressing downloads (e.g. large .deb files from slow mirrors) are
+# never aborted mid-transfer. Only aborts when throughput drops below 1 KB/s
+# for 60 consecutive seconds (i.e. a genuine stall or dead connection).
+# Retries up to 3 times on failure.
+# Returns 0 on success, 7 if all attempts fail.
# ------------------------------------------------------------------------------
function curl_download() {
local output="$1"
local url="$2"
- local timeouts=(60 120 240 480 960)
+ local retries=3
+ local attempt=1
- for i in "${!timeouts[@]}"; do
- if curl --connect-timeout 15 --max-time "${timeouts[$i]}" -fsSL -o "$output" "$url"; then
+ while ((attempt <= retries)); do
+ if curl --connect-timeout 15 \
+ --speed-limit 1024 \
+ --speed-time 60 \
+ -fsSL -o "$output" "$url"; then
return 0
fi
- if ((i < ${#timeouts[@]} - 1)); then
- msg_warn "Download timed out after ${timeouts[$i]}s, retrying... (attempt $((i + 2))/${#timeouts[@]})"
+ if ((attempt < retries)); then
+ msg_warn "Download failed or stalled (attempt ${attempt}/${retries}), retrying..."
fi
+ ((attempt++))
done
return 7
}