async sockets

This commit is contained in:
Alex Emmet 2025-11-09 19:25:01 +00:00
commit 4170b9f387
23 changed files with 544 additions and 479 deletions

View file

@ -1,7 +1,5 @@
use crate::communities::interactables::category::Category;
use crate::communities::interactables::registry;
use crate::communities::interactables::text_chat::TextChat;
use crate::communities::interactables::voice_chat::VoiceChat;
use crate::communities::{
community_connection::CommunityConnection, interactables::interactable::Interactable,
};
@ -12,8 +10,6 @@ use json::JsonValue;
use json::object::Object;
use rand::RngCore;
use rand_core::OsRng;
use ratatui::text;
use serde::de::value::StringDeserializer;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
@ -200,10 +196,10 @@ impl Community {
let mut permissions = JsonValue::new_array();
for perm in self.permissions.get(user).unwrap() {
permissions.push(perm.to_string());
if let Ok(_) = permissions.push(perm.to_string()) {}
}
data.insert("permissions", permissions);
if let Ok(_) = data.insert("permissions", permissions) {}
user_data.insert(&user.to_string(), data);
}
file_util::save_file(
@ -230,7 +226,7 @@ pub async fn load(name: &String) -> Option<Arc<Community>> {
let (str, json): (&str, &JsonValue) = user;
let perms_j = &json["permissions"];
let perms = Vec::new();
for i in perms_j.entries() {
for _ in perms_j.entries() {
// let perm_j = i.as_str().unwrap();
// perms.push(perm_j.to_string());
}
@ -242,11 +238,12 @@ pub async fn load(name: &String) -> Option<Arc<Community>> {
}
let role_data = file_util::load_file(&format!("communities/{}/", name), "roles.json");
if let Ok(user_json) = json::parse(&role_data) {
let roles: HashMap<String, Vec<String>> = HashMap::new();
if let Ok(_) = json::parse(&role_data) {
// Fill roles
} else {
return None;
};
let mut roles: HashMap<String, Vec<String>> = HashMap::new();
let community = Community {
name: json_content["name"].as_str().unwrap().to_string(),
@ -283,15 +280,5 @@ pub async fn load(name: &String) -> Option<Arc<Community>> {
comarc.add_interactable(Arc::new(interactable)).await;
}
}
let mut text_chat: TextChat = TextChat::new();
text_chat.load(
comarc.clone(),
String::new(),
String::from("a"),
&JsonValue::Null,
);
comarc.add_interactable(Arc::new(Box::new(text_chat))).await;
Some(comarc)
}

View file

@ -4,6 +4,10 @@ use crate::communities::community::Community;
use crate::communities::interactables::interactable::Interactable;
use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes};
use aes_gcm::{Aes256Gcm, KeyInit, Nonce, aead::Aead};
use async_tungstenite::WebSocketReceiver;
use async_tungstenite::WebSocketSender;
use async_tungstenite::tungstenite::Utf8Bytes;
use async_tungstenite::{WebSocketStream, tungstenite::Message};
use base64::{Engine as _, engine::general_purpose::STANDARD};
use futures::SinkExt;
use hkdf::Hkdf;
@ -13,11 +17,12 @@ use sha2::Sha256;
use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::sync::RwLock;
use tokio_tungstenite::{WebSocketStream, tungstenite::Message};
use tokio_util::compat::Compat;
use uuid::Uuid;
use x448::PublicKey;
pub struct CommunityConnection {
pub session: Arc<Mutex<WebSocketStream<tokio::net::TcpStream>>>,
pub sender: Arc<RwLock<WebSocketSender<Compat<tokio::net::TcpStream>>>>,
pub receiver: Arc<RwLock<WebSocketReceiver<Compat<tokio::net::TcpStream>>>>,
pub user_id: Arc<RwLock<Option<Uuid>>>,
pub community: Arc<RwLock<Option<Arc<Community>>>>,
identified: Arc<RwLock<bool>>,
@ -28,11 +33,13 @@ pub struct CommunityConnection {
}
impl CommunityConnection {
pub fn new(
session: WebSocketStream<tokio::net::TcpStream>,
sender: WebSocketSender<Compat<tokio::net::TcpStream>>,
receiver: WebSocketReceiver<Compat<tokio::net::TcpStream>>,
community: Arc<Community>,
) -> Arc<Self> {
Arc::new(Self {
session: Arc::new(Mutex::new(session)),
sender: Arc::new(RwLock::new(sender)),
receiver: Arc::new(RwLock::new(receiver)),
user_id: Arc::new(RwLock::new(None)),
community: Arc::new(RwLock::new(Some(community))),
identified: Arc::new(RwLock::new(false)),
@ -43,9 +50,11 @@ impl CommunityConnection {
})
}
pub async fn send_message(&self, message: &CommunicationValue) {
let mut session = self.session.lock().await;
let mut session = self.sender.write().await;
session
.send(Message::Text(message.to_json().to_string()))
.send(Message::Text(Utf8Bytes::from(
message.to_json().to_string(),
)))
.await
.unwrap();
}
@ -60,7 +69,8 @@ impl CommunityConnection {
}
pub async fn handle_message(self: Arc<Self>, message: String) {
let cv = CommunicationValue::from_json(&message);
let cv =
CommunicationValue::from_json(&message).with_sender(self.get_user_id().await.unwrap());
if cv.is_type(CommunicationType::identification) && !self.is_identified().await {
self.handle_identification(cv).await;
@ -388,7 +398,7 @@ impl CommunityConnection {
self.send_message(&error).await;
}
pub async fn close(&self) {
let mut session = self.session.lock().await;
let mut session = self.sender.write().await;
let _ = session.close(None).await;
}
pub async fn handle_close(self: Arc<Self>) {

View file

@ -1,65 +0,0 @@
use crate::communities::{community_connection::CommunityConnection, community_manager};
use futures::StreamExt;
use std::sync::Arc;
use tokio::net::TcpListener;
use tokio_tungstenite::accept_hdr_async;
use tungstenite::handshake::server::{Request, Response};
pub async fn start(port: u16) -> bool {
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await;
if let Err(_) = listener {
return false;
}
let listener = listener.unwrap();
tokio::spawn(async move {
while let Ok((stream, _)) = listener.accept().await {
tokio::spawn(async move {
let mut path: String = "/".to_string();
let callback = |req: &Request, response: Response| {
path = format!("{}", &req.uri().path());
Ok(response)
};
let ws_stream = match accept_hdr_async(stream, callback).await {
Ok(ws) => ws,
Err(e) => {
return;
}
};
if path.starts_with("/community/") {
let community_id = path.split("/").nth(2).unwrap();
if let Some(community) = community_manager::get_community(community_id).await {
let community_conn: Arc<CommunityConnection> =
Arc::from(CommunityConnection::new(ws_stream, community));
loop {
let msg_result = {
let mut session_lock = community_conn.session.lock().await;
session_lock.next().await
};
match msg_result {
Some(Ok(msg)) => {
if msg.is_text() {
let text = msg.into_text().unwrap();
community_conn.clone().handle_message(text).await;
} else if msg.is_close() {
community_conn.handle_close().await;
return;
}
}
Some(Err(e)) => {
community_conn.handle_close().await;
return;
}
None => {
community_conn.handle_close().await;
return;
}
}
}
}
}
});
}
});
true
}

View file

@ -98,11 +98,11 @@ impl Interactable for Category {
let mut v = JsonValue::new_object();
v["children"] = JsonValue::new_array();
for child in &self.children {
v["children"].push(child.to_json());
let _ = v["children"].push(child.to_json());
}
v
}
fn load(&mut self, community: Arc<Community>, path: String, name: String, json: &JsonValue) {
fn load(&mut self, community: Arc<Community>, path: String, name: String, _json: &JsonValue) {
self.community = community;
self.name = name;
self.path = path;

View file

@ -11,13 +11,9 @@ use aes_gcm::aead::Payload;
use async_trait::async_trait;
use axum::Json;
use json::{JsonValue, array, object};
use rustls::ClientConnection;
use std::sync::Arc;
use std::{any::Any, collections::HashMap};
use std::{
fs::{self, File},
pin::Pin,
};
use std::{fs, pin::Pin};
use uuid::Uuid;
pub struct TextChat {
name: String,
@ -246,10 +242,9 @@ impl Interactable for TextChat {
CommunicationValue::new(CommunicationType::error).with_id(cv.get_id())
}
fn to_json(&self) -> JsonValue {
let mut v = JsonValue::new_object();
v
JsonValue::new_object()
}
fn load(&mut self, community: Arc<Community>, path: String, name: String, json: &JsonValue) {
fn load(&mut self, community: Arc<Community>, path: String, name: String, _: &JsonValue) {
self.community = community;
self.name = name;
self.path = path;

View file

@ -188,7 +188,7 @@ impl Interactable for VoiceChat {
let v = JsonValue::new_object();
v
}
fn load(&mut self, community: Arc<Community>, path: String, name: String, _: &JsonValue) {
fn load(&mut self, community: Arc<Community>, path: String, name: String, _json: &JsonValue) {
self.community = community;
self.name = name;
self.path = path;

View file

@ -1,5 +1,4 @@
pub mod community_manager;
pub mod community_socket;
pub mod interactables {
pub mod category;
pub mod interactable;