this package can manage room for axum websoket.
it is flexible and you can do what you want with rooms.
for a single room: it creates a channel for room and sends data through channel.
```rs
struct State { rooms: RoomsManager, }
async fn main(){ let rooms = axumwsrooms::RoomsManager::new();
// create two rooms rooms.newroom("global".into(), None).await; rooms.newroom("room".into(), None).await;
let state = Arc::new(State { rooms });
// build our application with a single route let app = Router::new() .route("/", get(websocket_handler)) .layer(Extension(state));
// run it with axum on localhost:5000 let addr = SocketAddr::from(([0, 0, 0, 0], 5000)); tracing::debug!("listening on {}", addr); axum::Server::bind(&addr) .serve(app.intomakeservice()) .await .unwrap(); }
pub async fn websockethandler(
ws: WebSocketUpgrade,
Extension(state): Extension
async fn websocket(stream: WebSocket, state: Arc
// authenticate user if it fails close the socket if its ok then break the loop;
while let Some(Ok(Message::Text(token))) = receiver.next().await {
// do auth stuff here
let info = check_auth_header(&token).await;
match info {
Ok(user_info) => {
user = user_info;
break;
}
Err(_) => {
sender
.send(Message::Text("auth failed closing socket".to_string()))
.await
.unwrap();
sender.close().await.unwrap();
return;
}
}
}
//init for authenticated user
state
.rooms
.init_user(user.session_id.to_string(), None)
.await;
// join user to global room
state
.rooms
.join_room("global".into(), user.session_id.to_string())
.await
.unwrap();
// get receiver for user that get message from all rooms
let mut user_receiver = state
.rooms
.get_user_receiver(user.session_id.to_string())
.await
.unwrap();
// spawn a task to get message from rooms and send it to user
let mut send_task = tokio::spawn(async move {
while let Ok(data) = user_receiver.recv().await {
sender.send(Message::Text(data)).await.unwrap();
}
});
let rec_state = state.clone();
// spawn a task to get message from user and handle things
let mut recv_task = tokio::spawn(async move {
while let Some(Ok(Message::Text(data))) = receiver.next().await {
if data.starts_with("join") {
// we can join rooms and reciever gets message from that room
rec_state
.rooms
.join_room("room".into(), user.session_id.to_string())
.await
.unwrap();
}
if data.starts_with("send") {
// we can send message to a specific room
rec_state
.rooms
.send_message_to_room("room".into(), data)
.await
.unwrap();
} else {
rec_state
.rooms
.send_message_to_room("global".into(), data)
.await
.unwrap();
}
}
});
// If any one of the tasks exit, abort the other.
tokio::select! {
_ = (&mut send_task) => recv_task.abort(),
_ = (&mut recv_task) => send_task.abort(),
};
// after connection closed you have to call this so all things gets
// removed safely
state.rooms.end_user(user.session_id.to_string()).await;
println!("connection closed");
}
```