Skip to content

Commit

Permalink
Use stable hash to determine if configuration number needs bumping
Browse files Browse the repository at this point in the history
The old implementation would increase the configuration number on each
server restart. This caused issues with e.g. Homepod that would reset
room configurations. We need a stable hash that is the same accross reboots
and maybe even hardware. We don't need a good distribution of this hash, but
importantly a hash that is unique for changes to device configuration.
  • Loading branch information
Bouke committed Nov 12, 2018
1 parent 60d7875 commit 30e8c26
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Sources/HAP/Server/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ extension Device {
// must be unique for the lifetime of the server/ client pairing.
internal var aidForAccessorySerialNumber = [String: InstanceID]()

// Hash of the attached accessories, services and characteristics. Used
// to assert if the current configuration number should be updated after
// initializing / modifying list of accessories.
internal var stableHash: Int = 0

private var aidGenerator = AIDGenerator()

// The next aid - should be checked against existing devices to ensure it is unique
Expand Down
22 changes: 21 additions & 1 deletion Sources/HAP/Server/Device.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,11 @@ public class Device {
/// - write the configuration to storage
/// - notify interested parties of the change
func updatedConfiguration() {
configuration.number = configuration.number &+ 1
var newStableHash = generateStableHash()
if newStableHash != configuration.stableHash {
configuration.number = configuration.number &+ 1
configuration.stableHash = newStableHash
}
if configuration.number < 1 {
configuration.number = 1
}
Expand All @@ -247,6 +251,22 @@ public class Device {
notifyConfigurationChange()
}

/// Generate uniqueness hash for device configuration, used to determine
/// if the configuration number should be updated.
func generateStableHash() -> Int {
var hash = 0
for accessory in accessories {
hash ^= 17 &* accessory.aid
for service in accessory.services {
hash ^= 19 &* service.iid
for characteristic in service.characteristics {
hash ^= 23 &* characteristic.iid
}
}
}
return hash
}

/// Notify the server that the config record has changed
func notifyConfigurationChange() {
server?.updateDiscoveryRecord()
Expand Down

0 comments on commit 30e8c26

Please sign in to comment.