PNXMPPFramework/Extensions/XEP-0280/XMPPMessageCarbons.m
2016-02-24 16:56:39 +01:00

294 lines
7.2 KiB
Objective-C

#import "XMPPMessageCarbons.h"
#import "XMPP.h"
#import "XMPPFramework.h"
#import "XMPPLogging.h"
#import "XMPPIDTracker.h"
#import "NSXMLElement+XEP_0297.h"
#import "XMPPMessage+XEP_0280.h"
#import "XMPPInternal.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
// Log levels: off, error, warn, info, verbose
// Log flags: trace
#if DEBUG
static const int xmppLogLevel = XMPP_LOG_LEVEL_VERBOSE; // | XMPP_LOG_FLAG_TRACE;
#else
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
#endif
#define XMLNS_XMPP_MESSAGE_CARBONS @"urn:xmpp:carbons:2"
@implementation XMPPMessageCarbons
- (id)initWithDispatchQueue:(dispatch_queue_t)queue
{
if((self = [super initWithDispatchQueue:queue]))
{
autoEnableMessageCarbons = YES;
}
return self;
}
- (BOOL)activate:(XMPPStream *)aXmppStream
{
XMPPLogTrace();
if ([super activate:aXmppStream])
{
XMPPLogVerbose(@"%@: Activated", THIS_FILE);
xmppIDTracker = [[XMPPIDTracker alloc] initWithDispatchQueue:moduleQueue];
return YES;
}
return NO;
}
- (void)deactivate
{
XMPPLogTrace();
dispatch_block_t block = ^{ @autoreleasepool {
[xmppIDTracker removeAllIDs];
xmppIDTracker = nil;
}};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
[super deactivate];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Properties
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)autoEnableMessageCarbons
{
__block BOOL result = NO;
dispatch_block_t block = ^{
result = autoEnableMessageCarbons;
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
return result;
}
- (void)setAutoEnableMessageCarbons:(BOOL)flag
{
dispatch_block_t block = ^{
autoEnableMessageCarbons = flag;
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_async(moduleQueue, block);
}
- (BOOL)isMessageCarbonsEnabled
{
__block BOOL result = NO;
dispatch_block_t block = ^{
result = messageCarbonsEnabled;
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
return result;
}
- (BOOL)allowsUntrustedMessageCarbons
{
__block BOOL result = NO;
dispatch_block_t block = ^{
result = allowsUntrustedMessageCarbons;
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
return result;
}
- (void)setAllowsUntrustedMessageCarbons:(BOOL)flag
{
dispatch_block_t block = ^{
allowsUntrustedMessageCarbons = flag;
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_async(moduleQueue, block);
}
- (void)enableMessageCarbons
{
dispatch_block_t block = ^{
if(!messageCarbonsEnabled && [xmppIDTracker numberOfIDs] == 0)
{
NSString *elementID = [XMPPStream generateUUID];
XMPPIQ *iq = [XMPPIQ iqWithType:@"set" elementID:elementID];
[iq setXmlns:@"jabber:client"];
NSXMLElement *enable = [NSXMLElement elementWithName:@"enable" xmlns:XMLNS_XMPP_MESSAGE_CARBONS];
[iq addChild:enable];
[xmppIDTracker addElement:iq
target:self
selector:@selector(enableMessageCarbonsIQ:withInfo:)
timeout:XMPPIDTrackerTimeoutNone];
[xmppStream sendElement:iq];
}
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
}
- (void)disableMessageCarbons
{
dispatch_block_t block = ^{
if(messageCarbonsEnabled && [xmppIDTracker numberOfIDs] == 0)
{
NSString *elementID = [XMPPStream generateUUID];
XMPPIQ *iq = [XMPPIQ iqWithType:@"set" elementID:elementID];
[iq setXmlns:@"jabber:client"];
NSXMLElement *enable = [NSXMLElement elementWithName:@"disable" xmlns:XMLNS_XMPP_MESSAGE_CARBONS];
[iq addChild:enable];
[xmppIDTracker addElement:iq
target:self
selector:@selector(disableMessageCarbonsIQ:withInfo:)
timeout:XMPPIDTrackerTimeoutNone];
[xmppStream sendElement:iq];
}
};
if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPStream Delegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
XMPPLogTrace();
messageCarbonsEnabled = NO;
if(self.autoEnableMessageCarbons)
{
[self enableMessageCarbons];
}
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
messageCarbonsEnabled = NO;
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
[xmppIDTracker invokeForID:[iq elementID] withObject:iq];
return NO;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPStream Delegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)enableMessageCarbonsIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)trackerInfo
{
XMPPLogTrace();
if([iq isResultIQ])
{
messageCarbonsEnabled = YES;
}
}
- (void)disableMessageCarbonsIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)trackerInfo
{
XMPPLogTrace();
if([iq isResultIQ])
{
messageCarbonsEnabled = NO;
}
}
- (XMPPMessage *)xmppStream:(XMPPStream *)sender willReceiveMessage:(XMPPMessage *)message
{
XMPPLogTrace();
if([message isTrustedMessageCarbonForMyJID:sender.myJID] ||
([message isMessageCarbon] && allowsUntrustedMessageCarbons))
{
BOOL outgoing = [message isSentMessageCarbon];
XMPPMessage *messageCarbonForwardedMessage = [message messageCarbonForwardedMessage];
[multicastDelegate xmppMessageCarbons:self
willReceiveMessage:messageCarbonForwardedMessage
outgoing:outgoing];
}
return message;
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
XMPPLogTrace();
if([message isTrustedMessageCarbonForMyJID:sender.myJID] ||
([message isMessageCarbon] && allowsUntrustedMessageCarbons))
{
BOOL outgoing = [message isSentMessageCarbon];
XMPPMessage *messageCarbonForwardedMessage = [message messageCarbonForwardedMessage];
[multicastDelegate xmppMessageCarbons:self
didReceiveMessage:messageCarbonForwardedMessage
outgoing:outgoing];
}
}
@end