Merge pull request #20 from loki-project/p2p

P2P
pull/26/head
Niels Andriesse 6 years ago committed by GitHub
commit 521cfd360d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit c8f9b28f577a03f9f03a0b2e38e125811785ee29
Subproject commit 7005b4be3cd1596fcf644356aea526663cd8ac67

@ -320,11 +320,13 @@ static NSTimeInterval launchStartedAt;
if (self.lokiP2PServer.isRunning) { break; }
BOOL isStarted = [self.lokiP2PServer startOnPort:port.unsignedIntegerValue];
if (isStarted) {
NSString *serverURL = self.lokiP2PServer.serverURL.absoluteString;
if ([serverURL hasSuffix:@"/"]) {
serverURL = [serverURL substringToIndex:serverURL.length - 1];
NSURL *serverURL = self.lokiP2PServer.serverURL;
[LokiP2PManager setOurP2PAddressWithUrl:self.lokiP2PServer.serverURL];
NSString *serverURLDescription = serverURL.absoluteString;
if ([serverURLDescription hasSuffix:@"/"]) {
serverURLDescription = [serverURLDescription substringToIndex:serverURLDescription.length - 1];
}
OWSLogInfo(@"[Loki] Started server at %@.", serverURL);
OWSLogInfo(@"[Loki] Started server at %@.", serverURLDescription);
break;
}
}
@ -755,7 +757,8 @@ static NSTimeInterval launchStartedAt;
// Loki: Start poller
[Poller.shared startIfNeeded];
// TODO: Ping friends to let them know we're online
// Loki: Tell our friends that we are online
[LokiP2PManager broadcastOnlineStatus];
if (![UIApplication sharedApplication].isRegisteredForRemoteNotifications) {
OWSLogInfo(@"Retrying to register for remote notifications since user hasn't registered yet.");

@ -9,49 +9,58 @@ public extension LokiAPI {
let data: LosslessStringConvertible
/// The time to live for the message in milliseconds.
let ttl: UInt64
/// When the proof of work was calculated, if applicable.
/// Whether this message is a ping.
///
/// - Note: The concept of pinging only applies to P2P messaging.
let isPing: Bool
/// When the proof of work was calculated, if applicable (P2P messages don't require proof of work).
///
/// - Note: Expressed as milliseconds since 00:00:00 UTC on 1 January 1970.
let timestamp: UInt64?
/// The base 64 encoded proof of work, if applicable.
let nonce: String?
private(set) var timestamp: UInt64? = nil
/// The base 64 encoded proof of work, if applicable (P2P messages don't require proof of work).
private(set) var nonce: String? = nil
public init(destination: String, data: LosslessStringConvertible, ttl: UInt64, timestamp: UInt64?, nonce: String?) {
private init(destination: String, data: LosslessStringConvertible, ttl: UInt64, isPing: Bool) {
self.destination = destination
self.data = data
self.ttl = ttl
self.timestamp = timestamp
self.nonce = nonce
self.isPing = isPing
}
/// Construct a `LokiMessage` from a `SignalMessage`.
///
/// - Note: `timestamp` is the original message timestamp (i.e. `TSOutgoingMessage.timestamp`).
public static func from(signalMessage: SignalMessage, timestamp: UInt64, requiringPoW isPoWRequired: Bool) -> Promise<Message> {
public static func from(signalMessage: SignalMessage, with timestamp: UInt64) -> Message? {
// To match the desktop application, we have to wrap the data in an envelope and then wrap that in a websocket object
do {
let wrappedMessage = try LokiMessageWrapper.wrap(message: signalMessage, timestamp: timestamp)
let data = wrappedMessage.base64EncodedString()
let destination = signalMessage["destination"] as! String
var ttl = LokiAPI.defaultMessageTTL
if let messageTTL = signalMessage["ttl"] as! UInt?, messageTTL > 0 { ttl = UInt64(messageTTL) }
let isPing = signalMessage["isPing"] as! Bool
return Message(destination: destination, data: data, ttl: ttl, isPing: isPing)
} catch let error {
Logger.debug("[Loki] Failed to convert Signal message to Loki message: \(signalMessage).")
return nil
}
}
/// Calculate the proof of work for this message.
///
/// - Returns: The promise of a new message with its `timestamp` and `nonce` set.
public func calculatePoW() -> Promise<Message> {
return Promise<Message> { seal in
DispatchQueue.global(qos: .default).async {
do {
let wrappedMessage = try LokiMessageWrapper.wrap(message: signalMessage, timestamp: timestamp)
let data = wrappedMessage.base64EncodedString()
let destination = signalMessage["destination"] as! String
var ttl = LokiAPI.defaultMessageTTL
if let messageTTL = signalMessage["ttl"] as? UInt, messageTTL > 0 { ttl = UInt64(messageTTL) }
if isPoWRequired {
// The storage server takes a time interval in milliseconds
let now = NSDate.ows_millisecondTimeStamp()
if let nonce = ProofOfWork.calculate(data: data, pubKey: destination, timestamp: now, ttl: ttl) {
let result = Message(destination: destination, data: data, ttl: ttl, timestamp: now, nonce: nonce)
seal.fulfill(result)
} else {
seal.reject(Error.proofOfWorkCalculationFailed)
}
} else {
let result = Message(destination: destination, data: data, ttl: ttl, timestamp: nil, nonce: nil)
seal.fulfill(result)
}
} catch let error {
seal.reject(error)
let now = NSDate.ows_millisecondTimeStamp()
let dataAsString = self.data as! String // Safe because of how from(signalMessage:with:) is implemented
if let nonce = ProofOfWork.calculate(data: dataAsString, pubKey: self.destination, timestamp: now, ttl: self.ttl) {
var result = self
result.timestamp = now
result.nonce = nonce
seal.fulfill(result)
} else {
seal.reject(Error.proofOfWorkCalculationFailed)
}
}
}

@ -5,8 +5,8 @@ import PromiseKit
// MARK: Settings
private static let version = "v1"
public static let defaultMessageTTL: UInt64 = 1 * 24 * 60 * 60 * 1000
private static let maxRetryCount: UInt = 3
public static let defaultMessageTTL: UInt64 = 1 * 24 * 60 * 60 * 1000
// MARK: Types
public typealias RawResponse = Any
@ -14,15 +14,18 @@ import PromiseKit
public enum Error : LocalizedError {
/// Only applicable to snode targets as proof of work isn't required for P2P messaging.
case proofOfWorkCalculationFailed
case messageConversionFailed
public var errorDescription: String? {
switch self {
case .proofOfWorkCalculationFailed: return NSLocalizedString("Failed to calculate proof of work.", comment: "")
case .messageConversionFailed: return "Failed to convert Signal message to Loki message."
}
}
}
public typealias MessagePromise = Promise<[SSKProtoEnvelope]> // To keep the return type of getMessages() readable
public typealias MessagePromise = Promise<[SSKProtoEnvelope]>
public typealias RawResponsePromise = Promise<RawResponse>
// MARK: Lifecycle
override private init() { }
@ -47,39 +50,47 @@ import PromiseKit
let newRawMessages = removeDuplicates(from: rawMessages)
return parseProtoEnvelopes(from: newRawMessages)
}
}.retryingIfNeeded(maxRetryCount: maxRetryCount).map { Set($0) }
}.map { Set($0) }.retryingIfNeeded(maxRetryCount: maxRetryCount)
}
public static func sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, timestamp: UInt64) -> Promise<Set<Promise<RawResponse>>> {
let isP2PMessagingPossible = false
return Message.from(signalMessage: signalMessage, timestamp: timestamp, requiringPoW: !isP2PMessagingPossible).then(sendMessage)
}
public static func sendMessage(_ lokiMessage: Message) -> Promise<Set<Promise<RawResponse>>> {
let isP2PMessagingPossible = false
if isP2PMessagingPossible {
// TODO: Send using P2P protocol
} else {
public static func sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64) -> Promise<Set<RawResponsePromise>> {
guard let lokiMessage = Message.from(signalMessage: signalMessage, with: timestamp) else { return Promise(error: Error.messageConversionFailed) }
let destination = lokiMessage.destination
func sendLokiMessage(_ lokiMessage: Message, to target: Target) -> RawResponsePromise {
let parameters = lokiMessage.toJSON()
return getTargetSnodes(for: lokiMessage.destination).mapValues { invoke(.sendMessage, on: $0, associatedWith: lokiMessage.destination, parameters: parameters) }
.retryingIfNeeded(maxRetryCount: maxRetryCount).map { Set($0) }
return invoke(.sendMessage, on: target, associatedWith: destination, parameters: parameters)
}
}
public static func ping(_ hexEncodedPublicKey: String) -> Promise<Set<Promise<RawResponse>>> {
let isP2PMessagingPossible = false
if isP2PMessagingPossible {
// TODO: Send using P2P protocol
func sendLokiMessageUsingSwarmAPI() -> Promise<Set<RawResponsePromise>> {
let powPromise = lokiMessage.calculatePoW()
let swarmPromise = getTargetSnodes(for: destination)
return when(fulfilled: powPromise, swarmPromise).map { lokiMessageWithPoW, swarm in
return Set(swarm.map { sendLokiMessage(lokiMessageWithPoW, to: $0) })
}
}
if let p2pDetails = LokiP2PManager.getDetails(forContact: destination), (lokiMessage.isPing || p2pDetails.isOnline) {
return Promise.value([ p2pDetails.target ]).mapValues { sendLokiMessage(lokiMessage, to: $0) }.map { Set($0) }.retryingIfNeeded(maxRetryCount: maxRetryCount).get { _ in
LokiP2PManager.setOnline(true, forContact: destination)
}.recover { error -> Promise<Set<RawResponsePromise>> in
LokiP2PManager.setOnline(false, forContact: destination)
if lokiMessage.isPing {
Logger.warn("[Loki] Failed to ping \(destination); marking contact as offline.")
if let nsError = error as? NSError {
nsError.isRetryable = false
throw nsError
} else {
throw error
}
}
return sendLokiMessageUsingSwarmAPI().retryingIfNeeded(maxRetryCount: maxRetryCount)
}
} else {
let parameters: [String:Any] = [ "pubKey" : hexEncodedPublicKey ] // TODO: Figure out correct parameters
return getTargetSnodes(for: hexEncodedPublicKey).mapValues { invoke(.sendMessage, on: $0, associatedWith: hexEncodedPublicKey, parameters: parameters) }
.retryingIfNeeded(maxRetryCount: maxRetryCount).map { Set($0) }
return sendLokiMessageUsingSwarmAPI().retryingIfNeeded(maxRetryCount: maxRetryCount)
}
}
// MARK: Public API (Obj-C)
@objc public static func objc_sendSignalMessage(_ signalMessage: SignalMessage, to destination: String, with timestamp: UInt64) -> AnyPromise {
let promise = sendSignalMessage(signalMessage, to: destination, timestamp: timestamp).mapValues { AnyPromise.from($0) }.map { Set($0) }
let promise = sendSignalMessage(signalMessage, to: destination, with: timestamp).mapValues { AnyPromise.from($0) }.map { Set($0) }
return AnyPromise.from(promise)
}

@ -0,0 +1,201 @@
@objc public class LokiP2PManager : NSObject {
private static let storage = OWSPrimaryStorage.shared()
private static let messageSender = SSKEnvironment.shared.messageSender
private static let ourHexEncodedPubKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey
/// The amount of time before pinging when a user is set to offline
private static let offlinePingTime = 2 * kMinuteInterval
/// A p2p state struct
internal struct P2PDetails {
var address: String
var port: UInt16
var isOnline: Bool
var timerDuration: Double
var pingTimer: Timer? = nil
var target: LokiAPI.Target {
return LokiAPI.Target(address: address, port: port)
}
}
/// Our p2p address
private static var ourP2PAddress: LokiAPI.Target? = nil
/// This is where we store the p2p details of our contacts
private static var contactP2PDetails = [String: P2PDetails]()
// MARK: - Public functions
/// Set our local P2P address
///
/// - Parameter url: The url to our local server
@objc public static func setOurP2PAddress(url: URL) {
guard let scheme = url.scheme, let host = url.host, let port = url.port else { return }
let target = LokiAPI.Target(address: "\(scheme)://\(host)", port: UInt16(port))
ourP2PAddress = target
}
/// Ping a contact
///
/// - Parameter pubKey: The contact hex pubkey
@objc(pingContact:)
public static func ping(contact pubKey: String) {
// Dispatch on the main queue so we escape any transaction blocks
DispatchQueue.main.async {
var contactThread: TSThread? = nil
storage.dbReadConnection.read { transaction in
contactThread = TSContactThread.getWithContactId(pubKey, transaction: transaction)
}
guard let thread = contactThread else {
Logger.warn("[Loki][Ping] Failed to fetch thread for \(pubKey).")
return
}
guard let message = lokiAddressMessage(for: thread, isPing: true) else {
Logger.warn("[Loki][Ping] Failed to build ping message for \(pubKey).")
return
}
messageSender.sendPromise(message: message).retainUntilComplete()
}
}
/// Broadcast an online message to all our friends.
/// This shouldn't be called inside a transaction.
@objc public static func broadcastOnlineStatus() {
// Escape any transaction blocks
DispatchQueue.main.async {
let friendThreads = getAllFriendThreads()
for thread in friendThreads {
sendOnlineBroadcastMessage(forThread: thread)
}
}
}
// MARK: - Internal functions
/// Get the P2P details for the given contact.
///
/// - Parameter pubKey: The contact hex pubkey
/// - Returns: The P2P Details or nil if they don't exist
internal static func getDetails(forContact pubKey: String) -> P2PDetails? {
return contactP2PDetails[pubKey]
}
/// Get the `LokiAddressMessage` for the given thread.
///
/// - Parameter thread: The contact thread.
/// - Returns: The `LokiAddressMessage` for that thread.
@objc public static func onlineBroadcastMessage(forThread thread: TSThread) -> LokiAddressMessage? {
return lokiAddressMessage(for: thread, isPing: false)
}
/// 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 internal static func didReceiveLokiAddressMessage(forContact pubKey: String, address: String, port: UInt16, 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)
contactP2PDetails[pubKey] = details
// 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 {
setOnline(true, forContact: pubKey)
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.
*/
ping(contact: pubKey)
}
/// Mark a contact as online or offline.
///
/// - Parameters:
/// - isOnline: Whether to set the contact to online or offline.
/// - pubKey: The contact hexh pubKey
@objc internal static func setOnline(_ isOnline: Bool, forContact pubKey: String) {
// Make sure we are on the main thread
DispatchQueue.main.async {
guard var details = contactP2PDetails[pubKey] else { return }
let interval = isOnline ? details.timerDuration : offlinePingTime
// Setup a new timer
details.pingTimer?.invalidate()
details.pingTimer = WeakTimer.scheduledTimer(timeInterval: interval, target: self, userInfo: nil, repeats: true) { _ in ping(contact: pubKey) }
details.isOnline = isOnline
contactP2PDetails[pubKey] = details
}
}
// MARK: - Private functions
private static func sendOnlineBroadcastMessage(forThread thread: TSContactThread) {
AssertIsOnMainThread()
guard let message = onlineBroadcastMessage(forThread: thread) else {
owsFailDebug("P2P Address not set")
return
}
messageSender.sendPromise(message: message).catch { error in
Logger.warn("Failed to send online status to \(thread.contactIdentifier())")
}.retainUntilComplete()
}
private static func getAllFriendThreads() -> [TSContactThread] {
var friendThreadIds = [String]()
TSContactThread.enumerateCollectionObjects { (object, _) in
guard let thread = object as? TSContactThread, let uniqueId = thread.uniqueId else { return }
if thread.friendRequestStatus == .friends && thread.contactIdentifier() != ourHexEncodedPubKey {
friendThreadIds.append(thread.uniqueId!)
}
}
return friendThreadIds.compactMap { TSContactThread.fetch(uniqueId: $0) }
}
private static func lokiAddressMessage(for thread: TSThread, isPing: Bool) -> LokiAddressMessage? {
guard let ourAddress = ourP2PAddress else {
Logger.error("P2P Address not set")
return nil
}
return LokiAddressMessage(in: thread, address: ourAddress.address, port: ourAddress.port, isPing: isPing)
}
}

@ -63,7 +63,7 @@ public enum ProofOfWork {
/// - data: The message data
/// - pubKey: The message recipient
/// - timestamp: The timestamp
/// - ttl: The message time to live
/// - ttl: The message time to live in milliseconds
/// - Returns: A nonce string or `nil` if it failed
public static func calculate(data: String, pubKey: String, timestamp: UInt64, ttl: UInt64) -> String? {
let payload = createPayload(pubKey: pubKey, data: data, timestamp: timestamp, ttl: ttl)

@ -0,0 +1,16 @@
#import "LKEphemeralMessage.h"
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(LokiAddressMessage)
@interface LKAddressMessage : LKEphemeralMessage
@property (nonatomic, readonly) NSString *address;
@property (nonatomic, readonly) uint16_t port;
@property (nonatomic, readonly) BOOL isPing;
- (instancetype)initInThread:(nullable TSThread *)thread address:(NSString *)address port:(uint16_t)port isPing:(BOOL)isPing;
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,51 @@
#import "LKAddressMessage.h"
#import "NSDate+OWS.h"
#import "SignalRecipient.h"
#import <SignalServiceKit/SignalServiceKit-Swift.h>
@interface LKAddressMessage ()
@property (nonatomic) NSString *address;
@property (nonatomic) uint16_t port;
@property (nonatomic) BOOL isPing;
@end
@implementation LKAddressMessage
- (instancetype)initInThread:(nullable TSThread *)thread address:(NSString *)address port:(uint16_t)port isPing:(bool)isPing
{
self = [LKEphemeralMessage createEmptyOutgoingMessageInThread:thread];
if (self) {
_address = address;
_port = port;
_isPing = isPing;
}
return self;
}
- (SSKProtoContentBuilder *)contentBuilder:(SignalRecipient *)recipient {
SSKProtoContentBuilder *contentBuilder = [super contentBuilder:recipient];
SSKProtoLokiAddressMessageBuilder *addressBuilder = [SSKProtoLokiAddressMessage builder];
[addressBuilder setPtpAddress:self.address];
uint32_t portAsUInt32 = self.port;
[addressBuilder setPtpPort:portAsUInt32];
NSError *error;
SSKProtoLokiAddressMessage *addressMessage = [addressBuilder buildAndReturnError:&error];
if (error || !addressMessage) {
OWSFailDebug(@"Failed to build LokiAddressMessage for %@: %@.", recipient.recipientId, error);
} else {
[contentBuilder setLokiAddressMessage:addressMessage];
}
return contentBuilder;
}
- (uint)ttl {
// Address messages should only last 1 minute
return 1 * kMinuteInMs;
}
@end

@ -5,7 +5,7 @@ NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(EphemeralMessage)
@interface LKEphemeralMessage : TSOutgoingMessage
/// Used to establish sessions.
/// Used for e.g. session initialization.
+ (LKEphemeralMessage *)createEmptyOutgoingMessageInThread:(TSThread *)thread;
@end

@ -8,6 +8,7 @@
expiresInSeconds:0 expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMetaMessageUnspecified quotedMessage:nil contactShare:nil linkPreview:nil];
}
- (BOOL)shouldSyncTranscript { return NO; }
- (BOOL)shouldBeSaved { return NO; }
@end

@ -78,7 +78,10 @@ NSString *envelopeAddress(SSKProtoEnvelope *envelope)
} else {
// Don't fire an analytics event; if we ever add a new content type, we'd generate a ton of
// analytics traffic.
OWSFailDebug(@"Unknown content type.");
// Loki: Original code
// ========
// OWSFailDebug(@"Unknown content type.");
// ========
return @"UnknownContent";
}
}

@ -432,6 +432,13 @@ NS_ASSUME_NONNULL_BEGIN
}
[self.primaryStorage setPreKeyBundle:bundle forContact:envelope.source transaction:transaction];
}
// Loki: Check if we got p2p address
if (contentProto.lokiAddressMessage) {
NSString *address = contentProto.lokiAddressMessage.ptpAddress;
uint32_t port = contentProto.lokiAddressMessage.ptpPort;
[LokiP2PManager didReceiveLokiAddressMessageForContact:envelope.source address:address port:port receivedThroughP2P:envelope.isPtpMessage];
}
if (contentProto.syncMessage) {
[self throws_handleIncomingEnvelope:envelope
@ -1452,6 +1459,16 @@ NS_ASSUME_NONNULL_BEGIN
(unsigned long)timestamp);
return nil;
}
// Loki
// If we received a message from a contact in the last 2 minues that was not p2p, then we need to ping them.
// We assume this occurred because they don't have our p2p details.
if (!envelope.isPtpMessage && envelope.source != nil) {
uint64_t timestamp = envelope.timestamp;
uint64_t now = NSDate.ows_millisecondTimeStamp;
uint64_t ageInSeconds = (now - timestamp) / 1000;
if (ageInSeconds <= 120) { [LokiP2PManager pingContact:envelope.source]; }
}
[self finalizeIncomingMessage:incomingMessage
thread:thread
@ -1500,6 +1517,12 @@ NS_ASSUME_NONNULL_BEGIN
if (existingFriendRequestMessage != nil && existingFriendRequestMessage.isFriendRequest) {
[existingFriendRequestMessage saveFriendRequestStatus:LKMessageFriendRequestStatusAccepted withTransaction:transaction];
}
// Send our p2p details to the other user
LKAddressMessage *_Nullable onlineMessage = [LokiP2PManager onlineBroadcastMessageForThread:thread];
if (onlineMessage != nil) {
[self.messageSenderJobQueue addMessage:onlineMessage transaction:transaction];
}
}
}

