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:
@@ -175,32 +175,46 @@ pub struct ServerActor {
|
||||
shared_folder_count: u32,
|
||||
shared_file_count: u32,
|
||||
session: SessionWatch,
|
||||
/// The name we logged in as, once a login has been asked for.
|
||||
username: String,
|
||||
}
|
||||
|
||||
/// The messages a client sends right after a successful login: its shared-file
|
||||
/// counts, distributed-network opt-out, online status, and (when listening) the
|
||||
/// port peers should connect to. Kept as a free function so it can be tested
|
||||
/// without a live connection.
|
||||
/// counts, its distributed-network stance, online status, and (when listening)
|
||||
/// the port peers should connect to. Kept as a free function so it can be
|
||||
/// tested without a live connection.
|
||||
fn post_login_messages(
|
||||
enable_listen: bool,
|
||||
listen_port: u16,
|
||||
shared_folders: u32,
|
||||
shared_files: u32,
|
||||
own_username: &str,
|
||||
) -> Vec<Message> {
|
||||
let mut messages = vec![
|
||||
MessageFactory::build_shared_folders_message(
|
||||
shared_folders,
|
||||
shared_files,
|
||||
),
|
||||
MessageFactory::build_no_parent_message(),
|
||||
MessageFactory::build_set_status_message(2),
|
||||
];
|
||||
messages.splice(1..1, parentless_stance(own_username));
|
||||
if enable_listen {
|
||||
messages.push(MessageFactory::build_set_wait_port_message(listen_port));
|
||||
}
|
||||
messages
|
||||
}
|
||||
|
||||
/// What a leaf tells the server while it has no parent: it is its own branch
|
||||
/// root at level 0 and takes no children. Nicotine+ sends the same four.
|
||||
fn parentless_stance(own_username: &str) -> Vec<Message> {
|
||||
vec![
|
||||
MessageFactory::build_have_no_parent(true),
|
||||
MessageFactory::build_branch_root(own_username),
|
||||
MessageFactory::build_branch_level(0),
|
||||
MessageFactory::build_accept_children(false),
|
||||
]
|
||||
}
|
||||
|
||||
impl ServerActor {
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
@@ -228,6 +242,7 @@ impl ServerActor {
|
||||
shared_folder_count,
|
||||
shared_file_count,
|
||||
session: SessionWatch::default(),
|
||||
username: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,6 +565,7 @@ impl ServerActor {
|
||||
self.listen_port,
|
||||
self.shared_folder_count,
|
||||
self.shared_file_count,
|
||||
&self.username,
|
||||
) {
|
||||
self.send_message(msg);
|
||||
}
|
||||
@@ -621,6 +637,7 @@ impl ServerActor {
|
||||
version: ClientVersion,
|
||||
response: std::sync::mpsc::Sender<Result<bool, SoulseekRs>>,
|
||||
) {
|
||||
self.username.clone_from(&username);
|
||||
if self.stream.is_none() && !self.initiate_connection() {
|
||||
let _ = response.send(Err(SoulseekRs::NotConnected));
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user