Media server support

Still only works for clients and is not federated. Need to figure out
caching when I get to the federated version
This commit is contained in:
2026-05-30 22:22:16 -07:00
parent 8ba58234e0
commit 0e3600c31f
4 changed files with 61 additions and 11 deletions
Generated
+4 -2
View File
@@ -275,6 +275,7 @@ dependencies = [
"toml",
"tracing",
"tracing-subscriber",
"uuid",
]
[[package]]
@@ -545,6 +546,7 @@ dependencies = [
[[package]]
name = "fedichat"
version = "0.1.0"
source = "git+https://git.firechicken.net/fedichat/fedichat-lib#49cbd905ceecb7bf7be463f81836742e3a7ddc24"
dependencies = [
"serde",
"serde_bytes",
@@ -1870,9 +1872,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.23.1"
version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
dependencies = [
"getrandom 0.4.2",
"js-sys",
+3 -2
View File
@@ -6,8 +6,8 @@ edition = "2024"
[dependencies]
diesel = { version = "2.3.9", features = ["postgres_backend"] }
quinn = "0.11.9"
#fedichat = {git = "https://git.firechicken.net/fedichat/fedichat-lib"}
fedichat = {path = "../fedichat-lib"}
fedichat = {git = "https://git.firechicken.net/fedichat/fedichat-lib"}
#fedichat = {path = "../fedichat-lib"}
tracing = "0.1.44"
tracing-subscriber = "0.3.23"
clap = { version = "4.6.1", features = ["derive"] }
@@ -22,4 +22,5 @@ diesel-derive-composite = "0.1.0"
bcrypt = "0.19.1"
time = { version = "0.3.47", features = ["serde"] }
rand = "0.10.1"
uuid = { version = "1.23.2", features = ["v4"] }
#postcard = {version = "1.1.3", features = ["use-std"]}
+43 -7
View File
@@ -6,10 +6,13 @@ use diesel_async::AsyncPgConnection;
use diesel_async::pooled_connection::deadpool::{Pool,Object};
use rmp_serde;
use std::collections::{HashMap,HashSet};
use std::fs::File;
use std::io::{Read,Write};
use std::sync::{Arc};
use thiserror::Error;
use tokio::sync::{broadcast,mpsc,RwLock};
use tokio::select;
use uuid::Uuid;
use crate::Coordinate;
use crate::db;
use crate::state::{self,State};
@@ -17,12 +20,6 @@ use crate::state::{self,State};
use quinn::ConnectionError;
use tracing::{warn,error,debug,instrument};
#[derive(Error,Debug)]
enum HandlerError {
#[error("Foo")]
Foo
}
pub struct Client {
statehandle: Arc<RwLock<State>>,
// Channel for local messages, all are broadcast to all
@@ -457,7 +454,46 @@ impl Client {
// with users
MediaUpload {
bytes,
} => {unimplemented!()},
} => {
//NOTE: This maybe should have a limit on filesize
// Right now the only limit is on message size in the quic
// handler. Probably should be configurable too
//
// On boot the media directory should have already been created
let uuid = Uuid::new_v4();
let path = config.media_directory.clone() + &format!("/{}",uuid);
// Hide fs errors from the user but print on server console
let mut file = File::create(&path).map_err(|e| {
error!("Problem writing media file {}: {}",path,e);
ServerError::Generic
})?;
debug!("Writing file: {:?}", bytes);
file.write_all(&bytes).map_err(|e| {
error!("Problem writing media file {}: {}",path,e);
ServerError::Generic
})?;
Ok(ServerMessage::MediaId(uuid))
},
MediaFetch {
id
} => {
let path = config.media_directory.clone() + &format!("/{}",id);
// Hide fs errors from the user but print on server console
let mut file = File::open(&path).map_err(|e| {
error!("Problem reading media file {}: {}",path,e);
ServerError::Generic
})?;
// Start the buffer at 4KiB. Probably could be larger because
// we expect the files stored using this method to be at least
// a few MB
let mut buf = Vec::with_capacity(4096);
file.read_to_end(&mut buf).map_err(|e| {
error!("Problem reading media file {}: {}",path,e);
ServerError::Generic
})?;
Ok(ServerMessage::Media(buf.into_boxed_slice()))
},
// Join and subscribe
RoomJoin {
room_id,
+11
View File
@@ -79,6 +79,17 @@ async fn main() -> ExitCode {
tracing_subscriber::fmt().with_max_level(level).finish()
).expect("Failed to setup logger");
// Check to make sure media directory exists
match std::fs::exists(&config.media_directory) {
Ok(true) => {},
// NOTE: maybe shouldnt shadow this error
_ => {
error!("Media directory {} does not exist. Check to make sure it is a directory and is writable.",config.media_directory);
return ExitCode::FAILURE;
}
}
// Set up database connection
let db_string = format!("postgres://{}:{}@{}/{}",config.database.user,config.database.password,config.database.url,config.database.db_name);