cllipy fix

This commit is contained in:
Donjuanplatinum
2026-03-08 12:23:02 +08:00
parent 2b81e189cb
commit ad896bb091
4 changed files with 52 additions and 42 deletions

View File

@@ -100,17 +100,21 @@ pub(crate) async fn create_mxc_uri_route(
media_id: &utils::random_string(MXC_LENGTH), media_id: &utils::random_string(MXC_LENGTH),
}; };
let unused_expires_at = (std::time::SystemTime::now() let unused_expires_at = u64::try_from(
.duration_since(std::time::UNIX_EPOCH) std::time::SystemTime::now()
.expect("Time went backwards") .duration_since(std::time::UNIX_EPOCH)
.as_millis() as u64) .expect("Time went backwards")
.saturating_add( .as_millis(),
services )?
.saturating_add(
services
.server .server
.config .config
.media_create_unused_expiration_time .media_create_unused_expiration_time
* 1000, // safe because even if it overflows, it will be greater than the current time
); // and the unused media will be deleted anyway
.saturating_mul(1000),
);
services services
.media .media
.create_pending(&mxc, user, unused_expires_at) .create_pending(&mxc, user, unused_expires_at)

View File

@@ -427,13 +427,13 @@ pub struct Config {
/// ///
/// default: 10 /// default: 10
#[serde(default = "default_rc_media_create_per_second")] #[serde(default = "default_rc_media_create_per_second")]
pub rc_media_create_per_second: u64, pub rc_media_create_per_second: u32,
/// The maximum burst count for media create requests from a single user. /// The maximum burst count for media create requests from a single user.
/// ///
/// default: 50 /// default: 50
#[serde(default = "default_rc_media_create_burst_count")] #[serde(default = "default_rc_media_create_burst_count")]
pub rc_media_create_burst_count: u64, pub rc_media_create_burst_count: u32,
/// default: 192 /// default: 192
#[serde(default = "default_max_fetch_prev_events")] #[serde(default = "default_max_fetch_prev_events")]
@@ -3274,8 +3274,8 @@ fn default_ip_lookup_strategy() -> u8 { 5 }
fn default_max_request_size() -> usize { 24 * 1024 * 1024 } fn default_max_request_size() -> usize { 24 * 1024 * 1024 }
fn default_max_pending_media_uploads() -> usize { 5 } fn default_max_pending_media_uploads() -> usize { 5 }
fn default_media_create_unused_expiration_time() -> u64 { 86400 } fn default_media_create_unused_expiration_time() -> u64 { 86400 }
fn default_rc_media_create_per_second() -> u64 { 10 } fn default_rc_media_create_per_second() -> u32 { 10 }
fn default_rc_media_create_burst_count() -> u64 { 50 } fn default_rc_media_create_burst_count() -> u32 { 50 }
fn default_request_conn_timeout() -> u64 { 10 } fn default_request_conn_timeout() -> u64 { 10 }

View File

@@ -70,7 +70,12 @@ impl Data {
); );
// 8 bytes for unused_expires_at (u64), 1 byte for 0xFF, and // 8 bytes for unused_expires_at (u64), 1 byte for 0xFF, and
// user.as_bytes().len() for user value: [unused_expires_at, 0xFF, user] // user.as_bytes().len() for user value: [unused_expires_at, 0xFF, user]
let mut value = Vec::with_capacity(user.as_bytes().len() + 9); let mut value = Vec::with_capacity(
user.as_bytes()
.len()
.checked_add(9)
.expect("User len too large,capacity overflow!"),
);
value.extend_from_slice(&unused_expires_at.to_be_bytes()); value.extend_from_slice(&unused_expires_at.to_be_bytes());
value.push(0xFF); value.push(0xFF);
value.extend_from_slice(user.as_bytes()); value.extend_from_slice(user.as_bytes());
@@ -80,7 +85,7 @@ impl Data {
/// Count the number of pending MXC URIs for a specific user /// Count the number of pending MXC URIs for a specific user
pub(super) async fn count_pending_mxc_for_user(&self, user: &UserId) -> (usize, u64) { pub(super) async fn count_pending_mxc_for_user(&self, user: &UserId) -> (usize, u64) {
let mut count = 0; let mut count: usize = 0;
let mut earliest_expiration = u64::MAX; let mut earliest_expiration = u64::MAX;
let user_bytes = user.as_bytes(); let user_bytes = user.as_bytes();
@@ -89,18 +94,19 @@ impl Data {
.ignore_err() .ignore_err()
.ready_for_each(|(_key, value)| { .ready_for_each(|(_key, value)| {
let mut parts = value.splitn(2, |&b| b == 0xFF); let mut parts = value.splitn(2, |&b| b == 0xFF);
if let Some(expires_at_bytes) = parts.next() { match (parts.next(), parts.next()) {
if let Some(user_id_bytes) = parts.next() { | (Some(expires_at_bytes), Some(user_id_bytes))
if user_id_bytes == user_bytes { if user_id_bytes == user_bytes =>
count += 1; {
let expires_at = u64::from_be_bytes( // safe to add 1 even if count = usize::MAX it also > max_uploads
expires_at_bytes.try_into().unwrap_or([0u8; 8]), count = count.saturating_add(1_usize);
); let expires_at =
if expires_at < earliest_expiration { u64::from_be_bytes(expires_at_bytes.try_into().unwrap_or([0_u8; 8]));
earliest_expiration = expires_at; if expires_at < earliest_expiration {
} earliest_expiration = expires_at;
} }
} },
| _ => {},
} }
}) })
.await; .await;
@@ -133,12 +139,10 @@ impl Data {
}, },
}; };
let user_id_bytes = parts.next()?; let user_id_bytes = parts.next()?;
let user_str = match str_from_bytes(user_id_bytes) {
| Ok(v) => v, let Ok(user_str) = str_from_bytes(user_id_bytes) else {
| Err(_) => { tracing::error!("Failed to parse user_str for {}", key);
tracing::error!("Failed to parse user_str for {}", key); return None;
return None;
},
}; };
let user_id = match user_str.try_into() { let user_id = match user_str.try_into() {
| Ok(v) => v, | Ok(v) => v,

View File

@@ -93,8 +93,8 @@ impl Service {
let config = &self.services.server.config; let config = &self.services.server.config;
// Rate limiting (rc_media_create) // Rate limiting (rc_media_create)
let rate = config.rc_media_create_per_second as f64; let rate = f64::from(config.rc_media_create_per_second);
let burst = config.rc_media_create_burst_count as f64; let burst = f64::from(config.rc_media_create_burst_count);
// Check rate limiting // Check rate limiting
if rate > 0.0 && burst > 0.0 { if rate > 0.0 && burst > 0.0 {
@@ -106,7 +106,7 @@ impl Service {
.or_insert_with(|| (now, burst)); .or_insert_with(|| (now, burst));
let elapsed = now.duration_since(*last_time).as_secs_f64(); let elapsed = now.duration_since(*last_time).as_secs_f64();
let new_tokens = (*tokens + elapsed * rate).min(burst); let new_tokens = elapsed.mul_add(rate, *tokens).min(burst);
if new_tokens >= 1.0 { if new_tokens >= 1.0 {
*last_time = now; *last_time = now;
@@ -126,12 +126,12 @@ impl Service {
// Check if the user has reached the maximum number of pending media uploads // Check if the user has reached the maximum number of pending media uploads
if current_uploads >= max_uploads { if current_uploads >= max_uploads {
let retry_after = earliest_expiration.saturating_sub( let retry_after = earliest_expiration.saturating_sub(u64::try_from(
SystemTime::now() SystemTime::now()
.duration_since(std::time::UNIX_EPOCH) .duration_since(std::time::UNIX_EPOCH)
.unwrap() .unwrap()
.as_millis() as u64, .as_millis(),
); )?);
return Err(tuwunel_core::Error::Request( return Err(tuwunel_core::Error::Request(
ruma::api::client::error::ErrorKind::LimitExceeded { ruma::api::client::error::ErrorKind::LimitExceeded {
retry_after: Some(ruma::api::client::error::RetryAfter::Delay( retry_after: Some(ruma::api::client::error::RetryAfter::Delay(
@@ -166,10 +166,12 @@ impl Service {
return Err!(Request(Forbidden("You did not create this media ID"))); return Err!(Request(Forbidden("You did not create this media ID")));
} }
let current_time = SystemTime::now() let current_time = u64::try_from(
.duration_since(std::time::UNIX_EPOCH) SystemTime::now()
.expect("Time went backwards") .duration_since(std::time::UNIX_EPOCH)
.as_millis() as u64; .expect("Time went backwards")
.as_millis(),
)?;
if expires_at < current_time { if expires_at < current_time {
return Err!(Request(NotFound("Pending media ID expired"))); return Err!(Request(NotFound("Pending media ID expired")));