Remove protocol versioning and handshake logic (#433)

Simplified the protocol by removing version negotiation and handshake sequences.
All devices now use protocol version 1 without negotiation. This eliminates
unnecessary connection overhead and complexity while maintaining full
compatibility across the network.

Changes:
- Removed versionHello and versionAck message types
- Simplified connection flow to use announce packets only
- Removed version negotiation state tracking
- Cleaned up handshake timeout logic
- Reduced connection establishment overhead

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2025-08-12 02:24:34 +02:00
committed by GitHub
co-authored by jack
parent 3226b9cd14
commit 7a7c89e689
4 changed files with 302 additions and 706 deletions
@@ -233,8 +233,6 @@ protocol BinaryEncodable {
enum BinaryMessageType: UInt8 {
case deliveryAck = 0x01
case readReceipt = 0x02
case versionHello = 0x07
case versionAck = 0x08
case noiseIdentityAnnouncement = 0x09
case noiseMessage = 0x0A
}
+2 -2
View File
@@ -223,8 +223,8 @@ struct BinaryProtocol {
guard offset + 1 <= unpaddedData.count else { return nil }
let version = unpaddedData[offset]; offset += 1
// Check if version is supported
guard ProtocolVersion.isSupported(version) else {
// Check if version is 1 (only supported version)
guard version == 1 else {
return nil
}
-234
View File
@@ -152,10 +152,6 @@ enum MessageType: UInt8 {
case noiseEncrypted = 0x12 // Noise encrypted transport message
case noiseIdentityAnnounce = 0x13 // Announce static public key for discovery
// Protocol version negotiation
case versionHello = 0x20 // Initial version announcement
case versionAck = 0x21 // Version acknowledgment
// Protocol-level acknowledgments
case protocolAck = 0x22 // Generic protocol acknowledgment
case protocolNack = 0x23 // Negative acknowledgment (failure)
@@ -181,8 +177,6 @@ enum MessageType: UInt8 {
case .noiseHandshakeResp: return "noiseHandshakeResp"
case .noiseEncrypted: return "noiseEncrypted"
case .noiseIdentityAnnounce: return "noiseIdentityAnnounce"
case .versionHello: return "versionHello"
case .versionAck: return "versionAck"
case .protocolAck: return "protocolAck"
case .protocolNack: return "protocolNack"
case .systemValidation: return "systemValidation"
@@ -917,234 +911,6 @@ struct PeerIdentityBinding {
}
}
// MARK: - Protocol Version Negotiation
// Protocol version constants
struct ProtocolVersion {
static let current: UInt8 = 1
static let minimum: UInt8 = 1
static let maximum: UInt8 = 1
// Future versions can be added here
static let supportedVersions: Set<UInt8> = [1]
static func isSupported(_ version: UInt8) -> Bool {
return supportedVersions.contains(version)
}
static func negotiateVersion(clientVersions: [UInt8], serverVersions: [UInt8]) -> UInt8? {
// Find the highest common version
let clientSet = Set(clientVersions)
let serverSet = Set(serverVersions)
let common = clientSet.intersection(serverSet)
return common.max()
}
}
// Version negotiation hello message
struct VersionHello: Codable {
let supportedVersions: [UInt8] // List of supported protocol versions
let preferredVersion: UInt8 // Preferred version (usually the latest)
let clientVersion: String // App version string (e.g., "1.0.0")
let platform: String // Platform identifier (e.g., "iOS", "macOS")
let capabilities: [String]? // Optional capability flags for future extensions
init(supportedVersions: [UInt8] = Array(ProtocolVersion.supportedVersions),
preferredVersion: UInt8 = ProtocolVersion.current,
clientVersion: String,
platform: String,
capabilities: [String]? = nil) {
self.supportedVersions = supportedVersions
self.preferredVersion = preferredVersion
self.clientVersion = clientVersion
self.platform = platform
self.capabilities = capabilities
}
func encode() -> Data? {
return try? JSONEncoder().encode(self)
}
static func decode(from data: Data) -> VersionHello? {
try? JSONDecoder().decode(VersionHello.self, from: data)
}
// MARK: - Binary Encoding
func toBinaryData() -> Data {
var data = Data()
// Flags byte: bit 0 = hasCapabilities
var flags: UInt8 = 0
if capabilities != nil { flags |= 0x01 }
data.appendUInt8(flags)
// Supported versions array
data.appendUInt8(UInt8(supportedVersions.count))
for version in supportedVersions {
data.appendUInt8(version)
}
data.appendUInt8(preferredVersion)
data.appendString(clientVersion)
data.appendString(platform)
if let capabilities = capabilities {
data.appendUInt8(UInt8(capabilities.count))
for capability in capabilities {
data.appendString(capability)
}
}
return data
}
static func fromBinaryData(_ data: Data) -> VersionHello? {
// Create defensive copy
let dataCopy = Data(data)
// Minimum size check: flags(1) + versionCount(1) + at least one version(1) + preferredVersion(1) + min strings
guard dataCopy.count >= 4 else { return nil }
var offset = 0
guard let flags = dataCopy.readUInt8(at: &offset) else { return nil }
let hasCapabilities = (flags & 0x01) != 0
guard let versionCount = dataCopy.readUInt8(at: &offset) else { return nil }
var supportedVersions: [UInt8] = []
for _ in 0..<versionCount {
guard let version = dataCopy.readUInt8(at: &offset) else { return nil }
supportedVersions.append(version)
}
guard let preferredVersion = dataCopy.readUInt8(at: &offset),
let clientVersion = dataCopy.readString(at: &offset),
let platform = dataCopy.readString(at: &offset) else { return nil }
var capabilities: [String]? = nil
if hasCapabilities {
guard let capCount = dataCopy.readUInt8(at: &offset) else { return nil }
capabilities = []
for _ in 0..<capCount {
guard let capability = dataCopy.readString(at: &offset) else { return nil }
capabilities?.append(capability)
}
}
return VersionHello(supportedVersions: supportedVersions,
preferredVersion: preferredVersion,
clientVersion: clientVersion,
platform: platform,
capabilities: capabilities)
}
}
// Version negotiation acknowledgment
struct VersionAck: Codable {
let agreedVersion: UInt8 // The version both peers will use
let serverVersion: String // Responder's app version
let platform: String // Responder's platform
let capabilities: [String]? // Responder's capabilities
let rejected: Bool // True if no compatible version found
let reason: String? // Reason for rejection if applicable
init(agreedVersion: UInt8,
serverVersion: String,
platform: String,
capabilities: [String]? = nil,
rejected: Bool = false,
reason: String? = nil) {
self.agreedVersion = agreedVersion
self.serverVersion = serverVersion
self.platform = platform
self.capabilities = capabilities
self.rejected = rejected
self.reason = reason
}
func encode() -> Data? {
return try? JSONEncoder().encode(self)
}
static func decode(from data: Data) -> VersionAck? {
try? JSONDecoder().decode(VersionAck.self, from: data)
}
// MARK: - Binary Encoding
func toBinaryData() -> Data {
var data = Data()
// Flags byte: bit 0 = hasCapabilities, bit 1 = hasReason
var flags: UInt8 = 0
if capabilities != nil { flags |= 0x01 }
if reason != nil { flags |= 0x02 }
data.appendUInt8(flags)
data.appendUInt8(agreedVersion)
data.appendString(serverVersion)
data.appendString(platform)
data.appendUInt8(rejected ? 1 : 0)
if let capabilities = capabilities {
data.appendUInt8(UInt8(capabilities.count))
for capability in capabilities {
data.appendString(capability)
}
}
if let reason = reason {
data.appendString(reason)
}
return data
}
static func fromBinaryData(_ data: Data) -> VersionAck? {
// Create defensive copy
let dataCopy = Data(data)
// Minimum size: flags(1) + version(1) + rejected(1) + min strings
guard dataCopy.count >= 5 else { return nil }
var offset = 0
guard let flags = dataCopy.readUInt8(at: &offset) else { return nil }
let hasCapabilities = (flags & 0x01) != 0
let hasReason = (flags & 0x02) != 0
guard let agreedVersion = dataCopy.readUInt8(at: &offset),
let serverVersion = dataCopy.readString(at: &offset),
let platform = dataCopy.readString(at: &offset),
let rejectedByte = dataCopy.readUInt8(at: &offset) else { return nil }
let rejected = rejectedByte != 0
var capabilities: [String]? = nil
if hasCapabilities {
guard let capCount = dataCopy.readUInt8(at: &offset) else { return nil }
capabilities = []
for _ in 0..<capCount {
guard let capability = dataCopy.readString(at: &offset) else { return nil }
capabilities?.append(capability)
}
}
var reason: String? = nil
if hasReason {
reason = dataCopy.readString(at: &offset)
}
return VersionAck(agreedVersion: agreedVersion,
serverVersion: serverVersion,
platform: platform,
capabilities: capabilities,
rejected: rejected,
reason: reason)
}
}
// MARK: - Delivery Status
File diff suppressed because it is too large Load Diff