Skip to content

Commit

Permalink
Merge pull request #51 from windy1/feature/event-loop-lifetime
Browse files Browse the repository at this point in the history
Remove lifetime specifier from EventLoop; use Rcs to handle drop order
  • Loading branch information
windy1 authored Jan 28, 2024
2 parents 6fba0b5 + ecb1db4 commit 6e5a27a
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 76 deletions.
44 changes: 24 additions & 20 deletions zeroconf/src/avahi/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use std::{fmt, ptr};
#[derive(Debug)]
pub struct AvahiMdnsBrowser {
context: Box<AvahiBrowserContext>,
client: Option<ManagedAvahiClient>,
client: Option<Rc<ManagedAvahiClient>>,
poll: Option<Rc<ManagedAvahiSimplePoll>>,
}

Expand Down Expand Up @@ -77,21 +77,30 @@ impl TMdnsBrowser for AvahiMdnsBrowser {

self.poll = Some(Rc::new(ManagedAvahiSimplePoll::new()?));

self.client = Some(ManagedAvahiClient::new(
self.client = Some(Rc::new(ManagedAvahiClient::new(
ManagedAvahiClientParams::builder()
.poll(self.poll.as_ref().unwrap().inner())
.poll(self.poll.as_ref().unwrap().clone())
.flags(AvahiClientFlags(0))
.callback(Some(client_callback))
.userdata(self.context.as_raw())
.build()?,
)?);
)?));

self.context.client = self.client.clone();

unsafe {
if let Err(e) = create_browser(&mut self.context) {
self.context.invoke_callback(Err(e));
}
}

Ok(EventLoop::new(self.poll.as_ref().unwrap().clone()))
}
}

