Cleanup & Fixes
This commit is contained in:
1 parent
340b8db1b9
commit
68de25838c
6 files changed
+510
-765
No files matched your search
+1
-1
@@ -19,6 +19,6 @@ tokio-util.workspace = true
|
||||
tracing.workspace = true
|
||||
rand.workspace = true
|
||||
url.workspace = true
|
||||
flume.workspace =true
|
||||
flume.workspace = true
|
||||
error-stack.workspace = true
|
||||
thiserror.workspace = true
|
||||
+53
-327
@@ -23,11 +23,12 @@ pub mod config;
|
||||
|
||||
pub struct BankClient {
|
||||
client: Client<Handler>,
|
||||
rx: Receiver<ResponseMessage>,
|
||||
rx_msg: Receiver<ResponseMessage>,
|
||||
rx_act: Receiver<ClientAction>,
|
||||
handle: JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>>
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum BankError {
|
||||
#[error("Request timed out")]
|
||||
TimedOut,
|
||||
@@ -41,8 +42,8 @@ pub enum BankError {
|
||||
DestinationUnknown,
|
||||
#[error("You don't have enough Steam Coins")]
|
||||
NotEnoughMoney,
|
||||
#[error("Unknown unexpected message received")]
|
||||
UnexpectedMessage
|
||||
#[error("Unknown unexpected message received {_0:?}")]
|
||||
UnexpectedMessage(ResponseMessage)
|
||||
}
|
||||
|
||||
pub type BankResult<T, E = BankError> = error_stack::Result<T, E>;
|
||||
@@ -52,42 +53,38 @@ impl BankClient {
|
||||
let url = url.into();
|
||||
let client_config = ClientConfig::new(url);
|
||||
let random: u8 = random();
|
||||
let (tx, rx) = flume::unbounded();
|
||||
let (tx_msg, rx_msg) = flume::unbounded();
|
||||
let (tx_act, rx_act) = flume::unbounded();
|
||||
let (client, future) = ezsockets::connect(
|
||||
move |client| Handler {
|
||||
client,
|
||||
tx,
|
||||
tx_msg,
|
||||
tx_act,
|
||||
username: String::new(),
|
||||
password: String::new(),
|
||||
id: random as i32,
|
||||
receivers: VecDeque::new(),
|
||||
},
|
||||
client_config,
|
||||
}, client_config,
|
||||
).await;
|
||||
let handle = tokio::spawn(future);
|
||||
Self {
|
||||
client,
|
||||
rx,
|
||||
handle,
|
||||
}
|
||||
Self { client, rx_msg, rx_act, handle }
|
||||
}
|
||||
pub async fn send_authenticated(
|
||||
&self,
|
||||
message: AuthenticatedMessage,
|
||||
accept: fn(&ResponseMessage) -> bool,
|
||||
) -> BankResult<Response> {
|
||||
pub async fn send_authenticated(&self, message: AuthenticatedMessage, accept: fn(&ResponseMessage) -> bool) -> BankResult<Response> {
|
||||
self.check_running()?;
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.client.call(ClientCommand::SendAuthenticatedNew {message, accept, tx}).map_err(|_| report!(BankError::InternalError))?;
|
||||
tokio::time::timeout(Duration::from_secs(2), rx.into_future()).await.map_err(|_| report!(BankError::TimedOut))?.map_err(|_| report!(BankError::InternalError))?.map_err(|err| report!(err))
|
||||
tokio::time::timeout(Duration::from_secs(5), rx.into_future()).await.map_err(|_| report!(BankError::TimedOut))?.map_err(|_| report!(BankError::InternalError))?.map_err(|err| report!(err))
|
||||
}
|
||||
|
||||
pub fn set_credentials(&self, username: String, password: String) -> BankResult<()> {
|
||||
self.client.call(ClientCommand::ChangeCredentials {username, password}).map_err(|_| report!(BankError::InternalError))
|
||||
}
|
||||
|
||||
pub fn receiver(&self) -> &Receiver<ResponseMessage> {
|
||||
&self.rx
|
||||
pub fn receiver_msg(&self) -> &Receiver<ResponseMessage> {
|
||||
&self.rx_msg
|
||||
}
|
||||
pub fn receiver_act(&self) -> &Receiver<ClientAction> {
|
||||
&self.rx_act
|
||||
}
|
||||
|
||||
fn check_running(&self) -> BankResult<(), BankError>{
|
||||
@@ -108,22 +105,11 @@ impl BankClient {
|
||||
|
||||
struct Handler {
|
||||
client: Client<Handler>,
|
||||
//config: Arc<Mutex<Config>>,
|
||||
tx: Sender<ResponseMessage>,
|
||||
tx_msg: Sender<ResponseMessage>,
|
||||
tx_act: Sender<ClientAction>,
|
||||
username: String,
|
||||
password: String,
|
||||
//last_username: String,
|
||||
//last_password: String,
|
||||
id: i32,
|
||||
//logged_in: bool,
|
||||
/*message_queue: VecDeque<(
|
||||
AuthenticatedMessage,
|
||||
Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
)>,
|
||||
send_time: SystemTime,
|
||||
retry_count: u8,
|
||||
inbox_message_count: u8,
|
||||
pm_message_count: u8,*/
|
||||
receivers: VecDeque<(fn(&ResponseMessage) -> bool, oneshot::Sender<Result<Response, BankError>>)>
|
||||
}
|
||||
|
||||
@@ -135,34 +121,7 @@ impl Handler {
|
||||
}
|
||||
}
|
||||
|
||||
/*fn last_credentials(&self) -> Credentials {
|
||||
Credentials {
|
||||
username: &self.last_username,
|
||||
password: &self.last_password,
|
||||
}
|
||||
}*/
|
||||
|
||||
/*fn send_authenticated(&mut self, message: AuthenticatedMessage) {
|
||||
self.send_authenticated_callback(message);
|
||||
}*/
|
||||
|
||||
/*fn send_authenticated_callback(
|
||||
&mut self,
|
||||
message: AuthenticatedMessage,
|
||||
callback: Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
) {
|
||||
if self.message_queue.is_empty() {
|
||||
self.send_authenticated_now(message, callback);
|
||||
} else {
|
||||
self.message_queue.push_back((message, callback));
|
||||
}
|
||||
}*/
|
||||
|
||||
fn send_authenticated(
|
||||
&mut self,
|
||||
message: AuthenticatedMessage,
|
||||
//callback: Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
) {
|
||||
fn send_authenticated(&mut self, message: AuthenticatedMessage) {
|
||||
#[derive(Serialize)]
|
||||
struct WithCredentials<'a> {
|
||||
#[serde(flatten)]
|
||||
@@ -172,40 +131,20 @@ impl Handler {
|
||||
id: i32,
|
||||
}
|
||||
|
||||
/*if message == AuthenticatedMessage::Authenticate && self.logged_in {
|
||||
self.send_authenticated_now(AuthenticatedMessage::Logout, Box::new(Box::pin(async {})));
|
||||
self.send_authenticated(message);
|
||||
return;
|
||||
}*/
|
||||
|
||||
//self.send_time = SystemTime::now();
|
||||
//self.message_queue.push_front((message.clone(), callback));
|
||||
|
||||
debug!("Sending: {message:?}");
|
||||
let credentials: Credentials = self.credentials();
|
||||
self.client
|
||||
.text(
|
||||
serde_json::to_string(&WithCredentials {
|
||||
credentials,
|
||||
message,
|
||||
id: self.id,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
.expect("Could not send authenticated message");
|
||||
self.client.text(serde_json::to_string(&WithCredentials {
|
||||
credentials,
|
||||
message,
|
||||
id: self.id,
|
||||
}).unwrap(), ).expect("Could not send authenticated message");
|
||||
}
|
||||
|
||||
/*fn backup_auth(&mut self) {
|
||||
if !self.last_username.is_empty() && !self.last_password.is_empty() {
|
||||
self.username = self.last_username.clone();
|
||||
self.password = self.last_password.clone();
|
||||
self.send_authenticated(AuthenticatedMessage::Authenticate)
|
||||
fn clear_receivers(&mut self, error: BankError) {
|
||||
for (_, tx) in self.receivers.drain(..) {
|
||||
let _ = tx.send(Err(error.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn auth_error(&self) {
|
||||
warn!("Authentication error while logged in. Did the password change?");
|
||||
}*/
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -254,7 +193,7 @@ pub enum AuthenticatedMessage {
|
||||
Motd,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[serde(tag = "action", rename_all = "camelCase")]
|
||||
pub enum Response {
|
||||
DisplayMessage {
|
||||
@@ -286,7 +225,7 @@ pub enum Response {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
pub struct ResponseMessage {
|
||||
#[serde(flatten)]
|
||||
pub message: Response,
|
||||
@@ -309,7 +248,6 @@ impl ezsockets::ClientExt for Handler {
|
||||
async fn on_text(&mut self, text: String) -> Result<(), Error> {
|
||||
debug!("Received: {text}");
|
||||
|
||||
|
||||
let message: ResponseMessage =
|
||||
serde_json::from_str(text.as_str()).expect("Error decoding message");
|
||||
if message.id == self.id || message.id == -1 {
|
||||
@@ -325,163 +263,21 @@ impl ezsockets::ClientExt for Handler {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some((index, (_, _))) = self.receivers.iter().enumerate().find(|(_, (accept, _))| accept(&message)) {
|
||||
let mut found = false;
|
||||
while let Some((index, (_, _))) = self.receivers.iter().enumerate().find(|(_, (accept, _))| accept(&message)) {
|
||||
let (_, tx) = self.receivers.remove(index).unwrap();
|
||||
if let Err(_) = tx.send(Ok(message.message)) {
|
||||
warn!("Message receiver dropped");
|
||||
found = true;
|
||||
|
||||
if let Err(message) = tx.send(Ok(message.message.clone())) {
|
||||
warn!("Message receiver dropped {:?}", message);
|
||||
continue;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let _ = self.tx.send(message);
|
||||
|
||||
/*if self.message_queue.is_empty() {
|
||||
warn!("Received unexpected message from server");
|
||||
if !found {
|
||||
let _ = self.tx_msg.send(message);
|
||||
}
|
||||
|
||||
match message.message {
|
||||
Response::DisplayMessage { message, id, value } => {
|
||||
if !message.is_empty() {
|
||||
println!("{message}");
|
||||
}
|
||||
|
||||
let config = self.config.lock().unwrap();
|
||||
let show_motd_after_login = config.general.show_motd_after_login;
|
||||
let show_inbox_count_after_login = config.general.show_inbox_count_after_login;
|
||||
let show_pm_inbox_count_after_login =
|
||||
config.general.show_pm_inbox_count_after_login;
|
||||
let show_balance_after_payment = config.general.show_balance_after_payment;
|
||||
drop(config);
|
||||
|
||||
match id.as_str() {
|
||||
"auth.success" => {
|
||||
self.id = value as i32;
|
||||
self.last_username = self.username.clone();
|
||||
self.last_password = self.password.clone();
|
||||
self.logged_in = true;
|
||||
|
||||
if show_motd_after_login {
|
||||
self.send_authenticated(AuthenticatedMessage::Motd);
|
||||
}
|
||||
if show_inbox_count_after_login {
|
||||
self.send_authenticated(AuthenticatedMessage::GetInbox {
|
||||
message_id: -1,
|
||||
})
|
||||
}
|
||||
if show_pm_inbox_count_after_login {
|
||||
self.send_authenticated(AuthenticatedMessage::GetPmInbox {
|
||||
message_id: -1,
|
||||
})
|
||||
}
|
||||
|
||||
println!("(Client Id: {})", self.id);
|
||||
}
|
||||
"auth.fail.credentials" => {
|
||||
self.backup_auth();
|
||||
}
|
||||
"register.success" => {
|
||||
self.send_authenticated(AuthenticatedMessage::Authenticate);
|
||||
}
|
||||
"register.fail.usernameTaken" => {
|
||||
self.backup_auth();
|
||||
}
|
||||
"logout.success" => {
|
||||
self.logged_in = false;
|
||||
}
|
||||
"logout.fail.credentials" => {
|
||||
self.auth_error();
|
||||
}
|
||||
"logout.fail.notloggedin" => {
|
||||
self.logged_in = false;
|
||||
}
|
||||
"balance.success" => {}
|
||||
"balance.fail.credentials" => {
|
||||
self.auth_error();
|
||||
}
|
||||
"pay.fail.negative_amount" => {
|
||||
panic!("Should not be able to send a negative amount")
|
||||
}
|
||||
"pay.fail.orig_user_unknown" => {
|
||||
self.auth_error();
|
||||
}
|
||||
"pay.fail.credentials" => {
|
||||
self.auth_error();
|
||||
}
|
||||
"pay.fail.unknown_dest" => {}
|
||||
"pay.fail.not_enough_money" => {
|
||||
if show_balance_after_payment {
|
||||
self.send_authenticated(AuthenticatedMessage::GetBalance);
|
||||
}
|
||||
}
|
||||
"pay.fail.unknown_error" => {}
|
||||
"pay.success" => {
|
||||
if show_balance_after_payment {
|
||||
self.send_authenticated(AuthenticatedMessage::GetBalance);
|
||||
}
|
||||
}
|
||||
"pay.received" => {
|
||||
if show_balance_after_payment {
|
||||
self.send_authenticated(AuthenticatedMessage::GetBalance);
|
||||
}
|
||||
}
|
||||
"message_count" => {
|
||||
self.inbox_message_count = value as u8;
|
||||
println!(
|
||||
"You have {} unread message{}",
|
||||
self.inbox_message_count,
|
||||
if self.inbox_message_count == 1 {
|
||||
""
|
||||
} else {
|
||||
"s"
|
||||
}
|
||||
)
|
||||
}
|
||||
"pm_message_count" => {
|
||||
self.pm_message_count = value as u8;
|
||||
println!(
|
||||
"You have {} unread private message{}",
|
||||
self.pm_message_count,
|
||||
if self.pm_message_count == 1 { "" } else { "s" }
|
||||
)
|
||||
}
|
||||
"pm_inbox.send.success" => {}
|
||||
"pm_inbox.dest.unkown" => {}
|
||||
"read_inbox.success" => {}
|
||||
"read_inbox.fail.credentials" => {
|
||||
self.auth_error();
|
||||
}
|
||||
"read_pm.success" => {}
|
||||
"read_pm.fail.credentials" => {
|
||||
self.auth_error();
|
||||
}
|
||||
_ => {
|
||||
warn!("Unknown message id: {}", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
Response::Inbox {
|
||||
message_id,
|
||||
message,
|
||||
} => {
|
||||
println!("{}. {}", message_id, message);
|
||||
}
|
||||
Response::PmInbox {
|
||||
message_id,
|
||||
message,
|
||||
} => {
|
||||
println!("{}. {}", message_id, message);
|
||||
}
|
||||
Response::Motd { motd } => {
|
||||
println!("--- {motd} ---");
|
||||
}
|
||||
}
|
||||
|
||||
if !self.message_queue.is_empty() {
|
||||
self.message_queue.pop_front().unwrap().1.await;
|
||||
if !self.message_queue.is_empty() {
|
||||
let queued = self.message_queue.pop_front().unwrap();
|
||||
self.send_authenticated_now(queued.0, queued.1);
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
debug!("ignoring message for other id")
|
||||
}
|
||||
@@ -495,11 +291,7 @@ impl ezsockets::ClientExt for Handler {
|
||||
|
||||
async fn on_call(&mut self, call: Self::Call) -> Result<(), Error> {
|
||||
match call {
|
||||
ClientCommand::SendAuthenticatedNew {
|
||||
message,
|
||||
accept,
|
||||
tx,
|
||||
} => {
|
||||
ClientCommand::SendAuthenticatedNew { message, accept, tx, } => {
|
||||
self.send_authenticated(message);
|
||||
self.receivers.push_back((accept, tx));
|
||||
}
|
||||
@@ -510,116 +302,50 @@ impl ezsockets::ClientExt for Handler {
|
||||
self.username = username;
|
||||
self.password = password;
|
||||
}
|
||||
/*ClientCommand::TryLastLogin => {
|
||||
if self.last_username.is_empty() || self.last_password.is_empty() {
|
||||
println!("You need to enter a username and password");
|
||||
} else {
|
||||
self.send_authenticated(AuthenticatedMessage::Authenticate);
|
||||
}
|
||||
}
|
||||
ClientCommand::CheckTimeout => {
|
||||
if !self.message_queue.is_empty() && self.send_time.elapsed().unwrap().as_secs() > 5
|
||||
{
|
||||
if self.retry_count >= 3 {
|
||||
self.message_queue.pop_front();
|
||||
self.retry_count = 0;
|
||||
println!("Request Timeout - All Retries failed")
|
||||
} else {
|
||||
self.retry_count += 1;
|
||||
println!("Request Timeout - Retrying {}/3", self.retry_count);
|
||||
}
|
||||
if !self.message_queue.is_empty() {
|
||||
let queued = self.message_queue.pop_front().unwrap();
|
||||
self.send_authenticated_now(queued.0, queued.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientCommand::SendWithCallback(message, callback) => {
|
||||
self.send_authenticated_callback(message, callback);
|
||||
}
|
||||
ClientCommand::PrintInbox => {
|
||||
for i in 0..self.inbox_message_count {
|
||||
self.send_authenticated(AuthenticatedMessage::GetInbox {
|
||||
message_id: (i + 1) as i8,
|
||||
})
|
||||
}
|
||||
}
|
||||
ClientCommand::PrintPmInbox => {
|
||||
for i in 0..self.pm_message_count {
|
||||
self.send_authenticated(AuthenticatedMessage::GetPmInbox {
|
||||
message_id: (i + 1) as i8,
|
||||
})
|
||||
}
|
||||
}
|
||||
ClientCommand::TryAccount(success, error) => {
|
||||
//let last_username = self.last_username.clone();
|
||||
//let last_password = self.last_password.clone();
|
||||
self.last_username = String::new();
|
||||
self.last_password = String::new();
|
||||
/*self.send_authenticated_callback(AuthenticatedMessage::Authenticate, Box::new(Box::pin(async move {
|
||||
if !self.logged_in {
|
||||
self.send_authenticated_callback(AuthenticatedMessage::Register, Box::new(Box::pin(async move {
|
||||
if !self.logged_in {
|
||||
error.await;
|
||||
} else {
|
||||
success.await;
|
||||
}
|
||||
})));
|
||||
} else {
|
||||
success.await;
|
||||
}
|
||||
})));
|
||||
*/
|
||||
}*/
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_connect(&mut self) -> Result<(), Error> {
|
||||
info!("Successfully connected to the Server");
|
||||
if !self.username.is_empty() && !self.password.is_empty() {
|
||||
self.send_authenticated(AuthenticatedMessage::Authenticate);
|
||||
}
|
||||
let _ = self.tx_act.send(ClientAction::Connected);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_connect_fail(&mut self, _error: WSError) -> Result<ClientCloseMode, Error> {
|
||||
info!("Disconnected, reconnecting...");
|
||||
info!("Connection failed, reconnecting...");
|
||||
Ok(ClientCloseMode::Reconnect)
|
||||
}
|
||||
|
||||
async fn on_close(&mut self, _frame: Option<CloseFrame>) -> Result<ClientCloseMode, Error> {
|
||||
self.clear_receivers(BankError::Disconnected);
|
||||
let _ = self.tx_act.send(ClientAction::Disconnected);
|
||||
info!("Disconnected, reconnecting...");
|
||||
Ok(ClientCloseMode::Reconnect)
|
||||
}
|
||||
|
||||
async fn on_disconnect(&mut self) -> Result<ClientCloseMode, Error> {
|
||||
self.clear_receivers(BankError::Disconnected);
|
||||
let _ = self.tx_act.send(ClientAction::Disconnected);
|
||||
info!("Disconnected, reconnecting...");
|
||||
Ok(ClientCloseMode::Reconnect)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ClientAction {
|
||||
Connected,
|
||||
Disconnected
|
||||
}
|
||||
|
||||
pub enum ClientCommand {
|
||||
SendAuthenticatedNew {
|
||||
message: AuthenticatedMessage,
|
||||
accept: fn(&ResponseMessage) -> bool,
|
||||
tx: tokio::sync::oneshot::Sender<Result<Response, BankError>>,
|
||||
tx: oneshot::Sender<Result<Response, BankError>>,
|
||||
},
|
||||
SendAuthenticated(AuthenticatedMessage),
|
||||
/*SendWithCallback(
|
||||
AuthenticatedMessage,
|
||||
Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
),
|
||||
PrintInbox,
|
||||
PrintPmInbox,*/
|
||||
ChangeCredentials {
|
||||
username: String,
|
||||
password: String,
|
||||
},
|
||||
/*TryLastLogin,
|
||||
CheckTimeout,
|
||||
TryAccount(
|
||||
Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
Box<dyn Future<Output = ()> + Send + Unpin>,
|
||||
),*/
|
||||
}
|
||||
Reference in new issue
Block a user