Skip to content

Commit

Permalink
XMPPManagedMessaging module
Browse files Browse the repository at this point in the history
  • Loading branch information
pwetrifork committed Nov 10, 2017
1 parent f15b9b4 commit eab19b5
Show file tree
Hide file tree
Showing 8 changed files with 401 additions and 0 deletions.
1 change: 1 addition & 0 deletions Core/XMPPFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
#import "XMPPStreamManagementMemoryStorage.h"
#import "XMPPStreamManagementStanzas.h"
#import "XMPPStreamManagement.h"
#import "XMPPManagedMessaging.h"
#import "XMPPAutoPing.h"
#import "XMPPPing.h"
#import "XMPPAutoTime.h"
Expand Down
34 changes: 34 additions & 0 deletions Extensions/XEP-0198/Managed Messaging/XMPPManagedMessaging.h
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 Extensions/XEP-0198/Managed Messaging/XMPPManagedMessaging.m
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
24 changes: 24 additions & 0 deletions XMPPFramework.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,12 @@
DD1E733A1ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1E73391ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD1E733B1ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1E73391ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD1E733C1ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1E73391ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD2AD6E81F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2AD6DD1F84B49200E0FED2 /* XMPPManagedMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD2AD6E91F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2AD6DD1F84B49200E0FED2 /* XMPPManagedMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD2AD6EA1F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2AD6DD1F84B49200E0FED2 /* XMPPManagedMessaging.h */; settings = {ATTRIBUTES = (Public, ); }; };
DD2AD6EB1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2AD6DE1F84B49200E0FED2 /* XMPPManagedMessaging.m */; };
DD2AD6EC1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2AD6DE1F84B49200E0FED2 /* XMPPManagedMessaging.m */; };
DD2AD6ED1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2AD6DE1F84B49200E0FED2 /* XMPPManagedMessaging.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -1514,6 +1520,8 @@
DD1E73311ED885FD009B529B /* XMPPRoomLightCoreDataStorage+XEP_0313.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XMPPRoomLightCoreDataStorage+XEP_0313.h"; sourceTree = "<group>"; };
DD1E73321ED885FD009B529B /* XMPPRoomLightCoreDataStorage+XEP_0313.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XMPPRoomLightCoreDataStorage+XEP_0313.m"; sourceTree = "<group>"; };
DD1E73391ED88622009B529B /* XMPPRoomLightCoreDataStorageProtected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPRoomLightCoreDataStorageProtected.h; sourceTree = "<group>"; };
DD2AD6DD1F84B49200E0FED2 /* XMPPManagedMessaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPManagedMessaging.h; sourceTree = "<group>"; };
DD2AD6DE1F84B49200E0FED2 /* XMPPManagedMessaging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPManagedMessaging.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -2267,6 +2275,7 @@
D9DCD2001E6250930010D1C7 /* XEP-0198 */ = {
isa = PBXGroup;
children = (
DD2AD6D91F84B49200E0FED2 /* Managed Messaging */,
D9DCD2011E6250930010D1C7 /* Memory Storage */,
D9DCD2041E6250930010D1C7 /* Private */,
D9DCD2071E6250930010D1C7 /* XMPPStreamManagement.h */,
Expand Down Expand Up @@ -2533,6 +2542,15 @@
name = Frameworks;
sourceTree = "<group>";
};
DD2AD6D91F84B49200E0FED2 /* Managed Messaging */ = {
isa = PBXGroup;
children = (
DD2AD6DD1F84B49200E0FED2 /* XMPPManagedMessaging.h */,
DD2AD6DE1F84B49200E0FED2 /* XMPPManagedMessaging.m */,
);
path = "Managed Messaging";
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -2589,6 +2607,7 @@
D9DCD32A1E6250930010D1C7 /* XMPPIQ+XEP_0357.h in Headers */,
D9DCD24D1E6250930010D1C7 /* XMPPCoreDataStorage.h in Headers */,
D9DCD24B1E6250930010D1C7 /* XMPPBandwidthMonitor.h in Headers */,
DD2AD6E81F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */,
D9DCD2901E6250930010D1C7 /* XMPPRoomCoreDataStorage.h in Headers */,
D9DCD3081E6250930010D1C7 /* XMPPAutoPing.h in Headers */,
D9DCD2F61E6250930010D1C7 /* XMPPvCardAvatarModule.h in Headers */,
Expand Down Expand Up @@ -2750,6 +2769,7 @@
D9DCD4C41E6256D90010D1C7 /* XMPPIQ+XEP_0357.h in Headers */,
D9DCD4C51E6256D90010D1C7 /* XMPPCoreDataStorage.h in Headers */,
D9DCD4C61E6256D90010D1C7 /* XMPPBandwidthMonitor.h in Headers */,
DD2AD6E91F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */,
D9DCD4C71E6256D90010D1C7 /* XMPPRoomCoreDataStorage.h in Headers */,
D9DCD4C81E6256D90010D1C7 /* XMPPAutoPing.h in Headers */,
D9DCD4C91E6256D90010D1C7 /* XMPPvCardAvatarModule.h in Headers */,
Expand Down Expand Up @@ -2911,6 +2931,7 @@
D9DCD6271E6258CF0010D1C7 /* XMPPIQ+XEP_0357.h in Headers */,
D9DCD6281E6258CF0010D1C7 /* XMPPCoreDataStorage.h in Headers */,
D9DCD6291E6258CF0010D1C7 /* XMPPBandwidthMonitor.h in Headers */,
DD2AD6EA1F84B49200E0FED2 /* XMPPManagedMessaging.h in Headers */,
D9DCD62A1E6258CF0010D1C7 /* XMPPRoomCoreDataStorage.h in Headers */,
D9DCD62B1E6258CF0010D1C7 /* XMPPAutoPing.h in Headers */,
D9DCD62C1E6258CF0010D1C7 /* XMPPvCardAvatarModule.h in Headers */,
Expand Down Expand Up @@ -3477,6 +3498,7 @@
D9DCD3051E6250930010D1C7 /* XMPPStreamManagementStanzas.m in Sources */,
D9DCD2AD1E6250930010D1C7 /* XMPPvCard.xcdatamodeld in Sources */,
D9DCD2D71E6250930010D1C7 /* NSDate+XMPPDateTimeProfiles.m in Sources */,
DD2AD6EB1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */,
D9DCD3381E6250930010D1C7 /* XMPPRoomLight.m in Sources */,
0D44BB111E5370ED000930E0 /* XMPPElement.m in Sources */,
0D44BB6A1E537110000930E0 /* GCDMulticastDelegate.m in Sources */,
Expand Down Expand Up @@ -3629,6 +3651,7 @@
D9DCD4711E6256D90010D1C7 /* XMPPStreamManagementStanzas.m in Sources */,
D9DCD4721E6256D90010D1C7 /* XMPPvCard.xcdatamodeld in Sources */,
D9DCD4731E6256D90010D1C7 /* NSDate+XMPPDateTimeProfiles.m in Sources */,
DD2AD6EC1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */,
D9DCD4741E6256D90010D1C7 /* XMPPRoomLight.m in Sources */,
D9DCD4751E6256D90010D1C7 /* XMPPElement.m in Sources */,
D9DCD4761E6256D90010D1C7 /* GCDMulticastDelegate.m in Sources */,
Expand Down Expand Up @@ -3781,6 +3804,7 @@
D9DCD5D41E6258CF0010D1C7 /* XMPPStreamManagementStanzas.m in Sources */,
D9DCD5D51E6258CF0010D1C7 /* XMPPvCard.xcdatamodeld in Sources */,
D9DCD5D61E6258CF0010D1C7 /* NSDate+XMPPDateTimeProfiles.m in Sources */,
DD2AD6ED1F84B49200E0FED2 /* XMPPManagedMessaging.m in Sources */,
D9DCD5D71E6258CF0010D1C7 /* XMPPRoomLight.m in Sources */,
D9DCD5D81E6258CF0010D1C7 /* XMPPElement.m in Sources */,
D9DCD5D91E6258CF0010D1C7 /* GCDMulticastDelegate.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
D9DCD70E1E625C560010D1C7 /* OMEMOTestStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = D99C5E0C1D99C48100FB068A /* OMEMOTestStorage.m */; };
D9DCD7191E625CAE0010D1C7 /* XMPPFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9DCD6B01E625A9B0010D1C7 /* XMPPFramework.framework */; };
D9E35E701D90B894002E7CF7 /* OMEMOElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D9E35E6F1D90B894002E7CF7 /* OMEMOElementTests.m */; };
DDA11A4C1F8518AE00591D1B /* XMPPManagedMessagingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA11A4B1F8518AE00591D1B /* XMPPManagedMessagingTests.m */; };
DDA11A4D1F8518BA00591D1B /* XMPPManagedMessagingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA11A4B1F8518AE00591D1B /* XMPPManagedMessagingTests.m */; };
DDA11A4E1F8518BB00591D1B /* XMPPManagedMessagingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DDA11A4B1F8518AE00591D1B /* XMPPManagedMessagingTests.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -133,6 +136,7 @@
D9DCD3EC1E6255E10010D1C7 /* XMPPFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D9DCD7151E625C560010D1C7 /* XMPPFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D9E35E6F1D90B894002E7CF7 /* OMEMOElementTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OMEMOElementTests.m; path = "../Testing-Shared/OMEMOElementTests.m"; sourceTree = SOURCE_ROOT; };
DDA11A4B1F8518AE00591D1B /* XMPPManagedMessagingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPManagedMessagingTests.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -202,6 +206,7 @@
D973A0791D2F18040096F3ED /* XMPPStorageHintTests.m */,
D973A07A1D2F18040096F3ED /* XMPPURITests.m */,
D973A07B1D2F18040096F3ED /* XMPPvCardTests.m */,
DDA11A4B1F8518AE00591D1B /* XMPPManagedMessagingTests.m */,
63F50D971C60208200CA0201 /* Info.plist */,
);
name = XMPPFrameworkTests;
Expand Down Expand Up @@ -389,6 +394,7 @@
D97509281D9C82DB002E6F51 /* OMEMOServerTests.m in Sources */,
D99C5E0D1D99C48100FB068A /* OMEMOModuleTests.m in Sources */,
D973A0861D2F18040096F3ED /* XMPPURITests.m in Sources */,
DDA11A4C1F8518AE00591D1B /* XMPPManagedMessagingTests.m in Sources */,
D973A07F1D2F18040096F3ED /* XMPPMessageArchiveManagementTests.m in Sources */,
D973A07E1D2F18040096F3ED /* XMPPHTTPFileUploadTests.m in Sources */,
D973A0821D2F18040096F3ED /* XMPPPushTests.swift in Sources */,
Expand All @@ -413,6 +419,7 @@
D9DCD3DB1E6255E10010D1C7 /* OMEMOServerTests.m in Sources */,
D9DCD3DC1E6255E10010D1C7 /* OMEMOModuleTests.m in Sources */,
D9DCD3DD1E6255E10010D1C7 /* XMPPURITests.m in Sources */,
DDA11A4D1F8518BA00591D1B /* XMPPManagedMessagingTests.m in Sources */,
D9DCD3DE1E6255E10010D1C7 /* XMPPMessageArchiveManagementTests.m in Sources */,
D9DCD3DF1E6255E10010D1C7 /* XMPPHTTPFileUploadTests.m in Sources */,
D9DCD3E01E6255E10010D1C7 /* XMPPPushTests.swift in Sources */,
Expand All @@ -437,6 +444,7 @@
D9DCD7041E625C560010D1C7 /* OMEMOServerTests.m in Sources */,
D9DCD7051E625C560010D1C7 /* OMEMOModuleTests.m in Sources */,
D9DCD7061E625C560010D1C7 /* XMPPURITests.m in Sources */,
DDA11A4E1F8518BB00591D1B /* XMPPManagedMessagingTests.m in Sources */,
D9DCD7071E625C560010D1C7 /* XMPPMessageArchiveManagementTests.m in Sources */,
D9DCD7081E625C560010D1C7 /* XMPPHTTPFileUploadTests.m in Sources */,
D9DCD7091E625C560010D1C7 /* XMPPPushTests.swift in Sources */,
Expand Down
Loading

0 comments on commit eab19b5

Please sign in to comment.