Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMPPManagedMessaging module #1002

Merged
merged 1 commit into from
Nov 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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