Skip to content

introduce Zeroconf AFP service discovery#300

Merged
andylemin merged 1 commit into
mainfrom
zeroconf
Jul 21, 2026
Merged

introduce Zeroconf AFP service discovery#300
andylemin merged 1 commit into
mainfrom
zeroconf

Conversation

@rdmark

@rdmark rdmark commented Jul 19, 2026

Copy link
Copy Markdown
Member

Add a provider-neutral discovery layer with native Avahi and DNS-SD backends, plus a stub backend so builds continue to work without Zeroconf dependencies. Normalize browse, resolve, snapshot, endpoint, and TXT data across providers.

Expose bounded discovery through 'afp_client discover' with human-readable, verbose, and JSON output. Add a live service picker to afpcmd and support exact advertised service lookup for mounts, including authenticated volume listing.

Browse companion _device-info._tcp advertisements alongside AFP services, associate matching records, and show their model TXT value in the MODEL column. (Note that we don't see _device-info._tcp advertisements from Apple AFP servers.) Retain standalone device-info records in verbose output for diagnostics.

Detect and select discovery providers in Meson, install the new utility and man page, and extend CI dependencies. Document the user and developer workflows and cover discovery events, output, service resolution, ambiguity, and picker behavior with deterministic fake-backend tests.

Rework the afpcmd volume picker TUI to align with the new Zeroconf selection menu.

Usage examples:

$ afp_client discover
NAME                           TARGET                                PORT   MODEL                   
Daniels-MacBook-Pro            Daniels-MacBook-Pro.local              548   -                       
Time Capsule                   Time-Capsule.local                     548   -                       
afpfs_testsrv                  alien.local                            548   Tower 
$ afpcmd -b
Discovered AFP servers

  1  Daniels-MacBook-Pro
  2  Time Capsule
  3  afpfs_testsrv

  q  Quit

afpcmd: 3
Username (blank for guest): myuser
Password: 
Connected to server afpfs_testsrv

Available volumes on afpfs_testsrv:

  1  afpfs_test
  2  DeLorean
  3  My AFP Vol
  4  myuser's home

  q  Quit

afpcmd: 1
Attached to volume afpfs_test
afpcmd:

@rdmark rdmark changed the title instroduce Zeroconf AFP service discovery introduce Zeroconf AFP service discovery Jul 19, 2026
@rdmark
rdmark force-pushed the zeroconf branch 2 times, most recently from 8d94578 to 5794834 Compare July 19, 2026 14:04
@rdmark
rdmark marked this pull request as ready for review July 19, 2026 14:05
@rdmark
rdmark requested a review from andylemin as a code owner July 19, 2026 14:05
@augmentcode

augmentcode Bot commented Jul 19, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR adds Zeroconf-based AFP service discovery across the project, with a provider-neutral core and multiple backend implementations.

Changes:

  • Introduces a normalized discovery API (discovery/) with Avahi, DNS-SD, and stub backends
  • Adds a shared client layer for bounded browse, resolve, snapshot, endpoint selection, and TXT handling
  • Exposes discovery via afp_client discover and a new standalone afpdiscover utility (when built with Zeroconf)
  • Adds an interactive live service picker to afpcmd (--browse)
  • Extends afp_client mount to resolve and mount/list services by exact advertised instance name (--service/--volume)
  • Updates Meson build detection/options for Zeroconf and installs the new man page
  • Extends CI and test infrastructure, adding deterministic fake-backend tests for discovery behavior/output

Technical Notes: Provider selection is done at build time (preferring DNS-SD on macOS and Avahi elsewhere), while the stub backend preserves builds without Zeroconf dependencies; frontends consume a consistent service/endpoint model and error semantics.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread cmdline/cmdline_main.c
Comment thread discovery/backend_dnssd.c Outdated
Comment thread discovery/backend_avahi.c Outdated
@andylemin

andylemin commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Great to see, but why afp_client discover and afpdiscover?

This creates confusion about why there are two, what's the differences, when should you use one over the other..

@andylemin

andylemin commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Best to have only afp_client discover, to keep everything under one organised namespace (better for humans and tools).

I realise it's probably because the code is standalone (great) but I don't think that warrants random duplicate entry points?

It's a bit of a pet hate 🤣

@rdmark

rdmark commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

fair point, the problem is that afp_client is part of the FUSE client and I don't think we want to gate this functionality behind libfuse availability

afpdiscover is a tiny wrapper that calls the exact same function as afp_client discover but doesn't have a libfuse dependency

the semantics of afp_client are too deeply coupled with FUSE to make it into a general-purpose tool, I think, so perhaps removing the afp_client discover subcommand is the right choice since zeroconf is the odd one out arguably

@andylemin

Copy link
Copy Markdown
Contributor

That does make sense.

My thinking is; what about the next command set? Where would those live?

I'm trying to think about a long term solution where everything (now and future) can be accessed in one place and users only have to remember one command.

The client is something that users will interact with a lot, so simplicity and an intuitive structure is very important - more important than code convenience.

I often have to push teams to prioritise the user experience over the developer experience.

Could we rename the libfuse entry, and make afp_client the one and only thin wrapper instead, which then redirects to the various backends as required.

This would be easier to maintain in the long run?

Now is the best time to get this right, before it becomes harder to change?

@rdmark

rdmark commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

right now is indeed the ideal time to make broader changes!

we are talking about the same thing, but I like to say user ergonomics over developer ergonomics :)

