mirror of
https://github.com/Corfirean/coa-server-manager.git
synced 2026-11-11 03:51:01 +00:00
fix(friends): restore LAN realm address after restart (#158)
This commit is contained in:
1 parent
4a99dd3a6a
commit
bf2fffcffa
3 files changed
+73
-7
No files matched your search
@@ -0,0 +1,7 @@
|
||||
---
|
||||
area: manager
|
||||
type: fixed
|
||||
audience: admins
|
||||
title: Internet sharing restores the LAN address after server restarts
|
||||
---
|
||||
Friends on the local network receive the server's LAN address and network mask while internet players keep using its public address.
|
||||
@@ -163,10 +163,52 @@ pub fn set_open(root: &Path, meta: &Path, open: bool) -> Result<bool> {
|
||||
|
||||
/// Make the realm list advertise `host` to remote clients (the launcher resets it to 127.0.0.1 at every start, so this
|
||||
/// runs after each start).
|
||||
pub fn apply_realm_address(root: &Path, host: &str) -> Result<()> {
|
||||
fn realm_address_sql(
|
||||
host: &str,
|
||||
local: Option<(std::net::Ipv4Addr, std::net::Ipv4Addr)>,
|
||||
where_realms: &str,
|
||||
) -> Result<String> {
|
||||
if !host_ok(host) {
|
||||
return Err(Error::Invalid("That address is not valid.".into()));
|
||||
}
|
||||
let local = local
|
||||
.map(|(address, mask)| format!(",localAddress='{address}',localSubnetMask='{mask}'"))
|
||||
.unwrap_or_default();
|
||||
Ok(format!(
|
||||
"UPDATE acore_auth.realmlist SET address='{host}'{local} WHERE {where_realms};"
|
||||
))
|
||||
}
|
||||
|
||||
pub fn apply_realm_address(root: &Path, settings: &Settings) -> Result<()> {
|
||||
let host = settings.host.as_deref().unwrap_or("127.0.0.1");
|
||||
let local = match settings.mode {
|
||||
Mode::Direct | Mode::Lan => {
|
||||
let address = if settings.mode == Mode::Lan {
|
||||
host.to_owned()
|
||||
} else {
|
||||
crate::net::resolve_lan_host(
|
||||
settings.lan_address_override.as_deref(),
|
||||
crate::net::lan_ip(),
|
||||
)?
|
||||
};
|
||||
let address = crate::net::validate_lan_address(&address)?;
|
||||
let mask = if_addrs::get_if_addrs()?
|
||||
.into_iter()
|
||||
.find_map(|interface| match interface.addr {
|
||||
if_addrs::IfAddr::V4(v4) if v4.ip == address => Some(v4.netmask),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
Error::Invalid("The selected local network address is not connected.".into())
|
||||
})?;
|
||||
Some((address, mask))
|
||||
}
|
||||
Mode::Local => Some((
|
||||
std::net::Ipv4Addr::LOCALHOST,
|
||||
std::net::Ipv4Addr::new(255, 0, 0, 0),
|
||||
)),
|
||||
Mode::Private => None,
|
||||
};
|
||||
let db = Db::from_repack(root, Account::Admin)?;
|
||||
let realm = crate::realms::state(root)?.active.realm_id();
|
||||
let where_realms = if crate::realms::state(root)?.simultaneous {
|
||||
@@ -174,9 +216,7 @@ pub fn apply_realm_address(root: &Path, host: &str) -> Result<()> {
|
||||
} else {
|
||||
format!("id={realm}")
|
||||
};
|
||||
db.query(&format!(
|
||||
"UPDATE acore_auth.realmlist SET address='{host}' WHERE {where_realms};"
|
||||
))?;
|
||||
db.query(&realm_address_sql(host, local, &where_realms)?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -194,9 +234,9 @@ pub fn ensure_bind(root: &Path, meta: &Path) -> Result<bool> {
|
||||
/// After every server start: put the chosen address back into the realm list (the launcher resets it to 127.0.0.1).
|
||||
pub fn reapply(root: &Path, meta: &Path) -> Result<()> {
|
||||
let s = load(meta);
|
||||
match (s.mode, s.host) {
|
||||
match (s.mode, &s.host) {
|
||||
(Mode::Local, _) | (_, None) => Ok(()),
|
||||
(_, Some(host)) => apply_realm_address(root, &host),
|
||||
(_, Some(_)) => apply_realm_address(root, &s),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,6 +430,25 @@ CoA.AllowRemoteClients = 0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn realm_addresses_restore_lan_without_replacing_public_host() {
|
||||
let sql = realm_address_sql(
|
||||
"203.0.113.9",
|
||||
Some((
|
||||
"192.168.50.7".parse().unwrap(),
|
||||
"255.255.254.0".parse().unwrap(),
|
||||
)),
|
||||
"id IN (1,2)",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(sql, "UPDATE acore_auth.realmlist SET address='203.0.113.9',localAddress='192.168.50.7',localSubnetMask='255.255.254.0' WHERE id IN (1,2);");
|
||||
assert_eq!(
|
||||
realm_address_sql("100.64.1.2", None, "id=1").unwrap(),
|
||||
"UPDATE acore_auth.realmlist SET address='100.64.1.2' WHERE id=1;"
|
||||
);
|
||||
assert!(realm_address_sql("bad'host", None, "id=1").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn old_settings_load_without_migrating_effective_host_to_override() {
|
||||
let s: Settings = serde_json::from_str(r#"{"mode":"lan","host":"192.168.1.50"}"#).unwrap();
|
||||
|
||||
@@ -2571,7 +2571,7 @@ async fn friends_enable(
|
||||
friends::save(&meta, &settings)?;
|
||||
let running = coa_core::process::observe(&root, &ports).world.state == coa_core::process::ServiceState::Running;
|
||||
if running {
|
||||
friends::apply_realm_address(&root, &host)?;
|
||||
friends::apply_realm_address(&root, &settings)?;
|
||||
}
|
||||
Ok(FriendsResult { host, restart_required: changed && running, note })
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user