Rewrite in pure Swift - #8
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the libdbus wrapper with a pure-Swift implementation of the D-Bus protocol. No C library, no
CDBussystem-library package, noOpaquePointer.Why
The wrapper layer held several defects that were artifacts of wrapping C rather than of D-Bus itself: borrowed messages were never returned to the connection,
DBusPendingCallretained itself and could never deallocate,DBusConnection.inittrapped on a NULL handle before it could throw, and the header-field getters calledfatalError()on remote-controlled input. Separately,variantanddict— the two types every service uses throughorg.freedesktop.DBus.Properties— were unimplemented and crashed on receipt.Rewriting in Swift removes that class of bug by construction. It also drops the libdbus build dependency, which was emitting
couldn't find pc file for dbus-1.0, and lets the package adopt Swift 6 concurrency.What is implemented
Wire format. Marshalling and unmarshalling in both byte orders, with the full alignment table, the 128 MiB message cap, and required-zero padding on read. Empty arrays encode from the declared element type rather than inferring it from the (absent) elements.
variantanddictionaryare real argument cases now.Transport. Unix sockets including the Linux abstract namespace, plus TCP and nonce-TCP.
Socket.UnixSocketAddressstores aFilePathand writessun_pathviawithPlatformString, so it cannot express an abstract address; this package defines its own.Authentication. SASL
EXTERNAL,ANONYMOUSandDBUS_COOKIE_SHA1, with SHA-1 and a keyring parser. Cookie contexts are validated as bus-name elements so a hostile server cannot escape the keyring directory with a relative path.Client.
DBusConnectionis an actor. A read loop unmarshals frames and resumes per-serial continuations, sosend(_:)is a plainasync throwscall andDBusPendingCallis gone. Serials wrap to 1, never 0. Malformed input throws; nothing on a decode path traps.Bus API.
Hello, name registration and release, ownership queries,ListNames,GetNameOwner, connection credentials, bus ID.Signals. Match rules with correct value escaping, subscriptions delivered as
AsyncStream, reference-counted bus-side match rules shared between subscriptions on one connection, and local demultiplexing so each subscription only sees what its own rule matches.Server side. Object export with method dispatch, and the standard
Peer,IntrospectableandPropertiesinterfaces includingPropertiesChanged.File descriptor passing.
UNIX_FDmarshals as an index into the out-of-band descriptor array, as the specification requires. TheUNIX_FDSheader field is derived from what marshalling actually produced, so it cannot disagree with the body. Descriptors ride along viaSCM_RIGHTS.Introspection. XML generation, and parsing into a node model. Parsing uses a small XML reader in-package rather than pulling in
FoundationXMLor libxml2.API
Public value types are preserved:
DBusSignature,DBusObjectPath,DBusInterface,DBusMember,DBusBusName,DBusMessageArgument,DBusError.DBusMessagebecomes aSendablestruct instead of a class wrapping a pointer, andMethodCall/Signalgain public initializers — the synthesized memberwise ones were internal, soDBusMessage.init(methodCall:)was unreachable from client code.Removed:
PendingCall,MessageIterator,Boolean(dbus_bool_t),Timeout(nowDuration),DispatchStatusandHandlerResult(libdbus main-loop concepts with no analogue here).Validation
The validators no longer delegate to libdbus, so they are solely responsible for correctness now. Three real bugs surfaced once the existing tests were fixed to actually run every case —
testInvalidwas a loop whosecatchended inreturn, so exactly one of nine object paths and one of twelve signatures was ever checked:a{vs}was accepted.DictionaryType.init?only rejected containers, and a variant is not a container by that definition. Dictionary keys are now checked against an explicit basic-type list.org.7zip.Pluginwas accepted. Interface elements must not begin with a digit./com//examplewas accepted.parsesplit withomittingEmptySubsequences: true.Length caps now count UTF-8 bytes rather than
Characters, and container nesting is capped at 32 levels.Tests
205 tests across 23 suites, migrated from XCTest to Swift Testing.
Marshalling is checked against hand-computed byte vectors in both endiannesses, not only round trips — a marshaller can be self-consistently wrong. Live tests run against a real session bus and are reported as skipped, not passed, when none is available. The TCP tests start a
dbus-daemonconfigured forANONYMOUS, which also exercises the mechanism fallback for real.Dependency
Building this out surfaced four bugs in
PureSwift/Socket, all fixed there rather than worked around here:SCM_RIGHTSsupport, plus a deferred poll result being applied to a reused descriptor number.POLLHUPacted on after the socket had connected. Together these were the intermittentESHUTDOWNon a fresh connection.EWOULDBLOCKto the caller as a spurious failure.Package.swifttherefore tracksPureSwift/Socketat branchfix/stale-readinessuntil #27 merges, at which point it returns tomain. That is isolated in a single commit.Continuous integration
.github/workflows/swift.ymlbuilds macOS and Linux on both x86_64 and arm64.Linux runs the full suite — 205 tests — on Swift 6.2.3 and 6.3.3, in debug and release, statically and as a dynamic library, under a real session bus started with
dbus-run-session. Without a bus the live tests report as skipped rather than passing, which would make the run meaningless. macOS is a compile target: it builds the library and the tests, so they cannot rot out of compiling on Darwin, but does not run them, since D-Bus is not part of the system there.All 20 jobs pass.
Not implemented
Code generation from introspection XML. Parsing landed; generation did not.