at the same time, I want to keep the Unix philosophy in mind: of having small programs that does one or a handful of things very well, and avoid monoliths overloaded with functionality

off the top of my head, we could for instance rename the current afp_client (which is actually a symlink to mount_afpfs) to afpfs (as in "AFP FUSE") and then repurpose afp_client for general purpose operations

now the question is, what operations should the new afp_client be responsible for? discover is obvious, perhaps exit and status -- anything else?

one complication is that we have two types of AFP session daemons, the afpfsd FUSE daemon and afpsld Stateless daemon, which have different state machines and use different sockets. I'm thinking exit and status would operate on all running forks of both types of daemons by default, or a specific daemon if you pass the socket path as a positional argument

thoughts?

@andylemin

andylemin commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

we are talking about the same thing, but I like to say user ergonomics over developer ergonomics :)

Haha indeed 🙂

at the same time, I want to keep the Unix philosophy in mind: of having small programs that does one or a handful of things very well, and avoid monoliths overloaded with functionality

True, but this is not program code, this is the user interface which should be thin on business logic and broad in coverage - so there is no monolith.

To your point, the different things the CLI can call should be separated where possible.

one complication is that we have two types of AFP session daemons, the afpfsd FUSE daemon and afpsld Stateless daemon, which have different state machines and use different sockets. I'm thinking exit and status would operate on all running forks of both types of daemons by default, or a specific daemon if you pass the socket path as a positional argument

Perfect! This is a great example of why the clients CLI should be a wrapper that calls the different backends depending on the namespace provided to the CLI command?

afp_client cmd <op> ... (stateless daemon namespace)?
afp_client <op> (fuse daemon - default namespace)?
afp_client discover (discover namespace)?
etc..

This should provide a structure to apply future advanced configuration options and spec stuff?

We should be careful of having a flat hierarchy, which is why I'm thinking cmd for all the stateless commands?

Is there are afpc command? Can't remember if you said this is too close to other trademarks? Or maybe afpcli?

afp_client is long and typing the _ on the keyboard is difficult to type quickly

Add a provider-neutral discovery layer with native Avahi and DNS-SD
backends, plus a stub backend so builds continue to work without
Zeroconf dependencies. Normalize browse, resolve, snapshot, endpoint,
and TXT data across providers.

Expose bounded discovery through 'afp_client discover' with
human-readable, verbose, and JSON output. Add a live service picker
to afpcmd and support exact advertised service lookup for mounts,
including authenticated volume listing.

Browse companion _device-info._tcp advertisements alongside AFP services,
associate matching records, and show their model TXT value in the MODEL
column. Retain standalone device-info records in verbose output for
diagnostics.

Detect and select discovery providers in Meson, install the new utility
and man page, and extend CI dependencies. Document the user and
developer workflows and cover discovery events, output, service
resolution, ambiguity, and picker behavior with deterministic
fake-backend tests.

Rework the afpcmd volume picker TUI to align with the new Zeroconf
selection menu.
@rdmark

rdmark commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

alright, for starters the stand-alone afpdiscover binary has been purged, keeping afp_client discover as the only entry point

I propose we wrap up and merge this PR now, and then pivot to restructuring afp_client in a future PR!

@sonarqubecloud

Copy link
Copy Markdown

@andylemin
andylemin merged commit 2335674 into main Jul 21, 2026
23 checks passed
@andylemin

Copy link
Copy Markdown
Contributor

@rdmark Agreed. Thanks for discussing it...

Is there are afpc command? Can't remember if you said this is too close to other trademarks? Or maybe afpcli?

afp_client is long and typing the _ on the keyboard is difficult to type quickly

@rdmark
rdmark deleted the zeroconf branch July 22, 2026 05:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants