aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/lib.rs9
-rw-r--r--server/src/main.rs33
-rw-r--r--server/src/register.rs80
3 files changed, 115 insertions, 7 deletions
diff --git a/server/src/lib.rs b/server/src/lib.rs
index c35a2b5a..ea514d5b 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -27,6 +27,7 @@ pub mod commands;
pub mod data;
pub mod entity;
pub mod interaction;
+pub mod register;
pub mod scoreboard;
pub mod server;
pub mod state;
@@ -72,7 +73,9 @@ macro_rules! trm_param {
(t, $x:expr) => {
hurrycurry_protocol::Message::Tile($x)
};
- (m, $x:expr) => { $x };
+ (m, $x:expr) => {
+ $x
+ };
}
#[derive(Debug)]
@@ -110,5 +113,7 @@ macro_rules! tre_param {
(t, $x:expr) => {
hurrycurry_protocol::Message::Tile($x)
};
- (m, $x:expr) => { $x };
+ (m, $x:expr) => {
+ $x
+ };
}
diff --git a/server/src/main.rs b/server/src/main.rs
index 20d9908d..4db43c64 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -21,6 +21,7 @@ use futures_util::{SinkExt, StreamExt};
use hurrycurry_protocol::{PacketC, PacketS, BINCODE_CONFIG, VERSION};
use hurrycurry_server::{
data::DATA_DIR,
+ register::Register,
server::{GameServerExt, Server},
trm, ConnectionID,
};
@@ -45,7 +46,7 @@ use tokio::{
use tokio_tungstenite::tungstenite::Message;
#[derive(Parser)]
-struct Args {
+pub(crate) struct Args {
/// Print the version, then exit
#[arg(short, long)]
version: bool,
@@ -55,6 +56,18 @@ struct Args {
/// Set the address on which the server should listen
#[arg(short, long, default_value = "0.0.0.0:27032")]
listen: SocketAddr,
+ /// Enables submissions to the public server registry
+ #[arg(long)]
+ register: bool,
+ /// Enables mDNS discoverability
+ #[arg(long)]
+ discoverable: bool,
+ /// Server name
+ #[arg(long, short = 'N', default_value = "A Hurry Curry! Server")]
+ server_name: String,
+ /// Uri for connecting remotely for registry submission
+ #[arg(long)]
+ register_uri: Option<String>,
}
fn main() -> Result<()> {
@@ -70,7 +83,7 @@ fn main() -> Result<()> {
exit(0);
}
- let data_dir = if let Some(d) = args.data_dir {
+ let data_dir = if let Some(d) = args.data_dir.clone() {
d
} else {
let d = PathBuf::from_str(
@@ -94,12 +107,12 @@ fn main() -> Result<()> {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
- .block_on(run(args.listen))?;
+ .block_on(run(args))?;
Ok(())
}
-async fn run(addr: SocketAddr) -> anyhow::Result<()> {
- let ws_listener = TcpListener::bind(addr).await?;
+async fn run(args: Args) -> anyhow::Result<()> {
+ let ws_listener = TcpListener::bind(args.listen).await?;
info!("Listening for websockets on {}", ws_listener.local_addr()?);
let (tx, rx) = broadcast::channel::<PacketC>(128 * 1024);
@@ -108,6 +121,16 @@ async fn run(addr: SocketAddr) -> anyhow::Result<()> {
state.load(state.index.generate("lobby").await?, None);
let state = Arc::new(RwLock::new(state));
+ if args.register {
+ let r = Register::new(
+ args.server_name.clone(),
+ args.listen.port(),
+ args.register_uri,
+ state.clone(),
+ );
+ tokio::task::spawn(r.register_loop());
+ }
+
{
let state = state.clone();
spawn(async move {
diff --git a/server/src/register.rs b/server/src/register.rs
new file mode 100644
index 00000000..ef940fbf
--- /dev/null
+++ b/server/src/register.rs
@@ -0,0 +1,80 @@
+use crate::server::Server;
+use anyhow::{bail, Result};
+use hurrycurry_protocol::{registry::Submission, VERSION};
+use log::{info, warn};
+use rand::random;
+use reqwest::{header::USER_AGENT, Client, Url};
+use std::{str::FromStr, sync::Arc, time::Duration};
+use tokio::{sync::RwLock, time::interval};
+
+const REGISTRY_URI: &'static str = "https://hurrycurry-registry.metamuffin.org";
+
+pub struct Register {
+ name: String,
+ port: u16,
+ register_uri: Option<String>,
+ state: Arc<RwLock<Server>>,
+ client: Client,
+ secret: u128,
+ players: usize,
+}
+
+impl Register {
+ pub fn new(
+ name: String,
+ port: u16,
+ register_uri: Option<String>,
+ state: Arc<RwLock<Server>>,
+ ) -> Self {
+ Self {
+ name,
+ register_uri,
+ players: 0,
+ port,
+ secret: random(),
+ state,
+ client: Client::new(),
+ }
+ }
+ pub async fn register_loop(mut self) {
+ let mut interval = interval(Duration::from_secs(60));
+ loop {
+ interval.tick().await;
+ self.players = self.state.read().await.count_chefs();
+ if let Err(e) = self.register().await {
+ warn!("register error: {e}")
+ }
+ }
+ }
+ // TODO ip v6
+ pub async fn register(&mut self) -> Result<()> {
+ let res = self
+ .client
+ .post(Url::from_str(&format!("{REGISTRY_URI}/v1/register")).unwrap())
+ .header(
+ USER_AGENT,
+ format!("hurrycurry-server {}", env!("CARGO_PKG_VERSION")),
+ )
+ .json(&Submission {
+ last_game: 0,
+ name: self.name.clone(),
+ uri: self
+ .register_uri
+ .clone()
+ .unwrap_or_else(|| format!("ws://0.0.0.0:{}", self.port)),
+ players: self.players,
+ secret: self.secret,
+ version: VERSION,
+ })
+ .send()
+ .await?;
+
+ let r = res.text().await?;
+ if r == "ok" {
+ info!("register ok");
+ Ok(())
+ } else {
+ bail!("{r}");
+ }
+ }
+}