use super::*;
use std::time::{Duration, Instant};
fn wait_slice(deadline: Instant) -> i32 {
deadline
.saturating_duration_since(Instant::now())
.min(Duration::from_millis(50))
.as_millis()
.min(i32::MAX as u128) as i32
}
impl Client {
pub fn login(&self, nickname: &str, username: &str, password: &str, client_name: &str) -> i32 {
if !can_login_in_state(self.connection_state()) {
return 0;
}
let cmd_id =
self.backend()
.do_login_ex(self.ptr.0, nickname, username, password, client_name);
if cmd_id > 0 {
self.set_connection_state(crate::events::ConnectionState::LoggingIn);
self.mark_login_phase_started(cmd_id);
}
cmd_id
}
pub fn set_login_params(&self, params: LoginParams) {
let mut auto = self
.auto_reconnect
.lock()
.unwrap_or_else(|e| e.into_inner());
auto.login = Some(params);
auto.login_gave_up = false;
auto.clear_login_phase();
}
pub fn login_params(&self) -> Option<LoginParams> {
self.auto_reconnect
.lock()
.unwrap_or_else(|e| e.into_inner())
.login
.clone()
}
pub fn login_with_params(&self) -> Result<i32, crate::events::Error> {
let params = self
.login_params()
.ok_or(crate::events::Error::MissingLoginParams)?;
Ok(self.login(
¶ms.nickname,
¶ms.username,
¶ms.password,
¶ms.client_name,
))
}
pub fn login_and_wait(
&self,
nickname: &str,
username: &str,
password: &str,
client_name: &str,
timeout_ms: i32,
) -> Result<crate::client::Message, crate::events::Error> {
let cmd_id = self.login(nickname, username, password, client_name);
if cmd_id <= 0 {
return Err(crate::events::Error::AuthFailed);
}
if timeout_ms < 0 {
loop {
if let Some((event, message)) = self.poll(50) {
match event {
crate::events::Event::MySelfLoggedIn => return Ok(message),
crate::events::Event::CmdError if message.source() == cmd_id => {
return Err(crate::events::Error::AuthFailed);
}
_ => {}
}
}
if self.connection_state() != crate::events::ConnectionState::LoggingIn {
return Err(crate::events::Error::AuthFailed);
}
}
}
let deadline = Instant::now() + Duration::from_millis(timeout_ms as u64);
loop {
let wait_ms = wait_slice(deadline);
if wait_ms <= 0 {
return Err(crate::events::Error::Timeout);
}
if let Some((event, message)) = self.poll(wait_ms) {
match event {
crate::events::Event::MySelfLoggedIn => return Ok(message),
crate::events::Event::CmdError if message.source() == cmd_id => {
return Err(crate::events::Error::AuthFailed);
}
_ => {}
}
}
if self.connection_state() != crate::events::ConnectionState::LoggingIn {
return Err(crate::events::Error::AuthFailed);
}
}
}
pub fn login_remember(
&self,
nickname: &str,
username: &str,
password: &str,
client_name: &str,
) -> i32 {
let params = LoginParams::new(nickname, username, password, client_name);
self.set_login_params(params);
self.login(nickname, username, password, client_name)
}
pub fn login_from_env(&self) -> i32 {
let params = LoginParams::from_env();
self.set_login_params(params.clone());
self.login(
¶ms.nickname,
¶ms.username,
¶ms.password,
¶ms.client_name,
)
}
pub fn logout(&self) -> i32 {
if !can_logout_in_state(self.connection_state()) {
return 0;
}
let cmd_id = self.backend().do_logout(self.ptr.0);
if cmd_id > 0 {
self.set_connection_state(crate::events::ConnectionState::Connected);
}
cmd_id
}
}