#[derive(FromRaw, AsRaw)]
struct AvahiBrowserContext {
client: Option<Rc<ManagedAvahiClient>>,
resolvers: ServiceResolverSet,
service_discovered_callback: Option<Box<ServiceDiscoveredCallback>>,
user_context: Option<Arc<dyn Any>>,
Expand All @@ -103,6 +112,7 @@ struct AvahiBrowserContext {
impl AvahiBrowserContext {
fn new(kind: CString, interface_index: AvahiIfIndex) -> Self {
Self {
client: None,
resolvers: ServiceResolverSet::default(),
service_discovered_callback: None,
user_context: None,
Expand Down Expand Up @@ -136,23 +146,12 @@ unsafe extern "C" fn client_callback(
) {
let context = AvahiBrowserContext::from_raw(userdata);

match state {
avahi_sys::AvahiClientState_AVAHI_CLIENT_S_RUNNING => {
if let Err(e) = create_browser(client, context) {
context.invoke_callback(Err(e));
}
}
avahi_sys::AvahiClientState_AVAHI_CLIENT_FAILURE => {
context.invoke_callback(Err(avahi_util::get_last_error(client).into()))
}
_ => {}
if state == avahi_sys::AvahiClientState_AVAHI_CLIENT_FAILURE {
context.invoke_callback(Err(avahi_util::get_last_error(client).into()));
}
}

unsafe fn create_browser(
client: *mut AvahiClient,
context: &mut AvahiBrowserContext,
) -> Result<()> {
unsafe fn create_browser(context: &mut AvahiBrowserContext) -> Result<()> {
context.browser = Some(ManagedAvahiServiceBrowser::new(
ManagedAvahiServiceBrowserParams::builder()
.interface(context.interface_index)
Expand All @@ -162,7 +161,7 @@ unsafe fn create_browser(
.flags(0)
.callback(Some(browse_callback))
.userdata(context.as_raw())
.client(client)
.client(Rc::clone(context.client.as_ref().unwrap()))
.build()?,
)?);

Expand Down Expand Up @@ -205,9 +204,14 @@ unsafe fn handle_browser_new(
) -> Result<()> {
let raw_context = context.as_raw();

let client = context
.client
.as_ref()
.ok_or("expected initialized client")?;

context.resolvers.insert(ManagedAvahiServiceResolver::new(
ManagedAvahiServiceResolverParams::builder()
.client(context.browser.as_ref().unwrap().get_client())
.client(client.clone())
.interface(interface)
.protocol(protocol)
.name(name)
Expand Down
13 changes: 8 additions & 5 deletions zeroconf/src/avahi/client.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Rust friendly `AvahiClient` wrappers/helpers

use super::avahi_util;
use std::rc::Rc;

use super::{avahi_util, poll::ManagedAvahiSimplePoll};
use crate::ffi::c_str;
use crate::Result;
use avahi_sys::{
avahi_client_free, avahi_client_get_host_name, avahi_client_new, avahi_simple_poll_get,
AvahiClient, AvahiClientCallback, AvahiClientFlags, AvahiSimplePoll,
AvahiClient, AvahiClientCallback, AvahiClientFlags,
};
use libc::{c_int, c_void};

Expand All @@ -16,6 +18,7 @@ use libc::{c_int, c_void};
#[derive(Debug)]
pub struct ManagedAvahiClient {
pub(crate) inner: *mut AvahiClient,
_poll: Rc<ManagedAvahiSimplePoll>,
}

impl ManagedAvahiClient {
Expand All @@ -33,7 +36,7 @@ impl ManagedAvahiClient {

let inner = unsafe {
avahi_client_new(
avahi_simple_poll_get(poll),
avahi_simple_poll_get(poll.inner()),
flags,
callback,
userdata,
Expand All @@ -46,7 +49,7 @@ impl ManagedAvahiClient {
}

match err {
0 => Ok(Self { inner }),
0 => Ok(Self { inner, _poll: poll }),
_ => Err(format!(
"could not initialize AvahiClient: {}",
avahi_util::get_error(err)
Expand Down Expand Up @@ -76,7 +79,7 @@ impl Drop for ManagedAvahiClient {
/// [`avahi_client_new()`]: https://avahi.org/doxygen/html/client_8h.html#a07b2a33a3e7cbb18a0eb9d00eade6ae6
#[derive(Builder, BuilderDelegate)]
pub struct ManagedAvahiClientParams {
poll: *mut AvahiSimplePoll,
poll: Rc<ManagedAvahiSimplePoll>,
flags: AvahiClientFlags,
callback: AvahiClientCallback,
userdata: *mut c_void,
Expand Down
16 changes: 11 additions & 5 deletions zeroconf/src/avahi/entry_group.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Rust friendly `AvahiEntryGroup` wrappers/helpers

use super::string_list::ManagedAvahiStringList;
use std::rc::Rc;

use super::{client::ManagedAvahiClient, string_list::ManagedAvahiStringList};
use crate::avahi::avahi_util;
use crate::ffi::UnwrapMutOrNull;
use crate::Result;
Expand All @@ -19,6 +21,7 @@ use libc::{c_char, c_void};
#[derive(Debug)]
pub struct ManagedAvahiEntryGroup {
inner: *mut AvahiEntryGroup,
_client: Rc<ManagedAvahiClient>,
}

impl ManagedAvahiEntryGroup {
Expand All @@ -31,13 +34,16 @@ impl ManagedAvahiEntryGroup {
userdata,
}: ManagedAvahiEntryGroupParams,
) -> Result<Self> {
let inner = unsafe { avahi_entry_group_new(client, callback, userdata) };
let inner = unsafe { avahi_entry_group_new(client.inner, callback, userdata) };

if inner.is_null() {
let err = avahi_util::get_error(unsafe { avahi_client_errno(client) });
let err = avahi_util::get_error(unsafe { avahi_client_errno(client.inner) });
Err(format!("could not initialize AvahiEntryGroup: {}", err).into())
} else {
Ok(Self { inner })
Ok(Self {
inner,
_client: client,
})
}
}

Expand Down Expand Up @@ -156,7 +162,7 @@ impl Drop for ManagedAvahiEntryGroup {
/// [avahi_entry_group_new()]: https://avahi.org/doxygen/html/publish_8h.html#abb17598f2b6ec3c3f69defdd488d568c
#[derive(Builder, BuilderDelegate)]
pub struct ManagedAvahiEntryGroupParams {
client: *mut AvahiClient,
client: Rc<ManagedAvahiClient>,
callback: AvahiEntryGroupCallback,
userdata: *mut c_void,
}
Expand Down
6 changes: 2 additions & 4 deletions zeroconf/src/avahi/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
use super::poll::ManagedAvahiSimplePoll;
use crate::event_loop::TEventLoop;
use crate::Result;
use std::marker::PhantomData;
use std::rc::Rc;
use std::time::Duration;

#[derive(new)]
pub struct AvahiEventLoop<'a> {
pub struct AvahiEventLoop {
poll: Rc<ManagedAvahiSimplePoll>,
phantom: PhantomData<&'a ManagedAvahiSimplePoll>,
}

impl<'a> TEventLoop for AvahiEventLoop<'a> {
impl TEventLoop for AvahiEventLoop {
/// Polls for new events.
///
/// Internally calls `ManagedAvahiSimplePoll::iterate(..)`.
Expand Down
21 changes: 18 additions & 3 deletions zeroconf/src/avahi/raw_browser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Rust friendly `AvahiServiceBrowser` wrappers/helpers

use std::rc::Rc;

use crate::Result;
use avahi_sys::{
avahi_service_browser_free, avahi_service_browser_get_client, avahi_service_browser_new,
Expand All @@ -8,13 +10,16 @@ use avahi_sys::{
};
use libc::{c_char, c_void};

use super::client::ManagedAvahiClient;

/// Wraps the `AvahiServiceBrowser` type from the raw Avahi bindings.
///
/// This struct allocates a new `*mut AvahiServiceBrowser` when `ManagedAvahiServiceBrowser::new()`
/// is invoked and calls the Avahi function responsible for freeing the client on `trait Drop`.
#[derive(Debug)]
pub struct ManagedAvahiServiceBrowser {
inner: *mut AvahiServiceBrowser,
_client: Rc<ManagedAvahiClient>,
}

impl ManagedAvahiServiceBrowser {
Expand All @@ -34,14 +39,24 @@ impl ManagedAvahiServiceBrowser {
) -> Result<Self> {
let inner = unsafe {
avahi_service_browser_new(
client, interface, protocol, kind, domain, flags, callback, userdata,
client.inner,
interface,
protocol,
kind,
domain,
flags,
callback,
userdata,
)
};

if inner.is_null() {
Err("could not initialize Avahi service browser".into())
} else {
Ok(Self { inner })
Ok(Self {
inner,
_client: client,
})
}
}

Expand Down Expand Up @@ -69,7 +84,7 @@ impl Drop for ManagedAvahiServiceBrowser {
/// [`avahi_service_browser_new()`]: https://avahi.org/doxygen/html/lookup_8h.html#a52d55a5156a7943012d03e6700880d2b
#[derive(Builder, BuilderDelegate)]
pub struct ManagedAvahiServiceBrowserParams {
client: *mut AvahiClient,
client: Rc<ManagedAvahiClient>,
interface: AvahiIfIndex,
protocol: AvahiProtocol,
kind: *const c_char,
Expand Down
26 changes: 20 additions & 6 deletions zeroconf/src/avahi/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

use crate::Result;
use avahi_sys::{
avahi_service_resolver_free, avahi_service_resolver_new, AvahiClient, AvahiIfIndex,
AvahiLookupFlags, AvahiProtocol, AvahiServiceResolver, AvahiServiceResolverCallback,
avahi_service_resolver_free, avahi_service_resolver_new, AvahiIfIndex, AvahiLookupFlags,
AvahiProtocol, AvahiServiceResolver, AvahiServiceResolverCallback,
};
use libc::{c_char, c_void};
use std::collections::HashMap;
use std::{collections::HashMap, rc::Rc};

use super::client::ManagedAvahiClient;

/// Wraps the `AvahiServiceResolver` type from the raw Avahi bindings.
///
Expand All @@ -16,6 +18,7 @@ use std::collections::HashMap;
#[derive(Debug)]
pub struct ManagedAvahiServiceResolver {
inner: *mut AvahiServiceResolver,
_client: Rc<ManagedAvahiClient>,
}

impl ManagedAvahiServiceResolver {
Expand All @@ -37,15 +40,26 @@ impl ManagedAvahiServiceResolver {
) -> Result<Self> {
let inner = unsafe {
avahi_service_resolver_new(
client, interface, protocol, name, kind, domain, aprotocol, flags, callback,
client.inner,
interface,
protocol,
name,
kind,
domain,
aprotocol,
flags,
callback,
userdata,
)
};

if inner.is_null() {
Err("could not initialize AvahiServiceResolver".into())
} else {
Ok(Self { inner })
Ok(Self {
inner,
_client: client,
})
}
}
}
Expand All @@ -64,7 +78,7 @@ impl Drop for ManagedAvahiServiceResolver {
/// [`avahi_service_resolver_new()`]: https://avahi.org/doxygen/html/lookup_8h.html#a904611a4134ceb5919f6bb637df84124
#[derive(Builder, BuilderDelegate)]
pub struct ManagedAvahiServiceResolverParams {
client: *mut AvahiClient,
client: Rc<ManagedAvahiClient>,
interface: AvahiIfIndex,
protocol: AvahiProtocol,
name: *const c_char,
Expand Down
Loading

0 comments on commit 6e5a27a

Please sign in to comment.