fix(daemon): correct the published contract and harden the control socket
A review pass over the diff found seventeen confirmed defects. The worst was
the contract itself: every method's parameters were published as a single
descriptor named `params`, so a client generated from openrpc.json sent
{"params":{"params":{…}}} and every call failed -32602. Parameters are now
published per field, with a test asserting the published names are the keys
the daemon actually deserializes.
Security and lifecycle:
- download.start no longer lets a caller name a directory, which was an
arbitrary write on the daemon's host.
- The Unix socket is bound under a temporary name and renamed into place; it
was briefly connectable by any local user between bind and chmod, and on
that transport connecting is authenticating.
- Pre-auth reads are capped at 1 MiB with a 30s handshake timeout, and
connections are capped, so an unauthenticated peer cannot exhaust memory or
threads.
- A read error no longer returns past the hub unsubscribe, which leaked a
subscriber and two threads per occurrence.
- A client whose event queue fills is now actually disconnected. It used to be
dropped from the fan-out and left connected, working on but blind to every
event after — the documentation already promised otherwise.
- A client whose daemon vanishes mid-transfer is told at once instead of
waiting out its full timeout and reporting a misleading "gave up".
Contract accuracy: errors carry an explicit null id (a missing one reads as a
notification and gets dropped), a second auth answers with the published
shape, and nullable fields are sent rather than omitted so a generated client
sees one shape.
Also splits proto.rs and server.rs, whose concerns had diverged, and applies
the review's simplifications.
This commit is contained in:
+13
-11
@@ -39,11 +39,16 @@ pub trait SessionApi: Send + Sync {
|
||||
fn listen_port(&self) -> Option<u16>;
|
||||
fn session_loss(&self) -> Option<SessionLoss>;
|
||||
|
||||
/// Search and wait out the window. Every implementation is
|
||||
/// `search_with_cancel` with nothing to cancel on.
|
||||
fn search(
|
||||
&self,
|
||||
query: &str,
|
||||
timeout: Duration,
|
||||
) -> Result<Vec<SearchResult>>;
|
||||
) -> Result<Vec<SearchResult>> {
|
||||
self.search_with_cancel(query, timeout, None)
|
||||
}
|
||||
|
||||
fn search_with_cancel(
|
||||
&self,
|
||||
query: &str,
|
||||
@@ -91,7 +96,8 @@ pub trait SessionApi: Send + Sync {
|
||||
fn room_members(&self, room: &str) -> Vec<String>;
|
||||
fn take_room_events(&self) -> Vec<RoomEvent>;
|
||||
|
||||
fn send_private_message(&self, username: &str, message: &str) -> Result<()>;
|
||||
fn send_private_message(&self, username: &str, message: &str)
|
||||
-> Result<()>;
|
||||
fn take_private_messages(&self) -> Vec<UserMessage>;
|
||||
|
||||
fn browse_user(&self, username: &str) -> Result<()>;
|
||||
@@ -133,14 +139,6 @@ impl SessionApi for Client {
|
||||
Self::session_loss(self)
|
||||
}
|
||||
|
||||
fn search(
|
||||
&self,
|
||||
query: &str,
|
||||
timeout: Duration,
|
||||
) -> Result<Vec<SearchResult>> {
|
||||
Self::search(self, query, timeout)
|
||||
}
|
||||
|
||||
fn search_with_cancel(
|
||||
&self,
|
||||
query: &str,
|
||||
@@ -266,7 +264,11 @@ impl SessionApi for Client {
|
||||
Self::take_room_events(self)
|
||||
}
|
||||
|
||||
fn send_private_message(&self, username: &str, message: &str) -> Result<()> {
|
||||
fn send_private_message(
|
||||
&self,
|
||||
username: &str,
|
||||
message: &str,
|
||||
) -> Result<()> {
|
||||
Self::send_private_message(self, username, message)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user