mirror of
https://github.com/shiroyashik/sculptor.git
synced 2025-12-06 13:01:12 +03:00
Code refactored + new API
Added ability to send messages to a websocket session via HTTP API
This commit is contained in:
parent
ca6990c5b1
commit
81ab2ba724
11 changed files with 172 additions and 74 deletions
|
|
@ -1,7 +1,11 @@
|
||||||
listen = "0.0.0.0:6665" # Don't touch this if you running under Docker container
|
## Don't touch this if you running under Docker container
|
||||||
|
listen = "0.0.0.0:6665"
|
||||||
|
|
||||||
# Message of The Day
|
## Don't touch if you don't know what you're doing
|
||||||
# It will be displayed to every player in the Figura menu who is connected to your server
|
# token = "<random symbols>"
|
||||||
|
|
||||||
|
## Message of The Day
|
||||||
|
## It will be displayed to every player in the Figura menu who is connected to your server
|
||||||
motd = """
|
motd = """
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|
@ -41,7 +45,7 @@ motd = """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[limitations]
|
[limitations]
|
||||||
maxAvatarSize = 100000
|
maxAvatarSize = 100000 # 100 KB
|
||||||
maxAvatars = 10
|
maxAvatars = 10
|
||||||
|
|
||||||
[advancedUsers.66004548-4de5-49de-bade-9c3933d8eb97]
|
[advancedUsers.66004548-4de5-49de-bade-9c3933d8eb97]
|
||||||
|
|
@ -50,11 +54,11 @@ authSystem = "elyby"
|
||||||
special = [0,0,0,1,0,0] # 6
|
special = [0,0,0,1,0,0] # 6
|
||||||
pride = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # 25
|
pride = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # 25
|
||||||
|
|
||||||
# With advancedUsers you can set additional parameters
|
## With advancedUsers you can set additional parameters
|
||||||
# [advancedUsers.your uuid here]
|
# [advancedUsers.your uuid here]
|
||||||
# username = "Your_username_here"
|
# username = "Your_username_here"
|
||||||
# authSystem = "mojang" # can be: mojang, elyby, internal (cant be authenticated)
|
# authSystem = "mojang" # can be: mojang, elyby, internal (cant be authenticated)
|
||||||
# special = [0,1,0,0,0,0] # and set badges what you want! :D
|
# special = [0,1,0,0,0,0] # and set badges what you want! :D
|
||||||
# pride = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
# pride = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||||
|
|
||||||
# you can create an unlimited number of "advancedUsers" for any users.
|
## you can create an unlimited number of "advancedUsers" for any users.
|
||||||
|
|
@ -7,11 +7,27 @@ use toml::Table;
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub listen: String,
|
pub listen: String,
|
||||||
|
pub token: Option<String>,
|
||||||
pub motd: String,
|
pub motd: String,
|
||||||
pub limitations: Limitations,
|
pub limitations: Limitations,
|
||||||
pub advanced_users: Table,
|
pub advanced_users: Table,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn verify_token(&self, suspicious: &str) -> bool {
|
||||||
|
match &self.token {
|
||||||
|
Some(t) => {
|
||||||
|
if t == suspicious {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Deserialize, Clone, Debug, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Limitations {
|
pub struct Limitations {
|
||||||
|
|
|
||||||
10
src/main.rs
10
src/main.rs
|
|
@ -4,7 +4,7 @@ use axum::{
|
||||||
};
|
};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{broadcast, Mutex};
|
use tokio::sync::{broadcast, mpsc, Mutex};
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
@ -35,12 +35,10 @@ use config::Config;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
/// Users with incomplete authentication
|
|
||||||
//pending: Arc<DashMap<String, String>>, // <SHA1 serverId, USERNAME>
|
|
||||||
/// Authenticated users
|
|
||||||
//authenticated: Arc<Authenticated>, // <SHA1 serverId, Userinfo> NOTE: In the future, try it in a separate LockRw branch
|
|
||||||
/// User manager
|
/// User manager
|
||||||
user_manager: Arc<UManager>,
|
user_manager: Arc<UManager>,
|
||||||
|
/// Send into WebSocket
|
||||||
|
session: Arc<DashMap<Uuid, mpsc::Sender<Vec<u8>>>>,
|
||||||
/// Ping broadcasts for WebSocket connections
|
/// Ping broadcasts for WebSocket connections
|
||||||
broadcasts: Arc<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>,
|
broadcasts: Arc<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>,
|
||||||
/// Current configuration
|
/// Current configuration
|
||||||
|
|
@ -73,6 +71,7 @@ async fn main() -> Result<()> {
|
||||||
// State
|
// State
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
user_manager: Arc::new(UManager::new()),
|
user_manager: Arc::new(UManager::new()),
|
||||||
|
session: Arc::new(DashMap::new()),
|
||||||
broadcasts: Arc::new(DashMap::new()),
|
broadcasts: Arc::new(DashMap::new()),
|
||||||
config: config,
|
config: config,
|
||||||
};
|
};
|
||||||
|
|
@ -97,6 +96,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let api = Router::new()
|
let api = Router::new()
|
||||||
.nest("//auth", api_auth::router())
|
.nest("//auth", api_auth::router())
|
||||||
|
.nest("/v1", ws::http_router())
|
||||||
.route("/limits", get(api_info::limits))
|
.route("/limits", get(api_info::limits))
|
||||||
.route("/version", get(api_info::version))
|
.route("/version", get(api_info::version))
|
||||||
.route("/motd", get(api_info::motd))
|
.route("/motd", get(api_info::motd))
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ pub async fn equip_avatar(Token(token): Token, State(state): State<AppState>) ->
|
||||||
.send(S2CMessage::Event(uuid).to_vec())
|
.send(S2CMessage::Event(uuid).to_vec())
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
warn!("[WebSocket] Failed to send Event! Maybe there is no one to send")
|
debug!("[WebSocket] Failed to send Event! Maybe there is no one to send")
|
||||||
// TODO: Put into Handler
|
// TODO: Put into Handler
|
||||||
};
|
};
|
||||||
"ok".to_string()
|
"ok".to_string()
|
||||||
|
|
|
||||||
83
src/ws/http.rs
Normal file
83
src/ws/http.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
use axum::{
|
||||||
|
extract::{Query, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
routing::{get, post},
|
||||||
|
Router
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tracing::debug;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{auth::Token, AppState};
|
||||||
|
|
||||||
|
pub fn router() -> Router<AppState> {
|
||||||
|
Router::new()
|
||||||
|
.route("/verify", get(verify))
|
||||||
|
// .route("/ping", post(ping))
|
||||||
|
// .route("/event", post(event))
|
||||||
|
// .route("/toast", post(toast))
|
||||||
|
// .route("/chat", post(chat))
|
||||||
|
// .route("/notice", post(notice))
|
||||||
|
.route("/raw", post(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct UserUuid {
|
||||||
|
uuid: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn verify(
|
||||||
|
Token(token): Token,
|
||||||
|
State(state): State<AppState>,
|
||||||
|
) -> Response {
|
||||||
|
match token {
|
||||||
|
Some(t) => {
|
||||||
|
if !state.config.lock().await.verify_token(&t) {
|
||||||
|
return (StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => return (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response(),
|
||||||
|
}
|
||||||
|
(StatusCode::OK, "ok".to_string()).into_response()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn raw(
|
||||||
|
Token(token): Token,
|
||||||
|
Query(query): Query<UserUuid>,
|
||||||
|
State(state): State<AppState>,
|
||||||
|
body: String,
|
||||||
|
) -> Response {
|
||||||
|
debug!(body = body);
|
||||||
|
match token {
|
||||||
|
Some(t) => {
|
||||||
|
if !state.config.lock().await.verify_token(&t) {
|
||||||
|
return (StatusCode::UNAUTHORIZED, "wrong token".to_string()).into_response()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => return (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response(),
|
||||||
|
}
|
||||||
|
let payload = match hex::decode(body) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => return (StatusCode::NOT_ACCEPTABLE, "not raw data".to_string()).into_response(),
|
||||||
|
};
|
||||||
|
debug!("{:?}", payload);
|
||||||
|
|
||||||
|
match query.uuid {
|
||||||
|
Some(uuid) => {
|
||||||
|
// for only one
|
||||||
|
let tx = match state.session.get(&uuid) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => return (StatusCode::NOT_FOUND, "unknown uuid".to_string()).into_response(),
|
||||||
|
};
|
||||||
|
match tx.value().send(payload).await {
|
||||||
|
Ok(_) => return (StatusCode::OK, "ok".to_string()).into_response(),
|
||||||
|
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "cant send".to_string()).into_response(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
// for all
|
||||||
|
return (StatusCode::NOT_FOUND, "uuid doesnt defined".to_string()).into_response();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
mod c2s;
|
mod types;
|
||||||
mod errors;
|
mod websocket;
|
||||||
mod handler;
|
mod http;
|
||||||
mod s2c;
|
|
||||||
|
|
||||||
pub use c2s::C2SMessage;
|
pub use types::C2SMessage;
|
||||||
pub use errors::MessageLoadError;
|
pub use types::S2CMessage;
|
||||||
pub use handler::handler;
|
pub use websocket::handler;
|
||||||
pub use s2c::S2CMessage;
|
pub use http::router as http_router;
|
||||||
7
src/ws/types/mod.rs
Normal file
7
src/ws/types/mod.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
mod c2s;
|
||||||
|
mod errors;
|
||||||
|
mod s2c;
|
||||||
|
|
||||||
|
pub use c2s::C2SMessage;
|
||||||
|
pub use errors::MessageLoadError;
|
||||||
|
pub use s2c::S2CMessage;
|
||||||
|
|
@ -24,9 +24,6 @@ pub async fn handler(ws: WebSocketUpgrade, State(state): State<AppState>) -> Res
|
||||||
ws.on_upgrade(|socket| handle_socket(socket, state))
|
ws.on_upgrade(|socket| handle_socket(socket, state))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct WSOwner(Option<WSUser>);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct WSUser {
|
struct WSUser {
|
||||||
username: String,
|
username: String,
|
||||||
|
|
@ -34,9 +31,13 @@ struct WSUser {
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WSOwner {
|
trait ExtWSUser {
|
||||||
|
fn name(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtWSUser for Option<WSUser> {
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
if let Some(user) = &self.0 {
|
if let Some(user) = self {
|
||||||
format!(" ({})", user.username)
|
format!(" ({})", user.username)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
|
|
@ -46,31 +47,24 @@ impl WSOwner {
|
||||||
|
|
||||||
async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
debug!("[WebSocket] New unknown connection!");
|
debug!("[WebSocket] New unknown connection!");
|
||||||
let mut owner = WSOwner(None);
|
let mut owner: Option<WSUser> = None; // Information about user
|
||||||
let cutoff: DashMap<Uuid, Arc<Notify>> = DashMap::new();
|
let cutoff: DashMap<Uuid, Arc<Notify>> = DashMap::new(); // Отключение подписки
|
||||||
let (mtx, mut mrx) = mpsc::channel(64);
|
let (mtx, mut mrx) = mpsc::channel(64); // multiple tx and single receive
|
||||||
let mut bctx: Option<broadcast::Sender<Vec<u8>>> = None;
|
let mut bctx: Option<broadcast::Sender<Vec<u8>>> = None; // broadcast tx send
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
// Main loop what receving messages from WebSocket
|
||||||
Some(msg) = socket.recv() => {
|
Some(msg) = socket.recv() => {
|
||||||
trace!("[WebSocket{}] Raw: {msg:?}", owner.name());
|
trace!("[WebSocket{}] Raw: {msg:?}", owner.name());
|
||||||
let mut msg = if let Ok(msg) = msg {
|
let mut msg = if let Ok(msg) = msg {
|
||||||
if let Message::Close(_) = msg {
|
if let Message::Close(_) = msg {
|
||||||
info!("[WebSocket{}] Connection successfully closed!", owner.name());
|
info!("[WebSocket{}] Connection successfully closed!", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
|
||||||
state.user_manager.remove(&u.uuid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
msg
|
msg
|
||||||
} else {
|
} else {
|
||||||
debug!("[WebSocket{}] Receive error! Connection terminated!", owner.name());
|
debug!("[WebSocket{}] Receive error! Connection terminated!", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
|
||||||
state.user_manager.remove(&u.uuid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
// Next is the code for processing msg
|
// Next is the code for processing msg
|
||||||
let msg_vec = msg.clone().into_data();
|
let msg_vec = msg.clone().into_data();
|
||||||
|
|
@ -80,11 +74,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("[WebSocket{}] This message is not from Figura! {e:?}", owner.name());
|
error!("[WebSocket{}] This message is not from Figura! {e:?}", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
|
||||||
state.user_manager.remove(&u.uuid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -97,7 +87,8 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
match state.user_manager.get(&token) { // The principle is simple: if there is no token in authenticated, then it's "dirty hacker" :D
|
match state.user_manager.get(&token) { // The principle is simple: if there is no token in authenticated, then it's "dirty hacker" :D
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
//username = t.username.clone();
|
//username = t.username.clone();
|
||||||
owner.0 = Some(WSUser { username: t.username.clone(), token, uuid: t.uuid });
|
owner = Some(WSUser { username: t.username.clone(), token, uuid: t.uuid });
|
||||||
|
state.session.insert(t.uuid, mtx.clone());
|
||||||
msg = Message::Binary(S2CMessage::Auth.to_vec());
|
msg = Message::Binary(S2CMessage::Auth.to_vec());
|
||||||
match state.broadcasts.get(&t.uuid) {
|
match state.broadcasts.get(&t.uuid) {
|
||||||
Some(tx) => {
|
Some(tx) => {
|
||||||
|
|
@ -113,53 +104,52 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
None => {
|
None => {
|
||||||
warn!("[WebSocket] Authenticaton error! Connection terminated!");
|
warn!("[WebSocket] Authenticaton error! Connection terminated!");
|
||||||
debug!("[WebSocket] Tried to log in with {token}"); // Tried to log in with token: {token}
|
debug!("[WebSocket] Tried to log in with {token}"); // Tried to log in with token: {token}
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
|
||||||
state.user_manager.remove(&u.uuid);
|
|
||||||
}
|
|
||||||
return; // TODO: Define the trip code
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
C2SMessage::Ping(_, _, _) => {
|
C2SMessage::Ping(_, _, _) => {
|
||||||
debug!("[WebSocket{}] C2S : Ping", owner.name());
|
debug!("[WebSocket{}] C2S : Ping", owner.name());
|
||||||
let data = into_s2c_ping(msg_vec, owner.0.clone().unwrap().uuid);
|
let data = into_s2c_ping(msg_vec, owner.clone().unwrap().uuid);
|
||||||
match bctx.clone().unwrap().send(data) {
|
match bctx.clone().unwrap().send(data) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(_) => debug!("[WebSocket{}] Failed to send Ping! Maybe there's no one to send", owner.name()),
|
Err(_) => debug!("[WebSocket{}] Failed to send Ping! Maybe there's no one to send", owner.name()),
|
||||||
};
|
};
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
// Subscribing
|
||||||
C2SMessage::Sub(uuid) => { // TODO: Eliminate the possibility of using SUB without authentication
|
C2SMessage::Sub(uuid) => { // TODO: Eliminate the possibility of using SUB without authentication
|
||||||
debug!("[WebSocket{}] C2S : Sub", owner.name());
|
debug!("[WebSocket{}] C2S : Sub", owner.name());
|
||||||
// Rejecting Sub to itself
|
// Ignoring self Sub
|
||||||
if uuid == owner.0.clone().unwrap().uuid {
|
if uuid == owner.clone().unwrap().uuid {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let rx = match state.broadcasts.get(&uuid) {
|
let rx = match state.broadcasts.get(&uuid) { // Get sender
|
||||||
Some(rx) => rx.to_owned().subscribe(),
|
Some(rx) => rx.to_owned().subscribe(), // Subscribe on sender to get receiver
|
||||||
None => {
|
None => {
|
||||||
warn!("[WebSocket{}] Attention! The required UUID for subscription was not found!", owner.name());
|
warn!("[WebSocket{}] Attention! The required UUID for subscription was not found!", owner.name());
|
||||||
let (tx, rx) = broadcast::channel(64);
|
let (tx, rx) = broadcast::channel(64); // Pre creating broadcast for future
|
||||||
state.broadcasts.insert(uuid, tx);
|
state.broadcasts.insert(uuid, tx); // Inserting into dashmap
|
||||||
rx
|
rx
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let shutdown = Arc::new(Notify::new());
|
let shutdown = Arc::new(Notify::new()); // Creating new shutdown <Notify>
|
||||||
tokio::spawn(subscribe(mtx.clone(), rx, shutdown.clone()));
|
tokio::spawn(subscribe(mtx.clone(), rx, shutdown.clone())); // <For send pings to >
|
||||||
cutoff.insert(uuid, shutdown);
|
cutoff.insert(uuid, shutdown);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
// Unsubscribing
|
||||||
C2SMessage::Unsub(uuid) => {
|
C2SMessage::Unsub(uuid) => {
|
||||||
debug!("[WebSocket{}] C2S : Unsub", owner.name());
|
debug!("[WebSocket{}] C2S : Unsub", owner.name());
|
||||||
// Rejecting UnSub to itself
|
// Ignoring self Unsub
|
||||||
if uuid == owner.0.clone().unwrap().uuid {
|
if uuid == owner.clone().unwrap().uuid {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let shutdown = cutoff.remove(&uuid).unwrap().1;
|
|
||||||
shutdown.notify_one();
|
let shutdown = cutoff.remove(&uuid).unwrap().1; // Getting <Notify> from list // FIXME: UNWRAP PANIC! NONE VALUE
|
||||||
|
shutdown.notify_one(); // Shutdown <subscribe> function
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -168,11 +158,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
debug!("[WebSocket{}] Answering: {msg:?}", owner.name());
|
debug!("[WebSocket{}] Answering: {msg:?}", owner.name());
|
||||||
if socket.send(msg).await.is_err() {
|
if socket.send(msg).await.is_err() {
|
||||||
warn!("[WebSocket{}] Send error! Connection terminated!", owner.name());
|
warn!("[WebSocket{}] Send error! Connection terminated!", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
|
||||||
state.user_manager.remove(&u.uuid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg = mrx.recv() => {
|
msg = mrx.recv() => {
|
||||||
|
|
@ -182,16 +168,19 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("[WebSocketSubscriber{}] Send error! Connection terminated!", owner.name());
|
warn!("[WebSocketSubscriber{}] Send error! Connection terminated!", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
break;
|
||||||
state.broadcasts.remove(&u.uuid);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Closing connection
|
||||||
|
if let Some(u) = owner {
|
||||||
|
state.session.remove(&u.uuid);
|
||||||
|
// state.broadcasts.remove(&u.uuid); // NOTE: Create broadcasts manager ??
|
||||||
state.user_manager.remove(&u.uuid);
|
state.user_manager.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn subscribe(
|
async fn subscribe(
|
||||||
Loading…
Add table
Add a link
Reference in a new issue