mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
PeerID 31/n: Remove String interop to be explicit (#840)
* PeerID 28/n: `ChatViewModel.getShortIDForNoiseKey` * PeerID 29/n: `BLEService` + remove dupe funcs from #823 * `handleFileTransfer` to use PeerID * `sendMessage` and `sendPrivateMessage` * PeerID 30/n: Update some leftovers * `lowercased()` inside PeerID for normalization * PeerID 31/n: Remove String interop to be explicit * MockBLEService: Remove direct target delivery This causes a delivery even if the sender and receiver are not connected --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
@@ -246,7 +246,7 @@ final class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
|
||||
// Get peer ID from userInfo
|
||||
if let peerID = userInfo["peerID"] as? String {
|
||||
// Don't show notification if the private chat is already open
|
||||
if chatViewModel?.selectedPrivateChatPeer == peerID {
|
||||
if chatViewModel?.selectedPrivateChatPeer == PeerID(str: peerID) {
|
||||
completionHandler([])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -76,6 +76,12 @@ extension PeerID {
|
||||
init(hexData: Data) {
|
||||
self.init(str: hexData.hexEncodedString())
|
||||
}
|
||||
|
||||
/// Convenience init to "hide" hex-encoding implementation detail
|
||||
init?(hexData: Data?) {
|
||||
guard let hexData else { return nil }
|
||||
self.init(hexData: hexData)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Noise Public Key Helpers
|
||||
@@ -191,9 +197,7 @@ extension PeerID: Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - String Interop Helpers
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
// MARK: - CustomStringConvertible
|
||||
|
||||
extension PeerID: CustomStringConvertible {
|
||||
/// So it returns the actual `id` like before even inside another String
|
||||
@@ -201,17 +205,3 @@ extension PeerID: CustomStringConvertible {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Custom Equatable w/ String & Optionality
|
||||
|
||||
// PeerID <> String
|
||||
extension Optional where Wrapped == PeerID {
|
||||
static func ==(lhs: Optional<Wrapped>, rhs: Optional<String>) -> Bool { lhs?.id == rhs }
|
||||
static func !=(lhs: Optional<Wrapped>, rhs: Optional<String>) -> Bool { lhs?.id != rhs }
|
||||
}
|
||||
|
||||
// String <> PeerID
|
||||
extension Optional where Wrapped == String {
|
||||
static func ==(lhs: Optional<Wrapped>, rhs: Optional<PeerID>) -> Bool { lhs == rhs?.id }
|
||||
static func !=(lhs: Optional<Wrapped>, rhs: Optional<PeerID>) -> Bool { lhs != rhs?.id }
|
||||
}
|
||||
|
||||
@@ -734,8 +734,7 @@ final class BLEService: NSObject {
|
||||
}
|
||||
|
||||
private func sendEncrypted(_ packet: BitchatPacket, data: Data, pad: Bool) {
|
||||
guard let recipientID = packet.recipientID else { return }
|
||||
let recipientPeerID = PeerID(hexData: recipientID)
|
||||
guard let recipientPeerID = PeerID(hexData: packet.recipientID) else { return }
|
||||
var sentEncrypted = false
|
||||
|
||||
// Per-link limits for the specific peer
|
||||
@@ -1039,8 +1038,7 @@ final class BLEService: NSObject {
|
||||
|
||||
// Skip directed packets that are not intended for us
|
||||
if let recipient = packet.recipientID {
|
||||
let recipientHex = recipient.hexEncodedString()
|
||||
if recipientHex != myPeerID && !recipient.allSatisfy({ $0 == 0xFF }) {
|
||||
if PeerID(hexData: recipient) != myPeerID && !recipient.allSatisfy({ $0 == 0xFF }) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1122,10 +1120,7 @@ final class BLEService: NSObject {
|
||||
marker = "[file] \(fileName)"
|
||||
}
|
||||
|
||||
let isPrivateMessage: Bool = {
|
||||
guard let recipient = packet.recipientID else { return false }
|
||||
return recipient.hexEncodedString() == myPeerID
|
||||
}()
|
||||
let isPrivateMessage = PeerID(hexData: packet.recipientID) == myPeerID
|
||||
|
||||
if isPrivateMessage {
|
||||
updatePeerLastSeen(peerID)
|
||||
@@ -3078,9 +3073,9 @@ extension BLEService {
|
||||
|
||||
// Verify that the sender's derived ID from the announced noise public key matches the packet senderID
|
||||
// This helps detect relayed or spoofed announces. Only warn in release; assert in debug.
|
||||
let derivedFromKey = PeerID(publicKey: announcement.noisePublicKey).id
|
||||
let derivedFromKey = PeerID(publicKey: announcement.noisePublicKey)
|
||||
if derivedFromKey != peerID {
|
||||
SecureLogger.warning("⚠️ Announce sender mismatch: derived \(derivedFromKey.prefix(8))… vs packet \(peerID.id.prefix(8))…", category: .security)
|
||||
SecureLogger.warning("⚠️ Announce sender mismatch: derived \(derivedFromKey.id.prefix(8))… vs packet \(peerID.id.prefix(8))…", category: .security)
|
||||
|
||||
}
|
||||
|
||||
@@ -3366,8 +3361,7 @@ extension BLEService {
|
||||
|
||||
private func handleNoiseHandshake(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
// Use NoiseEncryptionService for handshake processing
|
||||
if let recipientID = packet.recipientID,
|
||||
recipientID.hexEncodedString() == myPeerID {
|
||||
if PeerID(hexData: packet.recipientID) == myPeerID {
|
||||
// Handshake is for us
|
||||
do {
|
||||
if let response = try noiseService.processHandshakeMessage(from: peerID, message: packet.payload) {
|
||||
@@ -3400,14 +3394,13 @@ extension BLEService {
|
||||
private func handleNoiseEncrypted(_ packet: BitchatPacket, from peerID: PeerID) {
|
||||
SecureLogger.debug("🔐 handleNoiseEncrypted called for packet from \(peerID)")
|
||||
|
||||
guard let recipientID = packet.recipientID else {
|
||||
guard let recipientID = PeerID(hexData: packet.recipientID) else {
|
||||
SecureLogger.warning("⚠️ Encrypted message has no recipient ID", category: .session)
|
||||
return
|
||||
}
|
||||
|
||||
let recipientHex = recipientID.hexEncodedString()
|
||||
if recipientHex != myPeerID {
|
||||
SecureLogger.debug("🔐 Encrypted message not for me (for \(recipientHex), I am \(myPeerID))", category: .session)
|
||||
if recipientID != myPeerID {
|
||||
SecureLogger.debug("🔐 Encrypted message not for me (for \(recipientID), I am \(myPeerID))", category: .session)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
nickname = trimmed
|
||||
}
|
||||
// Update mesh service nickname if it's initialized
|
||||
if meshService.myPeerID != "" {
|
||||
if !meshService.myPeerID.isEmpty {
|
||||
meshService.setNickname(nickname)
|
||||
}
|
||||
}
|
||||
@@ -4103,7 +4103,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if let spid = message.senderPeerID {
|
||||
if case .location(let ch) = activeChannel, spid.id.hasPrefix("nostr:") {
|
||||
if let myGeo = try? idBridge.deriveIdentity(forGeohash: ch.geohash) {
|
||||
return spid == "nostr:\(myGeo.publicKeyHex.prefix(TransportConfig.nostrShortKeyDisplayLength))"
|
||||
return spid == PeerID(nostr: myGeo.publicKeyHex)
|
||||
}
|
||||
}
|
||||
return spid == meshService.myPeerID
|
||||
@@ -5623,7 +5623,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
|
||||
// Validate recipient
|
||||
if let rid = packet.recipientID, rid.hexEncodedString() != meshService.myPeerID {
|
||||
if PeerID(hexData: packet.recipientID) != meshService.myPeerID {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -186,11 +186,11 @@ struct PrivateChatE2ETests {
|
||||
// Bob relays private messages for Charlie
|
||||
bob.packetDeliveryHandler = { packet in
|
||||
if let recipientID = packet.recipientID,
|
||||
String(data: recipientID, encoding: .utf8) == charlie.peerID {
|
||||
PeerID(data: recipientID) == charlie.peerID {
|
||||
// Relay to Charlie
|
||||
var relayPacket = packet
|
||||
relayPacket.ttl = packet.ttl - 1
|
||||
self.charlie.simulateIncomingPacket(relayPacket)
|
||||
charlie.simulateIncomingPacket(relayPacket)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,7 +388,7 @@ struct PublicChatE2ETests {
|
||||
|
||||
if let message = BitchatMessage(packet.payload) {
|
||||
// Don't relay own messages
|
||||
guard message.senderPeerID?.id != node.peerID else { return }
|
||||
guard message.senderPeerID != node.peerID else { return }
|
||||
|
||||
// Create relay message
|
||||
let relayMessage = BitchatMessage(
|
||||
|
||||
@@ -203,10 +203,7 @@ final class MockBLEService: NSObject {
|
||||
let target = bus.service(for: recipientPeerID) {
|
||||
target.simulateIncomingPacket(packet)
|
||||
} else {
|
||||
// Not directly connected: deliver to neighbors for relay; also deliver directly if target is known
|
||||
if let target = bus.service(for: recipientPeerID) {
|
||||
target.simulateIncomingPacket(packet)
|
||||
}
|
||||
// Not directly connected: deliver to neighbors for relay
|
||||
for neighbor in neighbors() where neighbor.peerID != recipientPeerID {
|
||||
neighbor.simulateIncomingPacket(packet)
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ struct PeerIDTests {
|
||||
@Test func comparable_sorting_and_equality() {
|
||||
let p1 = PeerID(str: "aaa")
|
||||
let p2 = PeerID(str: "bbb")
|
||||
let p3 = PeerID(str: "bbb")
|
||||
let p3 = PeerID(str: "BBB")
|
||||
|
||||
#expect(p1 < p2)
|
||||
#expect(p2 >= p1)
|
||||
@@ -284,44 +284,18 @@ struct PeerIDTests {
|
||||
}
|
||||
|
||||
@Test func equality() {
|
||||
let string = "aaa"
|
||||
let peerID = PeerID(str: string)
|
||||
let badString = "bbb"
|
||||
|
||||
// PeerID == String
|
||||
#expect(peerID == string)
|
||||
#expect(peerID == Optional(string))
|
||||
#expect(Optional(peerID) == string)
|
||||
#expect(Optional(peerID) == Optional(string))
|
||||
|
||||
// PeerID != String
|
||||
#expect(peerID != badString)
|
||||
#expect(peerID != Optional(badString))
|
||||
#expect(Optional(peerID) != badString)
|
||||
#expect(Optional(peerID) != Optional(badString))
|
||||
|
||||
// String == PeerID
|
||||
#expect(string == peerID)
|
||||
#expect(Optional(string) == peerID)
|
||||
#expect(string == Optional(peerID))
|
||||
#expect(Optional(string) == Optional(peerID))
|
||||
|
||||
// String != PeerID
|
||||
#expect(badString != peerID)
|
||||
#expect(Optional(badString) != peerID)
|
||||
#expect(badString != Optional(peerID))
|
||||
#expect(Optional(badString) != Optional(peerID))
|
||||
let peerID = PeerID(str: "aaa")
|
||||
|
||||
// Regular PeerID <> PeerID
|
||||
#expect(peerID == PeerID(str: "aaa"))
|
||||
#expect(peerID == Optional(PeerID(str: "aaa")))
|
||||
#expect(PeerID(str: "aaa") == peerID)
|
||||
#expect(Optional(PeerID(str: "aaa")) == Optional(peerID))
|
||||
#expect(peerID == PeerID(str: "AAA"))
|
||||
#expect(peerID == Optional(PeerID(str: "AAA")))
|
||||
#expect(PeerID(str: "AAA") == peerID)
|
||||
#expect(Optional(PeerID(str: "AAA")) == Optional(peerID))
|
||||
|
||||
#expect(peerID != PeerID(str: "bbb"))
|
||||
#expect(peerID != Optional(PeerID(str: "bbb")))
|
||||
#expect(PeerID(str: "bbb") != peerID)
|
||||
#expect(Optional(PeerID(str: "bbb")) != Optional(peerID))
|
||||
#expect(peerID != PeerID(str: "BBB"))
|
||||
#expect(peerID != Optional(PeerID(str: "BBB")))
|
||||
#expect(PeerID(str: "BBB") != peerID)
|
||||
#expect(Optional(PeerID(str: "BBB")) != Optional(peerID))
|
||||
}
|
||||
|
||||
// MARK: - Computed properties
|
||||
|
||||
Reference in New Issue
Block a user