mirror of
https://github.com/shiroyashik/sculptor.git
synced 2025-12-06 13:01:12 +03:00
added sending authSystem to user request
This commit is contained in:
parent
59440154c1
commit
2b5258d551
6 changed files with 81 additions and 47 deletions
|
|
@ -9,5 +9,5 @@ And also a distinctive feature is the possibility of player identification throu
|
||||||
### TODO:
|
### TODO:
|
||||||
- [ ] Realization of storing profiles in the database
|
- [ ] Realization of storing profiles in the database
|
||||||
- [ ] Frontend for moderation
|
- [ ] Frontend for moderation
|
||||||
- [ ] Check the possibility of replacing assets to display the authorization system used by the player
|
- [ ] Autonomous working without reverse proxy server
|
||||||
- [ ] and many other...
|
- [ ] and many other...
|
||||||
27
src/auth.rs
27
src/auth.rs
|
|
@ -15,7 +15,7 @@ pub fn router() -> Router<AppState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Веб функции
|
// Web
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Id {username: String}
|
struct Id {username: String}
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ async fn id( // First stage of authentication
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let server_id = bytes_into_string(&digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &rand()).as_ref()[0 .. 20]);
|
let server_id = bytes_into_string(&digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &rand()).as_ref()[0 .. 20]);
|
||||||
let state = state.pending.lock().await;
|
let state = state.pending;
|
||||||
state.insert(server_id.clone(), query.username);
|
state.insert(server_id.clone(), query.username);
|
||||||
server_id
|
server_id
|
||||||
}
|
}
|
||||||
|
|
@ -39,12 +39,12 @@ async fn verify( // Second stage of authentication
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let server_id = query.id.clone();
|
let server_id = query.id.clone();
|
||||||
let username = state.pending.lock().await.remove(&server_id).unwrap().1;
|
let username = state.pending.remove(&server_id).unwrap().1;
|
||||||
if let Some((uuid, auth_system)) = has_joined(&server_id, &username).await.unwrap() {
|
if let Some((uuid, auth_system)) = has_joined(&server_id, &username).await.unwrap() {
|
||||||
info!("[Authorization] {username} logged in using {auth_system:?}");
|
info!("[Authorization] {username} logged in using {auth_system:?}");
|
||||||
let authenticated = state.authenticated.lock().await;
|
let authenticated = state.authenticated;
|
||||||
// let link = state.authenticated_link.lock().await; // // Реализация поиска пользователя в HashMap по UUID
|
// let link = state.authenticated_link.lock().await; // // Реализация поиска пользователя в HashMap по UUID
|
||||||
authenticated.insert(server_id.clone(), crate::Userinfo { username, uuid, auth_system });
|
authenticated.insert(uuid, server_id.clone(), crate::Userinfo { username, uuid, auth_system });
|
||||||
// link.insert(uuid, crate::AuthenticatedLink(server_id.clone())); // Реализация поиска пользователя в HashMap по UUID
|
// link.insert(uuid, crate::AuthenticatedLink(server_id.clone())); // Реализация поиска пользователя в HashMap по UUID
|
||||||
return format!("{server_id}")
|
return format!("{server_id}")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -58,7 +58,7 @@ pub async fn status(
|
||||||
) -> Response {
|
) -> Response {
|
||||||
match token {
|
match token {
|
||||||
Some(token) => {
|
Some(token) => {
|
||||||
if state.authenticated.lock().await.contains_key(&token) {
|
if state.authenticated.contains_token(&token) {
|
||||||
// format!("ok") // 200
|
// format!("ok") // 200
|
||||||
(StatusCode::OK, format!("ok")).into_response()
|
(StatusCode::OK, format!("ok")).into_response()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -72,10 +72,10 @@ pub async fn status(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Конец веб функций
|
// Web End
|
||||||
|
|
||||||
|
|
||||||
// Это экстрактор достающий из Заголовка зовущегося токен, соответственно ТОКЕН.
|
// It's an extractor that pulls a token from the Header.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Token(pub Option<String>);
|
pub struct Token(pub Option<String>);
|
||||||
|
|
||||||
|
|
@ -98,7 +98,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Конец экстрактора
|
// End Extractor
|
||||||
|
|
||||||
// Work with external APIs
|
// Work with external APIs
|
||||||
|
|
||||||
|
|
@ -108,6 +108,15 @@ pub enum AuthSystem {
|
||||||
Mojang,
|
Mojang,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToString for AuthSystem {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
AuthSystem::ElyBy => String::from("elyby"),
|
||||||
|
AuthSystem::Mojang => String::from("mojang"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn has_joined(server_id: &str, username: &str) -> anyhow::Result<Option<(Uuid, AuthSystem)>> {
|
pub async fn has_joined(server_id: &str, username: &str) -> anyhow::Result<Option<(Uuid, AuthSystem)>> {
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
|
|
||||||
41
src/main.rs
41
src/main.rs
|
|
@ -41,14 +41,43 @@ pub struct Userinfo {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Authenticated {
|
||||||
|
user_data: DashMap<String, Userinfo>,
|
||||||
|
uuid: DashMap<Uuid, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Authenticated {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { user_data: DashMap::new(), uuid: DashMap::new() }
|
||||||
|
}
|
||||||
|
pub fn insert(&self, uuid: Uuid, token: String, userinfo: Userinfo) -> Option<Userinfo> {
|
||||||
|
self.uuid.insert(uuid, token.clone());
|
||||||
|
self.user_data.insert(token, userinfo)
|
||||||
|
}
|
||||||
|
pub fn get(&self, token: &String) -> Option<dashmap::mapref::one::Ref<'_, std::string::String, Userinfo>> {
|
||||||
|
self.user_data.get(token)
|
||||||
|
}
|
||||||
|
pub fn get_by_uuid(&self, uuid: &Uuid) -> Option<dashmap::mapref::one::Ref<'_, std::string::String, Userinfo>> {
|
||||||
|
if let Some(token) = self.uuid.get(uuid) {
|
||||||
|
self.user_data.get(&token.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn contains_token(&self, token: &String) -> bool {
|
||||||
|
self.user_data.contains_key(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
// Users with incomplete authentication
|
// Users with incomplete authentication
|
||||||
pending: Arc<Mutex<DashMap<String, String>>>, // <SHA1 serverId, USERNAME>
|
pending: Arc<DashMap<String, String>>, // <SHA1 serverId, USERNAME>
|
||||||
// Authenticated users
|
// Authenticated users
|
||||||
authenticated: Arc<Mutex<DashMap<String, Userinfo>>>, // <SHA1 serverId, Userinfo> NOTE: In the future, try it in a separate LockRw branch
|
authenticated: Arc<Authenticated>, // <SHA1 serverId, Userinfo> NOTE: In the future, try it in a separate LockRw branch
|
||||||
// Ping broadcasts for WebSocket connections
|
// Ping broadcasts for WebSocket connections
|
||||||
broadcasts: Arc<Mutex<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>>,
|
broadcasts: Arc<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>,
|
||||||
// Advanced configured users
|
// Advanced configured users
|
||||||
advanced_users: Arc<Mutex<toml::Table>>,
|
advanced_users: Arc<Mutex<toml::Table>>,
|
||||||
}
|
}
|
||||||
|
|
@ -83,9 +112,9 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
// State
|
// State
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
pending: Arc::new(Mutex::new(DashMap::new())),
|
pending: Arc::new(DashMap::new()),
|
||||||
authenticated: Arc::new(Mutex::new(DashMap::new())),
|
authenticated: Arc::new(Authenticated::new()),
|
||||||
broadcasts: Arc::new(Mutex::new(DashMap::new())),
|
broadcasts: Arc::new(DashMap::new()),
|
||||||
advanced_users: Arc::new(Mutex::new(config.advanced_users)),
|
advanced_users: Arc::new(Mutex::new(config.advanced_users)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,15 @@ pub async fn user_info(
|
||||||
) -> Json<Value> {
|
) -> Json<Value> {
|
||||||
log::info!("Receiving profile information for {}",uuid);
|
log::info!("Receiving profile information for {}",uuid);
|
||||||
|
|
||||||
let formatted_uuid = format_uuid(uuid);
|
let formatted_uuid = format_uuid(&uuid);
|
||||||
|
|
||||||
let avatar_file = format!("avatars/{}.moon", formatted_uuid);
|
let avatar_file = format!("avatars/{}.moon", formatted_uuid);
|
||||||
|
|
||||||
|
let auth_system = match state.authenticated.get_by_uuid(&uuid) {
|
||||||
|
Some(d) => d.auth_system.to_string(),
|
||||||
|
None => return Json(json!("err")),
|
||||||
|
};
|
||||||
|
|
||||||
let mut user_info_response = json!({
|
let mut user_info_response = json!({
|
||||||
"uuid": &formatted_uuid,
|
"uuid": &formatted_uuid,
|
||||||
"rank": "default",
|
"rank": "default",
|
||||||
|
|
@ -28,7 +33,8 @@ pub async fn user_info(
|
||||||
"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]
|
||||||
},
|
},
|
||||||
"version": "0.1.4+1.20.1",
|
"version": "0.1.4+1.20.1",
|
||||||
"banned": false
|
"banned": false,
|
||||||
|
"authSystem": auth_system // add Trust
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(settings) = state.advanced_users.lock().await.get(&formatted_uuid) {
|
if let Some(settings) = state.advanced_users.lock().await.get(&formatted_uuid) {
|
||||||
|
|
@ -64,7 +70,7 @@ pub async fn user_info(
|
||||||
pub async fn download_avatar(
|
pub async fn download_avatar(
|
||||||
Path(uuid): Path<Uuid>,
|
Path(uuid): Path<Uuid>,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let uuid = format_uuid(uuid);
|
let uuid = format_uuid(&uuid);
|
||||||
log::info!("Requesting an avatar: {}", uuid);
|
log::info!("Requesting an avatar: {}", uuid);
|
||||||
let mut file = if let Ok(file) = fs::File::open(format!("avatars/{}.moon", uuid)).await {
|
let mut file = if let Ok(file) = fs::File::open(format!("avatars/{}.moon", uuid)).await {
|
||||||
file
|
file
|
||||||
|
|
@ -94,9 +100,8 @@ pub async fn upload_avatar(
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => http_error_ret!(UNAUTHORIZED, "Authentication error!"),
|
None => http_error_ret!(UNAUTHORIZED, "Authentication error!"),
|
||||||
};
|
};
|
||||||
let userinfos = state.authenticated.lock().await;
|
|
||||||
|
|
||||||
if let Some(user_info) = userinfos.get(token.as_str()) {
|
if let Some(user_info) = state.authenticated.get(&token) {
|
||||||
log::info!("{} ({}) trying to upload an avatar",user_info.uuid,user_info.username);
|
log::info!("{} ({}) trying to upload an avatar",user_info.uuid,user_info.username);
|
||||||
let avatar_file = format!("avatars/{}.moon",user_info.uuid);
|
let avatar_file = format!("avatars/{}.moon",user_info.uuid);
|
||||||
let mut file = BufWriter::new(fs::File::create(&avatar_file).await?);
|
let mut file = BufWriter::new(fs::File::create(&avatar_file).await?);
|
||||||
|
|
@ -110,8 +115,8 @@ pub async fn equip_avatar(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
) -> String {
|
) -> String {
|
||||||
debug!("[API] S2C : Equip");
|
debug!("[API] S2C : Equip");
|
||||||
let uuid = state.authenticated.lock().await.get(&token.unwrap()).unwrap().uuid;
|
let uuid = state.authenticated.get(&token.unwrap()).unwrap().uuid;
|
||||||
if state.broadcasts.lock().await.get(&uuid).unwrap().send(S2CMessage::Event(uuid).to_vec()).is_err() {
|
if state.broadcasts.get(&uuid).unwrap().send(S2CMessage::Event(uuid).to_vec()).is_err() {
|
||||||
warn!("[WebSocket] Failed to send Event! Maybe there is no one to send") // FIXME: Засунуть в Handler
|
warn!("[WebSocket] Failed to send Event! Maybe there is no one to send") // FIXME: Засунуть в Handler
|
||||||
};
|
};
|
||||||
format!("ok")
|
format!("ok")
|
||||||
|
|
@ -125,8 +130,7 @@ pub async fn delete_avatar(
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => http_error_ret!(UNAUTHORIZED, "Authentication error!"),
|
None => http_error_ret!(UNAUTHORIZED, "Authentication error!"),
|
||||||
};
|
};
|
||||||
let userinfos = state.authenticated.lock().await;
|
if let Some(user_info) = state.authenticated.get(&token) {
|
||||||
if let Some(user_info) = userinfos.get(token.as_str()) {
|
|
||||||
log::info!("{} ({}) is trying to delete the avatar",user_info.uuid,user_info.username);
|
log::info!("{} ({}) is trying to delete the avatar",user_info.uuid,user_info.username);
|
||||||
let avatar_file = format!("avatars/{}.moon",user_info.uuid);
|
let avatar_file = format!("avatars/{}.moon",user_info.uuid);
|
||||||
fs::remove_file(avatar_file).await?;
|
fs::remove_file(avatar_file).await?;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ pub fn get_correct_array(value: &toml::Value) -> Vec<u8> {
|
||||||
value.as_array().unwrap().iter().map(move |x| x.as_integer().unwrap() as u8).collect()
|
value.as_array().unwrap().iter().map(move |x| x.as_integer().unwrap() as u8).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_uuid(uuid: Uuid) -> String {
|
pub fn format_uuid(uuid: &Uuid) -> String {
|
||||||
// let uuid = Uuid::parse_str(&uuid)?; TODO: Вероятно format_uuid стоит убрать
|
// let uuid = Uuid::parse_str(&uuid)?; TODO: Вероятно format_uuid стоит убрать
|
||||||
// .map_err(|_| tide::Error::from_str(StatusCode::InternalServerError, "Failed to parse UUID"))?;
|
// .map_err(|_| tide::Error::from_str(StatusCode::InternalServerError, "Failed to parse UUID"))?;
|
||||||
uuid.as_hyphenated().to_string()
|
uuid.as_hyphenated().to_string()
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
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 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
} else {
|
} else {
|
||||||
warn!("[WebSocket{}] Receive error! Connection terminated!", owner.name());
|
warn!("[WebSocket{}] Receive error! Connection terminated!", owner.name());
|
||||||
if let Some(u) = owner.0 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -70,7 +70,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
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 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|
@ -82,20 +82,18 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
C2SMessage::Token(token) => { // FIXME: Написать переменную спомощью которой бужет проверяться авторизовался ли пользователь или нет
|
C2SMessage::Token(token) => { // FIXME: Написать переменную спомощью которой бужет проверяться авторизовался ли пользователь или нет
|
||||||
debug!("[WebSocket{}] C2S : Token", owner.name());
|
debug!("[WebSocket{}] C2S : Token", owner.name());
|
||||||
let token = String::from_utf8(token.to_vec()).unwrap();
|
let token = String::from_utf8(token.to_vec()).unwrap();
|
||||||
let authenticated = state.authenticated.lock().await;
|
match state.authenticated.get(&token) { // Принцип прост: если токена в authenticated нет, значит это trash
|
||||||
match authenticated.get(&token) { // Принцип прост: если токена в authenticated нет, значит это trash
|
|
||||||
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.0 = Some(WSUser { username: t.username.clone(), token, uuid: t.uuid });
|
||||||
msg = Message::Binary(S2CMessage::Auth.to_vec());
|
msg = Message::Binary(S2CMessage::Auth.to_vec());
|
||||||
let bcs = state.broadcasts.lock().await;
|
match state.broadcasts.get(&t.uuid) {
|
||||||
match bcs.get(&t.uuid) {
|
|
||||||
Some(tx) => {
|
Some(tx) => {
|
||||||
bctx = Some(tx.to_owned());
|
bctx = Some(tx.to_owned());
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let (tx, _rx) = broadcast::channel(64);
|
let (tx, _rx) = broadcast::channel(64);
|
||||||
bcs.insert(t.uuid, tx.clone());
|
state.broadcasts.insert(t.uuid, tx.clone());
|
||||||
bctx = Some(tx.to_owned());
|
bctx = Some(tx.to_owned());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -104,7 +102,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
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 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return; // TODO: Прописать код отключения
|
return; // TODO: Прописать код отключения
|
||||||
},
|
},
|
||||||
|
|
@ -115,7 +113,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
let data = into_s2c_ping(msg_vec, owner.0.clone().unwrap().uuid);
|
let data = into_s2c_ping(msg_vec, owner.0.clone().unwrap().uuid);
|
||||||
match bctx.clone().unwrap().send(data) {
|
match bctx.clone().unwrap().send(data) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(_) => warn!("[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;
|
||||||
},
|
},
|
||||||
|
|
@ -126,13 +124,12 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let broadcast = state.broadcasts.lock().await;
|
let rx = match state.broadcasts.get(&uuid) {
|
||||||
let rx = match broadcast.get(&uuid) {
|
|
||||||
Some(rx) => rx.to_owned().subscribe(),
|
Some(rx) => rx.to_owned().subscribe(),
|
||||||
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);
|
||||||
broadcast.insert(uuid, tx);
|
state.broadcasts.insert(uuid, tx);
|
||||||
rx
|
rx
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -159,7 +156,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
|
||||||
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 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +169,7 @@ 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 {
|
if let Some(u) = owner.0 {
|
||||||
remove_broadcast(state.broadcasts.clone(), u.uuid).await;
|
state.broadcasts.remove(&u.uuid);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +200,3 @@ fn into_s2c_ping(buf: Vec<u8>, uuid: Uuid) -> Vec<u8> {
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
once(1).chain(uuid.into_bytes().iter().copied()).chain(buf.as_slice()[1..].iter().copied()).collect()
|
once(1).chain(uuid.into_bytes().iter().copied()).chain(buf.as_slice()[1..].iter().copied()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove_broadcast(broadcasts: Arc<tokio::sync::Mutex<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>>, uuid: Uuid) {
|
|
||||||
let map = broadcasts.lock().await;
|
|
||||||
map.remove(&uuid);
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue