-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f15b9b4
commit eab19b5
Showing
8 changed files
with
401 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
Extensions/XEP-0198/Managed Messaging/XMPPManagedMessaging.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#import "XMPPModule.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@class XMPPMessage; | ||
|
||
/** | ||
A module working in tandem with @c XMPPStreamManagement to trace outgoing message stream acknowledgements. | ||
This module only monitors messages with @c elementID assigned. The rationale behind this is that any potential retransmissions | ||
of messages without IDs will cause deduplication issues on the receiving end. | ||
*/ | ||
@interface XMPPManagedMessaging : XMPPModule | ||
|
||
@end | ||
|
||
/// A protocol defining @c XMPPManagedMessaging module delegate API. | ||
@protocol XMPPManagedMessagingDelegate <NSObject> | ||
|
||
@optional | ||
|
||
/// Notifies the delegate that a message subject to monitoring has been sent in the stream. | ||
- (void)xmppManagedMessaging:(XMPPManagedMessaging *)sender didBeginMonitoringOutgoingMessage:(XMPPMessage *)message; | ||
|
||
/// Notifies the delegate that @c XMPPStreamManagement module has received server acknowledgement for sent messages with given IDs. | ||
- (void)xmppManagedMessaging:(XMPPManagedMessaging *)sender didConfirmSentMessagesWithIDs:(NSArray<NSString *> *)messageIDs; | ||
|
||
/// @brief Notifies the delegate that post-reauthentication message acknowledgement processing is finished. | ||
/// At this point, no more acknowledgements for currently monitored messages are to be expected. | ||
- (void)xmppManagedMessagingDidFinishProcessingPreviousStreamConfirmations:(XMPPManagedMessaging *)sender; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
112 changes: 112 additions & 0 deletions
112
Extensions/XEP-0198/Managed Messaging/XMPPManagedMessaging.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#import "XMPPManagedMessaging.h" | ||
#import "XMPPStreamManagement.h" | ||
#import "XMPPLogging.h" | ||
|
||
// Log levels: off, error, warn, info, verbose | ||
// Log flags: trace | ||
#if DEBUG | ||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // | XMPP_LOG_FLAG_TRACE; | ||
#else | ||
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; | ||
#endif | ||
|
||
static NSString * const XMPPManagedMessagingURLScheme = @"xmppmanagedmessage"; | ||
|
||
@implementation XMPPManagedMessaging | ||
|
||
- (void)didActivate | ||
{ | ||
XMPPLogTrace(); | ||
[self.xmppStream autoAddDelegate:self delegateQueue:self.moduleQueue toModulesOfClass:[XMPPStreamManagement class]]; | ||
} | ||
|
||
- (void)willDeactivate | ||
{ | ||
XMPPLogTrace(); | ||
[self.xmppStream removeAutoDelegate:self delegateQueue:self.moduleQueue fromModulesOfClass:[XMPPStreamManagement class]]; | ||
} | ||
|
||
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message | ||
{ | ||
XMPPLogTrace(); | ||
|
||
if (![message elementID]) { | ||
XMPPLogWarn(@"Sent message without an ID excluded from managed messaging"); | ||
return; | ||
} | ||
|
||
XMPPLogInfo(@"Registering message with ID=%@ for managed messaging", [message elementID]); | ||
[multicastDelegate xmppManagedMessaging:self didBeginMonitoringOutgoingMessage:message]; | ||
} | ||
|
||
- (id)xmppStreamManagement:(XMPPStreamManagement *)sender stanzaIdForSentElement:(XMPPElement *)element | ||
{ | ||
if (![element isKindOfClass:[XMPPMessage class]] || ![element elementID]) { | ||
return nil; | ||
} | ||
|
||
NSURLComponents *managedMessageURLComponents = [[NSURLComponents alloc] init]; | ||
managedMessageURLComponents.scheme = XMPPManagedMessagingURLScheme; | ||
managedMessageURLComponents.path = [element elementID]; | ||
|
||
return managedMessageURLComponents.URL; | ||
} | ||
|
||
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender didReceiveAckForStanzaIds:(NSArray *)stanzaIds | ||
{ | ||
XMPPLogTrace(); | ||
|
||
NSArray *resumeStanzaIDs; | ||
[sender didResumeWithAckedStanzaIds:&resumeStanzaIDs serverResponse:nil]; | ||
if ([resumeStanzaIDs isEqualToArray:stanzaIds]) { | ||
// Handled in -xmppStreamDidAuthenticate: | ||
return; | ||
} | ||
|
||
[self processStreamManagementAcknowledgementForStanzaIDs:stanzaIds]; | ||
} | ||
|
||
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender | ||
{ | ||
XMPPLogTrace(); | ||
|
||
dispatch_group_t stanzaAcknowledgementGroup = dispatch_group_create(); | ||
|
||
[sender enumerateModulesOfClass:[XMPPStreamManagement class] withBlock:^(XMPPModule *module, NSUInteger idx, BOOL *stop) { | ||
NSArray *acknowledgedStanzaIDs; | ||
[(XMPPStreamManagement *)module didResumeWithAckedStanzaIds:&acknowledgedStanzaIDs serverResponse:nil]; | ||
if (acknowledgedStanzaIDs.count == 0) { | ||
return; | ||
} | ||
|
||
dispatch_group_async(stanzaAcknowledgementGroup, self.moduleQueue, ^{ | ||
[self processStreamManagementAcknowledgementForStanzaIDs:acknowledgedStanzaIDs]; | ||
}); | ||
}]; | ||
|
||
dispatch_group_notify(stanzaAcknowledgementGroup, self.moduleQueue, ^{ | ||
[multicastDelegate xmppManagedMessagingDidFinishProcessingPreviousStreamConfirmations:self]; | ||
}); | ||
} | ||
|
||
- (void)processStreamManagementAcknowledgementForStanzaIDs:(NSArray *)stanzaIDs | ||
{ | ||
NSMutableArray *managedMessageIDs = [NSMutableArray array]; | ||
for (id stanzaID in stanzaIDs) { | ||
if (![stanzaID isKindOfClass:[NSURL class]] || ![((NSURL *)stanzaID).scheme isEqualToString:XMPPManagedMessagingURLScheme]) { | ||
continue; | ||
} | ||
// Extracting path directly from NSURL does not work if it doesn't start with "/" | ||
NSURLComponents *managedMessageURLComponents = [[NSURLComponents alloc] initWithURL:stanzaID resolvingAgainstBaseURL:NO]; | ||
[managedMessageIDs addObject:managedMessageURLComponents.path]; | ||
} | ||
|
||
if (managedMessageIDs.count == 0) { | ||
return; | ||
} | ||
|
||
XMPPLogInfo(@"Confirming managed messages with IDs={%@}", [managedMessageIDs componentsJoinedByString:@","]); | ||
[multicastDelegate xmppManagedMessaging:self didConfirmSentMessagesWithIDs:managedMessageIDs]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.