Skip to content

Commit 4737a36

Browse files
warusadurabilelmoussaoui
authored andcommitted
server: Track connected clients
And drop there related resources when they dissapear from the bus
1 parent e79e5f1 commit 4737a36

4 files changed

Lines changed: 86 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ rpassword = "7.4"
2323
serde.workspace = true
2424
sha2 = { version = "0.10", optional = true }
2525
tokio = { workspace = true, features = ["full"] }
26+
tokio-stream = "0.1"
2627
tracing = "0.1"
2728
tracing-subscriber.workspace = true
2829
zbus.workspace = true

server/src/service.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use oo7::{
1212
Key, Secret,
1313
};
1414
use tokio::sync::{Mutex, RwLock};
15+
use tokio_stream::StreamExt;
1516
use zbus::{
17+
names::{OwnedUniqueName, UniqueName},
1618
object_server::SignalEmitter,
1719
proxy::Defaults,
1820
zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Value},
@@ -46,6 +48,7 @@ impl Service {
4648
&self,
4749
algorithm: Algorithm,
4850
input: Value<'_>,
51+
#[zbus(header)] header: zbus::message::Header<'_>,
4952
#[zbus(object_server)] object_server: &zbus::ObjectServer,
5053
) -> Result<(OwnedValue, OwnedObjectPath), ServiceError> {
5154
let (public_key, aes_key) = match algorithm {
@@ -68,7 +71,13 @@ impl Service {
6871
}
6972
};
7073

71-
let session = Session::new(aes_key.map(Arc::new), self.clone()).await;
74+
let sender = header
75+
.sender()
76+
.ok_or_else(|| custom_service_error("Failed to get sender from header."))?;
77+
78+
tracing::info!("Client {} connected", sender);
79+
80+
let session = Session::new(aes_key.map(Arc::new), self.clone(), sender.to_owned()).await;
7281
let path = session.path().clone();
7382

7483
self.sessions
@@ -335,6 +344,40 @@ impl Service {
335344
.at(collection.path().clone(), collection)
336345
.await?;
337346

347+
let service = service.clone();
348+
tokio::spawn(async move { service.on_client_disconnect().await });
349+
Ok(())
350+
}
351+
352+
async fn on_client_disconnect(&self) -> zbus::Result<()> {
353+
let rule = zbus::MatchRule::builder()
354+
.msg_type(zbus::message::Type::Signal)
355+
.sender("org.freedesktop.DBus")?
356+
.interface("org.freedesktop.DBus")?
357+
.member("NameOwnerChanged")?
358+
.arg(2, "")?
359+
.build();
360+
let mut stream = zbus::MessageStream::for_match_rule(rule, &self.connection, None).await?;
361+
while let Some(message) = stream.try_next().await? {
362+
let Ok((_name, old_owner, new_owner)) =
363+
message
364+
.body()
365+
.deserialize::<(String, OwnedUniqueName, OwnedUniqueName)>()
366+
else {
367+
continue;
368+
};
369+
assert_eq!(new_owner, ""); // We enforce that in the matching rule
370+
if let Some(session) = self.session_from_sender(old_owner.as_ref()).await {
371+
match session.close().await {
372+
Ok(_) => tracing::info!(
373+
"Client {} disconnected. Session: {} closed.",
374+
old_owner,
375+
session.path()
376+
),
377+
Err(err) => tracing::error!("Failed to close session: {}", err),
378+
}
379+
}
380+
}
338381
Ok(())
339382
}
340383

@@ -423,6 +466,18 @@ impl Service {
423466
n_sessions
424467
}
425468

469+
async fn session_from_sender<'a>(&self, sender: UniqueName<'a>) -> Option<Session> {
470+
let sessions = self.sessions.lock().await;
471+
472+
for session in sessions.values() {
473+
if session.sender() == &sender {
474+
return Some(session.clone());
475+
}
476+
}
477+
478+
None
479+
}
480+
426481
pub async fn session(&self, path: &OwnedObjectPath) -> Option<Session> {
427482
self.sessions.lock().await.get(path).cloned()
428483
}

server/src/session.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::sync::Arc;
44

55
use oo7::{dbus::ServiceError, Key};
6-
use zbus::{interface, zvariant::OwnedObjectPath};
6+
use zbus::{interface, names::UniqueName, zvariant::OwnedObjectPath};
77

88
use crate::Service;
99

@@ -12,32 +12,42 @@ pub struct Session {
1212
aes_key: Option<Arc<Key>>,
1313
service: Service,
1414
path: OwnedObjectPath,
15+
sender: UniqueName<'static>,
1516
}
1617

1718
#[interface(name = "org.freedesktop.Secret.Session")]
1819
impl Session {
19-
pub async fn close(
20-
&self,
21-
#[zbus(object_server)] object_server: &zbus::ObjectServer,
22-
) -> Result<(), ServiceError> {
20+
pub async fn close(&self) -> Result<(), ServiceError> {
2321
self.service.remove_session(&self.path).await;
24-
object_server.remove::<Self, _>(&self.path).await?;
22+
self.service
23+
.object_server()
24+
.remove::<Self, _>(&self.path)
25+
.await?;
2526

2627
Ok(())
2728
}
2829
}
2930

3031
impl Session {
31-
pub async fn new(aes_key: Option<Arc<Key>>, service: Service) -> Self {
32+
pub async fn new(
33+
aes_key: Option<Arc<Key>>,
34+
service: Service,
35+
sender: UniqueName<'static>,
36+
) -> Self {
3237
let index = service.session_index().await;
3338
Self {
3439
path: OwnedObjectPath::try_from(format!("/org/freedesktop/secrets/session/s{index}"))
3540
.unwrap(),
3641
aes_key,
3742
service,
43+
sender,
3844
}
3945
}
4046

47+
pub fn sender(&self) -> &UniqueName<'static> {
48+
&self.sender
49+
}
50+
4151
pub fn path(&self) -> &OwnedObjectPath {
4252
&self.path
4353
}

0 commit comments

Comments
 (0)