@ -44,6 +44,7 @@
#import "TSSocketManager.h"
#import "TSThread.h"
#import "LKFriendRequestMessage.h"
#import "LKAddressMessage.h"
#import <AxolotlKit/AxolotlExceptions.h>
#import <AxolotlKit/CipherMessage.h>
#import <AxolotlKit/PreKeyBundle.h>
@ -1802,7 +1803,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
isSilent:false
isOnline:false
registrationId:0
ttl:message.ttl];
ttl:message.ttl
isPing:false];
NSError *error;
NSDictionary *jsonDict = [MTLJSONAdapter JSONDictionaryFromModel:messageParams error:&error];
@ -1889,6 +1891,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
BOOL isSilent = message.isSilent;
BOOL isOnline = message.isOnline;
LKAddressMessage *_Nullable addressMessage = [message as:[LKAddressMessage class]];
BOOL isPing = addressMessage != nil && addressMessage.isPing;
OWSMessageServiceParams *messageParams =
[[OWSMessageServiceParams alloc] initWithType:messageType
recipientId:recipientId
@ -1897,7 +1902,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
isSilent:isSilent
isOnline:isOnline
registrationId:[cipher throws_remoteRegistrationId:transaction]
ttl:message.ttl];
ttl:message.ttl
isPing:isPing];
NSError *error;
NSDictionary *jsonDict = [MTLJSONAdapter JSONDictionaryFromModel:messageParams error:&error];

