aboutsummaryrefslogtreecommitdiff
path: root/server/registry/src/register.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/registry/src/register.rs')
-rw-r--r--server/registry/src/register.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/server/registry/src/register.rs b/server/registry/src/register.rs
index fb1c668a..603f5a4a 100644
--- a/server/registry/src/register.rs
+++ b/server/registry/src/register.rs
@@ -1,8 +1,31 @@
-use crate::Registry;
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2024 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
+use crate::{conn_test::test_connect, Registry, MAX_SERVERS};
+use anyhow::Result;
use hurrycurry_protocol::registry::Submission;
use log::{debug, info};
use rocket::{http::hyper::Uri, post, serde::json::Json, State};
-use std::{net::IpAddr, str::FromStr, sync::Arc, time::Instant};
+use std::{
+ net::{IpAddr, SocketAddr},
+ str::FromStr,
+ sync::Arc,
+ time::Instant,
+};
use tokio::{net::lookup_host, sync::RwLock};
#[post("/v1/register", data = "<submission>")]
@@ -11,6 +34,23 @@ pub(super) async fn r_register<'a>(
registry: &State<Arc<RwLock<Registry>>>,
submission: Json<Submission>,
) -> Result<&'static str, &'static str> {
+ match register_inner(client_addr, registry, &submission).await {
+ Ok(()) => {
+ info!("ok");
+ Ok("ok")
+ }
+ Err(e) => {
+ info!("err: {e}");
+ Err(e)
+ }
+ }
+}
+
+async fn register_inner(
+ client_addr: IpAddr,
+ registry: &Arc<RwLock<Registry>>,
+ submission: &Submission,
+) -> Result<(), &'static str> {
debug!("submission {submission:?}");
let uri = Uri::from_str(&submission.uri).map_err(|_| "invalid uri")?;
@@ -23,7 +63,7 @@ pub(super) async fn r_register<'a>(
let host = uri.host().ok_or("no host")?;
let port = uri.port_u16().unwrap_or(if secure { 443 } else { 27032 });
- let uri_q = match IpAddr::from_str(host) {
+ let (saddr, uri_q) = match IpAddr::from_str(host) {
Ok(mut addr) => {
if addr.is_unspecified() {
addr = client_addr;
@@ -35,31 +75,35 @@ pub(super) async fn r_register<'a>(
return Err("multicast address");
}
if client_addr == addr {
- format!("{scheme}://{addr}:{port}",)
+ let saddr = SocketAddr::new(addr, port);
+ (saddr, format!("{scheme}://{saddr}"))
} else {
return Err("source address does not match uri");
}
}
Err(_) => {
- if lookup_host(format!("{host}:0"))
+ if let Some(addr) = lookup_host(format!("{host}:0"))
.await
.map_err(|_| "dns lookup failed")?
.find(|a| a.ip() == client_addr)
- .is_some()
{
- format!("{scheme}://{host}:{port}")
+ (
+ SocketAddr::new(addr.ip(), port),
+ format!("{scheme}://{host}:{port}"),
+ )
} else {
return Err("host verification failed");
}
}
};
+ test_connect(saddr, &uri_q).await?;
+
let mut g = registry.write().await;
- if g.servers.len() > 1000 {
+ if g.servers.len() > MAX_SERVERS {
return Err("too many registered servers");
}
-
info!("submission approved for {uri_q:?}");
let entry = g.servers.entry(submission.secret).or_default();
entry.name = submission.name.clone();
@@ -68,5 +112,5 @@ pub(super) async fn r_register<'a>(
entry.version = submission.version;
entry.address.insert(uri_q, Instant::now());
- Ok("ok")
+ Ok(())
}