summary refs log tree commit diff
path: root/crates/messenger_server/src/main.rs
diff options
context:
space:
mode:
authorSophie Forrest <git@sophieforrest.com>2024-08-30 23:13:20 +1200
committerSophie Forrest <git@sophieforrest.com>2024-08-30 23:13:44 +1200
commite3cb82a3b33bd2a2e49c58ce18d1258fb505869e (patch)
tree2375279182fb4f90f5c28560a08cda90591f608b /crates/messenger_server/src/main.rs
chore: initial commit (codeberg upload) HEAD main
Diffstat (limited to 'crates/messenger_server/src/main.rs')
-rw-r--r--crates/messenger_server/src/main.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/crates/messenger_server/src/main.rs b/crates/messenger_server/src/main.rs
new file mode 100644
index 0000000..76ce81d
--- /dev/null
+++ b/crates/messenger_server/src/main.rs
@@ -0,0 +1,142 @@
+#![feature(async_fn_in_trait)]
+#![feature(custom_inner_attributes)]
+#![feature(lint_reasons)]
+#![feature(never_type)]
+#![feature(lazy_cell)]
+#![clippy::msrv = "1.69.0"]
+#![deny(clippy::nursery)]
+#![deny(clippy::pedantic)]
+#![deny(clippy::alloc_instead_of_core)]
+#![deny(clippy::as_underscore)]
+#![deny(clippy::clone_on_ref_ptr)]
+#![deny(clippy::create_dir)]
+#![warn(clippy::dbg_macro)]
+#![deny(clippy::default_numeric_fallback)]
+#![deny(clippy::default_union_representation)]
+#![deny(clippy::deref_by_slicing)]
+#![deny(clippy::else_if_without_else)]
+#![deny(clippy::empty_structs_with_brackets)]
+#![deny(clippy::exit)]
+#![deny(clippy::expect_used)]
+#![deny(clippy::filetype_is_file)]
+#![deny(clippy::fn_to_numeric_cast)]
+#![deny(clippy::format_push_string)]
+#![deny(clippy::get_unwrap)]
+#![deny(clippy::if_then_some_else_none)]
+#![allow(
+	clippy::implicit_return,
+	reason = "returns should be done implicitly, not explicitly"
+)]
+#![deny(clippy::indexing_slicing)]
+#![deny(clippy::large_include_file)]
+#![deny(clippy::let_underscore_must_use)]
+#![deny(clippy::lossy_float_literal)]
+#![deny(clippy::map_err_ignore)]
+#![deny(clippy::mem_forget)]
+#![deny(clippy::missing_docs_in_private_items)]
+#![deny(clippy::missing_trait_methods)]
+#![deny(clippy::multiple_inherent_impl)]
+#![deny(clippy::needless_return)]
+#![deny(clippy::non_ascii_literal)]
+#![deny(clippy::panic_in_result_fn)]
+#![deny(clippy::pattern_type_mismatch)]
+#![deny(clippy::rc_buffer)]
+#![deny(clippy::rc_mutex)]
+#![deny(clippy::rest_pat_in_fully_bound_structs)]
+#![deny(clippy::same_name_method)]
+#![deny(clippy::separated_literal_suffix)]
+#![deny(clippy::str_to_string)]
+#![deny(clippy::string_add)]
+#![deny(clippy::string_slice)]
+#![deny(clippy::string_to_string)]
+#![allow(
+	clippy::tabs_in_doc_comments,
+	reason = "tabs are preferred for this project"
+)]
+#![deny(clippy::try_err)]
+#![deny(clippy::undocumented_unsafe_blocks)]
+#![deny(clippy::unnecessary_self_imports)]
+#![deny(clippy::unneeded_field_pattern)]
+#![deny(clippy::unwrap_in_result)]
+#![deny(clippy::unwrap_used)]
+#![warn(clippy::use_debug)]
+#![deny(clippy::verbose_file_reads)]
+#![deny(clippy::wildcard_dependencies)]
+#![deny(clippy::wildcard_enum_match_arm)]
+#![deny(clippy::missing_panics_doc)]
+#![deny(missing_copy_implementations)]
+#![deny(missing_debug_implementations)]
+#![deny(missing_docs)]
+#![deny(single_use_lifetimes)]
+#![deny(unsafe_code)]
+#![deny(unused)]
+// Server-specific lint disables
+#![allow(clippy::redundant_pub_crate)]
+
+//! # Messenger Server
+//!
+//! Provides a server-side implementation of the messenger protocol
+
+mod app;
+mod message;
+mod session;
+mod websocket;
+
+use std::{
+	collections::{HashSet, VecDeque},
+	net::{Ipv4Addr, SocketAddr, SocketAddrV4},
+	sync::Arc,
+};
+
+use app::State as AppState;
+use axum::{response::Html, routing::get, Router};
+use tokio::sync::{broadcast, Mutex};
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
+
+/// Socket Address the server is bound to when ran.
+const ADDR: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 3000));
+
+#[tokio::main]
+async fn main() {
+	tracing_subscriber::registry()
+		.with(
+			tracing_subscriber::EnvFilter::try_from_default_env()
+				.unwrap_or_else(|_| "chat=trace".into()),
+		)
+		.with(tracing_subscriber::fmt::layer())
+		.init();
+
+	// Set up application state for use with with_state().
+	let user_set: Mutex<HashSet<String>> = Mutex::new(HashSet::new());
+	let (tx, _rx) = broadcast::channel::<String>(100);
+	let message_history = Mutex::new(VecDeque::new());
+
+	let app_state = Arc::new(AppState {
+		message_history,
+		tx,
+		user_set,
+	});
+
+	let app = Router::new()
+		.route("/", get(index))
+		.route("/websocket", get(websocket::handler))
+		.with_state(app_state);
+
+	tracing::debug!("listening on {ADDR}");
+
+	if let Err(error) = axum::Server::bind(&ADDR)
+		.serve(app.into_make_service())
+		.await
+	{
+		tracing::error!("server failed to start: {error}");
+	}
+}
+
+/// Include utf-8 file at **compile** time.
+#[expect(
+	clippy::unused_async,
+	reason = "axum requires this function to by async, but clippy disallows this"
+)]
+async fn index() -> Html<&'static str> {
+	Html(std::include_str!("../chat.html"))
+}