s2s: propagate CHGHOST/CHGIDENT host/ident changes to links (were applied locally only); inbound path uses a non-propagating variant to avoid a loop
This commit is contained in:
parent
73f8ff58ed
commit
92a3f5ba86
2 changed files with 36 additions and 2 deletions
|
|
@ -821,7 +821,7 @@ impl Server {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match self.link_local_target(&target) {
|
match self.link_local_target(&target) {
|
||||||
Some(tuid) => self.change_host_ident(tuid, None, Some(&host)),
|
Some(tuid) => self.change_host_ident_quiet(tuid, None, Some(&host)),
|
||||||
None => {
|
None => {
|
||||||
self.forward_to_target(&target, msg, from);
|
self.forward_to_target(&target, msg, from);
|
||||||
}
|
}
|
||||||
|
|
@ -837,7 +837,7 @@ impl Server {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
match self.link_local_target(&target) {
|
match self.link_local_target(&target) {
|
||||||
Some(tuid) => self.change_host_ident(tuid, Some(&ident), None),
|
Some(tuid) => self.change_host_ident_quiet(tuid, Some(&ident), None),
|
||||||
None => {
|
None => {
|
||||||
self.forward_to_target(&target, msg, from);
|
self.forward_to_target(&target, msg, from);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1049,6 +1049,28 @@ impl Server {
|
||||||
/// to the user, and sends RPL_HOSTHIDDEN (396) when the host changed. Local
|
/// to the user, and sends RPL_HOSTHIDDEN (396) when the host changed. Local
|
||||||
/// scope for now.
|
/// scope for now.
|
||||||
pub fn change_host_ident(&mut self, uid: Uid, new_ident: Option<&str>, new_host: Option<&str>) {
|
pub fn change_host_ident(&mut self, uid: Uid, new_ident: Option<&str>, new_host: Option<&str>) {
|
||||||
|
self.change_host_ident_inner(uid, new_ident, new_host, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Like [`change_host_ident`] but does NOT propagate over S2S — for applying an
|
||||||
|
/// inbound CHGHOST/CHGIDENT (the link layer already relayed it; re-propagating
|
||||||
|
/// would echo it back toward its origin).
|
||||||
|
pub fn change_host_ident_quiet(
|
||||||
|
&mut self,
|
||||||
|
uid: Uid,
|
||||||
|
new_ident: Option<&str>,
|
||||||
|
new_host: Option<&str>,
|
||||||
|
) {
|
||||||
|
self.change_host_ident_inner(uid, new_ident, new_host, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_host_ident_inner(
|
||||||
|
&mut self,
|
||||||
|
uid: Uid,
|
||||||
|
new_ident: Option<&str>,
|
||||||
|
new_host: Option<&str>,
|
||||||
|
propagate: bool,
|
||||||
|
) {
|
||||||
let Some(u) = self.users.get(&uid) else {
|
let Some(u) = self.users.get(&uid) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -1077,6 +1099,18 @@ impl Server {
|
||||||
if aware {
|
if aware {
|
||||||
self.send(uid, line);
|
self.send(uid, line);
|
||||||
}
|
}
|
||||||
|
// propagate to linked servers so their view stays in sync (echoIRCd applies an
|
||||||
|
// inbound ENCAP CHGHOST/CHGIDENT; a peer that doesn't understand ENCAP ignores
|
||||||
|
// it). Skipped when applying an inbound change, so it isn't echoed to its origin.
|
||||||
|
if propagate && !self.links.is_empty() {
|
||||||
|
let (uuid, sid) = (self.users[&uid].uuid.clone(), self.sid.clone());
|
||||||
|
if let Some(i) = new_ident {
|
||||||
|
self.propagate(&format!(":{sid} ENCAP * CHGIDENT {uuid} {i}"), None);
|
||||||
|
}
|
||||||
|
if let Some(h) = new_host {
|
||||||
|
self.propagate(&format!(":{sid} ENCAP * CHGHOST {uuid} {h}"), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
// hostcycle — clients WITHOUT the chghost cap only learn the new host via a
|
// hostcycle — clients WITHOUT the chghost cap only learn the new host via a
|
||||||
// PART+JOIN, so cycle them through each shared channel (chghost peers already
|
// PART+JOIN, so cycle them through each shared channel (chghost peers already
|
||||||
// got the CHGHOST line above). Prefix modes are re-sent so they don't appear
|
// got the CHGHOST line above). Prefix modes are re-sent so they don't appear
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue