feat(lib): decode distributed frames and announce a parentless stance

The distributed search network carries searches from parent to child
over connections whose frames have a one-byte code; the library had no
reader for them. This adds the codec for Search, BranchLevel,
BranchRoot and the embedded envelope, with the identifier check that
keeps malformed frames from being answered, and completes the post-login
stance Nicotine+ sends: HaveNoParent, BranchRoot (ourselves),
BranchLevel 0 and AcceptChildren false, in place of HaveNoParent alone.
This commit is contained in:
Michel de Graaf
2026-09-08 01:45:07 +02:00
parent 976dd706d7
commit 1976b49792
5 changed files with 221 additions and 11 deletions
@@ -127,8 +127,32 @@ impl MessageFactory {
.clone()
}
#[must_use]
pub fn build_no_parent_message() -> Message {
Message::new().write_int32(71).write_bool(true).clone()
/// Whether we lack a parent in the distributed network (code 71); the
/// server offers PossibleParents while we say so.
pub fn build_have_no_parent(no_parent: bool) -> Message {
Message::new().write_int32(71).write_bool(no_parent).clone()
}
/// The root of the branch we hang from (code 127): ourselves while we
/// have no parent.
#[must_use]
pub fn build_branch_root(username: &str) -> Message {
Message::new()
.write_int32(127)
.write_string(username)
.clone()
}
/// How deep in the tree we sit (code 126): 0 without a parent.
#[must_use]
pub fn build_branch_level(level: u32) -> Message {
Message::new().write_int32(126).write_int32(level).clone()
}
/// Whether we take children in the distributed network (code 100).
#[must_use]
pub fn build_accept_children(accept: bool) -> Message {
Message::new().write_int32(100).write_bool(accept).clone()
}
#[must_use]
pub fn build_set_wait_port_message(port: u16) -> Message {