diff --git a/NearbyShare/Connection/InboundNearbyConnection.swift b/NearbyShare/Connection/InboundNearbyConnection.swift index e22d61b..6af4f9c 100644 --- a/NearbyShare/Connection/InboundNearbyConnection.swift +++ b/NearbyShare/Connection/InboundNearbyConnection.swift @@ -123,9 +123,48 @@ class InboundNearbyConnection: NearbyConnection { } switch currentState { case .sentConnectionResponse: - try processPairedKeyEncryptionFrame(frame) + if frame.hasV1, frame.v1.hasPairedKeyEncryption { + try processPairedKeyEncryptionFrame(frame) + return + } + if frame.hasV1, frame.v1.hasIntroduction { + log("[InboundNearbyConnection \(self.id)] Received introduction before paired-key exchange finished; continuing unauthenticated flow.") + try sendPairedKeyResult(status: .unable) + try processIntroductionFrame(frame) + return + } + if frame.hasV1, frame.v1.hasType { + if frame.v1.type == .pairedKeyResult || frame.v1.type == .progressUpdate { + log("[InboundNearbyConnection \(self.id)] Ignoring duplicate/intermediate transfer setup frame \(frame.v1.type) while waiting for pairedKeyEncryption.") + return + } + if frame.v1.type == .response, case .accept = frame.v1.connectionResponse.status { + log("[InboundNearbyConnection \(self.id)] Ignoring accept response while waiting for pairedKeyEncryption.") + return + } + } + throw NearbyError.requiredFieldMissing("shareNearbyFrame.v1.pairedKeyEncryption") case .sentPairedKeyResult: - try processPairedKeyResultFrame(frame) + if frame.hasV1, frame.v1.hasPairedKeyResult { + try processPairedKeyResultFrame(frame) + return + } + if frame.hasV1, frame.v1.hasIntroduction { + log("[InboundNearbyConnection \(self.id)] Received introduction without pairedKeyResult; continuing for legacy compatibility.") + try processIntroductionFrame(frame) + return + } + if frame.hasV1, frame.v1.hasType { + if frame.v1.type == .pairedKeyEncryption || frame.v1.type == .progressUpdate { + log("[InboundNearbyConnection \(self.id)] Ignoring duplicate/intermediate transfer setup frame \(frame.v1.type) while waiting for pairedKeyResult.") + return + } + if frame.v1.type == .response, case .accept = frame.v1.connectionResponse.status { + log("[InboundNearbyConnection \(self.id)] Ignoring accept response while waiting for pairedKeyResult.") + return + } + } + throw NearbyError.requiredFieldMissing("shareNearbyFrame.v1.pairedKeyResult") case .receivedPairedKeyResult: if frame.hasV1, frame.v1.hasIntroduction { try processIntroductionFrame(frame) diff --git a/NearbyShare/Connection/OutboundNearbyConnection.swift b/NearbyShare/Connection/OutboundNearbyConnection.swift index 6fb76fc..9a76cd6 100644 --- a/NearbyShare/Connection/OutboundNearbyConnection.swift +++ b/NearbyShare/Connection/OutboundNearbyConnection.swift @@ -147,15 +147,50 @@ class OutboundNearbyConnection: NearbyConnection { switch currentState { case .sentPairedKeyEncryption: - try processPairedKeyEncryption(frame: frame) + if frame.hasV1, frame.v1.hasPairedKeyEncryption { + try processPairedKeyEncryption(frame: frame) + return + } + if frame.hasV1, frame.v1.hasPairedKeyResult { + log("[OutboundNearbyConnection \(self.id)] Received pairedKeyResult before pairedKeyEncryption; continuing for legacy compatibility.") + try processPairedKeyResult(frame: frame) + return + } + if frame.hasV1, frame.v1.hasType { + if frame.v1.type == .progressUpdate || frame.v1.type == .response { + log("[OutboundNearbyConnection \(self.id)] Ignoring duplicate/intermediate transfer setup frame \(frame.v1.type) while waiting for pairedKeyEncryption.") + return + } + } + throw NearbyError.requiredFieldMissing("sharingNearbyFrame.v1.pairedKeyEncryption") case .sentPairedKeyResult: - try processPairedKeyResult(frame: frame) + if frame.hasV1, frame.v1.hasPairedKeyResult { + try processPairedKeyResult(frame: frame) + return + } + if frame.hasV1, frame.v1.hasType { + if frame.v1.type == .pairedKeyEncryption || frame.v1.type == .progressUpdate || frame.v1.type == .response { + log("[OutboundNearbyConnection \(self.id)] Ignoring duplicate/intermediate transfer setup frame \(frame.v1.type) while waiting for pairedKeyResult.") + return + } + } + throw NearbyError.requiredFieldMissing("sharingNearbyFrame.v1.pairedKeyResult") case .sentIntroduction: - try processConsent(frame: frame) + if frame.version == .v1, frame.v1.type == .response { + try processConsent(frame: frame) + return + } + if frame.hasV1, frame.v1.hasType { + if frame.v1.type == .pairedKeyEncryption || frame.v1.type == .pairedKeyResult || frame.v1.type == .progressUpdate { + log("[OutboundNearbyConnection \(self.id)] Ignoring duplicate/intermediate transfer setup frame \(frame.v1.type) while waiting for consent.") + return + } + } + throw NearbyError.requiredFieldMissing("sharingNearbyFrame.v1.type==response") case .sendingFiles: break default: - assertionFailure("[OutboundNearbyConnection \(self.id)] Unexpected state \(currentState)") + log("[OutboundNearbyConnection \(self.id)] Unexpected state \(currentState)") } }