Added P2P pinging logic.

This commit is contained in:
Mikunj 2019-05-24 15:20:49 +10:00
parent 20f0b23951
commit 7f679ba5ed
3 changed files with 69 additions and 5 deletions

View File

@ -1,10 +1,72 @@
extension LokiAPI {
private static let messageSender: MessageSender = SSKEnvironment.shared.messageSender
/// A p2p state struct
internal struct P2PDetails {
var address: String
var port: UInt32
var isOnline: Bool
var timerDuration: Double
var pingTimer: WeakTimer? = nil
var target: Target {
return Target(address: address, port: port)
}
}
internal static var ourP2PAddress: Target? = nil
/// This is where we store the p2p details of our contacts
internal static var contactP2PDetails = [String: Target]()
internal static var contactP2PDetails = [String: P2PDetails]()
/// Handle P2P logic when we receive a `LokiAddressMessage`
///
/// - Parameters:
/// - pubKey: The other users pubKey
/// - address: The pther users p2p address
/// - port: The other users p2p port
/// - receivedThroughP2P: Wether we received the message through p2p
@objc public static func didReceiveLokiAddressMessage(forContact pubKey: String, address: String, port: UInt32, receivedThroughP2P: Bool) {
// Stagger the ping timers so that contacts don't ping each other at the same time
let timerDuration = pubKey < ourHexEncodedPubKey ? 1 * kMinuteInterval : 2 * kMinuteInterval
// Get out current contact details
let oldContactDetails = contactP2PDetails[pubKey]
// Set the new contact details
// A contact is always assumed to be offline unless the specific conditions below are met
let details = P2PDetails(address: address, port: port, isOnline: false, timerDuration: timerDuration, pingTimer: nil)
// Set up our checks
let oldContactExists = oldContactDetails != nil
let wasOnline = oldContactDetails?.isOnline ?? false
let p2pDetailsMatch = oldContactDetails?.address == address && oldContactDetails?.port == port
/*
We need to check if we should ping the user.
We don't ping the user IF:
- We had old contact details
- We got a P2P message
- The old contact was set as `Online`
- The new p2p details match the old one
*/
if oldContactExists && receivedThroughP2P && wasOnline && p2pDetailsMatch {
// TODO: Set contact to online and start the ping timers
return;
}
/*
Ping the contact.
This happens in the following scenarios:
1. We didn't have the contact, we need to ping them to let them know our details.
2. wasP2PMessage = false, so we assume the contact doesn't have our details.
3. We had the contact marked as offline, we need to make sure that we can reach their server.
4. The other contact details have changed, we need to make sure that we can reach their new server.
*/
// TODO: Ping the contact
}
/// Set the Contact p2p details
///
@ -13,8 +75,8 @@ extension LokiAPI {
/// - address: The contacts p2p address
/// - port: The contacts p2p port
@objc public static func setContactP2PDetails(forContact pubKey: String, address: String, port: UInt32) {
let target = Target(address: address, port: port)
contactP2PDetails[pubKey] = target
let details = P2PDetails(address: address, port: port, isOnline: false, timerDuration: 10, pingTimer: nil)
contactP2PDetails[pubKey] = details
}
/// Set our local P2P address

View File

@ -87,7 +87,7 @@ import PromiseKit
// TODO: probably only send to p2p if user is online or we are pinging them
// p2pDetails && (isPing || peerIsOnline)
if let p2pDetails = contactP2PDetails[destination] {
let targets = Promise.wrap([p2pDetails])
let targets = Promise.wrap([p2pDetails.target])
return sendMessage(message, targets: targets).recover { _ in return sendThroughStorageServer() }
}

View File

@ -435,7 +435,9 @@ NS_ASSUME_NONNULL_BEGIN
// Loki: Check if we got p2p address
if (contentProto.lokiAddressMessage) {
[LokiAPI setContactP2PDetailsForContact:envelope.source address:contentProto.lokiAddressMessage.ptpAddress port:contentProto.lokiAddressMessage.ptpPort];
NSString *address = contentProto.lokiAddressMessage.ptpAddress;
uint32_t port = contentProto.lokiAddressMessage.ptpPort;
[LokiAPI didReceiveLokiAddressMessageForContact:envelope.source address:address port:port receivedThroughP2P:envelope.isPtpMessage]
}
if (contentProto.syncMessage) {