mirror of
https://github.com/telemt/telemt.git
synced 2026-05-23 04:01:44 +03:00
Compare commits
6 Commits
toolchains
...
d0f02f59f8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0f02f59f8 | ||
|
|
bbc69f945e | ||
|
|
4d83d02a8f | ||
|
|
fea8bc63fd | ||
|
|
d8f7173f15 | ||
|
|
b23d433e19 |
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -130,14 +130,12 @@ jobs:
|
|||||||
pkg-config \
|
pkg-config \
|
||||||
curl
|
curl
|
||||||
|
|
||||||
# 💾 cache toolchain
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
if: matrix.target == 'aarch64-unknown-linux-musl'
|
if: matrix.target == 'aarch64-unknown-linux-musl'
|
||||||
with:
|
with:
|
||||||
path: ~/.musl-aarch64
|
path: ~/.musl-aarch64
|
||||||
key: musl-toolchain-aarch64-v1
|
key: musl-toolchain-aarch64-v1
|
||||||
|
|
||||||
# 🔥 надёжная установка
|
|
||||||
- name: Install aarch64 musl toolchain
|
- name: Install aarch64 musl toolchain
|
||||||
if: matrix.target == 'aarch64-unknown-linux-musl'
|
if: matrix.target == 'aarch64-unknown-linux-musl'
|
||||||
run: |
|
run: |
|
||||||
@@ -145,27 +143,19 @@ jobs:
|
|||||||
|
|
||||||
TOOLCHAIN_DIR="$HOME/.musl-aarch64"
|
TOOLCHAIN_DIR="$HOME/.musl-aarch64"
|
||||||
ARCHIVE="aarch64-linux-musl-cross.tgz"
|
ARCHIVE="aarch64-linux-musl-cross.tgz"
|
||||||
|
URL="https://github.com/telemt/telemt/releases/download/toolchains/$ARCHIVE"
|
||||||
|
|
||||||
if [ -x "$TOOLCHAIN_DIR/bin/aarch64-linux-musl-gcc" ]; then
|
if [ -x "$TOOLCHAIN_DIR/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
echo "✅ musl toolchain already installed"
|
echo "✅ MUSL toolchain already installed"
|
||||||
else
|
else
|
||||||
echo "⬇️ downloading musl toolchain..."
|
echo "⬇️ Downloading musl toolchain from Telemt GitHub Releases..."
|
||||||
|
|
||||||
download() {
|
curl -fL \
|
||||||
url="$1"
|
--retry 5 \
|
||||||
echo "→ trying $url"
|
--retry-delay 3 \
|
||||||
curl -fL \
|
--connect-timeout 10 \
|
||||||
--retry 5 \
|
--max-time 120 \
|
||||||
--retry-delay 3 \
|
-o "$ARCHIVE" "$URL"
|
||||||
--connect-timeout 10 \
|
|
||||||
--max-time 120 \
|
|
||||||
-o "$ARCHIVE" "$url" && return 0
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
download "https://musl.cc/$ARCHIVE" || \
|
|
||||||
download "https://more.musl.cc/$ARCHIVE" || \
|
|
||||||
{ echo "❌ failed to download musl toolchain"; exit 1; }
|
|
||||||
|
|
||||||
mkdir -p "$TOOLCHAIN_DIR"
|
mkdir -p "$TOOLCHAIN_DIR"
|
||||||
tar -xzf "$ARCHIVE" --strip-components=1 -C "$TOOLCHAIN_DIR"
|
tar -xzf "$ARCHIVE" --strip-components=1 -C "$TOOLCHAIN_DIR"
|
||||||
|
|||||||
@@ -346,6 +346,12 @@ impl ProxyConfig {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.timeouts.tg_connect == 0 {
|
||||||
|
return Err(ProxyError::Config(
|
||||||
|
"timeouts.tg_connect must be > 0".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if config.general.upstream_unhealthy_fail_threshold == 0 {
|
if config.general.upstream_unhealthy_fail_threshold == 0 {
|
||||||
return Err(ProxyError::Config(
|
return Err(ProxyError::Config(
|
||||||
"general.upstream_unhealthy_fail_threshold must be > 0".to_string(),
|
"general.upstream_unhealthy_fail_threshold must be > 0".to_string(),
|
||||||
@@ -1625,6 +1631,26 @@ mod tests {
|
|||||||
let _ = std::fs::remove_file(path);
|
let _ = std::fs::remove_file(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tg_connect_zero_is_rejected() {
|
||||||
|
let toml = r#"
|
||||||
|
[timeouts]
|
||||||
|
tg_connect = 0
|
||||||
|
|
||||||
|
[censorship]
|
||||||
|
tls_domain = "example.com"
|
||||||
|
|
||||||
|
[access.users]
|
||||||
|
user = "00000000000000000000000000000000"
|
||||||
|
"#;
|
||||||
|
let dir = std::env::temp_dir();
|
||||||
|
let path = dir.join("telemt_tg_connect_zero_test.toml");
|
||||||
|
std::fs::write(&path, toml).unwrap();
|
||||||
|
let err = ProxyConfig::load(&path).unwrap_err().to_string();
|
||||||
|
assert!(err.contains("timeouts.tg_connect must be > 0"));
|
||||||
|
let _ = std::fs::remove_file(path);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_proxy_req_every_out_of_range_is_rejected() {
|
fn rpc_proxy_req_every_out_of_range_is_rejected() {
|
||||||
let toml = r#"
|
let toml = r#"
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
|||||||
config.general.upstream_connect_retry_attempts,
|
config.general.upstream_connect_retry_attempts,
|
||||||
config.general.upstream_connect_retry_backoff_ms,
|
config.general.upstream_connect_retry_backoff_ms,
|
||||||
config.general.upstream_connect_budget_ms,
|
config.general.upstream_connect_budget_ms,
|
||||||
|
config.timeouts.tg_connect,
|
||||||
config.general.upstream_unhealthy_fail_threshold,
|
config.general.upstream_unhealthy_fail_threshold,
|
||||||
config.general.upstream_connect_failfast_hard_errors,
|
config.general.upstream_connect_failfast_hard_errors,
|
||||||
stats.clone(),
|
stats.clone(),
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ const NUM_DCS: usize = 5;
|
|||||||
|
|
||||||
/// Timeout for individual DC ping attempt
|
/// Timeout for individual DC ping attempt
|
||||||
const DC_PING_TIMEOUT_SECS: u64 = 5;
|
const DC_PING_TIMEOUT_SECS: u64 = 5;
|
||||||
/// Timeout for direct TG DC TCP connect readiness.
|
|
||||||
const DIRECT_CONNECT_TIMEOUT_SECS: u64 = 10;
|
|
||||||
/// Interval between upstream health-check cycles.
|
/// Interval between upstream health-check cycles.
|
||||||
const HEALTH_CHECK_INTERVAL_SECS: u64 = 30;
|
const HEALTH_CHECK_INTERVAL_SECS: u64 = 30;
|
||||||
/// Timeout for a single health-check connect attempt.
|
/// Timeout for a single health-check connect attempt.
|
||||||
@@ -319,6 +317,8 @@ pub struct UpstreamManager {
|
|||||||
connect_retry_attempts: u32,
|
connect_retry_attempts: u32,
|
||||||
connect_retry_backoff: Duration,
|
connect_retry_backoff: Duration,
|
||||||
connect_budget: Duration,
|
connect_budget: Duration,
|
||||||
|
/// Per-attempt TCP connect timeout to Telegram DC (`[timeouts] tg_connect`, seconds).
|
||||||
|
tg_connect_timeout_secs: u64,
|
||||||
unhealthy_fail_threshold: u32,
|
unhealthy_fail_threshold: u32,
|
||||||
connect_failfast_hard_errors: bool,
|
connect_failfast_hard_errors: bool,
|
||||||
no_upstreams_warn_epoch_ms: Arc<AtomicU64>,
|
no_upstreams_warn_epoch_ms: Arc<AtomicU64>,
|
||||||
@@ -332,6 +332,7 @@ impl UpstreamManager {
|
|||||||
connect_retry_attempts: u32,
|
connect_retry_attempts: u32,
|
||||||
connect_retry_backoff_ms: u64,
|
connect_retry_backoff_ms: u64,
|
||||||
connect_budget_ms: u64,
|
connect_budget_ms: u64,
|
||||||
|
tg_connect_timeout_secs: u64,
|
||||||
unhealthy_fail_threshold: u32,
|
unhealthy_fail_threshold: u32,
|
||||||
connect_failfast_hard_errors: bool,
|
connect_failfast_hard_errors: bool,
|
||||||
stats: Arc<Stats>,
|
stats: Arc<Stats>,
|
||||||
@@ -347,6 +348,7 @@ impl UpstreamManager {
|
|||||||
connect_retry_attempts: connect_retry_attempts.max(1),
|
connect_retry_attempts: connect_retry_attempts.max(1),
|
||||||
connect_retry_backoff: Duration::from_millis(connect_retry_backoff_ms),
|
connect_retry_backoff: Duration::from_millis(connect_retry_backoff_ms),
|
||||||
connect_budget: Duration::from_millis(connect_budget_ms.max(1)),
|
connect_budget: Duration::from_millis(connect_budget_ms.max(1)),
|
||||||
|
tg_connect_timeout_secs: tg_connect_timeout_secs.max(1),
|
||||||
unhealthy_fail_threshold: unhealthy_fail_threshold.max(1),
|
unhealthy_fail_threshold: unhealthy_fail_threshold.max(1),
|
||||||
connect_failfast_hard_errors,
|
connect_failfast_hard_errors,
|
||||||
no_upstreams_warn_epoch_ms: Arc::new(AtomicU64::new(0)),
|
no_upstreams_warn_epoch_ms: Arc::new(AtomicU64::new(0)),
|
||||||
@@ -797,8 +799,8 @@ impl UpstreamManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let remaining_budget = self.connect_budget.saturating_sub(elapsed);
|
let remaining_budget = self.connect_budget.saturating_sub(elapsed);
|
||||||
let attempt_timeout =
|
let attempt_timeout = Duration::from_secs(self.tg_connect_timeout_secs)
|
||||||
Duration::from_secs(DIRECT_CONNECT_TIMEOUT_SECS).min(remaining_budget);
|
.min(remaining_budget);
|
||||||
if attempt_timeout.is_zero() {
|
if attempt_timeout.is_zero() {
|
||||||
last_error = Some(ProxyError::ConnectionTimeout {
|
last_error = Some(ProxyError::ConnectionTimeout {
|
||||||
addr: target.to_string(),
|
addr: target.to_string(),
|
||||||
@@ -1901,6 +1903,7 @@ mod tests {
|
|||||||
1,
|
1,
|
||||||
100,
|
100,
|
||||||
1000,
|
1000,
|
||||||
|
10,
|
||||||
1,
|
1,
|
||||||
false,
|
false,
|
||||||
Arc::new(Stats::new()),
|
Arc::new(Stats::new()),
|
||||||
|
|||||||
Reference in New Issue
Block a user