@ -27,6 +27,9 @@ NS_ASSUME_NONNULL_BEGIN
// Loki: Message ttl
@property (nonatomic, readonly) uint ttl;
// Loki: Wether this message is a p2p ping
@property (nonatomic, readonly) BOOL isPing;
- (instancetype)initWithType:(TSWhisperMessageType)type
recipientId:(NSString *)destination
device:(int)deviceId
@ -34,7 +37,8 @@ NS_ASSUME_NONNULL_BEGIN
isSilent:(BOOL)isSilent
isOnline:(BOOL)isOnline
registrationId:(int)registrationId
ttl:(uint)ttl;
ttl:(uint)ttl
isPing:(BOOL)isPing;
@end

@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
isOnline:(BOOL)isOnline
registrationId:(int)registrationId
ttl:(uint)ttl
isPing:(BOOL)isPing
{
self = [super init];
@ -38,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
_silent = isSilent;
_online = isOnline;
_ttl = ttl;
_isPing = isPing;
return self;
}

@ -496,6 +496,10 @@ dispatch_queue_t NetworkManagerQueue()
+ (void)deregisterAfterAuthErrorIfNecessary:(NSURLSessionDataTask *)task
request:(TSRequest *)request
statusCode:(NSInteger)statusCode {
/* Loki: Original code
* We don't really care about invalid auth
* ========
OWSLogVerbose(@"Invalid auth: %@", task.originalRequest.allHTTPHeaderFields);
// We only want to de-register for:
@ -522,6 +526,9 @@ dispatch_queue_t NetworkManagerQueue()
} else {
OWSLogWarn(@"Ignoring %d for URL: %@", (int)statusCode, task.originalRequest.URL.absoluteString);
}
* ========
*/
}
+ (NSError *)errorWithHTTPCode:(NSInteger)code

Loading…
Cancel
Save