fix: harden OpenSim session readiness
This commit is contained in:
@@ -929,35 +929,43 @@ impl crate::session::GridSessionBackend for LibremetaverseSessionBackend {
|
||||
.delivery_generation
|
||||
.write()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
let mut params = self
|
||||
.network
|
||||
.native_default_login_params(
|
||||
self.first_name.clone(),
|
||||
self.last_name.clone(),
|
||||
self.password.expose_secret().to_owned(),
|
||||
"MetaCrate".to_owned(),
|
||||
env!("CARGO_PKG_VERSION").to_owned(),
|
||||
)
|
||||
.map_err(|_| {
|
||||
crate::session::SessionFailure::new(
|
||||
crate::session::SessionFailureKind::InvalidConfiguration,
|
||||
let mut start = "last";
|
||||
loop {
|
||||
let mut params = self
|
||||
.network
|
||||
.native_default_login_params(
|
||||
self.first_name.clone(),
|
||||
self.last_name.clone(),
|
||||
self.password.expose_secret().to_owned(),
|
||||
"MetaCrate".to_owned(),
|
||||
env!("CARGO_PKG_VERSION").to_owned(),
|
||||
)
|
||||
})?;
|
||||
params.uri.clone_from(&self.login_url);
|
||||
"last".clone_into(&mut params.start);
|
||||
let logged_in = self
|
||||
.network
|
||||
.native_login(params, Some(cancellation))
|
||||
.await
|
||||
.map_err(|_| {
|
||||
crate::session::SessionFailure::new(
|
||||
crate::session::SessionFailureKind::TransientTransport,
|
||||
)
|
||||
})?;
|
||||
if !logged_in {
|
||||
return Err(classify_native_login_failure(
|
||||
&self.network.native_login_error_key(),
|
||||
));
|
||||
.map_err(|_| {
|
||||
crate::session::SessionFailure::new(
|
||||
crate::session::SessionFailureKind::InvalidConfiguration,
|
||||
)
|
||||
})?;
|
||||
params.uri.clone_from(&self.login_url);
|
||||
start.clone_into(&mut params.start);
|
||||
let logged_in = self
|
||||
.network
|
||||
.native_login(params, Some(cancellation.clone()))
|
||||
.await
|
||||
.map_err(|_| {
|
||||
crate::session::SessionFailure::new(
|
||||
crate::session::SessionFailureKind::TransientTransport,
|
||||
)
|
||||
})?;
|
||||
if logged_in {
|
||||
break;
|
||||
}
|
||||
let error_key = self.network.native_login_error_key();
|
||||
let message = self.network.native_login_message();
|
||||
if start == "last" && native_last_location_unavailable(&message) {
|
||||
start = "home";
|
||||
continue;
|
||||
}
|
||||
return Err(classify_native_login_failure(&error_key, &message));
|
||||
}
|
||||
|
||||
// Native login has already installed the current simulator and
|
||||
@@ -1252,9 +1260,16 @@ fn native_delivery_id(prefix: &str, fields: &[&str]) -> String {
|
||||
}
|
||||
|
||||
#[cfg(feature = "live-grid")]
|
||||
fn classify_native_login_failure(error_key: &str) -> crate::session::SessionFailure {
|
||||
fn classify_native_login_failure(error_key: &str, message: &str) -> crate::session::SessionFailure {
|
||||
let normalized = error_key.trim().to_ascii_lowercase();
|
||||
let kind = if matches!(
|
||||
let kind = if native_last_location_unavailable(message)
|
||||
|| message
|
||||
.trim()
|
||||
.to_ascii_lowercase()
|
||||
.contains("already logged in")
|
||||
{
|
||||
crate::session::SessionFailureKind::ServerFailure
|
||||
} else if matches!(
|
||||
normalized.as_str(),
|
||||
"key" | "password" | "credential" | "account" | "username" | "user"
|
||||
) {
|
||||
@@ -1267,6 +1282,13 @@ fn classify_native_login_failure(error_key: &str) -> crate::session::SessionFail
|
||||
crate::session::SessionFailure::new(kind)
|
||||
}
|
||||
|
||||
#[cfg(feature = "live-grid")]
|
||||
fn native_last_location_unavailable(message: &str) -> bool {
|
||||
let message = message.trim().to_ascii_lowercase();
|
||||
message.contains("failed to verify user presence")
|
||||
|| message.contains("access denied to region")
|
||||
}
|
||||
|
||||
impl GridBackend for OfflineGridBackend {
|
||||
fn name(&self) -> &'static str {
|
||||
"offline-fake"
|
||||
@@ -1315,4 +1337,24 @@ mod tests {
|
||||
cancellation.cancel();
|
||||
run.await.expect("clean cancellation");
|
||||
}
|
||||
|
||||
#[cfg(feature = "live-grid")]
|
||||
#[test]
|
||||
fn stale_presence_is_retryable_without_masking_bad_credentials() {
|
||||
assert!(native_last_location_unavailable(
|
||||
"Failed to verify user presence in the grid, access denied to region",
|
||||
));
|
||||
assert_eq!(
|
||||
classify_native_login_failure(
|
||||
"account",
|
||||
"Failed to verify user presence in the grid, access denied to region",
|
||||
)
|
||||
.kind(),
|
||||
crate::session::SessionFailureKind::ServerFailure,
|
||||
);
|
||||
assert_eq!(
|
||||
classify_native_login_failure("account", "Invalid credentials").kind(),
|
||||
crate::session::SessionFailureKind::InvalidCredentials,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user